--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmresourcemgmt/mmresctrl/src/mmrcserver/mmrcservercontroller.cpp Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,917 @@
+// Copyright (c) 2007-2009 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:
+//
+
+#include "mmrcservercontroller.h"
+#include "mmrcerrorcodes.h"
+#include "mmrcserversession.h"
+#include "mmrcserverinfo.h"
+#include "mmrcserverrulemanager.h"
+#include "mmrcadaptationproxy.h"
+#include "mlogicalchain.h"
+#include <a3f/audioprocessingunittypeuids.h>
+
+/**
+@internalComponent
+
+This class implements a timer.
+*/
+class CARNNotificationObject : public CActive
+ {
+
+public:
+ static CARNNotificationObject* NewL(const TInt aPriority, CMMRCServerInfo& aMMRCServerInfo);
+ ~CARNNotificationObject();
+ void After(TTimeIntervalMicroSeconds32 aInterval);
+ void Initialize();
+
+protected:
+ void RunL();
+ void DoCancel();
+
+private:
+ CARNNotificationObject(const TInt aPriority);
+ void ConstructL(CMMRCServerInfo& aMMRCServerInfo);
+
+public:
+ TInt iIndex;
+
+protected:
+ RTimer iTimer;
+ CMMRCServerInfo* iMMRCServerInfo;
+ };
+
+//------------------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------------------
+
+/**
+ * Constructor
+ */
+CMMRCServerController::CMMRCServerController()
+ {
+ TRACE_CREATE();
+ DP_CONTEXT(----> CMMRCServerController::CMMRCServerController *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ DP_OUT();
+ }
+
+/**
+ * Destructor
+ */
+CMMRCServerController::~CMMRCServerController()
+ {
+ DP_CONTEXT(----> CMMRCServerController::~CMMRCServerController *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ delete iMMRCServerInfo;
+ delete iMMRCServerRuleManager;
+ delete iARNNotificationObject;
+
+ DP_OUT();
+ }
+
+/**
+ * Constructs, and returns a pointer to, a new CMMRCServerController object.
+ * Leaves on failure.
+ * @return CMMRCServerController* A pointer to newly created utlitly object.
+ */
+CMMRCServerController* CMMRCServerController::NewL()
+ {
+ DP_STATIC_CONTEXT(----> CMMRCServerController::NewL *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ CMMRCServerController* self = NewLC();
+ CleanupStack::Pop(self);
+
+ DP0_RET(self, "self = 0x%x");
+ }
+
+/**
+ * Constructs, leaves object on the cleanup stack, and returns a pointer
+ * to, a new CMMRCServerController object.
+ * Leaves on failure.
+ * @return CMMRCServerController* A pointer to newly created utlitly object.
+ */
+CMMRCServerController* CMMRCServerController::NewLC()
+ {
+ DP_STATIC_CONTEXT(----> CMMRCServerController::NewLC *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ CMMRCServerController* self = new(ELeave) CMMRCServerController();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+
+ DP0_RET(self, "self = 0x%x");
+ }
+
+/**
+ * CMMRCServerController::ConstructL
+ * Symbian 2nd phase constructor can leave.
+ */
+void CMMRCServerController::ConstructL()
+ {
+ DP_CONTEXT(----> CMMRCServerController::ConstructL *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ iMMRCServerInfo = CMMRCServerInfo::NewL(*this);
+ iMMRCServerRuleManager = CMMRCServerRuleManager::NewL(*this);
+ iARNNotificationObject = CARNNotificationObject::NewL(0, *iMMRCServerInfo); //Check the value
+
+ DP_OUT();
+ }
+
+/**
+* Process the request pointer by a specific session
+* @param CMMRCServerSession& aServerSession
+* @return KerrNone in case of success of the process
+*/
+TInt CMMRCServerController::EnqueueRequestL(CMMRCServerSession& aServerSession)
+ {
+ DP_CONTEXT(----> CMMRCServerController::ProcessRequestL *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ //add the request to the queue
+ iMMRCServerInfo->PushRequestL(aServerSession);
+ TInt err = ProcessNextRequestL();
+
+ DP0_RET(err, "err=%d");
+ }
+
+/**
+ * Process the first request with the highest priority from the FIFO queue
+ * @return KerrNone in case of success of the process
+ */
+ TInt CMMRCServerController::ProcessNextRequestL()
+ {
+ DP_CONTEXT(--------> CMMRCServerController::ProcessNextRequestL *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ TInt err = KErrNone;
+
+ TUint64 contextId;
+ TMMRCServerState serverState;
+ iMMRCServerInfo->ServerState(serverState, contextId);
+#ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
+ RDebug::Print(_L("serverState = %d"), serverState);
+ RDebug::Print(_L("size of message queue = %d"), iMMRCServerInfo->RequestsCount());
+ RDebug::Print(_L("size of inprocess queue = %d"), iMMRCServerInfo->AllocatedResourceContextsCount());
+ RDebug::Print(_L("size of paused queue = %d"), iMMRCServerInfo->AllocatedPausedContextsCount());
+#endif
+ if(EMMRCServerStateIdle != serverState)
+ {
+ DP0_RET(KErrNone, "%d");
+ }
+
+ CMMRCServerSession* serverSession = iMMRCServerInfo->PopAndRemoveFirstRequest(); //PopAndRemoveRequestFirstHighestPriority();
+ //Pop the next next commited message with the highest priority
+ if( NULL == serverSession )
+ {
+ DP0_RET(KErrNone, "%d");
+ }
+
+ if (!serverSession->HasUserEnvironmentCapability())
+ {
+ /* Check to see if it's a record use case and in IDLE, Active, or PRIME.
+ // in which case you should refuse the request for reasons
+ KErrPermissionDenied
+ */
+ MLogicalChain* requestedChange = serverSession->LogicalChainRequestedStack();
+ if ((requestedChange!=NULL) && (requestedChange->StreamState() > EInitialized)) // trying to play
+ {
+ TInt count = requestedChange->AudioProcessingUnitsCount();
+ for (TInt i=0; i<count; ++i)
+ {
+ if (KUidAudioDeviceSource == requestedChange->AudioProcessingUnitUid(i))
+ {
+ serverSession->NotifyClientOfError(KErrPermissionDenied);
+ // The following return value, doesn't actually make it back to the client
+ // We do however Notify the client above using NotifyClientOfError()
+ DP0_RET(KErrPermissionDenied, "%d");
+ }
+ }
+ }
+
+ }
+
+ //Pop the last commited message in process = the current resource in use
+ CMMRCServerSession* serverSessionAllocatedResource = iMMRCServerInfo->PopFirstAllocatedResourceContext();
+ //If no resource locked...
+ if( NULL == serverSessionAllocatedResource )
+ {
+
+ err = SendResourceRequest ( *serverSession );
+ }
+ else //If a resource has been allocated or is used, possibly preemption
+ {
+ TAudioContextId contextId = serverSession->ContextId( );
+ TAudioContextId contextIdAllocatedResource = serverSessionAllocatedResource->ContextId( );
+ #ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
+ RDebug::Print(_L("contextId = %d"), contextId.Id());
+ RDebug::Print(_L("contextIdAllocatedResource = %d"), contextIdAllocatedResource.Id());
+ #endif
+
+ //in case of processing the same context, remove the last committed request from the queue
+ // of in-process request to avoid preemption within the same context.
+ if(contextId == contextIdAllocatedResource)
+ {
+ err = SendResourceRequest ( *serverSession );
+ }
+ else // maybe preemption
+ {
+ //Pop the rule
+
+ MLogicalChain* logicalChainUsingResource = serverSessionAllocatedResource->LogicalChainLastCommited();
+ MLogicalChain* logicalChainNew = serverSession->LogicalChainRequestedStack();
+ //Should not/cannot be null!
+ if( NULL==logicalChainUsingResource || NULL==logicalChainNew )
+ {
+ #ifdef _DEBUG
+ RDebug::Print(_L("!!!!CMMRCServerController::ProcessNextRequestL - logicalChainUsingResource or logicalChainNew NULL"));
+ ASSERT(0);
+ #endif
+ User::Leave(EMMRCErrorLogicalChainNull);
+ }
+
+ TAudioState audioStateAllocatedResource = logicalChainUsingResource->StreamState();
+ TAudioState audioStateNew = logicalChainNew->StreamState ( );
+ TMMRCRule rule = DecisionRule(audioStateAllocatedResource, audioStateNew);
+ //Process according to the rule
+ if( rule == EAlwaysProcess )
+ {
+ err = SendResourceRequest( *serverSession );
+ }
+ else // process only in case of higher priority
+ {
+ TInt currentClientPriority = logicalChainUsingResource->Priority();
+ TInt newClientPriority = logicalChainNew->Priority();
+ TBool currentClient_HasMMDD = serverSessionAllocatedResource->HasMultimediaCapability();
+ TBool newClient_HasMMDD = serverSession->HasMultimediaCapability();
+
+ // If new client has multimedia capability and current doesn't have,
+ // priorities don't matter preempt the current client
+
+ // But if both are equal competitors (both has MMDD capability or both hasn't)
+ // and the newcomer has higher priority preempt too
+ if ( (!currentClient_HasMMDD && newClient_HasMMDD) ||
+ ( (currentClient_HasMMDD == newClient_HasMMDD) &&
+ (newClientPriority > currentClientPriority) ) )
+ {
+ //The process is delayed. First we have to preempt the current inprocess resource
+ // so puch back the request (its session)
+ iMMRCServerInfo->PushRequestL(*serverSession);
+ //
+ //send a premption message to the last commited message session
+ err = SendPreemptionRequest ( *serverSessionAllocatedResource );
+ }
+ else
+ {
+ // Deny the resource
+ TAudioContextId iId = serverSession->ContextId( );
+ TBool iIsOnPauseList = iMMRCServerInfo->IsOnPauseList(iId);
+ if(!iIsOnPauseList)
+ {
+ iMMRCServerInfo->PushPausedContextL(*serverSession);
+ }
+// nothing pending, deny resources, and notify client.
+ serverSession->AdaptationRequestAcknowledgment(EMMRCAdaptationToServerResourceIncomplete, KErrInUse);
+// Server is back to idle.
+ iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
+ }
+ }
+ }
+ }
+
+#ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
+ if(err != KErrNone)
+ {
+ RDebug::Print(_L("!!!!CMMRCServerController::ProcessNextRequestL - error = %d"), err);
+ }
+#endif
+
+ DP0_RET(err, "err=%d");
+ }
+
+/**
+ * Pop the decision rule on the base of the current in-process request and a new committed request
+ * @param TAudioState aAudioStateAllocatedResource
+ * @param TAudioState aAudioStateRequiringProcess
+ * @return TMMRCRule
+ */
+TMMRCRule CMMRCServerController::DecisionRule(TAudioState aAudioStateAllocatedResource, TAudioState aAudioStateRequiringProcess)
+ {
+ DP_CONTEXT(----> CMMRCServerController::DecisionRule *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ TMMRCRule rule = iMMRCServerRuleManager->DecisionRule(aAudioStateAllocatedResource, aAudioStateRequiringProcess);
+
+ DP0_RET(rule, "rule=%d");
+ }
+
+/**
+ * Pop the action reason on the base of the last committed request and the current one
+ * @param TAudioState aAudioStateLastCommitted
+ * @param TAudioState aAudioStateRequested
+ * @return TReason
+ */
+TReason CMMRCServerController::ActionReason(TAudioState aAudioStateLastCommitted, TAudioState aAudioStateRequested)
+ {
+ DP_CONTEXT(----> CMMRCServerController::ActionReason *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ TReason reason = iMMRCServerRuleManager->ActionReason(aAudioStateLastCommitted, aAudioStateRequested);
+
+ DP0_RET(reason, "reason=%d");
+ }
+
+/**
+ * Send a resource request to the adaptation
+ * @param MLogicalChain* aOldChain
+ * @param MLogicalChain* aNewChain
+ * @return KerrNone in case of success of the process
+ */
+TInt CMMRCServerController::SendResourceRequest( CMMRCServerSession& aServerSession )
+ {
+ DP_CONTEXT(----> CMMRCServerController::SendResourceRequest *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ iMMRCServerInfo->SwitchServerState( EMMRCServerStateWaitResourceResponseFromAdaptation, aServerSession.ContextId() );
+
+// if entering APR state, remove from Paused list.
+ TRAPD(err, aServerSession.StartProcessL());
+ {
+ MLogicalChain* logicalChainNew = aServerSession.LogicalChainRequested();
+ if (logicalChainNew)
+ {
+ TAudioState audioStateNew = logicalChainNew->StreamState();
+ if (
+ (audioStateNew == EActive ) ||
+ (audioStateNew == EPrimed) ||
+ (audioStateNew == EIdle)
+
+ )
+ {
+ TInt contextId = aServerSession.ContextId( );
+ iMMRCServerInfo->PopAndRemovePausedContext(contextId);
+ }
+ }
+ }
+ if(err == KErrNone)
+ {
+ //Send request
+ if (!aServerSession.SendRequestToAdaptation(ENormalRequest))
+ {
+// TBD fail at current task.
+// return server shutting down
+ }
+ }
+
+#ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
+ if(err != KErrNone)
+ {
+ RDebug::Print(_L("!!!!CMMRCServerController::SendResourceRequest - error = %d"), err);
+ }
+#endif
+
+ DP0_RET(err, "err=%d");
+ }
+
+/**
+ * Send a preemption request to the adaptation
+ * @param MLogicalChain* aOldChain
+ * @param MLogicalChain* aNewChain
+ * @return KerrNone in case of success of the process
+ */
+TInt CMMRCServerController::SendPreemptionRequest( CMMRCServerSession& aServerSession )
+ {
+ DP_CONTEXT(----> CMMRCServerController::SendPreemptionRequest *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ iMMRCServerInfo->SwitchServerState( EMMRCServerStateWaitPreemptionResponse, aServerSession.ContextId() );
+
+ //Update logical chains
+ TRAPD(err, aServerSession.StartPreemptionL());
+
+
+ if(err == KErrNone)
+ {
+ //Send request
+ if (!aServerSession.SendRequestToAdaptation(EPreemptionRequest))
+ {
+ // TBD fail at current task.
+ // return server shutting down/low memory where necessary
+ }
+ }
+
+#ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
+ if(err != KErrNone)
+ {
+ RDebug::Print(_L("!!!!CMMRCServerController::SendPreemptionRequest - error = %d"), err);
+ }
+#endif
+
+ DP0_RET(err, "err=%d");
+ }
+
+/**
+ * Callback from the adaptation
+ * @param MLogicalChain* aOldChain
+ * @param MLogicalChain* aNewChain
+ * @param TMMRCAdaptationToServerRequestResults aResult
+ */
+void CMMRCServerController::AdaptationRequestAcknowledgment(CMMRCServerSession& aServerSession, TMMRCAdaptationToServerRequestResults aResult, TInt /*aError*/)
+ {
+ DP_CONTEXT(--------> CMMRCServerController::AdaptationRequestAcknowledgment *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+#ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
+ RDebug::Print(_L("size of message queue = %d"), iMMRCServerInfo->RequestsCount());
+ RDebug::Print(_L("size of inprocess queue = %d"), iMMRCServerInfo->AllocatedResourceContextsCount());
+ RDebug::Print(_L("size of paused queue = %d"), iMMRCServerInfo->AllocatedPausedContextsCount());
+#endif
+
+ TUint64 contextId;
+ TMMRCServerState serverState;
+ TInt err = KErrNone;
+ iMMRCServerInfo->ServerState(serverState, contextId);
+ switch(serverState)
+ {
+ case EMMRCServerStateWaitPreemptionResponse: // here we process the response
+ {
+ switch(aResult)
+ {
+ case EMMRCAdaptationToServerResourceComplete:
+ {
+ //we remove the request in process from the queue
+ CMMRCServerSession* serverSession = iMMRCServerInfo->PopAndRemoveFirstAllocatedResourceContext();
+ if(serverSession)
+ {
+ TRAP(err, iMMRCServerInfo->PushPausedContextL(*serverSession));
+ DP1(DLERR,"EPushPauseContextLeft %d", err);
+ __ASSERT_DEBUG(err == KErrNone, Panic(EPushPauseContextLeft));
+ }
+ //Do not wait for a client acknowledgment
+ iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
+ }
+ break;
+ case EMMRCAdaptationToServerResourceTimeout:
+ default:
+ {
+ //jjpy TODO: What if the preemption request failed?!
+ // That will be specified/implemented during the integration with the resource manager
+ //we remove the request in process from the queue
+ iMMRCServerInfo->PopAndRemoveFirstAllocatedResourceContext();
+ }
+ } // end switch(aResult)
+ } //end case EMMRCServerStateWaitPreemptionResponse
+ break;
+ case EMMRCServerStateWaitResourceResponseFromAdaptation: // here we process the response
+ {
+ switch(aResult)
+ {
+ case EMMRCAdaptationToServerResourceComplete:
+ {
+ CMMRCServerSession* serverSessionAllocatedResource = iMMRCServerInfo->PopFirstAllocatedResourceContext();
+ if( serverSessionAllocatedResource ) //If some previously some context has allocated a resource
+ {
+ //check if same context, if not it might be an error
+ TAudioContextId contextId = aServerSession.ContextId( );
+ TAudioContextId contextIdAllocatedResource = serverSessionAllocatedResource->ContextId( );
+ #ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
+ RDebug::Print(_L("contextId = %d"), contextId.Id());
+ RDebug::Print(_L("contextIdAllocatedResource = %d"), contextIdAllocatedResource.Id());
+ #endif
+ MLogicalChain* logicalChainNew = aServerSession.LogicalChainRequested();
+ MLogicalChain* logicalChainOld = aServerSession.LogicalChainLastCommited();
+ TAudioState audioStateNew = logicalChainNew->StreamState ( );
+ if(contextId != contextIdAllocatedResource)
+ {
+ //it is ok if the rule said process always
+ MLogicalChain* logicalChainUsingResource = serverSessionAllocatedResource->LogicalChainLastCommited();
+ TAudioState audioStateAllocatedResource = logicalChainUsingResource->StreamState();
+ TAudioState audioStateNew = logicalChainNew->StreamState ( );
+ TMMRCRule rule = DecisionRule(audioStateAllocatedResource, audioStateNew);
+ if( rule != EAlwaysProcess )
+ {
+ //not possible in theory... this is an error
+ #ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
+ RDebug::Print(_L("!!!!CMMRCServerController::AdaptationRequestAcknowledgment - contextId allocating a resource and new request different. Should be the same!"), iMMRCServerInfo->AllocatedResourceContextsCount());
+ #endif
+ }
+ }
+ else //same context here, so check if the resource has been deallocated
+ {
+ // in case of stop etc. remove from in process request
+ //now check the reason
+ TAudioState audioStateOld = EUninitialized;
+ if(logicalChainOld)
+ {
+ audioStateOld = logicalChainOld->StreamState();
+ }
+ TReason reason = ActionReason(audioStateOld, audioStateNew);
+
+ if (reason == ELoad)
+ {
+ iARNNotificationObject->Cancel();
+ iMMRCServerInfo->PopAndRemovePausedContext(contextId);
+ }
+ else if (reason == EUnload)
+ {
+ iARNNotificationObject->Initialize();
+ iMMRCServerInfo->PopAndRemoveFirstAllocatedResourceContextByContextId(contextId);
+ }
+ }
+ }
+ else //no in process request locking a resource
+ {
+ MLogicalChain* logicalChainNew = aServerSession.LogicalChainRequested();
+ MLogicalChain* logicalChainOld = aServerSession.LogicalChainLastCommited();
+ TAudioState audioStateNew = logicalChainNew->StreamState ( );
+ TAudioState audioStateOld = EUninitialized;
+ if(logicalChainOld)
+ {
+ audioStateOld = logicalChainOld->StreamState();
+ }
+ TReason reason = ActionReason(audioStateOld, audioStateNew);
+ if( reason == ELoad ||
+ reason == EPrimeReason ||
+ reason == EActivate )
+ {
+ TRAP(err, iMMRCServerInfo->PushAllocatedResourceContextL( aServerSession ));
+ DP1(DLERR,"EPushAllocatedResourceContextFailed %d", err);
+ __ASSERT_DEBUG(err == KErrNone, Panic(EPushAllocatedResourceContextFailed));
+ }
+ }
+ iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
+ }
+ break;
+ case EMMRCAdaptationToServerResourceTimeout:
+ default:
+ {
+ //Just switch the state
+ iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
+ }
+ break;
+ } //end switch switch(aResult)
+ } // end case EMMRCServerStateWaitResourceResponseFromAdaptation
+ break;
+ case EMMRCServerStateIdle: //not possible....
+ default:
+ break;
+ }
+
+ TRAP(err, ProcessNextRequestL());
+ DP1(DLERR,"EProcessNextRequestLeft %d", err);
+ __ASSERT_DEBUG(err == KErrNone, Panic(EProcessNextRequestLeft));
+ DP_OUT();
+ }
+
+/*
+ *
+ */
+void CMMRCServerController::NotifyPausedClientsResourceUnallocated()
+ {
+ DP_CONTEXT(----> CMMRCServerController::NotifyClientsResourceUnallocated *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ CMMRCServerSession* serverSession = iMMRCServerInfo->PopAndRemoveFirstPausedContext( );
+ while( serverSession )
+ {
+ serverSession->NotifyClientResourceUnallocated();
+ serverSession = iMMRCServerInfo->PopAndRemoveFirstPausedContext( );
+ }
+
+ DP_OUT();
+ }
+
+/*
+ *
+ */
+void CMMRCServerController::CloseSessionByContextId(TInt32 aContextId)
+ {
+ DP_CONTEXT(----> CMMRCServerController::CloseSessionByContextId *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ while( iMMRCServerInfo->PopAndRemoveFirstAllocatedResourceContextByContextId( aContextId ) ){}
+ while( iMMRCServerInfo->PopAndRemoveFirstRequestByContextId( aContextId ) ){}
+ while( iMMRCServerInfo->PopAndRemovePausedContext( aContextId ) ){}
+ while( iMMRCServerInfo->PopAndRemoveFirstAPRContextByContextId( aContextId ) ){}
+ TUint64 contextId;
+ TMMRCServerState serverState;
+ iMMRCServerInfo->ServerState(serverState, contextId);
+ if( contextId == aContextId)
+ {
+ iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
+ }
+#ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
+ RDebug::Print(_L("size of message queue = %d"), iMMRCServerInfo->RequestsCount());
+ RDebug::Print(_L("size of inprocess queue = %d"), iMMRCServerInfo->AllocatedResourceContextsCount());
+ RDebug::Print(_L("size of paused queue = %d"), iMMRCServerInfo->AllocatedPausedContextsCount());
+ RDebug::Print(_L("size of APR queue = %d"), iMMRCServerInfo->AllocatedAPRContextsCount());
+#endif
+
+ DP_OUT();
+ }
+
+/*
+ *
+ */
+void CMMRCServerController::ServerState(TMMRCServerState& aServerState, TUint64& aContextId) const
+ {
+ iMMRCServerInfo->ServerState(aServerState, aContextId);
+ }
+
+/**
+
+*/
+TInt CMMRCServerController::EnqueueRequestForAPRL(CMMRCServerSession& aServerSession)
+ {
+ DP_CONTEXT(----> CMMRCServerController::EnqueueRequestForAPRL *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ //add the request to the queue
+ TInt err = KErrNone;
+ //if already there, should return KErrAlreadyExists
+
+ if (iMMRCServerInfo->IsOnAPRList(aServerSession.ContextId()))
+ {
+ err = KErrAlreadyExists;
+ }
+ else
+ {
+ iMMRCServerInfo->PushAPRContextL(aServerSession);
+ }
+ DP0_RET(err, "err=%d");
+ }
+
+/**
+
+*/
+TInt CMMRCServerController::RemoveRequestForAPR(CMMRCServerSession& aServerSession)
+ {
+ DP_CONTEXT(----> CMMRCServerController::RemoveRequestForAPR *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ TInt err = KErrNone;
+ TInt32 iContextId = aServerSession.ContextId();
+ TBool iIsOnAPRList = iMMRCServerInfo->IsOnAPRList(iContextId);
+ if(iIsOnAPRList)
+ {
+
+ // Its possible that the remove request has occured whilst clients are being notified that the resource is available
+ // Check if a notification sequence is currently under way
+ if ( iARNNotificationObject->IsActive() )
+ {
+
+ // Iterate through each paused client
+ for ( TInt index = 0 ; index < iMMRCServerInfo->AllocatedPausedContextsCount() ; index++ )
+ {
+
+ // Find the client that has requested removal in the list
+ TAudioContextId id = iMMRCServerInfo->PausedContextByIndex(index)->ContextId();
+ if ( aServerSession.ContextId() == id )
+ {
+ // Object has already received a notification
+ if ( index < iARNNotificationObject->iIndex )
+ {
+ // decrement the notification objects list index to account for the item that will be removed from the queue
+ --iARNNotificationObject->iIndex;
+ }
+
+ // no action needs to be taken if
+ // index >= iMMRCServerInfo.iIndex
+
+ break;
+ }
+ }
+
+ }
+
+ iMMRCServerInfo->PopAndRemoveFirstAPRContextByContextId(iContextId);
+ iMMRCServerInfo->PopAndRemovePausedContext(iContextId); //removing this session from the list of paused too.
+ }
+ else
+ {
+ err = KErrCancel;
+ }
+
+ DP0_RET(err, "err=%d");
+ }
+
+/**
+
+*/
+TInt CMMRCServerController::WillResumePlay()
+ {
+ DP_CONTEXT(----> CMMRCServerController::WillResumePlay *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ TInt err = KErrNone;
+ iARNNotificationObject->Cancel();
+
+
+ DP0_RET(err, "err=%d");
+ }
+
+
+//From CActive
+/**
+ * Constructor.
+ */
+CARNNotificationObject::CARNNotificationObject(const TInt aPriority)
+:CActive(aPriority)
+ {
+ TRACE_CREATE();
+ DP_CONTEXT(----> CARNNotificationObject::CARNNotificationObject *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+
+ DP_OUT();
+ }
+
+
+/**
+ * Destructor.
+ */
+CARNNotificationObject::~CARNNotificationObject()
+ {
+ DP_CONTEXT(----> CARNNotificationObject::~CARNNotificationObject *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ Cancel();
+ iTimer.Close();
+ delete iMMRCServerInfo;
+
+ DP_OUT();
+ }
+
+
+/**
+ CARNNotificationObject::ConstructL
+ Symbian 2nd phase constructor can leave.
+ */
+void CARNNotificationObject::ConstructL(CMMRCServerInfo& aMMRCServerInfo)
+ {
+ DP_CONTEXT(----> CARNNotificationObject::ConstructL *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ iMMRCServerInfo = &aMMRCServerInfo;
+ CActiveScheduler::Add(this);
+ User::LeaveIfError(iTimer.CreateLocal());
+
+
+ DP_OUT();
+ }
+
+// ---------------------------------------------------------------------------
+// CARNNotificationObject::NewL
+// ---------------------------------------------------------------------------
+CARNNotificationObject* CARNNotificationObject::NewL(const TInt aPriority, CMMRCServerInfo& aMMRCServerInfo)
+ {
+ DP_STATIC_CONTEXT(----> CARNNotificationObject::NewL *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ CARNNotificationObject* self = new(ELeave)CARNNotificationObject(aPriority);
+ CleanupStack::PushL(self);
+ self->ConstructL(aMMRCServerInfo);
+ CleanupStack::Pop(self);
+
+ DP0_RET(self, "0x%x");
+ }
+
+// ---------------------------------------------------------------------------
+// CARNNotificationObject::RunL
+// ---------------------------------------------------------------------------
+void CARNNotificationObject::RunL()
+ {
+ DP_CONTEXT(CARNNotificationObject::RunL *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ #if defined(_DEBUG) && defined(__WINS__)
+ const TTimeIntervalMicroSeconds32 KTimer = 1.8*1000000; // 1.8 seconds
+ #else
+ const TTimeIntervalMicroSeconds32 KTimer = 800000; // 0.8 seconds
+ #endif
+
+ TInt numPausedContext = iMMRCServerInfo->AllocatedPausedContextsCount();
+
+ // The list may have been modified whilst the AO was asleep, need to check that:
+ // 1) iIndex is still in range
+ // 2) the object at that location should still receive a notification
+
+ if ( (iIndex > -1) && (iIndex < numPausedContext) )
+ {
+ CMMRCServerSession* mmrcSession = iMMRCServerInfo->PausedContextByIndex(iIndex);
+
+ TAudioContextId id = mmrcSession->ContextId( );
+ TBool isOnAPRList = iMMRCServerInfo->IsOnAPRList(id);
+ if(isOnAPRList)
+ {
+ mmrcSession->NotifyClientResourceUnallocated();
+ }
+
+
+ for(TInt aux = iIndex + 1; aux < numPausedContext ; aux++)
+ {
+ mmrcSession = iMMRCServerInfo->PausedContextByIndex(aux);
+ id = mmrcSession->ContextId( );
+ isOnAPRList = iMMRCServerInfo->IsOnAPRList(id);
+ if(isOnAPRList)
+ {
+ iIndex = aux;
+ After(KTimer);
+ break;
+ }
+ }
+ }
+
+ else
+ {
+ iIndex = 0;
+ }
+
+ DP_OUT();
+ }
+
+// ---------------------------------------------------------------------------
+// CARNNotificationObject::After
+// ---------------------------------------------------------------------------
+void CARNNotificationObject::After(TTimeIntervalMicroSeconds32 aInterval)
+ {
+ DP_CONTEXT(CARNNotificationObject::After *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ Cancel();
+ iTimer.After(iStatus,aInterval);
+ SetActive();
+
+ DP_OUT();
+ }
+
+// ---------------------------------------------------------------------------
+// CARNNotificationObject::Initialize
+// ---------------------------------------------------------------------------
+void CARNNotificationObject::Initialize()
+ {
+ DP_CONTEXT(CARNNotificationObject::Initialize *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ #if defined(_DEBUG) && defined(__WINS__)
+ const TTimeIntervalMicroSeconds32 KTimer = 1.8*1000000; // 1.8 seconds
+ #else
+ const TTimeIntervalMicroSeconds32 KTimer = 800000; // 0.8 seconds
+ #endif
+
+ TInt numPausedContext = iMMRCServerInfo->AllocatedPausedContextsCount();
+ iIndex = 0;
+ CMMRCServerSession* mmrcSession = NULL;
+
+ if(numPausedContext) // don't bother if zero.
+ {
+ for(TInt i(0); i<numPausedContext ; ++i)
+ {
+ mmrcSession = iMMRCServerInfo->PausedContextByIndex(i);
+ TAudioContextId id = mmrcSession->ContextId( );
+ TBool isOnAPRList = iMMRCServerInfo->IsOnAPRList(id);
+ if(isOnAPRList)
+ {
+ iIndex = i;
+ After(KTimer);
+ break;
+ }
+ }
+ }
+
+ DP_OUT();
+ }
+
+// ---------------------------------------------------------------------------
+// CMMRCServer::DoCancel
+// ---------------------------------------------------------------------------
+void CARNNotificationObject::DoCancel()
+ {
+ DP_CONTEXT(CARNNotificationObject::DoCancel *CD1*, CtxDevSound, DPLOCAL);
+ DP_IN();
+
+ iTimer.Cancel();
+
+ DP_OUT();
+ }
+
+
+void CMMRCServerController::Panic(TMMRCServerControllerPanicCodes aCode)
+ {
+ User::Panic(KMMRCServerControllerPanicCategory, aCode);
+ }
+//EOF