diff -r 14979e23cb5e -r 3de6c4cf6b67 mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbhgplugin/src/mpxdbhandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbhgplugin/src/mpxdbhandler.cpp Wed Sep 01 12:32:02 2010 +0100 @@ -0,0 +1,3310 @@ +/* +* 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: This class is used by db plugin for all database related +* functionality. The main responsibilities are: +* +*/ + + +// INCLUDE FILES +#include +#ifdef RD_MULTIPLE_DRIVE +#include +#include +#endif //RD_MULTIPLE_DRIVE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpxresource.h" +#include "mpxdbcommonutil.h" + +#include "mpxdbutil.h" +#include "mpxcollectiondbdef.h" +#include "mpxdbpluginqueries.h" +#include "mpxcollectiondbmanager.h" +#include "mpxdbplaylist.h" +#include "mpxdbplaylistsongs.h" +#include "mpxdbcategory.h" +#include "mpxdbauxiliary.h" +#include "mpxdbautoplaylist.h" +#include "mpxdbhandler.h" +#include "mpxdbartist.h" +#include "mpxdbalbum.h" +#include "mpxdbgenre.h" +#include "mpxdbcomposer.h" + +// CONSTANTS +_LIT(KMPXVirtualPlaylistExt, ".vir"); +static const TInt KMaxOpInTransaction = 100; + +const TInt KSqlDbCorrupted = -321; + +#if defined (__MTP_PROTOCOL_SUPPORT) + +#include + +// MTP CenRep Key UID +const TUid KMPXMtpSettings = {0x101FFC53}; +// MTP CenRep Key for Delete contents +const TUint32 KMPXMtpSaveDeletedRecordFlag = 0x00000001; + +#endif + +// ============================ MEMBER FUNCTIONS ============================== + +// ---------------------------------------------------------------------------- +// Two-phased constructor. +// ---------------------------------------------------------------------------- +// +CMPXDbHandler* CMPXDbHandler::NewL( + RFs& aFs, + CMPXResource& aResource) + { + MPX_FUNC("CMPXDbHandler::NewL"); + CMPXDbHandler* self = CMPXDbHandler::NewLC(aFs, aResource); + CleanupStack::Pop(self); + return self; + } + +// ---------------------------------------------------------------------------- +// Two-phased constructor. +// ---------------------------------------------------------------------------- +// +CMPXDbHandler* CMPXDbHandler::NewLC( + RFs& aFs, + CMPXResource& aResource) + { + MPX_FUNC("CMPXDbHandler::NewLC"); + CMPXDbHandler* self = new (ELeave) CMPXDbHandler(aFs, aResource); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +// ---------------------------------------------------------------------------- +// Destructor +// ---------------------------------------------------------------------------- +// +CMPXDbHandler::~CMPXDbHandler() + { + MPX_FUNC("CMPXDbHandler::~CMPXDbHandler"); + + delete iAutoPlaylist; + + delete iDbMusic; + delete iDbPlaylist; + delete iDbArtist; + delete iDbAlbum; + delete iDbGenre; + delete iDbComposer; + delete iDbAuxiliary; + delete iDbManager; +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + delete iDbAbstractAlbum; +#endif // ABSTRACTAUDIOALBUM_INCLUDED + delete iMimeTypes; + delete iExtensions; + delete iExtensionsMime; + delete iExtensionsDrm; + + iDbDrives.Close(); + } + +// ---------------------------------------------------------------------------- +// C++ default constructor can NOT contain any code, that might leave +// ---------------------------------------------------------------------------- +// +CMPXDbHandler::CMPXDbHandler( + RFs& aFs, + CMPXResource& aResource) : + iFs(aFs), + iResource(aResource) + { + MPX_FUNC("CMPXDbHandler::CMPXDbHandler"); + } + +// ---------------------------------------------------------------------------- +// Symbian 2nd phase constructor can leave. +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::ConstructL() + { + MPX_FUNC("CMPXDbHandler::ConstructL"); + + iMimeTypes = iResource.ReadDesCArrayL(R_MC_MIME_TYPES); + iExtensions = iResource.ReadDesCArrayL(R_MC_MUSIC_FILE_EXTENSIONS); + iExtensionsMime = iResource.ReadDesCArrayL(R_MC_FILE_EXTENSIONS_MIME); + iExtensionsDrm = iResource.ReadDesCArrayL(R_MC_FILE_EXTENSIONS_DRM); + + // make sure all databases are created and valid + iDbManager = CMPXCollectionDbManager::NewL(iFs); + + CDesCArrayFlat* musicFolders = +#ifdef RD_MULTIPLE_DRIVE + GetMusicFoldersL(); +#else + iResource.ReadDesCArrayL(R_MC_DEFAULT_MUSIC_FOLDERS); +#endif + + // create the music folders and initialize iDbDrives + CleanupStack::PushL(musicFolders); + ProcessMusicFoldersL(*musicFolders); + CleanupStack::PopAndDestroy(musicFolders); + + // Create the db infrastructure, + // + iDbMusic = CMPXDbMusic::NewL(*iDbManager, iResource, *this); + iDbPlaylist = CMPXDbPlaylist::NewL(*iDbManager, *this); + iDbArtist = CMPXDbArtist::NewL(*iDbManager, EMPXArtist, *this); + iDbAlbum = CMPXDbAlbum::NewL(*iDbManager, EMPXAlbum, *this); + iDbGenre = CMPXDbGenre::NewL(*iDbManager, EMPXGenre); + iDbComposer = CMPXDbComposer::NewL(*iDbManager, EMPXComposer); +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + iDbAbstractAlbum = CMPXDbAbstractAlbum::NewL(*iDbManager, EMPXAbstractAlbum, iFs); +#endif // ABSTRACTAUDIOALBUM_INCLUDED + iAutoPlaylist = CMPXDbAutoPlaylist::NewL(*iDbManager, iFs, iResource); + iDbAuxiliary = CMPXDbAuxiliary::NewL(*iDbManager); + + MPX_TRAPD(err, iDbManager->InitDatabasesL(iDbDrives)); + + // If KErrCorrupt is returned, a database file was found to be corrupted + // and was replaced with a new one. The db plugin can ignore this error and continue + // because a new db file was successfully created in a subsequent retry. + if ((err != KErrNone) && (err != KErrCorrupt) && (err != KErrDiskFull)) + { + // leave to signal the caller that there was an error why creating and opening + // one or more of the databases + User::Leave(err); + } + else if (err == KErrDiskFull) + { + iOutOfDisk = ETrue; + } + else + { + // do nothing + } + + // Verify the volume ids of each drive matches the database + MPX_TRAP(err,VerifyVolumeIdL()); + if ((err != KErrNone) && (err != KErrDiskFull)) + { + // leave to signal the caller that there was an error why creating and opening + // one or more of the databases + User::Leave(err); + } + else if (err == KErrDiskFull) + { + iOutOfDisk = ETrue; + } + +//#ifdef _DEBUG +// iDbManager->PrintDatabaseL(); // PREQ2536 the files sqlrowsetutil.h and sqlrowsetutil.cpp has been removed +//#endif + + MPX_DEBUG2("CMPXDbHandler::ConstructL DbCount[%d]", iDbManager->DatabaseCount()); + } + +// ---------------------------------------------------------------------------- +// Add song to collection +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::AddSongL( + const CMPXMedia& aMedia, + CMPXMessageArray* aMessageArray) + { + MPX_FUNC("CMPXDbHandler::AddSongL"); + + BeginTransactionL(); + TUint32 songId(0); + MPX_TRAPD(err, songId = DoAddSongL(aMedia,aMessageArray)); + + if (iOutOfDisk && (err == KErrNotFound)) + { + err = KErrDiskFull; + } + EndTransactionL(err); + + return songId; + } + +// ---------------------------------------------------------------------------- +// Add song to collection with no database transaction +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::AddSongWithNoTransactionL( + const CMPXMedia& aMedia, + CMPXMessageArray* aMessageArray) + { + MPX_FUNC("CMPXDbHandler::AddSongWithNoTransactionL"); + + TUint32 songId(0); + MPX_TRAPD(err, songId = DoAddSongL(aMedia,aMessageArray)); + + if (iOutOfDisk && (err == KErrNotFound)) + { + err = KErrDiskFull; + } + User::LeaveIfError(err); + + return songId; + } + +// ---------------------------------------------------------------------------- +// Add playlist to collection +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::AddPlaylistL( + const CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbHandler::AddPlaylistL"); + + BeginTransactionL(); + TUint32 playlistId(0); + MPX_TRAPD(err, playlistId = DoAddPlaylistL(aMedia)); + EndTransactionL(err); + + return playlistId; + } + +// ---------------------------------------------------------------------------- +// Add song to playlist +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::AddSongToPlaylistL( + const CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbHandler::AddSongToPlaylistL"); + + BeginTransactionL(); + TUint32 playlistId(0); + MPX_TRAPD(err, playlistId = DoAddSongToPlaylistL(aMedia)); + EndTransactionL(err); + + return playlistId; + } + +#ifdef ABSTRACTAUDIOALBUM_INCLUDED +// ---------------------------------------------------------------------------- +// Add AbstractAlbum to collection +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::AddAbstractAlbumL( + const CMPXMedia& aMedia, + CMPXMessageArray* aMessageArray) + { + MPX_FUNC("CMPXDbHandler::AddAbstractAlbumL"); + + BeginTransactionL(); + TBool newRecord(EFalse); + TInt err(KErrNone); + + TDriveUnit drive(aMedia.ValueText(KMPXMediaGeneralUri)); + TPtrC uri(aMedia.ValueText(KMPXMediaGeneralUri).Left(KMCMaxTextLen)); + TPtrC name(aMedia.ValueText(KMPXMediaGeneralTitle).Left(KMCMaxTextLen)); + TPtrC albumartist(aMedia.ValueText(KMPXMediaMusicAlbumArtist).Left(KMCMaxTextLen)); + + //only insert to AbstractAlbum table when it is new item + TUint32 abstractAlbumId(MPXDbCommonUtil::GenerateUniqueIdL(iFs, EMPXAbstractAlbum, uri, EFalse)); + + newRecord = !iDbAbstractAlbum->CategoryItemExistsL(drive, abstractAlbumId); + + if (newRecord) + { + MPX_TRAP(err, abstractAlbumId = iDbAbstractAlbum->AddItemL(uri, name, albumartist, drive, newRecord, EFalse)); + if (iOutOfDisk && (err == KErrNotFound)) + { + err = KErrDiskFull; + } + if (aMessageArray) + { + MPXDbCommonUtil::AddItemChangedMessageL(*aMessageArray, abstractAlbumId, EMPXItemInserted, + EMPXAbstractAlbum, KDBPluginUid); + } + } + EndTransactionL(err); + + return abstractAlbumId; + } + +// ---------------------------------------------------------------------------- +// Update abstractalbum info to AbstractAlbum table and all songs which associate +// with AbstractAlbum in the collection +// ---------------------------------------------------------------------------- +// +CMPXDbActiveTask::TChangeVisibility CMPXDbHandler::UpdateAbstractAlbumL( + const CMPXMedia& aMedia, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::UpdateAbstractAlbumL"); + + CMPXDbActiveTask::TChangeVisibility visibleChange(CMPXDbActiveTask::ENotVisibile); + TUint32 itemId(0); + if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + const TDesC& uri(aMedia.ValueText (KMPXMediaGeneralUri)); + TDriveUnit drive(aMedia.ValueText(KMPXMediaGeneralUri)); + + //get Id based on new uri + itemId = MPXDbCommonUtil::GenerateUniqueIdL(iFs, EMPXAbstractAlbum, uri, EFalse); + if (!itemId) + { + User::Leave(KErrNotSupported); + } + + //if updating to new item, need do renaming for AbstractAlbum: delete old one and insert a new entry to AbstractAlbum table + //if a new item, need update songs associated and renaming albstractalbum table + if (aMedia.IsSupported(KMPXMediaGeneralId)) + { + MPX_DEBUG1("CMPXDbHandler::UpdateAbstractAlbumL, rename case"); + + BeginTransactionL(); + //get old id, for renaming + TInt err(KErrNone); + TUint32 oldId = (aMedia.ValueTObjectL(KMPXMediaGeneralId)).iId2; + if (oldId && (oldId != itemId) ) //pass the old UID for renaming, do not care if new itemId exist or not + { + //get old Uri based on old Id + HBufC* oldUri = iDbAbstractAlbum->GetUriL(oldId); + CleanupStack::PushL(oldUri); + + //add and update new item to AbstractAlbum table + //old existing item field values need to be saved and added when adding new item + MPX_TRAP(err, itemId = iDbAbstractAlbum->AddUpdatedItemL(oldId, uri )); + + if (iOutOfDisk && (err == KErrNotFound)) + { + err = KErrDiskFull; + } + + MPXDbCommonUtil::AddItemChangedMessageL(aItemChangedMessages, itemId, EMPXItemInserted, + EMPXAbstractAlbum, KDBPluginUid); + + //find and update all songs associated with oldId + RArray songAttributes; + CleanupClosePushL(songAttributes); + songAttributes.AppendL(KMPXMediaGeneralId); + + CMPXMediaArray* mediaArray = CMPXMediaArray::NewL(); + CleanupStack::PushL(mediaArray); + + //get all songs associated + MPX_TRAP(err, iDbMusic->GetAllSongsForAbstractAlbumL(oldId, songAttributes.Array(), *mediaArray)); + if (err == KErrNotFound) + { + // Leave with KErrNotFound + MPX_DEBUG1("CMPXDbHandler::UpdateAbstractAlbumL, leave with not found"); + User::Leave(KErrNotFound); + } + + TInt count(mediaArray->Count()); + MPX_DEBUG2("CMPXDbHandler::UpdateAbstractAlbumL, [%d] songs associated", count); + //go through all songs for updating + for (TInt i = 0; i < count; i++) + { + CMPXMedia* song = mediaArray->AtL(i); + song->SetTextValueL(KMPXMediaMusicAlbumArtFileName, uri ); + visibleChange = UpdateSongL(*song, aItemChangedMessages); + } + CleanupStack::PopAndDestroy(mediaArray); + CleanupStack::PopAndDestroy(&songAttributes); + + //rename TN + iDbAbstractAlbum->HandleTNL(*oldUri, uri, 0); + CleanupStack::PopAndDestroy(oldUri); + } + EndTransactionL(err); + }//renaming + + //check if abstractAlbum exist in ABSTRACTALBUM table before update it + else if (iDbAbstractAlbum->CategoryItemExistsL(drive, itemId)) + { + //support updating Name, AlbumArtist fields for AbstractAlbum table + iDbAbstractAlbum->UpdateItemL(itemId, aMedia, drive, &aItemChangedMessages); + } + } + return visibleChange; + } + +// ---------------------------------------------------------------------------- +// Update all songs which associate with AbstractAlbum to new AbstractAlbum info +// in the collection +// ---------------------------------------------------------------------------- +// +CMPXDbActiveTask::TChangeVisibility CMPXDbHandler::UpdateSongsAbstractAlbumInfoL( + const CMPXMedia& aMedia, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::UpdateSongsAbstractAlbumInfoL"); + const TDesC& uri(aMedia.ValueText (KMPXMediaGeneralUri)); + //need to update songs information to music table + CMPXMediaArray* mediaArray = aMedia.Value(KMPXMediaArrayContents); + User::LeaveIfNull(mediaArray); + TInt count(mediaArray->Count()); + CMPXDbActiveTask::TChangeVisibility visibleChange(CMPXDbActiveTask::ENotVisibile); + for (TInt i = 0; i < count; i++) + { + CMPXMedia* mediaSong = mediaArray->AtL(i); + mediaSong->SetTextValueL(KMPXMediaMusicAlbumArtFileName, uri ); + visibleChange = UpdateSongL(*mediaSong, aItemChangedMessages); + } + return visibleChange; + } +#endif // ABSTRACTAUDIOALBUM_INCLUDED + +// ---------------------------------------------------------------------------- +// Update a song in the collection +// ---------------------------------------------------------------------------- +// +CMPXDbActiveTask::TChangeVisibility CMPXDbHandler::UpdateSongL( + const CMPXMedia& aMedia, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::UpdateSongL"); + + BeginTransactionL(); + CMPXDbActiveTask::TChangeVisibility visibleChange(CMPXDbActiveTask::ENotVisibile); + MPX_TRAPD(err, visibleChange = DoUpdateSongL(aMedia, aItemChangedMessages)); + EndTransactionL(err); + return visibleChange; + } + +// ---------------------------------------------------------------------------- +// Update a playlist in the collection +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::UpdatePlaylistL( + const CMPXMedia& aMedia, + CMPXMessageArray& aMessageArray) + { + MPX_FUNC("CMPXDbHandler::UpdatePlaylistL"); + + BeginTransactionL(); + MPX_TRAPD(err, DoUpdatePlaylistL(aMedia, aMessageArray)); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------- +// Updates the playlist songs +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::UpdatePlaylistSongsL( + const CMPXMedia& aMedia, + CMPXMessage& aMessage) + { + MPX_FUNC("CMPXDbHandler::UpdatePlaylistSongsL"); + + BeginTransactionL(); + MPX_TRAPD(err, DoUpdatePlaylistSongsL(aMedia, aMessage)); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------- +// Reorder a song in a playlist +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::ReorderPlaylistL( + const TMPXItemId& aPlaylistId, + const TMPXItemId& aSongId, + TUint aOriginalOrdinal, + TUint aNewOrdinal, + CMPXMessage& aMessage) + { + MPX_DEBUG5("-->CMPXDbHandler::ReorderPlaylistL(0x%x, 0x%x, %d, %d)", + aPlaylistId.iId2, aSongId.iId2, aOriginalOrdinal, aNewOrdinal); + + BeginTransactionL(); + MPX_TRAPD(err, DoReorderPlaylistL(aPlaylistId, aSongId, aOriginalOrdinal, aNewOrdinal, aMessage)); + EndTransactionL(err); + MPX_DEBUG2("<--CMPXDbHandler::ReorderPlaylistL() error=%d", err); + } + +// ---------------------------------------------------------------------------- +// Remove the entire music collection database +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::RemoveEntireCollectionL() + { + MPX_FUNC("CMPXDbHandler::RemoveEntireCollectionL"); + BeginTransactionL(); + MPX_TRAPD(err, iDbManager->RecreateAllDatabasesL()); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------- +// Delete a song from collection +// The function notifies collection model to perform deletion +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::RemoveSongL( + TUint32 aSongId, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages, + TBool aDeleteRecord) + { + MPX_FUNC("CMPXDbHandler::RemoveSongL"); + + MPX_TRAPD(err, DoRemoveSongL(aSongId, aUriArray, aItemChangedMessages, aDeleteRecord)); + + MPX_TRAP(err, DoRemoveSongFromPlaylistL(aSongId,aItemChangedMessages)); + + } + +// ---------------------------------------------------------------------------- +// Removes a category of songs from the music collection, +// and its corresponding category in the lookup table +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::RemoveSongsMatchingCategoryL( + TMPXGeneralCategory aCategory, + TUint32 aCategoryId, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::RemoveSongsMatchingCategoryL"); + + BeginTransactionL(); + MPX_TRAPD(err, DoRemoveSongsMatchingCategoryL(aCategory, aCategoryId, aUriArray, aItemChangedMessages)); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------------------------------------- +// Delete songs for the specified artist and album from collection +// The function notifies collection model to perform deletion +// ---------------------------------------------------------------------------------------------------------- +// +void CMPXDbHandler::RemoveSongsMatchingArtistAndAlbumL( + TUint32 aArtistId, + TUint32 aAlbumId, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::RemoveSongsMatchingArtistAndAlbumL"); + + BeginTransactionL(); + MPX_TRAPD(err, DoRemoveSongsMatchingArtistAndAlbumL(aArtistId, aAlbumId, aUriArray, + aItemChangedMessages)); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------- +// Remove all playlists from collection +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::RemoveAllPlaylistsL() + { + MPX_FUNC("CMPXDbHandler::RemoveAllPlaylistsL"); + + BeginTransactionL(); + MPX_TRAPD(err, DoRemoveAllPlaylistsL()); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------- +// Remove specified playlist +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::RemovePlaylistL( + TUint32 aPlaylistId, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::RemovePlaylistL"); + + BeginTransactionL(); + MPX_TRAPD(err, DoRemovePlaylistL(aPlaylistId, aUriArray, aItemChangedMessages)); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------- +// Remove song from playlist songs table +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::RemoveSongFromPlaylistL( + TUint32 aPlaylistId, + const TMPXItemId& aSongId, + TInt aOrdinal, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::RemoveSongFromPlaylistL"); + MPX_DEBUG5("CMPXDbHandler::RemoveSongFromPlaylistL(playlist 0x%x, songId [0x%x,0x%x], ordinal %d)", + aPlaylistId, aSongId.iId1, aSongId.iId2, aOrdinal); + + MPX_TRAPD(err, DoRemoveSongFromPlaylistL(aPlaylistId, aSongId, aOrdinal, aItemChangedMessages)); + if ( err && InTransaction() ) + { + // only end transaction if there's an error + EndTransactionL( err ); + } + } + +#ifdef ABSTRACTAUDIOALBUM_INCLUDED +// ---------------------------------------------------------------------------- +// Remove specified abstractalbum +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::RemoveAbstractAlbumL( + TUint32 aAbstractAlbumId, + CMPXMessageArray& aItemChangedMessages, TBool aFileDeleted) + { + MPX_FUNC("CMPXDbHandler::RemoveAbstractAlbumL"); + iDbAbstractAlbum->RemoveAbstractAlbumL(aAbstractAlbumId, aItemChangedMessages, aFileDeleted); + } +#endif // ABSTRACTAUDIOALBUM_INCLUDED + +// ---------------------------------------------------------------------------- +// Cleanup records marked as deleted. This is designated for MTP to clean up records marked as deleted +// at the end of its session. +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::CleanupDeletedRecordsL() + { + MPX_FUNC("CMPXDbHandler::CleanupDeletedRecordsL"); + + BeginTransactionL(); + MPX_TRAPD(err, DoCleanupDeletedRecordsL()); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------- +// Read all songs and cache them into an array ordered by song name +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetAllSongsL( + CMPXMediaArray* aMediaArray, + const TArray& aAttrs) + { + MPX_FUNC("CMPXDbHandler::GetAllSongsL"); + iDbMusic->GetAllSongsL(aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Read a limited # of songs and cache them into an array ordered by song name +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetAllSongsLimitedL(const TArray& aAttrs, + CMPXMediaArray& aMediaArray, TInt aLimit) + { + MPX_FUNC("CMPXDbHandler::GetAllSongsLimitedL"); + iDbMusic->GetAllSongsLimitedL( aAttrs, aMediaArray, aLimit ); + } + +// ---------------------------------------------------------------------------- +// Read all songs and cache them into an array ordered by song name +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongsInBlockL( + CMPXMediaArray* aMediaArray, + const TArray& aAttrs, + TPtrC aTitle, + TUint aNumOfSongs, + TBool aAsc) + { + MPX_FUNC("CMPXDbHandler::GetSongsInBlockL"); + iDbMusic->GetSongsInBlockL(aAttrs, *aMediaArray, aTitle, aNumOfSongs, aAsc); + } + +// ---------------------------------------------------------------------------- +// Read songs at a particular offset +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongsAtOffsetL( CMPXMediaArray* aMediaArray, + const TArray& aAttrs, + TInt aOffset, + TInt aCount ) + { + MPX_DEBUG1("CMPXDbHandler::GetSongsAtOffsetL <--"); + iDbMusic->GetSongsAtOffsetL( *aMediaArray, aAttrs, aOffset, aCount ); + } + +// ---------------------------------------------------------------------------- +// Get all songs matching the given artist ID +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongsMatchingArtistL( + TUint aArtistId, + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetSongsMatchingArtistL"); + iDbMusic->GetSongsForArtistL(aArtistId, aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get all songs matching the given album ID +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongsMatchingAlbumL( + TUint aAlbumId, + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetSongsMatchingAlbumL"); + iDbMusic->GetSongsForAlbumL(aAlbumId, aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------------------------------------- +// Get all songs matching the given artist and album ID +// ---------------------------------------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongsMatchingArtistAndAlbumL( + TUint aArtistId, + TUint aAlbumId, + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetSongsMatchingArtistAndAlbumL"); + iDbMusic->GetSongsForArtistAndAlbumL(aArtistId, aAlbumId, aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get all songs matching the given genre ID +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongsMatchingGenreL( + TUint aGenreId, + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetSongsMatchingGenreL"); + iDbMusic->GetSongsForGenreL(aGenreId, aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get all songs matching the given composer ID +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongsMatchingComposerL( + TUint aComposerId, + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetSongsMatchingComposerL"); + iDbMusic->GetSongsForComposerL(aComposerId, aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get all songs that belong to the given playlist +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongsMatchingPlaylistL( + TUint aPlaylistId, + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetSongsMatchingPlaylistL"); + GetPlaylistSongsL(aPlaylistId, aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get song matching the given song ID +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongL( + TUint32 aSongId, + const TArray& aAttrs, + CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbHandler::GetSongL"); + iDbMusic->GetSongL(aSongId, aAttrs, aMedia); + } + +// ---------------------------------------------------------------------------- +// GetSongL +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetSongL( + TUint32 aSongId, + const TArray& aAttrs, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetSongL"); + + CMPXMedia* media = CMPXMedia::NewL(); + CleanupStack::PushL(media); + + GetSongL(aSongId, aAttrs, *media); + aMediaArray.AppendL(*media); + + CleanupStack::PopAndDestroy(media); + } + +// ---------------------------------------------------------------------------- +// Get song matching the given song ID and playlist ID +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetPlaylistSongL( + TUint32 aSongId, + TUint32 aPlaylistId, + const TArray& aAttrs, + CMPXMedia& aMedia) + { + MPX_DEBUG3("-->CMPXDbHandler::GetPlaylistSongL songId[0x%x] playlistId[0x%x]", aSongId, aPlaylistId); + + // complete the song information from the Music table + MPX_TRAPD(err, iDbMusic->GetSongL(aSongId, aAttrs, aMedia)); + + // + // song not found in Music table + // + if (err == KErrNotFound) + { + // + // Leave with KErrNotFound if one of the following is true: + // 1) the requested song is in an auto playlist. Since auto-playlist isn't + // stored in playlist tables, we won't be able to retrieve info elsewhere + // 2) the requested song is in a user playlist but we cannot find the song + // info from playlist tables either + // + if (EMPXNoAutoPlaylist != iAutoPlaylist->AutoPlaylistTypeL(aPlaylistId) || + !iDbPlaylist->Songs().GetSongL(aPlaylistId, aSongId, aAttrs, aMedia)) + { + User::Leave(KErrNotFound); + } + } + + // + // Unable to read information from Music table + // + else + { + // ignore the error if KErrNotFound + User::LeaveIfError(err); + } + MPX_DEBUG1("<--CMPXDbHandler::GetPlaylistSongL"); + } + +// ---------------------------------------------------------------------------- +// GetPlaylistSongL +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetPlaylistSongL( + TUint32 aSongId, + TUint32 aPlaylistId, + const TArray& aAttrs, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetPlaylistSongL"); + + CMPXMedia* media = CMPXMedia::NewL(); + CleanupStack::PushL(media); + + GetPlaylistSongL(aSongId, aPlaylistId, aAttrs, *media); + aMediaArray.AppendL(*media); + + CleanupStack::PopAndDestroy(media); + } + +// ---------------------------------------------------------------------------- +// Get song matching the given URI +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::GetSongIdMatchingUriL( + const TDesC& aUri) + { + MPX_FUNC("CMPXDbHandler::GetSongIdMatchingUriL"); + return MPXDbCommonUtil::GenerateUniqueIdL(iFs, EMPXCollection, aUri, EFalse); + } + +#ifdef ABSTRACTAUDIOALBUM_INCLUDED +// ---------------------------------------------------------------------------- +// Get abstractalbum Id matching the given URI +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::GetAbstractAlbumIdMatchingUriL( + const TDesC& aUri) + { + MPX_FUNC("CMPXDbHandler::GetAbstractAlbumIdMatchingUriL"); + return MPXDbCommonUtil::GenerateUniqueIdL(iFs, EMPXAbstractAlbum, aUri, EFalse); + } +#endif // ABSTRACTAUDIOALBUM_INCLUDED + +// ---------------------------------------------------------------------------- +// Get all artists +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetAllArtistsL( + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetAllArtistsL"); + iDbArtist->GetAllCategoryItemsL(aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get all albums +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetAllAlbumsL( + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetAllAlbumsL"); + iDbAlbum->GetAllCategoryItemsL(aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get all albums for the given artist ID +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetAlbumsMatchingArtistL( + TUint aArtistId, + const TArray& aAttrs, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetAlbumsMatchingArtistL"); + RArray attributes; + CleanupClosePushL( attributes ); + + TBool tryGetSongCount = EFalse; + TInt attrCount(aAttrs.Count()); + TInt i = 0; + for (i = 0; i < attrCount; i++) + { + TInt contentId(aAttrs[i].ContentId()); + TUint attributeId(aAttrs[i].AttributeId()); + + if (contentId == KMPXMediaIdGeneral && attributeId & EMPXMediaGeneralCount) + { + MPX_DEBUG1(" EMPXMediaGeneralCount"); + + attributes.Append(TMPXAttribute(KMPXMediaIdGeneral, attributeId & ~EMPXMediaGeneralCount)); + + tryGetSongCount = ETrue; + break; + } + + attributes.Append(aAttrs[i]); + } + + for (TInt j = i+1; j < attrCount; j++) + { + attributes.Append(aAttrs[j]); + } + iDbAlbum->GetSubCategoryItemsL(EMPXArtist, aArtistId, attributes.Array(), aMediaArray); + CleanupStack::PopAndDestroy(&attributes); + + TInt pPath(0); + if (aMediaArray.Count()) + { + CMPXMedia* pMedia = aMediaArray[0]; + if (pMedia->IsSupported(KMPXMediaGeneralValue)) + { + pPath = pMedia->ValueTObjectL(KMPXMediaGeneralValue); + MPX_ASSERT(pPath); + } + } + + TInt albumCount(aMediaArray.Count()); + if (albumCount) + { + if ( tryGetSongCount ) + { + TInt startIndex = pPath ? 1 : 0; + + for (TInt i = startIndex; i < albumCount; i++) + { + CMPXMedia* media = aMediaArray[i]; + TUint32 albumId((media->ValueTObjectL(KMPXMediaGeneralId))); + + TInt songCount = iDbAlbum->GetSongsCountInAlbumMatchingArtistL(aArtistId, albumId); + + media->SetTObjectValueL(KMPXMediaGeneralCount, songCount ); + MPX_DEBUG2(" SongCount[%d]", songCount ); + } + } + } + } + +// ---------------------------------------------------------------------------- +// Get all genres +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetAllGenresL( + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetAllGenresL"); + iDbGenre->GetAllCategoryItemsL(aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get all composers +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetAllComposersL( + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetAllComposersL"); + iDbComposer->GetAllCategoryItemsL(aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get the playlist ID of the playlist that matches the given URI +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::GetPlaylistIdMatchingUriL( + const TDesC& aUri) + { + MPX_FUNC("CMPXDbHandler::GetPlaylistIdMatchingUriL"); + return iDbPlaylist->GetIdL(aUri); + } + +// ---------------------------------------------------------------------------- +// CMPXDbHandler::IsAutoPlaylistL +// ---------------------------------------------------------------------------- +// +TBool CMPXDbHandler::IsAutoPlaylistL( + TUint32 aPlaylistId) + { + MPX_FUNC("CMPXDbHandler::IsAutoPlaylistL"); + return (iAutoPlaylist->AutoPlaylistTypeL(aPlaylistId) != EMPXNoAutoPlaylist); + } + +// ---------------------------------------------------------------------------- +// Get all user playlist names +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetAllPlaylistsL( + CMPXMediaArray* aMediaArray, + const TArray& aAttrs) + { + MPX_FUNC("CMPXDbHandler::GetAllPlaylistsL"); + iDbPlaylist->GetAllPlaylistsL(aAttrs, *aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get all system playlist names +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetAllSystemPlaylistNamesL( + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetAllSystemPlaylistNamesL()"); + iAutoPlaylist->GetAllPlaylistsL(*aMediaArray); + } + +// ---------------------------------------------------------------------------- +// Get the name of the row matching the given ID +// ---------------------------------------------------------------------------- +// +HBufC* CMPXDbHandler::GetNameMatchingIdL( + const TUint32 aId) const + { + MPX_FUNC("CMPXDbHandler::GetNameMatchingIdL()"); + + HBufC* name(NULL); + TMPXGeneralCategory category(MPX_ITEM_CATEGORY(aId)); + switch (category) + { + case EMPXCollection: + { + // song name + name = iDbMusic->GetNameL(aId); + break; + } + case EMPXPlaylist: + { + // playlist name + if (iAutoPlaylist->AutoPlaylistTypeL(aId) != EMPXNoAutoPlaylist) + { + name = iAutoPlaylist->AutoPlaylistNameL(aId).AllocL(); + } + else + { + name = iDbPlaylist->GetNameL(aId); + } + break; + } + default: + { + // category name + name = DbCategoryL(category)->GetNameL(aId); + break; + } + } + + return name; + } + +// ---------------------------------------------------------------------------- +// Get the URI of the row matching the given ID +// ---------------------------------------------------------------------------- +// +HBufC* CMPXDbHandler::GetUriMatchingIdL( + const TUint32 aId) const + { + MPX_FUNC("CMPXDbHandler::GetUriMatchingIdL"); + + HBufC* uri(NULL); + switch (MPX_ITEM_CATEGORY(aId)) + { + case EMPXCollection: + { + // song URI + uri = iDbMusic->GetUriL(aId); + break; + } + case EMPXPlaylist: + { + // playlist URI + uri = iDbPlaylist->GetUriL(aId); + break; + } + default: + User::Leave(KErrNotSupported); + } + + return uri; + } + +// ---------------------------------------------------------------------------- +// Get category +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetCategoryL( + const TUint32 aCategoryId, + TMPXGeneralCategory aCategory, + const TArray& aAttrs, + CMPXMedia* aMedia) + { + MPX_FUNC("CMPXDbHandler::GetCategoryL"); + + switch (aCategory) + { + case EMPXPlaylist: + { + if (iAutoPlaylist->AutoPlaylistTypeL(aCategoryId) != EMPXNoAutoPlaylist) + { + iAutoPlaylist->GetPlaylistL(aCategoryId, aAttrs, *aMedia); + } + else + { + iDbPlaylist->GetPlaylistL(aCategoryId, aAttrs, *aMedia); + } + break; + } + default: + { + DbCategoryL(aCategory)->GetCategoryItemL(aCategoryId, aAttrs, *aMedia); + break; + } + } + } + +// ---------------------------------------------------------------------------- +// Get the duration for all songs +// ---------------------------------------------------------------------------- +// +TInt CMPXDbHandler::GetAllSongsDurationL() + { + MPX_FUNC("CMPXDbHandler::GetAllSongsDurationL"); + return iDbMusic->AllSongsDurationL(); + } + +// ---------------------------------------------------------------------------- +// Get the duration for an artist +// ---------------------------------------------------------------------------- +// +TInt CMPXDbHandler::GetArtistDurationL( + TInt aArtistId) + { + MPX_FUNC("CMPXDbHandler::GetArtistDurationL"); + return iDbMusic->ArtistDurationL(aArtistId); + } + +// ---------------------------------------------------------------------------- +// Get the duration for an album +// ---------------------------------------------------------------------------- +// +TInt CMPXDbHandler::GetAlbumDurationL( + TInt aAlbumId) + { + MPX_FUNC("CMPXDbHandler::GetAlbumDurationL"); + return iDbMusic->AlbumDurationL(aAlbumId); + } + +// ---------------------------------------------------------------------------- +// Get the duration for an artist/album combination +// ---------------------------------------------------------------------------- +// +TInt CMPXDbHandler::GetArtistAlbumDurationL( + TInt aArtistId, + TInt aAlbumId) + { + MPX_FUNC("CMPXDbHandler::GetArtistAlbumDurationL"); + return iDbMusic->ArtistAlbumDurationL(aArtistId, aAlbumId); + } + +// ---------------------------------------------------------------------------- +// Get the duration for a composer +// ---------------------------------------------------------------------------- +// +TInt CMPXDbHandler::GetComposerDurationL( + TInt aComposerId) + { + MPX_FUNC("CMPXDbHandler::GetComposerDurationL"); + return iDbMusic->ComposerDurationL(aComposerId); + } + +// ---------------------------------------------------------------------------- +// Get the duration for a genre +// ---------------------------------------------------------------------------- +// +TInt CMPXDbHandler::GetGenreDurationL( + TInt aGenreId) + { + MPX_FUNC("CMPXDbHandler::GetGenreDurationL"); + return iDbMusic->GenreDurationL(aGenreId); + } + +// ---------------------------------------------------------------------------- +// Get the duration for a user playlist +// ---------------------------------------------------------------------------- +// +TInt CMPXDbHandler::GetUserPlaylistDurationL( + TInt aPlaylistId) + { + MPX_FUNC("CMPXDbHandler::GetUserPlaylistDurationL"); + + RArray attributes; + CleanupClosePushL(attributes); + attributes.AppendL(KMPXMediaGeneralId); + attributes.AppendL(TMPXAttribute(KMPXMediaIdGeneral, EMPXMediaGeneralDuration)); + + CMPXMediaArray* mediaArray = CMPXMediaArray::NewL(); + CleanupStack::PushL(mediaArray); + + GetPlaylistSongsL(aPlaylistId, attributes.Array(), *mediaArray); + + TInt duration(0); + TInt count(mediaArray->Count()); + for (TInt index = 0; index < count; ++index) + { + CMPXMedia* media((*mediaArray)[index]); + if (media->IsSupported(KMPXMediaGeneralDuration)) + { + duration += media->ValueTObjectL(KMPXMediaGeneralDuration); + } + } + + CleanupStack::PopAndDestroy(mediaArray); + CleanupStack::PopAndDestroy(&attributes); + + return duration; + } + +// ---------------------------------------------------------------------------- +// Get the duration for a playlist +// ---------------------------------------------------------------------------- +// +TInt CMPXDbHandler::GetPlaylistDurationL( + TInt aPlaylistId) + { + MPX_FUNC("CMPXDbHandler::GetPlaylistDurationL"); + + TInt duration(0); + + if (aPlaylistId == iAutoPlaylist->AutoPlaylistIdL(EMPXRecentlyPlayedPlaylist)) + { + duration = iDbMusic->RecentlyPlayedDurationL(); + } + else if (aPlaylistId == iAutoPlaylist->AutoPlaylistIdL(EMPXMostPlayedPlaylist)) + { + duration = iDbMusic->MostPlayedDurationL(); + } + else if (aPlaylistId == iAutoPlaylist->AutoPlaylistIdL(EMPXRecentlyAddedPlaylist)) + { + duration = iDbMusic->RecentlyAddedDurationL(); + } + else + { + duration = GetUserPlaylistDurationL(aPlaylistId); + } + + return duration; + } + +// ---------------------------------------------------------------------------- +// Find the number of items of a specified type +// ---------------------------------------------------------------------------- +// +TInt CMPXDbHandler::NumberOfItemsL( + TMPXGeneralCategory aCategory) + { + MPX_FUNC("CMPXDbHandler::NumberOfItemsL"); + + TInt count(0); + switch(aCategory) + { + case EMPXSong: + { + count = iDbMusic->CountL(); + break; + } + case EMPXPlaylist: + { + // return the total number of playlists, including the system ones + count = iDbPlaylist->CountL() + EMPXAutoPlaylistCount; + break; + } + default: + { + count = DbCategoryL(aCategory)->CountL(); + break; + } + } + + return count; + } + +// ---------------------------------------------------------------------------- +// CMPXDbHandler::FindAllLC +// ---------------------------------------------------------------------------- +// +CMPXMedia* CMPXDbHandler::FindAllLC( + const CMPXMedia& aCriteria, + const TArray& aAttrs) + { + MPX_FUNC("CMPXDbHandler::FindAllLC"); + + // leave if the given media doesn't contain the following attributes + if (!aCriteria.IsSupported(KMPXMediaGeneralType) || + !aCriteria.IsSupported(KMPXMediaGeneralCategory)) + { + User::Leave(KErrArgument); + } + + RArray supportedIds; + CleanupClosePushL(supportedIds); + supportedIds.AppendL(KMPXMediaIdContainer); + MPXDbCommonUtil::FillInSupportedUIDsL(aAttrs, supportedIds); + + CMPXMedia* entries = CMPXMedia::NewL(supportedIds.Array()); + CleanupStack::PopAndDestroy(&supportedIds); + CleanupStack::PushL(entries); + + CMPXMediaArray* array = CMPXMediaArray::NewL(); + CleanupStack::PushL(array); + + FindAllL(aCriteria, aAttrs, array); + + entries->SetTObjectValueL(KMPXMediaGeneralType, EMPXGroup); + entries->SetTObjectValueL(KMPXMediaGeneralCategory, + aCriteria.ValueTObjectL(KMPXMediaGeneralCategory)); + entries->SetCObjectValueL(KMPXMediaArrayContents, array); + entries->SetTObjectValueL(KMPXMediaArrayCount, array->Count()); + + CleanupStack::PopAndDestroy(array); + return entries; + } + +// ---------------------------------------------------------------------------- +// Set the last refreshed time into the collection +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::SetLastRefreshedTimeL( + TTime aTime) + { + MPX_FUNC("CMPXDbHandler::SetLastRefreshedTimeL"); + + BeginTransactionL(); + MPX_TRAPD(err, iDbAuxiliary->SetLastRefreshedTimeL(aTime)); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------- +// Get the last refreshed time from the collection +// ---------------------------------------------------------------------------- +// +TTime CMPXDbHandler::GetLastRefreshedTimeL() + { + MPX_FUNC("CMPXDbHandler::GetLastRefreshedTimeL"); + return iDbAuxiliary->LastRefreshedTimeL(); + } + +// ---------------------------------------------------------------------------- +// Set the db corrupted state for all drives +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::SetDBCorruptedL( + TBool aCorrupted) + { + MPX_FUNC("CMPXDbHandler::SetDBCorruptedL"); + + BeginTransactionL(); + MPX_TRAPD(err, iDbAuxiliary->SetDBCorruptedL(aCorrupted)); + EndTransactionL(err); + } + +// ---------------------------------------------------------------------------- +// Gets the db corrupted state for all drives +// ---------------------------------------------------------------------------- +// +TBool CMPXDbHandler::IsDBCorruptedL() + { + MPX_FUNC("CMPXDbHandler::IsDBCorruptedL"); + return iDbAuxiliary->DBCorruptedL(); + } + +// ---------------------------------------------------------------------------- +// Have the databases been created? +// ---------------------------------------------------------------------------- +// +TBool CMPXDbHandler::DatabaseCreated() + { + MPX_FUNC("CMPXDbHandler::DatabaseCreatedL"); + + TBool AuxilaryDbIsRefreshed(EFalse); + TRAP_IGNORE(AuxilaryDbIsRefreshed = iDbAuxiliary->IsRefreshedL()); + // If none of the databases were available, ie out of disk we return EFalse + return iDbManager->IsInitialized() && AuxilaryDbIsRefreshed; + } + +// ---------------------------------------------------------------------------- +// Open a database +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::OpenDatabaseL( + TInt aDrive) + { + MPX_FUNC("CMPXDbHandler::OpenDatabaseL"); + MPX_DEBUG2( "CMPXDbHandler::OpenDatabaseL: %i", aDrive); + iDbManager->OpenDatabaseL(aDrive); + + // Verify the volume ID after a remount event + VerifyVolumeIdL( aDrive ); + } + +// ---------------------------------------------------------------------------- +// Close a database +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::CloseDatabaseL( + TInt aDrive) + { + MPX_FUNC("CMPXDbHandler::CloseDatabaseL"); + MPX_DEBUG2( "CMPXDbHandler::CloseDatabaseL drive: %i", aDrive ); + iDbManager->CloseDatabaseL(aDrive); + } + +// ---------------------------------------------------------------------------- +// Re-create all databases +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::ReCreateDatabasesL() + { + MPX_FUNC("CMPXDbHandler::ReCreateDatabasesL"); + iDbManager->RecreateAllDatabasesL(); + } + +// ---------------------------------------------------------------------------- +// Set handler refresh status +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::RefreshStartL() + { + MPX_FUNC("CMPXDbHandler::RefreshStartL"); + + iOutOfDisk = EFalse; + // Re-open databases + // This is needed for the case where we were OOD before, but user + // has cleared some space but now try to refresh + MPX_TRAPD(err, iDbManager->InitDatabasesL(iDbDrives)); + + if(err == KErrDiskFull) + { + iOutOfDisk = ETrue; + } + + User::LeaveIfError( err ); + + if(!iOutOfDisk) + { + MPX_TRAP(err,CheckDiskSpaceOnDrivesL()); + + if(err == KErrDiskFull) + { + iOutOfDisk = ETrue; + } + } +#ifdef __RAMDISK_PERF_ENABLE + iDbManager->CopyDBsToRamL(); +#endif //__RAMDISK_PERF_ENABLE + + BeginTransactionL(); + iRefresh = ETrue; + } + +// ---------------------------------------------------------------------------- +// Re-set handler refresh status +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::RefreshEndL() + { + MPX_FUNC("CMPXDbHandler::RefreshEndL"); + if ( iRefresh ) + { + iRefresh = EFalse; + EndTransactionL(KErrNone); + if (!iOutOfDisk) + { + // Write last refreshed time as current time + // This also sets corrupt = 0 + TTime curTime; + curTime.HomeTime(); + SetLastRefreshedTimeL(curTime); + } + +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + //for AbstractAlbum garbage collection + TRAP_IGNORE( iDbAbstractAlbum->AbstractAlbumCleanUpL() ); +#endif + +#ifdef __RAMDISK_PERF_ENABLE + iDbManager->CopyDBsFromRamL(); +#endif //__RAMDISK_PERF_ENABLE + } + } + +// ---------------------------------------------------------------------------- +// Notification of Mtp status change +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::MtpStartL() + { + MPX_DEBUG1("-->CMPXDbHandler::MtpStartL"); + if(!iMtpInUse) + { + iMtpInUse = ETrue; + iOpOnDbCount = 0; + + #ifdef __RAMDISK_PERF_ENABLE + TRAPD(err, iDbManager->CopyDBsToRamL(iMtpInUse)); + if ( err != KErrNone ) + { + MPX_DEBUG2("CMPXDbHandler::MtpStartL error=%d", err); + } + #endif //__RAMDISK_PERF_ENABLE + + iDbManager->BeginL(); + } +//create Thumbnail manager session for cleanup for abstractalbum when MTP end. +//because when MTP end comes, in case of mode switching, we need to do it as fast as possible, +//hence we don’t want the delay happens on that time. +#ifdef RD_MPX_TNM_INTEGRATION + iDbAbstractAlbum->CreateTNMSessionL(); +#endif //RD_MPX_TNM_INTEGRATION + MPX_DEBUG1("<--CMPXDbHandler::MtpStartL"); + } + +// ---------------------------------------------------------------------------- +// Notification of Mtp status change +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::MtpEndL() + { + MPX_DEBUG1("-->CMPXDbHandler::MtpEndL"); + iMtpInUse = EFalse; + iOpOnDbCount = 0; + iDbManager->CommitL(); + TInt err = KErrNone; + + +#ifdef __RAMDISK_PERF_ENABLE + TRAP(err, iDbManager->CopyDBsFromRamL()); + if ( err != KErrNone ) + { + MPX_DEBUG2("CMPXDbHandler::MtpEndL error=%d", err); + } +#endif //__RAMDISK_PERF_ENABLE + +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + BeginTransactionL(); + TRAP(err, iDbAbstractAlbum->RemoveAbstractAlbumsWithNoSongL()); + if ( err != KErrNone ) + { + MPX_DEBUG2("CMPXDbHandler::MtpEndL error happened when cleanup albstractalbum with no songs association[%d]", err); + } + EndTransactionL(err); +#endif + MPX_DEBUG1("<--CMPXDbHandler::MtpEndL"); + } + +// ---------------------------------------------------------------------------- +// Get all records count for music +// ---------------------------------------------------------------------------- +// +TUint CMPXDbHandler::GetMusicCountL(TInt aDrive) + { + MPX_FUNC("CMPXDbHandler::GetMusicCountL"); + TUint total(0); + + //music + total += iDbMusic->GetDriveTrackCountL(aDrive); + + return total; + } + +// ---------------------------------------------------------------------------- +// Get all records count for playlists +// ---------------------------------------------------------------------------- +// +TUint CMPXDbHandler::GetPlaylistCountL(TInt aDrive) + { + MPX_FUNC("CMPXDbHandler::GetPlaylistCountL"); + TUint total(0); + + //playlist + total += iDbPlaylist->GetDrivePlaylistCountL(aDrive); + + return total; + } + +// ---------------------------------------------------------------------------- +// Get all records count for music and playlists +// ---------------------------------------------------------------------------- +// +TUint CMPXDbHandler::GetTotalCountL(TInt aDrive) + { + MPX_FUNC("CMPXDbHandler::GetTotalCountL"); + TUint total(0); + + //music + total += iDbMusic->GetDriveTrackCountL(aDrive); + //playlist + total += iDbPlaylist->GetDrivePlaylistCountL(aDrive); + + return total; + } + +// ---------------------------------------------------------------------------- +// Get all records count for music and playlists +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetMusicUriArrayL(TInt aDrive, TInt aFromID, TInt aRecords, + CDesCArray& aUriArr, TInt& aLastID) + { + MPX_FUNC("CMPXDbHandler::GetMusicUriArrayL"); + + iDbMusic->GetMusicUriArrayL(aDrive,aFromID,aRecords,aUriArr,aLastID); + } + +// ---------------------------------------------------------------------------- +// Get all records count for music and playlists +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetPlaylistUriArrayL(TInt aDrive, TInt aFromID, TInt aRecords, + CDesCArray& aUriArr, TInt& aLastID) + { + MPX_FUNC("CMPXDbHandler::GetPlaylistUriArrayL"); + + iDbPlaylist->GetPlaylistUriArrayL(aDrive,aFromID,aRecords,aUriArr,aLastID); + } + +// ---------------------------------------------------------------------------- +// Starts a transaction on all databases +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::BeginTransactionL() + { + MPX_FUNC("CMPXDbHandler::BeginTransactionL"); + +#ifdef __RAMDISK_PERF_ENABLE + // EnsureRamSpaceL will copy dbs from ram if ram space is low or dbs exceeded + // max space. + TRAPD(err, iDbManager->EnsureRamSpaceL()); + if (err) + { + //error but continue + } +#endif //__RAMDISK_PERF_ENABLE + + if(!iMtpInUse) + { + iDbManager->BeginL(); + } + } + +// ---------------------------------------------------------------------------- +// Ends a transaction on all databases +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::EndTransactionL( + TInt aError) + { + MPX_FUNC("CMPXDbHandler::EndTransactionL"); + + if(iMtpInUse) + { + if (aError) + { + iOpOnDbCount = 0; + iDbManager->RollbackL(); + User::Leave(aError); + } + + if(iOpOnDbCount >= KMaxOpInTransaction) + { + MPX_DEBUG2("CMPXDbHandler::EndTransactionL - %d>KMaxOpInTransaction Commiting",iOpOnDbCount); + iOpOnDbCount = 0; + iDbManager->CommitL(); + iDbManager->BeginL(); + } + } + else + { + if (aError) + { + MPX_DEBUG2("CMPXDbHandler::EndTransactionL - Rollback [%d]", aError); + + iDbManager->RollbackL(); + + // KSqlDbCorrupted indicates DB corrupted, need to recreate. + if ( aError != KSqlDbCorrupted ) + { + User::Leave(aError); + } + } + else + { + iDbManager->CommitL(); + } + } + } + +// ---------------------------------------------------------------------------- +// Checks if the database is currently in a transaction +// ---------------------------------------------------------------------------- +// +TBool CMPXDbHandler::InTransaction() + { + MPX_FUNC("CMPXDbHandler::InTransaction"); + return iDbManager->InTransaction(); + } + +// ---------------------------------------------------------------------------- +// Notifies the handler that the collection will be closed. +// It is called before closing the collection. +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::PreCloseCollectionL() + { + MPX_FUNC("CMPXDbHandler::PreCloseCollectionL"); + // Complete pending transaction and set the latest refresh time + // before closing the databases if collection close event occurs + // before the end of the refresh operation + if(iRefresh) + { + EndTransactionL(KErrNone); + if (!iOutOfDisk) + { + // Write last refreshed time as current time + // This also sets corrupt = 0 + TTime curTime; + curTime.HomeTime(); + SetLastRefreshedTimeL(curTime); + } + } + } + +// ---------------------------------------------------------------------------- +// Add song to collection +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::DoAddSongL( + const CMPXMedia& aMedia, + CMPXMessageArray* aMessageArray) + { + MPX_FUNC("CMPXDbHandler::DoAddSongL"); + + if (!aMedia.IsSupported(KMPXMediaGeneralUri)) + { + User::Leave(KErrArgument); + } + + // add the song to the Music table + TDriveUnit drive(aMedia.ValueText(KMPXMediaGeneralUri)); + TUint32 songId(iDbMusic->AddSongL(aMedia, drive, + iRefresh?NULL:aMessageArray)); + + // update the playlist tables + // make sure the song db flags are reset and not just updated + iDbPlaylist->UpdateSongL(aMedia, ETrue); + + if(iMtpInUse) + { + ++iOpOnDbCount; + } + + return songId; + } + +// ---------------------------------------------------------------------------- +// Add playlist to collection +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::DoAddPlaylistL( + const CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbHandler::DoAddPlaylistL"); + + CMPXMedia* media = CMPXMedia::NewL(aMedia); + CleanupStack::PushL(media); + + const TDesC& playlistUri = media->ValueText(KMPXMediaGeneralUri); + + // + // client has asked to create a virtual playlist if file name is not specified + // in the URI. In this case, generate URI for virtual playlist specified as + // follows: + // \timestamp.vir + // + TParsePtrC parser(playlistUri); + + if (!parser.NameOrExtPresent() || + parser.IsNameWild() || + parser.IsExtWild()) + { + HBufC* newUri = HBufC::NewLC(parser.DriveAndPath().Length() + KMCMaxTextLen + + KMPXVirtualPlaylistExt().Length()); + + TPtr ptr = newUri->Des(); + ptr.Append(parser.DriveAndPath()); + TTime time; + time.HomeTime(); + ptr.AppendNum(time.Int64()); + ptr.Append(KMPXVirtualPlaylistExt); + + // overwrite the old uri with the new one with full path and playlist + // playlist filename + media->SetTextValueL(KMPXMediaGeneralUri, *newUri); + + CleanupStack::PopAndDestroy(newUri); + + // set DbFlags to indicate that this is a virtual playlist + media->SetTObjectValueL(KMPXMediaGeneralFlags, + KMPXMediaGeneralFlagsSetOrUnsetBit | KMPXMediaGeneralFlagsIsVirtual); + } + + // complete the song attributes from the music table + UpdatePlaylistSongInfoL(*media); + + // add playlist to the database + TUint32 playlistId = iDbPlaylist->AddPlaylistL(*media); + + CleanupStack::PopAndDestroy(media); + return playlistId; + } + +// ---------------------------------------------------------------------------- +// Add song to playlist +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::DoAddSongToPlaylistL( + const CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbHandler::DoAddSongToPlaylistL"); + + CMPXMedia* media = CMPXMedia::NewL(aMedia); + CleanupStack::PushL(media); + + // complete the song attributes from the music table + UpdatePlaylistSongInfoL(*media); + + // add the songs to the playlist + TUint32 playlistId((media->ValueTObjectL(KMPXMediaGeneralId)).iId2); + + CMPXMediaArray* ary( aMedia.Value(KMPXMediaArrayContents) ); + User::LeaveIfNull( ary ); + iDbPlaylist->AddSongsL(playlistId,*ary); + + CleanupStack::PopAndDestroy(media); + return playlistId; + } + +// ---------------------------------------------------------------------------- +// Update a song in the collection +// ---------------------------------------------------------------------------- +// +CMPXDbActiveTask::TChangeVisibility CMPXDbHandler::DoUpdateSongL( + const CMPXMedia& aMedia, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::DoUpdateSongL"); + + CMPXDbActiveTask::TChangeVisibility visibleChange(CMPXDbActiveTask::ENotVisibile); + + TUint32 songId(0); + + if (aMedia.IsSupported(KMPXMediaGeneralId)) + { + songId = (aMedia.ValueTObjectL(KMPXMediaGeneralId)).iId2; + } + if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + const TDesC& uri = aMedia.ValueText(KMPXMediaGeneralUri); + songId = MPXDbCommonUtil::GenerateUniqueIdL(iFs, EMPXCollection, uri, EFalse); + } + if (!songId) + { + User::Leave(KErrNotSupported); + } + + // Update the Music table + TRAPD(err, visibleChange = iDbMusic->UpdateSongL(songId, aMedia, aItemChangedMessages)); + + // do not leave if song is not found in Music table + // leave for other errors such as disk full + if(err != KErrNone && err != KErrNotFound) + { + User::Leave(err); + } + + // Update the Playlist table + TBool visible = EFalse; + + TRAP( err, visible = iDbPlaylist->UpdateSongL(aMedia, EFalse, &aItemChangedMessages)); + + // do not leave if song is not found in Playlist table + // leave for other errors such as disk full + if(err != KErrNone && err != KErrNotFound) + { + User::Leave(err); + } + + // make it visible if either table is updated + if (visible) + { + visibleChange = CMPXDbActiveTask::EAllVisible; + } + if ( aMedia.ValueTObjectL( KMPXMediaMusicAlbumArtChanged )== 1 ) + { + ( const_cast( &aMedia ) + )->SetTObjectValueL( KMPXMediaMusicAlbumArtChanged, 0 ); + } + + return visibleChange; + } + +// ---------------------------------------------------------------------------- +// Update a playlist in the collection +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoUpdatePlaylistL( + const CMPXMedia& aMedia, + CMPXMessageArray& aMessageArray) + { + MPX_FUNC("CMPXDbHandler::DoUpdatePlaylistL"); + + TUint32 playlistId(0); + TInt drive(0); + + CMPXMedia* media = CMPXMedia::NewL(aMedia); + CleanupStack::PushL(media); + + + ProcessPlaylistMediaL(*media, playlistId, drive); + + CMPXMessage* m1 = CMPXMessage::NewL(); + CleanupStack::PushL(m1); + CMPXMessage* m2 = CMPXMessage::NewL(); + CleanupStack::PushL(m2); + + // send 2 messages to notify the playlist change & to refresh the display (update playlist name) + MPXDbCommonUtil::FillItemChangedMessageL(*m1, playlistId, EMPXItemModified, + EMPXPlaylist, KDBPluginUid); + + MPXDbCommonUtil::FillItemChangedMessageL(*m2, EBrowsePlaylist, EMPXItemModified, + EMPXPlaylist, KDBPluginUid); + + iDbPlaylist->UpdatePlaylistL(*media, *m1, drive); + + aMessageArray.AppendL(*m1); + aMessageArray.AppendL(*m2); + + + CleanupStack::PopAndDestroy(m2); + CleanupStack::PopAndDestroy(m1); + CleanupStack::PopAndDestroy(media); + } + +// ---------------------------------------------------------------------------- +// Update a playlist in the collection +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoUpdatePlaylistSongsL( + const CMPXMedia& aMedia, + CMPXMessage& aMessage) + { + MPX_FUNC("CMPXDbHandler::DoUpdatePlaylistSongsL"); + + CMPXMedia* media = CMPXMedia::NewL(aMedia); + CleanupStack::PushL(media); + + TUint32 playlistId(0); + TInt drive(0); + + // get the playlist ID and drive ID + ProcessPlaylistMediaL(*media, playlistId, drive); + MPXDbCommonUtil::FillItemChangedMessageL(aMessage, playlistId, EMPXItemModified, + EMPXPlaylist, KDBPluginUid); + + // complete the song attributes from the Music table + UpdatePlaylistSongInfoL(*media); + + // delete existing songs for the playlist first + iDbPlaylist->Songs().DeleteSongsL(playlistId, drive); + + // add new songs to the playlist + CMPXMediaArray* ary( media->Value(KMPXMediaArrayContents ) ); + User::LeaveIfNull( ary ); + iDbPlaylist->AddSongsL(playlistId, *ary); + + CleanupStack::PopAndDestroy(media); + } + +// ---------------------------------------------------------------------------- +// Reorder a song in a playlist +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoReorderPlaylistL( + const TMPXItemId& aPlaylistId, + const TMPXItemId& aSongId, + TUint aOriginalOrdinal, + TUint aNewOrdinal, + CMPXMessage& aMessage) + { + MPX_DEBUG1("-->CMPXDbHandler::DoReorderPlaylistL()"); + + if (aOriginalOrdinal != aNewOrdinal) + { + iDbPlaylist->Songs().ReorderSongL(aPlaylistId, aSongId, aOriginalOrdinal, aNewOrdinal); + + MPXDbCommonUtil::FillItemChangedMessageL(aMessage, aPlaylistId.iId2, EMPXItemModified, + EMPXPlaylist, KDBPluginUid); + } + + MPX_DEBUG1("<--CMPXDbHandler::DoReorderPlaylistL()"); + } + +// ---------------------------------------------------------------------------- +// Delete a song from collection +// The function notifies collection model to perform deletion +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoRemoveSongL( + TUint32 aSongId, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages, + TBool aDeleteRecord) + { + MPX_FUNC("CMPXDbHandler::DoRemoveSongL"); + + // Get the song drive + TUint32 artistID(0); + TUint32 albumID(0); + TUint32 genreID(0); + TUint32 composerID(0); + HBufC* art(NULL); +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + TUint32 abstractAlbumID(0); +#endif // ABSTRACTAUDIOALBUM_INCLUDED + TInt drive(0); + +// Get information from the Music table first +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + HBufC* uri = iDbMusic->GetSongInfoL(aSongId, artistID, albumID, genreID, composerID, abstractAlbumID, drive, art); +#else + HBufC* uri = iDbMusic->GetSongInfoL(aSongId, artistID, albumID, genreID, composerID, drive, art); +#endif // ABSTRACTAUDIOALBUM_INCLUDED + + CleanupStack::PushL(art); + // add the URI to the return array + CleanupStack::PushL(uri); + aUriArray.AppendL(*uri); + CleanupStack::PopAndDestroy(uri); + + // Update the category records + TBool categoryExist( EFalse ); + iDbArtist->DecrementSongsForCategoryL(artistID, drive, &aItemChangedMessages, categoryExist); + iDbAlbum->DecrementSongsForCategoryL(albumID, drive, &aItemChangedMessages, categoryExist, artistID, *art); + iDbGenre->DecrementSongsForCategoryL(genreID, drive, &aItemChangedMessages, categoryExist); + iDbComposer->DecrementSongsForCategoryL(composerID, drive, &aItemChangedMessages, categoryExist); + CleanupStack::PopAndDestroy(art); +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + if (abstractAlbumID) + { + iDbAbstractAlbum->DecrementSongsForCategoryL(abstractAlbumID, drive, &aItemChangedMessages, categoryExist, iMtpInUse); + } +#endif // ABSTRACTAUDIOALBUM_INCLUDED + // Update the music table + TBool deleteRecord(ETrue); + +#if defined (__MTP_PROTOCOL_SUPPORT) + // Mark the song record as deleted if the following is true; otherwise, delete the + // song record. + // + // A client other than MTP has initiated this song deletion (aDeleteRecord is EFalse) + // and MTP has turned on its cenrep key to save deleted records and current number of + // saved deleted records has not exceeded its maximum, KMCMaxSavedDeletedRecords. + // + // Songs are marked as deleted in order to support auto-sync. MTP will delete these + // marked records at the end of each session via CleanupDeletedRecordsL. + // + // For performance consideration, if the number of saved records exceeds its maximum, + // song record will be deleted. + if (!aDeleteRecord && SaveDeletedSongs()) + { + TUint32 savedDeletedRecordCount(iDbAuxiliary->SaveDeletedRecordCountL()); + MPX_DEBUG2("Current number of saved deleted record count is %d", savedDeletedRecordCount); + + if (savedDeletedRecordCount < KMCMaxSavedDeletedRecords) + { + deleteRecord = EFalse; + TUint32 savedDeletedDriveRecordCount(iDbAuxiliary->SaveDeletedRecordCountL(drive)); + iDbAuxiliary->SetSaveDeletedRecordCountL(drive,++savedDeletedDriveRecordCount); + } + } +#endif + + // delete the song from the Music table + iDbMusic->DeleteSongL(aSongId, drive, deleteRecord); + + // add the item changed message + MPXDbCommonUtil::AddItemChangedMessageL(aItemChangedMessages, aSongId, EMPXItemDeleted, + EMPXSong, KDBPluginUid); + + + if(iMtpInUse) + { + ++iOpOnDbCount; + } + } + +// ---------------------------------------------------------------------------- +// Delete a song from playlist tables +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoRemoveSongFromPlaylistL(TUint32 aSongId,CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::DoRemoveSongFromPlaylistL"); + // delete song from the playlist tables on all drives + iDbPlaylist->DeleteSongL(aSongId, aItemChangedMessages); + } + +// ---------------------------------------------------------------------------- +// Removes a category of songs from the music collection, +// and its corresponding category in the lookup table +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoRemoveSongsMatchingCategoryL( + TMPXGeneralCategory aCategory, + TUint32 aCategoryId, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::DoRemoveSongsMatchingCategoryL"); + + // get the songs for the specified category + CMPXMediaArray* songs = CMPXMediaArray::NewL(); + CleanupStack::PushL(songs); + + RArray attributes; + CleanupClosePushL(attributes); + attributes.AppendL(KMPXMediaGeneralId); + + switch (aCategory) + { + case EMPXArtist: + { + iDbMusic->GetSongsForArtistL(aCategoryId, attributes.Array(), *songs); + break; + } + case EMPXAlbum: + { + iDbMusic->GetSongsForAlbumL(aCategoryId, attributes.Array(), *songs); + break; + } + case EMPXGenre: + { + iDbMusic->GetSongsForGenreL(aCategoryId, attributes.Array(), *songs); + break; + } + case EMPXComposer: + { + iDbMusic->GetSongsForComposerL(aCategoryId, attributes.Array(), *songs); + break; + } + default: + User::Leave(KErrNotSupported); + } + + CleanupStack::PopAndDestroy(&attributes); + + // iterate the songs and remove them one by one + // so records in the category tables can also be updated + TInt count(songs->Count()); + for (TInt index = 0; index < count; ++index) + { + CMPXMedia* song = (*songs)[index]; + if (song->IsSupported(KMPXMediaGeneralId)) + { + DoRemoveSongL((song->ValueTObjectL(KMPXMediaGeneralId)).iId2, + aUriArray, aItemChangedMessages, EFalse); + DoRemoveSongFromPlaylistL((song->ValueTObjectL(KMPXMediaGeneralId)).iId2,aItemChangedMessages); + } + } + + CleanupStack::PopAndDestroy(songs); + } + +// ---------------------------------------------------------------------------------------------------------- +// Delete songs for the specified artist and album from collection +// ---------------------------------------------------------------------------------------------------------- +// +void CMPXDbHandler::DoRemoveSongsMatchingArtistAndAlbumL( + TUint32 aArtistId, + TUint32 aAlbumId, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::RemoveSongsMatchingArtistAndAlbumL"); + + // get the songs for the specified artist and album + CMPXMediaArray* songs = CMPXMediaArray::NewL(); + CleanupStack::PushL(songs); + + RArray attributes; + CleanupClosePushL (attributes); + attributes.AppendL(KMPXMediaGeneralId); + + iDbMusic->GetSongsForArtistAndAlbumL(aArtistId, aAlbumId, attributes.Array(), *songs); + CleanupStack::PopAndDestroy(&attributes); + + // iterate the songs and remove them one by one + // so records in the category tables can also be updated + TInt count(songs->Count()); + for (TInt index = 0; index < count; ++index) + { + CMPXMedia* song = (*songs)[index]; + if (song->IsSupported(KMPXMediaGeneralId)) + { + DoRemoveSongL( song->ValueTObjectL(KMPXMediaGeneralId), + aUriArray, aItemChangedMessages, EFalse); + DoRemoveSongFromPlaylistL(song->ValueTObjectL(KMPXMediaGeneralId),aItemChangedMessages); + } + } + + CleanupStack::PopAndDestroy(songs); + } + +// ---------------------------------------------------------------------------- +// Remove all playlists from collection +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoRemoveAllPlaylistsL() + { + MPX_FUNC("CMPXDbHandler::DoRemoveAllPlaylistsL"); + iDbPlaylist->DeleteAllPlaylistsL(); + } + +// ---------------------------------------------------------------------------- +// Remove specified playlist +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoRemovePlaylistL( + TUint32 aPlaylistId, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::DoRemovePlaylistL"); + + HBufC* uri(iDbPlaylist->DeletePlaylistL(aPlaylistId)); + if (uri) + { + CleanupStack::PushL(uri); + aUriArray.AppendL(*uri); + CleanupStack::PopAndDestroy(uri); + } + + MPXDbCommonUtil::AddItemChangedMessageL(aItemChangedMessages, aPlaylistId, EMPXItemDeleted, + EMPXPlaylist, KDBPluginUid); + } + +// ---------------------------------------------------------------------------- +// Remove song from playlist songs table +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoRemoveSongFromPlaylistL( + TUint32 aPlaylistId, + const TMPXItemId& aSongId, + TInt aOrdinal, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::DoRemoveSongFromPlaylistL"); + MPX_DEBUG5("CMPXDbHandler::DoRemoveSongFromPlaylistL(playlist 0x%x, songId [0x%x,0x%x], ordinal %d)", + aPlaylistId, aSongId.iId1, aSongId.iId2, aOrdinal); + + // delete the song + iDbPlaylist->DeleteSongL(aPlaylistId, aSongId.iId2, aOrdinal); + + // Send a playlist modified message + MPXDbCommonUtil::AddItemChangedMessageL(aItemChangedMessages, aPlaylistId, EMPXItemModified, + EMPXPlaylist, KDBPluginUid); + + // Send a message on the song in the playlist that is deleted + MPXDbCommonUtil::AddItemChangedMessageL(aItemChangedMessages, aSongId, EMPXItemDeleted, + EMPXSong, KDBPluginUid); + } + + +// ---------------------------------------------------------------------------- +// CMPXDbHandler::DoCleanupDeletedRecordsL +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DoCleanupDeletedRecordsL() + { + MPX_FUNC("CMPXDbHandler::DoCleanupDeletedRecordsL"); + + // delete all marked records from the Music table + iDbMusic->CleanupL(); + + // reset the count in the Auxiliary table + iDbAuxiliary->SetSaveDeletedRecordCountL(KDbManagerAllDrives,0); + } + +// ---------------------------------------------------------------------------- +// FindAllL +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::FindAllL( + const CMPXMedia& aCriteria, + const TArray& aAttrs, + CMPXMediaArray* aMediaArray) + { + MPX_FUNC("CMPXDbHandler::FindAllL"); + + RArray attributes; + CleanupClosePushL(attributes); + MPXUser::MergeAttributeL(aAttrs, attributes); + + TMPXGeneralCategory category = aCriteria.ValueTObjectL(KMPXMediaGeneralCategory); + switch (category) + { + case EMPXPlaylist: + { + TUint32 playlistId(0); + if (aCriteria.IsSupported(KMPXMediaGeneralId)) + { + playlistId = (aCriteria.ValueTObjectL(KMPXMediaGeneralId)).iId2; + } + + if (iAutoPlaylist->AutoPlaylistTypeL(playlistId) != EMPXNoAutoPlaylist) + { + CMPXMedia* media = CMPXMedia::NewL(); + CleanupStack::PushL(media); + + iAutoPlaylist->GetPlaylistL(playlistId, aAttrs, *media); + + aMediaArray->AppendL(*media); + CleanupStack::PopAndDestroy(media); + } + else + { + iDbPlaylist->FindAllL(aCriteria, attributes.Array(), *aMediaArray); + } + + break; + } + case EMPXSong: + { + FindSongL(aCriteria, attributes.Array(), *aMediaArray); + break; + } + default: + { + DbCategoryL(category)->FindAllL(aCriteria, attributes.Array(), *aMediaArray); + break; + } + } + + CleanupStack::PopAndDestroy(&attributes); + } + +// ---------------------------------------------------------------------------- +// Get song(s) from the music table that match the given criteria +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::FindSongL( + const CMPXMedia& aCriteria, + const TArray& aAttrs, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbCollection::FindSongL"); + + TMPXGeneralType type = aCriteria.ValueTObjectL(KMPXMediaGeneralType); + + TUint32 id(0); + if (aCriteria.IsSupported(KMPXMediaGeneralId)) + { + id = (aCriteria.ValueTObjectL(KMPXMediaGeneralId)).iId2; + } + + TUint32 containerId(0); + if (aCriteria.IsSupported(KMPXMediaGeneralContainerId)) + { + containerId = aCriteria.ValueTObjectL(KMPXMediaGeneralContainerId); + } + + ////////////////////////////////////////////////////////////////////// + // Find songs in the specified playlist + ////////////////////////////////////////////////////////////////////// + TMPXGeneralCategory cat(MPX_ITEM_CATEGORY(id)); + + if (type == EMPXGroup && + (cat == EMPXPlaylist || + MPX_ITEM_CATEGORY(containerId) == EMPXPlaylist)) + { + TUint32 playlistId = (cat == EMPXPlaylist) ? + id : (containerId & KMCCategoryMask); + + GetPlaylistSongsL(playlistId, aAttrs, aMediaArray); + } +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + else if (type == EMPXGroup && + (cat == EMPXAbstractAlbum || + MPX_ITEM_CATEGORY(containerId) == EMPXAbstractAlbum)) + { + TUint32 abstractAlbumId = (cat == EMPXAbstractAlbum) ? + id : (containerId & KMCCategoryMask); + TInt attrCount(aAttrs.Count()); + if ( attrCount > 1 || (attrCount == 1 && !(aAttrs[0] == KMPXMediaGeneralId)) ) + { + MPX_TRAPD(err, iDbMusic->GetAllSongsForAbstractAlbumL( abstractAlbumId, aAttrs, aMediaArray)); + if (err == KErrNotFound) + { + // + // Leave with KErrNotFound + User::Leave(KErrNotFound); + } + else + { + // Leave if error + User::LeaveIfError(err); + } + } + } +#endif // ABSTRACTAUDIOALBUM_INCLUDED + ////////////////////////////////////////////////////////////////////// + // Find a particular song in the specified playlist. This fills the + // song with info from Playlist table first then overwrites it with + // info from Songs table if Songs table where this song is located + // is present in order to support the display of song titles in a + // playlist when memory card is removed if the playlist refers to + // songs on the memory card. Caller of this scenario is OpenL/MediaL. + // When user attempts to play a track in an auto-playlist, we will + // find the song from Songs table directly since auto-playlists are + // not stored in the Playlist table. Auto-playlists are query-based, + // therefore, when memory card is removed, songs on the memory card + // will not be shown in the auto-playlist; hence they do not exhibit + // the same challenge as user created playlists. + ////////////////////////////////////////////////////////////////////// + else if (type == EMPXItem && + cat == EMPXCollection && + MPX_ITEM_CATEGORY(containerId) == EMPXPlaylist) + { + if (iAutoPlaylist->AutoPlaylistTypeL(containerId) != EMPXNoAutoPlaylist) + { + // auto playlist song, get the song details from the music table + iDbMusic->FindSongsL(id, 0, type, aCriteria, aAttrs, aMediaArray); + } + else + { + GetPlaylistSongL(id, containerId, aAttrs, aMediaArray); + } + } + + ////////////////////////////////////////////////////////////////////// + // Find all songs, all songs in a particular album and/or artist, or + // a particular song + ////////////////////////////////////////////////////////////////////// + else + { + iDbMusic->FindSongsL(id, containerId, type, aCriteria, aAttrs, aMediaArray); + } + } + +// ---------------------------------------------------------------------------- +// Get song(s) in the specified playlist +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::GetPlaylistSongsL( + TUint32 aPlaylistId, + const TArray& aAttrs, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbHandler::GetPlaylistSongsL"); + MPX_DEBUG2("CMPXDbHandler::GetPlaylistSongsL(0x%x)", aPlaylistId); + + // check the auto playlists first + if (aPlaylistId == iAutoPlaylist->AutoPlaylistIdL(EMPXRecentlyPlayedPlaylist)) + { + iDbMusic->GetRecentlyPlayedSongsL(aAttrs, aMediaArray); + } + else if (aPlaylistId == iAutoPlaylist->AutoPlaylistIdL(EMPXMostPlayedPlaylist)) + { + iDbMusic->GetMostPlayedSongsL(aAttrs, aMediaArray); + } + else if (aPlaylistId == iAutoPlaylist->AutoPlaylistIdL(EMPXRecentlyAddedPlaylist)) + { + iDbMusic->GetRecentlyAddedSongsL(aAttrs, aMediaArray); + } + else + { + TInt attrCount(aAttrs.Count()); + if ( attrCount > 1 || (attrCount == 1 && !(aAttrs[0] == KMPXMediaGeneralId)) ) + { + TInt plDrive(iDbPlaylist->GetDriveIdL(aPlaylistId)); + MPX_TRAPD(err, iDbMusic->GetAllSongsL(plDrive, aPlaylistId, aAttrs, aMediaArray)); + + // song not found in Music table + if (err == KErrNotFound) + { + // + // Leave with KErrNotFound if one of the following is true: + // 1) the requested song is in an auto playlist. Since auto-playlist isn't + // stored in playlist tables, we won't be able to retrieve info elsewhere + // 2) the requested song is in a user playlist but we cannot find the song + // info from playlist tables either + // + if (EMPXNoAutoPlaylist != iAutoPlaylist->AutoPlaylistTypeL(aPlaylistId) || + !iDbPlaylist->Songs().GetSongsL(aPlaylistId, aAttrs, aMediaArray)) + { + User::Leave(KErrNotFound); + } + } + else + { + // ignore the error if KErrNotFound + User::LeaveIfError(err); + } + } + else + { + // get ids of the songs in the playlist + iDbPlaylist->Songs().GetSongsL(aPlaylistId, aMediaArray); + } + } + } + +// ---------------------------------------------------------------------------- +// Find all albums or the albums for a specified artist +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::FindAlbumL( + const CMPXMedia& aCriteria, + const TArray& aAttrs, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbHandler::FindAlbumL"); + + TMPXGeneralType type = aCriteria.ValueTObjectL(KMPXMediaGeneralType); + + TUint32 id(0); + if (aCriteria.IsSupported(KMPXMediaGeneralId)) + { + id = aCriteria.ValueTObjectL(KMPXMediaGeneralId); + } + + if ((type == EMPXGroup) && (MPX_ITEM_CATEGORY(id) == EMPXArtist)) + { + // get all the albums for the artist + GetAlbumsMatchingArtistL(id, aAttrs, aMediaArray); + } + else + { + // look up all albums from album table + iDbAlbum->FindAllL(aCriteria, aAttrs, aMediaArray); + } + } + +// ---------------------------------------------------------------------------- +// Extracts the playlist ID and drive ID from a playlist media instance +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::ProcessPlaylistMediaL( + CMPXMedia& aMedia, + TUint32& aPlaylistId, + TInt& aPlaylistDriveId) + { + MPX_FUNC("CMPXDbHandler::ProcessPlaylistMediaL"); + + if (aMedia.IsSupported(KMPXMediaGeneralId)) + { + aPlaylistId = aMedia.ValueTObjectL(KMPXMediaGeneralId); + + if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + // find drive id of the playlist + aPlaylistDriveId = TDriveUnit(aMedia.ValueText(KMPXMediaGeneralUri)); + } + else + { + // Find drive Id(s) of corresponding Playlist Id + aPlaylistDriveId = iDbPlaylist->GetDriveIdL(aPlaylistId); + } + } + else if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + const TDesC& playlistUri = aMedia.ValueText(KMPXMediaGeneralUri); + // find drive id of the playlist + aPlaylistDriveId = TDriveUnit(playlistUri); + + // aMedia does not have an ID, make sure the add it + aPlaylistId = GetPlaylistIdMatchingUriL(playlistUri); + aMedia.SetTObjectValueL(KMPXMediaGeneralId, aPlaylistId); + } + else + { + User::Leave(KErrArgument); + } + } + +// ---------------------------------------------------------------------------- +// Makes sure that all songs in the specified playlist have the ID, title and URI attributes +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::UpdatePlaylistSongInfoL( + CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbHandler::UpdatePlaylistSongInfoL"); + + CMPXMediaArray* mediaArray = aMedia.Value(KMPXMediaArrayContents); + User::LeaveIfNull(mediaArray); + + // make sure each song has Id, Uri, and Title before they can be added to playlist + TInt count(mediaArray->Count()); + for (TInt i = 0; i < count; ++i) + { + CMPXMedia* element = mediaArray->AtL(i); + + // copy each song to deal w/ global heap issues + CMPXMedia* entry = CMPXMedia::NewL(*element); + CleanupStack::PushL(entry); + + // song has everything, go to next song + if (entry->IsSupported(KMPXMediaGeneralUri) && + entry->IsSupported(KMPXMediaGeneralId) && + entry->IsSupported(KMPXMediaGeneralTitle)) + { + // pop entry to maintain CleanupStack + CleanupStack::PopAndDestroy(entry); + continue; + } + + // songs must contain (at minimum) an Uri or an Id + if (!entry->IsSupported(KMPXMediaGeneralUri) && + !entry->IsSupported(KMPXMediaGeneralId)) + { + User::Leave(KErrArgument); + } + + // get Id + if (!entry->IsSupported(KMPXMediaGeneralId)) + { + // fill in the ID if not present + TParsePtrC parser(entry->ValueText(KMPXMediaGeneralUri)); + entry->SetTObjectValueL(KMPXMediaGeneralId, + MPXDbCommonUtil::GenerateUniqueIdL(iFs, EMPXCollection, parser.FullName(), EFalse)); + } + + CMPXMedia* song(NULL); + + // update songs info + TInt error(iDbMusic->GetSongL(*entry, song)); + TBool result (ETrue); + + // error can only be KErrNone or KErrNotFound + // from CMPXDbMusic::GetSongL + // if not found in Music, get info from PlaylistSongs (PlaylistSongs & PlaylistSongInfo) DB + if (error == KErrNotFound) + { + RArray attributes; + CleanupClosePushL(attributes); + attributes.AppendL(TMPXAttribute(KMPXMediaIdGeneral, + EMPXMediaGeneralId | EMPXMediaGeneralTitle | EMPXMediaGeneralUri | EMPXMediaGeneralFlags)); + + // this song doesn't exist in Music table. This song is either a broken link or + // is of an unsupported song type that exists in the file system. Broken links + // have already been marked as such during playlist import. + result = iDbPlaylist->Songs().GetSongL(entry->ValueTObjectL(KMPXMediaGeneralId), attributes.Array(), song); + if (!result) + { + // song is a broken link + //TUint flags = KMPXMediaGeneralFlagsSetOrUnsetBit; + //flags |= KMPXMediaGeneralFlagsIsInvalid; // set flag + //t->SetTObjectValueL( KMPXMediaGeneralFlags, flags ); + + if (entry->IsSupported(KMPXMediaGeneralUri)) + { + // no valid Id but has Uri, just verify Title is present + // this is the case if the song is a broken link or podcast + if (!entry->IsSupported(KMPXMediaGeneralTitle)) + { + // does not have Title, make up the Title from file name + TParsePtrC parser(entry->ValueText(KMPXMediaGeneralUri)); + entry->SetTextValueL(KMPXMediaGeneralTitle, parser.Name()); + } + } + else + { + // no valid Id & no Uri, bad argument + User::Leave(KErrArgument); + } + } + CleanupStack::PopAndDestroy(&attributes); + } + + // update attributes + CleanupStack::PushL(song); + + // song not found in Music or Playlist DB, update entry + if(error == KErrNotFound && !result) + { + mediaArray->InsertL(*entry,i); + } + else // found in DB, replace entry + { + mediaArray->InsertL(*song,i); + } + + // replace element in the array + CleanupStack::PopAndDestroy(song); + CleanupStack::PopAndDestroy(entry); + mediaArray->Remove(i+1); + } + } + +// ---------------------------------------------------------------------------- +// CMPXDbHandler::ProcessMusicFoldersL +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::ProcessMusicFoldersL( + const CDesCArray& aFolders) + { + MPX_FUNC("CMPXDbHandler::ProcessMusicFoldersL"); + + TInt count(aFolders.MdcaCount()); + for (TInt i = 0; i < count; ++i) + { + TPtrC16 folder = aFolders.MdcaPoint(i); + + // check if disk is inserted and act accordingly + TDriveUnit driveUnit(folder); + if (!iFs.IsValidDrive(driveUnit)) + { + User::Leave(KErrArgument); + } + + // append the drive to the drive list + iDbDrives.AppendL(driveUnit); + } + } + +// ---------------------------------------------------------------------------- +// CMPXDbHandler::DbCategoryL +// ---------------------------------------------------------------------------- +// +CMPXDbCategory* CMPXDbHandler::DbCategoryL( + TMPXGeneralCategory aCategory) const + { + MPX_FUNC("CMPXDbHandler::DbCategoryL"); + + CMPXDbCategory* dbCategory(NULL); + switch (aCategory) + { + case EMPXArtist: + { + dbCategory = (CMPXDbCategory*)iDbArtist; + break; + } + case EMPXAlbum: + { + dbCategory = (CMPXDbCategory*)iDbAlbum; + break; + } + case EMPXGenre: + { + dbCategory = (CMPXDbCategory*)iDbGenre; + break; + } + case EMPXComposer: + { + dbCategory = (CMPXDbCategory*)iDbComposer; + break; + } +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + case EMPXAbstractAlbum: + { + dbCategory = (CMPXDbCategory*)iDbAbstractAlbum; + break; + } +#endif // ABSTRACTAUDIOALBUM_INCLUDED + default: + User::Leave(KErrNotSupported); + } + + return dbCategory; + } + +// ---------------------------------------------------------------------------- +// Verifies that the volume ID of the database matches the drive +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::VerifyVolumeIdL( TInt aDrive ) + { + MPX_DEBUG1("CMPXDbHandler::VerifyVolumeIdL <--"); + if( iDbManager->IsOpen( aDrive ) ) + { + TVolumeInfo volInfo; + iFs.Volume(volInfo, aDrive ); + TUint curId(volInfo.iUniqueID); + + TInt volId = iDbAuxiliary->IdL( aDrive ); + + // New database, no volume id set, mask out top bit because this is an uint + // + MPX_DEBUG3("CMPXDBHandler::VerifyVolumeIdL drive:%i db:%i", curId, volId); + if( volId == 0 && (curId&0x7FFFFFFF) ) + { + MPX_DEBUG1("CMPXDbHandler::VerifyVolumeIdL -- New ID"); + BeginTransactionL(); + TRAPD( err, iDbAuxiliary->SetIdL( aDrive, curId&0x7FFFFFFF ) ); + EndTransactionL( err ); + + // KSqlDbCorrupted indicates DB corrupted, need to recreate. + if ( err == KSqlDbCorrupted ) + { + MPX_DEBUG1("CMPXPodcastDbHandler::VerifyVolumeIdL -- Corrupted DB"); + iDbManager->RecreateDatabaseL(aDrive); + BeginTransactionL(); + TRAPD(err, iDbAuxiliary->SetDBCorruptedL( ETrue ) ); + EndTransactionL( err ); + } + } + // Unmatched volume id, mark db as corrupt and break + // + else if ( (curId&0x7FFFFFFF) != (volId&0x7FFFFFFFF) ) + { + MPX_DEBUG1("CMPXDbHandler::VerifyVolumeIdL -- ID match FAILED"); + iDbManager->RecreateDatabaseL(aDrive); + BeginTransactionL(); + TRAPD(err, iDbAuxiliary->SetDBCorruptedL( ETrue ) ); + EndTransactionL( err ); + } + } + + MPX_DEBUG1("CMPXDbHandler::VerifyVolumeIdL -->"); + } + +// ---------------------------------------------------------------------------- +// Verifies that the volume ID of the database matches the drive +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::VerifyVolumeIdL() + { + MPX_DEBUG1("CMPXDbHandler::VerifyVolumeIdL <--"); + TInt count( iDbDrives.Count() ); + for( TInt i=0; i"); + } + + +// ---------------------------------------------------------------------------- +// Checks if there is a drive that has a low disk space +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::CheckDiskSpaceOnDrivesL() + { + MPX_DEBUG1("CMPXDbHandler::CheckDiskSpaceOnDrivesL <--"); + + TInt count( iDbDrives.Count() ); + for( TInt index=0; indexCheckDiskSpaceL(iDbDrives[index]); + } + MPX_DEBUG1("CMPXDbHandler::CheckDiskSpaceOnDrivesL -->"); + } + +#if defined (__MTP_PROTOCOL_SUPPORT) + +// ---------------------------------------------------------------------------- +// CMPXDbHandler::SaveDeletedSongs +// ---------------------------------------------------------------------------- +// +TBool CMPXDbHandler::SaveDeletedSongs() + { + MPX_FUNC("CMPXDbHandler::SaveDeletedSongs"); + + TBool saveDeletedSongs(ETrue); + CRepository* cenrep(NULL); + MPX_TRAPD(error, cenrep = CRepository::NewL(KMPXMtpSettings)); + if (!error) + { + cenrep->Get(KMPXMtpSaveDeletedRecordFlag, saveDeletedSongs); + delete cenrep; + MPX_DEBUG2("MTP indicated to save deleted songs? %d", saveDeletedSongs); + } + + return saveDeletedSongs; + } + +#endif + +#ifdef RD_MULTIPLE_DRIVE + +// ---------------------------------------------------------------------------------------------------------- +// Retrieve all visible music folder locations +// ---------------------------------------------------------------------------------------------------------- +// +CDesCArrayFlat* CMPXDbHandler::GetMusicFoldersL() + { + MPX_FUNC("CMPXDbHandler::GetMusicFoldersL()"); + TDriveList driveList; + TInt driveCount(0); + User::LeaveIfError(DriveInfo::GetUserVisibleDrives(iFs, driveList, driveCount)); + MPX_DEBUG2 ("CMPXDbHandler::GetMusicFoldersL() - driveCount = %d", driveCount); + + CDesCArrayFlat* folders = new (ELeave) CDesCArrayFlat(1); // granularity + CleanupStack::PushL(folders); + + for (TInt i = EDriveA; i <= EDriveZ; i++) + { + if ((driveList[i]) && (!IsRemoteDrive(static_cast(i)))) + { + if (i == EDriveC) + { + // Append the default phone memory path to the list + // of music folders + TPtrC rootPath(PathInfo::PhoneMemoryRootPath()); + folders->AppendL(rootPath); + MPX_DEBUG2("CMPXDbHandler::GetMusicFoldersL() - adding...%S", &rootPath); + } + else + { + // Get drive letter + TChar driveChar; + User::LeaveIfError(iFs.DriveToChar(i, driveChar)); + + // Append visible drive to list of music folders + TBuf<2> drive; + drive.Append(driveChar); + drive.Append(_L(":")); + folders->AppendL(drive); + MPX_DEBUG2 ("CMPXDbHandler::GetMusicFoldersL() - adding...%S", &drive); + } + } + } + + CleanupStack::Pop(folders); + return folders; + } + +#endif // RD_MULTIPLE_DRIVE + +// ---------------------------------------------------------------------------- +// CMPXDbHandler::AddCategoryItemL +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbHandler::AddCategoryItemL( + TMPXGeneralCategory aCategory, + const TDesC& aName, + TInt aDriveId, + CMPXMessageArray* aItemChangedMessages, + TBool& aItemExist +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + ,const TDesC& aUri + ,const TDesC& aAlbumArtist +#endif // ABSTRACTAUDIOALBUM_INCLUDED + ) + { + MPX_FUNC("CMPXDbHandler::AddCategoryItemL()"); + + MPX_PERF_START(CMPXDbHandler_AddCategoryItemL); + + TBool newRecord(EFalse); +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + TUint32 id(0); + //for AbstractAlbum, SetAbstractAlbum, associate songs with abstractalbum. + //only called with newRecord as EFalse + //increment songCount if id exist in AbstractAlbum table, otherwise do nothing. + + //only Genre, AbstractAlbum are not case sensitive + TBool caseSensitive = ETrue; + if ((aCategory == EMPXGenre) || (aCategory == EMPXAbstractAlbum)) + caseSensitive = EFalse; + + if (aCategory == EMPXAbstractAlbum) + { + id = iDbAbstractAlbum->AddItemL(aUri, aName, aAlbumArtist, aDriveId, newRecord, caseSensitive); + } + else + { + id = DbCategoryL(aCategory)->AddItemL(aName, aDriveId, newRecord, caseSensitive); +#else + TUint32 id(DbCategoryL(aCategory)->AddItemL(aName, aDriveId, newRecord, (aCategory != EMPXGenre))); +#endif // ABSTRACTAUDIOALBUM_INCLUDED + + if (newRecord && aItemChangedMessages) + { + MPXDbCommonUtil::AddItemChangedMessageL(*aItemChangedMessages, id, EMPXItemInserted, + aCategory, KDBPluginUid); + } + // when the added item's category is Genre or Composer, + // and it is NOT a new record, + // we should send the item number changed message + else if ( ( aCategory == EMPXGenre || aCategory == EMPXComposer ) && + !newRecord && aItemChangedMessages ) + { + MPXDbCommonUtil::AddItemChangedMessageL(*aItemChangedMessages, id, EMPXItemModified, + aCategory, KDBPluginUid); + } + aItemExist = !newRecord; +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + } +#endif // ABSTRACTAUDIOALBUM_INCLUDED + MPX_PERF_END(CMPXDbHandler_AddCategoryItemL); + return id; + } + +TUint32 CMPXDbHandler::AddCategoryItemL( + TMPXGeneralCategory aCategory, + const TDesC& aName, + const TDesC& aArtistName, + const TDesC& aArt, + TInt aDriveId, + CMPXMessageArray* aItemChangedMessages, + TBool& aItemExist) + { + MPX_FUNC("CMPXDbHandler::AddCategoryItemL()"); + + MPX_PERF_START(CMPXDbHandler_AddCategoryItemL); + + TBool newRecord(EFalse); + + TUint32 id = 0; + if(aCategory == EMPXAlbum) + { + id = iDbAlbum->AddItemL(aName, aArtistName, aArt, aDriveId, newRecord, (aCategory != EMPXGenre)); + } + else + { + id = iDbArtist->AddItemL(aName, aArt, aDriveId, newRecord, (aCategory != EMPXGenre)); + } + + if (newRecord && aItemChangedMessages) + { + MPXDbCommonUtil::AddItemChangedMessageL(*aItemChangedMessages, id, EMPXItemInserted, + aCategory, KDBPluginUid); + } + // when the added item's category is Artist, and it is NOT a new record, + // we should send the item number changed message + else if ( aCategory == EMPXArtist && + !newRecord && aItemChangedMessages ) + { + MPXDbCommonUtil::AddItemChangedMessageL(*aItemChangedMessages, id, EMPXItemModified, + aCategory, KDBPluginUid); + } + aItemExist = !newRecord; + MPX_PERF_END(CMPXDbHandler_AddCategoryItemL); + + return id; + } + +void CMPXDbHandler::UpdateCategoryItemL( + TMPXGeneralCategory aCategory, + TUint32 aCategoryId, + const CMPXMedia& aMedia, + TInt aDrive, + CMPXMessageArray* aItemChangedMessages) + { + switch(aCategory) + { + case EMPXAlbum: + iDbAlbum->UpdateItemL(aCategoryId, aMedia, aDrive, aItemChangedMessages); + break; + + case EMPXArtist: + iDbArtist->UpdateItemL(aCategoryId, aMedia, aDrive, aItemChangedMessages); + break; + + default: + DbCategoryL(aCategory)->UpdateItemL(aCategoryId, aMedia, aDrive, aItemChangedMessages); + break; + } + } +// ---------------------------------------------------------------------------- +// CMPXDbHandler::DeleteSongForCategoryL +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::DeleteSongForCategoryL( + TMPXGeneralCategory aCategory, + TUint32 aCategoryId, + TInt aDriveId, + CMPXMessageArray* aItemChangedMessages, + TBool& aItemExist) + { + MPX_FUNC("CMPXDbHandler::DeleteSongForCategoryL"); + DbCategoryL(aCategory)->DecrementSongsForCategoryL(aCategoryId, aDriveId, + aItemChangedMessages, aItemExist); + } + +// ---------------------------------------------------------------------------- +// CMPXDbHandler::HandlePlayCountModifiedL +// ---------------------------------------------------------------------------- +// +void CMPXDbHandler::HandlePlayCountModifiedL( + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::HandlePlayCountModifiedL"); + + TUint32 plId(iAutoPlaylist->AutoPlaylistIdL(EMPXMostPlayedPlaylist)); + + MPXDbCommonUtil::AddItemChangedMessageL(aItemChangedMessages, plId, EMPXItemModified, + EMPXSong, KDBPluginUid, plId); + + // Force the deprecated ID attribute + aItemChangedMessages[aItemChangedMessages.Count() - 1]-> + SetTObjectValueL(KMPXMessageMediaDeprecatedId, plId); + } + +// ---------------------------------------------------------------------------------------------------------- +// CMPXDbHandler::HandlePlaybackTimeModifiedL +// ---------------------------------------------------------------------------------------------------------- +// +void CMPXDbHandler::HandlePlaybackTimeModifiedL( + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbHandler::HandlePlaybackTimeModifiedL"); + + TUint32 plId(iAutoPlaylist->AutoPlaylistIdL(EMPXRecentlyPlayedPlaylist)); + + MPXDbCommonUtil::AddItemChangedMessageL(aItemChangedMessages, plId, EMPXItemModified, + EMPXSong, KDBPluginUid, plId); + + // Force the deprecated ID attribute + aItemChangedMessages[aItemChangedMessages.Count() - 1]-> + SetTObjectValueL(KMPXMessageMediaDeprecatedId, plId); + } + + +// --------------------------------------------------------------------------- +// CMPXDbHandler::IsRemoteDrive +// --------------------------------------------------------------------------- +// +TBool CMPXDbHandler::IsRemoteDrive(TDriveNumber aDrive) + { + return iDbManager->IsRemoteDrive(aDrive); + } + +TInt CMPXDbHandler::HandlePlaylistDurationL(TUint32 aPlaylistId) + { + return GetPlaylistDurationL(aPlaylistId); + } +void CMPXDbHandler::HandlePlaylistInfoL( + TUint32 aPlaylistId, + TInt& aCount, + TInt& aDuration) + { + MPX_FUNC("CMPXDbHandler::HandlePlaylistInfoL"); + MPX_DEBUG2("CMPXDbHandler::HandlePlaylistInfoL(0x%x)", aPlaylistId); + + RArray attributes; + CleanupClosePushL(attributes); + attributes.AppendL(KMPXMediaGeneralId); + attributes.AppendL(TMPXAttribute(KMPXMediaIdGeneral, EMPXMediaGeneralDuration)); + + CMPXMediaArray* mediaArray = CMPXMediaArray::NewL(); + CleanupStack::PushL(mediaArray); + + GetPlaylistSongsL(aPlaylistId, attributes.Array(), *mediaArray); + + aCount = mediaArray->Count(); + for (TInt index = 0; index < aCount; ++index) + { + CMPXMedia* media((*mediaArray)[index]); + if (media->IsSupported(KMPXMediaGeneralDuration)) + { + aDuration += media->ValueTObjectL(KMPXMediaGeneralDuration); + } + } + + CleanupStack::PopAndDestroy(mediaArray); + CleanupStack::PopAndDestroy(&attributes); + } + +TInt CMPXDbHandler::HandleGetAlbumsCountForArtistL(TUint32 aArtistId) + { + return iDbAlbum->GetAlbumsCountForArtistL(aArtistId); + } + +TBool CMPXDbHandler::HandleIsUnknownArtistL(TUint32 aArtistId) + { + return iDbArtist->IsUnknownArtistL(aArtistId); + } + +// --------------------------------------------------------------------------- +// CMPXDbHandler::HandleArtistForAlbumL +// --------------------------------------------------------------------------- +// +HBufC* CMPXDbHandler::HandleArtistForAlbumL(const TUint32 aAlbumId) + { + + TUint32 artistId = iDbMusic->ArtistForAlbumL(aAlbumId); + HBufC* artistname = GetNameMatchingIdL(artistId); + return artistname; + } + +// --------------------------------------------------------------------------- +// CMPXDbHandler::HandleAlbumartForAlbumL +// --------------------------------------------------------------------------- +// +HBufC* CMPXDbHandler::HandleAlbumartForAlbumL(const TUint32 aAlbumId, TPtrC aArt) + { + return iDbMusic->AlbumartForAlbumL(aAlbumId, aArt); + } +#ifdef ABSTRACTAUDIOALBUM_INCLUDED +// ---------------------------------------------------------------------------------------------------------- +// CMPXDbHandler::HandleGetAlbumNameForSongL +// ---------------------------------------------------------------------------------------------------------- +// +HBufC* CMPXDbHandler::HandleGetAlbumNameFromIdL(TUint32 aId) + { + return iDbAbstractAlbum->GetUriL(aId); + } +#endif // ABSTRACTAUDIOALBUM_INCLUDED +// End of file