--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbplugin/src/mpxdbplaylistsongs.cpp Thu Dec 17 08:45:05 2009 +0200
@@ -0,0 +1,832 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Responsible for interaction with the PlaylistSongs and
+* PlaylistSongInfo tables.
+*
+*/
+
+
+// INCLUDE FILES
+#include <f32file.h>
+#include <mpxlog.h>
+#include <mpxmedia.h>
+#include <mpxmediaarray.h>
+#include <mpxmediageneraldefs.h>
+#include "mpxdbcommonutil.h"
+
+#include "mpxcollectiondbdef.h"
+#include "mpxdbutil.h"
+#include "mpxdbpluginqueries.h"
+#include "mpxdbmanager.h"
+#include "mpxdbplaylistsongs.h"
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXDbPlaylistSongs* CMPXDbPlaylistSongs::NewL(
+ CMPXDbManager& aDbManager)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::NewL");
+
+ CMPXDbPlaylistSongs* self = CMPXDbPlaylistSongs::NewLC(aDbManager);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXDbPlaylistSongs* CMPXDbPlaylistSongs::NewLC(
+ CMPXDbManager& aDbManager)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::NewLC");
+
+ CMPXDbPlaylistSongs* self = new (ELeave) CMPXDbPlaylistSongs(aDbManager);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------------------------
+//
+CMPXDbPlaylistSongs::~CMPXDbPlaylistSongs()
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::~CMPXDbPlaylistSongs");
+ }
+
+// ----------------------------------------------------------------------------
+// Constructor
+// ----------------------------------------------------------------------------
+//
+CMPXDbPlaylistSongs::CMPXDbPlaylistSongs(
+ CMPXDbManager& aDbManager) :
+ CMPXDbTable(aDbManager)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::CMPXDbPlaylistSongs");
+ }
+
+// ----------------------------------------------------------------------------
+// Second phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::ConstructL()
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::ConstructL");
+ BaseConstructL();
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::AddSongsL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::AddSongsL(
+ TUint32 aPlaylistId,
+ const CMPXMediaArray& aMediaArray,
+ TInt aDriveId)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::AddSongsL");
+
+ TInt count(aMediaArray.Count());
+ for (TInt index = 0; index < count; ++index)
+ {
+ AddSongL(aPlaylistId, *(aMediaArray[index]), aDriveId);
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::AddSongL
+// ----------------------------------------------------------------------------
+//
+TUint32 CMPXDbPlaylistSongs::AddSongL(
+ TUint32 aPlaylistId,
+ const CMPXMedia& aMedia,
+ TInt aDriveId)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::AddSongL");
+ return AddSongL(aPlaylistId, CountL(aPlaylistId), aMedia, aDriveId);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::AddSongL
+// ----------------------------------------------------------------------------
+//
+TUint32 CMPXDbPlaylistSongs::AddSongL(
+ TUint32 aPlaylistId,
+ TInt aOrdinal,
+ const CMPXMedia& aMedia,
+ TInt aDriveId)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::AddSongL");
+
+ // the UniqueId field is AUTOINCREMENT and its value is going to be generated
+ // automatically by the database - no need to supply it here
+ TUint32 songId((aMedia.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId)).iId2);
+
+ // insert PlaylistSongs record
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsInsert, aPlaylistId, songId, aOrdinal);
+
+ // if the song is not already in the PlaylistSongInfo table - add it
+ if (!SongInfoExistsL(aDriveId, songId))
+ {
+ // add a new song info record
+ HBufC* uri = MPXDbCommonUtil::ProcessSingleQuotesLC(aMedia.ValueText(KMPXMediaGeneralUri));
+ HBufC* title = MPXDbCommonUtil::ProcessSingleQuotesLC(aMedia.ValueText(KMPXMediaGeneralTitle));
+
+ TUint32 dbFlag(0);
+ if (aMedia.IsSupported(KMPXMediaGeneralFlags))
+ {
+ dbFlag = (aMedia.ValueTObjectL<TUint>(KMPXMediaGeneralFlags));
+ dbFlag = dbFlag & (~KMPXMediaGeneralFlagsDriveInfo); // clear drive info
+ }
+
+ // add the URI without the drive letter
+ TPtrC uriPtr(uri->Mid(KMCPathStartPos));
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongInfoInsert, songId, &uriPtr, title,
+ MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), TDriveUnit(*uri)), dbFlag);
+
+ CleanupStack::PopAndDestroy(title);
+ CleanupStack::PopAndDestroy(uri);
+ }
+
+ return songId;
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::UpdateSongL
+// ----------------------------------------------------------------------------
+//
+TBool CMPXDbPlaylistSongs::UpdateSongL(
+ TUint32 aSongId,
+ const CMPXMedia& aMedia,
+ TBool aResetFlags,
+ TBool& aUpdated)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::UpdateSongL");
+
+ aUpdated = EFalse;
+ TBool visibleChange(EFalse);
+
+ // get the current record
+ RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryPlaylistSongInfoGet, aSongId));
+ CleanupClosePushL(recordset);
+
+ if (recordset.Next() == KSqlAtRow)
+ {
+ const TArray<TMPXAttribute> attributes = aMedia.Attributes();
+
+ // stores the current song ID, which may change during execution
+ TUint32 songId(aSongId);
+
+ TInt attrCount(attributes.Count());
+ for (TInt i = 0; i < attrCount; ++i)
+ {
+ TInt contentId(attributes[i].ContentId());
+ TUint attributeId(attributes[i].AttributeId());
+
+ switch(contentId)
+ {
+ case KMPXMediaIdGeneral:
+ {
+ if (attributeId & EMPXMediaGeneralTitle)
+ {
+ // existing title
+ TPtrC title(aMedia.ValueText(KMPXMediaGeneralTitle).Left(KMCMaxTextLen));
+
+ // compare with the old title
+ if (title.Compare(MPXDbCommonUtil::GetColumnTextL(recordset, EPlaylistSongInfoTitle)) != 0)
+ {
+ HBufC* titleProc = MPXDbCommonUtil::ProcessSingleQuotesLC(title);
+
+ // title has changed - update on all drives
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoUpdateTitle,
+ titleProc, songId);
+
+ CleanupStack::PopAndDestroy(titleProc);
+
+ visibleChange = ETrue;
+ aUpdated = ETrue;
+ MPX_DEBUG2(" Title[%S]", &title);
+ }
+ }
+
+ if (attributeId & EMPXMediaGeneralUri)
+ {
+ const TDesC& uriOrig(aMedia.ValueText(KMPXMediaGeneralUri));
+ songId = MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), EMPXCollection, uriOrig, EFalse);
+
+ if (aSongId != songId)
+ {
+ // URI of the song has been changed. This changes the Id of the song and both the
+ // PlaylistSongs and PlaylistSongInfo tables should be updated accordingly.
+
+ HBufC* uri = MPXDbCommonUtil::ProcessSingleQuotesLC(uriOrig);
+
+ // use the URI without the drive letter
+ TPtrC uriPtr(uri->Mid(KMCPathStartPos));
+
+ // update the PlaylistSongInfo table on all drives
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoUpdate, songId,
+ &uriPtr, MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), TDriveUnit(*uri)), aSongId);
+
+ // update the PlaylistSongs table on all drives
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsUpdate, songId,
+ aSongId);
+
+ aUpdated = ETrue;
+ MPX_DEBUG3(" CurrentSongId[0x%x] changed to [0x%x]", aSongId, songId);
+
+ CleanupStack::PopAndDestroy(uri);
+ }
+ }
+
+ if (attributeId & EMPXMediaGeneralFlags)
+ {
+ TUint flag(aMedia.ValueTObjectL<TUint>(KMPXMediaGeneralFlags));
+ TUint32 curFlag(recordset.ColumnInt64(EPlaylistSongInfoDbFlag));
+
+ if (flag & KMPXMediaGeneralFlagsSetOrUnsetBit)
+ {
+ if (aResetFlags)
+ {
+ visibleChange = ETrue;
+ curFlag = flag;
+ }
+ else
+ {
+ // Set flag, visible change is true only if the flag status is changing
+ visibleChange = visibleChange || ((curFlag^flag) & 0x7FFFFFFF);
+ curFlag |= flag;
+ }
+ }
+ else
+ {
+ // Clear flag, visible change is true only if the flag status is changing
+ visibleChange = visibleChange || (((curFlag^0xFFFFFFFF)^flag) & 0x7FFFFFFF);
+ curFlag &= (~flag);
+ }
+
+ if (visibleChange)
+ {
+ // update the flags on all drives
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoUpdateFlags,
+ curFlag, songId);
+ aUpdated = ETrue;
+ }
+
+ MPX_DEBUG2(" GeneralFlags[%b]", curFlag);
+ }
+ } // end case
+ } // end switch
+ } // end for
+ }
+
+ CleanupStack::PopAndDestroy(&recordset);
+ return visibleChange;
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::UpdateSongsL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::UpdateSongsL(
+ TUint32 aPlaylistId,
+ TUint32 aNewPlaylistId)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::UpdateSongsL");
+
+ // update the PlaylistSongs table on all drives
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsUpdatePlaylistId,
+ aNewPlaylistId, aPlaylistId);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::ReorderSongL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::ReorderSongL(
+ const TMPXItemId& aPlaylistId,
+ const TMPXItemId& aSongId,
+ TUint aOriginalOrdinal,
+ TUint aNewOrdinal)
+ {
+ MPX_DEBUG1("-->CMPXDbPlaylistSongs::ReorderSongL");
+ MPX_DEBUG5(" playlist[0x%x, 0x%x], song[0x%x, 0x%x]",
+ aPlaylistId.iId1, aPlaylistId.iId2, aSongId.iId1, aSongId.iId2);
+
+ //
+ // Move the song up. The rest of the songs in between the old ordinal and new ordinal
+ // need to be moved down, i.e. their ordinals need to be incremented
+ //
+ if (aOriginalOrdinal > aNewOrdinal)
+ {
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsMoveSongUp,
+ aPlaylistId.iId2, aNewOrdinal, aOriginalOrdinal);
+ }
+
+ //
+ // Move the song down. The rest of the songs in between the old ordinal and new ordinal
+ // need to be moved up, i.e. their ordinals need to be decremented
+ //
+ else if (aOriginalOrdinal < aNewOrdinal)
+ {
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsMoveSongDown,
+ aPlaylistId.iId2, aNewOrdinal, aOriginalOrdinal);
+ }
+
+ //
+ // Change the ordinal of the song itself. If the ordinal is unchanged, no update is
+ // required
+ //
+ if (aOriginalOrdinal != aNewOrdinal)
+ {
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsUpdateSongOrdinal,
+ aNewOrdinal, aSongId.iId1);
+ }
+
+ MPX_DEBUG1("<--CMPXDbPlaylistSongs::ReorderSongL");
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::DeleteSongL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::DeleteSongL(
+ TUint32 aSongId)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::DeleteSongL");
+
+ // delete from the PlaylistSongs table on all drives
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsDelete, aSongId);
+
+ // delete from the PlaylistSongInfo table on all drives
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoDelete, aSongId);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::DeleteSongL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::DeleteSongL(
+ TUint32 aPlaylistId,
+ TUint32 aSongId,
+ TInt aOrdinal,
+ TInt aDriveId)
+ {
+ MPX_FUNC("CMPXDbPlaylist::DeleteSongL");
+
+ // get the number of instances for the song in the playlist
+ TInt count(SongInstanceCountL(aPlaylistId, aSongId));
+
+ if (1 == count)
+ {
+ // just one instance with this ID in the playlist
+ // delete it regardless of the ordinal
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeleteSong, aPlaylistId, aSongId);
+
+ // check how many instances of this song are left for all playlists
+ if (!SongCountL(aSongId))
+ {
+ // delete the PlaylistSongInfo record
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongInfoDelete, aSongId);
+ }
+ }
+ else if (count > 1)
+ {
+ // multiple songs with this id in the playlist
+ // try to delete the one with the specified ordinal
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeleteSongOrdinal, aPlaylistId,
+ aSongId, aOrdinal);
+ }
+ else
+ {
+ // no such song in the playlist
+ User::Leave(KErrCorrupt);
+ }
+ // adjust song ordinals for the songs after the deleted song
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsUpdateSongOrdinalAfterDelete,
+ aPlaylistId, aOrdinal);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::DeleteSongsL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::DeleteSongsL(
+ TUint32 aPlaylistId,
+ TInt aDriveId)
+ {
+ MPX_FUNC("CMPXDbPlaylist::DeleteSongsL");
+
+ // delete the records from the PlaylistSongs table
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeletePlaylist, aPlaylistId);
+
+ // delete the unused records from the PlaylistSongInfo table
+ CleanupSongInfoL(aDriveId);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::DeleteSongsForCategoryL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::DeleteSongsForCategoryL(
+ TMPXGeneralCategory aCategory,
+ TUint32 aCategoryId,
+ TInt aDriveId)
+ {
+ MPX_FUNC("CMPXDbPlaylist::DeleteSongsForCategoryL");
+
+ // get the category field name in the Music table
+ TPtrC category = MPXDbUtil::MusicFieldNameForCategoryL(aCategory);
+
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeleteForCategory,
+ &category, aCategoryId);
+
+ // delete the unused records from the PlaylistSongInfo table
+ CleanupSongInfoL(aDriveId);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::DeleteSongsForArtistAndAlbumL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::DeleteSongsForArtistAndAlbumL(
+ TUint32 aArtistId,
+ TUint32 aAlbumId,
+ TInt aDriveId)
+ {
+ MPX_FUNC("CMPXDbPlaylist::DeleteSongsForArtistAndAlbumL");
+
+ // delete the songs in the PlaylisSongs table
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongsDeleteForArtistAlbum,
+ aArtistId, aAlbumId);
+
+ // delete the unused records from the PlaylistSongInfo table
+ CleanupSongInfoL(aDriveId);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::DeleteAllSongsL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::DeleteAllSongsL()
+ {
+ MPX_FUNC("CMPXDbPlaylist::DeleteAllSongsL");
+
+ // delete all records from the PlaylistSongs table, all drives
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongsDeleteAll);
+
+ // delete all records from the PlaylistSongInfo table, all drives
+ iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistSongInfoDeleteAll);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::GetSongsL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::GetSongsL(
+ TUint32 aPlaylistId,
+ CMPXMediaArray& aMediaArray)
+ {
+ MPX_DEBUG2("-->CMPXDbPlaylistSongs::GetSongsL(playlist 0x%x)", aPlaylistId);
+
+ RArray<TMPXAttribute> attributes;
+ CleanupClosePushL( attributes );
+
+ attributes.AppendL(KMPXMediaGeneralType);
+ attributes.AppendL(KMPXMediaGeneralCategory);
+ attributes.AppendL(KMPXMediaGeneralId);
+
+ // cannot execute a joined query to the music table
+ // because the song records in the music table may be on a different drive
+ ExecuteMediaQueryL(attributes.Array(), aMediaArray, KQueryPlaylistSongsGetSongs, aPlaylistId);
+
+ CleanupStack::PopAndDestroy(&attributes);
+
+ MPX_DEBUG1("<--CMPXDbPlaylistSongs::GetSongsL");
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::GetSongsL
+// ----------------------------------------------------------------------------
+//
+TBool CMPXDbPlaylistSongs::GetSongsL(
+ TUint32 aPlaylistId,
+ const TArray<TMPXAttribute>& aAttrs,
+ CMPXMediaArray& aMediaArray)
+ {
+ MPX_DEBUG2("-->CMPXDbPlaylistSongs::GetSongsL(playlist 0x%x)", aPlaylistId);
+ TBool valid(EFalse);
+
+ RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryPlaylistSongsGetSongsInfo,
+ aPlaylistId));
+ CleanupClosePushL(recordset);
+
+ TInt err(KErrNone);
+ while ((err = recordset.Next()) == KSqlAtRow)
+ {
+ CMPXMedia* media = CMPXMedia::NewL();
+ CleanupStack::PushL(media);
+
+ UpdateMediaL(recordset, aAttrs, *media);
+
+ aMediaArray.AppendL(*media);
+ CleanupStack::PopAndDestroy(media);
+ }
+ CleanupStack::PopAndDestroy(&recordset);
+
+ if (err!= KSqlAtEnd)
+ {
+ User::Leave(KErrCorrupt);
+ }
+ else
+ {
+ valid = ETrue;
+ }
+
+ MPX_DEBUG1("<--CMPXDbPlaylistSongs::GetSongsL");
+ return valid;
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::GetSongL
+// ----------------------------------------------------------------------------
+//
+TBool CMPXDbPlaylistSongs::GetSongL(
+ TUint32 aPlaylistId,
+ TUint32 aSongId,
+ const TArray<TMPXAttribute>& aAttrs,
+ CMPXMedia& aMedia)
+ {
+ MPX_FUNC("CMPXDbPlaylist::GetSongL");
+
+ // get the song
+ TBool valid(EFalse);
+ RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryPlaylistSongsGetSong,
+ aPlaylistId, aSongId));
+ CleanupClosePushL(recordset);
+
+ if (recordset.Next() == KSqlAtRow)
+ {
+ // convert to media
+ UpdateMediaL(recordset, aAttrs, aMedia);
+ valid = ETrue;
+ }
+
+ CleanupStack::PopAndDestroy(&recordset);
+
+ return valid;
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::GetSongL
+// ----------------------------------------------------------------------------
+//
+TBool CMPXDbPlaylistSongs::GetSongL(
+ const TMPXItemId& aSongId,
+ const TArray<TMPXAttribute>& aAttrs,
+ CMPXMedia*& aMedia)
+ {
+ MPX_FUNC("CMPXDbPlaylist::GetSongL");
+
+ // get the song
+ TBool valid(EFalse);
+ RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryPlaylistSongsGetSongInfo,
+ aSongId.iId1, aSongId.iId2));
+ CleanupClosePushL(recordset);
+
+ if (recordset.Next() == KSqlAtRow)
+ {
+ // convert to media
+ aMedia = CMPXMedia::NewL();
+ CleanupStack::PushL(aMedia);
+ UpdateMediaL(recordset, aAttrs, *aMedia);
+ CleanupStack::Pop(aMedia);
+ valid = ETrue;
+ }
+
+ CleanupStack::PopAndDestroy(&recordset);
+
+ return valid;
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::CountL
+// ----------------------------------------------------------------------------
+//
+TInt CMPXDbPlaylistSongs::CountL(
+ TUint32 aPlaylistId)
+ {
+ MPX_FUNC("CMPXDbPlaylist::CountL");
+ return ExecuteSumQueryL(KQueryPlaylistSongsCount, aPlaylistId);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::UpdateMediaL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::UpdateMediaL(
+ RSqlStatement& aRecord,
+ const TArray<TMPXAttribute>& aAttrs,
+ CMPXMedia& aMedia)
+ {
+ MPX_FUNC("CMPXDbPlaylist::UpdateMediaL");
+
+ aMedia.SetTObjectValueL<TMPXGeneralType>(KMPXMediaGeneralType, EMPXItem);
+ aMedia.SetTObjectValueL<TMPXGeneralCategory>(KMPXMediaGeneralCategory, EMPXSong);
+ aMedia.SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId, TMPXItemId(
+ aRecord.ColumnInt64(EPlaylistSongsUniqueId),
+ aRecord.ColumnInt64(EPlaylistSongsSongId)));
+
+/*
+ aMedia.SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId,
+ aRecord.ColumnInt64(EPlaylistSongsSongId));
+*/
+ TInt count(aAttrs.Count());
+ for (TInt index = 0; index < count; ++index)
+ {
+ TInt contentId(aAttrs[index].ContentId());
+ TUint attributeId(aAttrs[index].AttributeId());
+
+ if (contentId == KMPXMediaIdGeneral)
+ {
+ if (attributeId & EMPXMediaGeneralCollectionId)
+ {
+ aMedia.SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralCollectionId,
+ aRecord.ColumnInt64(EPlaylistSongsPlaylistId));
+ }
+ if (attributeId & EMPXMediaGeneralTitle)
+ {
+ TPtrC title(MPXDbCommonUtil::GetColumnTextL(aRecord, EPlaylistSongsTitle));
+ aMedia.SetTextValueL(KMPXMediaGeneralTitle, title);
+ MPX_DEBUG2(" Title[%S]", &title);
+ }
+ if (attributeId & EMPXMediaGeneralUri)
+ {
+ TUint volId(aRecord.ColumnInt64(EPlaylistSongsVolumeId));
+ HBufC* uri = MPXDbCommonUtil::CreateFullPathL(
+ MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(), volId),
+ MPXDbCommonUtil::GetColumnTextL(aRecord, EPlaylistSongsUri));
+ CleanupStack::PushL(uri);
+
+ aMedia.SetTextValueL(KMPXMediaGeneralUri, *uri);
+
+ MPX_DEBUG2(" URI[%S]", uri);
+ CleanupStack::PopAndDestroy(uri);
+ }
+ if (attributeId & EMPXMediaGeneralFlags)
+ {
+ // assuming song details shouldn't be available for this song
+ TUint32 dbFlags(aRecord.ColumnInt64(EPlaylistSongsDbFlag) |
+ KMPXMediaGeneralFlagsIsMissingDetails);
+ TUint32 volId(aRecord.ColumnInt64(EPlaylistSongsVolumeId));
+ TDriveUnit driveUnit(EDriveC);
+ if (aMedia.IsSupported(KMPXMediaGeneralUri))
+ {
+ // ignore the return value
+ MPXDbCommonUtil::GetDriveL(aMedia.ValueText(KMPXMediaGeneralUri), driveUnit);
+ }
+ else
+ {
+ driveUnit = MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(), volId);
+ }
+
+ // the volume the playlist song is located on may be removed
+ if (~dbFlags & KMPXMediaGeneralFlagsIsInvalid)
+ {
+ if (((volId != 0) && (MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(), volId) == KErrNotFound)) ||
+ ((volId == 0) && (MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), driveUnit) == 0)))
+ {
+ dbFlags |= KMPXMediaGeneralFlagsIsInvalid;
+ }
+ }
+
+ TInt driveId(driveUnit & KMPXMediaGeneralFlagsDriveInfo); // 5 bits
+ aMedia.SetTObjectValueL<TUint>(KMPXMediaGeneralFlags, dbFlags | driveId);
+ MPX_DEBUG2(" GeneralFlags[%b]", dbFlags | driveId);
+ }
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::SongInstanceCountL
+// ----------------------------------------------------------------------------
+//
+TInt CMPXDbPlaylistSongs::SongInstanceCountL(
+ TUint32 aPlaylistId,
+ TUint32 aSongId)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::SongInstanceCountL");
+ return ExecuteSumQueryL(KQueryPlaylistSongsPlaylistSongCount, aPlaylistId, aSongId);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::SongCountL
+// ----------------------------------------------------------------------------
+//
+TInt CMPXDbPlaylistSongs::SongCountL(
+ TUint32 aSongId)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::SongCountL");
+ return ExecuteSumQueryL(KQueryPlaylistSongsSongCount, aSongId);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::SongInfoExistsL
+// The song info record must be in the same database as the corresponding
+// PlaylistSongs record(s), otherwise when adding a duplicate of a song on a
+// different drive this method will return true and the song info record won't
+// be created.
+// ----------------------------------------------------------------------------
+//
+TBool CMPXDbPlaylistSongs::SongInfoExistsL(
+ TInt aDriveId,
+ TUint32 aSongId)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::SongInfoExistsL");
+
+ RSqlStatement recordset(
+ iDbManager.ExecuteSelectQueryL(aDriveId, KQueryPlaylistSongInfoExists, aSongId));
+ TBool exists(recordset.Next() == KSqlAtRow);
+ recordset.Close();
+ return exists;
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::CleanupSongInfoL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::CleanupSongInfoL(
+ TInt aDriveId)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::CleanupSongInfoL");
+ iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistSongInfoCleanup);
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::CreateTableL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::CreateTableL(
+ RSqlDatabase& aDatabase,
+ TBool /* aCorruptTable */)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::CreateTableL");
+
+ // create the PlaylistSongs table
+ User::LeaveIfError(aDatabase.Exec(KPlaylistSongsCreateTable));
+
+ // create the PlaylistSongInfo table
+ User::LeaveIfError(aDatabase.Exec(KPlaylistSongInfoCreateTable));
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::DropTableL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbPlaylistSongs::DropTableL(
+ RSqlDatabase& aDatabase)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::DropTableL");
+
+ // drop the PlaylistSongs table
+ User::LeaveIfError(aDatabase.Exec(KPlaylistSongsDropTable));
+
+ // drop the PlaylistSongInfo table
+ User::LeaveIfError(aDatabase.Exec(KPlaylistSongInfoDropTable));
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXDbPlaylistSongs::CheckTableL
+// ----------------------------------------------------------------------------
+//
+TBool CMPXDbPlaylistSongs::CheckTableL(
+ RSqlDatabase& aDatabase)
+ {
+ MPX_FUNC("CMPXDbPlaylistSongs::CheckTableL");
+
+ // check the PlaylistSongs table
+ TBool check = DoCheckTable(aDatabase, KPlaylistSongsCheckTable);
+
+ // check the PlaylistSongInfo table
+ return check && DoCheckTable(aDatabase, KPlaylistSongInfoCheckTable);
+ }
+
+// End of File