1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/devsound/a3fdevsound/src/devsoundadaptor/cdevcommoncontrol.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,850 @@
1.4 +// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "cdevcommoncontrol.h"
1.20 +#include <a3f/maudiocontext.h>
1.21 +#include <a3f/maudiocodec.h>
1.22 +
1.23 +
1.24 +CDevCommonControl::CDevCommonControl()
1.25 + {
1.26 + TRACE_CREATE();
1.27 + DP_CONTEXT(CDevCommonControl::CDevCommonControl, CtxDevSound, DPLOCAL);
1.28 + DP_IN();
1.29 + DP_OUT();
1.30 + }
1.31 +
1.32 +
1.33 +CDevCommonControl::~CDevCommonControl()
1.34 + {
1.35 + DP_CONTEXT(CDevCommonControl::~CDevCommonControl, CtxDevSound, DPLOCAL);
1.36 + DP_IN();
1.37 + DP_OUT();
1.38 + }
1.39 +
1.40 +
1.41 +TInt CDevCommonControl::Stop() // from CDevAudioControl
1.42 + {
1.43 + DP_CONTEXT(CDevCommonControl::Stop, CtxDevSound, DPLOCAL);
1.44 + DP_IN();
1.45 +
1.46 + TInt err = KErrNone;
1.47 + switch(iDevAudio->iActiveState)
1.48 + {
1.49 + case EDevSoundAdaptorActive_Active:
1.50 + case EDevSoundAdaptorPaused_Primed:
1.51 + err = iDevAudio->iAudioStream->Stop();
1.52 + if (err == KErrNone)
1.53 + {
1.54 + err = iDevAudio->CommitAudioContext();
1.55 + }
1.56 + if (err == KErrNone)
1.57 + {
1.58 + iDevAudio->iActiveState = EDevSoundAdaptorStopping;
1.59 + }
1.60 + break;
1.61 + case EDevSoundAdaptorGoingActive:
1.62 + iDevAudio->iActiveState = EDevSoundAdaptorStopping;
1.63 + break;
1.64 + case EDevSoundAdaptorInitialised_Idle:
1.65 + {
1.66 + //If following condition is true, then we are here because of a
1.67 + //pre-emption clash in last Commit cycle started from
1.68 + //CDevCommonControl::ContextEventUpdateWithStateEventNoError.
1.69 + if(iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
1.70 + {
1.71 + err = Unload();
1.72 + break;
1.73 + }
1.74 + }
1.75 + default:
1.76 + break;
1.77 + }
1.78 +
1.79 + if(err == KErrNone)
1.80 + {
1.81 + iDevAudio->iStop = ETrue;
1.82 + }
1.83 +
1.84 + DP0_RET(err,"%d");
1.85 + }
1.86 +
1.87 +
1.88 +TInt CDevCommonControl::Pause() // from CDevAudioControl
1.89 + {
1.90 + DP_CONTEXT(CDevCommonControl::Pause, CtxDevSound, DPLOCAL);
1.91 + DP_IN();
1.92 +
1.93 + TInt err = iDevAudio->iAudioStream->Prime();
1.94 + if ( err == KErrNone)
1.95 + {
1.96 + err = iDevAudio->CommitAudioContext();
1.97 + }
1.98 + if (err == KErrNone)
1.99 + {
1.100 + iDevAudio->iActiveState = EDevSoundAdaptorPausing;
1.101 + }
1.102 +
1.103 + DP0_RET(err,"%d");
1.104 + }
1.105 +
1.106 +
1.107 +TInt CDevCommonControl::Resume() // from CDevAudioControl
1.108 + {
1.109 + DP_CONTEXT(CDevCommonControl::Resume, CtxDevSound, DPLOCAL);
1.110 + DP_IN();
1.111 +
1.112 + TInt err = KErrNone;
1.113 +
1.114 + //If following condition is true, then we are here because of a
1.115 + //pre-emption clash in last Commit cycle started from
1.116 + //CDevCommonControl::ContextEventUpdateWithStateEventAndError.
1.117 + if(iDevAudio->iActiveState == EDevSoundAdaptorInitialised_Idle &&
1.118 + iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
1.119 + {
1.120 + err = Unload();
1.121 + DP0_RET(err,"%d");
1.122 + }
1.123 + else if(iDevAudio->iActiveState != EDevSoundAdaptorPaused_Primed)
1.124 + {
1.125 + DP0_RET(KErrNotReady, "%d");
1.126 + }
1.127 +
1.128 + if(err == KErrNone)
1.129 + {
1.130 + // Populate gain and balance values set in the Paused state and being cached
1.131 + err = iDevAudio->RequestGainAndBalance(this);
1.132 + }
1.133 + if(err == KErrNone)
1.134 + {
1.135 + err = iDevAudio->iAudioStream->Activate();
1.136 + }
1.137 + if ( err == KErrNone)
1.138 + {
1.139 + err = iDevAudio->CommitAudioContext();
1.140 + }
1.141 + if (err == KErrNone)
1.142 + {
1.143 + iDevAudio->iActiveState = EDevSoundAdaptorActivating;
1.144 + }
1.145 +
1.146 + DP0_RET(err,"%d");
1.147 + }
1.148 +
1.149 +
1.150 +void CDevCommonControl::StateEvent(MAudioStream& aStream, TInt aError, // from MAudioProcessingUnitObserver
1.151 + TAudioState aNewState)
1.152 + {
1.153 + DP_CONTEXT(CDevCommonControl::StateEvent, CtxDevSound, DPLOCAL);
1.154 + DP3_IN("activeState %d -> newstate %d, (%d)",
1.155 + iDevAudio->iActiveState, aNewState, aError);
1.156 +
1.157 + __ASSERT_ALWAYS(iDevAudio->iAudioStream == &aStream, Panic(EStreamMismatch));
1.158 +
1.159 + if(aError != KErrNone || iDevAudio->iActiveStreamState != aNewState)
1.160 + {
1.161 + iDevAudio->iActiveStreamState = aNewState;
1.162 + iStateEventReceived = ETrue;
1.163 + }
1.164 + // Since the audiostream already demoted the state for the most of the cases
1.165 + // only is need when a error comes were the stream was at the middle of A3f two-phase transition
1.166 + else
1.167 + {
1.168 + switch (aNewState)
1.169 + {
1.170 + case EIdle:
1.171 + // Demote the stream state
1.172 + iDevAudio->iActiveStreamState = EIdle;
1.173 + break;
1.174 + default:
1.175 + break;
1.176 + }
1.177 + }
1.178 + iStateEventError = aError;
1.179 +
1.180 + DP_OUT();
1.181 + }
1.182 +
1.183 +
1.184 +void CDevCommonControl::ProcessingUnitError(MAudioProcessingUnit* /*aInstance*/, // from MAudioProcessingUnitObserver
1.185 + TInt aError)
1.186 + {
1.187 + DP_CONTEXT(CDevCommonControl::ProcessingUnitError, CtxDevSound, DPLOCAL);
1.188 + DP_IN();
1.189 +
1.190 + if(iCallbackFromAdaptor == KCallbackNone)
1.191 + {
1.192 + iProcessingUnitError = aError;
1.193 + iCallbackFromAdaptor = KCallbackProcessingUnitError;
1.194 + iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackProcessingUnitError, aError);
1.195 + }
1.196 + else
1.197 + {
1.198 + // Multiple callbacks from adaptor
1.199 + DP0(DLINFO, "Multiple callbacks from adaptor");
1.200 + }
1.201 +
1.202 + DP_OUT();
1.203 + }
1.204 +
1.205 +
1.206 +void CDevCommonControl::ContextEvent(TUid aEvent, TInt aError)
1.207 + {
1.208 + DP_CONTEXT(CDevCommonControl::ContextEvent, CtxDevSound, DPLOCAL);
1.209 + DP3_IN("ContextEvent aEvent=%x iActiveState=%d aError=%d",aEvent, iDevAudio->iActiveState, aError);
1.210 +
1.211 + // Can't "switch {...}" on UIDs unfortunately:
1.212 + if (aEvent == KUidA3FContextUpdateComplete)
1.213 + {
1.214 + if(iBeingPreempted)
1.215 + {
1.216 + if(iStateEventReceived)
1.217 + {
1.218 + //use a sub state pattern to make pre-emption cycles like other cycles.
1.219 + DP1(DLERR,"Preemption error=%d", aError);
1.220 + iDevAudio->iActiveState = EDevSoundAdaptorBeingPreempted;
1.221 + if(iPreemptionClash)
1.222 + {
1.223 + // remove last request from front of queue without processing it
1.224 + iAdaptationObserver->PreemptionClashWithStateChange();
1.225 + iPreemptionClash=EFalse;
1.226 + }
1.227 + }
1.228 + else if(!iStateEventReceived && iPreemptionClash)
1.229 + {
1.230 + iIgnoreAsyncOpComplete=ETrue;
1.231 + iPreemptionClash=EFalse;
1.232 + }
1.233 + iBeingPreempted=EFalse;
1.234 + }
1.235 + ContextEventUpdateComplete(aError);
1.236 + }
1.237 +
1.238 + else if ((aEvent == KUidA3FContextCommitUpdate))
1.239 + {
1.240 + iBeingPreempted=EFalse; // clear being preempted
1.241 + iPreemptionClash=EFalse; // clear pre-emption clash flag
1.242 + TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
1.243 + iIgnoreAsyncOpComplete = !adaptorControlsContext;
1.244 + // if we don't control context, always send a PreemptionFinishedCallbackReceived()
1.245 + iStateEventReceived=EFalse;
1.246 + }
1.247 +
1.248 + else if (aEvent == KUidA3FContextPreEmption)
1.249 + {
1.250 + // clear iBeingPreepted - will be set in ContextEventPreEmption if req
1.251 + iBeingPreempted=EFalse;
1.252 + iPreemptionClash=EFalse; // clear pre-emption clash flag
1.253 + TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
1.254 + iStateEventReceived=EFalse;
1.255 + iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete
1.256 + ContextEventPreEmption(aEvent, aError);
1.257 + if (!adaptorControlsContext)
1.258 + {
1.259 + iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete
1.260 + }
1.261 + }
1.262 + else if (aEvent == KUidA3FContextPreEmptedCommit)
1.263 + {
1.264 + DP0(DLINFO,"KUidA3FContextPreEmptedCommit event received, thus clash with Pre-emption");
1.265 + // clear iBeingPreepted - will be set in ContextEventPreEmption if req
1.266 + iBeingPreempted=EFalse;
1.267 + TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
1.268 + if (adaptorControlsContext)
1.269 + {
1.270 + // push current request that was being processed onto front of queue.
1.271 + iAdaptationObserver->PreemptionClash();
1.272 + iPreemptionClash=ETrue;
1.273 + }
1.274 + iStateEventReceived=EFalse;
1.275 + iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete
1.276 + ContextEventPreEmption(aEvent, aError);
1.277 + if (!adaptorControlsContext)
1.278 + {
1.279 + iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete
1.280 + }
1.281 + }
1.282 +
1.283 + else if (aEvent == KUidA3FContextAbort)
1.284 + {
1.285 + ContextEventAbort(aError);
1.286 + }
1.287 +
1.288 + DP_OUT();
1.289 + }
1.290 +
1.291 +
1.292 +void CDevCommonControl::ContextEventAsynchronousPlayCompletion(TInt aError) // from CDevCommonControl
1.293 + {
1.294 + DP_CONTEXT(CDevCommonControl::ContextEventAsynchronousPlayCompletion, CtxDevSound, DPLOCAL);
1.295 + DP_IN();
1.296 +
1.297 + iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
1.298 +
1.299 + if (aError)
1.300 + {
1.301 + FinishWithError(aError);
1.302 + }
1.303 +
1.304 + DP_OUT();
1.305 + }
1.306 +
1.307 +
1.308 +void CDevCommonControl::ContextEventAsynchronousInitializeComplete(TInt aError) // from CDevCommonControl
1.309 + {
1.310 + DP_CONTEXT(CDevCommonControl::ContextEventAsynchronousInitializeComplete, CtxDevSound, DPLOCAL);
1.311 + DP_IN();
1.312 +
1.313 + iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
1.314 + iAdaptationObserver->InitializeComplete(aError);
1.315 +
1.316 + DP_OUT();
1.317 + }
1.318 +
1.319 +
1.320 +void CDevCommonControl::ContextEventUpdateComplete(TInt aError) // from CDevCommonControl
1.321 + {
1.322 + DP_CONTEXT(CDevCommonControl::ContextEventUpdateComplete, CtxDevSound, DPLOCAL);
1.323 + DP_IN();
1.324 +
1.325 + if (iStateEventReceived)
1.326 + {
1.327 + iStateEventReceived = EFalse;
1.328 + DP0(DLINFO,"Context event for that does involve state change");
1.329 +
1.330 + if (aError)
1.331 + {
1.332 + ContextEventUpdateWithStateEventAndError(aError);
1.333 + }
1.334 + else
1.335 + {
1.336 + ContextEventUpdateWithStateEventNoError();
1.337 + }
1.338 + DP_OUT();
1.339 + return;
1.340 + }
1.341 +
1.342 + DP0(DLINFO,"Context event for that doesn't involve state change");
1.343 +
1.344 + if (aError)
1.345 + {
1.346 + ContextEventUpdateWithoutStateEventButWithError(aError);
1.347 + }
1.348 + else
1.349 + {
1.350 + ContextEventUpdateWithoutStateEventNoError();
1.351 + }
1.352 +
1.353 + DP_OUT();
1.354 + }
1.355 +
1.356 +
1.357 +void CDevCommonControl::ContextEventPreEmption(TUid aEvent, TInt aError) // from CDevCommonControl
1.358 + {
1.359 + DP_CONTEXT(CDevCommonControl::ContextEventPreEmption, CtxDevSound, DPLOCAL);
1.360 + DP_IN();
1.361 +
1.362 + DP1(DLERR,"Preemption error=%d", aError);
1.363 + CDevAudioControl::ContextEvent(aEvent, aError);
1.364 + iBeingPreempted=ETrue;
1.365 +
1.366 + DP_OUT();
1.367 + }
1.368 +
1.369 +
1.370 +void CDevCommonControl::ContextEventAbort(TInt aError) // from CDevCommonControl
1.371 + {
1.372 + DP_CONTEXT(CDevCommonControl::ContextEventAbort, CtxDevSound, DPLOCAL);
1.373 + DP_IN();
1.374 +
1.375 + DP1(DLERR,"Abort error=%d", aError);
1.376 + FinishWithError(aError==KErrAbort ? KErrDied:aError);
1.377 +
1.378 + DP_OUT();
1.379 + }
1.380 +
1.381 +
1.382 +void CDevCommonControl::ContextEventStopDevSoundNotifications() // from CDevCommonControl
1.383 + {
1.384 + DP_CONTEXT(CDevCommonControl::ContextEventStopDevSoundNotifications, CtxDevSound, DPLOCAL);
1.385 + DP_IN();
1.386 +
1.387 + iDevAudio->iAudioStream->UnregisterAudioStreamObserver(*this);
1.388 + iGainControl->UnregisterAudioGainControlObserver(*this);
1.389 + iAudioCodecIf->UnregisterAudioCodecObserver(*this);
1.390 + iAudioCodecIf = NULL;
1.391 +
1.392 + DP_OUT();
1.393 + }
1.394 +
1.395 +
1.396 +void CDevCommonControl::ContextEventPauseResumeSequenceDueToEmptyBuffers(TBool aFlush) // from CDevCommonControl
1.397 + {
1.398 + DP_CONTEXT(CDevCommonControl::ContextEventPauseResumeSequenceDueToEmptyBuffers, CtxDevSound, DPLOCAL);
1.399 + DP_IN();
1.400 +
1.401 + TInt err(KErrNone);
1.402 +
1.403 + if (iPauseResumeSequenceDueToEmptyBuffers)
1.404 + {
1.405 + if (aFlush)
1.406 + {
1.407 + err = iDevAudio->iAudioStream->Flush();
1.408 + }
1.409 +
1.410 + if ((err) or (aFlush==EFalse))
1.411 + {
1.412 + iPauseResumeSequenceDueToEmptyBuffers = EFalse;
1.413 + iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, err);
1.414 + }
1.415 + }
1.416 + else
1.417 + {
1.418 + iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
1.419 + }
1.420 +
1.421 + DP_OUT();
1.422 + }
1.423 +
1.424 +
1.425 +void CDevCommonControl::ContextEventStateDevSoundAdaptorUnloading() // from CDevCommonControl
1.426 + {
1.427 + DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorUnloading, CtxDevSound, DPLOCAL);
1.428 + DP_IN();
1.429 +
1.430 + // Due destruction sequence or reinitialization
1.431 + if (iDevAudio->iClosing or iDevAudio->iReinitializing)
1.432 + {
1.433 + TInt err = Uninitialize();
1.434 + if (err and iDevAudio->iReinitializing)
1.435 + {
1.436 + ContextEventAsynchronousInitializeComplete(err);
1.437 +
1.438 + }
1.439 +
1.440 + DP_OUT();
1.441 + return;
1.442 + }
1.443 +
1.444 + // Notify the user that ProcessingFinished is complete.
1.445 + // Stop call complete, sent callback.
1.446 + if (iCallbackFromAdaptor != KCallbackNone)
1.447 + {
1.448 + iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
1.449 +
1.450 + if (iCallbackFromAdaptor == KCallbackProcessingFinished)
1.451 + {
1.452 + FinishWithError(KErrUnderflow);
1.453 + }
1.454 + else if (iCallbackFromAdaptor == KCallbackProcessingUnitError)
1.455 + {
1.456 + FinishWithError(iProcessingUnitError);
1.457 + }
1.458 +
1.459 + iCallbackFromAdaptor = KCallbackNone;
1.460 + DP_OUT();
1.461 + return;
1.462 + }
1.463 +
1.464 + // Error condition
1.465 + if (iErrorCondition)
1.466 + {
1.467 + FinishWithError(iErrorCondition);
1.468 + iErrorCondition = KErrNone;
1.469 + }
1.470 + else
1.471 + {
1.472 +
1.473 + iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
1.474 + }
1.475 +
1.476 + DP_OUT();
1.477 + }
1.478 +
1.479 +
1.480 +void CDevCommonControl::ContextEventStateDevSoundAdaptorLoading() // from CDevCommonControl
1.481 + {
1.482 + DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorLoading, CtxDevSound, DPLOCAL);
1.483 + DP_IN();
1.484 +
1.485 + iDevAudio->RequestGainAndBalance(this); // TODO handle error
1.486 +
1.487 + TInt err = iDevAudio->iAudioStream->Activate();
1.488 + if (err)
1.489 + {
1.490 + DP_OUT();
1.491 + return;
1.492 + }
1.493 +
1.494 + err = iDevAudio->CommitAudioContext();
1.495 + if (err)
1.496 + {
1.497 + ContextEventAsynchronousPlayCompletion(err);
1.498 + DP_OUT();
1.499 + return;
1.500 + }
1.501 +
1.502 + iDevAudio->iActiveState = EDevSoundAdaptorActivating;
1.503 + iAdaptationObserver->AsynchronousOperationComplete(KErrNone, EFalse);
1.504 +
1.505 + DP_OUT();
1.506 + }
1.507 +
1.508 +
1.509 +void CDevCommonControl::ContextEventStateDevSoundAdaptorStopping() // from CDevCommonControl
1.510 + {
1.511 + DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorStopping, CtxDevSound, DPLOCAL);
1.512 + DP_IN();
1.513 +
1.514 + TInt err = Unload();
1.515 + if (err)
1.516 + {
1.517 + DP0(DLINFO,"Commit failed during stopping");
1.518 + FinishWithError(err);
1.519 + }
1.520 +
1.521 + __ASSERT_DEBUG(err==KErrNone, Panic(ECommitFailedDuringStop));
1.522 +
1.523 + DP_OUT();
1.524 + }
1.525 +
1.526 +
1.527 +void CDevCommonControl::ContextEventStateDevSoundAdaptorBeingPreempted() // from CDevCommonControl
1.528 + {
1.529 + DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorBeingPreempted, CtxDevSound, DPLOCAL);
1.530 + DP_IN();
1.531 +
1.532 + __ASSERT_DEBUG(iDevAudio->iActiveStreamState == EInitialized, Panic(EStreamBeingDemotedToEIdle));
1.533 + FinishWithError(KErrInUse);
1.534 + if (iIgnoreAsyncOpComplete)
1.535 + {
1.536 + iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
1.537 + iIgnoreAsyncOpComplete=EFalse;
1.538 + DP_OUT();
1.539 + return;
1.540 + }
1.541 +
1.542 + ContextEventPauseResumeSequenceDueToEmptyBuffers(EFalse);
1.543 +
1.544 + DP_OUT();
1.545 + }
1.546 +
1.547 +
1.548 +void CDevCommonControl::ContextEventStateDevSoundAdaptorUninitializing() // from CDevCommonControl
1.549 + {
1.550 + DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorUninitializing, CtxDevSound, DPLOCAL);
1.551 + DP_IN();
1.552 + TInt err = RemoveProcessingUnits();
1.553 +
1.554 + if (err == KErrNone)
1.555 + {
1.556 + iDevAudio->iActiveState = EDevSoundAdaptorRemovingProcessingUnits;
1.557 + }
1.558 + else if (iDevAudio->iReinitializing)
1.559 + {
1.560 + ContextEventAsynchronousInitializeComplete(err);
1.561 + }
1.562 +
1.563 + DP_OUT();
1.564 + }
1.565 +
1.566 +
1.567 +void CDevCommonControl::ContextEventErrorStateDevSoundAdaptorActivating(TInt aError) // from CDevCommonControl
1.568 + {
1.569 + DP_CONTEXT(CDevCommonControl::ContextEventErrorStateDevSoundAdaptorActivating, CtxDevSound, DPLOCAL);
1.570 + DP_IN();
1.571 +
1.572 + // If the resume operation fails as result of EmptyBuffers
1.573 + // Notify about operation complete through CallbackFromAdaptorReceived
1.574 + // and continue to allow client to receive PlayError()
1.575 + if (iPauseResumeSequenceDueToEmptyBuffers)
1.576 + {
1.577 + iPauseResumeSequenceDueToEmptyBuffers = EFalse;
1.578 + iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, KErrNone);
1.579 + }
1.580 +
1.581 + iErrorCondition = aError;
1.582 +
1.583 + TInt err = Unload();
1.584 + if (err)
1.585 + {
1.586 + DP0(DLINFO,"Commit failed during stopping");
1.587 + FinishWithError(err);
1.588 + }
1.589 + __ASSERT_DEBUG(err==KErrNone, Panic(ECommitFailedDuringStop));
1.590 +
1.591 + DP_OUT();
1.592 + }
1.593 +
1.594 +
1.595 +void CDevCommonControl::ContextEventErrorStateDevSoundAdaptorBeingPreempted() // from CDevCommonControl
1.596 + {
1.597 + DP_CONTEXT(CDevCommonControl::ContextEventErrorStateDevSoundAdaptorBeingPreempted, CtxDevSound, DPLOCAL);
1.598 + DP_IN();
1.599 +
1.600 +__ASSERT_DEBUG(iDevAudio->iActiveStreamState == EInitialized, Panic(EStreamBeingDemotedToEIdle));
1.601 + FinishWithError(KErrInUse);
1.602 +
1.603 + if(iIgnoreAsyncOpComplete)
1.604 + {
1.605 + iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
1.606 + }
1.607 +
1.608 + DP_OUT();
1.609 + }
1.610 +
1.611 +
1.612 +void CDevCommonControl::ContextEventUpdateWithoutStateEventNoError() // from CDevCommonControl
1.613 + {
1.614 + DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithoutStateEventNoError, CtxDevSound, DPLOCAL);
1.615 + DP2_IN("iActiveState=%d iIgnoreAsyncOpComplete=%d",iDevAudio->iActiveState, iIgnoreAsyncOpComplete);
1.616 +
1.617 + if (iDevAudio->iActiveState != EDevSoundAdaptorRemovingProcessingUnits)
1.618 + {
1.619 + if (iIgnoreAsyncOpComplete)
1.620 + {
1.621 + iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
1.622 + iIgnoreAsyncOpComplete = EFalse;
1.623 + }
1.624 + else
1.625 + {
1.626 + iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
1.627 + }
1.628 + DP_OUT();
1.629 + return;
1.630 + }
1.631 +
1.632 + //If the Commit cycle when going into EDevSoundAdaptorRemovingProcessingUnits fails due to pre-emption
1.633 + //clash then we re-apply the client request again.
1.634 + if (iDevAudio->iActiveState == EDevSoundAdaptorRemovingProcessingUnits && iIgnoreAsyncOpComplete)
1.635 + {
1.636 + //Pop front of queue to re-apply the request again via CMMFDevSoundSession::DequeueRequest
1.637 + //from the callback into CMMFDevSoundSession below:
1.638 + iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
1.639 + iIgnoreAsyncOpComplete = EFalse;
1.640 + DP_OUT();
1.641 + return;
1.642 + }
1.643 +
1.644 + iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised;
1.645 +
1.646 + if (iDevAudio->iReinitializing)
1.647 + {
1.648 + ContextEventStopDevSoundNotifications();
1.649 +
1.650 + TInt err = iDevAudio->Initialize(iDevAudio->iTargetFormat, iDevAudio->iTargetMode);
1.651 + if(err)
1.652 + {
1.653 + ContextEventAsynchronousInitializeComplete(err);
1.654 + }
1.655 +
1.656 + iDevAudio->iReinitializing = EFalse;
1.657 + DP_OUT();
1.658 + return;
1.659 + }
1.660 +
1.661 + iDevAudio->iClosing = EFalse;
1.662 + iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
1.663 +
1.664 + DP_OUT();
1.665 + }
1.666 +
1.667 +
1.668 +void CDevCommonControl::ContextEventUpdateWithoutStateEventButWithError(TInt aError) // from CDevCommonControl
1.669 + {
1.670 + DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithoutStateEventButWithError, CtxDevSound, DPLOCAL);
1.671 + DP_IN();
1.672 +
1.673 + //If flag is true below then it must be due to a stateless normal pre-emption or
1.674 + //stateless pre-emption clash scenario.
1.675 + if(iIgnoreAsyncOpComplete)
1.676 + {
1.677 + //If we are in pre-emption clash then callback below will retry the client request again.
1.678 + iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); // notify client of end of cycle
1.679 + iIgnoreAsyncOpComplete = EFalse;
1.680 + }
1.681 + else
1.682 + {
1.683 + TDevSoundAdaptorState previousState = iDevAudio->iPreviousState;
1.684 +
1.685 + DP3(DLINFO,"Error with no state change, state %d, previous %d, error %d during Commit cycle",
1.686 + iDevAudio->iActiveState, previousState, aError);
1.687 +
1.688 + // We can end up here for a number of reasons. For non "mid states", this is
1.689 + // a standard error scenario. For some mid-states (e.g. Activating, Loading etc),
1.690 + // when we try and "promote" the state, this happens when the promotion is rejected
1.691 + // and we handle thus accordingly. For other mid-states the situation is less clear
1.692 + // and we call AsynchronousOperationComplete() with the error assuming the parent
1.693 + // session will deal with it. Whatever we don't want to stay in a mid-state, so
1.694 + // rewind to the previous ("normal") one if we are in one.
1.695 +
1.696 + // Longer term TODO. If the code were refactored so that the InitializeComplete(),
1.697 + // PlayError() etc callback came from AsynchronousOperationComplete() then the
1.698 + // following code might be simpler. Most of the time (at least) we get here because
1.699 + // we are doing a session function, and we can use the function to determine what
1.700 + // to do more easily than relying on the state. As it is, for some mid-states we
1.701 + // try and work out what error code to generate. Not clear this covers 100% cases,
1.702 + // although demotion transitions should not fail, so the problem cases might not occur.
1.703 + //
1.704 +
1.705 + //If we reach this condition then it is because of rejection/error during Commit cycle.
1.706 + switch (iDevAudio->iActiveState)
1.707 + {
1.708 + case EDevSoundAdaptorInitialising:
1.709 + {
1.710 + iDevAudio->iActiveState = previousState;
1.711 + ContextEventAsynchronousInitializeComplete(aError);
1.712 + break;
1.713 + }
1.714 + case EDevSoundAdaptorLoading:
1.715 + {
1.716 + iDevAudio->iActiveState = previousState;
1.717 + ContextEventAsynchronousPlayCompletion(aError);
1.718 + break;
1.719 + }
1.720 + case EDevSoundAdaptorActivating:
1.721 + {
1.722 + iDevAudio->iActiveState = previousState;
1.723 + ContextEventAsynchronousPlayCompletion(aError);
1.724 + break;
1.725 + }
1.726 + case EDevSoundAdaptorRemovingProcessingUnits:
1.727 + case EDevSoundAdaptorUninitialising:
1.728 + case EDevSoundAdaptorUnloading:
1.729 + case EDevSoundAdaptorStopping:
1.730 + case EDevSoundAdaptorPausing:
1.731 + {
1.732 + DP2(DLINFO,"Unexpected mid state [%d] when handling error [%d] during Commit cycle, workback", iDevAudio->iActiveState, aError);
1.733 + iDevAudio->iActiveState = previousState;
1.734 + iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
1.735 + break;
1.736 + }
1.737 + default:
1.738 + {
1.739 + DP2(DLINFO,"Unexpected state [%d] when handling error [%d] during Commit cycle", iDevAudio->iActiveState, aError);
1.740 + iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
1.741 + }
1.742 + }
1.743 + }
1.744 +
1.745 + DP_OUT();
1.746 + }
1.747 +
1.748 +
1.749 +void CDevCommonControl::ContextEventUpdateWithStateEventNoError() // from CDevCommonControl
1.750 + {
1.751 + DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithStateEventNoError, CtxDevSound, DPLOCAL);
1.752 + DP_IN();
1.753 +
1.754 + switch (iDevAudio->iActiveState)
1.755 + {
1.756 + case EDevSoundAdaptorUninitialising:
1.757 + iDevAudio->iActiveState = EDevSoundAdaptorUnitialised_Uninitialised;
1.758 + ContextEventStateDevSoundAdaptorUninitializing();
1.759 + break;
1.760 +
1.761 + case EDevSoundAdaptorInitialising:
1.762 + iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
1.763 + ContextEventAsynchronousInitializeComplete(KErrNone);
1.764 + break;
1.765 +
1.766 + case EDevSoundAdaptorUnloading:
1.767 + iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
1.768 + ContextEventStateDevSoundAdaptorUnloading();
1.769 + break;
1.770 +
1.771 + case EDevSoundAdaptorLoading:
1.772 + iDevAudio->iActiveState = EDevSoundAdaptorGoingActive;
1.773 + ContextEventStateDevSoundAdaptorLoading();
1.774 + break;
1.775 +
1.776 + case EDevSoundAdaptorStopping:
1.777 + iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Idle;
1.778 + ContextEventStateDevSoundAdaptorStopping();
1.779 + break;
1.780 +
1.781 + case EDevSoundAdaptorActivating:
1.782 + iDevAudio->iActiveState = EDevSoundAdaptorActive_Active;
1.783 + ContextEventPauseResumeSequenceDueToEmptyBuffers(EFalse);
1.784 + break;
1.785 +
1.786 + case EDevSoundAdaptorPausing:
1.787 + iDevAudio->iActiveState = EDevSoundAdaptorPaused_Primed;
1.788 + ContextEventPauseResumeSequenceDueToEmptyBuffers(ETrue);
1.789 + break;
1.790 +
1.791 + case EDevSoundAdaptorBeingPreempted:
1.792 + iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
1.793 + ContextEventStateDevSoundAdaptorBeingPreempted();
1.794 + break;
1.795 +
1.796 + default:
1.797 + break;
1.798 + }
1.799 +
1.800 + DP_OUT();
1.801 + }
1.802 +
1.803 +
1.804 +void CDevCommonControl::ContextEventUpdateWithStateEventAndError(TInt aError) // from CDevCommonControl
1.805 + {
1.806 + DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithStateEventAndError, CtxDevSound, DPLOCAL);
1.807 + DP_IN();
1.808 +
1.809 + DP1(DLERR,"ContextEventUpdateWithStateEventAndError error=%d", aError);
1.810 +
1.811 + switch(iDevAudio->iActiveState)
1.812 + {
1.813 + case EDevSoundAdaptorInitialising:
1.814 + iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised;
1.815 + iAdaptationObserver->InitializeComplete(aError);
1.816 + break;
1.817 +
1.818 + case EDevSoundAdaptorLoading:
1.819 + iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
1.820 + FinishWithError(aError);
1.821 + break;
1.822 +
1.823 + case EDevSoundAdaptorActivating:
1.824 + iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Idle;
1.825 + ContextEventErrorStateDevSoundAdaptorActivating(aError);
1.826 + break;
1.827 +
1.828 + case EDevSoundAdaptorBeingPreempted:
1.829 + iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
1.830 + ContextEventErrorStateDevSoundAdaptorBeingPreempted();
1.831 + break;
1.832 +
1.833 + default:
1.834 + break;
1.835 + }
1.836 +
1.837 + iCallbackFromAdaptor = KCallbackNone;
1.838 +
1.839 + if(!iIgnoreAsyncOpComplete)
1.840 + {
1.841 + iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
1.842 + }
1.843 + else
1.844 + {
1.845 + iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
1.846 + iIgnoreAsyncOpComplete=EFalse;
1.847 + }
1.848 +
1.849 + DP_OUT();
1.850 + }
1.851 +
1.852 +
1.853 +// end of file