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