mpserviceplugins/mpxsqlitedbhgplugin/src/mpxdbplaylistsongs.cpp
branchRCL_3
changeset 52 14979e23cb5e
equal deleted inserted replaced
50:26a1709b9fec 52:14979e23cb5e
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Responsible for interaction with the PlaylistSongs and
       
    15 *                PlaylistSongInfo tables.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <f32file.h>
       
    22 #include <mpxlog.h>
       
    23 #include <mpxmedia.h>
       
    24 #include <mpxmediaarray.h>
       
    25 #include <mpxmediageneraldefs.h>
       
    26 #include <mpxmediamusicdefs.h>
       
    27 #include "mpxdbcommonutil.h"
       
    28 
       
    29 #include "mpxcollectiondbdef.h"
       
    30 #include "mpxdbutil.h"
       
    31 #include "mpxdbpluginqueries.h"
       
    32 #include "mpxdbmanager.h"
       
    33 #include "mpxdbplaylistsongs.h"
       
    34 
       
    35 // ============================ MEMBER FUNCTIONS ==============================
       
    36 
       
    37 // ----------------------------------------------------------------------------
       
    38 // Two-phased constructor.
       
    39 // ----------------------------------------------------------------------------
       
    40 //
       
    41 CMPXDbPlaylistSongs* CMPXDbPlaylistSongs::NewL(
       
    42     CMPXDbManager& aDbManager)
       
    43     {
       
    44     MPX_FUNC("CMPXDbPlaylistSongs::NewL");
       
    45 
       
    46     CMPXDbPlaylistSongs* self = CMPXDbPlaylistSongs::NewLC(aDbManager);
       
    47     CleanupStack::Pop(self);
       
    48     return self;
       
    49     }
       
    50 
       
    51 // ----------------------------------------------------------------------------
       
    52 // Two-phased constructor.
       
    53 // ----------------------------------------------------------------------------
       
    54 //
       
    55 CMPXDbPlaylistSongs* CMPXDbPlaylistSongs::NewLC(
       
    56     CMPXDbManager& aDbManager)
       
    57     {
       
    58     MPX_FUNC("CMPXDbPlaylistSongs::NewLC");
       
    59 
       
    60     CMPXDbPlaylistSongs* self = new (ELeave) CMPXDbPlaylistSongs(aDbManager);
       
    61     CleanupStack::PushL(self);
       
    62     self->ConstructL();
       
    63     return self;
       
    64     }
       
    65 
       
    66 // ----------------------------------------------------------------------------
       
    67 // Destructor
       
    68 // ----------------------------------------------------------------------------
       
    69 //
       
    70 CMPXDbPlaylistSongs::~CMPXDbPlaylistSongs()
       
    71     {
       
    72     MPX_FUNC("CMPXDbPlaylistSongs::~CMPXDbPlaylistSongs");
       
    73     }
       
    74 
       
    75 // ----------------------------------------------------------------------------
       
    76 // Constructor
       
    77 // ----------------------------------------------------------------------------
       
    78 //
       
    79 CMPXDbPlaylistSongs::CMPXDbPlaylistSongs(
       
    80     CMPXDbManager& aDbManager) :
       
    81     CMPXDbTable(aDbManager)
       
    82     {
       
    83     MPX_FUNC("CMPXDbPlaylistSongs::CMPXDbPlaylistSongs");
       
    84     }
       
    85 
       
    86 // ----------------------------------------------------------------------------
       
    87 // Second phase constructor.
       
    88 // ----------------------------------------------------------------------------
       
    89 //
       
    90 void CMPXDbPlaylistSongs::ConstructL()
       
    91     {
       
    92     MPX_FUNC("CMPXDbPlaylistSongs::ConstructL");
       
    93     BaseConstructL();
       
    94     }
       
    95 
       
    96 // ----------------------------------------------------------------------------
       
    97 // CMPXDbPlaylistSongs::AddSongsL
       
    98 // ----------------------------------------------------------------------------
       
    99 //
       
   100 void CMPXDbPlaylistSongs::AddSongsL(
       
   101     TUint32 aPlaylistId,
       
   102     const CMPXMediaArray& aMediaArray,
       
   103     TInt aDriveId)
       
   104     {
       
   105     MPX_FUNC("CMPXDbPlaylistSongs::AddSongsL");
       
   106 
       
   107     TInt count(aMediaArray.Count());
       
   108     for (TInt index = 0; index < count; ++index)
       
   109         {
       
   110         AddSongL(aPlaylistId, *(aMediaArray[index]), aDriveId);
       
   111         }
       
   112     }
       
   113 
       
   114 // ----------------------------------------------------------------------------
       
   115 // CMPXDbPlaylistSongs::AddSongL
       
   116 // ----------------------------------------------------------------------------
       
   117 //
       
   118 TUint32 CMPXDbPlaylistSongs::AddSongL(
       
   119     TUint32 aPlaylistId,
       
   120     const CMPXMedia& aMedia,
       
   121     TInt aDriveId)
       
   122     {
       
   123     MPX_FUNC("CMPXDbPlaylistSongs::AddSongL");
       
   124     TInt count(0);
       
   125     if (aDriveId >= 0)
       
   126     	{
       
   127     	count = CountL(aPlaylistId, aDriveId);
       
   128     	}
       
   129     return AddSongL(aPlaylistId, count, aMedia, aDriveId);
       
   130     }
       
   131 
       
   132 // ----------------------------------------------------------------------------
       
   133 // CMPXDbPlaylistSongs::AddSongL
       
   134 // ----------------------------------------------------------------------------
       
   135 //
       
   136 TUint32 CMPXDbPlaylistSongs::AddSongL(
       
   137     TUint32 aPlaylistId,
       
   138     TInt aOrdinal,
       
   139     const CMPXMedia& aMedia,
       
   140     TInt aDriveId)
       
   141     {
       
   142     MPX_FUNC("CMPXDbPlaylistSongs::AddSongL");
       
   143 
       
   144     // the UniqueId field is AUTOINCREMENT and its value is going to be generated
       
   145     // automatically by the database - no need to supply it here
       
   146     TUint32 songId((aMedia.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId)).iId2);
       
   147 
       
   148     // insert PlaylistSongs record
       
   149     iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsInsert, aPlaylistId, songId, aOrdinal);
       
   150 
       
   151     // if the song is not already in the PlaylistSongInfo table - add it
       
   152     if (!SongInfoExistsL(aDriveId, songId))
       
   153         {
       
   154         // add a new song info record
       
   155         HBufC* uri = MPXDbCommonUtil::ProcessSingleQuotesLC(aMedia.ValueText(KMPXMediaGeneralUri));
       
   156         HBufC* title = MPXDbCommonUtil::ProcessSingleQuotesLC(aMedia.ValueText(KMPXMediaGeneralTitle));
       
   157 
       
   158         TUint32 dbFlag(0);
       
   159         if (aMedia.IsSupported(KMPXMediaGeneralFlags))
       
   160             {
       
   161             dbFlag = (aMedia.ValueTObjectL<TUint>(KMPXMediaGeneralFlags));
       
   162             dbFlag = dbFlag & (~KMPXMediaGeneralFlagsDriveInfo); // clear drive info
       
   163             }
       
   164 
       
   165         // add the URI without the drive letter
       
   166         TPtrC uriPtr(uri->Mid(KMCPathStartPos));
       
   167         iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongInfoInsert, songId, &uriPtr, title,
       
   168             MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), TDriveUnit(*uri)), dbFlag);
       
   169 
       
   170         CleanupStack::PopAndDestroy(title);
       
   171         CleanupStack::PopAndDestroy(uri);
       
   172         }
       
   173 
       
   174     return songId;
       
   175     }
       
   176 
       
   177 // ----------------------------------------------------------------------------
       
   178 // CMPXDbPlaylistSongs::UpdateSongL
       
   179 // ----------------------------------------------------------------------------
       
   180 //
       
   181 TBool CMPXDbPlaylistSongs::UpdateSongL(
       
   182     TUint32 aSongId,
       
   183     const CMPXMedia& aMedia,
       
   184     TBool aResetFlags,
       
   185     TBool& aUpdated)
       
   186     {
       
   187     MPX_FUNC("CMPXDbPlaylistSongs::UpdateSongL");
       
   188 
       
   189     aUpdated = EFalse;
       
   190     TBool visibleChange(EFalse);
       
   191 
       
   192     // get the current record
       
   193     RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryPlaylistSongInfoGet, aSongId));
       
   194     CleanupClosePushL(recordset);
       
   195 
       
   196     if (recordset.Next() == KSqlAtRow)
       
   197         {
       
   198         const TArray<TMPXAttribute> attributes = aMedia.Attributes();
       
   199 
       
   200         // stores the current song ID, which may change during execution
       
   201         TUint32 songId(aSongId);
       
   202 
       
   203         TInt attrCount(attributes.Count());
       
   204         for (TInt i = 0; i < attrCount; ++i)
       
   205             {
       
   206             TInt contentId(attributes[i].ContentId());
       
   207             TUint attributeId(attributes[i].AttributeId());
       
   208 
       
   209             switch(contentId)
       
   210                 {
       
   211                 case KMPXMediaIdGeneral:
       
   212                     {
       
   213                     if (attributeId & EMPXMediaGeneralTitle)
       
   214                         {
       
   215                         // existing title
       
   216                         TPtrC title(aMedia.ValueText(KMPXMediaGeneralTitle).Left(KMCMaxTextLen));
       
   217 
       
   218                         // compare with the old title
       
   219                         if (title.Compare(MPXDbCommonUtil::GetColumnTextL(recordset, EPlaylistSongInfoTitle)) != 0)
       
   220                             {
       
   221                             HBufC* titleProc = MPXDbCommonUtil::ProcessSingleQuotesLC(title);
       
   222 
       
   223                             // title has changed - update on all drives
       
   224                             iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoUpdateTitle,
       
   225                                 titleProc, songId);
       
   226 
       
   227                             CleanupStack::PopAndDestroy(titleProc);
       
   228 
       
   229                             visibleChange = ETrue;
       
   230                             aUpdated = ETrue;
       
   231                             MPX_DEBUG2("    Title[%S]", &title);
       
   232                             }
       
   233                         }
       
   234 
       
   235                     if (attributeId & EMPXMediaGeneralUri)
       
   236                         {
       
   237                         const TDesC& uriOrig(aMedia.ValueText(KMPXMediaGeneralUri));
       
   238                         songId = MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), EMPXCollection, uriOrig, EFalse);
       
   239 
       
   240                         if (aSongId != songId)
       
   241                             {
       
   242                             // URI of the song has been changed. This changes the Id of the song and both the
       
   243                             // PlaylistSongs and PlaylistSongInfo tables should be updated accordingly.
       
   244 
       
   245                             HBufC* uri = MPXDbCommonUtil::ProcessSingleQuotesLC(uriOrig);
       
   246 
       
   247                             // use the URI without the drive letter
       
   248                             TPtrC uriPtr(uri->Mid(KMCPathStartPos));
       
   249 
       
   250                             // update the PlaylistSongInfo table on all drives
       
   251                             iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoUpdate, songId,
       
   252                                 &uriPtr, MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), TDriveUnit(*uri)), aSongId);
       
   253 
       
   254                             // update the PlaylistSongs table on all drives
       
   255                             iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsUpdate, songId,
       
   256                                 aSongId);
       
   257 
       
   258                             aUpdated = ETrue;
       
   259                             MPX_DEBUG3("    CurrentSongId[0x%x] changed to [0x%x]", aSongId, songId);
       
   260 
       
   261                             CleanupStack::PopAndDestroy(uri);
       
   262                             }
       
   263                         }
       
   264 
       
   265                     if (attributeId & EMPXMediaGeneralFlags)
       
   266                         {
       
   267                         TUint flag(aMedia.ValueTObjectL<TUint>(KMPXMediaGeneralFlags));
       
   268                         TUint32 curFlag(recordset.ColumnInt64(EPlaylistSongInfoDbFlag));
       
   269 
       
   270                         if (flag & KMPXMediaGeneralFlagsSetOrUnsetBit)
       
   271                             {
       
   272                             if (aResetFlags)
       
   273                                 {
       
   274                                 visibleChange = ETrue;
       
   275                                 curFlag = flag;
       
   276                                 }
       
   277                             else
       
   278                                 {
       
   279                                 // Set flag, visible change is true only if the flag status is changing
       
   280                                 visibleChange = visibleChange || ((curFlag^flag) & 0x7FFFFFFF);
       
   281                                 curFlag |= flag;
       
   282                                 }
       
   283                             }
       
   284                         else
       
   285                             {
       
   286                             // Clear flag, visible change is true only if the flag status is changing
       
   287                             visibleChange = visibleChange || (((curFlag^0xFFFFFFFF)^flag) & 0x7FFFFFFF);
       
   288                             curFlag &= (~flag);
       
   289                             }
       
   290 
       
   291                         if (visibleChange)
       
   292                             {
       
   293                             // update the flags on all drives
       
   294                             iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoUpdateFlags,
       
   295                                 curFlag, songId);
       
   296                             aUpdated = ETrue;
       
   297                             }
       
   298 
       
   299                         MPX_DEBUG2("    GeneralFlags[%b]", curFlag);
       
   300                         }
       
   301                     } // end case
       
   302                 } // end switch
       
   303             } // end for
       
   304         if ( aMedia.IsSupported( KMPXMediaMusicAlbumArtChanged ) )
       
   305             {
       
   306             if ( aMedia.ValueTObjectL<TInt>( KMPXMediaMusicAlbumArtChanged )== 1 )
       
   307                 {
       
   308                 aUpdated = ETrue;                        
       
   309                 }
       
   310             }
       
   311         }
       
   312 
       
   313     CleanupStack::PopAndDestroy(&recordset);
       
   314     return visibleChange;
       
   315     }
       
   316 
       
   317 // ----------------------------------------------------------------------------
       
   318 // CMPXDbPlaylistSongs::UpdateSongsL
       
   319 // ----------------------------------------------------------------------------
       
   320 //
       
   321 void CMPXDbPlaylistSongs::UpdateSongsL(
       
   322     TUint32 aPlaylistId,
       
   323     TUint32 aNewPlaylistId)
       
   324     {
       
   325     MPX_FUNC("CMPXDbPlaylistSongs::UpdateSongsL");
       
   326 
       
   327     // update the PlaylistSongs table on all drives
       
   328     iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsUpdatePlaylistId,
       
   329         aNewPlaylistId, aPlaylistId);
       
   330     }
       
   331 
       
   332 // ----------------------------------------------------------------------------
       
   333 // CMPXDbPlaylistSongs::ReorderSongL
       
   334 // ----------------------------------------------------------------------------
       
   335 //
       
   336 void CMPXDbPlaylistSongs::ReorderSongL(
       
   337     const TMPXItemId& aPlaylistId,
       
   338     const TMPXItemId& aSongId,
       
   339     TUint aOriginalOrdinal,
       
   340     TUint aNewOrdinal)
       
   341     {
       
   342     MPX_DEBUG1("-->CMPXDbPlaylistSongs::ReorderSongL");
       
   343     MPX_DEBUG5("    playlist[0x%x, 0x%x], song[0x%x, 0x%x]",
       
   344                aPlaylistId.iId1, aPlaylistId.iId2, aSongId.iId1, aSongId.iId2);
       
   345 
       
   346     //
       
   347     // Move the song up. The rest of the songs in between the old ordinal and new ordinal
       
   348     // need to be moved down, i.e. their ordinals need to be incremented
       
   349     //
       
   350     if (aOriginalOrdinal > aNewOrdinal)
       
   351         {
       
   352         iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsMoveSongUp,
       
   353             aPlaylistId.iId2, aNewOrdinal, aOriginalOrdinal);
       
   354         }
       
   355 
       
   356     //
       
   357     // Move the song down. The rest of the songs in between the old ordinal and new ordinal
       
   358     // need to be moved up, i.e. their ordinals need to be decremented
       
   359     //
       
   360     else if (aOriginalOrdinal < aNewOrdinal)
       
   361         {
       
   362         iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsMoveSongDown,
       
   363             aPlaylistId.iId2, aNewOrdinal, aOriginalOrdinal);
       
   364         }
       
   365 
       
   366     //
       
   367     // Change the ordinal of the song itself. If the ordinal is unchanged, no update is
       
   368     // required
       
   369     //
       
   370     if (aOriginalOrdinal != aNewOrdinal)
       
   371         {
       
   372         iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsUpdateSongOrdinal,
       
   373             aNewOrdinal, aSongId.iId1);
       
   374         }
       
   375 
       
   376     MPX_DEBUG1("<--CMPXDbPlaylistSongs::ReorderSongL");
       
   377     }
       
   378 
       
   379 // ----------------------------------------------------------------------------
       
   380 // CMPXDbPlaylistSongs::DeleteSongL
       
   381 // ----------------------------------------------------------------------------
       
   382 //
       
   383 void CMPXDbPlaylistSongs::DeleteSongL(
       
   384     TUint32 aSongId)
       
   385     {
       
   386     MPX_FUNC("CMPXDbPlaylistSongs::DeleteSongL");
       
   387 
       
   388     // delete from the PlaylistSongs table on all drives
       
   389     iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsDelete, aSongId);
       
   390 
       
   391     // delete from the PlaylistSongInfo table on all drives
       
   392     iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoDelete, aSongId);
       
   393     }
       
   394 
       
   395 // ----------------------------------------------------------------------------
       
   396 // CMPXDbPlaylistSongs::DeleteSongL
       
   397 // ----------------------------------------------------------------------------
       
   398 //
       
   399 void CMPXDbPlaylistSongs::DeleteSongL(
       
   400     TUint32 aPlaylistId,
       
   401     TUint32 aSongId,
       
   402     TInt aOrdinal,
       
   403     TInt aDriveId)
       
   404     {
       
   405     MPX_FUNC("CMPXDbPlaylist::DeleteSongL");
       
   406 
       
   407     // get the number of instances for the song in the playlist
       
   408     TInt count(SongInstanceCountL(aPlaylistId, aSongId));
       
   409 
       
   410     if (1 == count)
       
   411         {
       
   412         // just one instance with this ID in the playlist
       
   413         // delete it regardless of the ordinal
       
   414         iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeleteSong, aPlaylistId, aSongId);
       
   415 
       
   416         // check how many instances of this song are left for all playlists
       
   417         if (!SongCountL(aSongId))
       
   418             {
       
   419             // delete the PlaylistSongInfo record
       
   420             iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongInfoDelete, aSongId);
       
   421             }
       
   422         }
       
   423     else if (count > 1)
       
   424         {
       
   425         // multiple songs with this id in the playlist
       
   426         // try to delete the one with the specified ordinal
       
   427         iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeleteSongOrdinal, aPlaylistId,
       
   428             aSongId, aOrdinal);
       
   429         }
       
   430     else
       
   431         {
       
   432         // no such song in the playlist
       
   433         User::Leave(KErrCorrupt);
       
   434         }
       
   435     // adjust song ordinals for the songs after the deleted song
       
   436     iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsUpdateSongOrdinalAfterDelete,
       
   437         aPlaylistId, aOrdinal);
       
   438     }
       
   439 
       
   440 // ----------------------------------------------------------------------------
       
   441 // CMPXDbPlaylistSongs::DeleteSongsL
       
   442 // ----------------------------------------------------------------------------
       
   443 //
       
   444 void CMPXDbPlaylistSongs::DeleteSongsL(
       
   445     TUint32 aPlaylistId,
       
   446     TInt aDriveId)
       
   447     {
       
   448     MPX_FUNC("CMPXDbPlaylist::DeleteSongsL");
       
   449 
       
   450     // delete the records from the PlaylistSongs table
       
   451     iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeletePlaylist, aPlaylistId);
       
   452 
       
   453     // delete the unused records from the PlaylistSongInfo table
       
   454     CleanupSongInfoL(aDriveId);
       
   455     }
       
   456 
       
   457 // ----------------------------------------------------------------------------
       
   458 // CMPXDbPlaylistSongs::DeleteSongsForCategoryL
       
   459 // ----------------------------------------------------------------------------
       
   460 //
       
   461 void CMPXDbPlaylistSongs::DeleteSongsForCategoryL(
       
   462     TMPXGeneralCategory aCategory,
       
   463     TUint32 aCategoryId,
       
   464     TInt aDriveId)
       
   465     {
       
   466     MPX_FUNC("CMPXDbPlaylist::DeleteSongsForCategoryL");
       
   467 
       
   468     // get the category field name in the Music table
       
   469     TPtrC category = MPXDbUtil::MusicFieldNameForCategoryL(aCategory);
       
   470 
       
   471     iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeleteForCategory,
       
   472         &category, aCategoryId);
       
   473 
       
   474     // delete the unused records from the PlaylistSongInfo table
       
   475     CleanupSongInfoL(aDriveId);
       
   476     }
       
   477 
       
   478 // ----------------------------------------------------------------------------
       
   479 // CMPXDbPlaylistSongs::DeleteSongsForArtistAndAlbumL
       
   480 // ----------------------------------------------------------------------------
       
   481 //
       
   482 void CMPXDbPlaylistSongs::DeleteSongsForArtistAndAlbumL(
       
   483     TUint32 aArtistId,
       
   484     TUint32 aAlbumId,
       
   485     TInt aDriveId)
       
   486     {
       
   487     MPX_FUNC("CMPXDbPlaylist::DeleteSongsForArtistAndAlbumL");
       
   488 
       
   489     // delete the songs in the PlaylisSongs table
       
   490     iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeleteForArtistAlbum,
       
   491         aArtistId, aAlbumId);
       
   492 
       
   493     // delete the unused records from the PlaylistSongInfo table
       
   494     CleanupSongInfoL(aDriveId);
       
   495     }
       
   496 
       
   497 // ----------------------------------------------------------------------------
       
   498 // CMPXDbPlaylistSongs::DeleteAllSongsL
       
   499 // ----------------------------------------------------------------------------
       
   500 //
       
   501 void CMPXDbPlaylistSongs::DeleteAllSongsL()
       
   502     {
       
   503     MPX_FUNC("CMPXDbPlaylist::DeleteAllSongsL");
       
   504 
       
   505     // delete all records from the PlaylistSongs table, all drives
       
   506     iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsDeleteAll);
       
   507 
       
   508     // delete all records from the PlaylistSongInfo table, all drives
       
   509     iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoDeleteAll);
       
   510     }
       
   511 
       
   512 // ----------------------------------------------------------------------------
       
   513 // CMPXDbPlaylistSongs::GetSongsL
       
   514 // ----------------------------------------------------------------------------
       
   515 //
       
   516 void CMPXDbPlaylistSongs::GetSongsL(
       
   517     TUint32 aPlaylistId,
       
   518     CMPXMediaArray& aMediaArray)
       
   519     {
       
   520     MPX_DEBUG2("-->CMPXDbPlaylistSongs::GetSongsL(playlist 0x%x)", aPlaylistId);
       
   521 
       
   522     RArray<TMPXAttribute> attributes;
       
   523     CleanupClosePushL( attributes );
       
   524 
       
   525     attributes.AppendL(KMPXMediaGeneralType);
       
   526     attributes.AppendL(KMPXMediaGeneralCategory);
       
   527     attributes.AppendL(KMPXMediaGeneralId);
       
   528 
       
   529     // cannot execute a joined query to the music table
       
   530     // because the song records in the music table may be on a different drive
       
   531     ExecuteMediaQueryL(attributes.Array(), aMediaArray, KQueryPlaylistSongsGetSongs, aPlaylistId);
       
   532 
       
   533     CleanupStack::PopAndDestroy(&attributes);
       
   534 
       
   535     MPX_DEBUG1("<--CMPXDbPlaylistSongs::GetSongsL");
       
   536     }
       
   537 
       
   538 // ----------------------------------------------------------------------------
       
   539 // CMPXDbPlaylistSongs::GetSongsL
       
   540 // ----------------------------------------------------------------------------
       
   541 //
       
   542 TBool CMPXDbPlaylistSongs::GetSongsL(
       
   543     TUint32 aPlaylistId,
       
   544     const TArray<TMPXAttribute>& aAttrs,
       
   545     CMPXMediaArray& aMediaArray)
       
   546     {
       
   547     MPX_DEBUG2("-->CMPXDbPlaylistSongs::GetSongsL(playlist 0x%x)", aPlaylistId);
       
   548     TBool valid(EFalse);
       
   549 
       
   550     RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryPlaylistSongsGetSongsInfo,
       
   551     		aPlaylistId));
       
   552     CleanupClosePushL(recordset);
       
   553 
       
   554     TInt err(KErrNone);
       
   555     while ((err = recordset.Next()) == KSqlAtRow)
       
   556         {
       
   557         CMPXMedia* media = CMPXMedia::NewL();
       
   558         CleanupStack::PushL(media);
       
   559 
       
   560         UpdateMediaL(recordset, aAttrs, *media);
       
   561 
       
   562         aMediaArray.AppendL(*media);
       
   563         CleanupStack::PopAndDestroy(media);
       
   564         }
       
   565     CleanupStack::PopAndDestroy(&recordset);
       
   566 
       
   567     if (err!= KSqlAtEnd)
       
   568         {
       
   569         User::Leave(KErrCorrupt);
       
   570         }
       
   571     else
       
   572     	{
       
   573     	valid = ETrue;
       
   574     	}
       
   575 
       
   576     MPX_DEBUG1("<--CMPXDbPlaylistSongs::GetSongsL");
       
   577     return valid;
       
   578     }
       
   579 
       
   580 // ----------------------------------------------------------------------------
       
   581 // CMPXDbPlaylistSongs::GetSongL
       
   582 // ----------------------------------------------------------------------------
       
   583 //
       
   584 TBool CMPXDbPlaylistSongs::GetSongL(
       
   585     TUint32 aPlaylistId,
       
   586     TUint32 aSongId,
       
   587     const TArray<TMPXAttribute>& aAttrs,
       
   588     CMPXMedia& aMedia)
       
   589     {
       
   590     MPX_FUNC("CMPXDbPlaylist::GetSongL");
       
   591 
       
   592     // get the song
       
   593     TBool valid(EFalse);
       
   594     RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryPlaylistSongsGetSong,
       
   595         aPlaylistId, aSongId));
       
   596     CleanupClosePushL(recordset);
       
   597 
       
   598     if (recordset.Next() == KSqlAtRow)
       
   599         {
       
   600         // convert to media
       
   601         UpdateMediaL(recordset, aAttrs, aMedia);
       
   602         valid = ETrue;
       
   603         }
       
   604 
       
   605     CleanupStack::PopAndDestroy(&recordset);
       
   606 
       
   607     return valid;
       
   608     }
       
   609 
       
   610 // ----------------------------------------------------------------------------
       
   611 // CMPXDbPlaylistSongs::GetSongL
       
   612 // ----------------------------------------------------------------------------
       
   613 //
       
   614 TBool CMPXDbPlaylistSongs::GetSongL(
       
   615     const TMPXItemId& aSongId,
       
   616     const TArray<TMPXAttribute>& aAttrs,
       
   617     CMPXMedia*& aMedia)
       
   618     {
       
   619     MPX_FUNC("CMPXDbPlaylist::GetSongL");
       
   620 
       
   621     // get the song
       
   622     TBool valid(EFalse);
       
   623     RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryPlaylistSongsGetSongInfo,
       
   624         aSongId.iId1, aSongId.iId2));
       
   625     CleanupClosePushL(recordset);
       
   626 
       
   627     if (recordset.Next() == KSqlAtRow)
       
   628         {
       
   629         // convert to media
       
   630         aMedia = CMPXMedia::NewL();
       
   631         CleanupStack::PushL(aMedia);
       
   632         UpdateMediaL(recordset, aAttrs, *aMedia);
       
   633         CleanupStack::Pop(aMedia);
       
   634         valid = ETrue;
       
   635         }
       
   636 
       
   637     CleanupStack::PopAndDestroy(&recordset);
       
   638 
       
   639     return valid;
       
   640     }
       
   641 
       
   642 // ----------------------------------------------------------------------------
       
   643 // CMPXDbPlaylistSongs::CountL
       
   644 // ----------------------------------------------------------------------------
       
   645 //
       
   646 TInt CMPXDbPlaylistSongs::CountL(
       
   647     TUint32 aPlaylistId,
       
   648     TInt aDriveId)
       
   649     {
       
   650     MPX_FUNC("CMPXDbPlaylist::CountL");
       
   651     return ExecuteSumExQueryL(KQueryPlaylistSongsCount, aPlaylistId, aDriveId);
       
   652     }
       
   653 
       
   654 // ----------------------------------------------------------------------------
       
   655 // CMPXDbPlaylistSongs::UpdateMediaL
       
   656 // ----------------------------------------------------------------------------
       
   657 //
       
   658 void CMPXDbPlaylistSongs::UpdateMediaL(
       
   659     RSqlStatement& aRecord,
       
   660     const TArray<TMPXAttribute>& aAttrs,
       
   661     CMPXMedia& aMedia)
       
   662     {
       
   663     MPX_FUNC("CMPXDbPlaylist::UpdateMediaL");
       
   664 
       
   665     aMedia.SetTObjectValueL<TMPXGeneralType>(KMPXMediaGeneralType, EMPXItem);
       
   666     aMedia.SetTObjectValueL<TMPXGeneralCategory>(KMPXMediaGeneralCategory, EMPXSong);
       
   667     aMedia.SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId, TMPXItemId(
       
   668         aRecord.ColumnInt64(EPlaylistSongsUniqueId),
       
   669         aRecord.ColumnInt64(EPlaylistSongsSongId)));
       
   670 
       
   671 /*
       
   672     aMedia.SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId,
       
   673         aRecord.ColumnInt64(EPlaylistSongsSongId));
       
   674 */
       
   675     TInt count(aAttrs.Count());
       
   676     for (TInt index = 0; index < count; ++index)
       
   677         {
       
   678         TInt contentId(aAttrs[index].ContentId());
       
   679         TUint attributeId(aAttrs[index].AttributeId());
       
   680 
       
   681         if (contentId == KMPXMediaIdGeneral)
       
   682             {
       
   683             if (attributeId & EMPXMediaGeneralCollectionId)
       
   684                 {
       
   685                 aMedia.SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralCollectionId,
       
   686                     aRecord.ColumnInt64(EPlaylistSongsPlaylistId));
       
   687                 }
       
   688             if (attributeId & EMPXMediaGeneralTitle)
       
   689                 {
       
   690                 TPtrC title(MPXDbCommonUtil::GetColumnTextL(aRecord, EPlaylistSongsTitle));
       
   691                 aMedia.SetTextValueL(KMPXMediaGeneralTitle, title);
       
   692                 MPX_DEBUG2("    Title[%S]", &title);
       
   693                 }
       
   694             if (attributeId & EMPXMediaGeneralUri)
       
   695                 {
       
   696                 TUint volId(aRecord.ColumnInt64(EPlaylistSongsVolumeId));
       
   697                 HBufC* uri = MPXDbCommonUtil::CreateFullPathL(
       
   698                     MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(), volId),
       
   699                     MPXDbCommonUtil::GetColumnTextL(aRecord, EPlaylistSongsUri));
       
   700                 CleanupStack::PushL(uri);
       
   701 
       
   702                 aMedia.SetTextValueL(KMPXMediaGeneralUri, *uri);
       
   703 
       
   704                 MPX_DEBUG2("    URI[%S]", uri);
       
   705                 CleanupStack::PopAndDestroy(uri);
       
   706                 }
       
   707             if (attributeId & EMPXMediaGeneralFlags)
       
   708                 {
       
   709                 // assuming song details shouldn't be available for this song
       
   710                 TUint32 dbFlags(aRecord.ColumnInt64(EPlaylistSongsDbFlag) |
       
   711                                 KMPXMediaGeneralFlagsIsMissingDetails);
       
   712                 TUint32 volId(aRecord.ColumnInt64(EPlaylistSongsVolumeId));
       
   713                 TDriveUnit driveUnit(EDriveC);
       
   714                 if (aMedia.IsSupported(KMPXMediaGeneralUri))
       
   715                     {
       
   716                     // ignore the return value
       
   717                     MPXDbCommonUtil::GetDriveL(aMedia.ValueText(KMPXMediaGeneralUri), driveUnit);
       
   718                     }
       
   719                 else
       
   720                     {
       
   721                     driveUnit = MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(), volId);
       
   722                     }
       
   723 
       
   724                 // the volume the playlist song is located on may be removed
       
   725                 if (~dbFlags & KMPXMediaGeneralFlagsIsInvalid)
       
   726                     {
       
   727                     if (((volId != 0) && (MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(), volId) == KErrNotFound)) ||
       
   728                         ((volId == 0) && (MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), driveUnit) == 0)))
       
   729                         {
       
   730                         dbFlags |= KMPXMediaGeneralFlagsIsInvalid;
       
   731                         }
       
   732                     }
       
   733 
       
   734                 TInt driveId(driveUnit & KMPXMediaGeneralFlagsDriveInfo);  // 5 bits
       
   735                 aMedia.SetTObjectValueL<TUint>(KMPXMediaGeneralFlags, dbFlags | driveId);
       
   736                 MPX_DEBUG2("    GeneralFlags[%b]", dbFlags | driveId);
       
   737                 }
       
   738             }
       
   739         }
       
   740     }
       
   741 
       
   742 // ----------------------------------------------------------------------------
       
   743 // CMPXDbPlaylistSongs::SongInstanceCountL
       
   744 // ----------------------------------------------------------------------------
       
   745 //
       
   746 TInt CMPXDbPlaylistSongs::SongInstanceCountL(
       
   747     TUint32 aPlaylistId,
       
   748     TUint32 aSongId)
       
   749     {
       
   750     MPX_FUNC("CMPXDbPlaylistSongs::SongInstanceCountL");
       
   751     return ExecuteSumQueryL(KQueryPlaylistSongsPlaylistSongCount, aPlaylistId, aSongId);
       
   752     }
       
   753 
       
   754 // ----------------------------------------------------------------------------
       
   755 // CMPXDbPlaylistSongs::SongCountL
       
   756 // ----------------------------------------------------------------------------
       
   757 //
       
   758 TInt CMPXDbPlaylistSongs::SongCountL(
       
   759     TUint32 aSongId)
       
   760     {
       
   761     MPX_FUNC("CMPXDbPlaylistSongs::SongCountL");
       
   762     return ExecuteSumQueryL(KQueryPlaylistSongsSongCount, aSongId);
       
   763     }
       
   764 
       
   765 // ----------------------------------------------------------------------------
       
   766 // CMPXDbPlaylistSongs::SongInfoExistsL
       
   767 // The song info record must be in the same database as the corresponding
       
   768 // PlaylistSongs record(s), otherwise when adding a duplicate of a song on a
       
   769 // different drive this method will return true and the song info record won't
       
   770 // be created.
       
   771 // ----------------------------------------------------------------------------
       
   772 //
       
   773 TBool CMPXDbPlaylistSongs::SongInfoExistsL(
       
   774     TInt aDriveId,
       
   775     TUint32 aSongId)
       
   776     {
       
   777     MPX_FUNC("CMPXDbPlaylistSongs::SongInfoExistsL");
       
   778 
       
   779     RSqlStatement recordset(
       
   780         iDbManager.ExecuteSelectQueryL(aDriveId, KQueryPlaylistSongInfoExists, aSongId));
       
   781     TBool exists(recordset.Next() == KSqlAtRow);
       
   782     recordset.Close();
       
   783     return exists;
       
   784     }
       
   785 
       
   786 // ----------------------------------------------------------------------------
       
   787 // CMPXDbPlaylistSongs::CleanupSongInfoL
       
   788 // ----------------------------------------------------------------------------
       
   789 //
       
   790 void CMPXDbPlaylistSongs::CleanupSongInfoL(
       
   791     TInt aDriveId)
       
   792     {
       
   793     MPX_FUNC("CMPXDbPlaylistSongs::CleanupSongInfoL");
       
   794     iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongInfoCleanup);
       
   795     }
       
   796 
       
   797 // ----------------------------------------------------------------------------
       
   798 // CMPXDbPlaylistSongs::CreateTableL
       
   799 // ----------------------------------------------------------------------------
       
   800 //
       
   801 void CMPXDbPlaylistSongs::CreateTableL(
       
   802     RSqlDatabase& aDatabase,
       
   803     TBool /* aCorruptTable */)
       
   804     {
       
   805     MPX_FUNC("CMPXDbPlaylistSongs::CreateTableL");
       
   806 
       
   807     // create the PlaylistSongs table
       
   808     User::LeaveIfError(aDatabase.Exec(KPlaylistSongsCreateTable));
       
   809 
       
   810     // create the PlaylistSongInfo table
       
   811     User::LeaveIfError(aDatabase.Exec(KPlaylistSongInfoCreateTable));
       
   812     }
       
   813 
       
   814 // ----------------------------------------------------------------------------
       
   815 // CMPXDbPlaylistSongs::DropTableL
       
   816 // ----------------------------------------------------------------------------
       
   817 //
       
   818 void CMPXDbPlaylistSongs::DropTableL(
       
   819     RSqlDatabase& aDatabase)
       
   820     {
       
   821     MPX_FUNC("CMPXDbPlaylistSongs::DropTableL");
       
   822 
       
   823     // drop the PlaylistSongs table
       
   824     User::LeaveIfError(aDatabase.Exec(KPlaylistSongsDropTable));
       
   825 
       
   826     // drop the PlaylistSongInfo table
       
   827     User::LeaveIfError(aDatabase.Exec(KPlaylistSongInfoDropTable));
       
   828     }
       
   829 
       
   830 // ----------------------------------------------------------------------------
       
   831 // CMPXDbPlaylistSongs::CheckTableL
       
   832 // ----------------------------------------------------------------------------
       
   833 //
       
   834 TBool CMPXDbPlaylistSongs::CheckTableL(
       
   835     RSqlDatabase& aDatabase)
       
   836     {
       
   837     MPX_FUNC("CMPXDbPlaylistSongs::CheckTableL");
       
   838 
       
   839     // check the PlaylistSongs table
       
   840     TBool check = DoCheckTable(aDatabase, KPlaylistSongsCheckTable);
       
   841 
       
   842     // check the PlaylistSongInfo table
       
   843     return check && DoCheckTable(aDatabase, KPlaylistSongInfoCheckTable);
       
   844     }
       
   845 
       
   846 // End of File