mmresourcemgmt/mmresctrl/src/mmrcserver/mmrcservercontroller.cpp
changeset 0 79dd3e2336a0
equal deleted inserted replaced
-1:000000000000 0:79dd3e2336a0
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "mmrcservercontroller.h"
       
    17 #include "mmrcerrorcodes.h"
       
    18 #include "mmrcserversession.h"
       
    19 #include "mmrcserverinfo.h"
       
    20 #include "mmrcserverrulemanager.h"
       
    21 #include "mmrcadaptationproxy.h"
       
    22 #include "mlogicalchain.h"
       
    23 #include <a3f/audioprocessingunittypeuids.h>
       
    24 
       
    25 /**
       
    26 @internalComponent
       
    27 
       
    28 This class implements a timer. 
       
    29 */	
       
    30 class CARNNotificationObject : public CActive
       
    31 	{
       
    32 	
       
    33 public:
       
    34 	static CARNNotificationObject* NewL(const TInt aPriority, CMMRCServerInfo& aMMRCServerInfo);
       
    35 	~CARNNotificationObject();
       
    36 	void After(TTimeIntervalMicroSeconds32 aInterval);
       
    37 	void Initialize();
       
    38 	
       
    39 protected:
       
    40 	void RunL();
       
    41 	void DoCancel();
       
    42 
       
    43 private:
       
    44 	CARNNotificationObject(const TInt aPriority);
       
    45 	void ConstructL(CMMRCServerInfo& aMMRCServerInfo);
       
    46 
       
    47 public:
       
    48 	TInt iIndex;
       
    49 	
       
    50 protected:
       
    51 	RTimer	iTimer;
       
    52 	CMMRCServerInfo*  iMMRCServerInfo;
       
    53 	};
       
    54 	
       
    55 //------------------------------------------------------------------------------------
       
    56 //
       
    57 //------------------------------------------------------------------------------------
       
    58 
       
    59 /**
       
    60  * Constructor
       
    61  */
       
    62 CMMRCServerController::CMMRCServerController()
       
    63 	{
       
    64 	TRACE_CREATE();
       
    65 	DP_CONTEXT(----> CMMRCServerController::CMMRCServerController *CD1*, CtxDevSound, DPLOCAL);
       
    66 	DP_IN();
       
    67 	
       
    68 	DP_OUT();
       
    69 	}
       
    70 
       
    71 /**
       
    72  * Destructor
       
    73  */
       
    74 CMMRCServerController::~CMMRCServerController()
       
    75 	{
       
    76 	DP_CONTEXT(----> CMMRCServerController::~CMMRCServerController *CD1*, CtxDevSound, DPLOCAL);
       
    77 	DP_IN();
       
    78 	
       
    79 	delete iMMRCServerInfo;
       
    80 	delete iMMRCServerRuleManager;
       
    81 	delete iARNNotificationObject;
       
    82 	
       
    83 	DP_OUT();
       
    84 	}
       
    85 
       
    86 /**
       
    87  * Constructs, and returns a pointer to, a new CMMRCServerController object.
       
    88  * Leaves on failure.
       
    89  * @return CMMRCServerController* A pointer to newly created utlitly object.
       
    90  */		
       
    91 CMMRCServerController* CMMRCServerController::NewL()
       
    92 	{
       
    93 	DP_STATIC_CONTEXT(----> CMMRCServerController::NewL *CD1*, CtxDevSound, DPLOCAL);
       
    94 	DP_IN();
       
    95 	
       
    96 	CMMRCServerController* self = NewLC();
       
    97 	CleanupStack::Pop(self);
       
    98 	
       
    99 	DP0_RET(self, "self = 0x%x");
       
   100 	}
       
   101 	
       
   102 /**
       
   103  * Constructs, leaves object on the cleanup stack, and returns a pointer
       
   104  * to, a new CMMRCServerController object.
       
   105  * Leaves on failure.
       
   106  * @return CMMRCServerController* A pointer to newly created utlitly object.
       
   107  */	
       
   108 CMMRCServerController* CMMRCServerController::NewLC()
       
   109 	{
       
   110 	DP_STATIC_CONTEXT(----> CMMRCServerController::NewLC *CD1*, CtxDevSound, DPLOCAL);
       
   111 	DP_IN();
       
   112 	
       
   113 	CMMRCServerController* self = new(ELeave) CMMRCServerController();
       
   114 	CleanupStack::PushL(self);
       
   115 	self->ConstructL();
       
   116 	
       
   117 	DP0_RET(self, "self = 0x%x");
       
   118 	}
       
   119 	
       
   120 /**
       
   121  * CMMRCServerController::ConstructL
       
   122  * Symbian 2nd phase constructor can leave.
       
   123  */
       
   124 void CMMRCServerController::ConstructL()
       
   125 	{
       
   126 	DP_CONTEXT(----> CMMRCServerController::ConstructL *CD1*, CtxDevSound, DPLOCAL);
       
   127 	DP_IN();
       
   128 	
       
   129 	iMMRCServerInfo = CMMRCServerInfo::NewL(*this);
       
   130 	iMMRCServerRuleManager = CMMRCServerRuleManager::NewL(*this);
       
   131 	iARNNotificationObject = CARNNotificationObject::NewL(0, *iMMRCServerInfo); //Check the value
       
   132 	
       
   133 	DP_OUT();
       
   134 	}
       
   135 
       
   136 /**
       
   137 * Process the request pointer by a specific session
       
   138 * @param CMMRCServerSession& aServerSession
       
   139 * @return KerrNone in case of success of the process
       
   140 */
       
   141 TInt CMMRCServerController::EnqueueRequestL(CMMRCServerSession& aServerSession)
       
   142 	{
       
   143 	DP_CONTEXT(----> CMMRCServerController::ProcessRequestL *CD1*, CtxDevSound, DPLOCAL);
       
   144 	DP_IN();
       
   145 	
       
   146 	//add the request to the queue
       
   147 	iMMRCServerInfo->PushRequestL(aServerSession);
       
   148 	TInt err = ProcessNextRequestL();
       
   149 	
       
   150 	DP0_RET(err, "err=%d");
       
   151 	}
       
   152 
       
   153 /**
       
   154  * Process the first request with the highest priority from the FIFO queue
       
   155  * @return KerrNone in case of success of the process
       
   156  */
       
   157  TInt CMMRCServerController::ProcessNextRequestL()
       
   158 	{
       
   159 	DP_CONTEXT(--------> CMMRCServerController::ProcessNextRequestL *CD1*, CtxDevSound, DPLOCAL);
       
   160 	DP_IN();
       
   161 	
       
   162 	TInt err = KErrNone;
       
   163 
       
   164 	TUint64 contextId;
       
   165 	TMMRCServerState serverState;
       
   166 	iMMRCServerInfo->ServerState(serverState, contextId);
       
   167 #ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING
       
   168 		RDebug::Print(_L("serverState    = %d"),  serverState);
       
   169 		RDebug::Print(_L("size of message queue    = %d"),  iMMRCServerInfo->RequestsCount());
       
   170 		RDebug::Print(_L("size of inprocess queue = %d"),  iMMRCServerInfo->AllocatedResourceContextsCount());
       
   171 		RDebug::Print(_L("size of paused queue = %d"),  iMMRCServerInfo->AllocatedPausedContextsCount());
       
   172 #endif
       
   173 	if(EMMRCServerStateIdle != serverState)
       
   174 		{
       
   175 		DP0_RET(KErrNone, "%d");
       
   176 		}
       
   177 	
       
   178 	CMMRCServerSession* serverSession = iMMRCServerInfo->PopAndRemoveFirstRequest(); //PopAndRemoveRequestFirstHighestPriority();
       
   179 	//Pop the next next commited message with the highest priority
       
   180 	if( NULL == serverSession )
       
   181 		{
       
   182 		DP0_RET(KErrNone, "%d");
       
   183 		}
       
   184 	
       
   185 	if (!serverSession->HasUserEnvironmentCapability())
       
   186 		{
       
   187 		/* Check to see if it's a record use case and in IDLE, Active, or PRIME.
       
   188 		// in which case you should refuse the request for reasons 
       
   189 		KErrPermissionDenied
       
   190 		*/
       
   191 		MLogicalChain* requestedChange = serverSession->LogicalChainRequestedStack();
       
   192 		if ((requestedChange!=NULL) && (requestedChange->StreamState() > EInitialized)) // trying to play
       
   193 			{
       
   194 			TInt count = requestedChange->AudioProcessingUnitsCount();
       
   195 			for (TInt i=0; i<count; ++i)
       
   196 				{
       
   197 				if (KUidAudioDeviceSource == requestedChange->AudioProcessingUnitUid(i))
       
   198 					{		
       
   199 					serverSession->NotifyClientOfError(KErrPermissionDenied);
       
   200 					// The following return value, doesn't actually make it back to the client
       
   201 					// We do however Notify the client above using NotifyClientOfError()
       
   202 					DP0_RET(KErrPermissionDenied, "%d");
       
   203 					}
       
   204 				}			
       
   205 			}
       
   206 
       
   207 		}
       
   208 	
       
   209 	//Pop the last commited message in process = the current resource in use
       
   210 	CMMRCServerSession* serverSessionAllocatedResource = iMMRCServerInfo->PopFirstAllocatedResourceContext();
       
   211 	//If no resource locked...
       
   212 	if( NULL == serverSessionAllocatedResource )
       
   213 		{
       
   214 		
       
   215 		err = SendResourceRequest ( *serverSession );
       
   216 		}
       
   217 	else //If a resource has been allocated or is used, possibly preemption
       
   218 		{
       
   219 		TAudioContextId contextId = serverSession->ContextId( );
       
   220 		TAudioContextId contextIdAllocatedResource = serverSessionAllocatedResource->ContextId( );
       
   221 	#ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING	
       
   222 			RDebug::Print(_L("contextId          = %d"),  contextId.Id());
       
   223 			RDebug::Print(_L("contextIdAllocatedResource = %d"),  contextIdAllocatedResource.Id());
       
   224 	#endif
       
   225 
       
   226 		//in case of processing the same context, remove the last committed request from the queue
       
   227 		// of in-process request to avoid preemption within the same context.
       
   228 		if(contextId == contextIdAllocatedResource)
       
   229 			{
       
   230 			err = SendResourceRequest ( *serverSession );
       
   231 			}
       
   232 		else // maybe preemption
       
   233 			{
       
   234 			//Pop the rule
       
   235 			
       
   236 			MLogicalChain* logicalChainUsingResource = serverSessionAllocatedResource->LogicalChainLastCommited();
       
   237 			MLogicalChain* logicalChainNew = serverSession->LogicalChainRequestedStack();
       
   238 			//Should not/cannot be null! 
       
   239 			if( NULL==logicalChainUsingResource || NULL==logicalChainNew )
       
   240 				{
       
   241 			#ifdef _DEBUG	
       
   242 					RDebug::Print(_L("!!!!CMMRCServerController::ProcessNextRequestL - logicalChainUsingResource or logicalChainNew NULL"));
       
   243 					ASSERT(0);
       
   244 			#endif
       
   245 				User::Leave(EMMRCErrorLogicalChainNull);
       
   246 				}
       
   247 			
       
   248 			TAudioState audioStateAllocatedResource = logicalChainUsingResource->StreamState();
       
   249 			TAudioState audioStateNew = logicalChainNew->StreamState ( );
       
   250 			TMMRCRule rule = DecisionRule(audioStateAllocatedResource, audioStateNew);
       
   251 			//Process according to the rule
       
   252 			if( rule == EAlwaysProcess )
       
   253 				{
       
   254 				err = SendResourceRequest( *serverSession );
       
   255 				}
       
   256 			else // process only in case of higher priority
       
   257 				{
       
   258 				TInt currentClientPriority = logicalChainUsingResource->Priority();
       
   259 				TInt newClientPriority = logicalChainNew->Priority();
       
   260 				TBool currentClient_HasMMDD = serverSessionAllocatedResource->HasMultimediaCapability();
       
   261 				TBool newClient_HasMMDD = serverSession->HasMultimediaCapability();
       
   262 
       
   263 				// If new client has multimedia capability and current doesn't have, 
       
   264 				// priorities don't matter preempt the current client
       
   265 				
       
   266 				// But if both are equal competitors (both has MMDD capability or both hasn't)
       
   267 				// and the newcomer has higher priority preempt too
       
   268 				if ( (!currentClient_HasMMDD && newClient_HasMMDD)  || 
       
   269 					( (currentClient_HasMMDD == newClient_HasMMDD) && 
       
   270 					  (newClientPriority > currentClientPriority) ) )
       
   271 					{
       
   272 					//The process is delayed. First we have to preempt the current inprocess resource
       
   273 					// so puch back the request (its session)
       
   274 					iMMRCServerInfo->PushRequestL(*serverSession);
       
   275 					//
       
   276 					//send a premption message to the last commited message session
       
   277 					err = SendPreemptionRequest ( *serverSessionAllocatedResource );
       
   278 					}
       
   279 				else 
       
   280 					{
       
   281 					// Deny the resource
       
   282 					TAudioContextId iId = serverSession->ContextId( );
       
   283 					TBool iIsOnPauseList = iMMRCServerInfo->IsOnPauseList(iId);
       
   284 					if(!iIsOnPauseList)
       
   285 						{
       
   286 						iMMRCServerInfo->PushPausedContextL(*serverSession);
       
   287 						}
       
   288 // nothing pending, deny resources, and notify client.						
       
   289 					serverSession->AdaptationRequestAcknowledgment(EMMRCAdaptationToServerResourceIncomplete, KErrInUse);
       
   290 // Server is back to idle.
       
   291 					iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
       
   292 					}
       
   293 				}
       
   294 			}
       
   295 		}
       
   296 	
       
   297 #ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING	
       
   298 	if(err != KErrNone)
       
   299 		{
       
   300 		RDebug::Print(_L("!!!!CMMRCServerController::ProcessNextRequestL - error = %d"), err);
       
   301 		}
       
   302 #endif
       
   303 	
       
   304 	DP0_RET(err, "err=%d");
       
   305 	}
       
   306 
       
   307 /**
       
   308  * Pop the decision rule on the base of the current in-process request and a new committed request
       
   309  * @param TAudioState aAudioStateAllocatedResource
       
   310  * @param TAudioState aAudioStateRequiringProcess
       
   311  * @return TMMRCRule
       
   312  */
       
   313 TMMRCRule CMMRCServerController::DecisionRule(TAudioState aAudioStateAllocatedResource, TAudioState aAudioStateRequiringProcess)
       
   314 	{
       
   315 	DP_CONTEXT(----> CMMRCServerController::DecisionRule *CD1*, CtxDevSound, DPLOCAL);
       
   316 	DP_IN();
       
   317 	
       
   318 	TMMRCRule rule = iMMRCServerRuleManager->DecisionRule(aAudioStateAllocatedResource, aAudioStateRequiringProcess);
       
   319 	
       
   320 	DP0_RET(rule, "rule=%d");
       
   321 	}
       
   322 
       
   323 /**
       
   324  * Pop the action reason on the base of the last committed request and the current one
       
   325  * @param TAudioState aAudioStateLastCommitted
       
   326  * @param TAudioState aAudioStateRequested
       
   327  * @return TReason
       
   328  */
       
   329 TReason CMMRCServerController::ActionReason(TAudioState aAudioStateLastCommitted, TAudioState aAudioStateRequested)
       
   330 	{
       
   331 	DP_CONTEXT(----> CMMRCServerController::ActionReason *CD1*, CtxDevSound, DPLOCAL);
       
   332 	DP_IN();
       
   333 	
       
   334 	TReason reason = iMMRCServerRuleManager->ActionReason(aAudioStateLastCommitted, aAudioStateRequested);
       
   335 	
       
   336 	DP0_RET(reason, "reason=%d");
       
   337 	}
       
   338 
       
   339 /**
       
   340  * Send a resource request to the adaptation
       
   341  * @param MLogicalChain* aOldChain
       
   342  * @param MLogicalChain* aNewChain
       
   343  * @return KerrNone in case of success of the process
       
   344  */
       
   345 TInt CMMRCServerController::SendResourceRequest( CMMRCServerSession& aServerSession )
       
   346 	{
       
   347 	DP_CONTEXT(----> CMMRCServerController::SendResourceRequest *CD1*, CtxDevSound, DPLOCAL);
       
   348 	DP_IN();
       
   349 	
       
   350 	iMMRCServerInfo->SwitchServerState( EMMRCServerStateWaitResourceResponseFromAdaptation, aServerSession.ContextId() );
       
   351 
       
   352 // if entering APR state, remove from Paused list.
       
   353 	TRAPD(err, aServerSession.StartProcessL());
       
   354 	{
       
   355 	MLogicalChain* logicalChainNew = aServerSession.LogicalChainRequested();
       
   356 	if (logicalChainNew)
       
   357 		{
       
   358 		TAudioState audioStateNew = logicalChainNew->StreamState();
       
   359 		if ( 
       
   360 			(audioStateNew == EActive ) || 
       
   361 			(audioStateNew == EPrimed) || 
       
   362 			(audioStateNew == EIdle) 
       
   363 			
       
   364 			)
       
   365 			{
       
   366 			TInt contextId = aServerSession.ContextId( );
       
   367 			iMMRCServerInfo->PopAndRemovePausedContext(contextId);
       
   368 			}
       
   369 		}
       
   370 	}
       
   371 	if(err == KErrNone)
       
   372 		{
       
   373 		//Send request
       
   374 		if (!aServerSession.SendRequestToAdaptation(ENormalRequest))
       
   375 			{
       
   376 // TBD fail at current task.
       
   377 // return server shutting down			
       
   378 			}
       
   379 		}
       
   380 	
       
   381 #ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING	
       
   382 	if(err != KErrNone)
       
   383 		{
       
   384 		RDebug::Print(_L("!!!!CMMRCServerController::SendResourceRequest - error = %d"), err);
       
   385 		}
       
   386 #endif
       
   387 	
       
   388 	DP0_RET(err, "err=%d");
       
   389 	}
       
   390 
       
   391 /** 
       
   392  * Send a preemption request to the adaptation
       
   393  * @param MLogicalChain* aOldChain
       
   394  * @param MLogicalChain* aNewChain
       
   395  * @return KerrNone in case of success of the process
       
   396  */
       
   397 TInt CMMRCServerController::SendPreemptionRequest( CMMRCServerSession& aServerSession )
       
   398 	{
       
   399 	DP_CONTEXT(----> CMMRCServerController::SendPreemptionRequest *CD1*, CtxDevSound, DPLOCAL);
       
   400 	DP_IN();
       
   401 	
       
   402 	iMMRCServerInfo->SwitchServerState( EMMRCServerStateWaitPreemptionResponse, aServerSession.ContextId() );
       
   403 
       
   404 	//Update logical chains
       
   405 	TRAPD(err, aServerSession.StartPreemptionL());
       
   406 		
       
   407 	
       
   408 	if(err == KErrNone)
       
   409 		{
       
   410 	//Send request
       
   411 		if (!aServerSession.SendRequestToAdaptation(EPreemptionRequest))
       
   412 			{
       
   413 	// TBD fail at current task.
       
   414 	// return server shutting down/low memory where necessary			
       
   415 			}
       
   416 		}
       
   417 	
       
   418 #ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING	
       
   419 	if(err != KErrNone)
       
   420 		{
       
   421 		RDebug::Print(_L("!!!!CMMRCServerController::SendPreemptionRequest - error = %d"), err);
       
   422 		}
       
   423 #endif
       
   424 
       
   425 	DP0_RET(err, "err=%d");
       
   426 	}
       
   427 
       
   428 /** 
       
   429  * Callback from the adaptation
       
   430  * @param MLogicalChain* aOldChain
       
   431  * @param MLogicalChain* aNewChain
       
   432  * @param TMMRCAdaptationToServerRequestResults aResult
       
   433  */
       
   434 void CMMRCServerController::AdaptationRequestAcknowledgment(CMMRCServerSession& aServerSession, TMMRCAdaptationToServerRequestResults aResult, TInt /*aError*/)
       
   435 	{
       
   436 	DP_CONTEXT(--------> CMMRCServerController::AdaptationRequestAcknowledgment *CD1*, CtxDevSound, DPLOCAL);
       
   437 	DP_IN();
       
   438 #ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING	
       
   439 		RDebug::Print(_L("size of message queue    = %d"),  iMMRCServerInfo->RequestsCount());
       
   440 		RDebug::Print(_L("size of inprocess queue = %d"),  iMMRCServerInfo->AllocatedResourceContextsCount());
       
   441 		RDebug::Print(_L("size of paused queue = %d"),  iMMRCServerInfo->AllocatedPausedContextsCount());
       
   442 #endif
       
   443 	
       
   444 	TUint64 contextId;
       
   445 	TMMRCServerState serverState;
       
   446 	TInt err = KErrNone;
       
   447 	iMMRCServerInfo->ServerState(serverState, contextId);
       
   448 	switch(serverState)
       
   449 		{
       
   450 		case EMMRCServerStateWaitPreemptionResponse: // here we process the response
       
   451 			{
       
   452 			switch(aResult)
       
   453 				{
       
   454 				case EMMRCAdaptationToServerResourceComplete:
       
   455 					{
       
   456 					//we remove the request in process from the queue
       
   457 					CMMRCServerSession* serverSession = iMMRCServerInfo->PopAndRemoveFirstAllocatedResourceContext();
       
   458 					if(serverSession)
       
   459 						{
       
   460 						TRAP(err, iMMRCServerInfo->PushPausedContextL(*serverSession));
       
   461 						DP1(DLERR,"EPushPauseContextLeft %d", err);
       
   462 						__ASSERT_DEBUG(err == KErrNone, Panic(EPushPauseContextLeft));
       
   463 						}
       
   464 					//Do not wait for a client acknowledgment
       
   465 					iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
       
   466 					}
       
   467 				break;
       
   468 				case EMMRCAdaptationToServerResourceTimeout:
       
   469 				default:
       
   470 					{
       
   471 					//jjpy TODO: What if the preemption request failed?!
       
   472 					// That will be specified/implemented during the integration with the resource manager
       
   473 					//we remove the request in process from the queue
       
   474 					iMMRCServerInfo->PopAndRemoveFirstAllocatedResourceContext();
       
   475 					}
       
   476 				} // end switch(aResult)
       
   477 			} //end case EMMRCServerStateWaitPreemptionResponse
       
   478 		break;
       
   479 		case EMMRCServerStateWaitResourceResponseFromAdaptation: // here we process the response
       
   480 			{
       
   481 			switch(aResult)
       
   482 				{
       
   483 				case EMMRCAdaptationToServerResourceComplete:
       
   484 					{
       
   485 					CMMRCServerSession* serverSessionAllocatedResource = iMMRCServerInfo->PopFirstAllocatedResourceContext();
       
   486 					if( serverSessionAllocatedResource ) //If some previously some context has allocated a resource
       
   487 						{
       
   488 					 	//check if same context, if not it might be an error
       
   489 					 	TAudioContextId contextId = aServerSession.ContextId( );
       
   490 					 	TAudioContextId contextIdAllocatedResource = serverSessionAllocatedResource->ContextId( );
       
   491 					#ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING	
       
   492 							RDebug::Print(_L("contextId          = %d"),  contextId.Id());
       
   493 							RDebug::Print(_L("contextIdAllocatedResource = %d"),  contextIdAllocatedResource.Id());
       
   494 					#endif
       
   495 						MLogicalChain* logicalChainNew = aServerSession.LogicalChainRequested();
       
   496 						MLogicalChain* logicalChainOld = aServerSession.LogicalChainLastCommited();
       
   497 						TAudioState audioStateNew = logicalChainNew->StreamState ( );
       
   498 					 	if(contextId != contextIdAllocatedResource)
       
   499 					 		{
       
   500 					 		//it is ok if the rule said process always
       
   501 							MLogicalChain* logicalChainUsingResource = serverSessionAllocatedResource->LogicalChainLastCommited();
       
   502 							TAudioState audioStateAllocatedResource = logicalChainUsingResource->StreamState();
       
   503 							TAudioState audioStateNew = logicalChainNew->StreamState ( );
       
   504 							TMMRCRule rule = DecisionRule(audioStateAllocatedResource, audioStateNew);
       
   505 					 		if( rule != EAlwaysProcess )
       
   506 					 			{
       
   507 					 			//not possible in theory... this is an error
       
   508 							#ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING	
       
   509 									RDebug::Print(_L("!!!!CMMRCServerController::AdaptationRequestAcknowledgment - contextId allocating a resource and new request different. Should be the same!"),  iMMRCServerInfo->AllocatedResourceContextsCount());
       
   510 							#endif				 		
       
   511 					 			}
       
   512 					 		}
       
   513 					 	else //same context here, so check if the resource has been deallocated
       
   514 					 		{
       
   515 						 	// in case of stop etc. remove from in process request
       
   516 						 	//now check the reason
       
   517 							TAudioState audioStateOld = EUninitialized;
       
   518 							if(logicalChainOld)
       
   519 								{
       
   520 								audioStateOld = logicalChainOld->StreamState();
       
   521 								}
       
   522 							TReason reason = ActionReason(audioStateOld, audioStateNew);
       
   523 								
       
   524 							if (reason == ELoad)
       
   525 								{
       
   526 								iARNNotificationObject->Cancel();
       
   527 								iMMRCServerInfo->PopAndRemovePausedContext(contextId);
       
   528 								}
       
   529 							else if (reason == EUnload)
       
   530 								{
       
   531 								iARNNotificationObject->Initialize();
       
   532 								iMMRCServerInfo->PopAndRemoveFirstAllocatedResourceContextByContextId(contextId);			
       
   533 								}
       
   534 					 		}
       
   535 					 	}
       
   536 					else //no in process request locking a resource
       
   537 						{
       
   538 						MLogicalChain* logicalChainNew = aServerSession.LogicalChainRequested();
       
   539 						MLogicalChain* logicalChainOld = aServerSession.LogicalChainLastCommited();
       
   540 						TAudioState audioStateNew = logicalChainNew->StreamState ( );
       
   541 						TAudioState audioStateOld = EUninitialized;
       
   542 						if(logicalChainOld)
       
   543 							{
       
   544 							audioStateOld = logicalChainOld->StreamState();
       
   545 							}
       
   546 						TReason reason = ActionReason(audioStateOld, audioStateNew);
       
   547 						if( reason == ELoad ||
       
   548 			 					reason == EPrimeReason ||
       
   549 			 					reason == EActivate )
       
   550 			 					{
       
   551 			 					TRAP(err, iMMRCServerInfo->PushAllocatedResourceContextL( aServerSession ));
       
   552 			 					DP1(DLERR,"EPushAllocatedResourceContextFailed %d", err);
       
   553 								__ASSERT_DEBUG(err == KErrNone, Panic(EPushAllocatedResourceContextFailed));
       
   554 			 					}					
       
   555 						}
       
   556 					iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
       
   557 					}
       
   558 				break;
       
   559 	 			case EMMRCAdaptationToServerResourceTimeout:
       
   560 	 			default:
       
   561 	 				{
       
   562 					//Just switch the state
       
   563 					iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
       
   564 					}
       
   565 	 			break;
       
   566 	 			} //end switch switch(aResult)
       
   567 	 		} // end case EMMRCServerStateWaitResourceResponseFromAdaptation
       
   568 	 	break;
       
   569 		case EMMRCServerStateIdle: //not possible....
       
   570 	 	default:
       
   571  	 	break;
       
   572 	 	}
       
   573  	
       
   574 	TRAP(err, ProcessNextRequestL());
       
   575 	DP1(DLERR,"EProcessNextRequestLeft %d", err);
       
   576 	__ASSERT_DEBUG(err == KErrNone, Panic(EProcessNextRequestLeft));
       
   577 	DP_OUT();
       
   578 	}
       
   579 
       
   580 /*
       
   581  * 
       
   582  */
       
   583 void CMMRCServerController::NotifyPausedClientsResourceUnallocated()
       
   584 	{
       
   585  	DP_CONTEXT(----> CMMRCServerController::NotifyClientsResourceUnallocated *CD1*, CtxDevSound, DPLOCAL);
       
   586 	DP_IN();
       
   587 	
       
   588 	CMMRCServerSession* serverSession  = iMMRCServerInfo->PopAndRemoveFirstPausedContext( );
       
   589 	while( serverSession )
       
   590 		{
       
   591 		serverSession->NotifyClientResourceUnallocated();
       
   592 		serverSession  = iMMRCServerInfo->PopAndRemoveFirstPausedContext( );
       
   593 		}
       
   594 	
       
   595 	DP_OUT();
       
   596 	}
       
   597 
       
   598 /*
       
   599  * 
       
   600  */
       
   601 void CMMRCServerController::CloseSessionByContextId(TInt32 aContextId)
       
   602 	{
       
   603  	DP_CONTEXT(----> CMMRCServerController::CloseSessionByContextId *CD1*, CtxDevSound, DPLOCAL);
       
   604 	DP_IN();
       
   605 	
       
   606 	while( iMMRCServerInfo->PopAndRemoveFirstAllocatedResourceContextByContextId( aContextId ) ){}
       
   607 	while( iMMRCServerInfo->PopAndRemoveFirstRequestByContextId( aContextId ) ){}
       
   608 	while( iMMRCServerInfo->PopAndRemovePausedContext( aContextId ) ){}
       
   609 	while( iMMRCServerInfo->PopAndRemoveFirstAPRContextByContextId( aContextId ) ){}
       
   610 	TUint64 contextId;
       
   611 	TMMRCServerState serverState;
       
   612 	iMMRCServerInfo->ServerState(serverState, contextId);
       
   613 	if( contextId == aContextId)
       
   614 		{
       
   615 		iMMRCServerInfo->SwitchServerState(EMMRCServerStateIdle, 0);
       
   616 		}
       
   617 #ifdef SYMBIAN_MULTIMEDIA_ENABLE_LOGGING	
       
   618 	RDebug::Print(_L("size of message queue    = %d"),  iMMRCServerInfo->RequestsCount());
       
   619 	RDebug::Print(_L("size of inprocess queue = %d"),  iMMRCServerInfo->AllocatedResourceContextsCount());
       
   620 	RDebug::Print(_L("size of paused queue = %d"),  iMMRCServerInfo->AllocatedPausedContextsCount());
       
   621 	RDebug::Print(_L("size of APR queue  = %d"),  iMMRCServerInfo->AllocatedAPRContextsCount());
       
   622 #endif
       
   623 	
       
   624 	DP_OUT();
       
   625 	}
       
   626 
       
   627 /*
       
   628  *
       
   629  */
       
   630 void CMMRCServerController::ServerState(TMMRCServerState& aServerState, TUint64& aContextId) const
       
   631 	{
       
   632 	iMMRCServerInfo->ServerState(aServerState, aContextId);
       
   633 	}
       
   634 	
       
   635 /**
       
   636 
       
   637 */
       
   638 TInt CMMRCServerController::EnqueueRequestForAPRL(CMMRCServerSession& aServerSession)
       
   639 	{
       
   640 	DP_CONTEXT(----> CMMRCServerController::EnqueueRequestForAPRL *CD1*, CtxDevSound, DPLOCAL);
       
   641 	DP_IN();
       
   642 	
       
   643 	//add the request to the queue
       
   644 	TInt err = KErrNone;
       
   645 	//if already there, should return KErrAlreadyExists
       
   646 
       
   647 	if (iMMRCServerInfo->IsOnAPRList(aServerSession.ContextId()))
       
   648 		{
       
   649 		err = KErrAlreadyExists;
       
   650 		}
       
   651 	else
       
   652 		{
       
   653 		iMMRCServerInfo->PushAPRContextL(aServerSession);
       
   654 		}	
       
   655 	DP0_RET(err, "err=%d");
       
   656 	}
       
   657 	
       
   658 /**
       
   659 
       
   660 */
       
   661 TInt CMMRCServerController::RemoveRequestForAPR(CMMRCServerSession& aServerSession)
       
   662 	{
       
   663 	DP_CONTEXT(----> CMMRCServerController::RemoveRequestForAPR *CD1*, CtxDevSound, DPLOCAL);
       
   664 	DP_IN();
       
   665 	
       
   666 	TInt err = KErrNone;
       
   667 	TInt32 iContextId = aServerSession.ContextId();
       
   668 	TBool iIsOnAPRList = iMMRCServerInfo->IsOnAPRList(iContextId);
       
   669 	if(iIsOnAPRList)
       
   670 		{
       
   671 
       
   672 		// Its possible that the remove request has occured whilst clients are being notified that the resource is available
       
   673 		// Check if a notification sequence is currently under way
       
   674 		if ( iARNNotificationObject->IsActive() )
       
   675 			{
       
   676 			
       
   677 			// Iterate through each paused client 
       
   678 			for ( TInt index = 0 ; index < iMMRCServerInfo->AllocatedPausedContextsCount() ; index++ )
       
   679 				{
       
   680 				
       
   681 				// Find the client that has requested removal in the list
       
   682 				TAudioContextId id = iMMRCServerInfo->PausedContextByIndex(index)->ContextId();
       
   683 				if ( aServerSession.ContextId() == id )
       
   684 					{
       
   685 					// Object has already received a notification
       
   686 					if ( index < iARNNotificationObject->iIndex )
       
   687 						{
       
   688 						// decrement the notification objects list index to account for the item that will be removed from the queue
       
   689 						--iARNNotificationObject->iIndex;
       
   690 						}
       
   691 						
       
   692 					// no action needs to be taken if 
       
   693 					// index >= iMMRCServerInfo.iIndex
       
   694 					
       
   695 					break;
       
   696 					}
       
   697 				}
       
   698 			
       
   699 			}
       
   700 
       
   701 		iMMRCServerInfo->PopAndRemoveFirstAPRContextByContextId(iContextId);
       
   702 		iMMRCServerInfo->PopAndRemovePausedContext(iContextId); //removing this session from the list of paused too.
       
   703 		}
       
   704 	else
       
   705 		{
       
   706 		err = KErrCancel;
       
   707 		}
       
   708 	
       
   709 	DP0_RET(err, "err=%d");
       
   710 	}
       
   711 
       
   712 /**
       
   713 
       
   714 */
       
   715 TInt CMMRCServerController::WillResumePlay()
       
   716 	{
       
   717 	DP_CONTEXT(----> CMMRCServerController::WillResumePlay *CD1*, CtxDevSound, DPLOCAL);
       
   718 	DP_IN();
       
   719 	
       
   720 	TInt err = KErrNone;
       
   721 	iARNNotificationObject->Cancel();
       
   722 	
       
   723 	
       
   724 	DP0_RET(err, "err=%d");
       
   725 	}
       
   726 
       
   727 
       
   728 //From CActive
       
   729 /**
       
   730  * Constructor.
       
   731  */
       
   732 CARNNotificationObject::CARNNotificationObject(const TInt aPriority)
       
   733 :CActive(aPriority)
       
   734 	{
       
   735 	TRACE_CREATE();
       
   736 	DP_CONTEXT(----> CARNNotificationObject::CARNNotificationObject *CD1*, CtxDevSound, DPLOCAL);
       
   737 	DP_IN();
       
   738 	
       
   739 	
       
   740 	DP_OUT();
       
   741 	}
       
   742 
       
   743 
       
   744 /**
       
   745  * Destructor.
       
   746  */
       
   747 CARNNotificationObject::~CARNNotificationObject()
       
   748 	{
       
   749 	DP_CONTEXT(----> CARNNotificationObject::~CARNNotificationObject *CD1*, CtxDevSound, DPLOCAL);
       
   750 	DP_IN();
       
   751 
       
   752 	Cancel();
       
   753 	iTimer.Close();
       
   754 	delete iMMRCServerInfo;
       
   755 	
       
   756 	DP_OUT();
       
   757 	}
       
   758 
       
   759 
       
   760 /**
       
   761  	CARNNotificationObject::ConstructL
       
   762  	Symbian 2nd phase constructor can leave.
       
   763  */
       
   764 void CARNNotificationObject::ConstructL(CMMRCServerInfo& aMMRCServerInfo)
       
   765 	{
       
   766 	DP_CONTEXT(----> CARNNotificationObject::ConstructL *CD1*, CtxDevSound, DPLOCAL);
       
   767 	DP_IN();
       
   768 	
       
   769 	iMMRCServerInfo = &aMMRCServerInfo; 
       
   770 	CActiveScheduler::Add(this);
       
   771 	User::LeaveIfError(iTimer.CreateLocal());
       
   772 	
       
   773 	
       
   774 	DP_OUT();
       
   775 	}
       
   776 
       
   777 // ---------------------------------------------------------------------------
       
   778 // CARNNotificationObject::NewL
       
   779 // ---------------------------------------------------------------------------
       
   780 CARNNotificationObject* CARNNotificationObject::NewL(const TInt aPriority, CMMRCServerInfo& aMMRCServerInfo)
       
   781 	{
       
   782 	DP_STATIC_CONTEXT(----> CARNNotificationObject::NewL *CD1*, CtxDevSound, DPLOCAL);
       
   783 	DP_IN();
       
   784 	
       
   785 	CARNNotificationObject* self = new(ELeave)CARNNotificationObject(aPriority);
       
   786 	CleanupStack::PushL(self);
       
   787 	self->ConstructL(aMMRCServerInfo);
       
   788 	CleanupStack::Pop(self);
       
   789 	
       
   790 	DP0_RET(self, "0x%x");
       
   791 	} 
       
   792 
       
   793 // ---------------------------------------------------------------------------
       
   794 // CARNNotificationObject::RunL
       
   795 // ---------------------------------------------------------------------------
       
   796 void CARNNotificationObject::RunL()
       
   797 	{
       
   798 	DP_CONTEXT(CARNNotificationObject::RunL *CD1*, CtxDevSound, DPLOCAL);
       
   799 	DP_IN();
       
   800 	
       
   801 	#if defined(_DEBUG) && defined(__WINS__) 
       
   802 	const TTimeIntervalMicroSeconds32 KTimer = 1.8*1000000; // 1.8 seconds
       
   803 	#else
       
   804 	const TTimeIntervalMicroSeconds32 KTimer = 800000; // 0.8 seconds
       
   805 	#endif
       
   806 	
       
   807 	TInt numPausedContext = iMMRCServerInfo->AllocatedPausedContextsCount();
       
   808 
       
   809 	// The list may have been modified whilst the AO was asleep, need to check that:
       
   810 	// 1) iIndex is still in range
       
   811 	// 2) the object at that location should still receive a notification
       
   812 	
       
   813 	if ( (iIndex > -1) && (iIndex < numPausedContext) )
       
   814 		{
       
   815 		CMMRCServerSession* mmrcSession = iMMRCServerInfo->PausedContextByIndex(iIndex);
       
   816 		
       
   817 		TAudioContextId id = mmrcSession->ContextId( );
       
   818 		TBool isOnAPRList = iMMRCServerInfo->IsOnAPRList(id);
       
   819 		if(isOnAPRList)
       
   820 			{
       
   821 			mmrcSession->NotifyClientResourceUnallocated();
       
   822 			}
       
   823 
       
   824 		
       
   825 		for(TInt aux = iIndex + 1; aux < numPausedContext ; aux++)
       
   826 			{
       
   827 			mmrcSession = iMMRCServerInfo->PausedContextByIndex(aux);
       
   828 			id = mmrcSession->ContextId( );
       
   829 			isOnAPRList = iMMRCServerInfo->IsOnAPRList(id);
       
   830 			if(isOnAPRList)
       
   831 				{
       
   832 				iIndex = aux;		
       
   833 				After(KTimer);
       
   834 				break;
       
   835 				}
       
   836 			}
       
   837 		}
       
   838 		
       
   839 	else
       
   840 		{
       
   841 		iIndex = 0;
       
   842 		}
       
   843 		
       
   844 	DP_OUT();
       
   845 	}
       
   846 
       
   847 // ---------------------------------------------------------------------------
       
   848 // CARNNotificationObject::After
       
   849 // ---------------------------------------------------------------------------
       
   850 void CARNNotificationObject::After(TTimeIntervalMicroSeconds32 aInterval)
       
   851 	{
       
   852 	DP_CONTEXT(CARNNotificationObject::After *CD1*, CtxDevSound, DPLOCAL);
       
   853 	DP_IN();
       
   854 
       
   855 	Cancel();
       
   856 	iTimer.After(iStatus,aInterval);
       
   857 	SetActive();
       
   858 
       
   859 	DP_OUT();
       
   860 	}
       
   861 
       
   862 // ---------------------------------------------------------------------------
       
   863 // CARNNotificationObject::Initialize
       
   864 // ---------------------------------------------------------------------------
       
   865 void CARNNotificationObject::Initialize()
       
   866 	{
       
   867 	DP_CONTEXT(CARNNotificationObject::Initialize *CD1*, CtxDevSound, DPLOCAL);
       
   868 	DP_IN();
       
   869 
       
   870 	#if defined(_DEBUG) && defined(__WINS__)
       
   871 	const TTimeIntervalMicroSeconds32 KTimer = 1.8*1000000; // 1.8 seconds
       
   872 	#else
       
   873 	const TTimeIntervalMicroSeconds32 KTimer = 800000; // 0.8 seconds
       
   874 	#endif
       
   875 
       
   876 	TInt numPausedContext = iMMRCServerInfo->AllocatedPausedContextsCount();
       
   877 	iIndex = 0;
       
   878 	CMMRCServerSession* mmrcSession = NULL;
       
   879 	
       
   880 	if(numPausedContext) // don't bother if zero.
       
   881 		{
       
   882 		for(TInt i(0); i<numPausedContext ; ++i)
       
   883 			{
       
   884 			mmrcSession = iMMRCServerInfo->PausedContextByIndex(i);
       
   885 			TAudioContextId id = mmrcSession->ContextId( );
       
   886 			TBool isOnAPRList = iMMRCServerInfo->IsOnAPRList(id);
       
   887 			if(isOnAPRList)
       
   888 				{
       
   889 				iIndex = i;
       
   890 				After(KTimer);
       
   891 				break;
       
   892 				}
       
   893 			}
       
   894 		}
       
   895 
       
   896 	DP_OUT();
       
   897 	}
       
   898 
       
   899 // ---------------------------------------------------------------------------
       
   900 // CMMRCServer::DoCancel
       
   901 // ---------------------------------------------------------------------------
       
   902 void CARNNotificationObject::DoCancel()
       
   903 	{
       
   904 	DP_CONTEXT(CARNNotificationObject::DoCancel *CD1*, CtxDevSound, DPLOCAL);
       
   905 	DP_IN();
       
   906 	
       
   907 	iTimer.Cancel();
       
   908 	
       
   909 	DP_OUT();
       
   910 	}
       
   911 
       
   912 
       
   913 void CMMRCServerController::Panic(TMMRCServerControllerPanicCodes aCode)
       
   914 	{
       
   915 	User::Panic(KMMRCServerControllerPanicCategory, aCode);
       
   916 	}	
       
   917 //EOF