devsound/a3fdevsound/src/devsoundadaptor/cdevcommoncontrol.cpp
changeset 0 b8ed18f6c07b
child 2 5c1df44f2eed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevcommoncontrol.cpp	Thu Oct 07 22:34:12 2010 +0100
@@ -0,0 +1,850 @@
+// Copyright (c) 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 "cdevcommoncontrol.h"
+#include <a3f/maudiocontext.h> 
+#include <a3f/maudiocodec.h>
+
+
+CDevCommonControl::CDevCommonControl()
+    {
+    TRACE_CREATE();
+    DP_CONTEXT(CDevCommonControl::CDevCommonControl, CtxDevSound, DPLOCAL);
+    DP_IN();
+    DP_OUT();
+    }
+
+
+CDevCommonControl::~CDevCommonControl()
+    {
+    DP_CONTEXT(CDevCommonControl::~CDevCommonControl, CtxDevSound, DPLOCAL);
+    DP_IN();
+    DP_OUT();
+    }
+
+
+TInt CDevCommonControl::Stop() // from CDevAudioControl
+    {
+    DP_CONTEXT(CDevCommonControl::Stop, CtxDevSound, DPLOCAL);
+    DP_IN();
+
+    TInt err = KErrNone;
+    switch(iDevAudio->iActiveState)
+        {
+        case EDevSoundAdaptorActive_Active:
+        case EDevSoundAdaptorPaused_Primed:
+            err = iDevAudio->iAudioStream->Stop();
+            if (err == KErrNone)
+                {
+                err = iDevAudio->CommitAudioContext();
+                }
+            if (err == KErrNone)
+                {
+                iDevAudio->iActiveState = EDevSoundAdaptorStopping;
+                }
+            break;
+        case EDevSoundAdaptorGoingActive:
+            iDevAudio->iActiveState = EDevSoundAdaptorStopping;
+            break;
+        case EDevSoundAdaptorInitialised_Idle:
+        	{
+        	//If following condition is true, then we are here because of a
+        	//pre-emption clash in last Commit cycle started from
+        	//CDevCommonControl::ContextEventUpdateWithStateEventNoError.
+        	if(iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
+        		{
+				err = Unload();
+				break;
+        		}
+        	}
+        default:
+            break;
+        }
+    
+    if(err == KErrNone)
+        {
+        iDevAudio->iStop = ETrue;
+        }
+    
+    DP0_RET(err,"%d");
+    }
+
+
+TInt CDevCommonControl::Pause() // from CDevAudioControl
+    {
+    DP_CONTEXT(CDevCommonControl::Pause, CtxDevSound, DPLOCAL);
+    DP_IN();
+
+    TInt err = iDevAudio->iAudioStream->Prime();
+    if ( err == KErrNone)
+        {
+        err = iDevAudio->CommitAudioContext();
+        }
+    if (err == KErrNone)
+        {
+        iDevAudio->iActiveState = EDevSoundAdaptorPausing;
+        }
+    
+    DP0_RET(err,"%d");
+    }
+
+
+TInt CDevCommonControl::Resume() // from CDevAudioControl
+    {
+    DP_CONTEXT(CDevCommonControl::Resume, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    TInt err = KErrNone;
+
+    //If following condition is true, then we are here because of a
+    //pre-emption clash in last Commit cycle started from
+    //CDevCommonControl::ContextEventUpdateWithStateEventAndError.
+    if(iDevAudio->iActiveState == EDevSoundAdaptorInitialised_Idle &&
+    		iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
+    	{
+		err = Unload();
+		DP0_RET(err,"%d");
+    	}
+    else if(iDevAudio->iActiveState != EDevSoundAdaptorPaused_Primed)
+        {
+        DP0_RET(KErrNotReady, "%d");
+        }
+
+    if(err == KErrNone)
+        {
+        // Populate gain and balance values set in the Paused state and being cached
+        err = iDevAudio->RequestGainAndBalance(this);
+        }
+    if(err == KErrNone)
+        {
+        err = iDevAudio->iAudioStream->Activate();
+        }
+    if ( err == KErrNone)
+        {
+        err = iDevAudio->CommitAudioContext();
+        }
+    if (err == KErrNone)
+        {
+        iDevAudio->iActiveState = EDevSoundAdaptorActivating;
+        }
+    
+    DP0_RET(err,"%d");
+    }
+
+
+void CDevCommonControl::StateEvent(MAudioStream& aStream, TInt aError,  // from MAudioProcessingUnitObserver
+                                    TAudioState aNewState)
+    {
+    DP_CONTEXT(CDevCommonControl::StateEvent, CtxDevSound, DPLOCAL);
+    DP3_IN("activeState %d -> newstate %d, (%d)",
+            iDevAudio->iActiveState, aNewState, aError);
+    
+    __ASSERT_ALWAYS(iDevAudio->iAudioStream == &aStream, Panic(EStreamMismatch));
+    
+    if(aError != KErrNone || iDevAudio->iActiveStreamState != aNewState) 
+        {
+        iDevAudio->iActiveStreamState = aNewState;
+        iStateEventReceived = ETrue;
+        }
+    // Since the audiostream already demoted the state for the most of the cases
+    // only is need  when a error comes were the stream was at the middle of A3f two-phase transition
+    else
+        {
+        switch (aNewState)
+            {
+            case EIdle:
+                // Demote the stream state
+                iDevAudio->iActiveStreamState = EIdle;
+                break;
+            default:
+                break;
+            }
+        }
+    iStateEventError = aError;
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ProcessingUnitError(MAudioProcessingUnit* /*aInstance*/, // from MAudioProcessingUnitObserver
+                                                                 TInt aError)
+    {
+    DP_CONTEXT(CDevCommonControl::ProcessingUnitError, CtxDevSound, DPLOCAL);
+    DP_IN();
+
+    if(iCallbackFromAdaptor == KCallbackNone)   
+        {
+        iProcessingUnitError = aError;
+        iCallbackFromAdaptor = KCallbackProcessingUnitError;
+        iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackProcessingUnitError, aError);
+        }
+    else
+        {
+        // Multiple callbacks from adaptor
+        DP0(DLINFO, "Multiple callbacks from adaptor");
+        }
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEvent(TUid aEvent, TInt aError) 
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEvent, CtxDevSound, DPLOCAL);
+    DP3_IN("ContextEvent aEvent=%x iActiveState=%d aError=%d",aEvent, iDevAudio->iActiveState, aError);
+
+    // Can't "switch {...}" on UIDs unfortunately:
+    if (aEvent == KUidA3FContextUpdateComplete)
+        {
+        if(iBeingPreempted)
+            {
+			if(iStateEventReceived)
+				{
+				//use a sub state pattern to make pre-emption cycles like other cycles.
+				DP1(DLERR,"Preemption error=%d", aError);
+				iDevAudio->iActiveState = EDevSoundAdaptorBeingPreempted;
+				if(iPreemptionClash)
+					{
+					// remove last request from front of queue without processing it
+					iAdaptationObserver->PreemptionClashWithStateChange();
+					iPreemptionClash=EFalse;
+					}
+				}
+            else if(!iStateEventReceived && iPreemptionClash)
+        		{
+				iIgnoreAsyncOpComplete=ETrue;
+				iPreemptionClash=EFalse;
+        		}
+			iBeingPreempted=EFalse;
+            }
+		ContextEventUpdateComplete(aError);
+        }
+
+    else if ((aEvent == KUidA3FContextCommitUpdate))
+        {
+        iBeingPreempted=EFalse; // clear being preempted
+        iPreemptionClash=EFalse; // clear pre-emption clash flag
+        TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
+        iIgnoreAsyncOpComplete = !adaptorControlsContext;
+            // if we don't control context, always send a PreemptionFinishedCallbackReceived()
+		iStateEventReceived=EFalse;
+        }
+
+    else if (aEvent == KUidA3FContextPreEmption)
+        {
+        // clear iBeingPreepted - will be set in ContextEventPreEmption if req
+        iBeingPreempted=EFalse;
+        iPreemptionClash=EFalse; // clear pre-emption clash flag
+        TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
+		iStateEventReceived=EFalse;
+        iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete
+        ContextEventPreEmption(aEvent, aError);
+        if (!adaptorControlsContext)
+            {
+            iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete
+            }
+        }
+    else if (aEvent == KUidA3FContextPreEmptedCommit)
+        {
+		DP0(DLINFO,"KUidA3FContextPreEmptedCommit event received, thus clash with Pre-emption");
+        // clear iBeingPreepted - will be set in ContextEventPreEmption if req
+        iBeingPreempted=EFalse;
+        TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
+        if (adaptorControlsContext)
+        	{
+			// push current request that was being processed onto front of queue.
+        	iAdaptationObserver->PreemptionClash();
+        	iPreemptionClash=ETrue;
+        	}
+		iStateEventReceived=EFalse;
+        iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete
+        ContextEventPreEmption(aEvent, aError);
+        if (!adaptorControlsContext)
+            {
+            iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete
+            }
+        }
+
+    else if (aEvent == KUidA3FContextAbort)
+        {
+        ContextEventAbort(aError);
+        }
+
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventAsynchronousPlayCompletion(TInt aError) // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventAsynchronousPlayCompletion, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+	iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
+		
+    if (aError)
+        {
+        FinishWithError(aError);
+        }
+           
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventAsynchronousInitializeComplete(TInt aError) // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventAsynchronousInitializeComplete, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
+    iAdaptationObserver->InitializeComplete(aError);
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventUpdateComplete(TInt aError) // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventUpdateComplete, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    if (iStateEventReceived)
+        {
+        iStateEventReceived = EFalse;
+        DP0(DLINFO,"Context event for that does involve state change");         
+        
+        if (aError)
+            {
+            ContextEventUpdateWithStateEventAndError(aError);
+            }
+        else
+            {
+            ContextEventUpdateWithStateEventNoError();
+            }   
+        DP_OUT();
+        return;
+        }
+    
+    DP0(DLINFO,"Context event for that doesn't involve state change");
+
+    if (aError)
+        {
+        ContextEventUpdateWithoutStateEventButWithError(aError);
+        }
+    else
+        {
+        ContextEventUpdateWithoutStateEventNoError();
+        }
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventPreEmption(TUid aEvent, TInt aError) // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventPreEmption, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    DP1(DLERR,"Preemption error=%d", aError);
+    CDevAudioControl::ContextEvent(aEvent, aError);
+    iBeingPreempted=ETrue;
+        
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventAbort(TInt aError) // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventAbort, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    DP1(DLERR,"Abort error=%d", aError);
+    FinishWithError(aError==KErrAbort ? KErrDied:aError);
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventStopDevSoundNotifications() // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventStopDevSoundNotifications, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    iDevAudio->iAudioStream->UnregisterAudioStreamObserver(*this);
+    iGainControl->UnregisterAudioGainControlObserver(*this);
+    iAudioCodecIf->UnregisterAudioCodecObserver(*this);
+    iAudioCodecIf = NULL;
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventPauseResumeSequenceDueToEmptyBuffers(TBool aFlush) // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventPauseResumeSequenceDueToEmptyBuffers, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    TInt err(KErrNone);
+
+    if (iPauseResumeSequenceDueToEmptyBuffers)
+        {
+        if (aFlush)
+            {
+            err = iDevAudio->iAudioStream->Flush();
+            }
+        
+        if ((err) or (aFlush==EFalse))
+            {
+            iPauseResumeSequenceDueToEmptyBuffers = EFalse;
+            iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, err);
+            }
+        }
+    else
+        {
+        iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);    
+        }
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventStateDevSoundAdaptorUnloading() // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorUnloading, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    // Due destruction sequence or reinitialization
+    if (iDevAudio->iClosing or iDevAudio->iReinitializing)
+        {
+        TInt err = Uninitialize();
+        if (err and iDevAudio->iReinitializing)
+            {
+            ContextEventAsynchronousInitializeComplete(err);
+    
+            }
+        
+        DP_OUT();
+        return;
+        }
+
+    // Notify the user that ProcessingFinished is complete. 
+    // Stop call complete, sent callback.
+    if (iCallbackFromAdaptor != KCallbackNone)
+        {
+        iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
+        
+        if (iCallbackFromAdaptor == KCallbackProcessingFinished)
+            {
+            FinishWithError(KErrUnderflow);
+            }
+        else if (iCallbackFromAdaptor == KCallbackProcessingUnitError)
+            {
+            FinishWithError(iProcessingUnitError);
+            }
+        
+        iCallbackFromAdaptor = KCallbackNone;
+        DP_OUT();
+        return;
+        }
+    
+    // Error condition
+    if (iErrorCondition)
+        {
+        FinishWithError(iErrorCondition);
+        iErrorCondition = KErrNone;
+        }
+    else
+        {
+    
+        iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
+        }
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventStateDevSoundAdaptorLoading() // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorLoading, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    iDevAudio->RequestGainAndBalance(this); // TODO handle error
+
+    TInt err = iDevAudio->iAudioStream->Activate();
+    if (err)
+        {
+        DP_OUT();
+        return;
+        }
+    
+    err = iDevAudio->CommitAudioContext();
+    if (err)
+        {
+        ContextEventAsynchronousPlayCompletion(err);
+        DP_OUT();
+        return;
+        }
+    
+    iDevAudio->iActiveState = EDevSoundAdaptorActivating;
+    iAdaptationObserver->AsynchronousOperationComplete(KErrNone, EFalse);
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventStateDevSoundAdaptorStopping() // from CDevCommonControl
+    {   
+    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorStopping, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    TInt err = Unload();
+    if (err)
+        {
+        DP0(DLINFO,"Commit failed during stopping");
+        FinishWithError(err);
+        }
+    
+    __ASSERT_DEBUG(err==KErrNone, Panic(ECommitFailedDuringStop));
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventStateDevSoundAdaptorBeingPreempted() // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorBeingPreempted, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+    __ASSERT_DEBUG(iDevAudio->iActiveStreamState == EInitialized, Panic(EStreamBeingDemotedToEIdle));
+    FinishWithError(KErrInUse);
+    if (iIgnoreAsyncOpComplete)
+        {
+        iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
+        iIgnoreAsyncOpComplete=EFalse;
+        DP_OUT();
+        return;
+        }
+    
+    ContextEventPauseResumeSequenceDueToEmptyBuffers(EFalse);
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventStateDevSoundAdaptorUninitializing() // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorUninitializing, CtxDevSound, DPLOCAL);
+    DP_IN();
+    TInt err = RemoveProcessingUnits();
+
+    if (err == KErrNone)
+        {
+        iDevAudio->iActiveState = EDevSoundAdaptorRemovingProcessingUnits;
+        }
+    else if (iDevAudio->iReinitializing)
+        {
+        ContextEventAsynchronousInitializeComplete(err);
+        }
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventErrorStateDevSoundAdaptorActivating(TInt aError) // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventErrorStateDevSoundAdaptorActivating, CtxDevSound, DPLOCAL);
+    DP_IN();
+
+    // If the resume operation fails as result of EmptyBuffers
+    // Notify about operation complete through CallbackFromAdaptorReceived
+    // and continue to allow client to receive PlayError()
+    if (iPauseResumeSequenceDueToEmptyBuffers)
+        {
+        iPauseResumeSequenceDueToEmptyBuffers = EFalse;
+        iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, KErrNone);
+        }
+    
+    iErrorCondition = aError;
+    
+    TInt err = Unload();
+    if (err)
+        {
+        DP0(DLINFO,"Commit failed during stopping");
+        FinishWithError(err);
+        }
+    __ASSERT_DEBUG(err==KErrNone, Panic(ECommitFailedDuringStop));
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventErrorStateDevSoundAdaptorBeingPreempted() // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventErrorStateDevSoundAdaptorBeingPreempted, CtxDevSound, DPLOCAL);
+    DP_IN();
+    
+__ASSERT_DEBUG(iDevAudio->iActiveStreamState == EInitialized, Panic(EStreamBeingDemotedToEIdle));
+    FinishWithError(KErrInUse);
+
+    if(iIgnoreAsyncOpComplete)
+        {
+        iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
+        }
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventUpdateWithoutStateEventNoError() // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithoutStateEventNoError, CtxDevSound, DPLOCAL);
+    DP2_IN("iActiveState=%d iIgnoreAsyncOpComplete=%d",iDevAudio->iActiveState, iIgnoreAsyncOpComplete);
+    
+    if (iDevAudio->iActiveState != EDevSoundAdaptorRemovingProcessingUnits)
+        {
+	    if (iIgnoreAsyncOpComplete)
+	      {
+	      iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
+	      iIgnoreAsyncOpComplete = EFalse;
+	      }
+	    else
+	      {
+	      iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
+	      }
+        DP_OUT();
+        return;
+        }
+
+    //If the Commit cycle when going into EDevSoundAdaptorRemovingProcessingUnits fails due to pre-emption
+    //clash then we re-apply the client request again.
+    if (iDevAudio->iActiveState == EDevSoundAdaptorRemovingProcessingUnits && iIgnoreAsyncOpComplete)
+    	{
+		//Pop front of queue to re-apply the request again via CMMFDevSoundSession::DequeueRequest
+		//from the callback into CMMFDevSoundSession below:
+		iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
+		iIgnoreAsyncOpComplete = EFalse;
+		DP_OUT();
+		return;
+    	}
+
+    iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised;
+    
+    if (iDevAudio->iReinitializing)
+        {
+        ContextEventStopDevSoundNotifications();
+        
+        TInt err = iDevAudio->Initialize(iDevAudio->iTargetFormat, iDevAudio->iTargetMode);
+        if(err)
+            {
+            ContextEventAsynchronousInitializeComplete(err);
+            }
+
+        iDevAudio->iReinitializing = EFalse;
+        DP_OUT();
+        return;
+        }
+    
+    iDevAudio->iClosing = EFalse;
+    iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventUpdateWithoutStateEventButWithError(TInt aError) // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithoutStateEventButWithError, CtxDevSound, DPLOCAL);
+    DP_IN();
+
+    //If flag is true below then it must be due to a stateless normal pre-emption or
+    //stateless pre-emption clash scenario.
+    if(iIgnoreAsyncOpComplete)
+    	{
+		//If we are in pre-emption clash then callback below will retry the client request again.
+		iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); // notify client of end of cycle
+		iIgnoreAsyncOpComplete = EFalse;
+    	}
+    else
+    	{
+        TDevSoundAdaptorState previousState = iDevAudio->iPreviousState;
+
+        DP3(DLINFO,"Error with no state change, state %d, previous %d, error %d during Commit cycle",
+                    iDevAudio->iActiveState, previousState, aError);
+
+        // We can end up here for a number of reasons. For non "mid states", this is
+        // a standard error scenario. For some mid-states (e.g. Activating, Loading etc),
+        // when we try and "promote" the state, this happens when the promotion is rejected
+        // and we handle thus accordingly. For other mid-states the situation is less clear
+        // and we call AsynchronousOperationComplete() with the error assuming the parent
+        // session will deal with it. Whatever we don't want to stay in a mid-state, so
+        // rewind to the previous ("normal") one if we are in one.
+
+        // Longer term TODO. If the code were refactored so that the InitializeComplete(),
+        // PlayError() etc callback came from AsynchronousOperationComplete() then the
+        // following code might be simpler. Most of the time (at least) we get here because
+        // we are doing a session function, and we can use the function to determine what
+        // to do more easily than relying on the state. As it is, for some mid-states we
+        // try and work out what error code to generate. Not clear this covers 100% cases,
+        // although demotion transitions should not fail, so the problem cases might not occur.
+        //
+
+		//If we reach this condition then it is because of rejection/error during Commit cycle.
+		switch (iDevAudio->iActiveState)
+			{
+			case EDevSoundAdaptorInitialising:
+				{
+				iDevAudio->iActiveState = previousState;
+				ContextEventAsynchronousInitializeComplete(aError);
+				break;
+				}
+			case EDevSoundAdaptorLoading:
+				{
+				iDevAudio->iActiveState = previousState;
+				ContextEventAsynchronousPlayCompletion(aError);
+				break;
+				}
+			case EDevSoundAdaptorActivating:
+				{
+				iDevAudio->iActiveState = previousState;
+				ContextEventAsynchronousPlayCompletion(aError);
+				break;
+				}
+			case EDevSoundAdaptorRemovingProcessingUnits:
+			case EDevSoundAdaptorUninitialising:
+			case EDevSoundAdaptorUnloading:
+			case EDevSoundAdaptorStopping:
+			case EDevSoundAdaptorPausing:
+			    {
+                DP2(DLINFO,"Unexpected mid state [%d] when handling error [%d] during Commit cycle, workback", iDevAudio->iActiveState, aError);
+			    iDevAudio->iActiveState = previousState;
+                iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
+			    break;
+			    }
+			default:
+				{
+				DP2(DLINFO,"Unexpected state [%d] when handling error [%d] during Commit cycle", iDevAudio->iActiveState, aError);
+		        iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
+				}
+			}
+    	}
+       
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventUpdateWithStateEventNoError() // from CDevCommonControl 
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithStateEventNoError, CtxDevSound, DPLOCAL);
+    DP_IN();
+
+    switch (iDevAudio->iActiveState)
+        {
+    case EDevSoundAdaptorUninitialising:
+        iDevAudio->iActiveState = EDevSoundAdaptorUnitialised_Uninitialised;
+        ContextEventStateDevSoundAdaptorUninitializing();
+        break;
+
+    case EDevSoundAdaptorInitialising:
+        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
+        ContextEventAsynchronousInitializeComplete(KErrNone);
+        break;
+
+    case EDevSoundAdaptorUnloading:
+        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
+        ContextEventStateDevSoundAdaptorUnloading();
+        break;
+
+    case EDevSoundAdaptorLoading:
+        iDevAudio->iActiveState = EDevSoundAdaptorGoingActive;
+        ContextEventStateDevSoundAdaptorLoading();
+        break;
+
+    case EDevSoundAdaptorStopping:
+        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Idle;
+        ContextEventStateDevSoundAdaptorStopping();
+        break;
+
+    case EDevSoundAdaptorActivating:
+        iDevAudio->iActiveState = EDevSoundAdaptorActive_Active;
+        ContextEventPauseResumeSequenceDueToEmptyBuffers(EFalse);
+        break;
+        
+    case EDevSoundAdaptorPausing:
+        iDevAudio->iActiveState = EDevSoundAdaptorPaused_Primed;
+        ContextEventPauseResumeSequenceDueToEmptyBuffers(ETrue);
+        break;
+
+    case EDevSoundAdaptorBeingPreempted:
+        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
+        ContextEventStateDevSoundAdaptorBeingPreempted();
+        break;
+        
+    default:
+        break;
+        }   
+    
+    DP_OUT();
+    }
+
+
+void CDevCommonControl::ContextEventUpdateWithStateEventAndError(TInt aError) // from CDevCommonControl
+    {
+    DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithStateEventAndError, CtxDevSound, DPLOCAL);
+    DP_IN();
+
+    DP1(DLERR,"ContextEventUpdateWithStateEventAndError error=%d", aError);
+    
+    switch(iDevAudio->iActiveState)
+        {
+    case EDevSoundAdaptorInitialising:
+        iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised;
+        iAdaptationObserver->InitializeComplete(aError);
+        break;
+        
+    case EDevSoundAdaptorLoading:
+        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
+        FinishWithError(aError);
+        break;
+        
+    case EDevSoundAdaptorActivating:
+        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Idle;
+        ContextEventErrorStateDevSoundAdaptorActivating(aError);
+        break;
+        
+    case EDevSoundAdaptorBeingPreempted:
+        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
+        ContextEventErrorStateDevSoundAdaptorBeingPreempted();
+        break;
+
+    default:
+        break;
+        }
+    
+    iCallbackFromAdaptor = KCallbackNone;
+    
+    if(!iIgnoreAsyncOpComplete)
+        {
+        iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
+        }
+    else
+        {
+        iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
+        iIgnoreAsyncOpComplete=EFalse;
+        }
+    
+    DP_OUT();
+    }
+
+
+// end of file