mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbhgplugin/src/mpxdbalbum.cpp
branchRCL_3
changeset 66 1f1dad4af8f8
parent 56 2cbbefa9af78
equal deleted inserted replaced
60:bdd9da0d70fe 66:1f1dad4af8f8
    35 // CONSTANTS
    35 // CONSTANTS
    36 #ifdef ABSTRACTAUDIOALBUM_INCLUDED
    36 #ifdef ABSTRACTAUDIOALBUM_INCLUDED
    37 _LIT( KAbstractAlbumExt, ".alb" );
    37 _LIT( KAbstractAlbumExt, ".alb" );
    38 #endif // ABSTRACTAUDIOALBUM_INCLUDED
    38 #endif // ABSTRACTAUDIOALBUM_INCLUDED
    39 
    39 
    40 _LIT( KAlbumAlbumArtistSeperator, "\t1");
       
    41 _LIT( KAlbumArtistSeperator, "\t2");
       
    42 
       
    43 const TInt KUnknownAlbumsGranularity = 250;
       
    44 
       
    45 // ============================ MEMBER FUNCTIONS ==============================
    40 // ============================ MEMBER FUNCTIONS ==============================
    46 
    41 
    47 // ----------------------------------------------------------------------------
    42 // ----------------------------------------------------------------------------
    48 // Two-phased constructor.
    43 // Two-phased constructor.
    49 // ----------------------------------------------------------------------------
    44 // ----------------------------------------------------------------------------
    82 // ----------------------------------------------------------------------------
    77 // ----------------------------------------------------------------------------
    83 //
    78 //
    84 CMPXDbAlbum::~CMPXDbAlbum()
    79 CMPXDbAlbum::~CMPXDbAlbum()
    85     {
    80     {
    86     MPX_FUNC("CMPXDbAlbum::~CMPXDbAlbum");
    81     MPX_FUNC("CMPXDbAlbum::~CMPXDbAlbum");
    87     
       
    88     iUnknownArtists.ResetAndDestroy();
       
    89     iUnknownAlbums.ResetAndDestroy();
       
    90     }
    82     }
    91 
    83 
    92 // ----------------------------------------------------------------------------
    84 // ----------------------------------------------------------------------------
    93 // Constructor
    85 // Constructor
    94 // ----------------------------------------------------------------------------
    86 // ----------------------------------------------------------------------------
    96 CMPXDbAlbum::CMPXDbAlbum(
    88 CMPXDbAlbum::CMPXDbAlbum(
    97     CMPXDbManager& aDbManager,
    89     CMPXDbManager& aDbManager,
    98     TMPXGeneralCategory aCategory,
    90     TMPXGeneralCategory aCategory,
    99     MMPXDbAlbumObserver& aObserver) :
    91     MMPXDbAlbumObserver& aObserver) :
   100     CMPXDbCategory(aDbManager, aCategory),
    92     CMPXDbCategory(aDbManager, aCategory),
   101     iObserver(aObserver),
    93     iObserver(aObserver)
   102     iUnknownArtists(KUnknownAlbumsGranularity),
       
   103     iUnknownAlbums(KUnknownAlbumsGranularity)
       
   104     {
    94     {
   105     MPX_FUNC("CMPXDbAlbum::CMPXDbAlbum");
    95     MPX_FUNC("CMPXDbAlbum::CMPXDbAlbum");
   106     }
    96     }
   107 
    97 
   108 // ----------------------------------------------------------------------------
    98 // ----------------------------------------------------------------------------
   119 // ----------------------------------------------------------------------------
   109 // ----------------------------------------------------------------------------
   120 // CMPXDbAlbum::AddItemL
   110 // CMPXDbAlbum::AddItemL
   121 // ----------------------------------------------------------------------------
   111 // ----------------------------------------------------------------------------
   122 //
   112 //
   123 TUint32 CMPXDbAlbum::AddItemL(
   113 TUint32 CMPXDbAlbum::AddItemL(
   124     TMPXGeneralCategory /*aCategory*/,        
   114     const TDesC& aName,
   125     const CMPXMedia& aMedia,
   115     const TDesC& aArtistName,
       
   116     const TDesC& aArt,
   126     TInt aDriveId,
   117     TInt aDriveId,
   127     TBool& aNewRecord,
   118     TBool& aNewRecord,
   128     TBool aCaseSensitive)
   119     TBool aCaseSensitive)
   129     {
   120     {
   130     MPX_FUNC("CMPXDbAlbum::AddItemL");
   121     MPX_FUNC("CMPXDbAlbum::AddItemL");
   131 
   122 
   132     TPtrC album(KNullDesC);
       
   133     TPtrC albumArtist(KNullDesC);
       
   134     TPtrC artist(KNullDesC);
       
   135     TPtrC albumArt(KNullDesC);
       
   136     
       
   137     // try to find the item first
   123     // try to find the item first
   138     TUint32 rowId(GenerateUniqueIdL(aMedia));
   124     TUint32 rowId(MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), iCategory,
   139     
   125         aName, aCaseSensitive));
   140     // retrieve the existing record
   126     aNewRecord = !CategoryItemExistsL(aDriveId, rowId);
   141     HBufC* query = PreProcessStringLC(KQueryCategoryItem);
   127 
   142     RSqlStatement recordset(
   128     if (aNewRecord)
   143         iDbManager.ExecuteSelectQueryL(aDriveId, *query, rowId));
   129         {
   144     CleanupStack::PopAndDestroy(query);
   130         // insert new
   145     CleanupClosePushL(recordset);
   131         HBufC* query = PreProcessStringLC(KQueryAlbumInsert);
   146     
   132         HBufC* name = MPXDbCommonUtil::ProcessSingleQuotesLC(aName);
   147     TInt result = recordset.Next();   
   133         HBufC* artistname = MPXDbCommonUtil::ProcessSingleQuotesLC(aArtistName);
   148     if (result == KSqlAtEnd)
   134 		HBufC* art = MPXDbCommonUtil::ProcessSingleQuotesLC(aArt);
   149         {
   135 
   150         aNewRecord = result;
   136         iDbManager.ExecuteQueryL(aDriveId, *query, rowId, artistname, name, 1, art); 
   151         
   137 
   152         // check Album attribute
   138 		CleanupStack::PopAndDestroy(art);
   153         if (aMedia.IsSupported(KMPXMediaMusicAlbum))     
   139         CleanupStack::PopAndDestroy(artistname);
   154             {
   140         CleanupStack::PopAndDestroy(name);
   155             album.Set(aMedia.ValueText(KMPXMediaMusicAlbum).Left(KMCMaxTextLen));
   141         CleanupStack::PopAndDestroy(query);
       
   142         }
       
   143     else
       
   144         {
       
   145         // retrieve the existing record
       
   146         HBufC* query = NULL;
       
   147         query = PreProcessStringLC(KQueryCategoryItem);
       
   148         RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(*query, rowId));
       
   149         CleanupStack::PopAndDestroy(query);
       
   150 
       
   151         CleanupClosePushL(recordset);
       
   152 
       
   153         if (recordset.Next() != KSqlAtRow)
       
   154             {
       
   155             User::Leave(KErrNotFound);
       
   156 	    }
       
   157 
       
   158         // Artist
       
   159         TPtrC artistname(KNullDesC);
       
   160         artistname.Set(MPXDbCommonUtil::GetColumnTextL(recordset, EAlbumArtistName));
       
   161 
       
   162 
       
   163         // the current one is Unknown and the new one is Not Unknown.
       
   164          if ( artistname == KNullDesC  && aArtistName!= KNullDesC )
       
   165             {
       
   166             HBufC* artistnameReplaceSingleQuote = 
       
   167                             MPXDbCommonUtil::ProcessSingleQuotesLC( aArtistName );
       
   168             TPtrC criteria(KCriterionArtistName);
       
   169             HBufC* setStr = HBufC::NewLC(criteria.Length() + artistnameReplaceSingleQuote->Length()); 
       
   170             setStr->Des().Format( KCriterionArtistName, artistnameReplaceSingleQuote );
       
   171            
       
   172             iDbManager.ExecuteQueryL(aDriveId, KQueryAlbumUpdate, setStr, rowId);
       
   173             CleanupStack::PopAndDestroy(setStr);
       
   174             CleanupStack::PopAndDestroy(artistnameReplaceSingleQuote);
       
   175 
   156             }
   176             }
   157         
   177 
   158         // check AlbumArt attirbute
   178         // Album Art
   159         if (aMedia.IsSupported(KMPXMediaMusicAlbumArtFileName))
       
   160             {
       
   161             albumArt.Set(aMedia.ValueText(KMPXMediaMusicAlbumArtFileName).Left(KMCMaxTextLen));
       
   162             }
       
   163 
       
   164         // insert new
       
   165         HBufC* name = MPXDbCommonUtil::ProcessSingleQuotesLC(album);
       
   166         TUint32 artistId(0);
       
   167         HBufC* artistName = NULL;        
       
   168         if (RetrieveAlbumArtistL(aMedia, albumArtist))
       
   169             {
       
   170             artistId = iObserver.AddAlbumArtistL(albumArtist, albumArt, aDriveId);
       
   171             artistName = MPXDbCommonUtil::ProcessSingleQuotesLC(albumArtist);
       
   172             }
       
   173         else
       
   174             {
       
   175             RetrieveArtist(aMedia, artist);
       
   176             artistId = iObserver.AddAlbumArtistL(artist, albumArt, aDriveId);
       
   177             artistName = MPXDbCommonUtil::ProcessSingleQuotesLC(artist);
       
   178             }
       
   179         
       
   180         HBufC* art = MPXDbCommonUtil::ProcessSingleQuotesLC(albumArt);
       
   181                 
       
   182         iDbManager.ExecuteQueryL(aDriveId, KQueryAlbumInsert, rowId, name, 1, artistId, artistName,art); 
       
   183 
       
   184         CleanupStack::PopAndDestroy(art);
       
   185         CleanupStack::PopAndDestroy(artistName);
       
   186         CleanupStack::PopAndDestroy(name);
       
   187         }
       
   188     else if (result == KSqlAtRow)
       
   189         {       
       
   190         // retrieve Art from Album table
       
   191         TPtrC art(KNullDesC);
   179         TPtrC art(KNullDesC);
   192         art.Set(MPXDbCommonUtil::GetColumnTextL(recordset, EAlbumArt));
   180         art.Set(MPXDbCommonUtil::GetColumnTextL(recordset, EAlbumArt));
   193 
   181 
   194         // the current one is Unknown and the new one is Not Unknown
   182         // the current one is Unknown and the new one is Not Unknown
   195         if ( art == KNullDesC && albumArt != KNullDesC )
   183         if ( art == KNullDesC && aArt != KNullDesC )
   196             {
   184             {
   197             HBufC* artReplaceSingleQuote = 
   185             HBufC* artReplaceSingleQuote = 
   198                 MPXDbCommonUtil::ProcessSingleQuotesLC( albumArt );
   186                             MPXDbCommonUtil::ProcessSingleQuotesLC( aArt );
   199 
   187 
   200             TPtrC criteria(KCriterionArt);
   188             TPtrC criteria(KCriterionArt);
   201             HBufC* setStr = HBufC::NewLC(criteria.Length() + artReplaceSingleQuote->Length()); 
   189             HBufC* setStr = HBufC::NewLC(criteria.Length() + artReplaceSingleQuote->Length()); 
   202             setStr->Des().Format( KCriterionArt, artReplaceSingleQuote );
   190             setStr->Des().Format( KCriterionArt, artReplaceSingleQuote );
   203 
   191 
   204             iDbManager.ExecuteQueryL(aDriveId, KQueryAlbumUpdate, setStr, rowId);
   192             iDbManager.ExecuteQueryL(aDriveId, KQueryAlbumUpdate, setStr, rowId);
   205             CleanupStack::PopAndDestroy(setStr);
   193             CleanupStack::PopAndDestroy(setStr);
   206             CleanupStack::PopAndDestroy(artReplaceSingleQuote);
   194             CleanupStack::PopAndDestroy(artReplaceSingleQuote);
   207             }
   195             }
   208 
   196 
       
   197         CleanupStack::PopAndDestroy(&recordset);
       
   198 
   209         // increment the number of songs for the category
   199         // increment the number of songs for the category
   210         query = PreProcessStringLC(KQueryCategoryIncrementSongCount);
   200         query = PreProcessStringLC(KQueryCategoryIncrementSongCount);
   211         iDbManager.ExecuteQueryL(aDriveId, *query, rowId);
   201         iDbManager.ExecuteQueryL(aDriveId, *query, rowId);
   212         CleanupStack::PopAndDestroy(query);
   202         CleanupStack::PopAndDestroy(query);
   213         } // existing record
   203         }
   214     else
   204 
   215         {
       
   216         MPX_DEBUG2("SQL error %d", result);
       
   217         User::Leave(result);
       
   218         }
       
   219 
       
   220     CleanupStack::PopAndDestroy(&recordset);
       
   221     
       
   222     return rowId;
   205     return rowId;
   223     }
   206     }
   224 
   207 
   225 // ----------------------------------------------------------------------------
   208 // ----------------------------------------------------------------------------
   226 // CMPXDbAlbum::DecrementSongsForAlbumL
   209 // CMPXDbAlbum::DecrementSongsForCategoryL
   227 // ----------------------------------------------------------------------------
   210 // ----------------------------------------------------------------------------
   228 //
   211 //
   229 void CMPXDbAlbum::DecrementSongsForAlbumL(
   212 void CMPXDbAlbum::DecrementSongsForCategoryL(
   230     const TUint32 aId,
   213     const TUint32 aId,
   231     TInt aDriveId,
   214     TInt aDriveId,
   232     CMPXMessageArray* aItemChangedMessages,
   215     CMPXMessageArray* aItemChangedMessages,
   233     TBool& aItemExist,
   216     TBool& aItemExist,
   234     const TDesC& aArt)       
   217     const TUint32 aArtist,
   235     {
   218     const TDesC& aArt)
   236     MPX_FUNC("CMPXDbAlbum::DecrementSongsForAlbumL");
   219     {
   237 
   220     MPX_FUNC("CMPXDbAlbum::DecrementSongsForCategoryL");
   238     // retrieve the existing record
       
   239     HBufC* query = PreProcessStringLC(KQueryCategoryItem);
       
   240     RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(*query, aId));
       
   241     CleanupStack::PopAndDestroy(query);
       
   242 
       
   243     CleanupClosePushL(recordset);
       
   244 
       
   245     if (recordset.Next() != KSqlAtRow)
       
   246         {
       
   247         User::Leave(KErrNotFound);
       
   248         }
       
   249 
   221 
   250     // if just one song uses this category. Use <= just in case
   222     // if just one song uses this category. Use <= just in case
   251     if (recordset.ColumnInt64(EAlbumSongCount) <= 1)
   223     if (GetSongsCountL(aDriveId, aId) <= 1)
   252         {
   224         {
   253         aItemExist = EFalse;
   225         aItemExist = EFalse;
   254 
       
   255         // Decrement albums count on artist       
       
   256         TUint32 albumArtistId = recordset.ColumnInt64(EAlbumArtist);
       
   257         iObserver.DeleteAlbumForArtistL(albumArtistId, aDriveId, aItemChangedMessages);
       
   258         CleanupStack::PopAndDestroy(&recordset);
       
   259                 
       
   260         // delete the category
   226         // delete the category
   261         DeleteCategoryL(aId, aDriveId);
   227         DeleteCategoryL(aId, aDriveId);
   262 
   228 
   263         if (aItemChangedMessages)
   229         if (aItemChangedMessages)
   264             {
   230             {
   269         }
   235         }
   270     else
   236     else
   271         {
   237         {
   272         aItemExist = ETrue;
   238         aItemExist = ETrue;
   273 
   239 
       
   240         // retrieve the existing record
       
   241         HBufC* query = PreProcessStringLC(KQueryCategoryItem);
       
   242         RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(*query, aId));
       
   243         CleanupStack::PopAndDestroy(query);
       
   244 
       
   245         CleanupClosePushL(recordset);
       
   246 
       
   247         if (recordset.Next() != KSqlAtRow)
       
   248             {
       
   249             User::Leave(KErrNotFound);
       
   250         }
       
   251 
   274         TBool itemModified = EFalse;
   252         TBool itemModified = EFalse;
   275         		
   253         TPtrC artistname(MPXDbCommonUtil::GetColumnTextL(recordset, EAlbumArtistName));
   276         TPtrC art(MPXDbCommonUtil::GetColumnTextL(recordset, EAlbumArt));        
   254         TUint32 artistId = MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), EMPXArtist,
   277         if (NeedToUpdateArt(aArt, art))
   255 	            artistname, ETrue);
       
   256 
       
   257         // the current artist is equal to deleted song's artist
       
   258         if ( artistId == aArtist )
       
   259             {
       
   260             HBufC* newArtistname = ArtistForAlbumL(aId);
       
   261             
       
   262             CleanupStack::PushL(newArtistname);
       
   263             if (newArtistname && newArtistname->CompareF(artistname)!=0)
       
   264                 { 
       
   265                 HBufC* artistnameReplaceSingleQuote = MPXDbCommonUtil::ProcessSingleQuotesLC( *newArtistname );
       
   266                 TPtrC criteria(KCriterionArtistName);
       
   267                 HBufC* setStr = HBufC::NewLC(criteria.Length() + artistnameReplaceSingleQuote->Length()); 
       
   268                 setStr->Des().Format( KCriterionArtistName, artistnameReplaceSingleQuote );                    	
       
   269 
       
   270                 iDbManager.ExecuteQueryL(aDriveId, KQueryAlbumUpdate, setStr, aId);
       
   271                 CleanupStack::PopAndDestroy(setStr);
       
   272                 CleanupStack::PopAndDestroy(artistnameReplaceSingleQuote);
       
   273                 itemModified = ETrue;
       
   274                 }
       
   275             CleanupStack::PopAndDestroy(newArtistname);             
       
   276             }         
       
   277         
       
   278 #ifdef ABSTRACTAUDIOALBUM_INCLUDED      
       
   279     TBool nonEmbeddedArt = EFalse;
       
   280     if (aArt.Length()>0)
       
   281         {
       
   282         TParsePtrC parse(aArt);
       
   283         TPtrC ext(parse.Ext());
       
   284         //set flag to false, so .alb will not overwrite art field in album, artist table 
       
   285         // when song with embedded art
       
   286         if (ext.CompareF(KAbstractAlbumExt)== 0) 
       
   287             {     
       
   288             nonEmbeddedArt = ETrue;        
       
   289             }
       
   290         }
       
   291   if (!nonEmbeddedArt)       
       
   292        {
       
   293 #endif // ABSTRACTAUDIOALBUM_INCLUDED
       
   294        TPtrC art(MPXDbCommonUtil::GetColumnTextL(recordset, EAlbumArt));
       
   295         // the current art is equal to deleted song's art      
       
   296         if(aArt.Length()>0 && art.Length()>0 && aArt.CompareF(art) ==0 )
   278             {
   297             {
   279             MPX_DEBUG2("AlbumArt of the Song to be deleted is [%S]", &aArt);
   298             MPX_DEBUG2("AlbumArt of the Song to be deleted is [%S]", &aArt);
   280             
   299             
   281             //need to get alternative art in the same album to display
   300             //need to get alternative art in the same album to display
   282             HBufC* newArt = AlbumartForAlbumL(aId, aArt);
   301             HBufC* newArt = AlbumartForAlbumL(aId, aArt);
   283             CleanupStack::PushL(newArt);
   302             CleanupStack::PushL(newArt);
   284 
   303 
   285             //update Album table only if alternative albumart found
   304             //update Album table only if alternative albumart found
   286             if (newArt)
   305             if (newArt)
   287                 {
   306                 {
   288                 MPX_DEBUG1("CMPXDbAlbum::DecrementSongsForAlbumL, get newArt");
   307                 MPX_DEBUG1("CMPXDbAlbum::DecrementSongsForCategoryL, get newArt");
   289                 HBufC* artReplaceSingleQuote = MPXDbCommonUtil::ProcessSingleQuotesLC( *newArt );
   308                 HBufC* artReplaceSingleQuote = MPXDbCommonUtil::ProcessSingleQuotesLC( *newArt );
   290                 TPtrC criteria(KCriterionArt);   
   309                 TPtrC criteria(KCriterionArt);   
   291                 HBufC* setStr = HBufC::NewLC(criteria.Length() + artReplaceSingleQuote->Length()); 
   310                 HBufC* setStr = HBufC::NewLC(criteria.Length() + artReplaceSingleQuote->Length()); 
   292                 setStr->Des().Format( KCriterionArt, artReplaceSingleQuote );
   311                 setStr->Des().Format( KCriterionArt, artReplaceSingleQuote );
   293 
   312 
   294                 iDbManager.ExecuteQueryL(aDriveId, KQueryAlbumUpdate, setStr, aId);
   313                 iDbManager.ExecuteQueryL(aDriveId, KQueryAlbumUpdate, setStr, aId);
   295                 CleanupStack::PopAndDestroy(setStr);
   314                 CleanupStack::PopAndDestroy(setStr);
   296                 CleanupStack::PopAndDestroy(artReplaceSingleQuote);
   315                 CleanupStack::PopAndDestroy(artReplaceSingleQuote);
   297                 itemModified = ETrue;                     
   316                 itemModified = ETrue;                     
   298                 }
   317                 }
   299             CleanupStack::PopAndDestroy(newArt);             
   318            CleanupStack::PopAndDestroy(newArt);             
   300             }
   319            }
   301 
   320 #ifdef ABSTRACTAUDIOALBUM_INCLUDED            
       
   321          }
       
   322 #endif // ABSTRACTAUDIOALBUM_INCLUDED
   302         if (aItemChangedMessages && itemModified)
   323         if (aItemChangedMessages && itemModified)
   303             {
   324            {
   304             // add the item changed message
   325            // add the item changed message
   305             MPXDbCommonUtil::AddItemAlbumChangedMessageL(*aItemChangedMessages, aId, EMPXItemModified,
   326            MPXDbCommonUtil::AddItemAlbumChangedMessageL(*aItemChangedMessages, aId, EMPXItemModified,
   306                 EMPXAlbum, KDBPluginUid, ETrue, 0 );
   327                       EMPXAlbum, KDBPluginUid, ETrue, 0 );
   307             }
   328            }
   308         CleanupStack::PopAndDestroy(&recordset);
   329         CleanupStack::PopAndDestroy(&recordset);
   309         
   330         
   310         // decrement the number of songs for the category
   331         // decrement the number of songs for the category
   311         query = PreProcessStringLC(KQueryCategoryDecrementSongCount);
   332         query = PreProcessStringLC(KQueryCategoryDecrementSongCount);
   312         iDbManager.ExecuteQueryL(aDriveId, *query, aId);
   333         iDbManager.ExecuteQueryL(aDriveId, *query, aId);
   322     const TArray<TMPXAttribute>& aAttrs,
   343     const TArray<TMPXAttribute>& aAttrs,
   323     CMPXMediaArray& aMediaArray)
   344     CMPXMediaArray& aMediaArray)
   324     {
   345     {
   325     MPX_FUNC("CMPXDbAlbum::GetAllCategoryItemsL");
   346     MPX_FUNC("CMPXDbAlbum::GetAllCategoryItemsL");
   326 
   347 
   327     RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryAlbumAll()));
   348     HBufC* query = PreProcessStringLC(KQueryAlbumAll);
       
   349     RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(*query));
       
   350     CleanupStack::PopAndDestroy(query);
   328 
   351 
   329     CleanupClosePushL(recordset);
   352     CleanupClosePushL(recordset);
   330     TRAPD(err, ProcessAlbumRecordSetL(aAttrs, recordset, aMediaArray));
   353     ProcessRecordsetL(aAttrs, recordset, aMediaArray);
   331     if (err != KErrNone)
       
   332         {
       
   333         iUnknownArtists.ResetAndDestroy();
       
   334         iUnknownAlbums.ResetAndDestroy();
       
   335         User::LeaveIfError(err);
       
   336         }
       
   337     CleanupStack::PopAndDestroy(&recordset);
   354     CleanupStack::PopAndDestroy(&recordset);
   338     }
   355     }
   339 
   356 
   340 // ----------------------------------------------------------------------------
   357 // ----------------------------------------------------------------------------
   341 // CMPXDbAlbum::UpdateItemL
   358 // CMPXDbAlbum::UpdateItemL
   369         }
   386         }
   370 
   387 
   371 	CleanupStack::PopAndDestroy(setStr);
   388 	CleanupStack::PopAndDestroy(setStr);
   372 	CleanupStack::PopAndDestroy(values);
   389 	CleanupStack::PopAndDestroy(values);
   373 	CleanupStack::PopAndDestroy(fields);
   390 	CleanupStack::PopAndDestroy(fields);
       
   391 	}
       
   392 
       
   393 // ----------------------------------------------------------------------------
       
   394 // CMPXDbAlbum::GetAlbumsCountForArtistL
       
   395 // ----------------------------------------------------------------------------
       
   396 //
       
   397 TInt CMPXDbAlbum::GetAlbumsCountForArtistL(TUint32 aArtistId)
       
   398 	{
       
   399     RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryCategorySubcategoryItems, aArtistId));
       
   400 
       
   401     TInt prevId(0);
       
   402     TInt count(0);
       
   403 	TInt err(KErrNone);
       
   404 
       
   405     while ((err = recordset.Next()) == KSqlAtRow)
       
   406 		{
       
   407 		TUint32 rowId(recordset.ColumnInt64(EAlbumUniqueId));
       
   408         if (prevId == rowId)
       
   409             {
       
   410             continue;
       
   411             }
       
   412 
       
   413 		count++;
       
   414 		prevId = rowId;
       
   415 		}
       
   416 
       
   417     if (err != KSqlAtEnd)
       
   418         {
       
   419         User::Leave(err);
       
   420         }
       
   421 
       
   422 	return count;
       
   423 
   374 	}
   424 	}
   375 
   425 
   376 // ----------------------------------------------------------------------------
   426 // ----------------------------------------------------------------------------
   377 // CMPXDbAlbum::GetSongsCountInAlbumMatchingArtistL
   427 // CMPXDbAlbum::GetSongsCountInAlbumMatchingArtistL
   378 // ----------------------------------------------------------------------------
   428 // ----------------------------------------------------------------------------
   433 			{
   483 			{
   434 			if (attributeId & EMPXMediaMusicArtist)
   484 			if (attributeId & EMPXMediaMusicArtist)
   435 				{
   485 				{
   436 				MPX_DEBUG1("	EMPXMediaMusicArtist");
   486 				MPX_DEBUG1("	EMPXMediaMusicArtist");
   437 
   487 
   438 				TPtrC artistName(MPXDbCommonUtil::GetColumnTextL(aRecord, EAlbumArtistName));
   488 				TPtrC artistName(KNullDesC);
       
   489 
       
   490 				// if album is unknown, ignore arist name
       
   491 				if (MPXDbCommonUtil::GetColumnTextL(aRecord, EAlbumName) != KNullDesC)
       
   492 					{
       
   493 					artistName.Set(MPXDbCommonUtil::GetColumnTextL(aRecord, EAlbumArtistName));
       
   494 					}
       
   495 
   439 				aMedia.SetTextValueL(KMPXMediaMusicArtist, artistName);
   496 				aMedia.SetTextValueL(KMPXMediaMusicArtist, artistName);
   440 				MPX_DEBUG2("	Artist[%S]", &artistName);
   497 				MPX_DEBUG2("	Artist[%S]", &artistName);
   441 				}
   498 				}
   442 
   499 
   443 			if (attributeId & EMPXMediaMusicAlbum)
   500 			if (attributeId & EMPXMediaMusicAlbum)
   459 				}
   516 				}
   460 			if (attributeId & EMPXMediaMusicAlbumArtFileName)
   517 			if (attributeId & EMPXMediaMusicAlbumArtFileName)
   461 				{
   518 				{
   462 				MPX_DEBUG1("	EMPXMediaMusicAlbumArtFileName");
   519 				MPX_DEBUG1("	EMPXMediaMusicAlbumArtFileName");
   463 
   520 
   464 				TPtrC art(MPXDbCommonUtil::GetColumnTextL(aRecord, EAlbumArt));
   521 				TPtrC art(KNullDesC);
       
   522 
       
   523 				// if album is unknown, ignore album art name
       
   524 				if (MPXDbCommonUtil::GetColumnTextL(aRecord, EAlbumName) != KNullDesC)
       
   525 					{
       
   526 					art.Set(MPXDbCommonUtil::GetColumnTextL(aRecord, EAlbumArt));
       
   527 					}
       
   528 
   465 				aMedia.SetTextValueL(KMPXMediaMusicAlbumArtFileName, art);
   529 				aMedia.SetTextValueL(KMPXMediaMusicAlbumArtFileName, art);
   466 				MPX_DEBUG2("	Art[%S]", &art);
   530 				MPX_DEBUG2("	Art[%S]", &art);
   467 				}
   531 				}
   468 			}
   532 			}
   469 		} // end for
   533 		} // end for
   480 	{
   544 	{
   481 	if (aMedia.IsSupported(KMPXMediaMusicAlbumArtFileName))
   545 	if (aMedia.IsSupported(KMPXMediaMusicAlbumArtFileName))
   482 		{
   546 		{
   483 		const TDesC& albumArtFilename = aMedia.ValueText(KMPXMediaMusicAlbumArtFileName).Left(KMCMaxTextLen);
   547 		const TDesC& albumArtFilename = aMedia.ValueText(KMPXMediaMusicAlbumArtFileName).Left(KMCMaxTextLen);
   484 		MPXDbCommonUtil::AppendValueL(aFields, aValues, KMCMusicArt, albumArtFilename);
   548 		MPXDbCommonUtil::AppendValueL(aFields, aValues, KMCMusicArt, albumArtFilename);
   485 		}	
   549 		}
       
   550 
       
   551 	if (aMedia.IsSupported(KMPXMediaMusicArtist))
       
   552 	    {
       
   553 	    const TDesC& artistName = aMedia.ValueText(KMPXMediaMusicArtist).Left(KMCMaxTextLen);
       
   554 	    MPXDbCommonUtil::AppendValueL(aFields, aValues, KMCAlbumArtistName, artistName);
       
   555 	    }
   486 	}
   556 	}
   487 
   557 
   488 // ----------------------------------------------------------------------------
   558 // ----------------------------------------------------------------------------
       
   559 // CMPXDbAlbum::IsUnknownArtistL
       
   560 // ----------------------------------------------------------------------------
       
   561 //
       
   562 TBool CMPXDbAlbum::IsUnknownArtistL(TUint32 aId)
       
   563 	{
       
   564 	return iObserver.HandleIsUnknownArtistL(aId);
       
   565 	}
       
   566 
       
   567 // ----------------------------------------------------------------------------
       
   568 // CMPXDbAlbum::ArtistForAlbumL
       
   569 // ----------------------------------------------------------------------------
       
   570 //
       
   571 HBufC* CMPXDbAlbum::ArtistForAlbumL(const TUint32 aId)
       
   572     {
       
   573     return iObserver.HandleArtistForAlbumL(aId);
       
   574     }
       
   575 
       
   576 // ----------------------------------------------------------------------------
   489 // CMPXDbAlbum::AlbumartForAlbumL
   577 // CMPXDbAlbum::AlbumartForAlbumL
   490 // ----------------------------------------------------------------------------
   578 // ----------------------------------------------------------------------------
   491 //
   579 //
   492 HBufC* CMPXDbAlbum::AlbumartForAlbumL(const TUint32 aId, TPtrC aArt)
   580 HBufC* CMPXDbAlbum::AlbumartForAlbumL(const TUint32 aId, TPtrC aArt)
   493     {
   581     {
   494     return iObserver.HandleAlbumartForAlbumL(aId, aArt);
   582     return iObserver.HandleAlbumartForAlbumL(aId, aArt);
   495     }
       
   496 
       
   497 // ----------------------------------------------------------------------------
       
   498 // CMPXDbAlbum::ProcessAlbumRecordSetL
       
   499 // Unknown album or Unknown artist are stored in the database as NULL (Name field and ArtistName field). 
       
   500 // The available unknown album is saved for later and will be appended to the array 
       
   501 // as the last item among items which have the same artist.
       
   502 // The available unknown artists are saved for later and will be appended to the array
       
   503 // as the last items after all known artists are appended.
       
   504 // The unknown album and unknown artist is saved for later and will be appended to the array
       
   505 // as the last item.
       
   506 //
       
   507 // NOTE: putting unknown album to the end of the array only takes place when title
       
   508 //       field is requested. normal sorting algorithm occurs if title isn't
       
   509 //       requested.
       
   510 //
       
   511 // Example:
       
   512 //     Album X of artist A
       
   513 //     Album Y of artist A
       
   514 //     Unknown album of artist A
       
   515 //     Album X of artist B
       
   516 //     Album Z of artist B
       
   517 //     Unknown album of artist B
       
   518 //     Album X of unknown artist
       
   519 //     Album Y of unknown artist
       
   520 //     Unknown album of unknown artist
       
   521 // ----------------------------------------------------------------------------
       
   522 //
       
   523 void CMPXDbAlbum::ProcessAlbumRecordSetL(
       
   524     const TArray<TMPXAttribute>& aAttrs,
       
   525     RSqlStatement& aRecordset,
       
   526     CMPXMediaArray& aMediaArray)
       
   527     {
       
   528     // populate the array
       
   529     TBool firstRecord(ETrue);
       
   530     CMPXMedia* unknownAlbumUnknownArtistMedia(NULL);
       
   531     CMPXMedia* unknownMedia(NULL);
       
   532     TUint32 prevId(0);
       
   533     TUint32 artistId(0);
       
   534     TUint32 prevArtistId(0);
       
   535     TInt count(0);
       
   536     TInt err(KErrNone);
       
   537        
       
   538     // Reset array for unknown artists
       
   539     if (iUnknownArtists.Count() > 0)
       
   540         {
       
   541         iUnknownArtists.ResetAndDestroy();
       
   542         }
       
   543     
       
   544     // Reset array for unknown albums
       
   545     if (iUnknownAlbums.Count() > 0)
       
   546         {
       
   547         iUnknownAlbums.ResetAndDestroy();
       
   548         }
       
   549         
       
   550     TInt pPath(0);
       
   551     if (aMediaArray.Count())
       
   552         {
       
   553         CMPXMedia* pMedia = aMediaArray[0];
       
   554         if (pMedia->IsSupported(KMPXMediaGeneralValue))
       
   555             { // Query excuted by OpenL
       
   556             pPath = pMedia->ValueTObjectL<TInt>(KMPXMediaGeneralValue);
       
   557             MPX_ASSERT(pPath);
       
   558             }
       
   559         }
       
   560     
       
   561     RArray<TMPXItemId> ids;
       
   562     CleanupClosePushL(ids);
       
   563 
       
   564     while ((err = aRecordset.Next()) == KSqlAtRow)
       
   565         {
       
   566         TUint32 rowId(aRecordset.ColumnInt64(EAlbumUniqueId));
       
   567         if (prevId == rowId)
       
   568             {
       
   569             continue;
       
   570             }
       
   571 
       
   572         prevId = rowId;
       
   573         CMPXMedia* media = CMPXMedia::NewL();
       
   574         CleanupStack::PushL(media);
       
   575 
       
   576         UpdateMediaL(aRecordset, aAttrs, *media);
       
   577     
       
   578         artistId = aRecordset.ColumnInt64(EAlbumArtist);
       
   579 
       
   580         // Append Known artist and Unknown albums
       
   581         count = iUnknownAlbums.Count();
       
   582         if (prevArtistId != artistId && count > 0)
       
   583             {
       
   584             unknownMedia = NULL;
       
   585                 
       
   586             for (TInt i = 0; i < count; i++)
       
   587                 {
       
   588                 unknownMedia = iUnknownAlbums[i];
       
   589                 if (unknownMedia->IsSupported(KMPXMediaGeneralId) && pPath)
       
   590                     {
       
   591                     ids.Append(unknownMedia->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId));
       
   592                     }
       
   593                 aMediaArray.AppendL(*unknownMedia);                 
       
   594                 }
       
   595                 
       
   596             iUnknownAlbums.ResetAndDestroy();
       
   597             }
       
   598         
       
   599         // for Unknown artist and Unknown album
       
   600         if (firstRecord && (MPXDbCommonUtil::GetColumnTextL(aRecordset, EAlbumName).Length() == 0) &&
       
   601             (MPXDbCommonUtil::GetColumnTextL(aRecordset, EAlbumArtistName).Length() == 0))
       
   602             {
       
   603             unknownAlbumUnknownArtistMedia = media;
       
   604             }
       
   605         // for Unknown artists and Known albums
       
   606         else if (MPXDbCommonUtil::GetColumnTextL(aRecordset, EAlbumArtistName).Length() == 0)
       
   607             {
       
   608             iUnknownArtists.Append(media);
       
   609             CleanupStack::Pop(media);
       
   610             }
       
   611         // for Known artist and Unknown album
       
   612         else if (MPXDbCommonUtil::GetColumnTextL(aRecordset, EAlbumName).Length() == 0)
       
   613             {
       
   614             iUnknownAlbums.Append(media);
       
   615             CleanupStack::Pop(media);
       
   616             prevArtistId = artistId;
       
   617             }
       
   618         else
       
   619             {
       
   620             if (media->IsSupported(KMPXMediaGeneralId) && pPath)
       
   621                 {
       
   622                 ids.AppendL(media->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId));
       
   623                 }
       
   624             aMediaArray.AppendL(*media);
       
   625             CleanupStack::PopAndDestroy(media);       
       
   626             }
       
   627         
       
   628         firstRecord = EFalse;               
       
   629         } // end while
       
   630 
       
   631     if (err != KSqlAtEnd)
       
   632         {
       
   633         User::LeaveIfError(err);
       
   634         }
       
   635 
       
   636     // Append Known artist and Unknown albums
       
   637     count = iUnknownAlbums.Count();
       
   638     if ( count > 0)
       
   639         {
       
   640         unknownMedia = NULL;
       
   641         
       
   642         for (TInt i = 0; i < count; i++)
       
   643             {
       
   644             unknownMedia = iUnknownAlbums[i];
       
   645             if (unknownMedia->IsSupported(KMPXMediaGeneralId) && pPath)
       
   646                 {
       
   647                 ids.Append(unknownMedia->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId));
       
   648                 }
       
   649             aMediaArray.AppendL(*unknownMedia);                 
       
   650             }
       
   651         
       
   652         iUnknownAlbums.ResetAndDestroy();
       
   653         }
       
   654 
       
   655     // Append Unknown artists to MediaArray
       
   656     count = iUnknownArtists.Count();
       
   657     if ( count > 0)
       
   658         {
       
   659         CMPXMedia* unknownMedia = NULL;
       
   660         
       
   661         for (TInt i = 0; i < count; i++)
       
   662             {
       
   663             unknownMedia = iUnknownArtists[i];
       
   664             if (unknownMedia->IsSupported(KMPXMediaGeneralId) && pPath)
       
   665                 {
       
   666                 ids.Append(unknownMedia->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId));
       
   667                 }
       
   668             aMediaArray.AppendL(*unknownMedia);                 
       
   669             }
       
   670         
       
   671         iUnknownArtists.ResetAndDestroy();
       
   672         }
       
   673     
       
   674     // the last item in the list
       
   675     if (unknownAlbumUnknownArtistMedia)
       
   676         {
       
   677         if (unknownAlbumUnknownArtistMedia->IsSupported(KMPXMediaGeneralId) && pPath)
       
   678             {
       
   679             ids.AppendL(unknownAlbumUnknownArtistMedia->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId));
       
   680             }
       
   681         aMediaArray.AppendL(*unknownAlbumUnknownArtistMedia);
       
   682         CleanupStack::PopAndDestroy(unknownAlbumUnknownArtistMedia);
       
   683         }
       
   684     
       
   685     // Append ids to the returned path
       
   686     if (pPath)
       
   687         {
       
   688         ((CMPXCollectionPath*)pPath)->AppendL(ids.Array());
       
   689         }
       
   690     CleanupStack::PopAndDestroy(&ids);
       
   691     }
       
   692 
       
   693 // ----------------------------------------------------------------------------
       
   694 // CMPXDbAlbum::GenerateUniqueIdL
       
   695 // ----------------------------------------------------------------------------
       
   696 //
       
   697 TUint32 CMPXDbAlbum::GenerateUniqueIdL(const CMPXMedia& aMedia)
       
   698     {
       
   699     TPtrC album(KNullDesC);
       
   700     TPtrC albumArtist(KNullDesC);
       
   701     TPtrC artist(KNullDesC);
       
   702     
       
   703     // check Album attirbute
       
   704     if (aMedia.IsSupported(KMPXMediaMusicAlbum))     
       
   705         {
       
   706         album.Set(aMedia.ValueText(KMPXMediaMusicAlbum).Left(KMCMaxTextLen));
       
   707         }
       
   708     
       
   709     HBufC* buf(NULL);    
       
   710     if (RetrieveAlbumArtistL(aMedia, albumArtist))
       
   711         {
       
   712         buf = HBufC::NewLC(album.Length() + albumArtist.Length() + KAlbumAlbumArtistSeperator().Length());
       
   713     
       
   714         buf->Des().Append(album);
       
   715         buf->Des().Append(KAlbumAlbumArtistSeperator);
       
   716         buf->Des().Append(albumArtist);
       
   717         }
       
   718     else
       
   719         {
       
   720         RetrieveArtist(aMedia, artist);
       
   721         
       
   722         buf = HBufC::NewLC(album.Length() + artist.Length() + KAlbumArtistSeperator().Length());
       
   723         
       
   724         buf->Des().Append(album);
       
   725         buf->Des().Append(KAlbumArtistSeperator);
       
   726         buf->Des().Append(artist);
       
   727         }
       
   728     
       
   729     // try to find the item first
       
   730     TUint32 id(MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), EMPXAlbum,
       
   731         *buf, ETrue));
       
   732     CleanupStack::PopAndDestroy(buf);
       
   733     
       
   734     return id;
       
   735     }
       
   736 
       
   737 // ----------------------------------------------------------------------------
       
   738 // CMPXDbAlbum::IsUnknownAlbumL
       
   739 // ----------------------------------------------------------------------------
       
   740 //
       
   741 TBool CMPXDbAlbum::IsUnknownAlbumL(const TUint32 aId)
       
   742     {
       
   743     HBufC* query = PreProcessStringLC(KQueryCategoryItem);
       
   744     RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(*query, aId));
       
   745     CleanupStack::PopAndDestroy(query);
       
   746     CleanupClosePushL(recordset);
       
   747 
       
   748     if (recordset.Next() != KSqlAtRow)
       
   749         {
       
   750         User::Leave(KErrNotFound);
       
   751         }
       
   752     
       
   753     TPtrC album(MPXDbCommonUtil::GetColumnTextL(recordset, EAlbumName)); 
       
   754     TPtrC artistName(MPXDbCommonUtil::GetColumnTextL(recordset, EAlbumArtistName)); 
       
   755 
       
   756     TBool ret = EFalse;
       
   757     if (album.Length() == 0 || artistName.Length() == 0)
       
   758         {
       
   759         ret = ETrue;   
       
   760         }
       
   761     else
       
   762         {
       
   763         ret = EFalse;
       
   764         }
       
   765     
       
   766     CleanupStack::PopAndDestroy(&recordset);
       
   767     
       
   768     return ret;
       
   769     }
       
   770 
       
   771 // ----------------------------------------------------------------------------
       
   772 // CMPXDbAlbum::RetrieveAlbumArtistL
       
   773 // ----------------------------------------------------------------------------
       
   774 //
       
   775 TBool CMPXDbAlbum::RetrieveAlbumArtistL(const CMPXMedia& aMedia, TPtrC& aName)
       
   776     {
       
   777     // check AlbumArtist attribute
       
   778     if (aMedia.IsSupported(KMPXMediaMusicAlbumArtist))
       
   779         {
       
   780         aName.Set(aMedia.ValueText(KMPXMediaMusicAlbumArtist).Left(KMCMaxTextLen));
       
   781         }
       
   782     else
       
   783         {
       
   784         aName.Set(KNullDesC);
       
   785         }
       
   786     
       
   787     if (aName.Length() > 0 )
       
   788         {
       
   789         return ETrue;
       
   790         }
       
   791     else
       
   792         {
       
   793         return EFalse;
       
   794         }
       
   795     }
       
   796 
       
   797 // ----------------------------------------------------------------------------
       
   798 // CMPXDbAlbum::RetrieveArtist
       
   799 // ----------------------------------------------------------------------------
       
   800 //
       
   801 void CMPXDbAlbum::RetrieveArtist(const CMPXMedia& aMedia, TPtrC& aName)
       
   802     {
       
   803     // check Artist attribute
       
   804     if (aMedia.IsSupported(KMPXMediaMusicArtist))
       
   805         {
       
   806         aName.Set(aMedia.ValueText(KMPXMediaMusicArtist).Left(KMCMaxTextLen));
       
   807         }
       
   808     else
       
   809         {
       
   810         aName.Set(KNullDesC);            
       
   811         }
       
   812     }
       
   813 
       
   814 // ----------------------------------------------------------------------------
       
   815 // CMPXDbAlbum::NeedToUpdateArt
       
   816 // ----------------------------------------------------------------------------
       
   817 //
       
   818 TBool CMPXDbAlbum::NeedToUpdateArt(const TDesC& aDeletedSongArt, const TDesC& aCurrentAlbumArt)
       
   819     {    
       
   820     if (aDeletedSongArt.Length() == 0)
       
   821         {
       
   822         // Deleted song's art has default album art
       
   823         return EFalse;
       
   824         }
       
   825 #ifdef ABSTRACTAUDIOALBUM_INCLUDED
       
   826     else
       
   827     if (aDeletedSongArt.Length() > 0)
       
   828         {
       
   829         TParsePtrC parse(aDeletedSongArt);
       
   830         TPtrC ext(parse.Ext());
       
   831         //set flag to false, so .alb will not overwrite art field in album, artist table 
       
   832         // when song with embedded art
       
   833         if (ext.CompareF(KAbstractAlbumExt) == 0) 
       
   834             {     
       
   835             // Deleted song's art is Non-embedded album art
       
   836             return EFalse;
       
   837             }
       
   838         }
       
   839     else
       
   840 #endif   
       
   841     if (aDeletedSongArt.Length() > 0 && aCurrentAlbumArt.Length() > 0 && aDeletedSongArt.CompareF(aCurrentAlbumArt) == 0)
       
   842         {
       
   843         // Deleted song's art is Embedded album art and it is the same as Album's current art
       
   844         return ETrue;
       
   845         }
       
   846     else
       
   847         {
       
   848         return EFalse;
       
   849         }
       
   850     }
   583     }
   851 
   584 
   852 // ----------------------------------------------------------------------------
   585 // ----------------------------------------------------------------------------
   853 // CMPXDbAlbum::CreateTableL
   586 // CMPXDbAlbum::CreateTableL
   854 // ----------------------------------------------------------------------------
   587 // ----------------------------------------------------------------------------
   858     TBool /* aCorruptTable */)
   591     TBool /* aCorruptTable */)
   859     {
   592     {
   860     MPX_FUNC("CMPXDbCategory::CreateTableL");
   593     MPX_FUNC("CMPXDbCategory::CreateTableL");
   861 
   594 
   862     // create the table
   595     // create the table
   863     User::LeaveIfError(aDatabase.Exec(KAlbumCreateTable));
   596     HBufC* query = PreProcessStringLC(KAlbumCreateTable);
       
   597     User::LeaveIfError(aDatabase.Exec(*query));
       
   598     CleanupStack::PopAndDestroy(query);
   864 
   599 
   865     // do not create an index on the Name field
   600     // do not create an index on the Name field
   866     // as it only slows down the insert/update queries overall
   601     // as it only slows down the insert/update queries overall
   867     }
   602     }
   868 
   603 
   873 TBool CMPXDbAlbum::CheckTableL(
   608 TBool CMPXDbAlbum::CheckTableL(
   874     RSqlDatabase& aDatabase)
   609     RSqlDatabase& aDatabase)
   875     {
   610     {
   876     MPX_FUNC("CMPXDbCategory::CheckTableL");
   611     MPX_FUNC("CMPXDbCategory::CheckTableL");
   877 
   612 
   878     TBool check(DoCheckTable(aDatabase, KAlbumCheckTable));
   613     HBufC* query = PreProcessStringLC(KAlbumCheckTable);
       
   614     TBool check(DoCheckTable(aDatabase, *query));
       
   615     CleanupStack::PopAndDestroy(query);
   879 
   616 
   880     return check;
   617     return check;
   881     }
   618     }
   882 
   619 
   883 // End of File
   620 // End of File