mpx/collectionframework/collectionutility/src/mpxcollectionutilityimpl.cpp
changeset 0 a2952bb97e68
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpx/collectionframework/collectionutility/src/mpxcollectionutilityimpl.cpp	Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,1187 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Collection Utility implementation
+*
+*/
+
+
+#include <bamdesca.h>
+#include <s32mem.h>
+#include <e32math.h>
+#include <mpxmessagemonitor.h>
+#include <mpxmedia.h>
+#include <mpxcollectionobserver.h>
+#include <mpxcollectionmessage.h>
+#include <mpxmessagegeneraldefs.h>
+#include <mpxcmn.h>
+#include <mpxtaskqueue.h>
+#include <mpxcollectionpath.h>
+#include <mpxcollectionplaylist.h>
+#include <mpxcollectiontype.h>
+#include <mpxcommandgeneraldefs.h>
+#include <mpxcollectioncommanddefs.h>
+#include <mpxsubscription.h>
+#include <mpxlog.h>
+
+#include "mpxcollectionutilityimpl.h"
+
+// ============================== MEMBER FUNCTIONS ============================
+ 
+// ----------------------------------------------------------------------------
+// Two phase constructor
+// ----------------------------------------------------------------------------
+// 
+CMPXCollectionUtility* CMPXCollectionUtility::NewL(
+    const TUid& aModeId,
+    MMPXCollectionObserver* aObs)
+    {
+    CMPXCollectionUtility* p=new(ELeave)CMPXCollectionUtility(aObs);
+    CleanupStack::PushL(p);
+    p->ConstructL(aModeId);
+    CleanupStack::Pop(p);
+    return p;
+    }
+ 
+// ----------------------------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------------------------
+// 
+CMPXCollectionUtility::~CMPXCollectionUtility()
+    { 
+    Cancel();
+#ifdef _ENABLE_GUARD_TIMER
+    delete iGuardTimer;
+#endif
+    if (iTaskQueue)
+        {
+        delete iTaskQueue;
+        }
+ 
+    delete iCurrentEntries;
+ 
+    if (iMsgMonitor)
+        {
+        delete iMsgMonitor;
+        }
+
+    iMcs.Close();
+
+    delete iBuffer;
+    delete iArray;
+    delete iMedia;
+    delete iMediaOnError;
+    }
+
+// ----------------------------------------------------------------------------
+// C++ constructor
+// Create a unique name out of thread ID and this pointer: no other instance of
+// this object will have the same name; used to identify this object for
+// receiving messages 
+// ----------------------------------------------------------------------------
+// 
+CMPXCollectionUtility::CMPXCollectionUtility(MMPXCollectionObserver* aObs)
+:   CActive(EPriorityStandard),
+    iObserver(aObs),
+    iCallbackOngoing(EFalse)
+    { 
+    CActiveScheduler::Add(this); 
+    TThreadId threadId=RThread().Id(); // this thread id
+    } 
+ 
+// ----------------------------------------------------------------------------
+// 2nd phase constructor
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::ConstructL(const TUid& aModeId)
+    {
+    MPX_FUNC_EX("CMPXCollectionUtility::ConstructL");
+    iTaskQueue = CMPXTaskQueue::NewL();
+    User::LeaveIfError(
+        iMcs.Connect(KMPXCollectionServerName,
+                     KMPXCollectionServerImg,
+                     TVersion(KMPXCollectionServerMajorVersionNumber,
+                     KMPXCollectionServerMinorVersionNumber,
+                     KMPXCollectionServerBuildVersionNumber)));
+    iMcs.SendReceiveL(EMcsSetMode,TIpcArgs(aModeId.iUid)); 
+    iMsgMonitor = CMPXMessageMonitor::NewL(iMcs,*this);
+    iMediaOnError = CMPXMedia::NewL();
+#ifdef _ENABLE_GUARD_TIMER
+    iGuardTimer=CPeriodic::NewL(CActive::EPriorityStandard);
+#endif
+    }
+ 
+// ----------------------------------------------------------------------------
+// Return reference to collection
+// ----------------------------------------------------------------------------
+// 
+MMPXCollection& CMPXCollectionUtility::Collection()
+    {
+    return *this;
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieves the ID of the collection resolved based on selection criteria
+// ----------------------------------------------------------------------------
+// 
+TUid CMPXCollectionUtility::CollectionIDL(const TArray<TUid>& aUids)
+    {
+    // Buffer to transfer UIDs
+    //
+    CBufBase* buf=CBufFlat::NewL(KMPXBufGranularity);
+    CleanupStack::PushL( buf );
+
+    RBufWriteStream writeStream( *buf );
+    CleanupClosePushL( writeStream );
+    ::ExternalizeL(aUids, writeStream);
+    writeStream.CommitL();
+    buf->Compress();
+    CleanupStack::PopAndDestroy(&writeStream);
+ 
+    // IPC the data
+    //
+    TPtr8 des = buf->Ptr(0);
+    TPckgBuf<TUid> pkg;
+    iMcs.SendReceiveL( EMcsCollectionIdLookup, TIpcArgs(&des, &pkg) );
+    CleanupStack::PopAndDestroy( buf );
+ 
+    return pkg();
+    }
+ 
+// ----------------------------------------------------------------------------
+// CMPXCollectionUtility::AddSubscriptionL
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::AddSubscriptionL(
+    const CMPXSubscription& aSubscription)
+    {
+    const CMPXMediaArray* items = aSubscription.ItemsL();
+ 
+    CMPXCommand* cmd = CMPXCommand::NewL();
+    CleanupStack::PushL(cmd);
+    cmd->SetTObjectValueL(KMPXCommandGeneralId, KMPXCommandSubscriptionAdd);
+    cmd->SetCObjectValueL(KMPXCommandSubscriptionAddItems, items);
+    cmd->SetTObjectValueL(KMPXCommandGeneralDoSync, ETrue);
+    CommandL(*cmd);
+    CleanupStack::PopAndDestroy(cmd); 
+    }
+ 
+// ----------------------------------------------------------------------------
+// CMPXCollectionUtility::RemoveSubscriptionL
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::RemoveSubscriptionL(
+    const CMPXSubscription& aSubscription)
+    {
+    const CMPXMediaArray* items = aSubscription.ItemsL();
+ 
+    CMPXCommand* cmd = CMPXCommand::NewL();
+    CleanupStack::PushL(cmd);
+    cmd->SetTObjectValueL(KMPXCommandGeneralId, KMPXCommandSubscriptionRemove);
+    cmd->SetCObjectValueL(KMPXCommandSubscriptionAddItems, items);
+    cmd->SetTObjectValueL(KMPXCommandGeneralDoSync, ETrue);
+    CommandL(*cmd);
+    CleanupStack::PopAndDestroy(cmd); 
+    }
+ 
+// ----------------------------------------------------------------------------
+// CMPXCollectionUtility::ClearSubscriptionsL
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::ClearSubscriptionsL()
+    {
+    CMPXCommand* cmd = CMPXCommand::NewL();
+    CleanupStack::PushL(cmd);
+    cmd->SetTObjectValueL(KMPXCommandGeneralId, KMPXCommandSubscriptionRemoveAll);
+    cmd->SetTObjectValueL(KMPXCommandGeneralDoSync, ETrue);
+    CommandL(*cmd);
+    CleanupStack::PopAndDestroy(cmd);
+    } 
+
+// ----------------------------------------------------------------------------
+// Destroy this object
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::Close()
+    {
+    MPX_DEBUG2("CMPXCollectionUtility::Close %08x", this);
+    iMsgMonitor->Cancel();
+    delete this;
+    } 
+
+// ----------------------------------------------------------------------------
+//  Open's collection with the mode. Data returned in callback
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionUtility::OpenL(TMPXOpenMode aMode)
+    {
+    MPX_DEBUG2("CMPXCollectionUtility::OpenL with mode %d", aMode);
+    AddRequestL(EMcsOpen, NULL, aMode);
+    }
+ 
+// ----------------------------------------------------------------------------
+// Open a collection
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::OpenL(TInt aIndex,TMPXOpenMode aMode)
+    {
+    RArray<TMPXAttribute> dummy;
+    CleanupClosePushL(dummy);
+    OpenL(aIndex, dummy.Array(), aMode);
+    CleanupStack::PopAndDestroy(&dummy); 
+    }
+
+// ----------------------------------------------------------------------------
+// Open a collection by path
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::OpenL(
+    const CMPXCollectionPath& aPath,
+    TMPXOpenMode aMode)
+    {
+    RArray<TMPXAttribute> dummy;
+    CleanupClosePushL(dummy);
+    OpenL(aPath, dummy.Array(), aMode);
+    CleanupStack::PopAndDestroy(&dummy); 
+    }
+
+// ----------------------------------------------------------------------------
+//  Opens the collection at a specific index 
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionUtility::OpenL(
+    TInt aIndex,
+    const TArray<TMPXAttribute>& aAttrs,
+    TMPXOpenMode aMode)
+    {
+    // Externalize parameters
+    //
+    CBufBase* buf=CBufFlat::NewL(KMPXBufGranularity);
+    CleanupStack::PushL( buf );
+
+    RBufWriteStream writeStream( *buf );
+    CleanupClosePushL( writeStream );
+    // Mode
+    writeStream.WriteInt32L(aMode); 
+    // externalize attributes array
+    ::ExternalizeL(aAttrs, writeStream);
+    // Close and compress buffer
+    writeStream.CommitL();
+    buf->Compress();
+    CleanupStack::PopAndDestroy(&writeStream);
+ 
+    // Async version, Add request to the task queue 
+    AddRequestL(EMcsOpenIndex, NULL, aIndex, buf);
+    CleanupStack::Pop( buf );  // ownership transferred to the queue
+    }
+
+// ----------------------------------------------------------------------------
+//  Opens the collection at a specific level 
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::OpenL(
+    const CMPXCollectionPath& aPath,
+    const TArray<TMPXAttribute>& aAttrs,
+    TMPXOpenMode aMode)
+    {
+    MPX_FUNC("CMPXCollectionUtility::OpenL(const CMPXCollectionPath& aPath)");
+    MPX_DEBUG_PATH(aPath);
+    CBufBase* buffer=CBufFlat::NewL(KMPXBufGranularity);
+    CleanupStack::PushL( buffer );
+    RBufWriteStream writeStream( *buffer );
+    CleanupClosePushL( writeStream );
+    //collection path 
+    writeStream << aPath; 
+    // externalize open mode
+    writeStream.WriteInt32L(aMode);
+    // externalize attributes array
+    ::ExternalizeL(aAttrs, writeStream);
+    writeStream.CommitL();
+    buffer->Compress();
+    CleanupStack::PopAndDestroy(&writeStream);
+    AddRequestL(EMcsOpenPath, NULL, 0, buffer);
+    CleanupStack::Pop(buffer); //buffer ownership transferred
+    }
+
+// ----------------------------------------------------------------------------
+//  Opens the collection in its current state, or if aUids do not
+//  apply to currently opened collection, then the state will
+//  revert back to root level
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::OpenL(
+    const TArray<TUid>& aUids,
+    TMPXOpenMode aMode)
+    {
+    MPX_FUNC_EX("CMPXCollectionUtility::OpenL(aUids, aMode)");
+    CBufBase* buf=CBufFlat::NewL(KMPXBufGranularity);
+    CleanupStack::PushL( buf );
+    // Externalize parameters
+    //
+    RArray<TUid> uids;
+    CleanupClosePushL(uids);
+    TInt count(aUids.Count());
+    for (TInt i=0; i<count; ++i)
+        { // sort uids
+        uids.InsertInOrderL(aUids[i], MPXUser::CompareUids);
+        }
+    RBufWriteStream writeStream( *buf );
+    CleanupClosePushL( writeStream );
+    // Mode
+    writeStream.WriteInt32L(aMode); 
+    // Uids
+    ::ExternalizeL(uids.Array(), writeStream);
+    // Close and compress buffer
+    writeStream.CommitL();
+    buf->Compress();
+    CleanupStack::PopAndDestroy(&writeStream);
+ 
+    CleanupStack::PopAndDestroy(&uids);
+    // Async version, Add request to the task queue 
+    AddRequestL(EMcsOpenByUids, NULL, 0, buf);
+    CleanupStack::Pop( buf );  // ownership transferred to the queue
+    }
+
+// ----------------------------------------------------------------------------
+//  Opens the collection in its current state, or if aUid does not
+//  apply to currently opened collection, then the state will
+//  revert back to root level
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::OpenL(
+    const TUid& aUid,
+    TMPXOpenMode aMode)
+    {
+    RArray<TUid> uids;
+    CleanupClosePushL(uids);
+    uids.AppendL(aUid);
+    OpenL(uids.Array(),aMode);
+    CleanupStack::PopAndDestroy(&uids);
+    }
+
+// ----------------------------------------------------------------------------
+//  Apply a filter to collection browsing; all subsequent calls
+//  to OpenL() will have this filter applied
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::SetFilterL(CMPXFilter* aFilter)
+    {
+    if (aFilter)
+        { // Send filter to server
+        CBufBase* buf=NULL;
+        ::CreateBufferL<CMPXFilter>(*aFilter,buf);
+        CleanupStack::PushL(buf);
+        TPtr8 ptr=buf->Ptr(0);
+        iMcs.SendReceiveL(EMcsSetFilter,TIpcArgs(&ptr));
+        CleanupStack::PopAndDestroy(buf);
+        }
+    else
+        { // Else send zero length descriptor
+        iMcs.SendReceiveL(EMcsSetFilter,TIpcArgs(&KNullDesC8));
+        }
+    }
+
+// ----------------------------------------------------------------------------
+//  Current filter that is applied to collection browsing
+// ----------------------------------------------------------------------------
+// 
+CMPXFilter* CMPXCollectionUtility::FilterL()
+    {
+    TInt size=iMcs.SendReceiveL(EMcsFilter);
+    // 
+    // Transfer results from server
+    //
+    CMPXMedia* filter=NULL;
+    if (size)
+        {
+        ::TransferBufferFromServerL(iMcs,EMcsGetSyncBuffer,size,iBuffer);
+        ::NewFromBufferL<CMPXFilter>(*iBuffer,filter); 
+        }
+    return filter;
+    }
+
+// ----------------------------------------------------------------------------
+// The UID identifying this collection
+// ----------------------------------------------------------------------------
+// 
+TUid CMPXCollectionUtility::UidL() const
+    {
+    TPckgBuf<TInt> uidPkg; 
+    iMcs.SendReceiveL(EMcsGetUid, TIpcArgs(&uidPkg));
+    return TUid::Uid(uidPkg());
+    }
+ 
+// ----------------------------------------------------------------------------
+// Return current collection path
+// ----------------------------------------------------------------------------
+// 
+CMPXCollectionPath* CMPXCollectionUtility::PathL()
+    {
+    CMPXCollectionPath* path = NULL;
+    TInt size = iMcs.SendReceiveL(EMcsGetPath);
+    if (size >0)
+        {
+        ::TransferBufferFromServerL(iMcs, EMcsGetSyncBuffer, size, iBuffer);
+        ::NewFromBufferL<CMPXCollectionPath>(*iBuffer, path);
+        }
+    return path;
+    }
+
+// ----------------------------------------------------------------------------
+// Back to upper level
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::BackL()
+    {
+    AddRequestL(EMcsBack, NULL);
+    }
+
+// ----------------------------------------------------------------------------
+// Is remote collection path
+// ----------------------------------------------------------------------------
+// 
+TBool CMPXCollectionUtility::IsRemote(const CMPXCollectionPath& aPath)
+    {
+    (void)aPath; 
+    return EFalse; 
+    }
+
+// ----------------------------------------------------------------------------
+// Remove outstanding requests
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::CancelRequest()
+    {
+    Cancel();
+    iTaskQueue->Reset();
+    }
+
+// ----------------------------------------------------------------------------
+// Add item(s)
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionUtility::AddL(const CMPXMedia& aNewProperties)
+    {
+    delete iMedia;
+    iMedia=NULL;
+    iMedia=CMPXMedia::NewL(aNewProperties);
+ 
+    CBufBase* buf(NULL);
+    ::CreateBufferL<CMPXMedia>( aNewProperties, buf );
+    CleanupStack::PushL( buf );
+    TPtr8 ptr = buf->Ptr(0);
+    iMcs.SendReceiveL( EMcsAddItem, TIpcArgs(&ptr));
+    CleanupStack::PopAndDestroy( buf );
+    }
+
+// ----------------------------------------------------------------------------
+// Remove a single item
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::RemoveL( 
+    const CMPXCollectionPath& aPath,
+    MMPXCollectionRemoveObserver* aObs )
+    {
+    // Serialize the path and send it to the collection
+    //
+    if (aPath.Levels()<=0)
+        {
+        User::Leave(KErrArgument);
+        }
+    CBufBase* buf(NULL);
+    ::CreateBufferL<CMPXCollectionPath>( aPath, buf );
+    CleanupStack::PushL(buf);
+    AddRequestL(EMcsRemovePath, aObs, 0, buf);  // buf ownership transferred
+    CleanupStack::Pop(buf);
+    }
+
+// ----------------------------------------------------------------------------
+// Remove a list of items
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::RemoveL(const CMPXMedia& aProperties)
+    {
+    delete iMedia;
+    iMedia=NULL;
+    iMedia=CMPXMedia::NewL(aProperties);
+ 
+    CBufBase* buf(NULL);
+    ::CreateBufferL<CMPXMedia>( aProperties, buf );
+    CleanupStack::PushL( buf );
+    TPtr8 ptr = buf->Ptr(0);
+    iMcs.SendReceiveL( EMcsRemoveItem, TIpcArgs(&ptr));
+    CleanupStack::PopAndDestroy( buf );
+    }
+
+// ----------------------------------------------------------------------------
+// Set properties
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::SetSyncL(const CMPXMedia& aMedia)
+    {
+    delete iMedia;
+    iMedia=NULL;
+    iMedia=CMPXMedia::NewL(aMedia);
+ 
+    CBufBase* buf(NULL);
+    ::CreateBufferL<CMPXMedia>( aMedia, buf );
+    CleanupStack::PushL( buf );
+    TPtr8 ptr = buf->Ptr(0);
+    iMcs.SendReceiveL( EMcsSetMedia, TIpcArgs(&ptr));
+    CleanupStack::PopAndDestroy( buf );
+    }
+
+// ----------------------------------------------------------------------------
+// Set properties Asynchronous
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::SetL(const CMPXMedia& /*aMedia*/)
+    {
+    ASSERT(0); // DEPRECATED, please use CommandL(CMPXCommand& aCmd)
+    }
+
+// ----------------------------------------------------------------------------
+// Find media
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::FindAllL(const CMPXMedia& aMedia,
+                                     const TArray<TMPXAttribute>& aAttrs,
+                                     MMPXCollectionFindObserver& aObs)
+    {
+    // Externalize parameters
+    //
+    CBufBase* buf(NULL);
+    ::CreateBufferL(aAttrs, buf);
+    CleanupStack::PushL(buf);
+    // Increase reference count on media ownership transferred
+    CMPXMedia* ref = CMPXMedia::NewL( aMedia ); 
+    CleanupStack::PushL(ref);
+    AddRequestL(EMcsFindAll, &aObs, aMedia.Data(), buf, NULL, ref);
+    // Async version, Add request to the task queue 
+    CleanupStack::Pop(ref);
+    CleanupStack::Pop( buf );  // ownership transferred to the queue
+    }
+
+// ----------------------------------------------------------------------------
+// Find media sync
+// ----------------------------------------------------------------------------
+// 
+CMPXMedia* CMPXCollectionUtility::FindAllL(const CMPXMedia& aMedia,
+                                           const TArray<TMPXAttribute>& aAttrs)
+    {
+    CMPXMedia* media=CMPXMedia::NewL(aMedia); // keep media alive
+    CleanupStack::PushL(media);
+ 
+    CBufBase* buf(NULL);
+    ::CreateBufferL(aAttrs, buf);
+    CleanupStack::PushL(buf);
+ 
+    // Synchronous version, transfer directly
+    TPtr8 ptr = buf->Ptr(0);
+    TInt size = iMcs.SendReceiveL( EMcsFindAll, 
+                                   TIpcArgs(&ptr, 1, media->Data()) );
+    CleanupStack::PopAndDestroy( buf );
+ 
+    // Transfer results from server
+    //
+    CMPXMedia* results(NULL);
+    ::TransferBufferFromServerL( iMcs, EMcsGetSyncBuffer, 
+                                 size, iBuffer );
+    ::NewFromBufferL<CMPXMedia>( *iBuffer, results );
+    CleanupStack::PopAndDestroy(media);
+    return results;
+    }
+
+// ----------------------------------------------------------------------------
+// Issue media request
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::MediaL(
+    const CMPXCollectionPath& aPath,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXAttributeSpecs* aSpecs/*=NULL*/,
+    CMPXFilter* aFilter/*=NULL*/)
+    {
+    MPX_FUNC_EX("CMPXCollectionUtility::MediaL()");
+    MPX_DEBUG_PATH(aPath);
+    if (aPath.Levels()<=0)
+        {
+        User::Leave(KErrArgument);
+        }
+    CMPXCommand* cmd = CMPXCommand::NewL();
+    CleanupStack::PushL(cmd);
+
+    CMPXCollectionPath* path = CMPXCollectionPath::NewL(aPath);
+    CleanupStack::PushL(path);
+    path->Set(aAttrs); // aAttrs should be removed from parameter
+                       // Clients should set attribute before API is called
+ 
+    cmd->SetTObjectValueL<TInt>(KMPXCommandGeneralId, KMPXCommandContentIdMedia);
+    cmd->SetCObjectValueL<CMPXCollectionPath>(KMPXCommandGeneralTargetIds, path);
+    CMPXAttributeSpecs* attrSpecs = aSpecs ? 
+            CMPXAttributeSpecs::NewL(*aSpecs) : CMPXAttributeSpecs::NewL();
+    CleanupStack::PushL(attrSpecs);
+    cmd->SetCObjectValueL<CMPXAttributeSpecs>(KMPXCommandMediaAttributeSpecs, attrSpecs);
+    CleanupStack::PopAndDestroy(attrSpecs);
+    CMPXFilter* filter = aFilter ? CMPXFilter::NewL(*aFilter) : CMPXFilter::NewL();
+    CleanupStack::PushL(filter);
+    cmd->SetCObjectValueL<CMPXFilter>(KMPXCommandMediaFilter, filter);
+    CleanupStack::PopAndDestroy(filter);
+    //call CommandL in the future. All APIs will be mapped to CommandL
+    AddRequestL(EMcsMediaByPath, NULL, 0, NULL, (TAny*)cmd, cmd);
+    CleanupStack::PopAndDestroy(path);
+    CleanupStack::Pop(cmd); // Ownership transferred to the task queue
+    }
+
+// ----------------------------------------------------------------------------
+// Add a request to broadcast a message
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::NotifyL( TMPXCollectionBroadCastMsg aMsg, 
+                                     TInt aData )
+    {
+    // Synchronous, for closing server file handles
+    iMcs.SendReceiveL( EMcsNotifyEvent,
+                       TIpcArgs((TInt)aMsg, aData));
+    }
+
+// ----------------------------------------------------------------------------
+// Send a Command to the collection
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::CommandL(TMPXCollectionCommand aCmd, TInt aData )
+    {
+    // Synchronous, send a command to the server
+    iMcs.SendReceiveL( EMcsCommand, TIpcArgs( (TInt)aCmd, aData ) );
+    }
+ 
+// ----------------------------------------------------------------------------
+// Send a Command to the collection
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionUtility::CommandL(CMPXCommand& aCmd)
+    {
+    TBool sync(EFalse); // by default command is asynchronous
+    if (aCmd.IsSupported(KMPXCommandGeneralDoSync))
+        { // check if command is sync
+        sync=(aCmd.ValueTObjectL<TBool>(KMPXCommandGeneralDoSync));
+        }
+    if (sync)
+        { // sync request
+        iMcs.SendReceiveL(EMcsCommandExt, TIpcArgs(EFalse, aCmd.Data()));
+        }
+    else
+        { // async request
+        // Increase reference count on command ownership transferred
+        CMPXCommand* ref = CMPXCommand::NewL(aCmd); 
+        // async version, Add request to the task queue 
+        CleanupStack::PushL(ref);
+        AddRequestL(EMcsCommandExt, NULL, ETrue, NULL, (TAny*)ref, ref );
+        CleanupStack::Pop(ref); // Ownership transferred to the task queue
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieve the list of supported mime types
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::GetSupportedTypesL( 
+    RPointerArray<CMPXCollectionType>& aArray )
+    {
+    TInt size = iMcs.SendReceiveL( EMcsGetSupportedTypes );
+    ::ArrayFromServerL( iMcs, EMcsGetSyncBuffer, size, aArray );
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieve the bitmask of supported capabilities of the collection
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::GetSupportedCapabilitiesL(
+    TCollectionCapability& aCapability)
+    {
+    TPckgBuf<TCollectionCapability> pkg;
+    iMcs.SendReceiveL( EMcsGetCapabilities, TIpcArgs(&pkg) );
+    aCapability = pkg();
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieves the actual collection implementation UID
+// ----------------------------------------------------------------------------
+// 
+TUid CMPXCollectionUtility::CollectionIDL(TUid& aCollection)
+    {
+    TPckgBuf<TUid> pkg( aCollection );
+    iMcs.SendReceiveL( EMcsCollectionID, TIpcArgs(&pkg) );
+ 
+    return pkg();
+    }
+
+// ----------------------------------------------------------------------------
+// Message received 
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::MessageReceived(TInt aMsgData, TInt aError)
+    {
+    TRAP_IGNORE(HandleMessageL(aMsgData, aError));
+    }
+
+// ----------------------------------------------------------------------------
+// Handles an active object's request completion event
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::RunL()
+    {
+#ifdef _ENABLE_GUARD_TIMER
+    iGuardTimer->Cancel();
+#endif
+    TInt err=iStatus.Int();
+    TInt task = iTaskQueue->Task();
+    MPX_DEBUG4("-->CMPXCollectionUtility::RunL 0x%08x task %d err%d", 
+               this, task, err);
+    if (KErrNotFound == task)
+        {
+        MPX_DEBUG1("CMPXCollectionUtility::RunL no task");
+        return;
+        }
+
+    // Try again in case server is down for IAD
+    if (err == KErrDied || err == KErrServerTerminated)
+        {
+        MPX_DEBUG3("-->CMPXCollectionUtility::RunL Reconnecting session for IAD 0x%08x task %d",
+                this, task);
+        
+        // attempt to bring the server back up
+        err = iMcs.Reconnect();
+        
+        if (err != KErrNone)
+            {
+            MPX_DEBUG1("-->CMPXCollectionUtility::RunL Reconnect Failed");
+            }
+        }
+    
+    // If there was an error, callback to observer with error code
+    User::LeaveIfError(err);
+    
+    switch(task)
+        {
+        case EMcsOpen:
+        case EMcsBack:
+        case EMcsOpenIndex:
+        case EMcsOpenPath:
+        case EMcsOpenByUids:
+            {
+            MPX_DEBUG1("CMPXCollectionUtility::RunL handle open");
+            if(err == KMPXCollectionPath && iObserver)
+                {
+                CMPXCollectionPath* path = PathL();
+                CleanupStack::PushL(path);
+                if (path->OpenNextMode() != EMPXOpenNoPlaylist)
+                    {
+                    CMPXCollectionPlaylist* p=CMPXCollectionPlaylist::NewL(*path);
+                    CleanupStack::PushL(p);
+ 
+                    if( path->OpenNextMode() == EMPXOpenPlaylistOnly )
+                        {
+                        p->SetToIndex( KErrNotFound );
+                        }
+ 
+                    iCallbackOngoing = ETrue;
+                    iObserver->HandleOpenL(*p, KErrNone);
+                    iCallbackOngoing = EFalse;
+                    CleanupStack::PopAndDestroy(p);
+                    }
+                CleanupStack::PopAndDestroy(path);
+                }
+            else if (KMPXCollectionEntries == err && iObserver)
+                {
+                MPX_DEBUG2("CMPXCollectionUtility::RunL with KMPXCollectionEntries %d", 
+                            iSizePckg());
+                if (iSizePckg() >0)
+                    {
+                    ::TransferBufferFromServerL(iMcs,EMcsGetAsyncBuffer, 
+                                                iSizePckg(), iBuffer);
+                    ::NewFromBufferL<CMPXMedia>(*iBuffer, iCurrentEntries);
+                    }
+                MPX_DEBUG1("CMPXCollectionUtility::RunL call back client with entries");
+                iCallbackOngoing = ETrue;
+                iObserver->HandleOpenL(*iCurrentEntries, 
+                                       iSelectionPckg(), 
+                                       (TBool)iCompletePckg(), 
+                                       KErrNone);
+                iCallbackOngoing = EFalse;
+                } // else message will be received which triggers to read buffer
+            break;
+            }
+         case EMcsMediaByPath:
+            {
+            CMPXMedia* props = NULL;
+            if (iObserver)
+                {
+                if(iSizePckg() && KMPXCollectionMedia == err)
+                    {
+                    ::TransferBufferFromServerL(iMcs,EMcsGetAsyncBuffer, 
+                                                iSizePckg(), iBuffer);
+                    ::NewFromBufferL<CMPXMedia>(*iBuffer, props);
+                    err = KErrNone;
+                    CleanupStack::PushL(props);
+                    }
+                else
+                    {
+                    props = iMediaOnError;
+                    }
+                iCallbackOngoing = ETrue;
+                iObserver->HandleCollectionMediaL(*props, err);
+                iCallbackOngoing = EFalse;
+                if (props && props != iMediaOnError)
+                    {
+                    CleanupStack::PopAndDestroy(props);
+                    }
+                }
+            break;
+            }
+        case EMcsRemovePath:
+            {
+            MMPXCollectionRemoveObserver* obs = 
+                     (MMPXCollectionRemoveObserver*) iTaskQueue->Callback();
+ 
+            // Optional observer callback
+            CDesCArray* ary(NULL);
+            if( obs && err>0 )
+                {
+                ::TransferBufferFromServerL(iMcs,EMcsGetAsyncBuffer, 
+                                            err, iBuffer);
+                MPXUser::CreateFromBufferL(*iBuffer, ary);
+                CleanupStack::PushL( ary );
+                iCallbackOngoing = ETrue;
+                obs->HandleRemoveL( *ary, KErrNone );
+                iCallbackOngoing = EFalse;
+                CleanupStack::PopAndDestroy( ary );
+                } // else error message will be sent later
+            break;
+            }
+        case EMcsFindAll:
+            {
+            MMPXCollectionFindObserver* obs = 
+                        (MMPXCollectionFindObserver*) iTaskQueue->Callback();
+            CMPXMedia* results(NULL);
+ 
+            // Any results?
+            if( err > 0 )
+                {
+                if(obs)
+                    {
+                    ::TransferBufferFromServerL( iMcs, EMcsGetAsyncBuffer, 
+                                                 err, iBuffer );
+                    ::NewFromBufferL<CMPXMedia>( *iBuffer, results );
+                    CleanupStack::PushL( results );
+                    iCallbackOngoing = ETrue;
+                    obs->HandleFindAllL( *results, ETrue, KErrNone );
+                    iCallbackOngoing = EFalse;
+                    CleanupStack::PopAndDestroy( results );
+                    }
+                }
+            break;
+            }
+        case EMcsSetMediaAsync:
+            { // DEPRECATED, please use CommandL(CMPXCommand& aCmd)
+            ASSERT(0);
+            break;
+            }
+        case EMcsCommandExt:
+            {
+            CMPXCommand* result = NULL;
+            if (iObserver && KErrNone == err)
+                {
+                if(iSizePckg())
+                    {
+                    ::TransferBufferFromServerL(iMcs,EMcsGetAsyncBuffer, 
+                                                iSizePckg(), iBuffer);
+                    ::NewFromBufferL<CMPXCommand>(*iBuffer, result);
+                    }
+                CleanupStack::PushL(result);
+                iCallbackOngoing = ETrue;
+                iObserver->HandleCommandComplete(result, KErrNone);
+                iCallbackOngoing = EFalse;
+                CleanupStack::PopAndDestroy(result);
+                }
+            break;
+            }
+        default:
+            ASSERT(0);
+        }
+    iTaskQueue->RemoveTask();
+    ExecuteNextRequest();
+    MPX_DEBUG4("<--CMPXCollectionUtility::RunL 0x%08x task %d err%d", 
+               this, task, err);
+    }
+
+// ----------------------------------------------------------------------------
+// Sends error message to all observers - maybe it should only be to the 
+// client that calls the async method?
+// ----------------------------------------------------------------------------
+// 
+TInt CMPXCollectionUtility::RunError(TInt aError)
+    {
+    MPX_FUNC_EX("CMPXCollectionUtility::RunError");
+    TRAP_IGNORE(HandleRunErrorL(aError));
+    iCallbackOngoing = EFalse;
+    iTaskQueue->RemoveTask();
+    ExecuteNextRequest();
+    return KErrNone;
+    }
+
+// ----------------------------------------------------------------------------
+// Handle cancelling request
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::DoCancel()
+    {
+#ifdef _ENABLE_GUARD_TIMER
+    iGuardTimer->Cancel();
+#endif
+    TRAP_IGNORE(iMcs.SendReceiveL(EMcsCancelRequest));
+    }
+
+// ----------------------------------------------------------------------------
+// Adds a sync request to the queue: if there is no outstanding request,
+// it will be executed immediately
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::AddRequestL(
+    TMPXCollectionServerOp aFunction,
+    TAny* aObs,
+    TInt aParamData/*=0*/,
+    CBufBase* aBuf/*=NULL*/,
+    TAny* aPtr/*=NULL*/,
+    CBase* aAlivePtr1/*=NULL*/,
+    CBase* aAlivePtr2/*=NULL*/)
+    {
+    iTaskQueue->AddTaskL(aFunction, aObs, aParamData, aBuf, 
+                         aPtr, aAlivePtr1, aAlivePtr2);
+    MPX_DEBUG3("CMPXCollectionUtility::AddRequestL this 0x%08x task=%d", 
+            this, aFunction);
+    if (!IsActive() && !iCallbackOngoing)
+        {
+        ExecuteNextRequest();
+        }
+    }
+ 
+// ----------------------------------------------------------------------------
+// Executes the next request in the queue. 
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::ExecuteNextRequest()
+    {
+    TInt task = iTaskQueue->Task();
+    if (KErrNotFound != task && !IsActive() &&  !iCallbackOngoing)
+        {
+        switch(task)
+            {
+            case EMcsOpenIndex:
+                {
+                iSelectionPckg = (TInt)iTaskQueue->Param();
+                } // deliberate fall through
+            case EMcsOpenByUids:
+            case EMcsOpenPath:
+                {
+                iMcs.SendReceive(task, 
+                                 TIpcArgs(&iSizePckg,   // [out] size of buffer
+                                          &iSelectionPckg, // [in, out] selection index 
+                                          &iCompletePckg,  // [out] complete
+                                          &iTaskQueue->BufData()), // index, mode and attr
+                                 iStatus);
+                break;
+                }
+ 
+            case EMcsOpen:
+                {
+                iMcs.SendReceive(EMcsOpen, 
+                                 TIpcArgs(&iSizePckg, 
+                                          &iSelectionPckg, 
+                                          &iCompletePckg,
+                                          iTaskQueue->Param()),  // mode
+                                 iStatus);
+                break;
+                }
+            case EMcsMediaByPath:
+                {
+                iMcs.SendReceive(EMcsMediaByPath, 
+                                 TIpcArgs(&iSizePckg,
+                                         ((CMPXCommand*)(iTaskQueue->PtrData()))->Data()), // command handle
+                                 iStatus);
+                break;
+                } 
+            case EMcsBack: 
+                {
+                iMcs.SendReceive(EMcsBack, 
+                                 TIpcArgs(&iSizePckg, 
+                                          &iSelectionPckg, 
+                                          &iCompletePckg),
+                                 iStatus);
+                break;
+                }
+            case EMcsRemovePath: // deliberate fall through
+                {
+                iMcs.SendReceive( task, 
+                                  TIpcArgs(&iTaskQueue->BufData()), 
+                                  iStatus);
+                break; 
+                }
+            case EMcsFindAll:
+                {
+                iMcs.SendReceive( task, 
+                                  TIpcArgs(&iTaskQueue->BufData(), // Attrs
+                                           0,                    // Not sync
+                                           iTaskQueue->Param()), // Media data handle
+                                  iStatus );
+                break; 
+                }
+            case EMcsCommandExt:
+                {
+                iMcs.SendReceive(EMcsCommandExt, 
+                                 TIpcArgs(iTaskQueue->Param(), //[in] Async flag
+                                          ((CMPXCommand*)(iTaskQueue->PtrData()))->Data(), 
+                                                               //[in] command handle 
+                                          &iSizePckg), //[out] size of buffer 
+                                 iStatus);
+                break;
+                }
+            default:
+                ASSERT(0);
+            }
+    #ifdef _ENABLE_GUARD_TIMER
+         iGuardTimer->Start(KMPXGuardTimer,KMPXGuardTimer,
+                            TCallBack(GuardTimerCallback,this)); 
+    #endif
+        SetActive(); 
+        MPX_DEBUG3("CMPXCollectionUtility::ExecuteNextRequest 0x%08x task %d ", 
+                this, task);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXCollectionUtility::HandleMessageL 
+// ----------------------------------------------------------------------------
+// 
+void CMPXCollectionUtility::HandleMessageL(TInt aMsgData, TInt aError)
+    {
+    MPX_FUNC_EX("CMPXCollectionUtility::HandleMessageL");
+    if (iObserver)
+        {
+        if (aMsgData>0)
+            {
+            CMPXMessage* msg= CMPXMessage::NewL(aMsgData);
+            CleanupStack::PushL(msg);
+            MPX_ASSERT(msg->IsSupported(KMPXMessageGeneralId));
+            iObserver->HandleCollectionMessage(msg, aError);
+            CleanupStack::PopAndDestroy(msg);
+            }
+        else
+            { // NULL message
+            iObserver->HandleCollectionMessage(NULL, aError);
+            }
+        }
+    else
+        {
+        MPX_DEBUG1("CMPXCollectionUtility::HandleMessageL no observer");
+        }
+    iMsgMonitor->GetNextMessage();
+    }
+
+
+// ----------------------------------------------------------------------------
+//  Handle error in RunL
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionUtility::HandleRunErrorL(TInt aError)
+    {
+    TInt task = iTaskQueue->Task();
+    if (!iCallbackOngoing)
+        { // Error happens during preparing callback
+        iCallbackOngoing = ETrue; // will be reset to EFalse in the RunError
+        switch(task)
+            {
+            case EMcsOpen:
+            case EMcsBack:
+            case EMcsOpenIndex:
+            case EMcsOpenPath:
+            case EMcsOpenByUids:
+                {
+                if (iObserver)
+                    {
+                    iObserver->HandleOpenL(*iMediaOnError, KErrNotFound, 
+                                           ETrue, aError);
+                    }
+                break;
+                }
+             case EMcsMediaByPath:
+                {
+                if (iObserver)
+                    {
+                    iObserver->HandleCollectionMediaL(*iMediaOnError, aError);
+                    }
+                break;
+                }
+            case EMcsRemovePath:
+                {
+                MMPXCollectionRemoveObserver* obs = 
+                         (MMPXCollectionRemoveObserver*) iTaskQueue->Callback();
+                if( obs)
+                    {
+                    CDesCArray* ary(NULL);
+                    obs->HandleRemoveL(*ary, aError); // change HandleRemoveL return pointer
+                    } // else error message will be sent later
+                break;
+                }
+            case EMcsFindAll:
+                {
+                MMPXCollectionFindObserver* obs = 
+                            (MMPXCollectionFindObserver*) iTaskQueue->Callback();
+                if (obs)
+                    {
+                    obs->HandleFindAllL( *iMediaOnError, ETrue, aError);
+                    }
+                break;
+                }
+            case EMcsCommandExt:
+                {
+                if (iObserver)
+                    {
+                    iObserver->HandleCommandComplete(iMediaOnError, aError);
+                    }
+                break;
+                }
+            default:
+                ASSERT(0);
+            }
+        } // do nothing if error happens during client processing callback.
+          // all callback should be changed into non-leave so that this will
+          // be never happen.
+    }
+
+#ifdef _ENABLE_GUARD_TIMER
+// ----------------------------------------------------------------------------
+// Guard timer time out
+// ----------------------------------------------------------------------------
+// 
+TInt CMPXCollectionUtility::GuardTimerCallback(TAny* aPtr)
+    {
+    CMPXCollectionUtility* cu = static_cast<CMPXCollectionUtility*>(aPtr);
+    MPX_DEBUG3("CMPXCollectionUtility::GaurdTimerCallback this 0x%08x task=%d", 
+               cu, cu->iTaskQueue->Task());
+    cu->iGuardTimer->Cancel();
+    ASSERT(0); // the function should never be called
+    return KErrNone;
+    }
+#endif
+// End of file