diff -r 14979e23cb5e -r 3de6c4cf6b67 mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbhgplugin/src/mpxdbplugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbhgplugin/src/mpxdbplugin.cpp Wed Sep 01 12:32:02 2010 +0100 @@ -0,0 +1,4491 @@ +/* +* Copyright (c) 2006 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: Implementation of collection DB Plugin interface +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RD_MULTIPLE_DRIVE +#include +#endif //RD_MULTIPLE_DRIVE + +#include "mpxresource.h" +#include "mpxdbcommondef.h" +#include "mpxdbcommonutil.h" + +#include "mpxdbhandler.h" +#include "mpxdbutil.h" +#include "mpxcollectiondbdef.h" +#include "mpxdbplugin.h" + +// CONSTANTS +_LIT(KMPlayerDbPluginMbmFile, "mpxdbhgplugin.mif"); +const TInt KFirstFetchCount = 400; + +const TUid KCRUIDMusicPlayerFeatures = { 0x101FFCD0 }; +const TInt KMusicPlayerFeatures = 1; +const TInt KDisablePodcasting = 0x08; + +const TInt KIncrementalDeleteCount = 400; + +const TInt KSQLErrGeneral = -311; // SQL General error. Don't want to include sql header here +// ============================ MEMBER FUNCTIONS ============================== + +// ---------------------------------------------------------------------------- +// Two-phased constructor. +// ---------------------------------------------------------------------------- +// +CMPXDbPlugin* CMPXDbPlugin::NewL( + TAny* /*aInitParams*/) + { + MPX_FUNC("CMPXDbPlugin::NewL"); + + CMPXDbPlugin* self = new (ELeave) CMPXDbPlugin(); + CleanupStack::PushL (self); + self->ConstructL (); + CleanupStack::Pop (self); + return self; + } + +// ---------------------------------------------------------------------------- +// Destructor. +// ---------------------------------------------------------------------------- +// +CMPXDbPlugin::~CMPXDbPlugin() + { + MPX_FUNC("CMPXDbPlugin::~CMPXDbPlugin"); + + iSelections.Reset(); + iSelections.Close(); + iFs.Close(); + delete iDbHandler; + delete iDrmMediaUtility; + if (iResource) + { + iResource->Release(); + } + iMusicLibraryMenuIds.Close(); + delete iMusicLibraryMenuTitles; + delete iMusicLibraryTitles; + delete iAllSongsForArtistTitle; + delete iMusicMenuTitle; + + if (iActiveTask) + { + iActiveTask->Cancel(); + delete iActiveTask; + } + } + +// ---------------------------------------------------------------------------- +// Constructor. +// ---------------------------------------------------------------------------- +// +CMPXDbPlugin::CMPXDbPlugin() + { + MPX_FUNC("CMPXDbPlugin::CMPXDbPlugin"); + } + +// ---------------------------------------------------------------------------- +// Symbian 2nd phase constructor can leave. +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::ConstructL() + { + MPX_FUNC("CMPXDbPlugin::ConstructL"); + iFirstDeleteStep = ETrue; + User::LeaveIfError(iFs.Connect()); + iDrmMediaUtility = CMPXDrmMediaUtility::NewL(); + + TParse parse; + parse.Set( KMPXCollectionDbResourceFile, &KDC_APP_RESOURCE_DIR, NULL ); + TFileName resFile(parse.FullName()); + User::LeaveIfError(MPXUser::CompleteWithDllPath(resFile)); + BaflUtils::NearestLanguageFile(iFs, resFile); + iResource = CMPXResource::NewL(resFile); + + iDbHandler = CMPXDbHandler::NewL(iFs, *iResource); + iMusicLibraryMenuTitles = iResource->ReadMenuArrayL(R_MC_MENU_ITEMS_ARRAY, iMusicLibraryMenuIds); + iMusicLibraryTitles = iResource->ReadMenuArrayL(R_MC_TITLE_ITEMS_ARRAY, iMusicLibraryMenuIds ); + iAllSongsForArtistTitle = iResource->ReadHBufCL(R_MC_ALL_SONGS_FOR_ARTIST); + +#ifdef __ENABLE_MUSIC_TEXT_ALIGNMENT + iMusicMenuTitle = iResource->ReadHBufCL(R_MPX_QTN_MP_TITLE_MY_MUSIC_MENU_NSERIES); +#else + iMusicMenuTitle = iResource->ReadHBufCL(R_MPX_QTN_MUS_TITLE_MUSIC_MENU); +#endif // __ENABLE_MUSIC_TEXT_ALIGNMENT + + + iActiveTask = CMPXDbActiveTask::NewL(*this); + + CRepository* cenrep(NULL); + TRAPD( err, cenrep = CRepository::NewL( KCRUIDMusicPlayerFeatures ) ); + if( err == KErrNone ) + { + TInt val(0); + cenrep->Get( KMusicPlayerFeatures, val ); + iDisablePodcasting = val&KDisablePodcasting ? ETrue:EFalse; + delete cenrep; + } + else + { + iDisablePodcasting = EFalse; + } + iAllSongsValid = ETrue; + } + +// ---------------------------------------------------------------------------- +// Navigates to the given path +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::OpenL( + const CMPXCollectionPath& aPath, + const TArray& /*aAttrs*/, + CMPXFilter* aFilter) + { + MPX_FUNC("CMPXDbPlugin::OpenL"); + MPX_DEBUG_PATH(aPath); + //Create a path object to be returned. + CMPXCollectionPath* path = CMPXCollectionPath::NewL(aPath); + CleanupStack::PushL(path); + RArray openAttrs; + CleanupClosePushL(openAttrs); + + RArray supportedIds; + CleanupClosePushL(supportedIds); + + // Replace the attributes requested by the client with the ones below. + // This will eventually have to be fixed + SetAttributesL(aPath, openAttrs, supportedIds); + + CMPXMedia* entries = CMPXMedia::NewL(supportedIds.Array()); + CleanupStack::PopAndDestroy(&supportedIds); + CleanupStack::PushL(entries); + //Add returned path into media + entries->SetTObjectValueL(KMPXMediaGeneralValue, (TInt)path); + + TInt error(KErrNone); + TBool isASong(EFalse); + CMPXCollectionPath* newPath(NULL); + + // Make sure we handle open the correct open mode + // + TMPXOpenMode openmode = aPath.OpenNextMode(); + switch (openmode) + { + case EMPXOpenGroupOrPlaylist: + { + // Open By Path + MPX_TRAP(error, isASong = DoOpenL(aPath, openAttrs.Array(), *entries, aFilter)); + break; + } + + case EMPXOpenPlaylistOnly: + { + if (aPath.Count() > 0) + { + // Try to open + MPX_TRAP(error, newPath = DoOpenPlaylistL(aPath, openAttrs.Array())); + CleanupStack::PushL(newPath); + isASong = ETrue; + } + else // no items + { + MPX_TRAP(error, isASong = DoOpenL(aPath, openAttrs.Array(), *entries, aFilter)); + } + + break; + } + + default: + // do nothing + break; + } + + // generate the callback + if (isASong ) + { + if (openmode == EMPXOpenGroupOrPlaylist) + { + iObs->HandleOpen(const_cast(&aPath), error); + } + else // openmode == EMPXOpenPlaylistOnly + { + iObs->HandleOpen(newPath, error); + } + } + else + { + entries->SetCObjectValueL(KMPXMediaGeneralContainerPath, + const_cast(&aPath)); + entries->Delete(KMPXMediaGeneralValue); + iObs->HandleOpen(entries, path, error); + } + + if (newPath) + { + CleanupStack::PopAndDestroy(newPath); + } + + CleanupStack::PopAndDestroy(entries); + CleanupStack::PopAndDestroy(&openAttrs); + CleanupStack::PopAndDestroy(path); + } + +// ---------------------------------------------------------------------------- +// Get the extended properties of the current file (async) +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::MediaL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + const TArray& /*aCaps*/, + CMPXAttributeSpecs* /*aSpecs*/) + { + MPX_FUNC("CMPXDbPlugin::MediaL"); + MPX_DEBUG_PATH(aPath); + + RArray supportedIds; + CleanupClosePushL(supportedIds); + if (aPath.Selection().Count()) + { + // it's a container if there are multiple selection, else it's not a container + supportedIds.AppendL(KMPXMediaIdContainer); + } + MPXDbCommonUtil::FillInSupportedUIDsL(aAttrs, supportedIds); + + CMPXMedia* entries = CMPXMedia::NewL(supportedIds.Array()); + CleanupStack::PopAndDestroy(&supportedIds); + CleanupStack::PushL(entries); + + DoMediaL(aPath, aAttrs, *entries); + + // Also fetch collection details and set the path if required + DoHandleOtherMediaAttributesL(aAttrs, aPath, *entries); + + iObs->HandleMedia(entries, KErrNone); + CleanupStack::PopAndDestroy(entries); + } + +// ---------------------------------------------------------------------------- +// Cancel outstanding request +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::CancelRequest() + { + MPX_FUNC("CMPXDbPlugin::CancelRequest"); + iActiveTask->Cancel(); + } + +// ---------------------------------------------------------------------------- +// Executes the given command on the collection +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::CommandL( + TMPXCollectionCommand aCmd, + TInt aArg /* = 0 */) + { + MPX_FUNC("CMPXDbPlugin::CommandL"); + MPX_DEBUG2("CMPXDbPlugin::CommandL %d", aCmd); + iAllSongsValid = ETrue; + switch (aCmd) + { + case EMcCmdRemoveAll: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - EMcCmdRemoveAll"); + // Remove EVERYthing from the collection + iDbHandler->RemoveEntireCollectionL(); + break; + } + case EMcCmdClose: + // called before destructing this plug-in: no actions required + break; + case EMcCloseCollection: + { + MPX_DEBUG2("CMPXDbPlugin::CommandL - EMcCloseCollection %d", aArg); + // Close the specified database + TRAP_IGNORE(iDbHandler->PreCloseCollectionL()); + #ifdef RD_MULTIPLE_DRIVE + MPX_DEBUG1("Multiple drives closing databases"); + if ( aArg <0) + { + DriveInfo::TDriveArray driveArray; + User::LeaveIfError ( DriveInfo::GetUserVisibleDrives( iFs, driveArray)); + TInt count( driveArray.Count ()); + for (TInt i=0; iIsRemoteDrive(static_cast(driveArray[i])))) + { + MPX_DEBUG2("Closing database %i", driveArray[i]); + TRAP_IGNORE( iDbHandler->CloseDatabaseL( driveArray[i] ) ); + } + } + } + else + { + TRAP_IGNORE( iDbHandler->CloseDatabaseL(aArg) ); //Closing can fail if physical media has been removed or forced disk dismount has occurred. + } + #else + iDbHandler->CloseDatabaseL(aArg); + #endif // RD_MULTIPLE_DRIVE + break; + } + case EMcReOpenCollection: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - EMcReOpenCollection"); + // Open the specified database +#ifdef RD_MULTIPLE_DRIVE + MPX_DEBUG1("Multiple drives opening databases"); + DriveInfo::TDriveArray driveArray; + User::LeaveIfError( DriveInfo::GetUserVisibleDrives( iFs, driveArray ) ); + TInt count( driveArray.Count() ); + for( TInt i=0; iIsRemoteDrive(static_cast(driveArray[i])))) + { + TUint driveStatus(0); + User::LeaveIfError( DriveInfo::GetDriveStatus( + iFs, driveArray[i], driveStatus ) ); + if( driveStatus & DriveInfo::EDrivePresent ) + { + MPX_DEBUG2("Opening database %i", driveArray[i]); + TRAP_IGNORE( iDbHandler->OpenDatabaseL( driveArray[i] ) ); + } + } + } +#else + iDbHandler->OpenDatabaseL(aArg); +#endif // RD_MULTIPLE_DRIVE + break; + } + case EMcRefreshStarted: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - EMcRefreshStarted"); + iDbHandler->CheckDiskSpaceOnDrivesL(); + // ask the handler to start a transaction + iDbHandler->RefreshStartL(); + iRefreshing=ETrue; + break; + } + case EMcRefreshEnded: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - EMcRefreshEnded"); + // ask the handler to finalize the transaction + iDbHandler->RefreshEndL(); + iRefreshing=EFalse; + break; + } + case EMcCmdReCreateDB: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - EMcCmdReCreateDB"); + // Recreate all databases + iDbHandler->ReCreateDatabasesL(); + break; + } + case EMcCmdDbCorrupted: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - EMcCmdDbCorrupted"); + iDbHandler->SetDBCorruptedL(ETrue); + break; + } + case EMcCmdRefresh: + case EMcCmdCollectionInit: + case EMcCmdCollectionResyn: + { + // deprecated + break; + } + case EMcCmdMtpStart: + iDbHandler->CheckDiskSpaceOnDrivesL(); + iMtpInUse = ETrue; + iDbHandler->MtpStartL(); + break; + case EMcCmdMtpEnd: + iMtpInUse = EFalse; + iDbHandler->MtpEndL(); + break; + default: + { + User::Leave(KErrNotSupported); + } + } + } + +// ---------------------------------------------------------------------------- +// Executes the given command on the collection +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::CommandL( + CMPXCommand& aCmd) + { + MPX_FUNC("CMPXDbPlugin::CommandL"); + + if (!aCmd.IsSupported(KMPXCommandGeneralId)) + { + User::Leave(KErrArgument); + } + + TMPXCommandId commandId = aCmd.ValueTObjectL(KMPXCommandGeneralId); + + TBool syncOp(EFalse); + if (aCmd.IsSupported(KMPXCommandGeneralDoSync)) + { + syncOp = aCmd.ValueTObjectL(KMPXCommandGeneralDoSync); + } + + // Handle this operation synchronously or asynchronously + // + if (!syncOp) + { + iActiveTask->StartL(commandId, aCmd); + } + else // Sync operation + { + switch (commandId) + { + case KMPXCommandIdCollectionRetrieveUriForDeletion: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdCollectionRetrieveUriForDeletion"); + DoRetrieveUriForDeletionL(aCmd); + break; + } + case KMPXCommandIdCollectionRemove: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdCollectionRemove"); + if ( !iDbHandler->InTransaction() ) + { + iDbHandler->BeginTransactionL(); + } + + if (iFirstDeleteStep ) + { + iFirstDeleteStep = EFalse; + } + DoRemovePathL(aCmd); + break; + } + case KMPXCommandIdCollectionRemoveMedia: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdCollectionRemoveMedia"); + DoRemoveMediaL(aCmd); + break; + } + case KMPXCommandIdCollectionCleanupDeletedMedias: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdCollectionCleanupDeletedMedias"); + CleanupDeletedRecordsL(aCmd); + break; + } + case KMPXCommandIdCollectionAdd: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdCollectioAdd"); + CMPXMedia* media = aCmd.Value(KMPXCommandColAddMedia); + User::LeaveIfNull( media ); + TUint32 id(DoAddL(*media)); + aCmd.SetTObjectValueL(KMPXCommandColAddRtnId, id); + break; + } + case KMPXCommandIdCollectionSet: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdCollectionSet"); + CMPXMedia* media = aCmd.Value(KMPXCommandColSetMedia); + User::LeaveIfNull( media ); + DoSetL(*media); + break; + } + case KMPXCommandIdCollectionCompleteDelete: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdCollectionCompleteDelete"); + DoHandleDeleteCompleteL(aCmd); + break; + } + case KMPXCommandIdReorderPlaylist: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdReorderPlaylist"); + DoReorderPlaylistL(aCmd); + break; + } + case KMPXCommandIdUpdateRefreshTime: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdUpdateRefreshTime"); + TTime curTime; + curTime.HomeTime(); + iDbHandler->SetLastRefreshedTimeL(curTime); + break; + } + case KMPXCommandCollectionGetCount: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandCollectionGetCount"); + DoGetCollectionCountL(aCmd); + break; + } + case KMPXCommandCollectionGetURIs: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandCollectionGetURIs"); + DoGetCollectionUriL(aCmd); + break; + } + default: + { + User::Leave(KErrNotSupported); + } + } + } + } + +// ---------------------------------------------------------------------------- +// Adds an item (song or playlist) to the collection +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::AddL( + const CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbPlugin::AddL"); + DoAddL(aMedia); + } + +// ---------------------------------------------------------------------------- +// Remove an item from the collection database using the given path +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::RemoveL( + const CMPXCollectionPath& aPath) + { + MPX_FUNC("CMPXDbPlugin::RemoveL(by path)"); + MPX_DEBUG_PATH(aPath); + + CMPXMessageArray* msgAry = CMPXMessageArray::NewL(); + CleanupStack::PushL(msgAry); + + // Return file path for deleted item(s) + CDesCArray* fp = DoRemoveL(aPath, *msgAry); + + iObs->HandleRemove(*fp, KErrNone); + delete fp; + + // Send Change Messages + iActiveTask->SetVisibleChange(CMPXDbActiveTask::EAllVisible); + DoHandleChangeL(msgAry); + CleanupStack::PopAndDestroy(msgAry); + } + +// ---------------------------------------------------------------------------- +// Remove an item from the collection database using the given media properties +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::RemoveL( + const CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbPlugin::RemoveL(by media)"); + DoRemoveL(aMedia, EFalse); + } + +// ---------------------------------------------------------------------------- +// Sets/updates the media for an item in the collection +// DEPRECATED for week 18 +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::SetL( + const CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbPlugin::SetL"); + DoSetL(aMedia); + } + +// ---------------------------------------------------------------------------- +// Find the items matching the media specifications +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::FindAllL( + const CMPXMedia& aCriteria, + const TArray& aAttrs) + { + MPX_FUNC("CMPXDbPlugin::FindAllL"); + + CMPXMedia* entries = FindAllSyncL(aCriteria, aAttrs); + + // notify client. if FindAllL leaves, framework will notify client of the error + iObs->HandleFindAll(entries, KErrNone); + delete entries; + } + +// ---------------------------------------------------------------------------- +// Find the items matching the media specifications +// ---------------------------------------------------------------------------- +// +CMPXMedia* CMPXDbPlugin::FindAllSyncL( + const CMPXMedia& aCriteria, + const TArray& aAttrs) + { + MPX_FUNC("CMPXDbPlugin::FindAllSyncL"); + + CMPXMedia* entries = iDbHandler->FindAllLC(aCriteria, aAttrs); + + if (entries) + { + CMPXMediaArray* ary = entries->Value(KMPXMediaArrayContents); + User::LeaveIfNull( ary ); + DoSetDrmForArrayL( *ary, aAttrs ); + } + + CleanupStack::Pop(entries); + return entries; + } + +// ---------------------------------------------------------------------------- +// Get the list of supported capabilities +// ---------------------------------------------------------------------------- +// +TCollectionCapability CMPXDbPlugin::GetCapabilities() + { + // This one supports simple search + return EMcSearch; + } + +// ---------------------------------------------------------------------------- +// Get the list of supported capabilities +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::HandleStepL() + { + MPX_FUNC("CMPXDbPlugin::HandleStepL"); + + TBool done(ETrue); + + switch (iActiveTask->GetTask()) + { + case KMPXCommandIdCollectionSet: + { + done = DoSetAsyncL(); + break; + } + case KMPXCommandIdCollectionAdd: + { + done = DoAddAsyncL(); + break; + } + case KMPXCommandIdCollectionRemove: + { + DoRemovePathL(iActiveTask->GetCommand()); + done = ETrue; + break; + } + case KMPXCommandIdCollectionRemoveMedia: + { + DoRemoveMediaL(iActiveTask->GetCommand()); + done = ETrue; + break; + } + case KMPXCommandIdCollectionRetrieveUriForDeletion: + { + DoRetrieveUriForDeletionL(iActiveTask->GetCommand()); + done = ETrue; + break; + } + case KMPXCommandIdCollectionCleanupDeletedMedias: + { + CleanupDeletedRecordsL(iActiveTask->GetCommand()); + done = ETrue; + break; + } + case KMPXCommandIdCollectionCompleteDelete: + { + DoHandleDeleteCompleteL( iActiveTask->GetCommand() ); + break; + } + case KMPXCommandIdUpdateRefreshTime: + { + MPX_DEBUG1("CMPXDbPlugin::CommandL - KMPXCommandIdUpdateRefreshTime"); + TTime curTime; + curTime.HomeTime(); + iDbHandler->SetLastRefreshedTimeL(curTime); + break; + } + case KMPXCommandIdIncrementalOpenL: + { + DoIncrementalOpenL( iActiveTask->GetCommand() ); + done = ETrue; + break; + } + default: + { + // Should never happen! + ASSERT(0); + break; + } + } + return done; + } + +// ---------------------------------------------------------------------------- +// Handler for async operations completed +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::HandleOperationCompleted( + TInt aErr) + { + MPX_FUNC("CMPXDbPlugin::HandleOperationCompleted"); + TRAP_IGNORE(DoHandleOperationCompletedL(aErr)); + } + +// ---------------------------------------------------------------------------- +// Process the OpenL command +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoOpenL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries, + CMPXFilter* aFilter ) + { + MPX_FUNC("CMPXDbPlugin::DoOpenL"); + + TInt err( KErrNone ); + CMPXMediaArray* array = CMPXMediaArray::NewL(); + CleanupStack::PushL(array); + + TInt levels(aPath.Levels()); + TBool isASong(EFalse); + + + if ( 1 == levels ) + { + + // Redirecting all open requests at level 1 to open albums + // due to UI changes that removed the library menu collection level. + TInt acount = array->Count(); + MPX_DEBUG2(" array count11 [%d]", acount); + + CMPXCollectionPath* path = CMPXCollectionPath::NewL(aPath); + CleanupStack::PushL( path ); + + path->AppendL(3); // Albums + TInt whatLevel = path->Levels(); + + MPX_DEBUG_PATH(*path); + + aEntries.SetTObjectValueL(KMPXMediaGeneralId, path->Id(whatLevel - 1) ); + + // Create a media which hold the pointer to the returned path + if (aEntries.IsSupported(KMPXMediaGeneralValue)) + { + MPX_DEBUG1(" pointer to the returned path "); + CMPXMedia* pMedia = CMPXMedia::NewL(); + CleanupStack::PushL(pMedia); + pMedia->SetTObjectValueL(KMPXMediaGeneralValue, + aEntries.ValueTObjectL(KMPXMediaGeneralValue)); + array->AppendL(*pMedia); + CleanupStack::PopAndDestroy(pMedia); + } + + + RArray openAttrs; + CleanupClosePushL(openAttrs); + + RArray supportedIds; + CleanupClosePushL(supportedIds); + + SetAttributesL(*path, openAttrs, supportedIds); + openAttrs.AppendL(KMPXMediaArrayContents); + + CleanupStack::PopAndDestroy(&supportedIds); + + if( iAllSongsValid ) + { + isASong = DoOpenBrowseAlbumL( *path, openAttrs.Array(), aEntries, array ); + } + CleanupStack::PopAndDestroy(&openAttrs); + CleanupStack::PopAndDestroy( path ); + + //Remove the first media + if ( array->Count() && + (*array)[0]->IsSupported(KMPXMediaGeneralValue)) + { + array->Remove(0); + } + } + else if (levels >= 2) + { + aEntries.SetTObjectValueL(KMPXMediaGeneralId, aPath.Id(levels - 1)); + // Create a media which hold the pointer to the returned path + if (aEntries.IsSupported(KMPXMediaGeneralValue)) + { + CMPXMedia* pMedia = CMPXMedia::NewL(); + CleanupStack::PushL(pMedia); + pMedia->SetTObjectValueL(KMPXMediaGeneralValue, + aEntries.ValueTObjectL(KMPXMediaGeneralValue)); + array->AppendL(*pMedia); + CleanupStack::PopAndDestroy(pMedia); + MPX_ASSERT(array->Count()==1); + } + + // check the browse type + switch (aPath.Id(1).iId2) + { + case EBrowseAll: + { + TBool doIncremental(ETrue); + if( aFilter && aFilter->IsSupported( KMPXCollectionOpenLSupportsIncremental ) ) + { + doIncremental = + aFilter->ValueTObjectL(KMPXCollectionOpenLSupportsIncremental); + } + + if( doIncremental ) + { + TRAP( err, isASong = DoOpenIncrementalL( aPath, aAttrs, aEntries, array ) ); + } + else + { + TRAP( err, isASong = DoOpenBrowseAllL(aPath, aAttrs, aEntries, array) ); + } + break; + } + + case EBrowseArtist: + { + if( iAllSongsValid ) + { + isASong = DoOpenBrowseArtistL( aPath, aAttrs, aEntries, array ); + } + break; + } + + case EBrowseAlbum: + { + if( iAllSongsValid ) + { + isASong = DoOpenBrowseAlbumL( aPath, aAttrs, aEntries, array ); + } + break; + } + + case EBrowsePlaylist: + { + if( iAllSongsValid ) + { + isASong = DoOpenBrowsePlaylistL(aPath, aAttrs, aEntries, array); + } + + break; + } + + case EBrowseGenre: + { + if( iAllSongsValid ) + { + isASong = DoOpenBrowseGenreL( aPath, aAttrs, aEntries, array ); + } + break; + } + + case EBrowseComposer: + { + if( iAllSongsValid ) + { + isASong = DoOpenBrowseComposerL( aPath, aAttrs, aEntries, array ); + } + break; + } + + default: + { + User::Leave(KErrArgument); + } + } + //Remove the first media + if ( array->Count() && + (*array)[0]->IsSupported(KMPXMediaGeneralValue)) + { + array->Remove(0); + } + } + else + { + User::Leave(KErrNotSupported); + } + aEntries.SetCObjectValueL(KMPXMediaArrayContents, array); + aEntries.SetTObjectValueL(KMPXMediaArrayCount, array->Count()); + + CleanupStack::PopAndDestroy(array); + + if( err == KSQLErrGeneral ) + { + iAllSongsValid = EFalse; + User::Leave( KErrDiskFull ); + } + else if( err != KErrNone ) + { + User::Leave( err ); + } + return isASong; + } + + +// ---------------------------------------------------------------------------- +// CMPXDbPlugin::DoOpenIncrementalL +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoOpenIncrementalL( const CMPXCollectionPath& aPath, const TArray& aAttrs, + CMPXMedia& aEntries, CMPXMediaArray* aArray) + { + TBool isASong(EFalse); + + TInt levels(aPath.Levels()); + + if( levels == 2 ) + { + // Remove the pPath dummy from the array + TInt pPath = aEntries.ValueTObjectL(KMPXMediaGeneralValue); + aArray->Remove(0); + CMPXCollectionPath* p = (CMPXCollectionPath*) pPath; + + RArray ids; + CleanupClosePushL( ids ); + + iDbHandler->GetAllSongsLimitedL( aAttrs, *aArray, KFirstFetchCount ); + + TInt c( aArray->Count() ); + for( TInt i=0; iAtL(i)->ValueTObjectL( KMPXMediaGeneralId ); + ids.Append( id ); + } + + // Rest are all blank items + CMPXMedia* entry = CMPXMedia::NewL(); + CleanupStack::PushL(entry); + entry->SetTObjectValueL(KMPXMediaGeneralType, EMPXItem); + entry->SetTObjectValueL(KMPXMediaGeneralCategory, EMPXSong); + entry->SetTObjectValueL(KMPXMediaGeneralId, KMPXInvalidItemId ); + + TInt count = iDbHandler->NumberOfItemsL(EMPXSong); + count-=c; + for( TInt i=0; iAppendL( *entry ); + ids.Append( KMPXInvalidItemId ); + } + CleanupStack::PopAndDestroy( entry ); + + // Set the "Supportes incremental Command" flag + // + aEntries.SetTObjectValueL( KMPXCollectionOpenLSupportsIncremental, ETrue ); + + TMPXOpenDataBlock block; + block.iOffset=KErrNotFound; + block.iSize=count; + aEntries.SetTObjectValueL( KMPXCollectionOpenLResultRange, block ); + + SetMediaGeneralAttributesL(aEntries, EMPXGroup, EMPXSong, + iMusicLibraryTitles->MdcaPoint(EBrowseAll)); + + p->AppendL(ids.Array()); + CleanupStack::PopAndDestroy( &ids ); + } + else if( levels == 3 ) + { + iDbHandler->GetSongL(aPath.Id(levels - 1).iId2, aAttrs, *aArray); + isASong = ETrue; + } + + + return isASong; + } + +// ---------------------------------------------------------------------------- +// Handles OpenL called for EBrowseAll +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoOpenBrowseAllL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries, + CMPXMediaArray* aArray) + { + MPX_FUNC("CMPXDbPlugin::DoOpenBrowseAllL"); + + TInt levels(aPath.Levels()); + switch (levels) + { + // All songs + case 2: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseAllL_All); + + iDbHandler->GetAllSongsL(aArray, aAttrs); + SetMediaGeneralAttributesL(aEntries, EMPXGroup, EMPXSong, + iMusicLibraryTitles->MdcaPoint(EBrowseAll)); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseAllL_All); + break; + } + + // A Song in all songs + case 3: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseAllL_Song); + + iDbHandler->GetSongL(aPath.Id(levels - 1).iId2, aAttrs, *aArray); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseAllL_Song); + break; + } + + default: + { + MPX_DEBUG2("CMPXDbPlugin_DoOpenBrowseAllL: Invalid levels[%d]", levels); + User::Leave(KErrNotSupported); + } + } // end switch(levels) + + return (levels == 3); + } + +// ---------------------------------------------------------------------------- +// Handles OpenL called for EBrowseArtist +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoOpenBrowseArtistL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries, + CMPXMediaArray* aArray) + { + MPX_FUNC("CMPXDbPlugin::DoOpenBrowseArtistL"); + + TBool isASong(EFalse); + TInt levels(aPath.Levels()); + TInt idIndex(levels - 1); + + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + switch (levels) + { + // All artists + case 2: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseArtistL_All); + + iDbHandler->GetAllArtistsL(aAttrs, aArray); + SetMediaGeneralAttributesL(aEntries, EMPXGroup, EMPXArtist, + iMusicLibraryTitles->MdcaPoint(EBrowseArtist)); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseArtistL_All); + break; + } + + // All albums of an artist + case 3: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseArtistL_AllAlbums); + // get the albums + TInt id(aPath.Id(idIndex).iId2); + MPX_ASSERT(aArray->Count()); + MPX_ASSERT((*aArray)[0]->IsSupported(KMPXMediaGeneralValue)); + TInt pPath = (*aArray)[0]->ValueTObjectL(KMPXMediaGeneralValue); + MPX_ASSERT(pPath); + iDbHandler->GetAlbumsMatchingArtistL(id, aAttrs, *aArray); + SetMediaGeneralAttributesL(aEntries, EMPXItem, EMPXArtist, id); + + TInt count = aArray->Count(); + if ( count > 2 ) + { + // Only show "all" item if there is more than 1 album + // count for "all" item + TInt total = 0; + for ( TInt i = 1; i < count; i++ ) + { + TInt temp = (*aArray)[i]->ValueTObjectL(KMPXMediaGeneralCount); + total += temp; + } + // Add "all" item under an artist + MPXDbCommonUtil::PrependMediaL(*aArray, *iAllSongsForArtistTitle, EMPXItem, EMPXAlbum, + aPath.Id(idIndex), 0, 0, 1); + + (*aArray)[1]->SetTObjectValueL(KMPXMediaGeneralCount, total); + + TMPXItemId allId = ((*aArray)[1]->ValueTObjectL(KMPXMediaGeneralId)); + if (aArray->Count() > 2) + { // path media, all id and at least one media + ((CMPXCollectionPath*)pPath)->InsertL(allId, 0); + } + else + { // only has all item + ((CMPXCollectionPath*)pPath)->AppendL(allId); + } + } + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseArtistL_AllAlbums); + break; + } + + // All songs of an album for an artist or all songs for an artist + case 4: + { + // all songs for an artist + if (aPath.Id(3) == aPath.Id(2)) + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseArtistL_AllSongs); + + TInt id(aPath.Id(idIndex - 1).iId2); + iDbHandler->GetSongsMatchingArtistL(id, aAttrs, aArray); + SetMediaGeneralAttributesL(aEntries, EMPXItem, EMPXSong, id); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseArtistL_AllSongs); + } + // all songs of an album for an artist + else + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseArtistL_AllSongsForAlbum); + TUint32 artistId(aPath.Id(idIndex - 1).iId2); + + if (selections.Count()) + { + // Multiple albums + const TInt count(aPath.Selection().Count()); + for (TInt i = 0; i < count; ++i) + { + iDbHandler->GetSongsMatchingArtistAndAlbumL(artistId, selections[i].iId2, + aAttrs, aArray); + } + } + else + { + // One album + iDbHandler->GetSongsMatchingArtistAndAlbumL(artistId, aPath.Id(idIndex).iId2, + aAttrs, aArray); + } + + SetMediaGeneralAttributesL(aEntries, EMPXItem, EMPXAlbum, aPath.Id(idIndex).iId2); + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseArtistL_AllSongsForAlbum); + } + + MPX_DEBUG2("CMPXDbPlugin_DoOpenBrowseArtistL: retrieved %d items", aArray->Count()); + + break; + } + + // A Song in an album + case 5: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseArtistL_Song); + + iDbHandler->GetSongL(aPath.Id(idIndex).iId2, aAttrs, *aArray); + isASong = ETrue; + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseArtistL_Song); + break; + } + + default: + { + MPX_DEBUG2("CMPXDbPlugin_DoOpenBrowseArtistL: Invalid levels[%d]", levels); + User::Leave(KErrNotSupported); + } + } // end switch(level) + + CleanupStack::PopAndDestroy(&selections); + return isASong; + } + +// ---------------------------------------------------------------------------- +// Handles OpenL called for EBrowseAlbum +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoOpenBrowseAlbumL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries, + CMPXMediaArray* aArray) + { + MPX_FUNC("CMPXDbPlugin::DoOpenBrowseAlbumL"); + + TBool isASong(EFalse); + TInt levels(aPath.Levels()); + TInt idIndex(levels - 1); + + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + switch (levels) + { + // All Albums + case 2: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseAlbumL_All); + + TRAPD(err, iDbHandler->GetAllAlbumsL(aAttrs, aArray) ); + // in error case, return empty list and append empty id to path + // in order to increase one level + if ( err != KErrNone ) + { + TInt pPath(0); + if (aArray->Count()) + { + CMPXMedia* pMedia = (*aArray)[0]; + if (pMedia->IsSupported(KMPXMediaGeneralValue)) + { + pPath = pMedia->ValueTObjectL(KMPXMediaGeneralValue); + MPX_ASSERT(pPath); + } + } + + RArray ids; + CleanupClosePushL(ids); + + // Append ids to the returned path + if (pPath) + { + ((CMPXCollectionPath*)pPath)->AppendL(ids.Array()); + } + CleanupStack::PopAndDestroy(&ids); + } + + SetMediaGeneralAttributesL(aEntries, EMPXGroup, EMPXAlbum, + iMusicLibraryTitles->MdcaPoint(EBrowseAlbum)); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseAlbumL_All); + break; + } + + // All songs in one or multiple albums + case 3: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseAlbumL_AllSongs); + if (selections.Count()) + { + // Multiple albums + const TInt count(aPath.Selection().Count()); + for (TInt i = 0; i < count; ++i) + { + iDbHandler->GetSongsMatchingAlbumL(selections[i].iId2, aAttrs, aArray); + } + } + else + { + // One album + iDbHandler->GetSongsMatchingAlbumL(aPath.Id(idIndex).iId2, aAttrs, aArray); + } + + // added for ganes + SetMediaGeneralAttributesL(aEntries, EMPXItem, EMPXAlbum, iMusicLibraryTitles->MdcaPoint(EBrowseAlbumSong)); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseAlbumL_AllSongs); + break; + } + + // A song in an album + case 4: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseAlbumL_Song); + + iDbHandler->GetSongL(aPath.Id(idIndex).iId2, aAttrs, *aArray); + isASong = ETrue; + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseAlbumL_Song); + break; + } + + default: + { + MPX_DEBUG2("CMPXDbPlugin_DoOpenBrowseAlbumL: Invalid levels[%d]", levels); + User::Leave(KErrNotSupported); + } + } + + CleanupStack::PopAndDestroy(&selections); + return isASong; + } + +// ---------------------------------------------------------------------------- +// Handles OpenL called for EBrowsePlaylist +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoOpenBrowsePlaylistL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries, + CMPXMediaArray* aArray) + { + MPX_FUNC("CMPXDbPlugin::DoOpenBrowsePlaylistL"); + + TBool isASong(EFalse); + TInt levels(aPath.Levels()); + TInt idIndex(levels - 1); + + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + switch (levels) + { + case 2: + { + // All playlists + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowsePlaylistL_All); + + iDbHandler->GetAllPlaylistsL(aArray, aAttrs); + iDbHandler->GetAllSystemPlaylistNamesL(aArray); + + SetMediaGeneralAttributesL(aEntries, EMPXGroup, EMPXPlaylist, + iMusicLibraryTitles->MdcaPoint(EBrowsePlaylist)); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowsePlaylistL_All); + break; + } + + // All songs in a playlist + case 3: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowsePlaylistL_AllSongs); + + if (selections.Count()) + { + const TInt count(aPath.Selection().Count()); + for (TInt i = 0; i < count; ++i) + { + iDbHandler->GetSongsMatchingPlaylistL(selections[i].iId2, aAttrs, aArray); + } + } + else + { + iDbHandler->GetSongsMatchingPlaylistL(aPath.Id (idIndex).iId2, aAttrs, aArray); + } + + + SetMediaGeneralAttributesL(aEntries, EMPXItem, EMPXPlaylist, aPath.Id(idIndex).iId2); + + // populate EMPXMediaGeneralNonPermissibleActions + if (iDbHandler->IsAutoPlaylistL(aPath.Id(idIndex).iId2)) + { + // set non-permissible actions to not writable and cacheable + aEntries.SetTObjectValueL( + KMPXMediaGeneralNonPermissibleActions, (TMPXGeneralNonPermissibleActions)(EMPXWrite | EMPXCache)); + } + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowsePlaylistL_AllSongs); + break; + } + + // Specific song in a playlist + case 4: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowsePlaylistL_Song); + + iDbHandler->GetPlaylistSongL(aPath.Id(idIndex).iId2, aPath.Id(idIndex - 1).iId2, + aAttrs, *aArray); + isASong = ETrue; + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowsePlaylistL_Song); + break; + } + + default: + { + MPX_DEBUG2("CMPXDbPlugin_DoOpenBrowsePlaylistL: Invalid levels[%d]", levels); + User::Leave(KErrNotSupported); + } + } + + CleanupStack::PopAndDestroy(&selections); + return isASong; + } + +// ---------------------------------------------------------------------------- +// Handles OpenL called for EBrowseGenre +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoOpenBrowseGenreL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries, + CMPXMediaArray* aArray) + { + MPX_FUNC("CMPXDbPlugin::DoOpenBrowseGenreL"); + + TBool isASong(EFalse); + TInt levels(aPath.Levels()); + TInt idIndex(levels - 1); + + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + switch (levels) + { + // All genres + case 2: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseGenreL_All); + + iDbHandler->GetAllGenresL(aAttrs, aArray); + SetMediaGeneralAttributesL(aEntries, EMPXGroup, EMPXGenre, + iMusicLibraryTitles->MdcaPoint(EBrowseGenre)); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseGenreL_All); + break; + } + + // All songs of a genre + case 3: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseGenreL_AllSongs); + + if (selections.Count()) + { + const TInt count(aPath.Selection().Count()); + for (TInt i = 0; i < count; ++i) + { + iDbHandler->GetSongsMatchingGenreL(selections[i].iId2, aAttrs, aArray); + } + } + else + { + iDbHandler->GetSongsMatchingGenreL(aPath.Id(idIndex).iId2, aAttrs, aArray); + } + SetMediaGeneralAttributesL(aEntries, EMPXItem, EMPXGenre, aPath.Id(idIndex).iId2); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseGenreL_AllSongs); + break; + } + + // Specific song in a genre + case 4: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseGenreL_Song); + + iDbHandler->GetSongL(aPath.Id(idIndex).iId2, aAttrs, *aArray); + isASong = ETrue; + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseGenreL_Song); + break; + } + + default: + { + MPX_DEBUG2("CMPXDbPlugin_DoOpenBrowseGenreL: Invalid levels[%d]", levels); + User::Leave(KErrNotSupported); + } + } + + CleanupStack::PopAndDestroy(&selections); + return isASong; + } + +// ---------------------------------------------------------------------------- +// Handles OpenL called for EBrowseComposer +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoOpenBrowseComposerL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries, + CMPXMediaArray* aArray) + { + MPX_FUNC("CMPXDbPlugin::DoOpenBrowseComposerL"); + + TBool isASong(EFalse); + TInt levels(aPath.Levels()); + TInt idIndex(levels - 1); + + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + switch (levels) + { + // All composers + case 2: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseComposerL_All); + + iDbHandler->GetAllComposersL(aAttrs, aArray); + SetMediaGeneralAttributesL(aEntries, EMPXGroup, EMPXComposer, + iMusicLibraryTitles->MdcaPoint(EBrowseComposer)); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseComposerL_All); + break; + } + + // All songs of a composer + case 3: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseComposerL_AllSongs); + if (selections.Count()) + { + const TInt count(aPath.Selection().Count()); + for (TInt i = 0; i < count; ++i) + { + iDbHandler->GetSongsMatchingComposerL(selections[i].iId2, aAttrs, aArray); + } + } + else + { + iDbHandler->GetSongsMatchingComposerL(aPath.Id(idIndex).iId2, aAttrs, aArray); + } + SetMediaGeneralAttributesL(aEntries, EMPXItem, EMPXComposer, aPath.Id(idIndex).iId2); + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseComposerL_AllSongs); + break; + } + + // Specific song of a composer + case 4: + { + MPX_PERF_START(CMPXDbPlugin_DoOpenBrowseComposerL_Song); + + iDbHandler->GetSongL(aPath.Id(idIndex).iId2, aAttrs, *aArray); + isASong = ETrue; + + MPX_PERF_END(CMPXDbPlugin_DoOpenBrowseComposerL_Song); + break; + } + + default: + { + MPX_DEBUG2("CMPXDbPlugin_DoOpenBrowseComposerL: Invalid levels[%d]", levels); + User::Leave(KErrNotSupported); + } + } + + CleanupStack::PopAndDestroy(&selections); + return isASong; + } + +// ---------------------------------------------------------------------------- +// Process the OpenL method with open mode EMPXOpenPlaylistOnly +// ---------------------------------------------------------------------------- +// +CMPXCollectionPath* CMPXDbPlugin::DoOpenPlaylistL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs ) + { + MPX_FUNC("CMPXDbPlugin::DoOpenPlaylistL"); + + RArray ids; + CleanupClosePushL(ids); + + CMPXMedia* entries = CMPXMedia::NewL(); + CleanupStack::PushL(entries); + + CMPXCollectionPath* path = CMPXCollectionPath::NewL(aPath); + CleanupStack::PushL(path); + + // Go through the browse path + TInt levels(aPath.Levels()); + if (levels == 2) + { + // Create a new collection path + CleanupStack::PopAndDestroy( path ); + path = CMPXCollectionPath::NewL(); + CleanupStack::PushL( path ); + + // Always return all songs here + ids.Reset(); + ids.AppendL( KDBPluginUid ); + path->AppendL(ids.Array()); + path->SelectL((TMPXItemId) KDBPluginUid); + + ids.Reset(); + ids.AppendL(EBrowseAll); + path->AppendL(ids.Array()); + path->SelectL((TMPXItemId) EBrowseAll); + path->Set(EMPXOpenPlaylistOnly); + + // Get all item IDs + CMPXMediaArray* array = CMPXMediaArray::NewL(); + CleanupStack::PushL(array); + + DoOpenBrowseAllL(*path, aAttrs, *entries, array); + + entries->SetCObjectValueL(KMPXMediaArrayContents, array); + entries->SetTObjectValueL(KMPXMediaArrayCount, array->Count()); + + CleanupStack::PopAndDestroy(array); + + DoAppendLevelL(*path, *entries); + } + else if (levels > 2) + { + switch (aPath.Id(1).iId2) + { + case EBrowseAll: + { + path->Set(EMPXOpenPlaylistOnly); + // Returns the same path that we copied + break; + } + case EBrowseArtist: + { + if (levels == 3) + { + // return all songs of a particular artist (currently highlighted) + path->Set(EMPXOpenGroupOrPlaylist); + ids.Reset(); + ids.Append(aPath.Id(2)); + path->AppendL(ids.Array()); + path->SelectL(aPath.Id(2)); + path->Set(EMPXOpenPlaylistOnly); + + // Opens all songs of an artist and create the corresponding + // Collection playlist by appending all songs of an artist to + // the collection path + // + DoOpenL(*path, aAttrs, *entries, NULL); + DoAppendLevelL(*path, *entries); + } + else if (levels == 4) + { + // Open the album of an artist and create the corresponding + // Collection playlist by appending all songs of an artist to + // the collection path + // + path->Set(EMPXOpenPlaylistOnly); + DoOpenL(*path, aAttrs, *entries, NULL); + DoAppendLevelL(*path, *entries); + } + else + { + // case is a song no need to open again! + } + + break; + } + // Playlist, album, genre and composer easier, only 2 levels deep + // plugin | category | category contents | songs of category + // + case EBrowsePlaylist: + case EBrowseAlbum: + case EBrowseGenre: + case EBrowseComposer: + { + if (!DoOpenL(aPath, aAttrs, *entries, NULL)) + { + // If it is not at a song level + // Append all entries to create collection path + // + path->Set(EMPXOpenPlaylistOnly); + DoAppendLevelL( *path, *entries ); + } + break; + } + default: + { + User::Leave(KErrNotSupported); + } + } + } + else // levels < 2 + { + User::Leave(KErrNotSupported); + } + + // Cleanup + CleanupStack::Pop(path); + CleanupStack::PopAndDestroy(entries); + CleanupStack::PopAndDestroy(&ids); + + return path; + } + +// ---------------------------------------------------------------------------- +// Process the MediaL command +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoMediaL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries) + { + MPX_FUNC("CMPXDbPlugin::DoMediaL"); + + // Fetch Media for root level + // + if (aPath.Levels() == 1) //root + { + DoRootMediaL( aAttrs, aEntries ); + } + // Ensure the database has been merged before attempting MediaL() + // + else + { + CMPXMediaArray* array = CMPXMediaArray::NewL(); + CleanupStack::PushL(array); + + switch (aPath.Id(1).iId2) + { + case EBrowseAll: + { + DoAllSongsMediaL(aPath, aAttrs, aEntries, *array); + break; + } // end case EBrowseAll + + case EBrowseArtist: + { + DoArtistMediaL(aPath, aAttrs, aEntries, *array); + break; + } // end case EBrowseArtist + + case EBrowseAlbum: + { + DoCategoryMediaL(aPath, aAttrs, EMPXAlbum, aEntries, *array); + break; + } // end case EBrowseAlbum + + case EBrowsePlaylist: + { + DoCategoryMediaL(aPath, aAttrs, EMPXPlaylist, aEntries, *array); + break; + } // end case EBrowsePlaylist + + case EBrowseGenre: + { + DoCategoryMediaL(aPath, aAttrs, EMPXGenre, aEntries, *array); + break; + } // end case EBrowseGenre + + case EBrowseComposer: + { + DoCategoryMediaL(aPath, aAttrs, EMPXComposer, aEntries, *array); + break; + } // end case EBrowseComposer +#ifdef __ENABLE_PODCAST_IN_MUSIC_MENU + case EBrowsePodcasts: + { + break; + } +#endif + default: + { + User::Leave(KErrArgument); + } + } // end switch(aPath.id(1) + + if (array->Count() > 0) + { + aEntries.SetCObjectValueL(KMPXMediaArrayContents, array); + aEntries.SetTObjectValueL(KMPXMediaArrayCount, array->Count()); + } + CleanupStack::PopAndDestroy(array); + } + // Else case cannot leave, because this will happen when we have no disk space to + // perform the merging. It should NOT leave. + // + } + +// ---------------------------------------------------------------------------- +// Find the collection media for root level +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRootMediaL( + const TArray& aAttrs, + CMPXMedia& aMedia ) + { + MPX_FUNC("CMPXDbPlugin::DoRootMediaL"); + + TInt count(aAttrs.Count()); +#ifndef __ENABLE_PODCAST_IN_MUSIC_MENU + aMedia.SetTObjectValueL ( + KMPXMediaGeneralNonPermissibleActions, (TMPXGeneralNonPermissibleActions)(EMPXWrite | EMPXCache) ); +#endif // __ENABLE_PODCAST_IN_MUSIC_MENU + for (TInt i = 0; i < count; ++i) + { + if (aAttrs[i].ContentId() == KMPXMediaIdGeneral) + { + TUint att(aAttrs[i].AttributeId()); + if (att & EMPXMediaGeneralTitle) + { + HBufC* title(iResource->ReadHBufCL(R_MPX_QTN_MUS_MUSIC)); + CleanupStack::PushL(title); + aMedia.SetTextValueL(KMPXMediaGeneralTitle, *title); + CleanupStack::PopAndDestroy(title); + } + if (att & EMPXMediaGeneralSubTitle) + { + TInt numSongs(iDbHandler->NumberOfItemsL(EMPXSong)); + aMedia.SetTObjectValueL(KMPXMediaGeneralCount, numSongs); + + HBufC* text(iResource->ReadHBufCL((1 == numSongs) ? + R_MPX_QTN_MUS_MUSIC_ONE_SONG : R_MPX_QTN_MUS_MUSIC_NUM_SONGS)); + + CleanupStack::PushL(text); + aMedia.SetTextValueL(KMPXMediaGeneralSubTitle, *text); + CleanupStack::PopAndDestroy(text); + } + if (att & EMPXMediaGeneralIcon) + { + TIconInfo icon; + icon.bmpfile = KMPlayerDbPluginMbmFile; + icon.bitmapId = EMbmMpxdbhgpluginQgn_graf_mup_dlst_music; + icon.maskId = EMbmMpxdbhgpluginQgn_graf_mup_dlst_music_mask; + aMedia.SetTObjectValueL(KMPXMediaGeneralIcon, icon); + } + } // if + } // for + } + +// ---------------------------------------------------------------------------- +// Find the collection media for all songs category +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoAllSongsMediaL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbPlugin::DoAllSongsMediaL"); + + TInt levels(aPath.Levels()); + + switch (levels) + { + // All songs + case 2: + { + MPX_PERF_START(CMPXDbPlugin_DoAllSongsMediaL_All); + DoRootCategoryMediaL(aAttrs, EBrowseAll, EMPXSong, aEntries); + MPX_PERF_END(CMPXDbPlugin_DoAllSongsMediaL_All); + break; + } + + // A Song in all songs + case 3: + { + MPX_PERF_START(CMPXDbPlugin_DoAllSongsMediaL_Song); + GetSongInfoL(aPath, aAttrs, aEntries, aMediaArray); + MPX_PERF_END(CMPXDbPlugin_DoAllSongsMediaL_Song); + break; + } + + default: + { + MPX_DEBUG2("CMPXDbPlugin_DoAllSongsMediaL: Invalid levels[%d]", levels); + User::Leave(KErrNotSupported); + } + } // end switch(levels) + } + +// ---------------------------------------------------------------------------- +// Find the collection media for artists category +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoArtistMediaL ( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntries, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbPlugin::DoArtistMediaL"); + + TInt levels(aPath.Levels()); + TInt count(aPath.Selection().Count()); + + // All artists + if (levels == 2) + { + MPX_PERF_START(CMPXDbPlugin_DoArtistMediaL_All); + DoRootCategoryMediaL(aAttrs, EBrowseArtist, EMPXArtist, aEntries); + MPX_PERF_END(CMPXDbPlugin_DoArtistMediaL_All); + } + else if ((levels == 3) && count) // multiple artists selected + { + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + for (TInt i = 0; i < count; ++i) + { + CMPXMedia* artist = CMPXMedia::NewL(); + CleanupStack::PushL(artist); + iDbHandler->GetCategoryL(selections[i].iId2, EMPXArtist, aAttrs, artist); + aMediaArray.AppendL(*artist); + CleanupStack::PopAndDestroy(artist); + } + + CleanupStack::PopAndDestroy(&selections); + } + else if (levels == 3) // single artist selected + { + iDbHandler->GetCategoryL(aPath.Id(2).iId2, EMPXArtist, aAttrs, &aEntries); + } + else if (levels == 4 && (aPath.Id(3) == aPath.Id(2))) // all songs for an artist + { + MPX_PERF_START(CMPXDbPlugin_DoArtistMediaL_AllSongs); + // Calculate duration directly with SQL + if (MPXDbCommonUtil::AttributeExists(aAttrs, KMPXMediaGeneralDuration)) + { + DoDurationL(aEntries, EMPXArtist, aPath.Id(2)); + } + + MPX_PERF_END(CMPXDbPlugin_DoArtistMediaL_AllSongs); + } + else if ((levels == 4) && count) // multiple albums of an artist + { + MPX_PERF_START(CMPXDbPlugin_DoArtistMediaL_AllAlbums); + + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + for (TInt i = 0; i < count; ++i) + { + CMPXMedia* media = CMPXMedia::NewL(); + CleanupStack::PushL(media); + iDbHandler->GetCategoryL(selections[i].iId2, EMPXAlbum, aAttrs, media); + aMediaArray.AppendL(*media); + CleanupStack::PopAndDestroy(media); + } + + CleanupStack::PopAndDestroy(&selections); + + MPX_PERF_END(CMPXDbPlugin_DoArtistMediaL_AllAlbums); + } + else if (levels == 4) // one album of an artist + { + MPX_PERF_START(CMPXDbPlugin_DoArtistMediaL_OneAlbum); + iDbHandler->GetCategoryL(aPath.Id(3).iId2, EMPXAlbum, aAttrs, &aEntries); + + // Calculate duration + if (MPXDbCommonUtil::AttributeExists(aAttrs, KMPXMediaGeneralDuration)) + { + DoDurationL(aEntries, EMPXArtist, aPath.Id(2), EMPXAlbum, aPath.Id(3)); + } + + MPX_PERF_END(CMPXDbPlugin_DoArtistMediaL_OneAlbum); + } + else if (levels == 5) // a song/songs in an album + { + MPX_PERF_START(CMPXDbPlugin_DoArtistMediaL_Song); + GetSongInfoL(aPath, aAttrs, aEntries, aMediaArray); + MPX_PERF_END(CMPXDbPlugin_DoArtistMediaL_Song); + } + else + { + MPX_DEBUG2("CMPXDbPlugin_DoArtistMediaL: Invalid levels[%d]", levels); + User::Leave(KErrNotSupported); + } + } + +// ---------------------------------------------------------------------------- +// Find the collection media for all songs category +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRootCategoryMediaL ( + const TArray& aAttrs, + TMPXItemId aRootCategoryId, + TMPXGeneralCategory aCategory, + CMPXMedia& aEntries) + { + MPX_FUNC("CMPXDbPlugin::DoRootCategoryMediaL"); + + TInt count(aAttrs.Count()); + for (TInt i = 0; i < count; ++i) + { + if (aAttrs[i].ContentId() == KMPXMediaIdGeneral) + { + TUint att(aAttrs[i].AttributeId()); + switch (att) + { + case EMPXMediaGeneralId: + { + aEntries.SetTObjectValueL(KMPXMediaGeneralId, aRootCategoryId); + break; + } + case EMPXMediaGeneralTitle: + { + aEntries.SetTextValueL(KMPXMediaGeneralTitle, + iMusicLibraryMenuTitles->MdcaPoint(BrowseTypeForCategory(aCategory))); + break; + } + case EMPXMediaGeneralCount: + { + // count number of category + aEntries.SetTObjectValueL(KMPXMediaGeneralCount, + iDbHandler->NumberOfItemsL(aCategory)); + break; + } + case EMPXMediaGeneralDuration: + { + if (aCategory == EMPXSong) + { + DoDurationL(aEntries, EMPXSong); + } + break; + } + default: + // not supported + break; + } // end switch + } // end if + } // end for + + aEntries.SetTObjectValueL(KMPXMediaGeneralType, EMPXGroup); + aEntries.SetTObjectValueL(KMPXMediaGeneralCategory, aCategory); + } + +// ---------------------------------------------------------------------------- +// Find the collection media for albums/playlists/genres/composers category +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoCategoryMediaL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + TMPXGeneralCategory aCategory, + CMPXMedia& aEntries, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbPlugin::DoCategoryMediaL"); + + TInt levels(aPath.Levels()); + TInt count(aPath.Selection().Count()); + + if (levels == 2) // all albums/playlists/genres/composers + { + MPX_PERF_START (CMPXDbPlugin_DoCategoryMediaL_All); + DoRootCategoryMediaL(aAttrs, aPath.Id(1).iId2, aCategory, aEntries); + MPX_PERF_END (CMPXDbPlugin_DoCategoryMediaL_All); + } + else if (levels == 3 && count) // multiple albums/playlists/genres/composers selected + { + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + for (TInt i = 0; i < count; ++i) + { + CMPXMedia* media = CMPXMedia::NewL(); + CleanupStack::PushL(media); + iDbHandler->GetCategoryL(selections[i].iId2, aCategory, aAttrs, media); + aMediaArray.AppendL(*media); + CleanupStack::PopAndDestroy(media); + } + + CleanupStack::PopAndDestroy(&selections); + } + else if (levels == 3) // all songs in an album/playlist/genre/composer + { + MPX_PERF_START(CMPXDbPlugin_DoCategoryMediaL_Category); + TMPXItemId id = aPath.Id(2); + iDbHandler->GetCategoryL(id.iId2, aCategory, aAttrs, &aEntries); + + // Calculate duration directly with SQL + if (MPXDbCommonUtil::AttributeExists(aAttrs, KMPXMediaGeneralDuration)) + { + DoDurationL(aEntries, aCategory, id); + } + + TInt nonPermisAction( aEntries.ValueTObjectL(KMPXMediaGeneralNonPermissibleActions)); + nonPermisAction |= EMPXCache; + + aEntries.SetTObjectValueL( + KMPXMediaGeneralNonPermissibleActions, (TMPXGeneralNonPermissibleActions) nonPermisAction ); + + MPX_PERF_END(CMPXDbPlugin_DoCategoryMediaL_Category); + } + else if (levels == 4) // a song/songs in an album/playlist/genre/composer + { + MPX_PERF_START(CMPXDbPlugin_DoCategoryMediaL_Song); + GetSongInfoL(aPath, aAttrs, aEntries, aMediaArray); + MPX_PERF_END(CMPXDbPlugin_DoCategoryMediaL_Song); + } + else + { + MPX_DEBUG2("CMPXDbPlugin__DoMediaL__EBrowseAlbum: Invalid levels[%d]", levels); + User::Leave(KErrNotSupported); + } + } + +// ---------------------------------------------------------------------------- +// Set all the attributes in CMPXMedia corresponding to KMPXMediaIdDrm +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoSetMediaDrmL( + CMPXMedia& aMedia, + TUint aDrmAttributes, + const TDesC& aLocation) + { + MPX_FUNC("CMPXDbPlugin::DoSetMediaDrmL"); + + iDrmMediaUtility->InitL(aLocation); + CleanupClosePushL(*iDrmMediaUtility); + const CMPXMedia* drmMedia(iDrmMediaUtility->GetMediaL(aDrmAttributes)); + + // Only get attributes if it's a DRM file + if (drmMedia) + { + if ((aDrmAttributes & EMPXMediaDrmType) && + drmMedia->IsSupported(KMPXMediaDrmType)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmType, + drmMedia->ValueTObjectL(KMPXMediaDrmType)); + } + if ((aDrmAttributes & EMPXMediaDrmRightsStatus) && + drmMedia->IsSupported(KMPXMediaDrmRightsStatus)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmRightsStatus, + drmMedia->ValueTObjectL(KMPXMediaDrmRightsStatus)); + } + if ((aDrmAttributes & EMPXMediaDrmRightsType) && + drmMedia->IsSupported(KMPXMediaDrmRightsType)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmRightsType, + drmMedia->ValueTObjectL(KMPXMediaDrmRightsType)); + } + if ((aDrmAttributes & EMPXMediaDrmCount) && + drmMedia->IsSupported(KMPXMediaDrmCount)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmCount, + drmMedia->ValueTObjectL(KMPXMediaDrmCount)); + } + if ((aDrmAttributes & EMPXMediaDrmProtected) && + drmMedia->IsSupported(KMPXMediaDrmProtected)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmProtected, + drmMedia->ValueTObjectL(KMPXMediaDrmProtected)); + } + if ((aDrmAttributes & EMPXMediaDrmSendingAllowed) && + drmMedia->IsSupported(KMPXMediaDrmSendingAllowed)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmSendingAllowed, + drmMedia->ValueTObjectL(KMPXMediaDrmSendingAllowed)); + } + if ((aDrmAttributes & EMPXMediaDrmCanSetAutomated) && + drmMedia->IsSupported(KMPXMediaDrmCanSetAutomated)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmCanSetAutomated, + drmMedia->ValueTObjectL(KMPXMediaDrmCanSetAutomated)); + } + if ((aDrmAttributes & EMPXMediaDrmHasInfoUrl) && + drmMedia->IsSupported(KMPXMediaDrmHasInfoUrl)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmHasInfoUrl, + drmMedia->ValueTObjectL(KMPXMediaDrmHasInfoUrl)); + } + if ((aDrmAttributes & EMPXMediaDrmHasPreviewUrl) && + drmMedia->IsSupported(KMPXMediaDrmHasPreviewUrl)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmHasPreviewUrl, + drmMedia->ValueTObjectL(KMPXMediaDrmHasPreviewUrl)); + } + if ((aDrmAttributes & EMPXMediaDrmAboutToExpire) && + drmMedia->IsSupported(KMPXMediaDrmAboutToExpire)) + { + aMedia.SetTObjectValueL( KMPXMediaDrmAboutToExpire, + drmMedia->ValueTObjectL(KMPXMediaDrmAboutToExpire)); + } + if ((aDrmAttributes & EMPXMediaDrmStartTime) && + drmMedia->IsSupported(KMPXMediaDrmStartTime)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmStartTime, + drmMedia->ValueTObjectL(KMPXMediaDrmStartTime)); + } + if ((aDrmAttributes & EMPXMediaDrmEndTime) && + drmMedia->IsSupported(KMPXMediaDrmEndTime)) + { + aMedia.SetTObjectValueL( KMPXMediaDrmEndTime, + drmMedia->ValueTObjectL(KMPXMediaDrmEndTime)); + } + if ((aDrmAttributes & EMPXMediaDrmIntervalStartTime) && + drmMedia->IsSupported(KMPXMediaDrmIntervalStartTime)) + { + aMedia.SetTObjectValueL( KMPXMediaDrmIntervalStartTime, + drmMedia->ValueTObjectL(KMPXMediaDrmIntervalStartTime)); + } + if ((aDrmAttributes & EMPXMediaDrmAccumulatedTime) && + drmMedia->IsSupported(KMPXMediaDrmAccumulatedTime)) + { + aMedia.SetTObjectValueL(KMPXMediaDrmAccumulatedTime, + drmMedia->ValueTObjectL(KMPXMediaDrmAccumulatedTime)); + } + if ((aDrmAttributes & EMPXMediaDrmInterval) && + drmMedia->IsSupported(KMPXMediaDrmInterval)) + { + aMedia.SetTObjectValueL( KMPXMediaDrmInterval, + drmMedia->ValueTObjectL(KMPXMediaDrmInterval)); + } + } + + CleanupStack::PopAndDestroy(iDrmMediaUtility); + } + +// ---------------------------------------------------------------------------- +// Add media objects to the array with attributes from song details +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::GetSongInfoL( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aEntry, + CMPXMediaArray& aMediaArray) + { + MPX_FUNC("CMPXDbPlugin::GetSongInfoL"); + + RArray supportedIds; + CleanupClosePushL(supportedIds); + MPXDbCommonUtil::FillInSupportedUIDsL(aAttrs, supportedIds); + + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + // + // If we are trying to locate a song from a playlist, we should read available song + // info from Playlist table first in case the song is located on a removable + // drive and the drive is not currently present. This is achieved by supplying + // playlist Id to GetSongMatchingSongIdL. When playlistId is 0, we are reading song + // info directly from Songs table. If playlistId is specified, GetSongMatchingSongIdL + // will populate song media from Playlist table and if Songs table for the drive + // exists, song media will be overwritten with info from Songs table. + // + TMPXItemId playlistId(0); + if (aPath.Id(1) == EBrowsePlaylist) + { + if (aPath.Levels() < 2) + { + User::Leave(KErrArgument); + } + + playlistId = aPath.Id(aPath.Levels() - 2); + } + + TInt countSelection(aPath.Selection().Count()); + if (countSelection) + { + // We have a selection, iterate it + for (TInt selectionIndex = 0; selectionIndex < countSelection; ++selectionIndex) + { + CMPXMedia* newEntry = CMPXMedia::NewL(supportedIds.Array()); + CleanupStack::PushL(newEntry); + + DoGetSongInfoL(aAttrs, selections[selectionIndex].iId2, playlistId.iId2, *newEntry); + + aMediaArray.AppendL(*newEntry); + CleanupStack::PopAndDestroy(newEntry); + } + } + else + { + // No selection, get the attributes for the one song + DoGetSongInfoL(aAttrs, aPath.Id(aPath.Levels() - 1).iId2, playlistId.iId2, aEntry); + } + + CleanupStack::PopAndDestroy(&selections); + CleanupStack::PopAndDestroy(&supportedIds); + } + +// ---------------------------------------------------------------------------- +// Retrieves the attributes for a media object. +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoGetSongInfoL( + const TArray& aAttrs, + TInt aEntryId, + TInt aPlaylistId, + CMPXMedia& aEntry) + { + MPX_FUNC("CMPXDbPlugin::DoGetSongInfoL"); + + if (aPlaylistId) + { + iDbHandler->GetPlaylistSongL(aEntryId, aPlaylistId, aAttrs, aEntry); + } + else + { + iDbHandler->GetSongL(aEntryId, aAttrs, aEntry); + } + + const TDesC& location(aEntry.ValueText(KMPXMediaGeneralUri)); + + // Check DRM Only if we have a location + if (location != KNullDesC) + { + TUint drmAttributes(0); + + // Compact the attribute set + TInt count(aAttrs.Count()); + for (TInt i = 0; i < count; ++i) + { + if (aAttrs[i].ContentId() == KMPXMediaIdDrm) + { + drmAttributes |= aAttrs[i].AttributeId(); + } + } + + // Set the correct attributes to media, only if requested + if (drmAttributes) + { + DoSetMediaDrmL(aEntry, drmAttributes, location); + } + } + + // Disable caching for any MediaL() returning song info. + TInt nonPermisAction( aEntry.ValueTObjectL(KMPXMediaGeneralNonPermissibleActions)); + nonPermisAction |= EMPXCache; + + aEntry.SetTObjectValueL( + KMPXMediaGeneralNonPermissibleActions, (TMPXGeneralNonPermissibleActions) nonPermisAction ); + } + +// ---------------------------------------------------------------------------- +// Find the collection details +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoHandleOtherMediaAttributesL( + const TArray& aAttrs, + const CMPXCollectionPath& aPath, + CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbPlugin::DoHandleOtherMediaAttributesL"); + + TInt count(aAttrs.Count()); + for (TInt i = 0; i < count; ++i) + { + if (aAttrs[i].ContentId() == KMPXMediaIdCollectionDetails) + { + TUint att(aAttrs[i].AttributeId()); + + if (att & EMPXMediaColDetailNumberOfItems) + { + aMedia.SetTObjectValueL(KMPXMediaColDetailNumberOfItems, + iDbHandler->NumberOfItemsL(EMPXSong)); + } + if (att & EMPXMediaColDetailDuration) + { + aMedia.SetTObjectValueL(KMPXMediaColDetailDuration, + DoDurationL(aMedia, EMPXSong)); + } + if (att & EMPXMediaColTotalSize) + { + // todo + TInt totalSize(0); + aMedia.SetTObjectValueL(KMPXMediaColDetailTotalSize, totalSize); + } + if (att & EMPXMediaLastRefreshed) + { + TTime lastRefreshed(iDbHandler->GetLastRefreshedTimeL()); + aMedia.SetTObjectValueL(KMPXMediaColDetailLastRefreshed, + lastRefreshed.Int64()); + } + if (att & EMPXMediaColDetailDBCreated) + { + aMedia.SetTObjectValueL(KMPXMediaColDetailDBCreated, + iDbHandler->DatabaseCreated()); + } + if (att & EMPXMediaColDetailDBCorrupted) + { + aMedia.SetTObjectValueL(KMPXMediaColDetailDBCorrupted, + iDbHandler->IsDBCorruptedL()); + } + } + else if (aAttrs[i] == KMPXMediaGeneralPath) + { + aMedia.SetCObjectValueL(KMPXMediaGeneralPath, + const_cast(&aPath)); + } + } + } + +// ---------------------------------------------------------------------------- +// Remove an item from the collection database using the given path +// ---------------------------------------------------------------------------- +// +CDesCArray* CMPXDbPlugin::DoRemoveL( + const CMPXCollectionPath& aPath, + CMPXMessageArray& aChangeMsgArray) + { + MPX_FUNC("CMPXDbPlugin::DoRemoveL"); + + if (aPath.Levels() <= 1) + { + User::Leave(KErrNotSupported); + } + + // Return file path for deleted item(s) + // + CDesCArray* fp = new(ELeave) CDesCArrayFlat(1); + CleanupStack::PushL(fp); + + // Ids of the selected items + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + switch (aPath.Id(1).iId2) + { + case EBrowseAll: + { + DoRemoveFromAllSongsL(aPath, selections.Array(), *fp, aChangeMsgArray); + } + break; + + case EBrowseArtist: + { + DoRemoveFromArtistsL(aPath, selections.Array(), *fp, aChangeMsgArray); + } + break; + + case EBrowseAlbum: // deliberate fall through + case EBrowseGenre: // deliberate fall through + case EBrowseComposer: // deliberate fall through + { + DoRemoveFromCategoriesL(aPath, selections.Array(), + CategoryForBrowseType(static_cast(aPath.Id(1).iId2)), *fp, aChangeMsgArray); + } + break; + + case EBrowsePlaylist: + { + DoRemoveFromPlaylistsL(aPath, selections.Array(), *fp, aChangeMsgArray); + } + break; + + default: + { + User::Leave(KErrArgument); + } + } // end switch (aPath.Id(1)) + + MPX_DEBUG2("CMPXDbPlugin::RemoveL itemId[%d]", aPath.Id(aPath.Levels() - 1).iId2); + + CleanupStack::PopAndDestroy( &selections ); + CleanupStack::Pop(fp); + + return fp; + } + +// ---------------------------------------------------------------------------- +// Remove an item from the collection database using the given media properties +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRemoveL( + const CMPXMedia& aMedia, + TBool aDeleteRecord) + { + MPX_FUNC("CMPXDbPlugin::DoRemoveL(by media)"); + + // Return deleted file paths to caller + CDesCArray* fp = new(ELeave) CDesCArrayFlat(1); + CleanupStack::PushL(fp); + + // a list of change event messages a result of the item being removed + CMPXMessageArray* itemChangedMessages = CMPXMediaArray::NewL(); + CleanupStack::PushL(itemChangedMessages); + + TUint32 mediaId(0); + + // Removing a container of items + // + if (aMedia.IsSupported(KMPXMediaArrayContents)) + { + MPX_DEBUG1("CMPXDbPlugin::RemoveL -- Removing a container of items"); + const CMPXMediaArray* media = aMedia.Value(KMPXMediaArrayContents); + if( !media ) + { + User::Leave(KErrNoMemory); + } + const TInt mediaCount(media->Count()); + for (TInt i = 0; i < mediaCount; ++i) + { + CMPXMedia* entry = media->AtL(i); + if (entry->IsSupported(KMPXMediaGeneralId)) + { + mediaId = entry->ValueTObjectL(KMPXMediaGeneralId); + } + else if (entry->IsSupported(KMPXMediaGeneralUri)) + { + const TDesC& uri = entry->ValueText(KMPXMediaGeneralUri); + mediaId = iDbHandler->GetSongIdMatchingUriL(uri); + } + else + { + // Unable to process this item + continue; + } + + iDbHandler->RemoveSongL(mediaId, *fp, *itemChangedMessages, aDeleteRecord); + } + } + // Removing an item with known item id + // + else if (aMedia.IsSupported(KMPXMediaGeneralId)) + { + MPX_DEBUG1("CMPXDbPlugin::RemoveL -- Removing an item by item id"); + mediaId = aMedia.ValueTObjectL(KMPXMediaGeneralId); + + if (MPX_ITEM_CATEGORY(mediaId) != EMPXPlaylist) + { + iDbHandler->RemoveSongL(mediaId, *fp, *itemChangedMessages, aDeleteRecord); + } + else + { + iDbHandler->RemovePlaylistL(mediaId, *fp, *itemChangedMessages); + } + } + // Removing an item with known uri + // + else if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + MPX_DEBUG1("CMPXDbPlugin::RemoveL -- Removing an item by uri"); + TPtrC uri = aMedia.ValueText( KMPXMediaGeneralUri ); + + TMPXGeneralCategory category = + aMedia.ValueTObjectL(KMPXMediaGeneralCategory); + + if (category == EMPXSong) + { + mediaId = iDbHandler->GetSongIdMatchingUriL(uri); + iDbHandler->RemoveSongL(mediaId, *fp, *itemChangedMessages, aDeleteRecord); + } + else if (category == EMPXPlaylist) + { + mediaId = iDbHandler->GetPlaylistIdMatchingUriL(uri); + iDbHandler->RemovePlaylistL(mediaId, *fp, *itemChangedMessages); + } +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + else if (category == EMPXAbstractAlbum ) + { + mediaId = iDbHandler->GetAbstractAlbumIdMatchingUriL(uri); + iDbHandler->RemoveAbstractAlbumL(mediaId, *itemChangedMessages, EFalse); + } +#endif // ABSTRACTAUDIOALBUM_INCLUDED + else + { + // otherwise unable to process this item + } + } + else + { + MPX_DEBUG1("CMPXDbPlugin::RemoveL -- Unknown item for removal"); + User::Leave(KErrNotSupported); + } + + iActiveTask->SetVisibleChange(CMPXDbActiveTask::EAllVisible); + + // Removing an item always invalidates all songs. + // + MPXDbCommonUtil::AddItemChangedMessageL(*itemChangedMessages, EBrowseAll, + EMPXItemModified, EMPXCollection, KDBPluginUid); + + DoHandleChangeL(itemChangedMessages); + + CleanupStack::PopAndDestroy(itemChangedMessages); + CleanupStack::PopAndDestroy(fp); + } + +// ---------------------------------------------------------------------------- +// Remove media by path through a command +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRemovePathL( + CMPXCommand& aCmd) + { + MPX_FUNC("CMPXDbPlugin::DoRemovePathL(by command)"); + + TInt removeError(KErrNone); + TBool removeCompleted(ETrue); + + if (!aCmd.IsSupported(KMPXCommandCollectionRemovePath) || + !aCmd.IsSupported(KMPXCommandCollectionRemoveMediaCount)) + { + removeError = KErrArgument; + } + else + { + CMPXCollectionPath* path = + aCmd.ValueCObjectL(KMPXCommandCollectionRemovePath); + CleanupStack::PushL(path); + + // in order to support cancel delete for a category, we need to adjust path. If + // the path ends in a category, retrieve all songs under the selected category + // and append a new level with all songs under the selected category + DoAppendLevelL(*path); + + CMPXCollectionPath* iterationPath = CMPXCollectionPath::NewL(*path); + CleanupStack::PushL(iterationPath); + iterationPath->ClearSelection(); + + // indices of the selected items + TArray selectionIndices = path->Selection(); + TInt count(selectionIndices.Count()); + + // number of media items to remove in this iteration + TInt removeCount = (aCmd.ValueTObjectL(KMPXCommandCollectionRemoveMediaCount)); + + // remove all in one shot if removeCount is 0 or negative + if (removeCount <= 0) + { + removeCount = count; + } + + // If the given path contains multiple selections, remove the first n selected media + // and update the path so that client can use this path to call remove iteratively + // until all selections are processed + // + if (count) + { + for (TInt i = 0; i < removeCount; ++i) + { + TInt index(selectionIndices[i]); + + MPX_DEBUG4(" path: selected item [index %d] [selectioncount %d] [remove count %d]", index, count, removeCount); + + iterationPath->SelectL(index); + path->Remove(index); + } + + aCmd.SetCObjectValueL(KMPXCommandCollectionRemovePath, path); + + // indicate to the client that subsequent remove command is required + if ((count - removeCount) > 0) + { + removeCompleted = EFalse; + } + } + + // Remove the media specified by the path + CDesCArray* fp(NULL); + TBool supressMsgs(EFalse); + CMPXMessageArray* msgAry(NULL); + + if (aCmd.IsSupported(KMPXCommandCollectionRemoveSuppressMsgs) && + aCmd.ValueTObjectL(KMPXCommandCollectionRemoveSuppressMsgs)) + { + // Msgs are stored in the command + supressMsgs = ETrue; + + CMPXMessageArray* msgs( aCmd.Value(KMPXCommandCollectionChangeMsgs) ); + User::LeaveIfNull( msgs ); + fp = DoRemoveL(*iterationPath, *msgs); + } + else + { + // Msgs will be sent after delete + msgAry = CMPXMessageArray::NewL(); + CleanupStack::PushL(msgAry); + fp = DoRemoveL(*iterationPath, *msgAry); + } + + CleanupStack::PushL(fp); + if (fp->MdcaCount() > removeCount) + { + removeError = KErrCorrupt; + } + CleanupStack::PopAndDestroy(fp); + + if (!supressMsgs) + { + // Send Change Messages + iActiveTask->SetVisibleChange(CMPXDbActiveTask::EAllVisible); + DoHandleChangeL(msgAry); + CleanupStack::PopAndDestroy(msgAry); + } + + // Cleanup + CleanupStack::PopAndDestroy(iterationPath); + CleanupStack::PopAndDestroy(path); + } + + // mandatory return parameters + aCmd.SetTObjectValueL(KMPXCommandCollectionRemoveError, removeError); + aCmd.SetTObjectValueL(KMPXCommandCollectionRemoveCompleted, removeCompleted); + } + +// ---------------------------------------------------------------------------- +// Remove media by CMPXMedia through a command +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRemoveMediaL( + CMPXCommand& aCmd) + { + MPX_FUNC("CMPXDbPlugin::DoRemoveMediaL(by command)"); + + TInt error(KErrArgument); + + if (aCmd.IsSupported(KMPXCommandCollectionRemoveMedia)) + { + CMPXMedia* media = aCmd.ValueCObjectL(KMPXCommandCollectionRemoveMedia); + CleanupStack::PushL(media); + + MPX_TRAP(error, DoRemoveL(*media, + aCmd.ValueTObjectL(KMPXCommandCollectionRemoveMediaDeleteRecord))); + + CleanupStack::PopAndDestroy(media); + } + + aCmd.SetTObjectValueL(KMPXCommandCollectionRemoveMediaError, error); + } + +// ---------------------------------------------------------------------------- +// Remove a media/media items from All Songs view +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRemoveFromAllSongsL( + const CMPXCollectionPath& aPath, + const TArray& aSelections, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbPlugin::DoRemoveFromAllSongsL"); + + switch (aPath.Levels()) + { + case 2: + { + // when the collection is removed, it's intended not to delete the files + iDbHandler->RemoveEntireCollectionL(); + } + break; + + case 3: + { + TInt count(aSelections.Count()); + if (count) + { + for (TInt i = 0; i < count; ++i) + { + iDbHandler->RemoveSongL(aSelections[i].iId2, aUriArray, aItemChangedMessages); + } // end for + } + else + { + iDbHandler->RemoveSongL(aPath.Id(aPath.Levels() - 1).iId2, aUriArray, + aItemChangedMessages); + } + } + break; + + default: + { + MPX_DEBUG2("CMPXDbPlugin_DoRemoveFromAllSongsL: Invalid levels[%d]", aPath.Levels()); + User::Leave(KErrNotSupported); + } + } + } + +// ---------------------------------------------------------------------------- +// Remove a media/media items from Artists view +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRemoveFromArtistsL( + const CMPXCollectionPath& aPath, + const TArray& aSelections, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbPlugin::DoRemoveFromArtistsL"); + + TInt levels(aPath.Levels()); + if (levels == 2) + { + // when the collection is removed, it's intended not to delete the files + iDbHandler->RemoveEntireCollectionL(); + } + else + { + TInt count(aSelections.Count()); + if (count) + { + for (TInt i = 0; i < count; ++i) + { + RemoveFromArtistsL(aPath, aSelections[i].iId2, aUriArray, aItemChangedMessages); + } + } + else + { + RemoveFromArtistsL(aPath, aPath.Id(levels - 1).iId2, aUriArray, aItemChangedMessages); + } + } + + MPX_DEBUG2("CMPXDbPlugin__RemoveL__EBrowseArtist: levels[%d]", levels); + } + +// ---------------------------------------------------------------------------- +// Remove a media item from Artists view +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::RemoveFromArtistsL( + const CMPXCollectionPath& aPath, + TUint32 aItemId, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbPlugin::RemoveFromArtistsL"); + + switch (aPath.Levels()) + { + case 3: + { + iDbHandler->RemoveSongsMatchingCategoryL(EMPXArtist, aItemId, aUriArray, aItemChangedMessages); + break; + } + case 4: + { + // remove the songs for the artist and album + iDbHandler->RemoveSongsMatchingArtistAndAlbumL(aPath.Id(aPath.Levels() - 2), aItemId, + aUriArray, aItemChangedMessages); + break; + } + case 5: + { + iDbHandler->RemoveSongL(aItemId, aUriArray, aItemChangedMessages); + break; + } + default: + { + User::Leave(KErrArgument); + } + } + } + +// ---------------------------------------------------------------------------- +// Remove a media/media items from Albums/Genres/Composers view +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRemoveFromCategoriesL( + const CMPXCollectionPath& aPath, + const TArray& aSelections, + TMPXGeneralCategory aCategory, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbPlugin::DoRemoveFromCategoriesL"); + + TInt levels(aPath.Levels()); + if (levels == 2) + { + // when the collection is removed, it's intended not to delete the files + iDbHandler->RemoveEntireCollectionL(); + } + else + { + TInt count(aSelections.Count()); + if (count) + { + for (TInt i = 0; i < count; ++i) + { + RemoveFromCategoriesL(aPath, aSelections[i].iId2, aCategory, + aUriArray, aItemChangedMessages); + } + } + else + { + RemoveFromCategoriesL(aPath, aPath.Id(levels - 1).iId2, aCategory, + aUriArray, aItemChangedMessages); + } + } + + MPX_DEBUG2("CMPXDbPlugin__RemoveL__EBrowseAlbum: levels[%d]", levels); + } + +// ---------------------------------------------------------------------------- +// Remove a media item from Albums/Genres/Composers view +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::RemoveFromCategoriesL( + const CMPXCollectionPath& aPath, + TUint32 aItemId, + TMPXGeneralCategory aCategory, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbPlugin::RemoveFromCategoriesL"); + + switch (aPath.Levels()) + { + case 3: + { + iDbHandler->RemoveSongsMatchingCategoryL(aCategory, aItemId, aUriArray, + aItemChangedMessages); + break; + } + case 4: + { + iDbHandler->RemoveSongL(aItemId, aUriArray, aItemChangedMessages); + break; + } + default: + { + User::Leave(KErrArgument); + } + } + } + +// ---------------------------------------------------------------------------- +// Remove one or multiple media items from Playlists view +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRemoveFromPlaylistsL( + const CMPXCollectionPath& aPath, + const TArray& aSelections, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbPlugin::DoRemoveFromPlaylistsL"); + + TInt levels(aPath.Levels()); + + // all playlists + if (levels == 2) + { + // when the collection is removed, it's intended not to delete the files + iDbHandler->RemoveAllPlaylistsL(); + } + else + { + TArray selectionIndices = aPath.Selection(); + TInt count(selectionIndices.Count()); + + // multiple selections + if (count) + { + for (TInt i = (count - 1); i >= 0; --i) + { + RemoveFromPlaylistsL(aPath, aSelections[i], selectionIndices[i], + aUriArray, aItemChangedMessages); + } + } + // else no selection + else + { + RemoveFromPlaylistsL(aPath, aPath.IdOfIndex(aPath.Index()), aPath.Index(), + aUriArray, aItemChangedMessages); + } + } + + MPX_DEBUG2("CMPXDbPlugin__RemoveL__EBrowsePlaylist: levels[%d]", levels); + } + +// ---------------------------------------------------------------------------- +// Remove a media item from Playlists view +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::RemoveFromPlaylistsL( + const CMPXCollectionPath& aPath, + const TMPXItemId& aItemId, + TInt aIndex, + CDesCArray& aUriArray, + CMPXMessageArray& aItemChangedMessages) + { + MPX_FUNC("CMPXDbPlugin::RemoveFromPlaylistsL"); + + switch (aPath.Levels()) + { + case 3: + { + iDbHandler->RemovePlaylistL(aItemId.iId2, aUriArray, aItemChangedMessages); + break; + } + case 4: + { + if ( !iDbHandler->InTransaction() ) + { + iDbHandler->BeginTransactionL(); + } + iDbHandler->RemoveSongFromPlaylistL(aPath.Id(aPath.Levels() - 2).iId2, aItemId, + aIndex, aItemChangedMessages); + break; + } + default: + { + User::Leave(KErrArgument); + } + } + } + +// ---------------------------------------------------------------------------- +// Retrieve URIs associated with this file path for file deletion +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoRetrieveUriForDeletionL( + CMPXCommand& aCmd) + { + MPX_FUNC("CMPXDbPlugin::DoRetrieveUriForDeletionL"); + + // initialize mandatory return parameters + aCmd.SetTObjectValueL(KMPXCommandCollectionRetrieveUriError, KErrNone); + + if (!aCmd.IsSupported(KMPXCommandCollectionRetrievePath)) + { + aCmd.SetTObjectValueL(KMPXCommandCollectionRetrieveUriError, KErrArgument); + } + else + { + CMPXCollectionPath* path = aCmd.ValueCObjectL(KMPXCommandCollectionRetrievePath); + CleanupStack::PushL(path); + if (iFirstDeleteStep ) + { + iSelections.Reset( ); + // in order to support cancel delete for a category, we need to adjust path. If + // the path ends in a category, retrieve all songs under the selected category + // and append a new level with all songs under the selected category + DoAppendLevelL(*path); + + // Ids of the selected items + path->SelectionL(iSelections ); + + // single selection + if (iSelections.Count()== 0 ) + { + iSelections.AppendL(path->Id (path->Levels()- 1 ) ); + } + } + + CDesCArray* fp = new(ELeave) CDesCArrayFlat(4); + CleanupStack::PushL(fp); + + TInt count(iSelections.Count()); + TInt itemCount = count > KIncrementalDeleteCount ? KIncrementalDeleteCount : count; + for (TInt i = 0; i < itemCount; ++i ) + { + // do not report song URIs if collection path is for songs within a playlist, i.e. + // EBrowsePlaylist and level 4, because client should not be deleting those song + // files + if (path->Id(1) != EBrowsePlaylist || path->Levels() !=4) + { + HBufC * uri = iDbHandler->GetUriMatchingIdL (iSelections[0].iId2 ); + CleanupStack::PushL(uri); + fp->AppendL(*uri); + CleanupStack::PopAndDestroy(uri); + } + iSelections.Remove(0); + } + + aCmd.SetNoNewLCObjectL(KMPXCommandCollectionRetrieveMediaUriArray, fp); + if (iFirstDeleteStep) + { + aCmd.SetCObjectValueL(KMPXCommandCollectionRetrievePath, path); + } + + CleanupStack::PopAndDestroy(fp); + CleanupStack::PopAndDestroy(path); + } + } + +// ---------------------------------------------------------------------------- +// Cleanup deleted records +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::CleanupDeletedRecordsL( + CMPXCommand& aCmd) + { + MPX_FUNC("CMPXDbPlugin::CleanupDeletedRecordsL"); + + MPX_TRAPD(error, iDbHandler->CleanupDeletedRecordsL()); + aCmd.SetTObjectValueL(KMPXCommandCollectionCleanupError, error); + } + +// ---------------------------------------------------------------------------- +// Find the duration +// ---------------------------------------------------------------------------- +// +TInt CMPXDbPlugin::DoDurationL( + CMPXMedia& aMedia, + TMPXGeneralCategory aFirstCat, + TMPXItemId aId, + TMPXGeneralCategory aSecondCat, + TMPXItemId aSubId) + { + MPX_FUNC("CMPXDbPlugin::DoDurationL"); + + TInt duration(0); + + switch (aFirstCat) + { + case EMPXSong: + { + duration = iDbHandler->GetAllSongsDurationL(); + break; + } + case EMPXAlbum: + { + duration = iDbHandler->GetAlbumDurationL(aId.iId2); + break; + } + case EMPXComposer: + { + duration = iDbHandler->GetComposerDurationL(aId.iId2); + break; + } + case EMPXGenre: + { + duration = iDbHandler->GetGenreDurationL(aId.iId2); + break; + } + case EMPXArtist: + { + if (aSecondCat == EMPXAlbum) + { + duration = iDbHandler->GetArtistAlbumDurationL(aId.iId2, aSubId.iId2); + } + else + { + duration = iDbHandler->GetArtistDurationL(aId.iId2); + } + break; + } + case EMPXPlaylist: + { + duration = iDbHandler->GetPlaylistDurationL(aId.iId2); + break; + } + default: + { + User::Leave(KErrNotSupported); + } + } + + aMedia.SetTObjectValueL(KMPXMediaGeneralDuration, duration); + return duration; + } + +// ---------------------------------------------------------------------------- +// Append a level to a collection path and set selection to the first item +// ---------------------------------------------------------------------------- +// +TInt CMPXDbPlugin::DoAppendLevelL( + CMPXCollectionPath& aPath, + CMPXMedia& aMedia ) + { + MPX_FUNC("CMPXDbPlugin::DoAppendLevelL"); + + RArray ids; + CleanupClosePushL(ids); + + // Extract media array, and get all item ids + // + const CMPXMediaArray* mediaArray = aMedia.Value(KMPXMediaArrayContents); + if( !mediaArray ) + { + User::Leave( KErrNoMemory ); + } + + TInt count(mediaArray->Count()); + if (count >= 0) + { + for (TInt i = 0; i < count; ++i) + { + TMPXItemId id = mediaArray->AtL(i)->ValueTObjectL(KMPXMediaGeneralId); + ids.AppendL(id); + } + + // Put item id array into the path and select the first one + aPath.AppendL(ids.Array()); + if (count > 0) + { + aPath.Set(0); + } + } + + CleanupStack::PopAndDestroy(&ids); + return count; + } + +// ---------------------------------------------------------------------------- +// Append a level to a collection path and set selection to all songs under the +// selected category/categories +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoAppendLevelL( + CMPXCollectionPath& aPath) + { + MPX_FUNC("CMPXDbPlugin::DoAppendLevelL"); + + TMPXItemId contextId(aPath.Id(1)); + TInt levels(aPath.Levels()); + + if ((contextId == EBrowseAll) || + (contextId == EBrowsePlaylist)) + { + return; + } + else if (levels == 3 || (levels == 4 && contextId == EBrowseArtist)) + { + // retrieve songs in the selected category + // + CMPXMediaArray* songs = CMPXMediaArray::NewL(); + CleanupStack::PushL(songs); + + RArray attributes; + CleanupClosePushL(attributes); + attributes.AppendL(KMPXMediaGeneralId); + + // Ids of the selected items + RArray selections; + CleanupClosePushL(selections); + aPath.SelectionL(selections); + + // single selection + if (selections.Count() == 0) + { + selections.AppendL(aPath.Id(aPath.Levels() - 1)); + } + + TInt count(selections.Count()); + + // all songs for the selected artist + if (contextId == EBrowseArtist && levels == 3) + { + for (TInt i = 0; i < count; ++i) + { + iDbHandler->GetSongsMatchingArtistL(selections[i].iId2, attributes.Array(), songs); + } + if (songs->Count()) + { + aPath.AppendL(selections.Array()); + } + } + + // all songs for the selected artist in the specified album + else if ((contextId == EBrowseArtist) && (levels == 4)) + { + for (TInt i = 0; i < count; ++i) + { + if (aPath.Id(2) == aPath.Id(3)) + { + iDbHandler->GetSongsMatchingArtistL(aPath.Id(3).iId2, + attributes.Array(), songs); + } + else + { + iDbHandler->GetSongsMatchingArtistAndAlbumL(aPath.Id(aPath.Levels() - 2), + selections[i].iId2, attributes.Array(), songs); + } + } + } + + // all songs for the selected album + else if (contextId == EBrowseAlbum && levels == 3) + { + for (TInt i = 0; i < count; ++i) + { + iDbHandler->GetSongsMatchingAlbumL(selections[i], attributes.Array(), songs); + } + } + + // all songs for the selected genre + else if (contextId == EBrowseGenre && levels == 3) + { + for (TInt i = 0; i < count; ++i) + { + iDbHandler->GetSongsMatchingGenreL(selections[i], attributes.Array(), songs); + } + } + + // all songs for the selected composer + else if (contextId == EBrowseComposer && levels == 3) + { + for (TInt i = 0; i < count; ++i) + { + iDbHandler->GetSongsMatchingComposerL(selections[i], attributes.Array(), songs); + } + } + else + { + // else do nothing + } + + CleanupStack::PopAndDestroy(&selections); + CleanupStack::PopAndDestroy(&attributes); + + // transform from CMPXMediaArray to RArray + RArray songIds; + CleanupClosePushL(songIds); + + TInt songCount(songs->Count()); + for (TInt i = 0; i < songCount; ++i) + { + CMPXMedia* song = (*songs)[i]; + + if (song->IsSupported(KMPXMediaGeneralId)) + { + songIds.AppendL(song->ValueTObjectL(KMPXMediaGeneralId)); + } + } + + // modify the collection path. append another level with all songs under the selected + // category/categories selected + songCount = songIds.Count(); + + if (songCount) + { + aPath.ClearSelection(); + aPath.AppendL(songIds.Array()); + + // select all + for (TInt i = 0; i < songCount; ++i) + { + aPath.SelectL(songIds[i]); + } + } + + CleanupStack::PopAndDestroy(&songIds); + CleanupStack::PopAndDestroy(songs); + } + else + { + // do nothing + } + } + +// ---------------------------------------------------------------------------- +// Execute an Add task step +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoAddAsyncL() + { + MPX_FUNC("CMPXDbPlugin::DoAddAsyncL"); + + TBool done(EFalse); + const CMPXMedia* task = (iActiveTask->GetCommand().Value(KMPXCommandColAddMedia)); + if( !task ) + { + User::Leave(KErrNoMemory); + } + + CMPXMessageArray& msgArray = iActiveTask->GetChangeMessages(); + + if (!task->IsSupported(KMPXMediaGeneralType)) + { + User::Leave(KErrArgument); + } + + // Group of items or a single item + // + if (task->ValueTObjectL(KMPXMediaGeneralType) == EMPXGroup) + { + if (!task->IsSupported(KMPXMediaArrayContents)) + { + User::Leave(KErrArgument); + } + + CMPXMediaArray* ary = task->Value(KMPXMediaArrayContents); + User::LeaveIfNull(ary); + TInt step( iActiveTask->GetStep() ); + DoAddItemL( *ary->AtL(step), msgArray ); + + if (++step == ary->Count()) + { + done = ETrue; + } + } + else // type == EMPXItem + { + TUint32 item = DoAddItemL( *task, msgArray ); + iActiveTask->GetCommand().SetTObjectValueL( KMPXCommandColAddRtnId, item); + done = ETrue; + } + + iActiveTask->SetVisibleChange(CMPXDbActiveTask::EAllVisible); + return done; + } + +// ---------------------------------------------------------------------------- +// Add an item to the collection +// ---------------------------------------------------------------------------- +// +TUint32 CMPXDbPlugin::DoAddL( + const CMPXMedia& aMedia) + { + MPX_FUNC("CMPXDbPlugin::DoAddL"); + + if (!aMedia.IsSupported(KMPXMediaGeneralType)) + { + User::Leave(KErrArgument); + } + + TUint32 itemId(0); + CMPXMessageArray* changeMsgAry = CMPXMessageArray::NewL(); + CleanupStack::PushL(changeMsgAry); + + // start a transaction here + if (!iDbHandler->InTransaction()) + { + iDbHandler->BeginTransactionL(); + } + + // Group of items + if (aMedia.ValueTObjectL(KMPXMediaGeneralType) == EMPXGroup) + { + CMPXMediaArray* array = aMedia.Value(KMPXMediaArrayContents); + User::LeaveIfNull( array ); + + TInt count(array->Count()); + for (TInt i = 0; i < count; ++i) + { + // ETrue indicates we are batch committing the songs. + // This parameter is only used for the use case of adding + // thousands of songs at a time. + DoAddItemL(*array->AtL(i), *changeMsgAry, ETrue); + } + } + else // single item + { + itemId = DoAddItemL(aMedia, *changeMsgAry); + } + + // end transaction here. + iDbHandler->EndTransactionL(KErrNone); + + iActiveTask->SetVisibleChange(CMPXDbActiveTask::EAllVisible); + DoHandleChangeL(changeMsgAry); + CleanupStack::PopAndDestroy(changeMsgAry); + + return itemId; + } + +// ---------------------------------------------------------------------------------------------------------- +// Add an item to the collection +// ---------------------------------------------------------------------------------------------------------- +// +TUint32 CMPXDbPlugin::DoAddItemL( + const CMPXMedia& aMedia, + CMPXMessageArray& aMessageArray, + TBool aBatchCommit) + { + MPX_FUNC("CMPXDbPlugin::DoAddItemL"); + + TUint32 itemId(0); + if (!aMedia.IsSupported(KMPXMediaGeneralCategory)) + { + User::Leave(KErrArgument); + } + + switch (aMedia.ValueTObjectL(KMPXMediaGeneralCategory)) + { + case EMPXPlaylist: + { + if (!aMedia.IsSupported(KMPXMediaArrayContents)) + { + User::Leave(KErrArgument); + } + + if (aMedia.IsSupported(KMPXMediaGeneralId)) + { + itemId = iDbHandler->AddSongToPlaylistL(aMedia); + MPXDbCommonUtil::AddItemChangedMessageL(aMessageArray, itemId, EMPXItemModified, + EMPXPlaylist, KDBPluginUid); + } + else if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + itemId = iDbHandler->AddPlaylistL(aMedia); + MPXDbCommonUtil::AddItemChangedMessageL(aMessageArray, EBrowsePlaylist, EMPXItemInserted, + EMPXPlaylist, KDBPluginUid); + } + else + { + User::Leave(KErrArgument); + } + } + break; +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + case EMPXAbstractAlbum: + { + if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + //add abstractalbum to AbstractAlbum table + itemId = iDbHandler->AddAbstractAlbumL(aMedia, &aMessageArray); + + //in case aMedia as mediaArray which contains songs as arrayContents, need to update all songs associated + if ( aMedia.IsSupported(KMPXMediaArrayContents)) + { + iDbHandler->UpdateSongsAbstractAlbumInfoL(aMedia, aMessageArray); + } + } + else + { + User::Leave(KErrArgument); + } + } + break; +#endif // ABSTRACTAUDIOALBUM_INCLUDED + case EMPXSong: + { + // For the use case of adding thousands of songs at once, + // we do not create a new database transaction for each song; + // Instead DoAddL() will batch 100 songs under a single transaction. + // This enhancement improves performance with MMC-based databases. + if (aBatchCommit) + { + itemId = iDbHandler->AddSongWithNoTransactionL(aMedia, &aMessageArray); + } + else + { + itemId = iDbHandler->AddSongL(aMedia, &aMessageArray); + } + + MPXDbCommonUtil::AddItemChangedMessageL(aMessageArray, itemId, EMPXItemInserted, + EMPXSong, KDBPluginUid); + } + break; + + default: + { + User::Leave(KErrNotSupported); + } + } + + return itemId; + } + +// ---------------------------------------------------------------------------- +// Update the collection from a media +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoSetL( + const CMPXMedia& aMedia ) + { + MPX_FUNC("CMPXDbPlugin::DoSetL"); + + if (!aMedia.IsSupported(KMPXMediaGeneralType)) + { + User::Leave(KErrArgument); + } + + CMPXDbActiveTask::TChangeVisibility visibleChange(CMPXDbActiveTask::ENotVisibile); + + CMPXMessageArray* changeMsgArray = CMPXMessageArray::NewL(); + CleanupStack::PushL(changeMsgArray); + + if (aMedia.ValueTObjectL(KMPXMediaGeneralType) == EMPXGroup) + { + if (!aMedia.IsSupported(KMPXMediaArrayContents)) + { + User::Leave(KErrArgument); + } + + CMPXMediaArray* array = aMedia.Value(KMPXMediaArrayContents); + User::LeaveIfNull( array ); + TInt count( array->Count() ); + for (TInt i = 0; i < count; ++i) + { + visibleChange = (CMPXDbActiveTask::TChangeVisibility)(visibleChange | DoSetItemL(*array->AtL(i), *changeMsgArray)); + } + } + else + { + visibleChange = DoSetItemL(aMedia, *changeMsgArray); + } + + // Handle Change Events + if (visibleChange) + { + iActiveTask->SetVisibleChange(visibleChange); + DoHandleChangeL(changeMsgArray); + } + CleanupStack::PopAndDestroy(changeMsgArray); + } + +// ---------------------------------------------------------------------------- +// Execute a task step for async set +// ---------------------------------------------------------------------------- +// +TBool CMPXDbPlugin::DoSetAsyncL() + { + MPX_FUNC("CMPXDbPlugin::DoSetAsyncL"); + + TBool done(EFalse); + CMPXMedia* task = iActiveTask->GetCommand().Value(KMPXCommandColSetMedia); + User::LeaveIfNull( task ); + + CMPXMessageArray& msgArray = iActiveTask->GetChangeMessages(); + CMPXDbActiveTask::TChangeVisibility visibleChange(iActiveTask->GetVisibleChange()); + + // Multiple steps can be in a transaction for faster response + if( !iDbHandler->InTransaction() ) + { + iDbHandler->BeginTransactionL(); + } + + if (!task->IsSupported(KMPXMediaGeneralType)) + { + User::Leave(KErrArgument); + } + + if (task->ValueTObjectL(KMPXMediaGeneralType) == EMPXGroup) + { + if (!task->IsSupported(KMPXMediaArrayContents)) + { + User::Leave(KErrArgument); + } + + // Multiple items + CMPXMediaArray* array = task->Value(KMPXMediaArrayContents); + User::LeaveIfNull( array ); + TInt step = iActiveTask->GetStep(); + visibleChange = (CMPXDbActiveTask::TChangeVisibility)(visibleChange | DoSetItemL(*array->AtL(step), msgArray)); + + if (++step == array->Count()) + { + done = ETrue; + } + } + else // Single item + { + visibleChange = DoSetItemL(*task, msgArray); + done = ETrue; + } + iActiveTask->SetVisibleChange(visibleChange); + return done; + } + +// ---------------------------------------------------------------------------- +// Update the collection from a media +// ---------------------------------------------------------------------------- +// +CMPXDbActiveTask::TChangeVisibility CMPXDbPlugin::DoSetItemL( + const CMPXMedia& aMedia, + CMPXMessageArray& aMessageArray ) + { + MPX_FUNC("CMPXDbPlugin::DoSetItemL"); + + TMPXGeneralCategory category = aMedia.ValueTObjectL(KMPXMediaGeneralCategory); + + CMPXDbActiveTask::TChangeVisibility visibleChange(CMPXDbActiveTask::ENotVisibile); + switch (category) + { + case EMPXPlaylist: + { + if (aMedia.IsSupported(KMPXMediaArrayContents)) + { + CMPXMessage* message = CMPXMedia::NewL(); + CleanupStack::PushL(message); + + iDbHandler->UpdatePlaylistSongsL(aMedia, *message); + + aMessageArray.AppendL(message); // ownership xfer + CleanupStack::Pop(message); + } + else + { + iDbHandler->UpdatePlaylistL(aMedia, aMessageArray); + } + + visibleChange = CMPXDbActiveTask::ESingleVisible; + } + break; +#ifdef ABSTRACTAUDIOALBUM_INCLUDED + case EMPXAbstractAlbum: + { + //update all songes which associate with ABSTRACTALBUM + if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + //in case aMedia as mediaArray which contains songs as arrayContents, need to update all songs associated + if ( aMedia.IsSupported(KMPXMediaArrayContents)) + { + iDbHandler->UpdateSongsAbstractAlbumInfoL(aMedia, aMessageArray); + } + //only update field values in abstractalbum table, or renaming (change uri) for abstractalbum table + else + { + visibleChange = iDbHandler->UpdateAbstractAlbumL(aMedia, aMessageArray); + } + } + } + break; +#endif // ABSTRACTAUDIOALBUM_INCLUDED + case EMPXSong: + { + // a list of changed messages as a result of the song being updated + visibleChange = iDbHandler->UpdateSongL(aMedia, aMessageArray); + } + break; + + default: + { + User::Leave(KErrNotSupported); + } + break; + } + return visibleChange; // ownership xfer + } + +// ---------------------------------------------------------------------------- +// Sets the drm properties for a list of medias +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoSetDrmForArrayL( + const CMPXMediaArray& mediaArray, + const TArray& aAttrs) + { + MPX_FUNC("CMPXDbPlugin::DoSetDrmForArrayL"); + + TUint drmAttributes(0); + + // Compact the attribute set + // + TInt attrCount(aAttrs.Count()); + for (TInt i = 0; i < attrCount; ++i) + { + if (aAttrs[i].ContentId() == KMPXMediaIdDrm) + { + drmAttributes |= aAttrs[i].AttributeId(); + } + } + + // Fetch drm attributes for every item + // + if (drmAttributes) + { + TInt count(mediaArray.Count()); + for (TInt i = 0; i < count; ++i) + { + if (mediaArray[i]->IsSupported(KMPXMediaGeneralUri)) + { + DoSetMediaDrmL(*mediaArray[i], drmAttributes, + mediaArray[i]->ValueText(KMPXMediaGeneralUri)); + } + } + } + } + +// ---------------------------------------------------------------------------- +// Handle change events +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::HandleChangeL( + const CMPXMessage& aMessage) + { + MPX_FUNC("CMPXDbPlugin::HandleChange"); + + // check if message is filled + if (aMessage.IsSupported(KMPXMessageGeneralId)) + { +#if _DEBUG + PrintMessagesL(aMessage); +#endif // _DEBUG + if(iRefreshing) + { + if (aMessage.IsSupported(KMPXMessageArrayContents)) + { + const CMPXMessageArray* messageArray = aMessage.Value(KMPXMessageArrayContents); + if(messageArray) + { + CMPXMessage& message = *((*messageArray)[0]); + TMPXChangeEventType changeType( message.ValueTObjectL( KMPXMessageChangeEventType ) ); + TMPXGeneralCategory cat(message.ValueTObjectL(KMPXMessageMediaGeneralCategory)); + if(changeType == EMPXItemInserted && (cat == EMPXSong || cat == EMPXPlaylist || cat == EMPXPodcast)) + { + iObs->HandleMessage(aMessage); + } + } + } + else + { + TMPXChangeEventType changeType( aMessage.ValueTObjectL( KMPXMessageChangeEventType ) ); + TMPXGeneralCategory cat(aMessage.ValueTObjectL(KMPXMessageMediaGeneralCategory)); + if(changeType == EMPXItemInserted && (cat == EMPXSong || cat == EMPXPlaylist || cat == EMPXPodcast)) + { + iObs->HandleMessage(aMessage); + } + } + } + else + { + if(!iMtpInUse) + { + iObs->HandleMessage(aMessage); + } + } + } + } + +// ---------------------------------------------------------------------------- +// Construct a CMPXMedia and call HandleChange +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoHandleChangeL( + CMPXMessageArray* aItemChangedMessages, + TMPXCommandId aCommandId ) + { + MPX_FUNC("CMPXDbPlugin::DoHandleChangeL"); + + if( (iActiveTask->GetVisibleChange() & CMPXDbActiveTask::EAllVisible) + && (aCommandId == KMPXCommandIdCollectionSet || + aCommandId == KMPXCommandIdCollectionAdd || + aCommandId == KMPXCommandIdCollectionRemove || + aCommandId == KMPXCommandIdCollectionCompleteDelete )) + { + MPXDbCommonUtil::AddItemChangedMessageL(*aItemChangedMessages, EBrowseAll, + EMPXItemModified, EMPXCollection, KDBPluginUid); + } + // group change messages and send to collection client context + // + CMPXMessage* message = CMPXMessage::NewL(); + CleanupStack::PushL(message); + + message->SetTObjectValueL(KMPXMessageGeneralId, KMPXMessageIdItemChanged); + message->SetCObjectValueL(KMPXMessageArrayContents, aItemChangedMessages); + message->SetTObjectValueL(KMPXMessageArrayCount, aItemChangedMessages->Count()); + + HandleChangeL(*message); + + CleanupStack::PopAndDestroy(message); + } + +// ---------------------------------------------------------------------------- +// Handle completion of operation +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoHandleOperationCompletedL( + TInt aErr) + { + MPX_FUNC("CMPXDbPlugin::DoHandleOperationCompletedL"); + + // Broadcase change messages + // + if (iActiveTask->GetVisibleChange()) + { + DoHandleChangeL(&iActiveTask->GetChangeMessages(), iActiveTask->GetTask() ); + } + + // Callback to engine to signal completion + // NOTE: Collection server immediately completes the async message when + // Cancel is called, no need to callback to observer + if (aErr != KErrCancel) + { + if( iActiveTask->GetTask() == KMPXCommandIdCollectionAdd ) + { + iObs->HandleCommandComplete( &iActiveTask->GetCommand(), aErr ); + } + else + { + iObs->HandleCommandComplete(NULL, aErr); + } + } + + if( iDbHandler->InTransaction() ) + { + // Commit if cancelled + TInt err(aErr); + if( err == KErrCancel ) + { + err = KErrNone; + } + iDbHandler->EndTransactionL( err ); + } + } + +// ---------------------------------------------------------------------------------------------------------- +// Complete a delete operation +// ---------------------------------------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoHandleDeleteCompleteL( + CMPXCommand& aCmd) + { + MPX_FUNC("CMPXDbPlugin::DoHandleDeleteCompleteL"); + iFirstDeleteStep = ETrue; + iSelections.Reset(); + if ( iDbHandler->InTransaction() ) + { + // if it can reach this point in a transaction, there's no error + iDbHandler->EndTransactionL( KErrNone ); + } + + // Change messages + if (aCmd.IsSupported(KMPXCommandCollectionDeleteMsgArray)) + { + CMPXMessageArray* msgs = aCmd.Value(KMPXCommandCollectionDeleteMsgArray); + User::LeaveIfNull( msgs ); + iActiveTask->SetVisibleChange(CMPXDbActiveTask::EAllVisible); + DoHandleChangeL(msgs, KMPXCommandIdCollectionCompleteDelete); + } + } + +// ---------------------------------------------------------------------------------------------------------- +// Reorder a song in a playlist +// ---------------------------------------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoReorderPlaylistL( + const CMPXCommand& aCmd) + { + MPX_FUNC("CMPXDbPlugin::DoReorderPlaylistL"); + + if (!aCmd.IsSupported(KMPXCommandReorderPlaylistId) || + !aCmd.IsSupported(KMPXCommandReorderSongId) || + !aCmd.IsSupported(KMPXCommandReorderOriginalOrdinal) || + !aCmd.IsSupported(KMPXCommandReorderNewOrdinal)) + { + User::Leave(KErrArgument); + } + + CMPXMessage* message = CMPXMedia::NewL(); + CleanupStack::PushL(message); + + iDbHandler->ReorderPlaylistL( + aCmd.ValueTObjectL(KMPXCommandReorderPlaylistId), + aCmd.ValueTObjectL(KMPXCommandReorderSongId), + aCmd.ValueTObjectL(KMPXCommandReorderOriginalOrdinal), + aCmd.ValueTObjectL(KMPXCommandReorderNewOrdinal), + *message); + + HandleChangeL(*message); + + CleanupStack::PopAndDestroy(message); + } + +// ---------------------------------------------------------------------------------------------------------- +// Get total songs and playlists count for a database +// ---------------------------------------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoGetCollectionCountL( const CMPXCommand& aCmd ) + { + MPX_FUNC("CMPXDbPlugin::DoGetCollectionCountL"); + if (!aCmd.IsSupported(KMPXCommandCollectionCountDrive) || + !aCmd.IsSupported(KMPXCommandCollectionCountTable) ) + { + User::Leave(KErrArgument); + } + + TInt count = 0; + TInt drive = aCmd.ValueTObjectL(KMPXCommandCollectionCountDrive); + TInt table = aCmd.ValueTObjectL(KMPXCommandCollectionCountTable); + switch(table) + { + case EMPXCollectionCountTrack: + count = (TInt)iDbHandler->GetMusicCountL(drive); + break; + case EMPXCollectionCountPlaylist: + count = (TInt)iDbHandler->GetPlaylistCountL(drive); + break; + case EMPXCollectionCountTotal: + count = (TInt)iDbHandler->GetTotalCountL(drive); + break; + default: + User::Leave(KErrArgument); + } + ((CMPXMedia&)aCmd).SetTObjectValueL(KMPXCommandCollectionCountValue, count); + } + +// ---------------------------------------------------------------------------------------------------------- +// Get URIs for all songs and file playlists in a database +// ---------------------------------------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoGetCollectionUriL( const CMPXCommand& aCmd ) + { + MPX_FUNC("CMPXDbPlugin::DoGetCollectionCountL"); + if (!aCmd.IsSupported(KMPXCommandCollectionURIDrive) || + !aCmd.IsSupported(KMPXCommandCollectionURITable) || + !aCmd.IsSupported(KMPXCommandCollectionURIFromID) || + !aCmd.IsSupported(KMPXCommandCollectionURIRecords) ) + { + User::Leave(KErrArgument); + } + + TInt drive = aCmd.ValueTObjectL(KMPXCommandCollectionURIDrive); + TInt table = aCmd.ValueTObjectL(KMPXCommandCollectionURITable); + TInt fromID = aCmd.ValueTObjectL(KMPXCommandCollectionURIFromID); + TInt recnum = aCmd.ValueTObjectL(KMPXCommandCollectionURIRecords); + + CDesCArray* uris = new(ELeave) CDesCArrayFlat(4); + CleanupStack::PushL(uris); + TInt lastID = 0; + + switch(table) + { + case EMPXCollectionURITrack: + iDbHandler->GetMusicUriArrayL(drive, fromID, recnum, *uris, lastID); + break; + case EMPXCollectionURIPlaylist: + iDbHandler->GetPlaylistUriArrayL(drive, fromID, recnum, *uris, lastID); + break; + default: + User::Leave(KErrArgument); + } + + ((CMPXMedia&)aCmd).SetNoNewLCObjectL(KMPXCommandCollectionURIList, uris); + ((CMPXMedia&)aCmd).SetTObjectValueL(KMPXCommandCollectionURILastID, lastID); + CleanupStack::PopAndDestroy(uris); + } + + +// ---------------------------------------------------------------------------------------------------------- +// Perform one step of the incremental operation +// ---------------------------------------------------------------------------------------------------------- +// +void CMPXDbPlugin::DoIncrementalOpenL( const CMPXCommand& aCmd ) + { + MPX_DEBUG1("CMPXDbPlugin::DoIncrementalOpenL <--"); + + TInt offset = aCmd.ValueTObjectL( KMPXCollectionCommandIdIncOpenLOffset ); + TInt numItems = aCmd.ValueTObjectL( KMPXCollectionCommandIdIncOpenLNumItems ); + + TReadDirection direction(EReadUnknown); +/* Ascending and Decending reads are currently not used. We optimized for offset reads. + if( aCmd.IsSupported(KMPXCollectionCommandIdIncOpenLAscDsc) && + aCmd.IsSupported(KMPXCollectionCommandIdIncOpenLKeyItem) ) + { + direction = aCmd.ValueTObjectL(KMPXCollectionCommandIdIncOpenLAscDsc); + } +*/ + CMPXCollectionPath* path = aCmd.ValueCObjectL(KMPXCollectionCommandIdIncOpenLPath); + CleanupStack::PushL( path ); + MPX_DEBUG_PATH( *path ); + + // Switch on level and item selected + // + TInt levels( path->Levels() ); + switch( levels ) + { + case 3: // levels of 3 top level is not stripped + { + switch( path->Id(1).iId2 ) + { + case EBrowseAll: + { + CMPXMedia* results = CMPXMedia::NewL(); + CleanupStack::PushL( results ); + + TMPXOpenDataBlock block; + block.iOffset = offset; + block.iSize = numItems; + + // Todo: this should come from the UI + RArray attrs; + CleanupClosePushL( attrs ); + attrs.AppendL(TMPXAttribute(KMPXMediaIdGeneral, + EMPXMediaGeneralId | EMPXMediaGeneralType | EMPXMediaGeneralCategory | + EMPXMediaGeneralTitle | EMPXMediaGeneralFlags)); + attrs.AppendL( TMPXAttribute(KMPXMediaIdMusic, + EMPXMediaMusicArtist | EMPXMediaMusicAlbumArtFileName ) ); + + // Array to read data from + CMPXMediaArray* array = CMPXMediaArray::NewL(); + CleanupStack::PushL( array ); + + // Do we have to use offset or can we use asc/dsc + // + if( direction == EReadUnknown ) + { + iDbHandler->GetSongsAtOffsetL( array, attrs.Array(), offset, numItems ); + } + else + { + iDbHandler->GetSongsInBlockL( array, attrs.Array(), + aCmd.ValueText( KMPXCollectionCommandIdIncOpenLKeyItem ), + numItems, + direction ); + } + + TInt max( path->Count() ); + TInt count(0); + TInt aryCount( array->Count() ); + // Update the collection path + while( countAtL(count)->ValueTObjectL( KMPXMediaGeneralId ); + path->Update( offset, id ); + + // Next items + offset++; + count++; + } + + // Setup the results + // + results->SetCObjectValueL(KMPXMediaArrayContents, array); + results->SetTObjectValueL(KMPXMediaArrayCount, array->Count()); + CleanupStack::PopAndDestroy( array ); + CleanupStack::PopAndDestroy( &attrs ); + + // Callback with results + // + results->SetTObjectValueL( KMPXCollectionOpenLResultRange, block ); + iObs->HandleOpen( results, path, KErrNone ); + CleanupStack::PopAndDestroy( results ); + break; + } + default: + User::Leave(KErrNotSupported); + break; + } + break; + } + default: + { + User::Leave(KErrNotSupported); + break; + } + + } + CleanupStack::PopAndDestroy( path ); + + MPX_DEBUG1("CMPXDbPlugin::DoIncrementalOpenL -->"); + } + +// ---------------------------------------------------------------------------- +// Maps a given browse type to a category ID. +// ---------------------------------------------------------------------------- +// +TMPXGeneralCategory CMPXDbPlugin::CategoryForBrowseType( + TMCBrowseType aBrowseType) + { + MPX_FUNC("CMPXDbPlugin::CategoryForBrowseType"); + + TMPXGeneralCategory cat(EMPXNoCategory); + + switch (aBrowseType) + { + case EBrowseAll: + { + cat = EMPXSong; + break; + } + case EBrowseArtist: + { + cat = EMPXArtist; + break; + } + case EBrowseAlbum: + { + cat = EMPXAlbum; + break; + } + case EBrowsePlaylist: + { + cat = EMPXPlaylist; + break; + } + case EBrowseGenre: + { + cat = EMPXGenre; + break; + } + case EBrowseComposer: + { + cat = EMPXComposer; + break; + } +#ifdef __ENABLE_PODCAST_IN_MUSIC_MENU + case EBrowsePodcasts: + { + cat = EMPXPodcast; + break; + } +#endif + default: + { + // do nothing + break; + } + } + + return cat; + } + +// ---------------------------------------------------------------------------- +// Maps a given category ID to a browse type. +// ---------------------------------------------------------------------------- +// +TMCBrowseType CMPXDbPlugin::BrowseTypeForCategory( + TMPXGeneralCategory aCategory) + { + MPX_FUNC("CMPXDbPlugin::BrowseTypeForCategory"); + + TMCBrowseType browseType(EBrowseComposer); + + switch (aCategory) + { + case EMPXSong: + { + browseType = EBrowseAll; + break; + } + case EMPXArtist: + { + browseType = EBrowseArtist; + break; + } + case EMPXAlbum: + { + browseType = EBrowseAlbum; + break; + } + case EMPXPlaylist: + { + browseType = EBrowsePlaylist; + break; + } + case EMPXGenre: + { + browseType = EBrowseGenre; + break; + } + default: + { + // do nothing + break; + } + } + + return browseType; + } + +// ---------------------------------------------------------------------------- +// Sets the type, category and title attributes in the specified media instance +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::SetMediaGeneralAttributesL( + CMPXMedia& aMedia, + TMPXGeneralType aType, + TMPXGeneralCategory aCategory, + const TDesC& aTitle) + { + aMedia.SetTObjectValueL(KMPXMediaGeneralType, aType); + aMedia.SetTObjectValueL(KMPXMediaGeneralCategory, aCategory); + aMedia.SetTextValueL(KMPXMediaGeneralTitle, aTitle); + } + +// ---------------------------------------------------------------------------- +// Sets the type, category and title attributes in the specified media instance +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::SetMediaGeneralAttributesL( + CMPXMedia& aMedia, + TMPXGeneralType aType, + TMPXGeneralCategory aCategory, + TInt aId) + { + MPX_FUNC("CMPXDbPlugin::SetMediaGeneralAttributesL"); + + HBufC* title = iDbHandler->GetNameMatchingIdL(aId); + CleanupStack::PushL(title); + SetMediaGeneralAttributesL(aMedia, aType, aCategory, *title); + CleanupStack::PopAndDestroy(title); + } + +// ---------------------------------------------------------------------------- +// Set the attribute list according to current path +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::SetAttributesL( + const CMPXCollectionPath& aPath, + RArray& aAttrs, + RArray& aSupportedIds ) + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdGeneral, + EMPXMediaGeneralId | EMPXMediaGeneralType | EMPXMediaGeneralCategory | + EMPXMediaGeneralTitle | EMPXMediaGeneralFlags) ); + + aSupportedIds.AppendL(KMPXMediaIdContainer); + aSupportedIds.AppendL(KMPXMediaIdGeneral); + + TInt levels(aPath.Levels()); + if ( 2 == levels ) + { + // check the browse type + switch ( aPath.Id(1).iId2 ) + { + case EBrowseAll: + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdMusic, + EMPXMediaMusicArtist | EMPXMediaMusicAlbumArtFileName ) ); + aSupportedIds.AppendL( KMPXMediaIdMusic ); + break; + } + case EBrowseArtist: + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdGeneral, EMPXMediaGeneralCount) ); + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdMusic, + EMPXMediaMusicAlbumArtFileName ) ); + break; + } + case EBrowseAlbum: + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdMusic, + EMPXMediaMusicArtist | EMPXMediaMusicAlbum | EMPXMediaMusicAlbumArtFileName ) ); + aSupportedIds.AppendL( KMPXMediaIdMusic ); + break; + } + case EBrowsePlaylist: + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdGeneral, + EMPXMediaGeneralCount | EMPXMediaGeneralDuration ) ); + break; + } + case EBrowseGenre: + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdGeneral, EMPXMediaGeneralCount) ); + break; + } + case EBrowseComposer: + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdGeneral, EMPXMediaGeneralCount) ); + break; + } + default: + { + User::Leave(KErrArgument); + } + } + } + else if ( 3 == levels ) + { + // check the browse type + switch ( aPath.Id(1).iId2 ) + { + case EBrowseArtist: + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdGeneral, EMPXMediaGeneralCount) ); + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdMusic, EMPXMediaMusicAlbumArtFileName ) ); + aSupportedIds.AppendL( KMPXMediaIdMusic ); + break; + } + case EBrowseAlbum: + { + + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdMusic, + EMPXMediaMusicArtist | EMPXMediaMusicAlbum | EMPXMediaMusicAlbumArtFileName ) ); + aSupportedIds.AppendL( KMPXMediaIdMusic ); + break; + } + case EBrowsePlaylist: + case EBrowseGenre: + case EBrowseComposer: + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdMusic, +// EMPXMediaMusicArtist | EMPXMediaMusicAlbumArtFileName ) ); + //added ganes + EMPXMediaMusicArtist | EMPXMediaMusicAlbumArtFileName | EMPXMediaMusicAlbum) ); + aSupportedIds.AppendL( KMPXMediaIdMusic ); + break; + } + } + } + else if ( (4 == levels) && (aPath.Id(1).iId2 == EBrowseArtist) ) + { + aAttrs.AppendL( TMPXAttribute(KMPXMediaIdMusic, + EMPXMediaMusicArtist | EMPXMediaMusicAlbum | EMPXMediaMusicAlbumArtFileName ) ); + aSupportedIds.AppendL( KMPXMediaIdMusic ); + } + } + +#ifdef _DEBUG +// ---------------------------------------------------------------------------- +// Print change events +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::PrintMessagesL( + const CMPXMessage& aMessage) + { + MPX_FUNC("CMPXDbPlugin::PrintMessages"); + + if (aMessage.IsSupported(KMPXMessageArrayContents)) + { + const CMPXMessageArray* messageArray = + aMessage.Value(KMPXMessageArrayContents); + if( !messageArray ) + { + User::Leave( KErrNoMemory ); + } + + TInt count(messageArray->Count()); + MPX_DEBUG2("%d messages:", count); + + for (TInt i = 0; i < count; ++i) + { + PrintMessage(*((*messageArray)[i])); + } + } + else + { + PrintMessage(aMessage); + } + } + +// ---------------------------------------------------------------------------- +// Print one change event +// ---------------------------------------------------------------------------- +// +void CMPXDbPlugin::PrintMessage( + const CMPXMessage& aMessage) + { + MPX_FUNC("CMPXDbPlugin::PrintMessage"); + + if (aMessage.IsSupported(KMPXMessageGeneralId)) + { + TMPXItemId id = aMessage.ValueTObjectL(KMPXMessageGeneralId); + MPX_DEBUG3(" message id[0x%x, 0x%x]", id.iId1, id.iId2); + } + + if (aMessage.IsSupported(KMPXMessageCollectionId)) + { + TUid uid = aMessage.ValueTObjectL(KMPXMessageCollectionId); + MPX_DEBUG2(" uid [0x%x]", uid.iUid); + } + + if (aMessage.IsSupported(KMPXMessageChangeEventType)) + { + MPX_DEBUG2(" change event type [%d]", + aMessage.ValueTObjectL(KMPXMessageChangeEventType)); + } + + if (aMessage.IsSupported(KMPXMessageMediaGeneralCategory)) + { + MPX_DEBUG2(" category [%d]", + aMessage.ValueTObjectL(KMPXMessageMediaGeneralCategory)); + } + + if (aMessage.IsSupported(KMPXMessageMediaGeneralId)) + { + TMPXItemId id = aMessage.ValueTObjectL(KMPXMessageMediaGeneralId); + MPX_DEBUG3(" media id[0x%x, 0x%x]", id.iId1, id.iId2); + } + + if (aMessage.IsSupported(KMPXMessageMediaDeprecatedId)) + { + TMPXItemId id = aMessage.ValueTObjectL(KMPXMessageMediaDeprecatedId); + MPX_DEBUG3(" deprecated id [0x%x, 0x%x]", id.iId1, id.iId2); + } + } + +#endif// _DEBUG + +// End of file