diff -r 000000000000 -r a2952bb97e68 mpx/collectionframework/collectionengine/src/mpxcollectionclientcontext.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpx/collectionframework/collectionengine/src/mpxcollectionclientcontext.cpp Thu Dec 17 08:55:47 2009 +0200 @@ -0,0 +1,2613 @@ +/* +* 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: Maintains sessions to paths +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mpxcollectionengineobserver.h" +#include "mpxcollectionpluginhandler.h" +#include "mpxcollectionengine.h" +#include "mpxcollectioncache.h" +#include "mpxcollectionclientcontext.h" + +// ---------------------------------------------------------------------------- +// Helper. Sets next open mode on path +// ---------------------------------------------------------------------------- +// +LOCAL_C void SetPathOpenMode(CMPXCollectionPath& aPath, TInt aMode) + { + TMPXOpenMode mode=static_cast(aMode); + if (aPath.Levels()) + { + aPath.Set(mode == EMPXOpenDefault ? aPath.OpenPreviousMode() : mode); + } + } + +// ---------------------------------------------------------------------------- +// Helper. Returns whether next open mode is the same as previous open +// request +// ---------------------------------------------------------------------------- +// +LOCAL_C TBool OpenModeValid(const CMPXCollectionPath& aPath) + { + TMPXOpenMode next=aPath.OpenNextMode(); + return (aPath.OpenPreviousMode() == next) || (next == EMPXOpenDefault); + } + +// ============================ MEMBER FUNCTIONS ============================== + +// ---------------------------------------------------------------------------- +// Two-phased constructor. +// ---------------------------------------------------------------------------- +// +CMPXCollectionClientContext* CMPXCollectionClientContext::NewL( + CMPXCollectionEngine& aEngine, + CMPXCollectionCache& aCache, + const TUid& aModeId) + { + CMPXCollectionClientContext* p = + new(ELeave) CMPXCollectionClientContext(aEngine, aCache, aModeId); + CleanupStack::PushL(p); + p->ConstructL(); + CleanupStack::Pop(p); + return p; + } + +// ---------------------------------------------------------------------------- +// C++ constructor. +// ---------------------------------------------------------------------------- +// +CMPXCollectionClientContext::CMPXCollectionClientContext( + CMPXCollectionEngine& aEngine, + CMPXCollectionCache& aCache, + const TUid& aModeId) + : iModeId(aModeId),iFocusItemId(KMPXInvalidItemId), + iEngine(aEngine),iCache(aCache) + { + } + +// ---------------------------------------------------------------------------- +// 2nd phase constructor. +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::ConstructL() + { + iClientList = CMPXClientList::NewL(); + iBrowsePath = CMPXCollectionPath::NewL(); + iMedia = CMPXMedia::NewL(); // empty media + // initialize to null uid + for (TInt index = 0; index < EContextCount; ++index) + { + iPluginUids.AppendL(KNullUid); + } + } + +// ---------------------------------------------------------------------------- +// Destructor +// ---------------------------------------------------------------------------- +// +CMPXCollectionClientContext::~CMPXCollectionClientContext() + { + MPX_DEBUG2("CMPXCollectionClientContext::~CMPXCollectionClientContext %08x", + this); + + // Release all plugins this context has references on, this could result in the + // plugin(s) being unloaded. + for (TInt index = 0; index < EContextCount; ++index) + { + if (iPluginUids[index] != KNullUid) + { + iEngine.ReleasePlugin(iPluginUids[index]); + } + } + + delete iClientList; + delete iBrowsePath; + delete iMediaPath; + delete iMedia; + delete iFilter; + iPluginUids.Close(); + iUids.Close(); + } + +// ---------------------------------------------------------------------------- +// Open collection by path +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::OpenL( + CMPXCollectionPath* aPath, + TInt aMode, + MMPXCollectionEngineObserver* aCallback) + { + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 1 <--"); + MPX_ASSERT(aPath); + if (aPath->Levels() > 0) + { + // Increment the plugin reference count + CMPXCollectionPlugin*plugin = iEngine.ResolvePluginL(*aPath); + if (!plugin) + { + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 1 bad path plugin"); + User::Leave(KErrArgument); + } + + iEngine.CleanupPluginPushL(plugin); + + // Ownership of aPath transferred + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 1 Add task"); + plugin->AddTaskL(EMcsOpenPath, aCallback, this, + aMode, NULL, plugin, aPath); + + // Pop the plugin + iEngine.PluginPop(); + } + else + { // Go back to root level + MPX_DEBUG1("CMPXCollectionClientContext::OpenL restarting path"); + iIndex=0; + iFocusItemId = KMPXInvalidItemId; + InitL(aCallback); + } + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 1 -->"); + } + +// ---------------------------------------------------------------------------- +// Open collection by index +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::OpenL( + TInt aIndex, + TInt aMode, + const TArray& aAttrs, + MMPXCollectionEngineObserver* aCallback) + { + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 2 <--"); + if (iBrowsePath->Levels()<=0) + { + User::Leave(KErrNotReady); + } + if (aIndex<0 || aIndex>=iBrowsePath->Count()) + { + User::Leave(KErrArgument); + } + iBrowsePath->Set(aIndex); + // plugin not resolved yet + if (iPluginUids[EContextBrowse] == KNullUid) + { + // Increment the new plugin reference count, decrement the old. + // No need to push/release the plugin it is stored in a member + // variable and will be released when that is overwritten. + ResolvePluginL(*iBrowsePath, iPluginUids[EContextBrowse]); + } + + if (iPluginUids[EContextBrowse] == KNullUid) + { + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 2 bad plugin"); + User::Leave(KErrNotReady); + } + + // add request to the queue + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 2 Add task"); + iBrowsePath->SetL(aAttrs); + LoadedPlugin(EContextBrowse)->AddTaskL(EMcsOpenIndex, aCallback, this, + aIndex, NULL, (TAny*)aMode); + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 2 -->"); + } + +// ---------------------------------------------------------------------------- +// Open collection by uids +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::OpenL( + const TArray& aUids, + TInt aMode, + MMPXCollectionEngineObserver* aCallback) + { + // Update path for open request + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 3 <---"); + SetPathOpenMode(*iBrowsePath,aMode); + if (!MPXUser::CompareOrderedUidArrays(iUids.Array(), aUids)) + { // the same context + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 3 return Open"); + aCallback->HandleOpen(iMedia, iIndex, ETrue, iMediaType); + } + else + { // go back to root level + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 3 Going to Root"); + iUids.Reset(); + ::CopyArrayL(aUids, iUids); + iIndex=0; + iFocusItemId = KMPXInvalidItemId; + InitL(aCallback); + } + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 3 --->"); + } + +// ---------------------------------------------------------------------------- +// Request current content of browse context +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::OpenL( + TInt aMode, + MMPXCollectionEngineObserver* aCallback) + { + // Update path for open request + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 <---"); + SetPathOpenMode(*iBrowsePath,aMode); + if (iPluginUids[EContextBrowse] == KNullUid) + {// No plug-in has been resolved + if (iBrowsePath->Levels() == 0) + // + // Open called at root level: just need to list the plug-ins, + // no need to resolve any plugin. Open request doesn't apply + // at this level + { + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 InitL()"); + iIndex=0; + iFocusItemId = KMPXInvalidItemId; + InitL(aCallback); + } + else if (OpenModeValid(*iBrowsePath) && !iPathUpdated) + // + // The existing media is still valid (no change + // in the request for entries + // + { + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 return media"); + aCallback->HandleOpen(iMedia, + iIndex, ETrue, + iMediaType); + } + else // Open mode has changed and open NOT called at root level + { + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 add task different open mode"); + ResolvePluginL(*iBrowsePath, iPluginUids[EContextBrowse]); // Find a plug-in + if (iPluginUids[EContextBrowse] != KNullUid) + { + LoadedPlugin(EContextBrowse)->AddTaskL(EMcsOpen, aCallback, this); + } + } + } + else + { + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 add task"); + LoadedPlugin(EContextBrowse)->AddTaskL(EMcsOpen, aCallback,this); + } + MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 --->"); + } + +// ---------------------------------------------------------------------------- +// Media request by collection path +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::BackL( + MMPXCollectionEngineObserver* aCallback) + { + MPX_DEBUG1("CMPXCollectionClientContext::BackL()"); + if (iPluginUids[EContextBrowse]==KNullUid) + { + User::Leave(KErrNotReady); + } + + MPX_DEBUG1("CMPXCollectionClientContext::BackL() -- Add task"); + LoadedPlugin(EContextBrowse)->AddTaskL(EMcsBack, aCallback, this); + } + +// ---------------------------------------------------------------------------- +// MediaL command +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::MediaL( + const CMPXCommand& aCmd, + MMPXCollectionEngineObserver* aCallback) + { + CMPXCollectionPath* path = + aCmd.ValueCObjectL(KMPXCommandGeneralTargetIds); + CleanupStack::PushL(path); + + // Increment the plugin reference count + CMPXCollectionPlugin*plugin = iEngine.ResolvePluginL(*path); + if (!plugin) + { + User::Leave(KErrArgument); + } + + iEngine.CleanupPluginPushL(plugin); + + CMPXCommand* cmd = CMPXCommand::NewL(aCmd); // make a copy + CleanupStack::PushL(cmd); + + plugin->AddTaskL(EMcsMediaByPath, aCallback, this, + 0, NULL, plugin, cmd, path); + + CleanupStack::Pop(cmd); // Ownership transferred to the task queue + iEngine.PluginPop(); // Pop the plugin + CleanupStack::Pop(path);// Ownership transferred to the task queue + } + +// ---------------------------------------------------------------------------- +// Add a media +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::AddL(const CMPXMedia& aMedia) + { + DoUpdateMediaL( EMcsAddItem, aMedia ); + } + +// ---------------------------------------------------------------------------- +// Remove a media +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::RemoveL(const CMPXMedia& aMedia) + { + DoUpdateMediaL( EMcsRemoveItem, aMedia ); + } + +// ---------------------------------------------------------------------------- +// Update a media +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::SetL(const CMPXMedia& aMedia) + { + DoUpdateMediaL( EMcsSetMedia, aMedia ); + } + +// ---------------------------------------------------------------------------- +// Remove media by path +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::RemoveL( + CMPXCollectionPath* aPath, + MMPXCollectionEngineObserver* aCallback) + { + TInt id(aPath->Id(CMPXCollectionPath::ECollectionUid)); + + // Increment the plugin reference count + CMPXCollectionPlugin* plugin = iEngine.ResolvePluginL(TUid::Uid(id)); + if (!plugin) + { + User::Leave(KErrArgument); + } + + iEngine.CleanupPluginPushL(plugin); + + // Ownership of aPath transferred + plugin->AddTaskL(EMcsRemovePath, aCallback, this, 0, NULL, plugin, aPath); + + iEngine.PluginPop(); + } + +// ---------------------------------------------------------------------------- +// Return current plugin id +// ---------------------------------------------------------------------------- +// +EXPORT_C TUid CMPXCollectionClientContext::PluginId() const + { + return iPluginUids[EContextBrowse]; + } + +// ---------------------------------------------------------------------------- +// Handle async request from client +// ---------------------------------------------------------------------------- +// +EXPORT_C const CMPXCollectionPath& CMPXCollectionClientContext::Path() const + { + return *iBrowsePath; + } + +// ---------------------------------------------------------------------------- +// Cancel request +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::CancelRequest( + MMPXCollectionEngineObserver* aCallback) + { + MPX_DEBUG3("CMPXCollectionClientContext::CancelRequest, this %08x, aCallback %08x", + this, aCallback); + iEngine.RemoveTask(aCallback); + } + +// ---------------------------------------------------------------------------- +// Add a client +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::AddClientL( + TThreadId aId, + CMPXMessageQueue* aMsgQueue) + { + iClientList->AddClientL(aId, aMsgQueue); + } + +// ---------------------------------------------------------------------------- +// Remove a client +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::RemoveClient( + const CMPXMessageQueue& aMsgQueue) + { + MPX_DEBUG2("CMPXCollectionClientContext::RemoveClient with the message queue 0x%08x", + &aMsgQueue); + TInt index(iClientList->Find(aMsgQueue)); + if (KErrNotFound != index) + { + iClientList->RemoveClient(index); + } + if (!iClientList->ClientCount()) + { + iEngine.RemoveContext(*this); + } + } + +// ---------------------------------------------------------------------------- +// Gets the supported capabilities of the current browse plugin +// ---------------------------------------------------------------------------- +// +EXPORT_C TCollectionCapability CMPXCollectionClientContext::GetCapabilities() + { + TCollectionCapability cap(0); + if (iPluginUids[EContextBrowse]!=KNullUid) + { + LoadedPlugin(EContextBrowse)->GetCapabilities(); + } + return cap; + } + +// ---------------------------------------------------------------------------- +// Find all aSync +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::FindAllL( + const CMPXMedia& aMedia, + CBufBase* aBuf, + MMPXCollectionEngineObserver* aCallback) + { + CMPXCollectionPlugin* plugin(NULL); // Not owned + + // Increment the plugin reference count + ResolvePluginL(aMedia, plugin); + if (!plugin) + { + User::Leave(KErrNotFound); // found nothing + } + + iEngine.CleanupPluginPushL(plugin); + + // Add the task + CMPXMedia* media = CMPXMedia::NewL(aMedia); + CleanupStack::PushL(media); + plugin->AddTaskL(EMcsFindAll, aCallback, this, 0, aBuf, plugin, media); + CleanupStack::Pop(media); // Ownership transferred + + iEngine.PluginPop(); + } + +// ---------------------------------------------------------------------------- +// Find all sync +// ---------------------------------------------------------------------------- +// +EXPORT_C CMPXMedia* CMPXCollectionClientContext::FindAllSyncL( + const CMPXMedia& aMedia, + const CBufBase& aBuf) + { + CMPXCollectionPlugin* plugin(NULL); // Not owned + + // Increment the plugin reference count + ResolvePluginL(aMedia, plugin); + iEngine.CleanupPluginPushL(plugin); + + CMPXMedia* result(NULL); + FindAllL(aMedia, aBuf, *plugin, &result, ETrue); + + // Synchronous call, safe to release the plugin + CleanupStack::PopAndDestroy(); // plugin + return result; + } + +// ---------------------------------------------------------------------------- +// Set filter +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::SetFilterL(const CMPXFilter* aFilter) + { + delete iFilter; + iFilter = NULL; + iFilter = aFilter ? CMPXFilter::NewL(*aFilter) : NULL; + } + +// ---------------------------------------------------------------------------- +// Returns filter +// ---------------------------------------------------------------------------- +// +EXPORT_C const CMPXFilter* CMPXCollectionClientContext::Filter() const + { + return iFilter; + } + +// ---------------------------------------------------------------------------- +// Handle a command +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::CommandL( + TMPXCollectionCommand aCmd, + TInt aData) + { + switch( aCmd ) + { + case EMcCmdRemoveAll: + case EMcCmdReCreateDB: // fall through + case EMcCmdDbCorrupted: // fall through + { + TUid uid = TUid::Uid(aData); + + // Increment the plugin reference count + CMPXCollectionPlugin* plugin = iEngine.ResolvePluginL( uid ); + iEngine.CleanupPluginPushL(plugin); + + if( plugin ) + { + // The trap is needed to keep the plugin reference count in sync + plugin->CommandL(aCmd); + } + + CleanupStack::PopAndDestroy(); // plugin + break; + } + case EMcCmdSelect: + if (iBrowsePath->Levels()<=0) + { + User::Leave(KErrNotReady); + } + if (aData<0 || aData>=iBrowsePath->Count()) + { + User::Leave(KErrArgument); + } + iBrowsePath->Set(aData); + iClientList->SendMsgL( + TMPXCollectionMessage(TMPXCollectionMessage::EFocusChanged, + aData, aData)); + iIndex = aData; // iIndex will always be up to date + iFocusItemId = iBrowsePath->Id(); + break; + case EMcCmdCollectionInit: + case EMcCmdCollectionResyn: + { + TUid uid = TUid::Uid(aData); + // Increment the plugin reference count + CMPXCollectionPlugin* plugin = iEngine.ResolvePluginL(uid); + if( !plugin ) + { + User::Leave(KErrArgument); + } + + iEngine.CleanupPluginPushL(plugin); + + plugin->AddTaskL(EMcsCommand, NULL, this, aCmd, NULL, plugin); + + iEngine.PluginPop(); + break; + } + default: + { + User::Leave(KErrNotSupported); + break; + } + } + } + +// ---------------------------------------------------------------------------- +// Handle a command +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXCollectionClientContext::CommandL( + const CMPXCommand& aCmd, + MMPXCollectionEngineObserver* aCallback, + const CMPXMessageQueue& aMsgQueue) + { + // Use the plugin id defined by the command object, + // or the browse context if collection id not defined + CMPXCollectionPlugin* plugin = NULL; + if (aCmd.IsSupported(KMPXCommandGeneralCollectionId)) + { + TInt data = aCmd.ValueTObjectL(KMPXCommandGeneralCollectionId); + + // Increment the plugin reference count + plugin = iEngine.ResolvePluginL(TUid::Uid(data)); + } + if (!plugin && iPluginUids[EContextBrowse]!=KNullUid) + { + plugin = LoadedPlugin(EContextBrowse); + + // Increment the plugin reference count manually + iEngine.UsePlugin(plugin->Uid()); + } + iEngine.CleanupPluginPushL(plugin); + + TBool async(ETrue); // by default command is asynchronous + if (aCmd.IsSupported(KMPXCommandGeneralDoSync)) + { // check if command is sync + async=!(aCmd.ValueTObjectL(KMPXCommandGeneralDoSync)); + } + + if (async) + { // Async, cmd ownership transferred + if (!plugin) + { + User::Leave(KErrNotReady); + } + + CMPXCommand* cmd = CMPXCommand::NewL(aCmd); + CleanupStack::PushL(cmd); + plugin->AddTaskL(EMcsCommandExt, aCallback, this, 0, + NULL, plugin, cmd); + CleanupStack::Pop(cmd); + + // Async, the plugin pointer passed through the task queue + iEngine.PluginPop(); + } + else + { + DoHandleSyncCommandL(aCmd, aMsgQueue, plugin); + CleanupStack::PopAndDestroy(); // plugin + } + } + +// ---------------------------------------------------------------------------- +// Find a shareable client +// ---------------------------------------------------------------------------- +// +TBool CMPXCollectionClientContext::HasShareableClient( + TThreadId aId) + { + TBool ret(EFalse); + if (iModeId != KMcModePlaylist) + { + if (iClientList->IsClient(aId) ) // Just look for same thread + { + ret = ETrue; + } + } + return ret; + } + +// ---------------------------------------------------------------------------- +// Notifies all clients of events +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::NotifyL( TMPXCollectionBroadCastMsg aMsg, + TInt aData ) + { + iClientList->SendMsgL( + TMPXCollectionMessage(TMPXCollectionMessage::EBroadcastEvent, + aMsg,aData)); + } + +const TUid& CMPXCollectionClientContext::ModeId() const + { + return iModeId; + } + +// ---------------------------------------------------------------------------- +// Initialises from file. iFile is not owned here +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::OpenL() + { + if (iPathUpdated) + { + ReOpenL(); + } + else + { + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse); + MPX_ASSERT(plugin); + plugin->CompleteTask(); + if (plugin->Callback()) + { + plugin->Callback()->HandleOpen(iMedia, + iIndex, ETrue,iMediaType); + plugin->SetCallback( NULL ); // Reset current observer + plugin->SetObserver(iEngine); + } + } + } + +// ---------------------------------------------------------------------------- +// Cancels all outstanding calls (tasks): plug-in should only have one +// outstanding so that is canceled; the tasks are deleted and removed from the +// queue +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::BackL() + { + TInt d=iBrowsePath->Levels(); + if(d>1) + { + iPathUpdated = EFalse; + // remove last item - the actual item selected + iBrowsePath->Back(); + // preserve focus, since we're rebuilding this level + iIndex=iBrowsePath->Index(); + iFocusItemId = iBrowsePath->Id(); + ReOpenL(); + } + } + +// ---------------------------------------------------------------------------- +// Re-open current level +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::ReOpenL() + { + // remove last item - go to the container which contained the item + if (iBrowsePath->Levels()) + { + iBrowsePath->Back(); + } + if (iBrowsePath->Levels() == 0) + { + //Plugin must be resolved ealier + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse); + plugin->CompleteTask(); + InitL(plugin->Callback()); + } + else + { + DoPluginOpenL(); + } + } + +// ---------------------------------------------------------------------------- +// Retrieve media info based on a find criteria +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::FindAllL( + const CMPXMedia& aMedia, + const CBufBase& aBuf, + CMPXCollectionPlugin& aPlugin, + CMPXMedia** aResult /*= NULL*/, + TBool aSync /*= EFalse*/) + { + // Find critera and return attributes + // + RArray attrs; + CleanupClosePushL(attrs); + ::CreateFromBufferL(aBuf, attrs); + + // Do the query + if (!aSync) + { + aPlugin.SetObserver(*this); + aPlugin.FindAllL(aMedia,attrs.Array()); + } + else + { + *aResult = aPlugin.FindAllSyncL(aMedia,attrs.Array()); + } + CleanupStack::PopAndDestroy( &attrs ); + } + +// ---------------------------------------------------------------------------- +// CMPXCollectionClientContext::HandleMessage +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::HandleMessage( + CMPXMessage* aMsg, + TInt aError) + { + MPX_FUNC_EX("CMPXCollectionClientContext::HandleMessage"); + DoHandleMessage(aMsg, aError, ETrue); + } + +// ---------------------------------------------------------------------------- +// CMPXCollectionClientContext::HandleMessage +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoHandleMessage( + CMPXMessage* aMsg, + TInt aError, + TBool aNotifyOthers) + { + MPX_DEBUG3("-->CMPXCollectionClientContext::HandleMessage this %08x, %d", this, aNotifyOthers); + if (!aMsg) + { + iClientList->SendMsg(aMsg, aError); + if (aNotifyOthers) + { + iEngine.NotifyChange(*this, aMsg, aError); + } + } + else + { + if (aMsg->IsSupported(KMPXMessageGeneralId)) + { + if (aMsg->IsSupported(KMPXMessageArrayContents)) + { + TBool pathUpdated(EFalse); + const CMPXMessageArray* messageArray = + aMsg->Value(KMPXMessageArrayContents); + if (messageArray) + { + TInt count = messageArray->Count(); + + MPX_DEBUG2("%d messages:", count); + + for (TInt i=0; i(aMsg), + aError); + } + } + else + { + TRAP_IGNORE(DoHandleMessageL(*aMsg, aError)); + + // Notify other context, collection is changed. + if (aNotifyOthers) + { + iEngine.NotifyChange(*this, aMsg, aError); + } + } + + // Broadcast change messages to the clients to handle + // + if( iModeId == KMcModePlaylist ) + { + // Playlist should not be handling msgs during refresh + if( !iEngine.IsRefreshing() ) + { + iClientList->SendMsg( aMsg, aError ); + } + } + else + { + // Other modes receive msg all the time + iClientList->SendMsg( aMsg, aError ); + } + + // Batched collection change messages and only send this once + // Path changed isn't sent to the UI during refresh + // + if (iPathUpdated) + { + MPX_DEBUG1("CMPXCollectionClientContext::DoHandleMessageL detected path changed"); + MPX_DEBUG_PATH(*iBrowsePath); + // notify clients to refresh + TRAP_IGNORE(iClientList->SendMsgL( + TMPXCollectionMessage(TMPXCollectionMessage::EPathChanged, + EMcPathChangedByCollectionChange))); + } + } + } + + MPX_DEBUG3("<--CMPXCollectionClientContext::HandleMessage this %08x, %d", this, aNotifyOthers); + } + +// ---------------------------------------------------------------------------- +// Handle collection item change message +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoHandleMessageL( + const CMPXMessage& aMsg, + TInt /*aError*/) + { + MPX_DEBUG2("-->CMPXCollectionClientContext::DoHandleMessageL this %08x", this); + TInt browseLevels = iBrowsePath->Levels(); // browse depth + + if (aMsg.ValueTObjectL(KMPXMessageGeneralId)== + KMPXMessageIdItemChanged) + { + if (!aMsg.IsSupported(KMPXMessageCollectionId) || + !aMsg.IsSupported(KMPXMessageChangeEventType) || + !aMsg.IsSupported(KMPXMessageMediaGeneralCategory) || + !aMsg.IsSupported(KMPXMessageMediaGeneralId)) + { + User::Leave(KErrArgument); + } + + TUid collectionId = aMsg.ValueTObjectL(KMPXMessageCollectionId); + + TMPXChangeEventType changeType = + aMsg.ValueTObjectL(KMPXMessageChangeEventType); + + TMPXGeneralCategory category = + aMsg.ValueTObjectL(KMPXMessageMediaGeneralCategory); + + TMPXItemId itemId = aMsg.ValueTObjectL(KMPXMessageMediaGeneralId); + + TMPXItemId deprecatedId(0); + if (aMsg.IsSupported(KMPXMessageMediaDeprecatedId)) + { + deprecatedId = aMsg.ValueTObjectL(KMPXMessageMediaDeprecatedId); + } + + MPX_DEBUG5("CMPXCollectionClientContext::DoHandleMessageL colId %08x, id %d, deprecatedId %d, type %d", + collectionId.iUid, itemId.iId1, deprecatedId.iId1, changeType); + + + if(!iEngine.IsRefreshing()) + { + // Invalidate path + TInt pct = KErrNotFound; // path change type + if (changeType == EMPXItemInserted && category != EMPXPlaylist) + { + pct = CMPXCollectionPath ::EAdded; + } + else if (changeType == EMPXItemModified && category != EMPXPlaylist) + { + pct = CMPXCollectionPath ::EModified; + } + else if (changeType == EMPXItemDeleted) + { + pct = CMPXCollectionPath ::EDeleted; + } + else if ((changeType == EMPXItemInserted || changeType == EMPXItemModified) && + category == EMPXPlaylist) + { + pct = CMPXCollectionPath ::EGroupModified; + } + if( changeType == EMPXItemModified && category == EMPXCollection ) + { + // Overwrite previous type + pct = CMPXCollectionPath ::EGroupModified; + } + + if (KErrNotFound != pct) + { // update browse path + CMPXCollectionPath::TMPXCollectionPathChange ct = + static_cast(pct); + TInt pUpdated(CMPXCollectionPath::EPathUnchanged); + + // If browse context and browse context is being modified + // + if (iModeId != KMcModePlaylist && browseLevels && + iBrowsePath->Id(0) == collectionId.iUid ) + { // check the browse path + TInt tmpIndex(0); + + pUpdated = iBrowsePath->HandleChange( + collectionId, itemId, deprecatedId, ct, + tmpIndex); + + // Take the updated selection index only if it was affected + // We need to store the TMPXItemId for iIndex because + // a previous collection change would have removed the + // top level of the collection path + // + iPathUpdated = iPathUpdated || + (pUpdated != CMPXCollectionPath::EPathUnchanged); + if( pUpdated ) + { + // Only update the selection index if the itemid that + // was modified is equal to the one selected + // + // OR take in the index if clipped the collection path + // (pUpdated == KPathClipped ) + // + if( pUpdated == CMPXCollectionPath::EPathClipped ) + { + iIndex = tmpIndex; + iFocusItemId = KMPXInvalidItemId; + } + else if( iFocusItemId.ApproxEqual(itemId ) && + ( iFocusItemId != KMPXInvalidItemId ) ) + { + // Also make sure the index that came back from + // checking the collection path isn't -1 + // + // The only case where the selected item will shift + // is when we are deleting that item. updaing the item or adding + // an item to the current path should not move the focus to another + // item + // + if( tmpIndex != -1 && changeType == EMPXItemDeleted) + { + if( tmpIndex == iBrowsePath->Count()-1 ) + { + // Last item, focus on previous + iIndex = tmpIndex-1; + iFocusItemId = iBrowsePath->IdOfIndex( tmpIndex-1 ); + } + else + { + // Not last, focus on next + iFocusItemId = iBrowsePath->IdOfIndex( tmpIndex+1 ); + } + } + } + else if( iFocusItemId.ApproxEqual( deprecatedId ) && + changeType == EMPXItemModified ) + { + // If we are modifying the item id of an item currently in focus + // We move the focus to the new item id + // + iFocusItemId = itemId; + } + } + } + } + } + } + else + { + // do nothing + } + MPX_DEBUG2("<--CMPXCollectionClientContext::DoHandleMessageL this %08x", this); + } + +// ---------------------------------------------------------------------------- +// Handle open event +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::HandleOpen( + CMPXMedia* aMedia, + TInt aErr) + { + MPX_FUNC("CMPXCollectionClientContext::HandleOpen with media returned"); + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse); + MPX_ASSERT(plugin); + + // Callback and Task Completion + // + MMPXCollectionEngineObserver* callback(NULL); + TBool openTask(EFalse); + TInt task = plugin->Task(); + if( task == EMcsOpen || task == EMcsOpenPath || + task == EMcsBack || task == EMcsOpenIndex ) + { + callback = plugin->Callback(); + openTask = ETrue; + } + + // Cachable flag + // + TBool cache(EFalse); + if( iBrowsePath && + iBrowsePath->Levels() >= 1 ) + { + TMPXItemId id(iBrowsePath->Id(CMPXCollectionPath::ECollectionUid) ); + cache = iEngine.PluginCacheable( TUid::Uid( id ) ); + } + + TRAPD(err, DoHandleOpenL(aMedia, NULL, callback, aErr, cache, openTask)); + if (err && openTask) + { + HandleError(*plugin, err); + } + else if( openTask ) + { + plugin->CompleteTask(); + } + } + +// ---------------------------------------------------------------------------- +// Handle open event +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::HandleOpen( + CMPXMedia* aMedia, + const CMPXCollectionPath* aPath, + TInt aErr) + { + MPX_FUNC("CMPXCollectionClientContext::HandleOpen with media returned"); + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse); + MPX_ASSERT(plugin); + + // Callback and Task Completion + // + MMPXCollectionEngineObserver* p(NULL); + TBool openTask(EFalse); + TInt task = plugin->Task(); + if( task == EMcsOpen || task == EMcsOpenPath || + task == EMcsBack || task == EMcsOpenIndex ) + { + p = plugin->Callback(); + openTask = ETrue; + } + + // Cachable flag + // + TBool cache(EFalse); + if( iBrowsePath && + iBrowsePath->Levels() >= 1 ) + { + TMPXItemId id(iBrowsePath->Id(CMPXCollectionPath::ECollectionUid) ); + cache = iEngine.PluginCacheable( TUid::Uid( id ) ); + } + + // Handle OpenL for Media + // + TRAPD(err, DoHandleOpenL(aMedia, aPath, p, aErr, cache, openTask)); + if (err && openTask) + { + HandleError(*plugin, err); + } + else if( openTask ) + { + plugin->CompleteTask(); + } + } + +// ---------------------------------------------------------------------------- +// Handle open event +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoHandleOpenL( + CMPXMedia* aMedia, + const CMPXCollectionPath* aPath, + MMPXCollectionEngineObserver* aCallback, + TInt aErr, + TBool aAddToCache, + TBool aOpenTask ) + { + MPX_FUNC("CMPXCollectionClientContext::DoHandleOpen with media returned"); + + // Make sure if we are updating the results the paths are aligned! + // + TBool openUpdate(EFalse); + if( !aOpenTask ) + { + openUpdate = ETrue; + iCacheMedia = ETrue; + if( aPath && + aPath->Levels() != iBrowsePath->Levels() ) + { + User::Leave( KErrArgument ); + } + } + + // Add to cache + // + if ( iBrowsePath->Levels() && aAddToCache && aMedia && iCacheMedia ) + { + // manage the priority + CMPXCollectionCache::TCachePriority priority(CMPXCollectionCache::EPriorityNormal); + if ((1 == iBrowsePath->Levels()) || + ((2 == iBrowsePath->Levels()) && ((iBrowsePath->Id(1)).iId1 == 0))) + { + priority = CMPXCollectionCache::EPriorityHigh; + } + + if( !aOpenTask ) + { + // Update the current browse path + // + CMPXCollectionPath* container = iBrowsePath->ContainerPathL(); + CleanupStack::PushL( container ); + + // Add the data to the generic cache and get the latest copy + // + aMedia = AddToCache( *container, + aMedia->Attributes(), + *aMedia, + ETrue, + priority); + CleanupStack::PopAndDestroy( container ); + } + else + { + AddToCache( *iBrowsePath, + aMedia->Attributes(), + *aMedia, + ETrue, + priority); + } + } + + // Current client context browse path media + // + iMediaType = KMPXCollectionEntries; + if (iMedia != aMedia) + { // new media + delete iMedia; + iMedia = NULL; + if (aMedia) + { + iMedia = CMPXMedia::NewL(*aMedia); + } + } + + TInt n(0); + if (aMedia && KErrNone == aErr) + { // Update the path + RArray selectionIndicies; + CleanupClosePushL( selectionIndicies ); + + if (aPath) + { // Update path from aPath + if ( aMedia->IsSupported (KMPXCollectionOpenLAllResultRange)) + { + iBrowsePath->Back (); + RArray ids; + CleanupClosePushL (ids); + RArray datablocks; + CleanupClosePushL (datablocks); + // De-serialize from global data, would be good to have global arrays + // + const TDesC + & buf = aMedia->ValueText (KMPXCollectionOpenLAllResultRange); + CBufBase* buffer(NULL); + MPXUser::CreateBufferL ( buf, buffer); + CleanupStack::PushL ( buffer); + ::CreateFromBufferL ( *buffer, datablocks); + CleanupStack::PopAndDestroy ( buffer); + + if ( aMedia->IsSupported (KMPXMediaArrayContents)) + { + const CMPXMediaArray + * mediaArray = aMedia->Value (KMPXMediaArrayContents); + User::LeaveIfNull (const_cast(mediaArray)); + TInt dataCount = mediaArray->Count (); + TInt rangeCount = datablocks.Count (); + for (TInt index = 0; index < dataCount; ++index) + { + CMPXMedia* media = mediaArray->AtL(index); + + //Check range + TBool validItem(EFalse); + MPX_ASSERT(rangeCount > 0); + for (TInt rangeIndex = 0; rangeIndex < rangeCount; ++rangeIndex) + { + TInt offset = datablocks[rangeIndex].iOffset; + TInt size = datablocks[rangeIndex].iSize; + if ( (index >= offset) && (index < offset + size)) + { + validItem = ETrue; + break; + } + } + + if (validItem) + { + const TMPXItemId + id = media->ValueTObjectL (KMPXMediaGeneralId); + ids.AppendL (id); + } + else + { + ids.AppendL (KMPXInvalidItemId); + } + } + iBrowsePath->AppendL (ids.Array ()); + } + CleanupStack::PopAndDestroy (&datablocks); + CleanupStack::PopAndDestroy (&ids); + } + else + { + delete iBrowsePath; + iBrowsePath = NULL; + iBrowsePath = CMPXCollectionPath::NewL ( *aPath); + } + } + else + { // Update path from media + RArray ids; + CleanupClosePushL(ids); + if( aMedia->IsSupported(KMPXMediaArrayContents) ) + { + const CMPXMediaArray* mediaArray=aMedia->Value( + KMPXMediaArrayContents); + User::LeaveIfNull(const_cast(mediaArray)); + n=mediaArray->Count(); + for (TInt i=0;iAtL(i); + const TMPXItemId id=media->ValueTObjectL(KMPXMediaGeneralId); + ids.AppendL(id); + + // Try to look for the selection that we want + if( iFocusItemId == id ) + { + selectionIndicies.AppendL( i ); + } + } + } + + iBrowsePath->AppendL(ids.Array()); + CleanupStack::PopAndDestroy(&ids); + } + + // List of items + const TArray& items = iBrowsePath->Items(); + + // OpenL Media has been updated, update the itemid + // based on the current index + if( openUpdate ) + { + // Check if we have item id first + // + if( iFocusItemId != KMPXInvalidItemId ) + { + TInt index = iBrowsePath->IndexOfId( iFocusItemId ); + if( index != KErrNotFound ) + { + iIndex = index; + } + } + + // Then update based on index + if( iIndex >=0 && iIndex < iBrowsePath->Count() ) + { + iBrowsePath->Set(iIndex); + iFocusItemId = iBrowsePath->Id(); + } + } + else if( aMedia->IsSupported( KMPXCollectionOpenLResultRange ) ) + { + TMPXOpenDataBlock data = + aMedia->ValueTObjectL(KMPXCollectionOpenLResultRange); + if( iBrowsePath->Count() && + iIndex >= 0 && + iIndex < iBrowsePath->Count() ) + { + // If all blank items then we don't change index yet + // Wait until we have re-opened the partial data + if( data.iOffset != KErrNotFound ) + { + // Not supported, stay with current focus + iBrowsePath->Set(iIndex); + iFocusItemId = iBrowsePath->Id(); + } + } + } + // If this selection appears more than once, then we have to find + // the closest matching index to what we had before + // + // + else if( selectionIndicies.Count() > 1 && + iFocusItemId != KMPXInvalidItemId ) + { + TInt best(selectionIndicies[0]); + TInt idAppearance( selectionIndicies.Count() ); + for( TInt i=0; iSet(iIndex); + } + // Always set by item id if we have it + // This is needed if an item was added to the current browse level + // We still want to select the item we were previously at + // + else if( iFocusItemId != KMPXInvalidItemId ) + { + TInt index = iBrowsePath->IndexOfId(iFocusItemId); + if (KErrNotFound != index) + { + iBrowsePath->Set(index); + } + else if( n > 0 ) // Focus item has been deleted, select next + { + // Bounds check for largest and smallest + if( iIndex >= n ) + { + iIndex = n-1; + } + if( iIndex < 0 ) + { + iIndex = 0; + } + iBrowsePath->Set(iIndex); + iFocusItemId = iBrowsePath->Id(); + } + iIndex = iBrowsePath->Index(); + } + else + { + // Bounds checking for iIndex + if( iIndex >= n && iIndex > 0 ) + { + iIndex = n-1; + + // Just in case if ids has 0 items + if( iIndex > 0 && iIndex < items.Count() ) + { + iFocusItemId = items[iIndex]; + } + } + + if (iBrowsePath->Levels()>0 && iIndex>=0 && + iIndexCount()) + { + iBrowsePath->Set(iIndex); + } + iFocusItemId = iBrowsePath->Id(); + } + CleanupStack::PopAndDestroy(&selectionIndicies); + } + + TInt err; + if( !iPathUpdated ) + { + // Normal open mode + err = KErrNone == aErr ? KMPXPathUpdated : aErr; + } + else + { + // Updates open mode, should be returning entries + err = KErrNone == aErr ? KMPXCollectionEntries : aErr; + } + + // Should not be broadcasting container opened messages + // When we are only rebuilding the leaf level + // + if( !iPathUpdated && aOpenTask ) + { + if( err >= KErrNone) + { + iClientList->SendMsgL( + TMPXCollectionMessage(TMPXCollectionMessage::EPathChanged, + EMcPathChangedByOpen, + EMcContainerOpened)); + } + } + + iPathUpdated = EFalse; + + // Notes: there should no leave function called after aCallback->HandleOpen + if (aCallback) + { // Complete open with error or PathUpdated + aCallback->HandleOpen(iMedia, iIndex, ETrue, err); + if (iPluginUids[EContextBrowse]!=KNullUid) + { + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse); + MPX_ASSERT(aCallback == plugin->Callback()); + plugin->SetCallback(NULL); + plugin->SetObserver(iEngine); + } + } + MPX_DEBUG_PATH(*iBrowsePath); + } + +// ---------------------------------------------------------------------------- +// Handle open event +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::HandleOpen( + CMPXCollectionPath* aPath, + TInt aErr) + { + MPX_FUNC("CMPXCollectionClientContext::HandleOpen with path returned"); + TRAPD(err, DoHandleOpenL(aPath, aErr)); + if (err) + { + HandleError(*(LoadedPlugin(EContextBrowse)), err); + } + } + +// ---------------------------------------------------------------------------- +// Handle open event +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoHandleOpenL( + CMPXCollectionPath* aPath, + TInt aErr) + { + MPX_FUNC("CMPXCollectionClientContext::DoHandleOpen with path returned"); + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse); + MPX_ASSERT(plugin); + + plugin->CompleteTask(); + + if (iBrowsePath != aPath && KErrNone == aErr) + { + delete iBrowsePath; + iBrowsePath = NULL; + MPX_ASSERT(aPath); + iBrowsePath = CMPXCollectionPath::NewL(*aPath); + } + iMediaType = KMPXCollectionPath; + iIndex = iBrowsePath->Index(); + iFocusItemId = iBrowsePath->Id(); + + TInt err = KErrNone == aErr ? KMPXPathUpdated : aErr; + + // Complete msg + // Complete open with error or PathUpdated + plugin->Callback()->HandleOpen(iMedia, iIndex, ETrue, err); + plugin->SetCallback(NULL); + plugin->SetObserver(iEngine); + if (aPath->OpenNextMode() != EMPXOpenNoPlaylist) + // + // The request was NOT to play, but the plug-in returned + // the path implying that we should play; so we don't + // send it + // + { + iClientList->SendMsgL( + TMPXCollectionMessage(TMPXCollectionMessage::EPathChanged, + EMcPathChangedByOpen, + EMcItemOpened)); + } + + MPX_DEBUG_PATH(*iBrowsePath); + } + +// ---------------------------------------------------------------------------- +// Callback of retrieving extended media property +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::HandleMedia( + CMPXMedia* aMedia, + TInt aError) + { + MPX_FUNC("CMPXCollectionClientContext::HandleMedia"); + + CMPXMedia* ret( aMedia ); + + TBool pluginCacheable(EFalse); + if( iMediaPath ) + { + TMPXItemId id(iMediaPath->Id(CMPXCollectionPath::ECollectionUid) ); + pluginCacheable = iEngine.PluginCacheable( TUid::Uid( id ) ); + + // if media returned was resulted from multiple selections we don't cache the + // results as it's very hard to reuse it anyway + if(iMediaPath->Selection().Count() > 0) + { + pluginCacheable = EFalse; + } + } + + // Cache the media + if ( !aError && aMedia && iCacheMedia && iMediaPath && pluginCacheable ) + { + TMPXItemId id( iMediaPath->Id( + CMPXCollectionPath::ECollectionUid )); + ret = AddToCache( *iMediaPath, aMedia->Attributes(), *aMedia ); + } + + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextMedia); + + plugin->CompleteTask(); + MPX_ASSERT(plugin->Callback()); + plugin->Callback()->HandleMedia(ret, aError); + plugin->SetCallback(NULL); // Reset current observer + plugin->SetObserver(iEngine); + } + +// ---------------------------------------------------------------------------- +// Callback of async CommandL +// ---------------------------------------------------------------------------- +// + void CMPXCollectionClientContext::HandleCommandComplete( + CMPXCommand* aCommandResult, + TInt aError) + { + MPX_FUNC_EX("CMPXCollectionClientContext::HandleCommandComplete"); + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextMedia); + + plugin->CompleteTask(); + MPX_ASSERT(plugin->Callback()); + plugin->Callback()->HandleCommandComplete(aCommandResult, aError); + plugin->SetCallback(NULL); // Reset current observer + plugin->SetObserver(iEngine); + } + +// ---------------------------------------------------------------------------- +// Handle find all +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::HandleFindAll( + CMPXMedia* aMedia, + TInt aError) + { + MPX_FUNC("CMPXCollectionClientContext::HandleFindAll"); + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextMedia); + plugin->CompleteTask(); + MPX_ASSERT(plugin->Callback()); + plugin->Callback()->HandleFindAll(aMedia, aError); + plugin->SetCallback(NULL); // Reset current observer + plugin->SetObserver(iEngine); + } + +// ---------------------------------------------------------------------------- +// Handle delete all +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::HandleRemove( + const CDesCArray& aUriArray, + TInt aError) + { + MPX_FUNC("CMPXCollectionClientContext::HandleRemove"); + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextRemove); + + plugin->CompleteTask(); + MPX_ASSERT(plugin->Callback()); + plugin->Callback()->HandleRemove(aUriArray, aError); + plugin->SetCallback(NULL); // Reset current observer + plugin->SetObserver(iEngine); + } + +// ---------------------------------------------------------------------------- +// Execute a async task +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::ExecuteTask( + TInt aTask, + TInt aParamData, + TAny* aPtrData, + const CBufBase& aBuf, + TAny* aCallback, + CBase* aCObject1, + CBase* aCObject2) + { + MPX_DEBUG2("-->CMPXCollectionClientContext::ExecuteTask %d", aTask); + CMPXCollectionPlugin* plugin(NULL); + TRAPD(err, ExecuteTaskL(aTask, aParamData, aPtrData, aCallback, aBuf, + aCObject1,aCObject2,plugin)); + if (KErrNone !=err) + { + HandleError(*plugin, err, EFalse); + } + MPX_DEBUG1("<--CMPXCollectionClientContext::ExecuteTask"); + } + +// ---------------------------------------------------------------------------- +// Indicates that a task was terminated with an error +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::HandleTaskError( + TInt aTask, + TAny* aPtrData, + TAny* aCallback, + TInt aError) + { + MPX_FUNC_EX("CMPXCollectionClientContext::HandleTaskError"); + CMPXCollectionPlugin* plugin(NULL); + switch (aTask) + { + case EMcsOpen: + case EMcsBack: + case EMcsOpenIndex: + plugin = LoadedPlugin(EContextBrowse); + plugin->SetObserver(*this); + plugin->SetCallback( + reinterpret_cast(aCallback)); + HandleError(*plugin, aError, EFalse); + break; + case EMcsOpenPath: + case EMcsMediaByPath: + case EMcsCommandExt: + case EMcsRemovePath: + case EMcsFindAll: + case EMcsCommand: + plugin = reinterpret_cast(aPtrData); + plugin->SetCallback( + reinterpret_cast(aCallback)); + HandleError(*plugin, aError, ETrue); + break; + default: + break; + } + } + +// ---------------------------------------------------------------------------- +// Initialize before first open +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::InitL(MMPXCollectionEngineObserver* aCallback) + { + MPX_DEBUG1("CMPXCollectionClientContext::InitL() <---"); + delete iMedia; + iMedia = NULL; + delete iBrowsePath; + iBrowsePath = NULL; + RArray supportedIds; + CleanupClosePushL(supportedIds); + supportedIds.AppendL(KMPXMediaIdContainer); + supportedIds.AppendL(KMPXMediaIdGeneral); + iMedia=CMPXMedia::NewL(supportedIds.Array()); + iBrowsePath = CMPXCollectionPath::NewL(); + CleanupStack::PopAndDestroy(&supportedIds); + + iEngine.ListPluginsL(*iMedia, iUids.Array()); + if (iPluginUids[EContextBrowse]!=KNullUid ) + { + MPX_DEBUG1("CMPXCollectionClientContext::InitL() Collection changed"); + iClientList->SendMsgL( + TMPXCollectionMessage(TMPXCollectionMessage::ECollectionChanged,0,0)); + } + + // sets the browse plugin to NULL + SetPlugin(EContextBrowse, NULL); + + // Update collection path, and buffer, send path update msg, + // complete request + TRAPD(err, DoHandleOpenL(iMedia, NULL, aCallback, KErrNone, ETrue, ETrue)); + if (err) + { + MPX_DEBUG2("CMPXCollectionClientContext::InitL() Complete Open %i", err); + aCallback->HandleOpen(iMedia, // Not used + iIndex, + ETrue, err); + } + MPX_DEBUG1("CMPXCollectionClientContext::InitL() --->"); + } + +// ---------------------------------------------------------------------------- +// Execute a async task +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::ExecuteTaskL( + TInt aTask, + TInt aParamData, + TAny* aPtrData, + TAny* aCallback, + const CBufBase& aBuf, + CBase* aCObject1, + CBase* aCObject2, + CMPXCollectionPlugin*& aPlugin) + { + MPX_DEBUG4("CMPXCollectionClientContext::ExecuteTaskL 0x%08x, task %d, aParam %d", + this, aTask, aParamData); + switch (aTask) + { + case EMcsOpen: + { + aPlugin = LoadedPlugin(EContextBrowse); + aPlugin->SetObserver(*this); + aPlugin->SetCallback( + reinterpret_cast(aCallback)); + OpenL(); + break; + } + case EMcsOpenPath: + { + // Set plugin first for handling error + TUid oldUid = iPluginUids[EContextBrowse]; + aPlugin = reinterpret_cast(aPtrData); + // Set plugin and task pointer for browse context + SetPlugin(EContextBrowse, aPlugin); + iPathUpdated = EFalse; + aPlugin->SetObserver(*this); + aPlugin->SetCallback( + reinterpret_cast(aCallback)); + CMPXCollectionPath* path = static_cast(aCObject1); + delete iBrowsePath; + iBrowsePath = NULL; + iBrowsePath = CMPXCollectionPath::NewL(*path); + SetPathOpenMode(*iBrowsePath, static_cast(aParamData)); + + // If the browsing plugin is changing, need to broadcast the + // collection changed message + if (iPluginUids[EContextBrowse] != oldUid) + { + // no leave before plugin API OpenL + TRAP_IGNORE(iClientList->SendMsgL( + TMPXCollectionMessage( + TMPXCollectionMessage::ECollectionChanged,0,iPluginUids[EContextBrowse].iUid))); + } + iIndex=0; + iFocusItemId = KMPXInvalidItemId; + DoPluginOpenL(); + break; + } + case EMcsOpenIndex: + { + // Internalize mode + TInt mode = (TInt)aPtrData; + aPlugin = LoadedPlugin(EContextBrowse); + aPlugin->SetObserver(*this); + aPlugin->SetCallback( + reinterpret_cast(aCallback)); + iBrowsePath->Set(aParamData); + SetPathOpenMode(*iBrowsePath,static_cast(mode)); + iIndex=0; + iFocusItemId = KMPXInvalidItemId; + DoPluginOpenL(); + break; + } + case EMcsBack: + { + aPlugin = LoadedPlugin(EContextBrowse); + aPlugin->SetObserver(*this); + aPlugin->SetCallback( + reinterpret_cast(aCallback)); + BackL(); + break; + } + case EMcsMediaByPath: + { + // Setup plugin first for handle error + aPlugin = reinterpret_cast(aPtrData); + SetPlugin(EContextMedia, aPlugin); + + aPlugin->SetObserver(*this); + aPlugin->SetCallback( + static_cast(aCallback)); + // Media path + CMPXCommand* cmd = reinterpret_cast(aCObject1); + MPX_ASSERT(cmd->IsSupported(KMPXCommandGeneralTargetIds)); + MPX_ASSERT(cmd->IsSupported(KMPXCommandMediaAttributeSpecs)); + CMPXCollectionPath* path = reinterpret_cast(aCObject2); + CMPXAttributeSpecs* specs = + cmd->Value(KMPXCommandMediaAttributeSpecs); + User::LeaveIfNull(specs); + CMPXAttributeSpecs* filter = + cmd->Value(KMPXCommandMediaFilter); + User::LeaveIfNull(filter); + TCapabilitySet caps = cmd->ValueTObjectL(KMPXCommandMediaCapbilitySet); + // Ask plugin for media + DoPluginMediaL( *path, caps, *specs, *filter ); + break; + } + case EMcsRemovePath: + { + aPlugin = reinterpret_cast(aPtrData); + // set the remove plugin + SetPlugin(EContextRemove, aPlugin); + + aPlugin->SetObserver(*this); + CMPXCollectionPath* path = + reinterpret_cast(aCObject1); + aPlugin->SetCallback( + reinterpret_cast(aCallback)); + aPlugin->RemoveL( *path ); + break; + } + case EMcsFindAll: + { + aPlugin = reinterpret_cast(aPtrData); + // set the media plugin + SetPlugin(EContextMedia, aPlugin); + + aPlugin->SetCallback( + reinterpret_cast(aCallback)); + CMPXMedia* media = static_cast(aCObject1); + FindAllL(*media, aBuf, *aPlugin); + break; + } + case EMcsCommand: + { + TMPXCollectionCommand cmd = + static_cast( aParamData ); + switch( cmd ) + { + case EMcCmdCollectionInit: + case EMcCmdCollectionResyn: + // Decrement the old plugin reference count + aPlugin = reinterpret_cast(aPtrData); + SetPlugin(EContextMedia, aPlugin); + + if( aPlugin ) + { + aPlugin->SetObserver(*this); + aPlugin->CommandL( cmd ); + aPlugin->SetObserver(iEngine); + aPlugin->CompleteTask(); + } + break; + default: + MPX_ASSERT(0); + break; + } + break; + } + case EMcsCommandExt: + { + CMPXCommand* cmd = reinterpret_cast(aCObject1); + aPlugin = reinterpret_cast(aPtrData); + MMPXCollectionEngineObserver* callback = + reinterpret_cast(aCallback); + if( cmd->IsSupported( KMPXCommandGeneralId) ) + { + TMPXCommandId commandId = cmd->ValueTObjectL(KMPXCommandGeneralId); + // Decrement the old plugin reference count + SetPlugin(EContextMedia, aPlugin); + aPlugin->SetCallback( callback ); + + if( commandId == KMPXCommandIdCollectionSelect ) + { + // Decrement the old plugin reference count + // + DoHandleSelectCommandL( *cmd ); + aPlugin->SetCallback( NULL ); + aPlugin->CompleteTask(); + callback->HandleCommandComplete( NULL, KErrNone ); + } + else + { + aPlugin->SetObserver(*this); + aPlugin->CommandL(*cmd); + } + } + else + { + aPlugin->CompleteTask(); + callback->HandleCommandComplete( NULL, KErrArgument ); // return error message + } + break; + } + default: + break; + } + } + +// ---------------------------------------------------------------------------- +// Error happens upon request +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::HandleError( + CMPXCollectionPlugin& aPlugin, + TInt aError, + TBool aUnusePlugin/*=EFalse*/) + { + TInt task(aPlugin.Task()); + MPX_DEBUG3("CMPXCollectionClientContext::HandleError %d, task %d", + aError, task); + switch (task) + { + case EMcsOpen: + case EMcsOpenPath: + case EMcsBack: + case EMcsOpenIndex: + aPlugin.Callback()->HandleOpen(iMedia, // Not used + iIndex, + ETrue, aError); + aPlugin.CompleteTask(); + aPlugin.SetCallback(NULL); // Reset current observer + aPlugin.SetObserver(iEngine); + break; + case EMcsMediaByPath: + aPlugin.Callback()->HandleMedia(iMedia, aError); + aPlugin.CompleteTask(); + aPlugin.SetCallback(NULL); // Reset current observer + aPlugin.SetObserver(iEngine); + break; + case EMcsCommandExt: + aPlugin.Callback()->HandleCommandComplete(iMedia, aError); + aPlugin.CompleteTask(); + aPlugin.SetCallback(NULL); // Reset current observer + aPlugin.SetObserver(iEngine); + break; + case EMcsRemovePath: + { + CDesCArray* dummy(NULL); // object will not be dereferenced in callback + aPlugin.Callback()->HandleRemove(*dummy, aError); + aPlugin.SetCallback(NULL); // Reset current observer + aPlugin.SetObserver(iEngine); + aPlugin.CompleteTask(); + } + break; + case EMcsFindAll: + aPlugin.Callback()->HandleFindAll(iMedia, aError); + aPlugin.SetCallback(NULL); // Reset current observer + aPlugin.SetObserver(iEngine); + aPlugin.CompleteTask(); + break; + case EMcsCommand: + { + // At least complete the task to not jam up the task queue + aPlugin.SetCallback(NULL); // Reset current observer + aPlugin.SetObserver(iEngine); + aPlugin.CompleteTask(); + break; + } + default: + break; + } + if (aUnusePlugin) + { + iEngine.ReleasePlugin(aPlugin.Uid()); + } + MPX_DEBUG1("<--CMPXCollectionClientContext::HandleError"); + } + +// ---------------------------------------------------------------------------- +// Error happens upon request +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::ResolvePluginL( + const CMPXCollectionPath& aPath, + TUid& aUid) + { + CMPXCollectionPlugin* p= iEngine.LoadedPlugin(aUid); // Save old plugin + // Resolve new plugin + CMPXCollectionPlugin* plugin=iEngine.ResolvePluginL(aPath); + // Update with new Uid + aUid = plugin->Uid(); + if (p != plugin && &aPath == iBrowsePath) + { + // browsing plugin changed + iClientList->SendMsgL(TMPXCollectionMessage( + TMPXCollectionMessage::ECollectionChanged,0,aUid.iUid)); + } + + if (p) + { + // Make sure we decrement the reference count for the old plugin + iEngine.ReleasePlugin(p->Uid()); + } + } + +// ---------------------------------------------------------------------------- +// resolve plugin for FindAllL +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::ResolvePluginL( + const CMPXMedia& aMedia, + CMPXCollectionPlugin*& aPlugin) + { + // We have to be finding from the same context as browse + // if we are from MPX UI + // + if (iPluginUids[EContextBrowse]!=KNullUid) + { + aPlugin = LoadedPlugin(EContextBrowse); + + // Increment the reference count manually + iEngine.UsePlugin(aPlugin->Uid()); + } + else // browse context does not exist + { + if (aMedia.IsSupported(KMPXMediaGeneralCollectionId)) + { + TUid col = aMedia.ValueTObjectL(KMPXMediaGeneralCollectionId); + + // Increment the plugin reference count + aPlugin = iEngine.ResolvePluginL(col); + } + else if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + const TDesC& uri = aMedia.ValueText(KMPXMediaGeneralUri); + + // Increment the plugin reference count + aPlugin = iEngine.ResolvePluginL(uri); + } + else + { + // Unable to find a collection plugin + User::Leave(KErrNotSupported); + } + } + } + +// ---------------------------------------------------------------------------- +// CMPXCollectionClientContext::SetPlugin +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::SetPlugin( + TContextType aType, + CMPXCollectionPlugin* aPlugin) + { + if (iPluginUids[aType]!=KNullUid) + { + iEngine.ReleasePlugin(iPluginUids[aType]); + } + if (aPlugin) + { + iPluginUids[aType] = aPlugin->Uid(); + } + else + { + iPluginUids[aType] = KNullUid; + } + } + +// ---------------------------------------------------------------------------- +// Add a media object to the collection +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoUpdateMediaL( TInt aOp, const CMPXMedia& aMedia ) + { + // Media object can be a single "item" or a list of "items" + // + TMPXGeneralType type = EMPXNoType; + if (aMedia.IsSupported(KMPXMediaGeneralType)) + { + type = aMedia.ValueTObjectL(KMPXMediaGeneralType); + } + else + { + User::Leave(KErrArgument); + } + + if ( type == EMPXGroup ) + { + // Group has to have a "container" + MPX_ASSERT(aMedia.IsSupported(KMPXMediaArrayContents)); + const CMPXMediaArray* array = + aMedia.Value(KMPXMediaArrayContents); + User::LeaveIfNull(const_cast(array)); + TInt count = array->Count(); + for( TInt i=0; iAtL(i)) ); + } + } + else if ( type == EMPXItem ) + { + DoHandleItemL( aOp, aMedia ); + } + else + { + // How do we handle "group" artists? + User::Leave( KErrNotSupported ); + } + } + +// ---------------------------------------------------------------------------- +// Add the media object to the correct plugin +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoHandleItemL( TInt aOp, const CMPXMedia& aMedia) + { + MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL <---"); + + // Find the correct plugin. + // The code below increments the plugin reference count + CMPXCollectionPlugin* plugin(NULL); + if (aMedia.IsSupported(KMPXMediaGeneralCollectionId)) + { + const TUid& uid = aMedia.ValueTObjectL(KMPXMediaGeneralCollectionId); + MPX_DEBUG2("CMPXCollectionClientContext::DoHandleItemL Collection %i", uid.iUid); + + // Increment the plugin reference count + plugin = iEngine.ResolvePluginL( uid ); + } + else if (aMedia.IsSupported(KMPXMediaGeneralUri)) + { + const TDesC& uri = aMedia.ValueText(KMPXMediaGeneralUri); + MPX_DEBUG2("CMPXCollectionClientContext::DoHandleItemL Collection %S", &uri); + + // Increment the plugin reference count + plugin = iEngine.ResolvePluginL( uri ); + } + else + { + MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Cannot resolve a plugin"); + User::Leave(KErrNotSupported); + } + + if( !plugin ) + { + MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Cannot resolve a plugin"); + User::Leave(KErrNotSupported); + } + + iEngine.CleanupPluginPushL(plugin); + + switch( aOp ) + { + case EMcsAddItem: + { + MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Add"); + + plugin->SetObserver(*this); + plugin->AddL( aMedia ); + plugin->SetObserver(iEngine); + break; + } + case EMcsRemoveItem: + { + MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Remove"); + plugin->SetObserver(*this); + plugin->RemoveL( aMedia ); + plugin->SetObserver(iEngine); + break; + } + case EMcsSetMedia: + { + MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Set"); + plugin->SetObserver(*this); + plugin->SetL( aMedia ); + plugin->SetObserver(iEngine); + break; + } + default: + { + User::Leave(KErrNotSupported); + break; + } + } // switch + + CleanupStack::PopAndDestroy(); // plugin + + MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL --->"); + } + +// ---------------------------------------------------------------------------- +// Handle a synchorouns command to the collection +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoHandleSyncCommandL( + const CMPXCommand& aCmd, + const CMPXMessageQueue& aMsgQueue, + CMPXCollectionPlugin* aPlugin/*=NULL*/) + { + // Only process the command if the command id has been defined, + // otherwise leave with KErrArgument + if (aCmd.IsSupported(KMPXCommandGeneralId)) + { + TMPXCommandId commandId = aCmd.ValueTObjectL(KMPXCommandGeneralId); + switch( commandId ) + { + case KMPXCommandIdCollectionSelect: + { + DoHandleSelectCommandL( aCmd ); + break; + } + + case KMPXCommandSubscriptionAdd: + { + TInt index( iClientList->Find( aMsgQueue )); + CMPXMediaArray* items( + aCmd.Value( KMPXCommandSubscriptionAddItems )); + User::LeaveIfNull(items); + CMPXSubscription* subscription( CMPXSubscription::NewL( *items )); + CleanupStack::PushL(subscription); + iClientList->AddSubscriptionL( index, subscription ); // ownership transferred + CleanupStack::Pop(subscription); + break; + } + case KMPXCommandSubscriptionRemove: + { + TInt index( iClientList->Find( aMsgQueue )); + CMPXMediaArray* items( + aCmd.Value( KMPXCommandSubscriptionAddItems )); + User::LeaveIfNull(items); + CMPXSubscription* subscription( CMPXSubscription::NewL( *items )); + CleanupStack::PushL(subscription); + iClientList->RemoveSubscriptionL( index, *subscription ); + CleanupStack::PopAndDestroy(subscription); + break; + } + case KMPXCommandSubscriptionRemoveAll: + { + TInt index( iClientList->Find( aMsgQueue )); + iClientList->RemoveAllSubscriptionsL( index ); + break; + } + + case KMPXCommandIdCollectionPrepareDelete: + { + if (aCmd.IsSupported (KMPXCommandCollectionPrepareRemovePath)) + { + CMPXCollectionPath + * path = aCmd.ValueCObjectL (KMPXCommandCollectionPrepareRemovePath); + CleanupStack::PushL(path); + iEngine.ResetCacheL(*path); + CleanupStack::PopAndDestroy(path); + } + break; + } + + default: + { + MPX_ASSERT(aPlugin); + aPlugin->SetObserver(*this); + TRAPD( err, aPlugin->CommandL( const_cast(aCmd) ) ); + aPlugin->SetObserver(iEngine); + User::LeaveIfError( err ); + break; + } + } + } + else + { + User::Leave(KErrArgument); + } + } + +// ---------------------------------------------------------------------------- +// CMPXCollectionClientContext::DoHandleSelectCommandL +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoHandleSelectCommandL(const CMPXCommand& aCmd) + { + TInt index(iIndex); + + // Selecting a new index + if( aCmd.IsSupported(KMPXCommandCollectionSelectIndex) ) + { + index = aCmd.ValueTObjectL(KMPXCommandCollectionSelectIndex); + if (iBrowsePath->Levels()<=0) + { + User::Leave(KErrNotReady); + } + if (index<0 || index>=iBrowsePath->Count()) + { + User::Leave(KErrArgument); + } + iBrowsePath->Set(index); + } + // Re-select the current index + else + { + TInt count = iBrowsePath->Count(); + + if( iFocusItemId != KMPXInvalidItemId ) + { + TInt index = iBrowsePath->IndexOfId(iFocusItemId); + if (KErrNotFound != index) + { + iBrowsePath->Set(index); + } + else if( count > 0 ) // Focus item has been deleted, select next + { + // Bounds check for largest and smallest + if( iIndex >= count ) + { + iIndex = count-1; + } + if( iIndex < 0 ) + { + iIndex = 0; + } + iBrowsePath->Set(iIndex); + iFocusItemId = iBrowsePath->Id(); + } + iIndex = iBrowsePath->Index(); + } + else + { + // Bounds checking for iIndex + if( iIndex >= count && iIndex > 0 ) + { + iIndex = count-1; + + // Just in case if ids has 0 items + if( iIndex > 0 && iIndex < count ) + { + iFocusItemId = iBrowsePath->IdOfIndex(iIndex); + } + } + + if (iBrowsePath->Levels()>0 && iIndex>=0 && + iIndexCount()) + { + iBrowsePath->Set(iIndex); + } + iFocusItemId = iBrowsePath->Id(); + } + } + iClientList->SendMsgL( + TMPXCollectionMessage(TMPXCollectionMessage::EFocusChanged, + index, index)); + iIndex = index; // iIndex will always be up to date + iFocusItemId = iBrowsePath->Id(); + } + +// ---------------------------------------------------------------------------- +// CMPXCollectionClientContext::DoPluginOpenL +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoPluginOpenL() + { + MPX_FUNC("CMPXCollectionClientContext::DoPluginOpenL()"); + TBool callOpen(ETrue); + MPX_ASSERT(iPluginUids[EContextBrowse]!=KNullUid); + TBool pluginCacheable(EFalse); + if( iBrowsePath ) + { + TMPXItemId id(iBrowsePath->Id(CMPXCollectionPath::ECollectionUid) ); + pluginCacheable = iEngine.PluginCacheable( TUid::Uid( id ) ); + } + + // Check for open playlist only mode. If in that mode, do not return the media + // from the cache but call the plugin to open, as that will callback a + // different HandleOpenL() with the collection path instead. + TMPXOpenMode mode( iBrowsePath->OpenNextMode() ); + CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse); + if ( !iFilter && mode != EMPXOpenPlaylistOnly ) + { + // try to get the results from the cache only if the plugin is cacheable + if ( pluginCacheable ) + { + CMPXMedia* results( iCache.GetL( *iBrowsePath, + iBrowsePath->OpenAttributes(), + ETrue )); + if (results) + { + MPX_DEBUG1("CMPXCollectionClientContext::DoPluginOpenL(): Results found in cache"); + MMPXCollectionEngineObserver* callback = plugin->Callback(); + plugin->CompleteTask(); + TRAPD(err, DoHandleOpenL(results, NULL, callback, KErrNone, EFalse, ETrue)); + if (err) + { + HandleError(*plugin, err); + } + + callOpen = EFalse; + } + } + } + + if (callOpen) + { + if ( pluginCacheable ) + { + iCacheMedia = AttributesCacheableL( iBrowsePath->OpenAttributes(), *iBrowsePath ); + } + plugin->OpenL(*iBrowsePath, iBrowsePath->OpenAttributes(), iFilter); + } + } + +// ---------------------------------------------------------------------------- +// CMPXCollectionClientContext::DoPluginMediaL +// ---------------------------------------------------------------------------- +// +void CMPXCollectionClientContext::DoPluginMediaL( + CMPXCollectionPath& aPath, + const TCapabilitySet& aCaps, + CMPXAttributeSpecs& aSpecs, + CMPXFilter& aFilter) + { + MPX_FUNC("CMPXCollectionClientContext::DoPluginMediaL()"); + TBool callMedia(ETrue); + delete iMediaPath; + iMediaPath = NULL; + + TMPXItemId id(aPath.Id(CMPXCollectionPath::ECollectionUid) ); + TBool pluginCacheable( iEngine.PluginCacheable( TUid::Uid( id ) )); + + // try to get the results from the cache only if + // the plugin is cacheable + CMPXMedia* results( NULL ); + if ( pluginCacheable ) + { + results = iCache.GetL( aPath, aPath.OpenAttributes() ); + + if (results) + { + // Check if the attribute specs match + if ( aSpecs.Count() > 0 ) + { + /* + // need to check if requested attribute specs + // match what we have cached + if ( results->IsSupported( KMPXCommandMediaAttributeSpecs )) + { + CMPXAttributeSpecs* specs( results->Value( + KMPXCommandMediaAttributeSpecs )); + User::LeaveIfNull(specs); + if ( *specs == *aSpecs ) + { + callMedia = EFalse; + } + } + */ + } + else + { + // Else client did not specify attribute specs, so we can return + // the match + callMedia = EFalse; + } + } + } + + if ( callMedia ) + { + iMediaPath = CMPXCollectionPath::NewL( aPath ); + + if ( pluginCacheable ) + { + iCacheMedia = AttributesCacheableL( aPath.OpenAttributes(), aPath ); + } + LoadedPlugin(EContextMedia)->MediaL( aPath, + aPath.OpenAttributes(), + aCaps, + &aSpecs, + &aFilter); + } + else + { + HandleMedia( results, KErrNone ); + } + } + + +// ---------------------------------------------------------------------------- +// CMPXCollectionClientContext::AttributesCacheableL +// ---------------------------------------------------------------------------- +// +TBool CMPXCollectionClientContext::AttributesCacheableL( + const TArray& aAttrs, + const CMPXCollectionPath& aPath ) + { + MPX_DEBUG1("-->CMPXCollectionClientContext::AttributesCacheableL"); + + TMPXItemId id( aPath.Id( CMPXCollectionPath::ECollectionUid )); + const TArray& nonCacheAttrs( iEngine.PluginNonCacheableAttributesL( TUid::Uid( id ))); + + TBool found( EFalse ); + TInt nonCacheCount( nonCacheAttrs.Count() ); + for ( TInt i = 0; i < nonCacheCount && !found; i++ ) + { + TInt attrCount( aAttrs.Count() ); + for ( TInt j = 0; j < attrCount && !found; j++ ) + { + TMPXAttribute att( aAttrs[j] ); + if ( nonCacheAttrs[i] == TUid::Uid( att.ContentId() )) + { + found = ETrue; + } + } + } + MPX_DEBUG1("<--CMPXCollectionClientContext::AttributesCacheableL"); + return !found; + } + +// ---------------------------------------------------------------------------- +// CMPXCollectionClientContext::AddToCache +// ---------------------------------------------------------------------------- +// +CMPXMedia* CMPXCollectionClientContext::AddToCache( + const CMPXCollectionPath& aPath, + const TArray& aAttrs, + CMPXMedia& aResults, + TBool aMediaFromOpenL, + CMPXCollectionCache::TCachePriority aPriority /* = EPriorityNormal */) + { + CMPXMedia* ret( &aResults ); + TRAP_IGNORE(ret = iCache.AddL(aPath, aAttrs, aResults, aMediaFromOpenL, aPriority)); + return ret; + } + +// ---------------------------------------------------------------------------- +// CMPXCollectionClientContext::LoadedPlugin +// ---------------------------------------------------------------------------- +// +CMPXCollectionPlugin* CMPXCollectionClientContext::LoadedPlugin(TContextType aType) + { + MPX_ASSERT(iPluginUids[aType]!=KNullUid); + CMPXCollectionPlugin* plugin(iEngine.LoadedPlugin(iPluginUids[aType])); + MPX_ASSERT(plugin); + return plugin; + } + +// End of file