mpx/collectionframework/collectionengine/src/mpxcollectionclientcontext.cpp
changeset 0 a2952bb97e68
child 15 d240f0a77280
equal deleted inserted replaced
-1:000000000000 0:a2952bb97e68
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Maintains sessions to paths
       
    15 *
       
    16 */
       
    17 
       
    18 #include <badesca.h>
       
    19 #include <mpxcollectionpath.h>
       
    20 #include <mpxclientlist.h>
       
    21 #include <mpxcollectionplugin.h>
       
    22 #include <mpxcollectionpath.h>
       
    23 #include <mpxcollectionframeworkdefs.h>
       
    24 #include <mpxcollectioncommanddefs.h>
       
    25 #include <mpxcommonframeworkdefs.h>
       
    26 #include <mpxcmn.h>
       
    27 #include <mpxmedia.h>
       
    28 #include <mpxmediaarray.h>
       
    29 #include <mpxmediageneraldefs.h>
       
    30 #include <mpxmediacontainerdefs.h>
       
    31 #include <mpxmessagegeneraldefs.h>
       
    32 #include <mpxmessagecontainerdefs.h>
       
    33 #include <mpxcollectionmessage.h>
       
    34 #include <mpxcollectionmessagedefs.h>
       
    35 #include <mpxcommandgeneraldefs.h>
       
    36 #include <mpxcollectionopenlresultdef.h>
       
    37 #include <mpxcommand.h>
       
    38 #include <mpxlog.h>
       
    39 #include <mpxsubscription.h>
       
    40 #include "mpxcollectionengineobserver.h"
       
    41 #include "mpxcollectionpluginhandler.h"
       
    42 #include "mpxcollectionengine.h"
       
    43 #include "mpxcollectioncache.h"
       
    44 #include "mpxcollectionclientcontext.h"
       
    45 
       
    46 // ----------------------------------------------------------------------------
       
    47 // Helper. Sets next open mode on path
       
    48 // ----------------------------------------------------------------------------
       
    49 //
       
    50 LOCAL_C void SetPathOpenMode(CMPXCollectionPath& aPath, TInt aMode)
       
    51     {
       
    52     TMPXOpenMode mode=static_cast<TMPXOpenMode>(aMode);
       
    53     if (aPath.Levels())
       
    54         {
       
    55         aPath.Set(mode == EMPXOpenDefault ? aPath.OpenPreviousMode() : mode);
       
    56         }
       
    57     }
       
    58 
       
    59 // ----------------------------------------------------------------------------
       
    60 // Helper. Returns whether next open mode is the same as previous open
       
    61 // request
       
    62 // ----------------------------------------------------------------------------
       
    63 //
       
    64 LOCAL_C TBool OpenModeValid(const CMPXCollectionPath& aPath)
       
    65     {
       
    66     TMPXOpenMode next=aPath.OpenNextMode();
       
    67     return (aPath.OpenPreviousMode() == next) || (next == EMPXOpenDefault);
       
    68     }
       
    69 
       
    70 // ============================ MEMBER FUNCTIONS ==============================
       
    71 
       
    72 // ----------------------------------------------------------------------------
       
    73 // Two-phased constructor.
       
    74 // ----------------------------------------------------------------------------
       
    75 //
       
    76 CMPXCollectionClientContext* CMPXCollectionClientContext::NewL(
       
    77     CMPXCollectionEngine& aEngine,
       
    78     CMPXCollectionCache& aCache,
       
    79     const TUid& aModeId)
       
    80     {
       
    81     CMPXCollectionClientContext* p =
       
    82                     new(ELeave) CMPXCollectionClientContext(aEngine, aCache, aModeId);
       
    83     CleanupStack::PushL(p);
       
    84     p->ConstructL();
       
    85     CleanupStack::Pop(p);
       
    86     return p;
       
    87     }
       
    88 
       
    89 // ----------------------------------------------------------------------------
       
    90 // C++ constructor.
       
    91 // ----------------------------------------------------------------------------
       
    92 //
       
    93 CMPXCollectionClientContext::CMPXCollectionClientContext(
       
    94     CMPXCollectionEngine& aEngine,
       
    95     CMPXCollectionCache& aCache,
       
    96     const TUid& aModeId)
       
    97   : iModeId(aModeId),iFocusItemId(KMPXInvalidItemId),
       
    98     iEngine(aEngine),iCache(aCache)
       
    99     {
       
   100     }
       
   101 
       
   102 // ----------------------------------------------------------------------------
       
   103 // 2nd phase constructor.
       
   104 // ----------------------------------------------------------------------------
       
   105 //
       
   106 void CMPXCollectionClientContext::ConstructL()
       
   107     {
       
   108     iClientList = CMPXClientList::NewL();
       
   109     iBrowsePath = CMPXCollectionPath::NewL();
       
   110     iMedia = CMPXMedia::NewL(); // empty media
       
   111     // initialize to null uid
       
   112     for (TInt index = 0; index < EContextCount; ++index)
       
   113         {
       
   114         iPluginUids.AppendL(KNullUid);
       
   115         }
       
   116     }
       
   117 
       
   118 // ----------------------------------------------------------------------------
       
   119 // Destructor
       
   120 // ----------------------------------------------------------------------------
       
   121 //
       
   122 CMPXCollectionClientContext::~CMPXCollectionClientContext()
       
   123     {
       
   124     MPX_DEBUG2("CMPXCollectionClientContext::~CMPXCollectionClientContext %08x",
       
   125                this);
       
   126 
       
   127     // Release all plugins this context has references on, this could result in the
       
   128     // plugin(s) being unloaded.
       
   129     for (TInt index = 0; index < EContextCount; ++index)
       
   130         {
       
   131         if (iPluginUids[index] != KNullUid)
       
   132             {
       
   133             iEngine.ReleasePlugin(iPluginUids[index]);
       
   134             }
       
   135         }
       
   136 
       
   137     delete iClientList;
       
   138     delete iBrowsePath;
       
   139     delete iMediaPath;
       
   140     delete iMedia;
       
   141     delete iFilter;
       
   142     iPluginUids.Close();
       
   143     iUids.Close();
       
   144     }
       
   145 
       
   146 // ----------------------------------------------------------------------------
       
   147 // Open collection by path
       
   148 // ----------------------------------------------------------------------------
       
   149 //
       
   150 EXPORT_C void CMPXCollectionClientContext::OpenL(
       
   151     CMPXCollectionPath* aPath,
       
   152     TInt aMode,
       
   153     MMPXCollectionEngineObserver* aCallback)
       
   154     {
       
   155     MPX_DEBUG1("CMPXCollectionClientContext::OpenL 1 <--");
       
   156     MPX_ASSERT(aPath);
       
   157     if (aPath->Levels() > 0)
       
   158         {
       
   159         // Increment the plugin reference count
       
   160         CMPXCollectionPlugin*plugin = iEngine.ResolvePluginL(*aPath);
       
   161         if (!plugin)
       
   162             {
       
   163             MPX_DEBUG1("CMPXCollectionClientContext::OpenL 1 bad path plugin");
       
   164             User::Leave(KErrArgument);
       
   165             }
       
   166 
       
   167         iEngine.CleanupPluginPushL(plugin);
       
   168 
       
   169         // Ownership of aPath transferred
       
   170         MPX_DEBUG1("CMPXCollectionClientContext::OpenL 1 Add task");
       
   171         plugin->AddTaskL(EMcsOpenPath, aCallback, this,
       
   172                         aMode, NULL, plugin, aPath);
       
   173 
       
   174         // Pop the plugin
       
   175         iEngine.PluginPop();
       
   176         }
       
   177     else
       
   178         { // Go back to root level
       
   179         MPX_DEBUG1("CMPXCollectionClientContext::OpenL restarting path");
       
   180         iIndex=0;
       
   181         iFocusItemId = KMPXInvalidItemId;
       
   182         InitL(aCallback);
       
   183         }
       
   184     MPX_DEBUG1("CMPXCollectionClientContext::OpenL 1 -->");
       
   185     }
       
   186 
       
   187 // ----------------------------------------------------------------------------
       
   188 // Open collection by index
       
   189 // ----------------------------------------------------------------------------
       
   190 //
       
   191 EXPORT_C void CMPXCollectionClientContext::OpenL(
       
   192     TInt aIndex,
       
   193     TInt aMode,
       
   194     const TArray<TMPXAttribute>& aAttrs,
       
   195     MMPXCollectionEngineObserver* aCallback)
       
   196     {
       
   197     MPX_DEBUG1("CMPXCollectionClientContext::OpenL 2 <--");
       
   198     if (iBrowsePath->Levels()<=0)
       
   199         {
       
   200         User::Leave(KErrNotReady);
       
   201         }
       
   202     if (aIndex<0 || aIndex>=iBrowsePath->Count())
       
   203         {
       
   204         User::Leave(KErrArgument);
       
   205         }
       
   206     iBrowsePath->Set(aIndex);
       
   207     // plugin not resolved yet
       
   208     if (iPluginUids[EContextBrowse] == KNullUid)
       
   209         {
       
   210         // Increment the new plugin reference count, decrement the old.
       
   211         // No need to push/release the plugin it is stored in a member
       
   212         // variable and will be released when that is overwritten.
       
   213         ResolvePluginL(*iBrowsePath, iPluginUids[EContextBrowse]);
       
   214         }
       
   215 
       
   216     if (iPluginUids[EContextBrowse] == KNullUid)
       
   217         {
       
   218         MPX_DEBUG1("CMPXCollectionClientContext::OpenL 2 bad plugin");
       
   219         User::Leave(KErrNotReady);
       
   220         }
       
   221 
       
   222     // add request to the queue
       
   223     MPX_DEBUG1("CMPXCollectionClientContext::OpenL 2 Add task");
       
   224     iBrowsePath->SetL(aAttrs);
       
   225     LoadedPlugin(EContextBrowse)->AddTaskL(EMcsOpenIndex, aCallback, this,
       
   226                                            aIndex, NULL, (TAny*)aMode);
       
   227     MPX_DEBUG1("CMPXCollectionClientContext::OpenL 2 -->");
       
   228     }
       
   229 
       
   230 // ----------------------------------------------------------------------------
       
   231 // Open collection by uids
       
   232 // ----------------------------------------------------------------------------
       
   233 //
       
   234 EXPORT_C void CMPXCollectionClientContext::OpenL(
       
   235     const TArray<TUid>& aUids,
       
   236     TInt aMode,
       
   237     MMPXCollectionEngineObserver* aCallback)
       
   238     {
       
   239     // Update path for open request
       
   240     MPX_DEBUG1("CMPXCollectionClientContext::OpenL 3 <---");
       
   241     SetPathOpenMode(*iBrowsePath,aMode);
       
   242     if (!MPXUser::CompareOrderedUidArrays(iUids.Array(), aUids))
       
   243         { // the same context
       
   244         MPX_DEBUG1("CMPXCollectionClientContext::OpenL 3 return Open");
       
   245         aCallback->HandleOpen(iMedia, iIndex, ETrue, iMediaType);
       
   246         }
       
   247     else
       
   248         { // go back to root level
       
   249         MPX_DEBUG1("CMPXCollectionClientContext::OpenL 3 Going to Root");
       
   250         iUids.Reset();
       
   251         ::CopyArrayL(aUids, iUids);
       
   252         iIndex=0;
       
   253         iFocusItemId = KMPXInvalidItemId;
       
   254         InitL(aCallback);
       
   255         }
       
   256     MPX_DEBUG1("CMPXCollectionClientContext::OpenL 3 --->");
       
   257     }
       
   258 
       
   259 // ----------------------------------------------------------------------------
       
   260 // Request current content of browse context
       
   261 // ----------------------------------------------------------------------------
       
   262 //
       
   263 EXPORT_C void CMPXCollectionClientContext::OpenL(
       
   264     TInt aMode,
       
   265     MMPXCollectionEngineObserver* aCallback)
       
   266     {
       
   267     // Update path for open request
       
   268     MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 <---");
       
   269     SetPathOpenMode(*iBrowsePath,aMode);
       
   270     if (iPluginUids[EContextBrowse] == KNullUid)
       
   271         {// No plug-in has been resolved
       
   272         if (iBrowsePath->Levels() == 0)
       
   273             //
       
   274             // Open called at root level: just need to list the plug-ins,
       
   275             // no need to resolve any plugin. Open request doesn't apply
       
   276             // at this level
       
   277             {
       
   278             MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 InitL()");
       
   279             iIndex=0;
       
   280             iFocusItemId = KMPXInvalidItemId;
       
   281             InitL(aCallback);
       
   282             }
       
   283         else if (OpenModeValid(*iBrowsePath) && !iPathUpdated)
       
   284             //
       
   285             // The existing media is still valid (no change
       
   286             // in the request for entries
       
   287             //
       
   288             {
       
   289             MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 return media");
       
   290             aCallback->HandleOpen(iMedia,
       
   291                                   iIndex, ETrue,
       
   292                                   iMediaType);
       
   293             }
       
   294            else // Open mode has changed and open NOT called at root level
       
   295                {
       
   296                MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 add task different open mode");
       
   297                ResolvePluginL(*iBrowsePath, iPluginUids[EContextBrowse]); // Find a plug-in
       
   298                if (iPluginUids[EContextBrowse] != KNullUid)
       
   299                 {
       
   300                 LoadedPlugin(EContextBrowse)->AddTaskL(EMcsOpen, aCallback, this);
       
   301                 }
       
   302                }
       
   303         }
       
   304     else
       
   305         {
       
   306         MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 add task");
       
   307         LoadedPlugin(EContextBrowse)->AddTaskL(EMcsOpen, aCallback,this);
       
   308         }
       
   309     MPX_DEBUG1("CMPXCollectionClientContext::OpenL 4 --->");
       
   310     }
       
   311 
       
   312 // ----------------------------------------------------------------------------
       
   313 // Media request by collection path
       
   314 // ----------------------------------------------------------------------------
       
   315 //
       
   316 EXPORT_C void CMPXCollectionClientContext::BackL(
       
   317     MMPXCollectionEngineObserver* aCallback)
       
   318     {
       
   319     MPX_DEBUG1("CMPXCollectionClientContext::BackL()");
       
   320     if (iPluginUids[EContextBrowse]==KNullUid)
       
   321         {
       
   322         User::Leave(KErrNotReady);
       
   323         }
       
   324 
       
   325     MPX_DEBUG1("CMPXCollectionClientContext::BackL() -- Add task");
       
   326     LoadedPlugin(EContextBrowse)->AddTaskL(EMcsBack, aCallback, this);
       
   327     }
       
   328 
       
   329 // ----------------------------------------------------------------------------
       
   330 // MediaL command
       
   331 // ----------------------------------------------------------------------------
       
   332 //
       
   333 EXPORT_C void CMPXCollectionClientContext::MediaL(
       
   334     const CMPXCommand& aCmd,
       
   335     MMPXCollectionEngineObserver* aCallback)
       
   336     {
       
   337     CMPXCollectionPath* path =
       
   338         aCmd.ValueCObjectL<CMPXCollectionPath>(KMPXCommandGeneralTargetIds);
       
   339     CleanupStack::PushL(path);
       
   340 
       
   341     // Increment the plugin reference count
       
   342     CMPXCollectionPlugin*plugin = iEngine.ResolvePluginL(*path);
       
   343     if (!plugin)
       
   344         {
       
   345         User::Leave(KErrArgument);
       
   346         }
       
   347 
       
   348     iEngine.CleanupPluginPushL(plugin);
       
   349 
       
   350     CMPXCommand* cmd = CMPXCommand::NewL(aCmd); // make a copy
       
   351     CleanupStack::PushL(cmd);
       
   352 
       
   353     plugin->AddTaskL(EMcsMediaByPath, aCallback, this,
       
   354                      0, NULL, plugin, cmd, path);
       
   355 
       
   356     CleanupStack::Pop(cmd); // Ownership transferred to the task queue
       
   357     iEngine.PluginPop();    // Pop the plugin
       
   358     CleanupStack::Pop(path);// Ownership transferred to the task queue
       
   359     }
       
   360 
       
   361 // ----------------------------------------------------------------------------
       
   362 // Add a media
       
   363 // ----------------------------------------------------------------------------
       
   364 //
       
   365 EXPORT_C void CMPXCollectionClientContext::AddL(const CMPXMedia& aMedia)
       
   366     {
       
   367     DoUpdateMediaL( EMcsAddItem, aMedia );
       
   368     }
       
   369 
       
   370 // ----------------------------------------------------------------------------
       
   371 // Remove a media
       
   372 // ----------------------------------------------------------------------------
       
   373 //
       
   374 EXPORT_C void CMPXCollectionClientContext::RemoveL(const CMPXMedia& aMedia)
       
   375     {
       
   376     DoUpdateMediaL( EMcsRemoveItem, aMedia );
       
   377     }
       
   378 
       
   379 // ----------------------------------------------------------------------------
       
   380 // Update a media
       
   381 // ----------------------------------------------------------------------------
       
   382 //
       
   383 EXPORT_C void CMPXCollectionClientContext::SetL(const CMPXMedia& aMedia)
       
   384     {
       
   385     DoUpdateMediaL( EMcsSetMedia, aMedia );
       
   386     }
       
   387 
       
   388 // ----------------------------------------------------------------------------
       
   389 // Remove media by path
       
   390 // ----------------------------------------------------------------------------
       
   391 //
       
   392 EXPORT_C void CMPXCollectionClientContext::RemoveL(
       
   393     CMPXCollectionPath* aPath,
       
   394     MMPXCollectionEngineObserver* aCallback)
       
   395     {
       
   396     TInt id(aPath->Id(CMPXCollectionPath::ECollectionUid));
       
   397 
       
   398     // Increment the plugin reference count
       
   399     CMPXCollectionPlugin* plugin = iEngine.ResolvePluginL(TUid::Uid(id));
       
   400     if (!plugin)
       
   401         {
       
   402         User::Leave(KErrArgument);
       
   403         }
       
   404 
       
   405     iEngine.CleanupPluginPushL(plugin);
       
   406 
       
   407     // Ownership of aPath transferred
       
   408     plugin->AddTaskL(EMcsRemovePath, aCallback, this, 0, NULL, plugin, aPath);
       
   409 
       
   410     iEngine.PluginPop();
       
   411     }
       
   412 
       
   413 // ----------------------------------------------------------------------------
       
   414 // Return current plugin id
       
   415 // ----------------------------------------------------------------------------
       
   416 //
       
   417 EXPORT_C TUid CMPXCollectionClientContext::PluginId() const
       
   418     {
       
   419     return iPluginUids[EContextBrowse];
       
   420     }
       
   421 
       
   422 // ----------------------------------------------------------------------------
       
   423 // Handle async request from client
       
   424 // ----------------------------------------------------------------------------
       
   425 //
       
   426 EXPORT_C const CMPXCollectionPath& CMPXCollectionClientContext::Path() const
       
   427     {
       
   428     return *iBrowsePath;
       
   429     }
       
   430 
       
   431 // ----------------------------------------------------------------------------
       
   432 // Cancel request
       
   433 // ----------------------------------------------------------------------------
       
   434 //
       
   435 EXPORT_C void CMPXCollectionClientContext::CancelRequest(
       
   436     MMPXCollectionEngineObserver* aCallback)
       
   437     {
       
   438     MPX_DEBUG3("CMPXCollectionClientContext::CancelRequest, this %08x, aCallback %08x",
       
   439                this, aCallback);
       
   440     iEngine.RemoveTask(aCallback);
       
   441     }
       
   442 
       
   443 // ----------------------------------------------------------------------------
       
   444 // Add a client
       
   445 // ----------------------------------------------------------------------------
       
   446 //
       
   447 EXPORT_C void CMPXCollectionClientContext::AddClientL(
       
   448     TThreadId aId,
       
   449     CMPXMessageQueue* aMsgQueue)
       
   450     {
       
   451     iClientList->AddClientL(aId, aMsgQueue);
       
   452     }
       
   453 
       
   454 // ----------------------------------------------------------------------------
       
   455 // Remove a client
       
   456 // ----------------------------------------------------------------------------
       
   457 //
       
   458 EXPORT_C void CMPXCollectionClientContext::RemoveClient(
       
   459     const CMPXMessageQueue& aMsgQueue)
       
   460     {
       
   461     MPX_DEBUG2("CMPXCollectionClientContext::RemoveClient with the message queue 0x%08x",
       
   462                &aMsgQueue);
       
   463     TInt index(iClientList->Find(aMsgQueue));
       
   464     if (KErrNotFound != index)
       
   465         {
       
   466         iClientList->RemoveClient(index);
       
   467         }
       
   468     if (!iClientList->ClientCount())
       
   469         {
       
   470         iEngine.RemoveContext(*this);
       
   471         }
       
   472     }
       
   473 
       
   474 // ----------------------------------------------------------------------------
       
   475 // Gets the supported capabilities of the current browse plugin
       
   476 // ----------------------------------------------------------------------------
       
   477 //
       
   478 EXPORT_C TCollectionCapability CMPXCollectionClientContext::GetCapabilities()
       
   479     {
       
   480     TCollectionCapability cap(0);
       
   481     if (iPluginUids[EContextBrowse]!=KNullUid)
       
   482         {
       
   483         LoadedPlugin(EContextBrowse)->GetCapabilities();
       
   484         }
       
   485     return cap;
       
   486     }
       
   487 
       
   488 // ----------------------------------------------------------------------------
       
   489 // Find all aSync
       
   490 // ----------------------------------------------------------------------------
       
   491 //
       
   492 EXPORT_C void CMPXCollectionClientContext::FindAllL(
       
   493     const CMPXMedia& aMedia,
       
   494     CBufBase* aBuf,
       
   495     MMPXCollectionEngineObserver* aCallback)
       
   496     {
       
   497     CMPXCollectionPlugin* plugin(NULL); // Not owned
       
   498 
       
   499     // Increment the plugin reference count
       
   500     ResolvePluginL(aMedia, plugin);
       
   501     if (!plugin)
       
   502         {
       
   503         User::Leave(KErrNotFound);  // found nothing
       
   504         }
       
   505 
       
   506     iEngine.CleanupPluginPushL(plugin);
       
   507 
       
   508     // Add the task
       
   509     CMPXMedia* media = CMPXMedia::NewL(aMedia);
       
   510     CleanupStack::PushL(media);
       
   511     plugin->AddTaskL(EMcsFindAll, aCallback, this, 0, aBuf, plugin, media);
       
   512     CleanupStack::Pop(media); // Ownership transferred
       
   513 
       
   514     iEngine.PluginPop();
       
   515     }
       
   516 
       
   517 // ----------------------------------------------------------------------------
       
   518 // Find all sync
       
   519 // ----------------------------------------------------------------------------
       
   520 //
       
   521 EXPORT_C CMPXMedia* CMPXCollectionClientContext::FindAllSyncL(
       
   522     const CMPXMedia& aMedia,
       
   523     const CBufBase& aBuf)
       
   524     {
       
   525     CMPXCollectionPlugin* plugin(NULL); // Not owned
       
   526 
       
   527     // Increment the plugin reference count
       
   528     ResolvePluginL(aMedia, plugin);
       
   529     iEngine.CleanupPluginPushL(plugin);
       
   530 
       
   531     CMPXMedia* result(NULL);
       
   532     FindAllL(aMedia, aBuf, *plugin, &result, ETrue);
       
   533 
       
   534     // Synchronous call, safe to release the plugin
       
   535     CleanupStack::PopAndDestroy();    // plugin
       
   536     return result;
       
   537     }
       
   538 
       
   539 // ----------------------------------------------------------------------------
       
   540 // Set filter
       
   541 // ----------------------------------------------------------------------------
       
   542 //
       
   543 EXPORT_C void CMPXCollectionClientContext::SetFilterL(const CMPXFilter* aFilter)
       
   544     {
       
   545     delete iFilter;
       
   546     iFilter = NULL;
       
   547     iFilter = aFilter ? CMPXFilter::NewL(*aFilter) : NULL;
       
   548     }
       
   549 
       
   550 // ----------------------------------------------------------------------------
       
   551 // Returns filter
       
   552 // ----------------------------------------------------------------------------
       
   553 //
       
   554 EXPORT_C const CMPXFilter* CMPXCollectionClientContext::Filter() const
       
   555     {
       
   556     return iFilter;
       
   557     }
       
   558 
       
   559 // ----------------------------------------------------------------------------
       
   560 // Handle a command
       
   561 // ----------------------------------------------------------------------------
       
   562 //
       
   563 EXPORT_C void CMPXCollectionClientContext::CommandL(
       
   564     TMPXCollectionCommand aCmd,
       
   565     TInt aData)
       
   566     {
       
   567     switch( aCmd )
       
   568         {
       
   569         case EMcCmdRemoveAll:
       
   570         case EMcCmdReCreateDB: // fall through
       
   571         case EMcCmdDbCorrupted: // fall through
       
   572             {
       
   573             TUid uid = TUid::Uid(aData);
       
   574 
       
   575             // Increment the plugin reference count
       
   576             CMPXCollectionPlugin* plugin = iEngine.ResolvePluginL( uid );
       
   577             iEngine.CleanupPluginPushL(plugin);
       
   578 
       
   579             if( plugin )
       
   580                 {
       
   581                 // The trap is needed to keep the plugin reference count in sync
       
   582                 plugin->CommandL(aCmd);
       
   583                 }
       
   584 
       
   585             CleanupStack::PopAndDestroy();    // plugin
       
   586             break;
       
   587             }
       
   588         case EMcCmdSelect:
       
   589             if (iBrowsePath->Levels()<=0)
       
   590                 {
       
   591                 User::Leave(KErrNotReady);
       
   592                 }
       
   593             if (aData<0 || aData>=iBrowsePath->Count())
       
   594                 {
       
   595                 User::Leave(KErrArgument);
       
   596                 }
       
   597             iBrowsePath->Set(aData);
       
   598             iClientList->SendMsgL(
       
   599                   TMPXCollectionMessage(TMPXCollectionMessage::EFocusChanged,
       
   600                                         aData, aData));
       
   601             iIndex = aData; // iIndex will always be up to date
       
   602             iFocusItemId = iBrowsePath->Id();
       
   603             break;
       
   604         case EMcCmdCollectionInit:
       
   605         case EMcCmdCollectionResyn:
       
   606             {
       
   607             TUid uid = TUid::Uid(aData);
       
   608             // Increment the plugin reference count
       
   609             CMPXCollectionPlugin* plugin = iEngine.ResolvePluginL(uid);
       
   610             if( !plugin )
       
   611                 {
       
   612                 User::Leave(KErrArgument);
       
   613                 }
       
   614 
       
   615             iEngine.CleanupPluginPushL(plugin);
       
   616 
       
   617             plugin->AddTaskL(EMcsCommand, NULL, this, aCmd, NULL, plugin);
       
   618 
       
   619             iEngine.PluginPop();
       
   620             break;
       
   621             }
       
   622         default:
       
   623             {
       
   624             User::Leave(KErrNotSupported);
       
   625             break;
       
   626             }
       
   627         }
       
   628     }
       
   629 
       
   630 // ----------------------------------------------------------------------------
       
   631 // Handle a command
       
   632 // ----------------------------------------------------------------------------
       
   633 //
       
   634 EXPORT_C void CMPXCollectionClientContext::CommandL(
       
   635     const CMPXCommand& aCmd,
       
   636     MMPXCollectionEngineObserver* aCallback,
       
   637     const CMPXMessageQueue& aMsgQueue)
       
   638     {
       
   639     // Use the plugin id defined by the command object,
       
   640     // or the browse context if collection id not defined
       
   641     CMPXCollectionPlugin* plugin = NULL;
       
   642     if (aCmd.IsSupported(KMPXCommandGeneralCollectionId))
       
   643         {
       
   644         TInt data = aCmd.ValueTObjectL<TInt>(KMPXCommandGeneralCollectionId);
       
   645 
       
   646         // Increment the plugin reference count
       
   647         plugin = iEngine.ResolvePluginL(TUid::Uid(data));
       
   648         }
       
   649     if (!plugin && iPluginUids[EContextBrowse]!=KNullUid)
       
   650         {
       
   651         plugin = LoadedPlugin(EContextBrowse);
       
   652 
       
   653         // Increment the plugin reference count manually
       
   654         iEngine.UsePlugin(plugin->Uid());
       
   655         }
       
   656    iEngine.CleanupPluginPushL(plugin);
       
   657 
       
   658    TBool async(ETrue); // by default command is asynchronous
       
   659    if (aCmd.IsSupported(KMPXCommandGeneralDoSync))
       
   660        { // check if command is sync
       
   661        async=!(aCmd.ValueTObjectL<TBool>(KMPXCommandGeneralDoSync));
       
   662        }
       
   663 
       
   664    if (async)
       
   665         { // Async, cmd ownership transferred
       
   666         if (!plugin)
       
   667             {
       
   668             User::Leave(KErrNotReady);
       
   669             }
       
   670 
       
   671         CMPXCommand* cmd = CMPXCommand::NewL(aCmd);
       
   672         CleanupStack::PushL(cmd);
       
   673         plugin->AddTaskL(EMcsCommandExt, aCallback, this, 0,
       
   674                         NULL, plugin, cmd);
       
   675         CleanupStack::Pop(cmd);
       
   676 
       
   677         // Async, the plugin pointer passed through the task queue
       
   678         iEngine.PluginPop();
       
   679         }
       
   680     else
       
   681         {
       
   682         DoHandleSyncCommandL(aCmd, aMsgQueue, plugin);
       
   683         CleanupStack::PopAndDestroy();     // plugin
       
   684         }
       
   685     }
       
   686 
       
   687 // ----------------------------------------------------------------------------
       
   688 // Find a shareable client
       
   689 // ----------------------------------------------------------------------------
       
   690 //
       
   691 TBool CMPXCollectionClientContext::HasShareableClient(
       
   692     TThreadId aId)
       
   693     {
       
   694     TBool ret(EFalse);
       
   695     if (iModeId != KMcModePlaylist)
       
   696         {
       
   697         if (iClientList->IsClient(aId) )    // Just look for same thread
       
   698             {
       
   699             ret = ETrue;
       
   700             }
       
   701         }
       
   702     return ret;
       
   703     }
       
   704 
       
   705 // ----------------------------------------------------------------------------
       
   706 // Notifies all clients of events
       
   707 // ----------------------------------------------------------------------------
       
   708 //
       
   709 void CMPXCollectionClientContext::NotifyL( TMPXCollectionBroadCastMsg aMsg,
       
   710                                            TInt aData )
       
   711     {
       
   712     iClientList->SendMsgL(
       
   713           TMPXCollectionMessage(TMPXCollectionMessage::EBroadcastEvent,
       
   714                                 aMsg,aData));
       
   715     }
       
   716 
       
   717 const TUid& CMPXCollectionClientContext::ModeId() const
       
   718     {
       
   719     return iModeId;
       
   720     }
       
   721 
       
   722 // ----------------------------------------------------------------------------
       
   723 // Initialises from file. iFile is not owned here
       
   724 // ----------------------------------------------------------------------------
       
   725 //
       
   726 void CMPXCollectionClientContext::OpenL()
       
   727     {
       
   728     if (iPathUpdated)
       
   729         {
       
   730         ReOpenL();
       
   731         }
       
   732     else
       
   733         {
       
   734         CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse);
       
   735         MPX_ASSERT(plugin);
       
   736         plugin->CompleteTask();
       
   737         if (plugin->Callback())
       
   738             {
       
   739             plugin->Callback()->HandleOpen(iMedia,
       
   740                                                    iIndex, ETrue,iMediaType);
       
   741             plugin->SetCallback( NULL ); // Reset current observer
       
   742             plugin->SetObserver(iEngine);
       
   743             }
       
   744         }
       
   745     }
       
   746 
       
   747 // ----------------------------------------------------------------------------
       
   748 // Cancels all outstanding calls (tasks): plug-in should only have one
       
   749 // outstanding so that is canceled; the tasks are deleted and removed from the
       
   750 //  queue
       
   751 // ----------------------------------------------------------------------------
       
   752 //
       
   753 void CMPXCollectionClientContext::BackL()
       
   754     {
       
   755     TInt d=iBrowsePath->Levels();
       
   756     if(d>1)
       
   757         {
       
   758         iPathUpdated = EFalse;
       
   759         // remove last item - the actual item selected
       
   760         iBrowsePath->Back();
       
   761         // preserve focus, since we're rebuilding this level
       
   762         iIndex=iBrowsePath->Index();
       
   763         iFocusItemId = iBrowsePath->Id();
       
   764         ReOpenL();
       
   765         }
       
   766     }
       
   767 
       
   768 // ----------------------------------------------------------------------------
       
   769 // Re-open current level
       
   770 // ----------------------------------------------------------------------------
       
   771 //
       
   772 void CMPXCollectionClientContext::ReOpenL()
       
   773     {
       
   774     // remove last item - go to the container which contained the item
       
   775     if (iBrowsePath->Levels())
       
   776         {
       
   777         iBrowsePath->Back();
       
   778         }
       
   779     if (iBrowsePath->Levels() == 0)
       
   780         {
       
   781         //Plugin must be resolved ealier
       
   782         CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse);
       
   783         plugin->CompleteTask();
       
   784         InitL(plugin->Callback());
       
   785         }
       
   786     else
       
   787         {
       
   788         DoPluginOpenL();
       
   789         }
       
   790     }
       
   791 
       
   792 // ----------------------------------------------------------------------------
       
   793 // Retrieve media info based on a find criteria
       
   794 // ----------------------------------------------------------------------------
       
   795 //
       
   796 void CMPXCollectionClientContext::FindAllL(
       
   797     const CMPXMedia& aMedia,
       
   798     const CBufBase& aBuf,
       
   799     CMPXCollectionPlugin& aPlugin,
       
   800     CMPXMedia** aResult /*= NULL*/,
       
   801     TBool aSync /*= EFalse*/)
       
   802     {
       
   803     // Find critera and return attributes
       
   804     //
       
   805     RArray<TMPXAttribute> attrs;
       
   806     CleanupClosePushL(attrs);
       
   807     ::CreateFromBufferL(aBuf, attrs);
       
   808 
       
   809     // Do the query
       
   810     if (!aSync)
       
   811         {
       
   812         aPlugin.SetObserver(*this);
       
   813         aPlugin.FindAllL(aMedia,attrs.Array());
       
   814         }
       
   815     else
       
   816         {
       
   817         *aResult = aPlugin.FindAllSyncL(aMedia,attrs.Array());
       
   818         }
       
   819     CleanupStack::PopAndDestroy( &attrs );
       
   820     }
       
   821 
       
   822 // ----------------------------------------------------------------------------
       
   823 // CMPXCollectionClientContext::HandleMessage
       
   824 // ----------------------------------------------------------------------------
       
   825 //
       
   826 void CMPXCollectionClientContext::HandleMessage(
       
   827     CMPXMessage* aMsg,
       
   828     TInt aError)
       
   829     {
       
   830     MPX_FUNC_EX("CMPXCollectionClientContext::HandleMessage");
       
   831     DoHandleMessage(aMsg, aError, ETrue);
       
   832     }
       
   833 
       
   834 // ----------------------------------------------------------------------------
       
   835 // CMPXCollectionClientContext::HandleMessage
       
   836 // ----------------------------------------------------------------------------
       
   837 //
       
   838 void CMPXCollectionClientContext::DoHandleMessage(
       
   839     CMPXMessage* aMsg,
       
   840     TInt aError,
       
   841     TBool aNotifyOthers)
       
   842     {
       
   843     MPX_DEBUG3("-->CMPXCollectionClientContext::HandleMessage this %08x, %d", this, aNotifyOthers);
       
   844     if (!aMsg)
       
   845         {
       
   846         iClientList->SendMsg(aMsg, aError);
       
   847         if (aNotifyOthers)
       
   848             {
       
   849             iEngine.NotifyChange(*this, aMsg, aError);
       
   850             }
       
   851         }
       
   852     else
       
   853         {
       
   854         if (aMsg->IsSupported(KMPXMessageGeneralId))
       
   855             {
       
   856             if (aMsg->IsSupported(KMPXMessageArrayContents))
       
   857                 {
       
   858                 TBool pathUpdated(EFalse);
       
   859                 const CMPXMessageArray* messageArray =
       
   860                     aMsg->Value<CMPXMessageArray>(KMPXMessageArrayContents);
       
   861                 if (messageArray)
       
   862                     {
       
   863                     TInt count = messageArray->Count();
       
   864 
       
   865                     MPX_DEBUG2("%d messages:", count);
       
   866 
       
   867                     for (TInt i=0; i<count; i++)
       
   868                         {
       
   869                         const CMPXMessage* message =(*messageArray)[i];
       
   870                         if (message)
       
   871                             {
       
   872                             TRAP_IGNORE(DoHandleMessageL(*message, KErrNone));
       
   873                             pathUpdated |=iPathUpdated;
       
   874                             }
       
   875                         }
       
   876                     iPathUpdated = pathUpdated;
       
   877                     }
       
   878                 // Notify other context, collection is changed.
       
   879                 // Send the batched version
       
   880                 //
       
   881                 if (aNotifyOthers)
       
   882                     {
       
   883                     iEngine.NotifyChange(*this,
       
   884                                          const_cast<CMPXMessage*>(aMsg),
       
   885                                          aError);
       
   886                     }
       
   887                 }
       
   888             else
       
   889                 {
       
   890                 TRAP_IGNORE(DoHandleMessageL(*aMsg, aError));
       
   891 
       
   892                 // Notify other context, collection is changed.
       
   893                 if (aNotifyOthers)
       
   894                     {
       
   895                     iEngine.NotifyChange(*this, aMsg, aError);
       
   896                     }
       
   897                 }
       
   898 
       
   899             // Broadcast change messages to the clients to handle
       
   900             //
       
   901             if( iModeId == KMcModePlaylist )
       
   902                 {
       
   903                 // Playlist should not be handling msgs during refresh
       
   904                 if( !iEngine.IsRefreshing() )
       
   905                     {
       
   906                     iClientList->SendMsg( aMsg, aError );
       
   907                     }
       
   908                 }
       
   909             else
       
   910                 {
       
   911                 // Other modes receive msg all the time
       
   912                 iClientList->SendMsg( aMsg, aError );
       
   913                 }
       
   914 
       
   915             // Batched collection change messages and only send this once
       
   916             // Path changed isn't sent to the UI during refresh
       
   917             //
       
   918             if (iPathUpdated)
       
   919                 {
       
   920                 MPX_DEBUG1("CMPXCollectionClientContext::DoHandleMessageL detected path changed");
       
   921                 MPX_DEBUG_PATH(*iBrowsePath);
       
   922                 // notify clients to refresh
       
   923                 TRAP_IGNORE(iClientList->SendMsgL(
       
   924                     TMPXCollectionMessage(TMPXCollectionMessage::EPathChanged,
       
   925                                           EMcPathChangedByCollectionChange)));
       
   926                 }
       
   927             }
       
   928         }
       
   929 
       
   930     MPX_DEBUG3("<--CMPXCollectionClientContext::HandleMessage this %08x, %d", this, aNotifyOthers);
       
   931     }
       
   932 
       
   933 // ----------------------------------------------------------------------------
       
   934 // Handle collection item change message
       
   935 // ----------------------------------------------------------------------------
       
   936 //
       
   937 void CMPXCollectionClientContext::DoHandleMessageL(
       
   938     const CMPXMessage& aMsg,
       
   939     TInt /*aError*/)
       
   940     {
       
   941     MPX_DEBUG2("-->CMPXCollectionClientContext::DoHandleMessageL this %08x", this);
       
   942     TInt browseLevels = iBrowsePath->Levels(); // browse depth
       
   943 
       
   944     if (aMsg.ValueTObjectL<TMPXMessageId>(KMPXMessageGeneralId)==
       
   945         KMPXMessageIdItemChanged)
       
   946         {
       
   947         if (!aMsg.IsSupported(KMPXMessageCollectionId) ||
       
   948             !aMsg.IsSupported(KMPXMessageChangeEventType) ||
       
   949             !aMsg.IsSupported(KMPXMessageMediaGeneralCategory) ||
       
   950             !aMsg.IsSupported(KMPXMessageMediaGeneralId))
       
   951             {
       
   952             User::Leave(KErrArgument);
       
   953             }
       
   954 
       
   955         TUid collectionId = aMsg.ValueTObjectL<TUid>(KMPXMessageCollectionId);
       
   956 
       
   957         TMPXChangeEventType changeType =
       
   958             aMsg.ValueTObjectL<TMPXChangeEventType>(KMPXMessageChangeEventType);
       
   959 
       
   960         TMPXGeneralCategory category =
       
   961             aMsg.ValueTObjectL<TMPXGeneralCategory>(KMPXMessageMediaGeneralCategory);
       
   962 
       
   963         TMPXItemId itemId = aMsg.ValueTObjectL<TMPXItemId>(KMPXMessageMediaGeneralId);
       
   964 
       
   965         TMPXItemId deprecatedId(0);
       
   966         if (aMsg.IsSupported(KMPXMessageMediaDeprecatedId))
       
   967             {
       
   968             deprecatedId = aMsg.ValueTObjectL<TMPXItemId>(KMPXMessageMediaDeprecatedId);
       
   969             }
       
   970 
       
   971         MPX_DEBUG5("CMPXCollectionClientContext::DoHandleMessageL colId %08x, id %d, deprecatedId %d, type %d",
       
   972                   collectionId.iUid, itemId.iId1, deprecatedId.iId1, changeType);
       
   973 
       
   974 
       
   975         if(!iEngine.IsRefreshing())
       
   976             {
       
   977             // Invalidate path
       
   978             TInt pct = KErrNotFound; // path change type
       
   979             if (changeType == EMPXItemInserted && category != EMPXPlaylist)
       
   980                 {
       
   981                 pct = CMPXCollectionPath ::EAdded;
       
   982                 }
       
   983             else if (changeType == EMPXItemModified && category != EMPXPlaylist)
       
   984                 {
       
   985                 pct = CMPXCollectionPath ::EModified;
       
   986                 }
       
   987             else if (changeType == EMPXItemDeleted)
       
   988                 {
       
   989                 pct = CMPXCollectionPath ::EDeleted;
       
   990                 }
       
   991             else if ((changeType == EMPXItemInserted || changeType == EMPXItemModified) &&
       
   992                      category == EMPXPlaylist)
       
   993                 {
       
   994                 pct = CMPXCollectionPath ::EGroupModified;
       
   995                 }
       
   996             if( changeType == EMPXItemModified && category == EMPXCollection )
       
   997                 {
       
   998                 // Overwrite previous type
       
   999                 pct = CMPXCollectionPath ::EGroupModified;
       
  1000                 }
       
  1001 
       
  1002             if (KErrNotFound != pct)
       
  1003                 { // update browse path
       
  1004                 CMPXCollectionPath::TMPXCollectionPathChange ct =
       
  1005                     static_cast<CMPXCollectionPath::TMPXCollectionPathChange>(pct);
       
  1006                 TInt pUpdated(CMPXCollectionPath::EPathUnchanged);
       
  1007 
       
  1008                 // If browse context and browse context is being modified
       
  1009                 //
       
  1010                 if (iModeId != KMcModePlaylist && browseLevels &&
       
  1011                     iBrowsePath->Id(0) == collectionId.iUid )
       
  1012                     { // check the browse path
       
  1013                     TInt tmpIndex(0);
       
  1014 
       
  1015                     pUpdated = iBrowsePath->HandleChange(
       
  1016                                        collectionId, itemId, deprecatedId, ct,
       
  1017                                        tmpIndex);
       
  1018 
       
  1019                     // Take the updated selection index only if it was affected
       
  1020                     // We need to store the TMPXItemId for iIndex because
       
  1021                     // a previous collection change would have removed the
       
  1022                     // top level of the collection path
       
  1023                     //
       
  1024                     iPathUpdated = iPathUpdated ||
       
  1025                                    (pUpdated != CMPXCollectionPath::EPathUnchanged);
       
  1026                     if( pUpdated )
       
  1027                         {
       
  1028                         // Only update the selection index if the itemid that
       
  1029                         // was modified is equal to the one selected
       
  1030                         //
       
  1031                         // OR take in the index if clipped the collection path
       
  1032                         // (pUpdated == KPathClipped )
       
  1033                         //
       
  1034                         if( pUpdated == CMPXCollectionPath::EPathClipped )
       
  1035                             {
       
  1036                             iIndex = tmpIndex;
       
  1037                             iFocusItemId = KMPXInvalidItemId;
       
  1038                             }
       
  1039                         else if( iFocusItemId.ApproxEqual(itemId ) &&
       
  1040                                  ( iFocusItemId != KMPXInvalidItemId )  )
       
  1041                             {
       
  1042                             // Also make sure the index that came back from
       
  1043                             // checking the collection path isn't -1
       
  1044                             //
       
  1045                             // The only case where the selected item will shift
       
  1046                             // is when we are deleting that item. updaing the item or adding
       
  1047                             // an item to the current path should not move the focus to another
       
  1048                             // item
       
  1049                             //
       
  1050                             if( tmpIndex != -1 && changeType == EMPXItemDeleted)
       
  1051                                 {
       
  1052                                 if( tmpIndex == iBrowsePath->Count()-1 )
       
  1053                                     {
       
  1054                                     // Last item, focus on previous
       
  1055                                     iIndex = tmpIndex-1;
       
  1056                                     iFocusItemId = iBrowsePath->IdOfIndex( tmpIndex-1 );
       
  1057                                     }
       
  1058                                 else
       
  1059                                     {
       
  1060                                     // Not last, focus on next
       
  1061                                     iFocusItemId = iBrowsePath->IdOfIndex( tmpIndex+1 );
       
  1062                                     }
       
  1063                                 }
       
  1064                             }
       
  1065                         else if( iFocusItemId.ApproxEqual( deprecatedId ) &&
       
  1066                                  changeType == EMPXItemModified )
       
  1067                             {
       
  1068                             // If we are modifying the item id of an item currently in focus
       
  1069                             // We move the focus to the new item id
       
  1070                             //
       
  1071                             iFocusItemId = itemId;
       
  1072                             }
       
  1073                         }
       
  1074                     }
       
  1075                 }
       
  1076             }
       
  1077         }
       
  1078     else
       
  1079         {
       
  1080         // do nothing
       
  1081         }
       
  1082     MPX_DEBUG2("<--CMPXCollectionClientContext::DoHandleMessageL this %08x", this);
       
  1083     }
       
  1084 
       
  1085 // ----------------------------------------------------------------------------
       
  1086 // Handle open event
       
  1087 // ----------------------------------------------------------------------------
       
  1088 //
       
  1089 void CMPXCollectionClientContext::HandleOpen(
       
  1090     CMPXMedia* aMedia,
       
  1091     TInt aErr)
       
  1092     {
       
  1093     MPX_FUNC("CMPXCollectionClientContext::HandleOpen with media returned");
       
  1094     CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse);
       
  1095     MPX_ASSERT(plugin);
       
  1096 
       
  1097     // Callback and Task Completion
       
  1098     //
       
  1099     MMPXCollectionEngineObserver* callback(NULL);
       
  1100     TBool openTask(EFalse);
       
  1101     TInt task = plugin->Task();
       
  1102     if( task == EMcsOpen || task == EMcsOpenPath ||
       
  1103         task == EMcsBack || task == EMcsOpenIndex )
       
  1104         {
       
  1105         callback = plugin->Callback();
       
  1106         openTask = ETrue;
       
  1107         }
       
  1108 
       
  1109     // Cachable flag
       
  1110     //
       
  1111     TBool cache(EFalse);
       
  1112     if( iBrowsePath &&
       
  1113         iBrowsePath->Levels() >= 1 )
       
  1114         {
       
  1115         TMPXItemId id(iBrowsePath->Id(CMPXCollectionPath::ECollectionUid) );
       
  1116         cache = iEngine.PluginCacheable( TUid::Uid( id ) );
       
  1117         }
       
  1118 
       
  1119     TRAPD(err, DoHandleOpenL(aMedia, NULL, callback, aErr, cache, openTask));
       
  1120     if (err && openTask)
       
  1121         {
       
  1122         HandleError(*plugin, err);
       
  1123         }
       
  1124     else if( openTask )
       
  1125         {
       
  1126         plugin->CompleteTask();
       
  1127         }
       
  1128     }
       
  1129 
       
  1130 // ----------------------------------------------------------------------------
       
  1131 // Handle open event
       
  1132 // ----------------------------------------------------------------------------
       
  1133 //
       
  1134 void CMPXCollectionClientContext::HandleOpen(
       
  1135     CMPXMedia* aMedia,
       
  1136     const CMPXCollectionPath* aPath,
       
  1137     TInt aErr)
       
  1138     {
       
  1139     MPX_FUNC("CMPXCollectionClientContext::HandleOpen with media returned");
       
  1140     CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse);
       
  1141     MPX_ASSERT(plugin);
       
  1142 
       
  1143     // Callback and Task Completion
       
  1144     //
       
  1145     MMPXCollectionEngineObserver* p(NULL);
       
  1146     TBool openTask(EFalse);
       
  1147     TInt task = plugin->Task();
       
  1148     if( task == EMcsOpen || task == EMcsOpenPath ||
       
  1149         task == EMcsBack || task == EMcsOpenIndex )
       
  1150         {
       
  1151         p = plugin->Callback();
       
  1152         openTask = ETrue;
       
  1153         }
       
  1154 
       
  1155     // Cachable flag
       
  1156     //
       
  1157     TBool cache(EFalse);
       
  1158     if( iBrowsePath &&
       
  1159         iBrowsePath->Levels() >= 1 )
       
  1160         {
       
  1161         TMPXItemId id(iBrowsePath->Id(CMPXCollectionPath::ECollectionUid) );
       
  1162         cache = iEngine.PluginCacheable( TUid::Uid( id ) );
       
  1163         }
       
  1164 
       
  1165     // Handle OpenL for Media
       
  1166     //
       
  1167     TRAPD(err, DoHandleOpenL(aMedia, aPath, p, aErr, cache, openTask));
       
  1168     if (err && openTask)
       
  1169         {
       
  1170         HandleError(*plugin, err);
       
  1171         }
       
  1172     else if( openTask )
       
  1173         {
       
  1174         plugin->CompleteTask();
       
  1175         }
       
  1176     }
       
  1177 
       
  1178 // ----------------------------------------------------------------------------
       
  1179 // Handle open event
       
  1180 // ----------------------------------------------------------------------------
       
  1181 //
       
  1182 void CMPXCollectionClientContext::DoHandleOpenL(
       
  1183     CMPXMedia* aMedia,
       
  1184     const CMPXCollectionPath* aPath,
       
  1185     MMPXCollectionEngineObserver* aCallback,
       
  1186     TInt aErr,
       
  1187     TBool aAddToCache,
       
  1188     TBool aOpenTask )
       
  1189     {
       
  1190     MPX_FUNC("CMPXCollectionClientContext::DoHandleOpen with media returned");
       
  1191 
       
  1192     // Make sure if we are updating the results the paths are aligned!
       
  1193     //
       
  1194     TBool openUpdate(EFalse);
       
  1195     if( !aOpenTask )
       
  1196         {
       
  1197         openUpdate = ETrue;
       
  1198         iCacheMedia = ETrue;
       
  1199         if( aPath &&
       
  1200             aPath->Levels() != iBrowsePath->Levels() )
       
  1201             {
       
  1202             User::Leave( KErrArgument );
       
  1203             }
       
  1204         }
       
  1205 
       
  1206     // Add to cache
       
  1207     //
       
  1208     if ( iBrowsePath->Levels() && aAddToCache && aMedia && iCacheMedia )
       
  1209         {
       
  1210         // manage the priority
       
  1211         CMPXCollectionCache::TCachePriority priority(CMPXCollectionCache::EPriorityNormal);
       
  1212         if ((1 == iBrowsePath->Levels()) ||
       
  1213             ((2 == iBrowsePath->Levels()) && ((iBrowsePath->Id(1)).iId1 == 0)))
       
  1214             {
       
  1215             priority = CMPXCollectionCache::EPriorityHigh;
       
  1216             }
       
  1217 
       
  1218         if( !aOpenTask )
       
  1219             {
       
  1220             // Update the current browse path
       
  1221             //
       
  1222             CMPXCollectionPath* container = iBrowsePath->ContainerPathL();
       
  1223             CleanupStack::PushL( container );
       
  1224 
       
  1225             // Add the data to the generic cache and get the latest copy
       
  1226             //
       
  1227             aMedia = AddToCache( *container,
       
  1228                          aMedia->Attributes(),
       
  1229                          *aMedia,
       
  1230                          ETrue,
       
  1231                          priority);
       
  1232             CleanupStack::PopAndDestroy( container );
       
  1233             }
       
  1234         else
       
  1235             {
       
  1236             AddToCache( *iBrowsePath,
       
  1237                          aMedia->Attributes(),
       
  1238                          *aMedia,
       
  1239                          ETrue,
       
  1240                          priority);
       
  1241             }
       
  1242         }
       
  1243 
       
  1244     // Current client context browse path media
       
  1245     //
       
  1246     iMediaType = KMPXCollectionEntries;
       
  1247     if (iMedia != aMedia)
       
  1248         { // new media
       
  1249         delete iMedia;
       
  1250         iMedia = NULL;
       
  1251         if (aMedia)
       
  1252             {
       
  1253             iMedia = CMPXMedia::NewL(*aMedia);
       
  1254             }
       
  1255         }
       
  1256 
       
  1257     TInt n(0);
       
  1258     if (aMedia && KErrNone == aErr)
       
  1259         {  // Update the path
       
  1260         RArray<TInt> selectionIndicies;
       
  1261         CleanupClosePushL( selectionIndicies );
       
  1262 
       
  1263         if (aPath)
       
  1264             { // Update path from aPath
       
  1265             if ( aMedia->IsSupported (KMPXCollectionOpenLAllResultRange))
       
  1266                 {
       
  1267                 iBrowsePath->Back ();
       
  1268                 RArray<TMPXItemId> ids;
       
  1269                 CleanupClosePushL (ids);
       
  1270                 RArray<TMPXOpenDataBlock> datablocks;
       
  1271                 CleanupClosePushL (datablocks);
       
  1272                 // De-serialize from global data, would be good to have global arrays
       
  1273                 //
       
  1274                 const TDesC
       
  1275                         & buf = aMedia->ValueText (KMPXCollectionOpenLAllResultRange);
       
  1276                 CBufBase* buffer(NULL);
       
  1277                 MPXUser::CreateBufferL ( buf, buffer);
       
  1278                 CleanupStack::PushL ( buffer);
       
  1279                 ::CreateFromBufferL ( *buffer, datablocks);
       
  1280                 CleanupStack::PopAndDestroy ( buffer);
       
  1281 
       
  1282                 if ( aMedia->IsSupported (KMPXMediaArrayContents))
       
  1283                     {
       
  1284                     const CMPXMediaArray
       
  1285                             * mediaArray = aMedia->Value<CMPXMediaArray> (KMPXMediaArrayContents);
       
  1286                     User::LeaveIfNull (const_cast<CMPXMediaArray*>(mediaArray));
       
  1287                     TInt dataCount = mediaArray->Count ();
       
  1288                     TInt rangeCount = datablocks.Count ();
       
  1289                     for (TInt index = 0; index < dataCount; ++index)
       
  1290                         {
       
  1291                         CMPXMedia* media = mediaArray->AtL(index);
       
  1292 
       
  1293                         //Check range
       
  1294                         TBool validItem(EFalse);
       
  1295                         MPX_ASSERT(rangeCount > 0);
       
  1296                         for (TInt rangeIndex = 0; rangeIndex < rangeCount; ++rangeIndex)
       
  1297                             {
       
  1298                             TInt offset = datablocks[rangeIndex].iOffset;
       
  1299                             TInt size = datablocks[rangeIndex].iSize;
       
  1300                             if ( (index >= offset) && (index < offset + size))
       
  1301                                 {
       
  1302                                 validItem = ETrue;
       
  1303                                 break;
       
  1304                                 }
       
  1305                             }
       
  1306                         
       
  1307                         if (validItem)
       
  1308                             {
       
  1309                             const TMPXItemId
       
  1310                                     id = media->ValueTObjectL<TMPXItemId> (KMPXMediaGeneralId);
       
  1311                             ids.AppendL (id);
       
  1312                             }
       
  1313                         else
       
  1314                             {
       
  1315                             ids.AppendL (KMPXInvalidItemId);
       
  1316                             }
       
  1317                         }
       
  1318                     iBrowsePath->AppendL (ids.Array ());
       
  1319                     }
       
  1320                 CleanupStack::PopAndDestroy (&datablocks);
       
  1321                 CleanupStack::PopAndDestroy (&ids);
       
  1322                 }
       
  1323             else
       
  1324                 {
       
  1325                 delete iBrowsePath;
       
  1326                 iBrowsePath = NULL;
       
  1327                 iBrowsePath = CMPXCollectionPath::NewL ( *aPath);
       
  1328                 }
       
  1329             }
       
  1330         else
       
  1331             { // Update path from media
       
  1332             RArray<TMPXItemId> ids;
       
  1333             CleanupClosePushL(ids);
       
  1334             if( aMedia->IsSupported(KMPXMediaArrayContents) )
       
  1335                 {
       
  1336                 const CMPXMediaArray* mediaArray=aMedia->Value<CMPXMediaArray>(
       
  1337                                                             KMPXMediaArrayContents);
       
  1338                 User::LeaveIfNull(const_cast<CMPXMediaArray*>(mediaArray));
       
  1339                 n=mediaArray->Count();
       
  1340                 for (TInt i=0;i<n;++i)
       
  1341                     {
       
  1342                     CMPXMedia* media=mediaArray->AtL(i);
       
  1343                     const TMPXItemId id=media->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId);
       
  1344                     ids.AppendL(id);
       
  1345 
       
  1346                     // Try to look for the selection that we want
       
  1347                     if( iFocusItemId == id )
       
  1348                         {
       
  1349                         selectionIndicies.AppendL( i );
       
  1350                         }
       
  1351                     }
       
  1352                 }
       
  1353 
       
  1354             iBrowsePath->AppendL(ids.Array());
       
  1355             CleanupStack::PopAndDestroy(&ids);
       
  1356             }
       
  1357 
       
  1358         // List of items
       
  1359         const TArray<TMPXItemId>& items = iBrowsePath->Items();
       
  1360 
       
  1361         // OpenL Media has been updated, update the itemid
       
  1362         // based on the current index
       
  1363         if( openUpdate )
       
  1364             {
       
  1365             // Check if we have item id first
       
  1366             //
       
  1367             if( iFocusItemId != KMPXInvalidItemId )
       
  1368                 {
       
  1369                 TInt index = iBrowsePath->IndexOfId( iFocusItemId );
       
  1370                 if( index != KErrNotFound )
       
  1371                     {
       
  1372                     iIndex = index;
       
  1373                     }
       
  1374                 }
       
  1375 
       
  1376             // Then update based on index
       
  1377             if( iIndex >=0 && iIndex < iBrowsePath->Count() )
       
  1378                 {
       
  1379                 iBrowsePath->Set(iIndex);
       
  1380                 iFocusItemId = iBrowsePath->Id();
       
  1381                 }
       
  1382             }
       
  1383         else if( aMedia->IsSupported( KMPXCollectionOpenLResultRange ) )
       
  1384             {
       
  1385             TMPXOpenDataBlock data =
       
  1386                 aMedia->ValueTObjectL<TMPXOpenDataBlock>(KMPXCollectionOpenLResultRange);
       
  1387             if( iBrowsePath->Count() &&
       
  1388                 iIndex >= 0 &&
       
  1389                 iIndex < iBrowsePath->Count() )
       
  1390                 {
       
  1391                 // If all blank items then we don't change index yet
       
  1392                 // Wait until we have re-opened the partial data
       
  1393                 if( data.iOffset != KErrNotFound )
       
  1394                     {
       
  1395                     // Not supported, stay with current focus
       
  1396                     iBrowsePath->Set(iIndex);
       
  1397                     iFocusItemId = iBrowsePath->Id();
       
  1398                     }
       
  1399                 }
       
  1400             }
       
  1401         // If this selection appears more than once, then we have to find
       
  1402         // the closest matching index to what we had before
       
  1403         //
       
  1404         //
       
  1405         else if( selectionIndicies.Count() > 1 &&
       
  1406                  iFocusItemId != KMPXInvalidItemId )
       
  1407             {
       
  1408             TInt best(selectionIndicies[0]);
       
  1409             TInt idAppearance( selectionIndicies.Count() );
       
  1410             for( TInt i=0; i<idAppearance; ++i )
       
  1411                 {
       
  1412                 if( Abs(selectionIndicies[i]-iIndex) <= Abs(best-iIndex) )
       
  1413                     {
       
  1414                     best = selectionIndicies[i];
       
  1415                     }
       
  1416                 }
       
  1417             iIndex = best;
       
  1418             iBrowsePath->Set(iIndex);
       
  1419             }
       
  1420         // Always set by item id if we have it
       
  1421         // This is needed if an item was added to the current browse level
       
  1422         // We still want to select the item we were previously at
       
  1423         //
       
  1424         else if( iFocusItemId != KMPXInvalidItemId )
       
  1425             {
       
  1426             TInt index = iBrowsePath->IndexOfId(iFocusItemId);
       
  1427             if (KErrNotFound != index)
       
  1428                 {
       
  1429                 iBrowsePath->Set(index);
       
  1430                 }
       
  1431             else if( n > 0 ) // Focus item has been deleted, select next
       
  1432                 {
       
  1433                 // Bounds check for largest and smallest
       
  1434                 if( iIndex >= n )
       
  1435                     {
       
  1436                     iIndex = n-1;
       
  1437                     }
       
  1438                 if( iIndex < 0 )
       
  1439                     {
       
  1440                     iIndex = 0;
       
  1441                     }
       
  1442                 iBrowsePath->Set(iIndex);
       
  1443                 iFocusItemId = iBrowsePath->Id();
       
  1444                 }
       
  1445             iIndex = iBrowsePath->Index();
       
  1446             }
       
  1447         else
       
  1448             {
       
  1449             // Bounds checking for iIndex
       
  1450             if( iIndex >= n && iIndex > 0 )
       
  1451                 {
       
  1452                 iIndex = n-1;
       
  1453 
       
  1454                 // Just in case if ids has 0 items
       
  1455                 if( iIndex > 0 && iIndex < items.Count() )
       
  1456                     {
       
  1457                     iFocusItemId = items[iIndex];
       
  1458                     }
       
  1459                 }
       
  1460 
       
  1461             if (iBrowsePath->Levels()>0 && iIndex>=0 &&
       
  1462                 iIndex<iBrowsePath->Count())
       
  1463                 {
       
  1464                 iBrowsePath->Set(iIndex);
       
  1465                 }
       
  1466             iFocusItemId = iBrowsePath->Id();
       
  1467             }
       
  1468         CleanupStack::PopAndDestroy(&selectionIndicies);
       
  1469         }
       
  1470 
       
  1471     TInt err;
       
  1472     if( !iPathUpdated )
       
  1473         {
       
  1474         // Normal open mode
       
  1475         err = KErrNone == aErr ? KMPXPathUpdated : aErr;
       
  1476         }
       
  1477     else
       
  1478         {
       
  1479         // Updates open mode, should be returning entries
       
  1480         err = KErrNone == aErr ? KMPXCollectionEntries : aErr;
       
  1481         }
       
  1482 
       
  1483     // Should not be broadcasting container opened messages
       
  1484     // When we are only rebuilding the leaf level
       
  1485     //
       
  1486     if( !iPathUpdated && aOpenTask )
       
  1487         {
       
  1488         if( err >= KErrNone)
       
  1489             {
       
  1490             iClientList->SendMsgL(
       
  1491                 TMPXCollectionMessage(TMPXCollectionMessage::EPathChanged,
       
  1492                                       EMcPathChangedByOpen,
       
  1493                                       EMcContainerOpened));
       
  1494             }
       
  1495         }
       
  1496 
       
  1497     iPathUpdated = EFalse;
       
  1498 
       
  1499     // Notes: there should no leave function called after aCallback->HandleOpen
       
  1500     if (aCallback)
       
  1501         {  // Complete open with error or PathUpdated
       
  1502         aCallback->HandleOpen(iMedia, iIndex, ETrue, err);
       
  1503         if (iPluginUids[EContextBrowse]!=KNullUid)
       
  1504             {
       
  1505             CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse);
       
  1506             MPX_ASSERT(aCallback == plugin->Callback());
       
  1507             plugin->SetCallback(NULL);
       
  1508             plugin->SetObserver(iEngine);
       
  1509             }
       
  1510         }
       
  1511     MPX_DEBUG_PATH(*iBrowsePath);
       
  1512     }
       
  1513 
       
  1514 // ----------------------------------------------------------------------------
       
  1515 // Handle open event
       
  1516 // ----------------------------------------------------------------------------
       
  1517 //
       
  1518 void CMPXCollectionClientContext::HandleOpen(
       
  1519    CMPXCollectionPath* aPath,
       
  1520    TInt aErr)
       
  1521     {
       
  1522     MPX_FUNC("CMPXCollectionClientContext::HandleOpen with path returned");
       
  1523     TRAPD(err, DoHandleOpenL(aPath, aErr));
       
  1524     if (err)
       
  1525         {
       
  1526         HandleError(*(LoadedPlugin(EContextBrowse)), err);
       
  1527         }
       
  1528     }
       
  1529 
       
  1530 // ----------------------------------------------------------------------------
       
  1531 // Handle open event
       
  1532 // ----------------------------------------------------------------------------
       
  1533 //
       
  1534 void CMPXCollectionClientContext::DoHandleOpenL(
       
  1535     CMPXCollectionPath* aPath,
       
  1536     TInt aErr)
       
  1537     {
       
  1538     MPX_FUNC("CMPXCollectionClientContext::DoHandleOpen with path returned");
       
  1539     CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse);
       
  1540     MPX_ASSERT(plugin);
       
  1541 
       
  1542     plugin->CompleteTask();
       
  1543 
       
  1544     if (iBrowsePath != aPath && KErrNone == aErr)
       
  1545         {
       
  1546         delete iBrowsePath;
       
  1547         iBrowsePath = NULL;
       
  1548         MPX_ASSERT(aPath);
       
  1549         iBrowsePath = CMPXCollectionPath::NewL(*aPath);
       
  1550         }
       
  1551     iMediaType = KMPXCollectionPath;
       
  1552     iIndex = iBrowsePath->Index();
       
  1553     iFocusItemId = iBrowsePath->Id();
       
  1554 
       
  1555     TInt err = KErrNone == aErr ? KMPXPathUpdated : aErr;
       
  1556 
       
  1557     // Complete msg
       
  1558     // Complete open with error or PathUpdated
       
  1559     plugin->Callback()->HandleOpen(iMedia, iIndex, ETrue, err);
       
  1560     plugin->SetCallback(NULL);
       
  1561     plugin->SetObserver(iEngine);
       
  1562     if (aPath->OpenNextMode() != EMPXOpenNoPlaylist)
       
  1563          //
       
  1564          // The request was NOT to play, but the plug-in returned
       
  1565          // the path implying that we should play; so we don't
       
  1566          // send it
       
  1567          //
       
  1568         {
       
  1569         iClientList->SendMsgL(
       
  1570                TMPXCollectionMessage(TMPXCollectionMessage::EPathChanged,
       
  1571                                      EMcPathChangedByOpen,
       
  1572                                      EMcItemOpened));
       
  1573         }
       
  1574 
       
  1575     MPX_DEBUG_PATH(*iBrowsePath);
       
  1576     }
       
  1577 
       
  1578 // ----------------------------------------------------------------------------
       
  1579 // Callback of retrieving extended media property
       
  1580 // ----------------------------------------------------------------------------
       
  1581 //
       
  1582 void CMPXCollectionClientContext::HandleMedia(
       
  1583     CMPXMedia* aMedia,
       
  1584     TInt aError)
       
  1585     {
       
  1586     MPX_FUNC("CMPXCollectionClientContext::HandleMedia");
       
  1587 
       
  1588     CMPXMedia* ret( aMedia );
       
  1589 
       
  1590     TBool pluginCacheable(EFalse);
       
  1591     if( iMediaPath )
       
  1592         {
       
  1593         TMPXItemId id(iMediaPath->Id(CMPXCollectionPath::ECollectionUid) );
       
  1594         pluginCacheable = iEngine.PluginCacheable( TUid::Uid( id ) );
       
  1595 
       
  1596         // if media returned was resulted from multiple selections we don't cache the
       
  1597         // results as it's very hard to reuse it anyway
       
  1598         if(iMediaPath->Selection().Count() > 0)
       
  1599             {
       
  1600             pluginCacheable = EFalse;
       
  1601             }
       
  1602         }
       
  1603 
       
  1604     // Cache the media
       
  1605     if ( !aError && aMedia && iCacheMedia && iMediaPath && pluginCacheable )
       
  1606         {
       
  1607         TMPXItemId id( iMediaPath->Id(
       
  1608                             CMPXCollectionPath::ECollectionUid ));
       
  1609         ret = AddToCache( *iMediaPath, aMedia->Attributes(), *aMedia );
       
  1610         }
       
  1611 
       
  1612     CMPXCollectionPlugin* plugin = LoadedPlugin(EContextMedia);
       
  1613 
       
  1614     plugin->CompleteTask();
       
  1615     MPX_ASSERT(plugin->Callback());
       
  1616     plugin->Callback()->HandleMedia(ret, aError);
       
  1617     plugin->SetCallback(NULL); // Reset current observer
       
  1618     plugin->SetObserver(iEngine);
       
  1619     }
       
  1620 
       
  1621 // ----------------------------------------------------------------------------
       
  1622 // Callback of async CommandL
       
  1623 // ----------------------------------------------------------------------------
       
  1624 //
       
  1625  void CMPXCollectionClientContext::HandleCommandComplete(
       
  1626     CMPXCommand* aCommandResult,
       
  1627     TInt aError)
       
  1628     {
       
  1629     MPX_FUNC_EX("CMPXCollectionClientContext::HandleCommandComplete");
       
  1630     CMPXCollectionPlugin* plugin = LoadedPlugin(EContextMedia);
       
  1631 
       
  1632     plugin->CompleteTask();
       
  1633     MPX_ASSERT(plugin->Callback());
       
  1634     plugin->Callback()->HandleCommandComplete(aCommandResult, aError);
       
  1635     plugin->SetCallback(NULL); // Reset current observer
       
  1636     plugin->SetObserver(iEngine);
       
  1637     }
       
  1638 
       
  1639 // ----------------------------------------------------------------------------
       
  1640 // Handle find all
       
  1641 // ----------------------------------------------------------------------------
       
  1642 //
       
  1643 void CMPXCollectionClientContext::HandleFindAll(
       
  1644     CMPXMedia* aMedia,
       
  1645     TInt aError)
       
  1646     {
       
  1647     MPX_FUNC("CMPXCollectionClientContext::HandleFindAll");
       
  1648     CMPXCollectionPlugin* plugin = LoadedPlugin(EContextMedia);
       
  1649     plugin->CompleteTask();
       
  1650     MPX_ASSERT(plugin->Callback());
       
  1651     plugin->Callback()->HandleFindAll(aMedia, aError);
       
  1652     plugin->SetCallback(NULL); // Reset current observer
       
  1653     plugin->SetObserver(iEngine);
       
  1654     }
       
  1655 
       
  1656 // ----------------------------------------------------------------------------
       
  1657 // Handle delete all
       
  1658 // ----------------------------------------------------------------------------
       
  1659 //
       
  1660 void CMPXCollectionClientContext::HandleRemove(
       
  1661     const CDesCArray& aUriArray,
       
  1662     TInt aError)
       
  1663     {
       
  1664     MPX_FUNC("CMPXCollectionClientContext::HandleRemove");
       
  1665     CMPXCollectionPlugin* plugin = LoadedPlugin(EContextRemove);
       
  1666 
       
  1667     plugin->CompleteTask();
       
  1668     MPX_ASSERT(plugin->Callback());
       
  1669     plugin->Callback()->HandleRemove(aUriArray, aError);
       
  1670     plugin->SetCallback(NULL); // Reset current observer
       
  1671     plugin->SetObserver(iEngine);
       
  1672     }
       
  1673 
       
  1674 // ----------------------------------------------------------------------------
       
  1675 // Execute a async task
       
  1676 // ----------------------------------------------------------------------------
       
  1677 //
       
  1678 void CMPXCollectionClientContext::ExecuteTask(
       
  1679     TInt aTask,
       
  1680     TInt aParamData,
       
  1681     TAny* aPtrData,
       
  1682     const CBufBase& aBuf,
       
  1683     TAny* aCallback,
       
  1684     CBase* aCObject1,
       
  1685     CBase* aCObject2)
       
  1686     {
       
  1687     MPX_DEBUG2("-->CMPXCollectionClientContext::ExecuteTask %d", aTask);
       
  1688     CMPXCollectionPlugin* plugin(NULL);
       
  1689     TRAPD(err, ExecuteTaskL(aTask, aParamData, aPtrData, aCallback, aBuf,
       
  1690                             aCObject1,aCObject2,plugin));
       
  1691     if (KErrNone !=err)
       
  1692         {
       
  1693         HandleError(*plugin, err, EFalse);
       
  1694         }
       
  1695     MPX_DEBUG1("<--CMPXCollectionClientContext::ExecuteTask");
       
  1696     }
       
  1697 
       
  1698 // ----------------------------------------------------------------------------
       
  1699 // Indicates that a task was terminated with an error
       
  1700 // ----------------------------------------------------------------------------
       
  1701 //
       
  1702 void CMPXCollectionClientContext::HandleTaskError(
       
  1703     TInt aTask,
       
  1704     TAny* aPtrData,
       
  1705     TAny* aCallback,
       
  1706     TInt aError)
       
  1707     {
       
  1708     MPX_FUNC_EX("CMPXCollectionClientContext::HandleTaskError");
       
  1709     CMPXCollectionPlugin* plugin(NULL);
       
  1710     switch (aTask)
       
  1711         {
       
  1712         case EMcsOpen:
       
  1713         case EMcsBack:
       
  1714         case EMcsOpenIndex:
       
  1715             plugin = LoadedPlugin(EContextBrowse);
       
  1716             plugin->SetObserver(*this);
       
  1717             plugin->SetCallback(
       
  1718                     reinterpret_cast<MMPXCollectionEngineObserver*>(aCallback));
       
  1719             HandleError(*plugin, aError, EFalse);
       
  1720             break;
       
  1721         case EMcsOpenPath:
       
  1722         case EMcsMediaByPath:
       
  1723         case EMcsCommandExt:
       
  1724         case EMcsRemovePath:
       
  1725         case EMcsFindAll:
       
  1726         case EMcsCommand:
       
  1727             plugin = reinterpret_cast<CMPXCollectionPlugin*>(aPtrData);
       
  1728             plugin->SetCallback(
       
  1729                     reinterpret_cast<MMPXCollectionEngineObserver*>(aCallback));
       
  1730             HandleError(*plugin, aError, ETrue);
       
  1731             break;
       
  1732         default:
       
  1733             break;
       
  1734         }
       
  1735     }
       
  1736 
       
  1737 // ----------------------------------------------------------------------------
       
  1738 // Initialize before first open
       
  1739 // ----------------------------------------------------------------------------
       
  1740 //
       
  1741 void CMPXCollectionClientContext::InitL(MMPXCollectionEngineObserver* aCallback)
       
  1742     {
       
  1743     MPX_DEBUG1("CMPXCollectionClientContext::InitL() <---");
       
  1744     delete iMedia;
       
  1745     iMedia = NULL;
       
  1746     delete iBrowsePath;
       
  1747     iBrowsePath = NULL;
       
  1748     RArray<TInt> supportedIds;
       
  1749     CleanupClosePushL(supportedIds);
       
  1750     supportedIds.AppendL(KMPXMediaIdContainer);
       
  1751     supportedIds.AppendL(KMPXMediaIdGeneral);
       
  1752     iMedia=CMPXMedia::NewL(supportedIds.Array());
       
  1753     iBrowsePath = CMPXCollectionPath::NewL();
       
  1754     CleanupStack::PopAndDestroy(&supportedIds);
       
  1755 
       
  1756     iEngine.ListPluginsL(*iMedia, iUids.Array());
       
  1757     if (iPluginUids[EContextBrowse]!=KNullUid )
       
  1758         {
       
  1759         MPX_DEBUG1("CMPXCollectionClientContext::InitL() Collection changed");
       
  1760         iClientList->SendMsgL(
       
  1761             TMPXCollectionMessage(TMPXCollectionMessage::ECollectionChanged,0,0));
       
  1762         }
       
  1763 
       
  1764     // sets the browse plugin to NULL
       
  1765     SetPlugin(EContextBrowse, NULL);
       
  1766 
       
  1767     // Update collection path, and buffer, send path update msg,
       
  1768     // complete request
       
  1769     TRAPD(err, DoHandleOpenL(iMedia, NULL, aCallback, KErrNone, ETrue, ETrue));
       
  1770     if (err)
       
  1771         {
       
  1772         MPX_DEBUG2("CMPXCollectionClientContext::InitL() Complete Open %i", err);
       
  1773         aCallback->HandleOpen(iMedia, // Not used
       
  1774                               iIndex,
       
  1775                               ETrue, err);
       
  1776         }
       
  1777     MPX_DEBUG1("CMPXCollectionClientContext::InitL() --->");
       
  1778     }
       
  1779 
       
  1780 // ----------------------------------------------------------------------------
       
  1781 // Execute a async task
       
  1782 // ----------------------------------------------------------------------------
       
  1783 //
       
  1784 void CMPXCollectionClientContext::ExecuteTaskL(
       
  1785     TInt aTask,
       
  1786     TInt aParamData,
       
  1787     TAny* aPtrData,
       
  1788     TAny* aCallback,
       
  1789     const CBufBase& aBuf,
       
  1790     CBase* aCObject1,
       
  1791     CBase* aCObject2,
       
  1792     CMPXCollectionPlugin*& aPlugin)
       
  1793     {
       
  1794     MPX_DEBUG4("CMPXCollectionClientContext::ExecuteTaskL 0x%08x, task %d, aParam %d",
       
  1795                this, aTask, aParamData);
       
  1796     switch (aTask)
       
  1797         {
       
  1798         case EMcsOpen:
       
  1799             {
       
  1800             aPlugin = LoadedPlugin(EContextBrowse);
       
  1801             aPlugin->SetObserver(*this);
       
  1802             aPlugin->SetCallback(
       
  1803                     reinterpret_cast<MMPXCollectionEngineObserver*>(aCallback));
       
  1804             OpenL();
       
  1805             break;
       
  1806             }
       
  1807         case EMcsOpenPath:
       
  1808             {
       
  1809             // Set plugin first for handling error
       
  1810             TUid oldUid = iPluginUids[EContextBrowse];
       
  1811             aPlugin = reinterpret_cast<CMPXCollectionPlugin*>(aPtrData);
       
  1812             // Set plugin and task pointer for browse context
       
  1813             SetPlugin(EContextBrowse, aPlugin);
       
  1814             iPathUpdated = EFalse;
       
  1815             aPlugin->SetObserver(*this);
       
  1816             aPlugin->SetCallback(
       
  1817                     reinterpret_cast<MMPXCollectionEngineObserver*>(aCallback));
       
  1818             CMPXCollectionPath* path = static_cast<CMPXCollectionPath*>(aCObject1);
       
  1819             delete iBrowsePath;
       
  1820             iBrowsePath = NULL;
       
  1821             iBrowsePath = CMPXCollectionPath::NewL(*path);
       
  1822             SetPathOpenMode(*iBrowsePath, static_cast<TMPXOpenMode>(aParamData));
       
  1823 
       
  1824             // If the browsing plugin is changing, need to broadcast the
       
  1825             // collection changed message
       
  1826             if (iPluginUids[EContextBrowse] != oldUid)
       
  1827                 {
       
  1828                 // no leave before plugin API OpenL
       
  1829                 TRAP_IGNORE(iClientList->SendMsgL(
       
  1830                     TMPXCollectionMessage(
       
  1831                          TMPXCollectionMessage::ECollectionChanged,0,iPluginUids[EContextBrowse].iUid)));
       
  1832                 }
       
  1833             iIndex=0;
       
  1834             iFocusItemId = KMPXInvalidItemId;
       
  1835             DoPluginOpenL();
       
  1836             break;
       
  1837             }
       
  1838         case EMcsOpenIndex:
       
  1839             {
       
  1840             // Internalize mode
       
  1841             TInt mode = (TInt)aPtrData;
       
  1842             aPlugin = LoadedPlugin(EContextBrowse);
       
  1843             aPlugin->SetObserver(*this);
       
  1844             aPlugin->SetCallback(
       
  1845                     reinterpret_cast<MMPXCollectionEngineObserver*>(aCallback));
       
  1846             iBrowsePath->Set(aParamData);
       
  1847             SetPathOpenMode(*iBrowsePath,static_cast<TMPXOpenMode>(mode));
       
  1848             iIndex=0;
       
  1849             iFocusItemId = KMPXInvalidItemId;
       
  1850             DoPluginOpenL();
       
  1851             break;
       
  1852             }
       
  1853         case EMcsBack:
       
  1854             {
       
  1855             aPlugin = LoadedPlugin(EContextBrowse);
       
  1856             aPlugin->SetObserver(*this);
       
  1857             aPlugin->SetCallback(
       
  1858                     reinterpret_cast<MMPXCollectionEngineObserver*>(aCallback));
       
  1859             BackL();
       
  1860             break;
       
  1861             }
       
  1862         case EMcsMediaByPath:
       
  1863             {
       
  1864             // Setup plugin first for handle error
       
  1865             aPlugin = reinterpret_cast<CMPXCollectionPlugin*>(aPtrData);
       
  1866             SetPlugin(EContextMedia, aPlugin);
       
  1867 
       
  1868             aPlugin->SetObserver(*this);
       
  1869             aPlugin->SetCallback(
       
  1870                         static_cast<MMPXCollectionEngineObserver*>(aCallback));
       
  1871             // Media path
       
  1872             CMPXCommand* cmd = reinterpret_cast<CMPXCommand*>(aCObject1);
       
  1873             MPX_ASSERT(cmd->IsSupported(KMPXCommandGeneralTargetIds));
       
  1874             MPX_ASSERT(cmd->IsSupported(KMPXCommandMediaAttributeSpecs));
       
  1875             CMPXCollectionPath* path = reinterpret_cast<CMPXCollectionPath*>(aCObject2);
       
  1876             CMPXAttributeSpecs* specs =
       
  1877                 cmd->Value<CMPXAttributeSpecs>(KMPXCommandMediaAttributeSpecs);
       
  1878             User::LeaveIfNull(specs);
       
  1879             CMPXAttributeSpecs* filter =
       
  1880                 cmd->Value<CMPXAttributeSpecs>(KMPXCommandMediaFilter);
       
  1881             User::LeaveIfNull(filter);
       
  1882             TCapabilitySet caps = cmd->ValueTObjectL<TCapabilitySet>(KMPXCommandMediaCapbilitySet);
       
  1883             // Ask plugin for media
       
  1884             DoPluginMediaL( *path, caps, *specs, *filter );
       
  1885             break;
       
  1886             }
       
  1887         case EMcsRemovePath:
       
  1888             {
       
  1889             aPlugin = reinterpret_cast<CMPXCollectionPlugin*>(aPtrData);
       
  1890             // set the remove plugin
       
  1891             SetPlugin(EContextRemove, aPlugin);
       
  1892 
       
  1893             aPlugin->SetObserver(*this);
       
  1894             CMPXCollectionPath* path =
       
  1895                 reinterpret_cast<CMPXCollectionPath*>(aCObject1);
       
  1896             aPlugin->SetCallback(
       
  1897                     reinterpret_cast<MMPXCollectionEngineObserver*>(aCallback));
       
  1898             aPlugin->RemoveL( *path );
       
  1899             break;
       
  1900             }
       
  1901         case EMcsFindAll:
       
  1902             {
       
  1903             aPlugin = reinterpret_cast<CMPXCollectionPlugin*>(aPtrData);
       
  1904             // set the media plugin
       
  1905             SetPlugin(EContextMedia, aPlugin);
       
  1906 
       
  1907             aPlugin->SetCallback(
       
  1908                     reinterpret_cast<MMPXCollectionEngineObserver*>(aCallback));
       
  1909             CMPXMedia* media = static_cast<CMPXMedia*>(aCObject1);
       
  1910             FindAllL(*media, aBuf, *aPlugin);
       
  1911             break;
       
  1912             }
       
  1913         case EMcsCommand:
       
  1914             {
       
  1915             TMPXCollectionCommand cmd =
       
  1916                 static_cast<TMPXCollectionCommand>( aParamData );
       
  1917             switch( cmd )
       
  1918                 {
       
  1919                 case EMcCmdCollectionInit:
       
  1920                 case EMcCmdCollectionResyn:
       
  1921                     // Decrement the old plugin reference count
       
  1922                     aPlugin = reinterpret_cast<CMPXCollectionPlugin*>(aPtrData);
       
  1923                     SetPlugin(EContextMedia, aPlugin);
       
  1924 
       
  1925                     if( aPlugin )
       
  1926                         {
       
  1927                         aPlugin->SetObserver(*this);
       
  1928                         aPlugin->CommandL( cmd );
       
  1929                         aPlugin->SetObserver(iEngine);
       
  1930                         aPlugin->CompleteTask();
       
  1931                         }
       
  1932                     break;
       
  1933                 default:
       
  1934                     MPX_ASSERT(0);
       
  1935                     break;
       
  1936                 }
       
  1937             break;
       
  1938             }
       
  1939         case EMcsCommandExt:
       
  1940             {
       
  1941             CMPXCommand* cmd = reinterpret_cast<CMPXCommand*>(aCObject1);
       
  1942             aPlugin = reinterpret_cast<CMPXCollectionPlugin*>(aPtrData);
       
  1943             MMPXCollectionEngineObserver* callback =
       
  1944                              reinterpret_cast<MMPXCollectionEngineObserver*>(aCallback);
       
  1945             if( cmd->IsSupported( KMPXCommandGeneralId) )
       
  1946                 {
       
  1947                 TMPXCommandId commandId = cmd->ValueTObjectL<TMPXCommandId>(KMPXCommandGeneralId);
       
  1948                 // Decrement the old plugin reference count
       
  1949                 SetPlugin(EContextMedia, aPlugin);
       
  1950                 aPlugin->SetCallback( callback );
       
  1951 
       
  1952                 if( commandId == KMPXCommandIdCollectionSelect )
       
  1953                     {
       
  1954                     // Decrement the old plugin reference count
       
  1955                     //
       
  1956                     DoHandleSelectCommandL( *cmd );
       
  1957                     aPlugin->SetCallback( NULL );
       
  1958                     aPlugin->CompleteTask();
       
  1959                     callback->HandleCommandComplete( NULL, KErrNone );
       
  1960                     }
       
  1961                 else
       
  1962                     {
       
  1963                     aPlugin->SetObserver(*this);
       
  1964                     aPlugin->CommandL(*cmd);
       
  1965                     }
       
  1966                 }
       
  1967             else
       
  1968                 {
       
  1969                 aPlugin->CompleteTask();
       
  1970                 callback->HandleCommandComplete( NULL, KErrArgument );  // return error message
       
  1971                 }
       
  1972             break;
       
  1973             }
       
  1974         default:
       
  1975             break;
       
  1976         }
       
  1977     }
       
  1978 
       
  1979 // ----------------------------------------------------------------------------
       
  1980 // Error happens upon request
       
  1981 // ----------------------------------------------------------------------------
       
  1982 //
       
  1983 void CMPXCollectionClientContext::HandleError(
       
  1984     CMPXCollectionPlugin& aPlugin,
       
  1985     TInt aError,
       
  1986     TBool aUnusePlugin/*=EFalse*/)
       
  1987     {
       
  1988     TInt task(aPlugin.Task());
       
  1989     MPX_DEBUG3("CMPXCollectionClientContext::HandleError %d, task %d",
       
  1990               aError, task);
       
  1991     switch (task)
       
  1992         {
       
  1993         case EMcsOpen:
       
  1994         case EMcsOpenPath:
       
  1995         case EMcsBack:
       
  1996         case EMcsOpenIndex:
       
  1997             aPlugin.Callback()->HandleOpen(iMedia, // Not used
       
  1998                                            iIndex,
       
  1999                                            ETrue, aError);
       
  2000             aPlugin.CompleteTask();
       
  2001             aPlugin.SetCallback(NULL); // Reset current observer
       
  2002             aPlugin.SetObserver(iEngine);
       
  2003             break;
       
  2004         case EMcsMediaByPath:
       
  2005             aPlugin.Callback()->HandleMedia(iMedia, aError);
       
  2006             aPlugin.CompleteTask();
       
  2007             aPlugin.SetCallback(NULL); // Reset current observer
       
  2008             aPlugin.SetObserver(iEngine);
       
  2009             break;
       
  2010         case EMcsCommandExt:
       
  2011             aPlugin.Callback()->HandleCommandComplete(iMedia, aError);
       
  2012             aPlugin.CompleteTask();
       
  2013             aPlugin.SetCallback(NULL); // Reset current observer
       
  2014             aPlugin.SetObserver(iEngine);
       
  2015             break;
       
  2016         case EMcsRemovePath:
       
  2017             {
       
  2018             CDesCArray* dummy(NULL); // object will not be dereferenced in callback
       
  2019             aPlugin.Callback()->HandleRemove(*dummy, aError);
       
  2020             aPlugin.SetCallback(NULL); // Reset current observer
       
  2021             aPlugin.SetObserver(iEngine);
       
  2022             aPlugin.CompleteTask();
       
  2023             }
       
  2024             break;
       
  2025         case EMcsFindAll:
       
  2026             aPlugin.Callback()->HandleFindAll(iMedia, aError);
       
  2027             aPlugin.SetCallback(NULL); // Reset current observer
       
  2028             aPlugin.SetObserver(iEngine);
       
  2029             aPlugin.CompleteTask();
       
  2030             break;
       
  2031         case EMcsCommand:
       
  2032             {
       
  2033             // At least complete the task to not jam up the task queue
       
  2034             aPlugin.SetCallback(NULL); // Reset current observer
       
  2035             aPlugin.SetObserver(iEngine);
       
  2036             aPlugin.CompleteTask();
       
  2037             break;
       
  2038             }
       
  2039         default:
       
  2040             break;
       
  2041         }
       
  2042     if (aUnusePlugin)
       
  2043         {
       
  2044         iEngine.ReleasePlugin(aPlugin.Uid());
       
  2045         }
       
  2046     MPX_DEBUG1("<--CMPXCollectionClientContext::HandleError");
       
  2047     }
       
  2048 
       
  2049 // ----------------------------------------------------------------------------
       
  2050 // Error happens upon request
       
  2051 // ----------------------------------------------------------------------------
       
  2052 //
       
  2053 void CMPXCollectionClientContext::ResolvePluginL(
       
  2054     const CMPXCollectionPath& aPath,
       
  2055     TUid& aUid)
       
  2056     {
       
  2057     CMPXCollectionPlugin* p= iEngine.LoadedPlugin(aUid); // Save old plugin
       
  2058     // Resolve new plugin
       
  2059     CMPXCollectionPlugin* plugin=iEngine.ResolvePluginL(aPath);
       
  2060     // Update with new Uid
       
  2061     aUid = plugin->Uid();
       
  2062     if (p != plugin && &aPath == iBrowsePath)
       
  2063         {
       
  2064         // browsing plugin changed
       
  2065         iClientList->SendMsgL(TMPXCollectionMessage(
       
  2066                  TMPXCollectionMessage::ECollectionChanged,0,aUid.iUid));
       
  2067         }
       
  2068 
       
  2069     if (p)
       
  2070         {
       
  2071         // Make sure we decrement the reference count for the old plugin
       
  2072         iEngine.ReleasePlugin(p->Uid());
       
  2073         }
       
  2074     }
       
  2075 
       
  2076 // ----------------------------------------------------------------------------
       
  2077 // resolve plugin for FindAllL
       
  2078 // ----------------------------------------------------------------------------
       
  2079 //
       
  2080 void CMPXCollectionClientContext::ResolvePluginL(
       
  2081     const CMPXMedia& aMedia,
       
  2082     CMPXCollectionPlugin*& aPlugin)
       
  2083     {
       
  2084     // We have to be finding from the same context as browse
       
  2085     // if we are from MPX UI
       
  2086     //
       
  2087     if (iPluginUids[EContextBrowse]!=KNullUid)
       
  2088         {
       
  2089         aPlugin = LoadedPlugin(EContextBrowse);
       
  2090 
       
  2091         // Increment the reference count manually
       
  2092         iEngine.UsePlugin(aPlugin->Uid());
       
  2093         }
       
  2094     else // browse context does not exist
       
  2095         {
       
  2096         if (aMedia.IsSupported(KMPXMediaGeneralCollectionId))
       
  2097             {
       
  2098             TUid col = aMedia.ValueTObjectL<TUid>(KMPXMediaGeneralCollectionId);
       
  2099 
       
  2100             // Increment the plugin reference count
       
  2101             aPlugin = iEngine.ResolvePluginL(col);
       
  2102             }
       
  2103         else if (aMedia.IsSupported(KMPXMediaGeneralUri))
       
  2104             {
       
  2105             const TDesC& uri = aMedia.ValueText(KMPXMediaGeneralUri);
       
  2106 
       
  2107             // Increment the plugin reference count
       
  2108             aPlugin = iEngine.ResolvePluginL(uri);
       
  2109             }
       
  2110         else
       
  2111             {
       
  2112             // Unable to find a collection plugin
       
  2113             User::Leave(KErrNotSupported);
       
  2114             }
       
  2115         }
       
  2116     }
       
  2117 
       
  2118 // ----------------------------------------------------------------------------
       
  2119 // CMPXCollectionClientContext::SetPlugin
       
  2120 // ----------------------------------------------------------------------------
       
  2121 //
       
  2122 void CMPXCollectionClientContext::SetPlugin(
       
  2123     TContextType aType,
       
  2124     CMPXCollectionPlugin* aPlugin)
       
  2125     {
       
  2126     if (iPluginUids[aType]!=KNullUid)
       
  2127         {
       
  2128         iEngine.ReleasePlugin(iPluginUids[aType]);
       
  2129         }
       
  2130     if (aPlugin)
       
  2131         {
       
  2132         iPluginUids[aType] = aPlugin->Uid();
       
  2133         }
       
  2134     else
       
  2135         {
       
  2136         iPluginUids[aType] = KNullUid;
       
  2137         }
       
  2138     }
       
  2139 
       
  2140 // ----------------------------------------------------------------------------
       
  2141 // Add a media object to the collection
       
  2142 // ----------------------------------------------------------------------------
       
  2143 //
       
  2144 void CMPXCollectionClientContext::DoUpdateMediaL( TInt aOp, const CMPXMedia& aMedia )
       
  2145     {
       
  2146     // Media object can be a single "item" or a list of "items"
       
  2147     //
       
  2148     TMPXGeneralType type = EMPXNoType;
       
  2149     if (aMedia.IsSupported(KMPXMediaGeneralType))
       
  2150         {
       
  2151         type = aMedia.ValueTObjectL<TMPXGeneralType>(KMPXMediaGeneralType);
       
  2152         }
       
  2153     else
       
  2154         {
       
  2155         User::Leave(KErrArgument);
       
  2156         }
       
  2157 
       
  2158     if ( type == EMPXGroup )
       
  2159         {
       
  2160         // Group has to have a "container"
       
  2161         MPX_ASSERT(aMedia.IsSupported(KMPXMediaArrayContents));
       
  2162         const CMPXMediaArray* array =
       
  2163                         aMedia.Value<CMPXMediaArray>(KMPXMediaArrayContents);
       
  2164         User::LeaveIfNull(const_cast<CMPXMediaArray*>(array));
       
  2165         TInt count = array->Count();
       
  2166         for( TInt i=0; i<count; ++i )
       
  2167             {
       
  2168             DoUpdateMediaL( aOp, *(array->AtL(i)) );
       
  2169             }
       
  2170         }
       
  2171     else if ( type == EMPXItem )
       
  2172         {
       
  2173         DoHandleItemL( aOp, aMedia );
       
  2174         }
       
  2175     else
       
  2176         {
       
  2177         // How do we handle "group" artists? 
       
  2178         User::Leave( KErrNotSupported );
       
  2179         }
       
  2180     }
       
  2181 
       
  2182 // ----------------------------------------------------------------------------
       
  2183 // Add the media object to the correct plugin
       
  2184 // ----------------------------------------------------------------------------
       
  2185 //
       
  2186 void CMPXCollectionClientContext::DoHandleItemL( TInt aOp, const CMPXMedia& aMedia)
       
  2187     {
       
  2188     MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL <---");
       
  2189 
       
  2190     // Find the correct plugin.
       
  2191     // The code below increments the plugin reference count
       
  2192     CMPXCollectionPlugin* plugin(NULL);
       
  2193     if (aMedia.IsSupported(KMPXMediaGeneralCollectionId))
       
  2194         {
       
  2195         const TUid& uid = aMedia.ValueTObjectL<TUid>(KMPXMediaGeneralCollectionId);
       
  2196         MPX_DEBUG2("CMPXCollectionClientContext::DoHandleItemL Collection %i", uid.iUid);
       
  2197 
       
  2198         // Increment the plugin reference count
       
  2199         plugin = iEngine.ResolvePluginL( uid );
       
  2200         }
       
  2201     else if (aMedia.IsSupported(KMPXMediaGeneralUri))
       
  2202         {
       
  2203         const TDesC& uri = aMedia.ValueText(KMPXMediaGeneralUri);
       
  2204         MPX_DEBUG2("CMPXCollectionClientContext::DoHandleItemL Collection %S", &uri);
       
  2205 
       
  2206         // Increment the plugin reference count
       
  2207         plugin = iEngine.ResolvePluginL( uri );
       
  2208         }
       
  2209     else
       
  2210         {
       
  2211         MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Cannot resolve a plugin");
       
  2212         User::Leave(KErrNotSupported);
       
  2213         }
       
  2214 
       
  2215     if( !plugin )
       
  2216         {
       
  2217         MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Cannot resolve a plugin");
       
  2218         User::Leave(KErrNotSupported);
       
  2219         }
       
  2220 
       
  2221     iEngine.CleanupPluginPushL(plugin);
       
  2222 
       
  2223     switch( aOp )
       
  2224         {
       
  2225         case EMcsAddItem:
       
  2226             {
       
  2227             MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Add");
       
  2228 
       
  2229             plugin->SetObserver(*this);
       
  2230             plugin->AddL( aMedia );
       
  2231             plugin->SetObserver(iEngine);
       
  2232             break;
       
  2233             }
       
  2234         case EMcsRemoveItem:
       
  2235             {
       
  2236             MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Remove");
       
  2237             plugin->SetObserver(*this);
       
  2238             plugin->RemoveL( aMedia );
       
  2239             plugin->SetObserver(iEngine);
       
  2240             break;
       
  2241             }
       
  2242         case EMcsSetMedia:
       
  2243             {
       
  2244             MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL Set");
       
  2245             plugin->SetObserver(*this);
       
  2246             plugin->SetL( aMedia );
       
  2247             plugin->SetObserver(iEngine);
       
  2248             break;
       
  2249             }
       
  2250         default:
       
  2251             {
       
  2252             User::Leave(KErrNotSupported);
       
  2253             break;
       
  2254             }
       
  2255         }  // switch
       
  2256 
       
  2257     CleanupStack::PopAndDestroy();    // plugin
       
  2258 
       
  2259     MPX_DEBUG1("CMPXCollectionClientContext::DoHandleItemL --->");
       
  2260     }
       
  2261 
       
  2262 // ----------------------------------------------------------------------------
       
  2263 // Handle a synchorouns command to the collection
       
  2264 // ----------------------------------------------------------------------------
       
  2265 //
       
  2266 void CMPXCollectionClientContext::DoHandleSyncCommandL(
       
  2267     const CMPXCommand& aCmd,
       
  2268     const CMPXMessageQueue& aMsgQueue,
       
  2269     CMPXCollectionPlugin* aPlugin/*=NULL*/)
       
  2270     {
       
  2271     // Only process the command if the command id has been defined,
       
  2272     // otherwise leave with KErrArgument
       
  2273     if (aCmd.IsSupported(KMPXCommandGeneralId))
       
  2274         {
       
  2275         TMPXCommandId commandId = aCmd.ValueTObjectL<TMPXCommandId>(KMPXCommandGeneralId);
       
  2276         switch( commandId )
       
  2277             {
       
  2278             case KMPXCommandIdCollectionSelect:
       
  2279                 {
       
  2280                 DoHandleSelectCommandL( aCmd );
       
  2281                 break;
       
  2282                 }
       
  2283 
       
  2284             case KMPXCommandSubscriptionAdd:
       
  2285                 {
       
  2286                 TInt index( iClientList->Find( aMsgQueue ));
       
  2287                 CMPXMediaArray* items(
       
  2288                     aCmd.Value<CMPXMediaArray>( KMPXCommandSubscriptionAddItems ));
       
  2289                 User::LeaveIfNull(items);
       
  2290                 CMPXSubscription* subscription( CMPXSubscription::NewL( *items ));
       
  2291                  CleanupStack::PushL(subscription);
       
  2292                  iClientList->AddSubscriptionL( index, subscription );   // ownership transferred
       
  2293                  CleanupStack::Pop(subscription);
       
  2294                 break;
       
  2295                 }
       
  2296             case KMPXCommandSubscriptionRemove:
       
  2297                 {
       
  2298                 TInt index( iClientList->Find( aMsgQueue ));
       
  2299                 CMPXMediaArray* items(
       
  2300                     aCmd.Value<CMPXMediaArray>( KMPXCommandSubscriptionAddItems ));
       
  2301                 User::LeaveIfNull(items);
       
  2302                 CMPXSubscription* subscription( CMPXSubscription::NewL( *items ));
       
  2303                  CleanupStack::PushL(subscription);
       
  2304                  iClientList->RemoveSubscriptionL( index, *subscription );
       
  2305                  CleanupStack::PopAndDestroy(subscription);
       
  2306                 break;
       
  2307                 }
       
  2308             case KMPXCommandSubscriptionRemoveAll:
       
  2309                 {
       
  2310                 TInt index( iClientList->Find( aMsgQueue ));
       
  2311                  iClientList->RemoveAllSubscriptionsL( index );
       
  2312                 break;
       
  2313                 }
       
  2314                 
       
  2315            case KMPXCommandIdCollectionPrepareDelete:
       
  2316                 {
       
  2317                 if (aCmd.IsSupported (KMPXCommandCollectionPrepareRemovePath))
       
  2318                     {
       
  2319                     CMPXCollectionPath
       
  2320                             * path = aCmd.ValueCObjectL<CMPXCollectionPath> (KMPXCommandCollectionPrepareRemovePath);
       
  2321                     CleanupStack::PushL(path);
       
  2322                     iEngine.ResetCacheL(*path);
       
  2323                     CleanupStack::PopAndDestroy(path);
       
  2324                     }
       
  2325                 break;
       
  2326                 }
       
  2327 
       
  2328             default:
       
  2329                 {
       
  2330                 MPX_ASSERT(aPlugin);
       
  2331                 aPlugin->SetObserver(*this);
       
  2332                 TRAPD( err, aPlugin->CommandL( const_cast<CMPXCommand&>(aCmd) ) );
       
  2333                 aPlugin->SetObserver(iEngine);
       
  2334                 User::LeaveIfError( err );
       
  2335                 break;
       
  2336                 }
       
  2337             }
       
  2338         }
       
  2339     else
       
  2340         {
       
  2341         User::Leave(KErrArgument);
       
  2342         }
       
  2343     }
       
  2344 
       
  2345 // ----------------------------------------------------------------------------
       
  2346 // CMPXCollectionClientContext::DoHandleSelectCommandL
       
  2347 // ----------------------------------------------------------------------------
       
  2348 //
       
  2349 void CMPXCollectionClientContext::DoHandleSelectCommandL(const CMPXCommand& aCmd)
       
  2350     {
       
  2351     TInt index(iIndex);
       
  2352 
       
  2353     // Selecting a new index
       
  2354     if( aCmd.IsSupported(KMPXCommandCollectionSelectIndex) )
       
  2355         {
       
  2356         index = aCmd.ValueTObjectL<TInt>(KMPXCommandCollectionSelectIndex);
       
  2357         if (iBrowsePath->Levels()<=0)
       
  2358             {
       
  2359             User::Leave(KErrNotReady);
       
  2360             }
       
  2361         if (index<0 || index>=iBrowsePath->Count())
       
  2362             {
       
  2363             User::Leave(KErrArgument);
       
  2364             }
       
  2365         iBrowsePath->Set(index);
       
  2366         }
       
  2367     // Re-select the current index
       
  2368     else
       
  2369         {
       
  2370         TInt count = iBrowsePath->Count();
       
  2371 
       
  2372         if( iFocusItemId != KMPXInvalidItemId )
       
  2373             {
       
  2374             TInt index = iBrowsePath->IndexOfId(iFocusItemId);
       
  2375             if (KErrNotFound != index)
       
  2376                 {
       
  2377                 iBrowsePath->Set(index);
       
  2378                 }
       
  2379             else if( count > 0 ) // Focus item has been deleted, select next
       
  2380                 {
       
  2381                 // Bounds check for largest and smallest
       
  2382                 if( iIndex >= count )
       
  2383                     {
       
  2384                     iIndex = count-1;
       
  2385                     }
       
  2386                 if( iIndex < 0 )
       
  2387                     {
       
  2388                     iIndex = 0;
       
  2389                     }
       
  2390                 iBrowsePath->Set(iIndex);
       
  2391                 iFocusItemId = iBrowsePath->Id();
       
  2392                 }
       
  2393             iIndex = iBrowsePath->Index();
       
  2394             }
       
  2395         else
       
  2396             {
       
  2397             // Bounds checking for iIndex
       
  2398             if( iIndex >= count && iIndex > 0 )
       
  2399                 {
       
  2400                 iIndex = count-1;
       
  2401 
       
  2402                 // Just in case if ids has 0 items
       
  2403                 if( iIndex > 0 && iIndex < count )
       
  2404                     {
       
  2405                     iFocusItemId = iBrowsePath->IdOfIndex(iIndex);
       
  2406                     }
       
  2407                 }
       
  2408 
       
  2409             if (iBrowsePath->Levels()>0 && iIndex>=0 &&
       
  2410                 iIndex<iBrowsePath->Count())
       
  2411                 {
       
  2412                 iBrowsePath->Set(iIndex);
       
  2413                 }
       
  2414             iFocusItemId = iBrowsePath->Id();
       
  2415             }
       
  2416         }
       
  2417     iClientList->SendMsgL(
       
  2418           TMPXCollectionMessage(TMPXCollectionMessage::EFocusChanged,
       
  2419                                 index, index));
       
  2420     iIndex = index; // iIndex will always be up to date
       
  2421     iFocusItemId = iBrowsePath->Id();
       
  2422     }
       
  2423 
       
  2424 // ----------------------------------------------------------------------------
       
  2425 // CMPXCollectionClientContext::DoPluginOpenL
       
  2426 // ----------------------------------------------------------------------------
       
  2427 //
       
  2428 void CMPXCollectionClientContext::DoPluginOpenL()
       
  2429     {
       
  2430     MPX_FUNC("CMPXCollectionClientContext::DoPluginOpenL()");
       
  2431     TBool callOpen(ETrue);
       
  2432     MPX_ASSERT(iPluginUids[EContextBrowse]!=KNullUid);
       
  2433     TBool pluginCacheable(EFalse);
       
  2434     if( iBrowsePath )
       
  2435         {
       
  2436         TMPXItemId id(iBrowsePath->Id(CMPXCollectionPath::ECollectionUid) );
       
  2437         pluginCacheable = iEngine.PluginCacheable( TUid::Uid( id ) );
       
  2438         }
       
  2439 
       
  2440     // Check for open playlist only mode.  If in that mode, do not return the media
       
  2441     // from the cache but call the plugin to open, as that will callback a
       
  2442     // different HandleOpenL() with the collection path instead.
       
  2443     TMPXOpenMode mode( iBrowsePath->OpenNextMode() );
       
  2444     CMPXCollectionPlugin* plugin = LoadedPlugin(EContextBrowse);
       
  2445     if ( !iFilter && mode != EMPXOpenPlaylistOnly )
       
  2446         {
       
  2447         // try to get the results from the cache only if the plugin is cacheable
       
  2448         if ( pluginCacheable )
       
  2449             {
       
  2450             CMPXMedia* results( iCache.GetL( *iBrowsePath,
       
  2451                                              iBrowsePath->OpenAttributes(),
       
  2452                                              ETrue ));
       
  2453             if (results)
       
  2454                 {
       
  2455                 MPX_DEBUG1("CMPXCollectionClientContext::DoPluginOpenL(): Results found in cache");
       
  2456                 MMPXCollectionEngineObserver* callback = plugin->Callback();
       
  2457                 plugin->CompleteTask();
       
  2458                 TRAPD(err, DoHandleOpenL(results, NULL, callback, KErrNone, EFalse, ETrue));
       
  2459                 if (err)
       
  2460                     {
       
  2461                     HandleError(*plugin, err);
       
  2462                     }
       
  2463 
       
  2464                 callOpen = EFalse;
       
  2465                 }
       
  2466             }
       
  2467         }
       
  2468 
       
  2469     if (callOpen)
       
  2470         {
       
  2471         if ( pluginCacheable )
       
  2472             {
       
  2473             iCacheMedia = AttributesCacheableL( iBrowsePath->OpenAttributes(), *iBrowsePath );
       
  2474             }
       
  2475         plugin->OpenL(*iBrowsePath, iBrowsePath->OpenAttributes(), iFilter);
       
  2476         }
       
  2477     }
       
  2478 
       
  2479 // ----------------------------------------------------------------------------
       
  2480 // CMPXCollectionClientContext::DoPluginMediaL
       
  2481 // ----------------------------------------------------------------------------
       
  2482 //
       
  2483 void CMPXCollectionClientContext::DoPluginMediaL(
       
  2484     CMPXCollectionPath& aPath,
       
  2485     const TCapabilitySet& aCaps,
       
  2486     CMPXAttributeSpecs& aSpecs,
       
  2487     CMPXFilter& aFilter)
       
  2488     {
       
  2489     MPX_FUNC("CMPXCollectionClientContext::DoPluginMediaL()");
       
  2490     TBool callMedia(ETrue);
       
  2491     delete iMediaPath;
       
  2492     iMediaPath = NULL;
       
  2493 
       
  2494     TMPXItemId id(aPath.Id(CMPXCollectionPath::ECollectionUid) );
       
  2495     TBool pluginCacheable( iEngine.PluginCacheable( TUid::Uid( id ) ));
       
  2496 
       
  2497     // try to get the results from the cache only if
       
  2498     // the plugin is cacheable
       
  2499     CMPXMedia* results( NULL );
       
  2500     if ( pluginCacheable )
       
  2501         {
       
  2502         results = iCache.GetL( aPath, aPath.OpenAttributes() );
       
  2503 
       
  2504         if (results)
       
  2505             {
       
  2506             // Check if the attribute specs match
       
  2507             if ( aSpecs.Count() > 0 )
       
  2508                 {
       
  2509                 /*
       
  2510                 // need to check if requested attribute specs
       
  2511                 // match what we have cached
       
  2512                 if ( results->IsSupported( KMPXCommandMediaAttributeSpecs ))
       
  2513                     {
       
  2514                     CMPXAttributeSpecs* specs( results->Value<CMPXAttributeSpecs>(
       
  2515                                                 KMPXCommandMediaAttributeSpecs ));
       
  2516                     User::LeaveIfNull(specs);
       
  2517                     if ( *specs == *aSpecs )
       
  2518                         {
       
  2519                         callMedia = EFalse;
       
  2520                         }
       
  2521                     }
       
  2522                 */
       
  2523                 }
       
  2524             else
       
  2525                 {
       
  2526                 // Else client did not specify attribute specs, so we can return
       
  2527                 // the match
       
  2528                 callMedia = EFalse;
       
  2529                 }
       
  2530             }
       
  2531         }
       
  2532 
       
  2533     if ( callMedia )
       
  2534         {
       
  2535         iMediaPath = CMPXCollectionPath::NewL( aPath );
       
  2536 
       
  2537         if ( pluginCacheable )
       
  2538             {
       
  2539             iCacheMedia = AttributesCacheableL( aPath.OpenAttributes(), aPath );
       
  2540             }
       
  2541         LoadedPlugin(EContextMedia)->MediaL( aPath,
       
  2542                                              aPath.OpenAttributes(),
       
  2543                                              aCaps,
       
  2544                                              &aSpecs,
       
  2545                                              &aFilter);
       
  2546         }
       
  2547     else
       
  2548         {
       
  2549         HandleMedia( results, KErrNone );
       
  2550         }
       
  2551     }
       
  2552 
       
  2553 
       
  2554 // ----------------------------------------------------------------------------
       
  2555 // CMPXCollectionClientContext::AttributesCacheableL
       
  2556 // ----------------------------------------------------------------------------
       
  2557 //
       
  2558 TBool CMPXCollectionClientContext::AttributesCacheableL(
       
  2559     const TArray<TMPXAttribute>& aAttrs,
       
  2560     const CMPXCollectionPath& aPath )
       
  2561     {
       
  2562     MPX_DEBUG1("-->CMPXCollectionClientContext::AttributesCacheableL");
       
  2563 
       
  2564     TMPXItemId id( aPath.Id( CMPXCollectionPath::ECollectionUid ));
       
  2565     const TArray<TUid>& nonCacheAttrs( iEngine.PluginNonCacheableAttributesL( TUid::Uid( id )));
       
  2566 
       
  2567     TBool found( EFalse );
       
  2568     TInt nonCacheCount( nonCacheAttrs.Count() );
       
  2569     for ( TInt i = 0; i < nonCacheCount && !found; i++ )
       
  2570         {
       
  2571         TInt attrCount( aAttrs.Count() );
       
  2572         for ( TInt j = 0; j < attrCount && !found; j++ )
       
  2573             {
       
  2574             TMPXAttribute att( aAttrs[j] );
       
  2575             if ( nonCacheAttrs[i] == TUid::Uid( att.ContentId() ))
       
  2576                 {
       
  2577                 found = ETrue;
       
  2578                 }
       
  2579             }
       
  2580         }
       
  2581     MPX_DEBUG1("<--CMPXCollectionClientContext::AttributesCacheableL");
       
  2582     return !found;
       
  2583     }
       
  2584 
       
  2585 // ----------------------------------------------------------------------------
       
  2586 // CMPXCollectionClientContext::AddToCache
       
  2587 // ----------------------------------------------------------------------------
       
  2588 //
       
  2589 CMPXMedia* CMPXCollectionClientContext::AddToCache(
       
  2590     const CMPXCollectionPath& aPath,
       
  2591     const TArray<TMPXAttribute>& aAttrs,
       
  2592     CMPXMedia& aResults,
       
  2593     TBool aMediaFromOpenL,
       
  2594     CMPXCollectionCache::TCachePriority aPriority /* = EPriorityNormal */)
       
  2595     {
       
  2596     CMPXMedia* ret( &aResults );
       
  2597     TRAP_IGNORE(ret = iCache.AddL(aPath, aAttrs, aResults, aMediaFromOpenL, aPriority));
       
  2598     return ret;
       
  2599     }
       
  2600 
       
  2601 // ----------------------------------------------------------------------------
       
  2602 // CMPXCollectionClientContext::LoadedPlugin
       
  2603 // ----------------------------------------------------------------------------
       
  2604 //
       
  2605 CMPXCollectionPlugin* CMPXCollectionClientContext::LoadedPlugin(TContextType aType)
       
  2606     {
       
  2607     MPX_ASSERT(iPluginUids[aType]!=KNullUid);
       
  2608     CMPXCollectionPlugin* plugin(iEngine.LoadedPlugin(iPluginUids[aType]));
       
  2609     MPX_ASSERT(plugin);
       
  2610     return plugin;
       
  2611     }
       
  2612 
       
  2613 // End of file