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