--- /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