|
1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "cdevcommoncontrol.h" |
|
17 #include <a3f/maudiocontext.h> |
|
18 #include <a3f/maudiocodec.h> |
|
19 |
|
20 |
|
21 CDevCommonControl::CDevCommonControl() |
|
22 { |
|
23 TRACE_CREATE(); |
|
24 DP_CONTEXT(CDevCommonControl::CDevCommonControl, CtxDevSound, DPLOCAL); |
|
25 DP_IN(); |
|
26 DP_OUT(); |
|
27 } |
|
28 |
|
29 |
|
30 CDevCommonControl::~CDevCommonControl() |
|
31 { |
|
32 DP_CONTEXT(CDevCommonControl::~CDevCommonControl, CtxDevSound, DPLOCAL); |
|
33 DP_IN(); |
|
34 DP_OUT(); |
|
35 } |
|
36 |
|
37 |
|
38 TInt CDevCommonControl::Stop() // from CDevAudioControl |
|
39 { |
|
40 DP_CONTEXT(CDevCommonControl::Stop, CtxDevSound, DPLOCAL); |
|
41 DP_IN(); |
|
42 |
|
43 TInt err = KErrNone; |
|
44 switch(iDevAudio->iActiveState) |
|
45 { |
|
46 case EDevSoundAdaptorActive_Active: |
|
47 case EDevSoundAdaptorPaused_Primed: |
|
48 err = iDevAudio->iAudioStream->Stop(); |
|
49 if (err == KErrNone) |
|
50 { |
|
51 err = iDevAudio->CommitAudioContext(); |
|
52 } |
|
53 if (err == KErrNone) |
|
54 { |
|
55 iDevAudio->iActiveState = EDevSoundAdaptorStopping; |
|
56 } |
|
57 break; |
|
58 case EDevSoundAdaptorGoingActive: |
|
59 iDevAudio->iActiveState = EDevSoundAdaptorStopping; |
|
60 break; |
|
61 case EDevSoundAdaptorInitialised_Idle: |
|
62 { |
|
63 //If following condition is true, then we are here because of a |
|
64 //pre-emption clash in last Commit cycle started from |
|
65 //CDevCommonControl::ContextEventUpdateWithStateEventNoError. |
|
66 if(iDevAudio->iPreviousState == EDevSoundAdaptorUnloading) |
|
67 { |
|
68 err = Unload(); |
|
69 break; |
|
70 } |
|
71 } |
|
72 default: |
|
73 break; |
|
74 } |
|
75 |
|
76 if(err == KErrNone) |
|
77 { |
|
78 iDevAudio->iStop = ETrue; |
|
79 } |
|
80 |
|
81 DP0_RET(err,"%d"); |
|
82 } |
|
83 |
|
84 |
|
85 TInt CDevCommonControl::Pause() // from CDevAudioControl |
|
86 { |
|
87 DP_CONTEXT(CDevCommonControl::Pause, CtxDevSound, DPLOCAL); |
|
88 DP_IN(); |
|
89 |
|
90 TInt err = iDevAudio->iAudioStream->Prime(); |
|
91 if ( err == KErrNone) |
|
92 { |
|
93 err = iDevAudio->CommitAudioContext(); |
|
94 } |
|
95 if (err == KErrNone) |
|
96 { |
|
97 iDevAudio->iActiveState = EDevSoundAdaptorPausing; |
|
98 } |
|
99 |
|
100 DP0_RET(err,"%d"); |
|
101 } |
|
102 |
|
103 |
|
104 TInt CDevCommonControl::Resume() // from CDevAudioControl |
|
105 { |
|
106 DP_CONTEXT(CDevCommonControl::Resume, CtxDevSound, DPLOCAL); |
|
107 DP_IN(); |
|
108 |
|
109 TInt err = KErrNone; |
|
110 |
|
111 //If following condition is true, then we are here because of a |
|
112 //pre-emption clash in last Commit cycle started from |
|
113 //CDevCommonControl::ContextEventUpdateWithStateEventAndError. |
|
114 if(iDevAudio->iActiveState == EDevSoundAdaptorInitialised_Idle && |
|
115 iDevAudio->iPreviousState == EDevSoundAdaptorUnloading) |
|
116 { |
|
117 err = Unload(); |
|
118 DP0_RET(err,"%d"); |
|
119 } |
|
120 else if(iDevAudio->iActiveState != EDevSoundAdaptorPaused_Primed) |
|
121 { |
|
122 DP0_RET(KErrNotReady, "%d"); |
|
123 } |
|
124 |
|
125 if(err == KErrNone) |
|
126 { |
|
127 // Populate gain and balance values set in the Paused state and being cached |
|
128 err = iDevAudio->RequestGainAndBalance(this); |
|
129 } |
|
130 if(err == KErrNone) |
|
131 { |
|
132 err = iDevAudio->iAudioStream->Activate(); |
|
133 } |
|
134 if ( err == KErrNone) |
|
135 { |
|
136 err = iDevAudio->CommitAudioContext(); |
|
137 } |
|
138 if (err == KErrNone) |
|
139 { |
|
140 iDevAudio->iActiveState = EDevSoundAdaptorActivating; |
|
141 } |
|
142 |
|
143 DP0_RET(err,"%d"); |
|
144 } |
|
145 |
|
146 |
|
147 void CDevCommonControl::StateEvent(MAudioStream& aStream, TInt aError, // from MAudioProcessingUnitObserver |
|
148 TAudioState aNewState) |
|
149 { |
|
150 DP_CONTEXT(CDevCommonControl::StateEvent, CtxDevSound, DPLOCAL); |
|
151 DP3_IN("activeState %d -> newstate %d, (%d)", |
|
152 iDevAudio->iActiveState, aNewState, aError); |
|
153 |
|
154 __ASSERT_ALWAYS(iDevAudio->iAudioStream == &aStream, Panic(EStreamMismatch)); |
|
155 |
|
156 if(aError != KErrNone || iDevAudio->iActiveStreamState != aNewState) |
|
157 { |
|
158 iDevAudio->iActiveStreamState = aNewState; |
|
159 iStateEventReceived = ETrue; |
|
160 } |
|
161 // Since the audiostream already demoted the state for the most of the cases |
|
162 // only is need when a error comes were the stream was at the middle of A3f two-phase transition |
|
163 else |
|
164 { |
|
165 switch (aNewState) |
|
166 { |
|
167 case EIdle: |
|
168 // Demote the stream state |
|
169 iDevAudio->iActiveStreamState = EIdle; |
|
170 break; |
|
171 default: |
|
172 break; |
|
173 } |
|
174 } |
|
175 iStateEventError = aError; |
|
176 |
|
177 DP_OUT(); |
|
178 } |
|
179 |
|
180 |
|
181 void CDevCommonControl::ProcessingUnitError(MAudioProcessingUnit* /*aInstance*/, // from MAudioProcessingUnitObserver |
|
182 TInt aError) |
|
183 { |
|
184 DP_CONTEXT(CDevCommonControl::ProcessingUnitError, CtxDevSound, DPLOCAL); |
|
185 DP_IN(); |
|
186 |
|
187 if(iCallbackFromAdaptor == KCallbackNone) |
|
188 { |
|
189 iProcessingUnitError = aError; |
|
190 iCallbackFromAdaptor = KCallbackProcessingUnitError; |
|
191 iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackProcessingUnitError, aError); |
|
192 } |
|
193 else |
|
194 { |
|
195 // Multiple callbacks from adaptor |
|
196 DP0(DLINFO, "Multiple callbacks from adaptor"); |
|
197 } |
|
198 |
|
199 DP_OUT(); |
|
200 } |
|
201 |
|
202 |
|
203 void CDevCommonControl::ContextEvent(TUid aEvent, TInt aError) |
|
204 { |
|
205 DP_CONTEXT(CDevCommonControl::ContextEvent, CtxDevSound, DPLOCAL); |
|
206 DP3_IN("ContextEvent aEvent=%x iActiveState=%d aError=%d",aEvent, iDevAudio->iActiveState, aError); |
|
207 |
|
208 // Can't "switch {...}" on UIDs unfortunately: |
|
209 if (aEvent == KUidA3FContextUpdateComplete) |
|
210 { |
|
211 if(iBeingPreempted) |
|
212 { |
|
213 if(iStateEventReceived) |
|
214 { |
|
215 //use a sub state pattern to make pre-emption cycles like other cycles. |
|
216 DP1(DLERR,"Preemption error=%d", aError); |
|
217 iDevAudio->iActiveState = EDevSoundAdaptorBeingPreempted; |
|
218 if(iPreemptionClash) |
|
219 { |
|
220 // remove last request from front of queue without processing it |
|
221 iAdaptationObserver->PreemptionClashWithStateChange(); |
|
222 iPreemptionClash=EFalse; |
|
223 } |
|
224 } |
|
225 else if(!iStateEventReceived && iPreemptionClash) |
|
226 { |
|
227 iIgnoreAsyncOpComplete=ETrue; |
|
228 iPreemptionClash=EFalse; |
|
229 } |
|
230 iBeingPreempted=EFalse; |
|
231 } |
|
232 ContextEventUpdateComplete(aError); |
|
233 } |
|
234 |
|
235 else if ((aEvent == KUidA3FContextCommitUpdate)) |
|
236 { |
|
237 iBeingPreempted=EFalse; // clear being preempted |
|
238 iPreemptionClash=EFalse; // clear pre-emption clash flag |
|
239 TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext(); |
|
240 iIgnoreAsyncOpComplete = !adaptorControlsContext; |
|
241 // if we don't control context, always send a PreemptionFinishedCallbackReceived() |
|
242 iStateEventReceived=EFalse; |
|
243 } |
|
244 |
|
245 else if (aEvent == KUidA3FContextPreEmption) |
|
246 { |
|
247 // clear iBeingPreepted - will be set in ContextEventPreEmption if req |
|
248 iBeingPreempted=EFalse; |
|
249 iPreemptionClash=EFalse; // clear pre-emption clash flag |
|
250 TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext(); |
|
251 iStateEventReceived=EFalse; |
|
252 iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete |
|
253 ContextEventPreEmption(aEvent, aError); |
|
254 if (!adaptorControlsContext) |
|
255 { |
|
256 iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete |
|
257 } |
|
258 } |
|
259 else if (aEvent == KUidA3FContextPreEmptedCommit) |
|
260 { |
|
261 DP0(DLINFO,"KUidA3FContextPreEmptedCommit event received, thus clash with Pre-emption"); |
|
262 // clear iBeingPreepted - will be set in ContextEventPreEmption if req |
|
263 iBeingPreempted=EFalse; |
|
264 TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext(); |
|
265 if (adaptorControlsContext) |
|
266 { |
|
267 // push current request that was being processed onto front of queue. |
|
268 iAdaptationObserver->PreemptionClash(); |
|
269 iPreemptionClash=ETrue; |
|
270 } |
|
271 iStateEventReceived=EFalse; |
|
272 iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete |
|
273 ContextEventPreEmption(aEvent, aError); |
|
274 if (!adaptorControlsContext) |
|
275 { |
|
276 iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete |
|
277 } |
|
278 } |
|
279 |
|
280 else if (aEvent == KUidA3FContextAbort) |
|
281 { |
|
282 ContextEventAbort(aError); |
|
283 } |
|
284 |
|
285 DP_OUT(); |
|
286 } |
|
287 |
|
288 |
|
289 void CDevCommonControl::ContextEventAsynchronousPlayCompletion(TInt aError) // from CDevCommonControl |
|
290 { |
|
291 DP_CONTEXT(CDevCommonControl::ContextEventAsynchronousPlayCompletion, CtxDevSound, DPLOCAL); |
|
292 DP_IN(); |
|
293 |
|
294 iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue); |
|
295 |
|
296 if (aError) |
|
297 { |
|
298 FinishWithError(aError); |
|
299 } |
|
300 |
|
301 DP_OUT(); |
|
302 } |
|
303 |
|
304 |
|
305 void CDevCommonControl::ContextEventAsynchronousInitializeComplete(TInt aError) // from CDevCommonControl |
|
306 { |
|
307 DP_CONTEXT(CDevCommonControl::ContextEventAsynchronousInitializeComplete, CtxDevSound, DPLOCAL); |
|
308 DP_IN(); |
|
309 |
|
310 iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue); |
|
311 iAdaptationObserver->InitializeComplete(aError); |
|
312 |
|
313 DP_OUT(); |
|
314 } |
|
315 |
|
316 |
|
317 void CDevCommonControl::ContextEventUpdateComplete(TInt aError) // from CDevCommonControl |
|
318 { |
|
319 DP_CONTEXT(CDevCommonControl::ContextEventUpdateComplete, CtxDevSound, DPLOCAL); |
|
320 DP_IN(); |
|
321 |
|
322 if (iStateEventReceived) |
|
323 { |
|
324 iStateEventReceived = EFalse; |
|
325 DP0(DLINFO,"Context event for that does involve state change"); |
|
326 |
|
327 if (aError) |
|
328 { |
|
329 ContextEventUpdateWithStateEventAndError(aError); |
|
330 } |
|
331 else |
|
332 { |
|
333 ContextEventUpdateWithStateEventNoError(); |
|
334 } |
|
335 DP_OUT(); |
|
336 return; |
|
337 } |
|
338 |
|
339 DP0(DLINFO,"Context event for that doesn't involve state change"); |
|
340 |
|
341 if (aError) |
|
342 { |
|
343 ContextEventUpdateWithoutStateEventButWithError(aError); |
|
344 } |
|
345 else |
|
346 { |
|
347 ContextEventUpdateWithoutStateEventNoError(); |
|
348 } |
|
349 |
|
350 DP_OUT(); |
|
351 } |
|
352 |
|
353 |
|
354 void CDevCommonControl::ContextEventPreEmption(TUid aEvent, TInt aError) // from CDevCommonControl |
|
355 { |
|
356 DP_CONTEXT(CDevCommonControl::ContextEventPreEmption, CtxDevSound, DPLOCAL); |
|
357 DP_IN(); |
|
358 |
|
359 DP1(DLERR,"Preemption error=%d", aError); |
|
360 CDevAudioControl::ContextEvent(aEvent, aError); |
|
361 iBeingPreempted=ETrue; |
|
362 |
|
363 DP_OUT(); |
|
364 } |
|
365 |
|
366 |
|
367 void CDevCommonControl::ContextEventAbort(TInt aError) // from CDevCommonControl |
|
368 { |
|
369 DP_CONTEXT(CDevCommonControl::ContextEventAbort, CtxDevSound, DPLOCAL); |
|
370 DP_IN(); |
|
371 |
|
372 DP1(DLERR,"Abort error=%d", aError); |
|
373 FinishWithError(aError==KErrAbort ? KErrDied:aError); |
|
374 |
|
375 DP_OUT(); |
|
376 } |
|
377 |
|
378 |
|
379 void CDevCommonControl::ContextEventStopDevSoundNotifications() // from CDevCommonControl |
|
380 { |
|
381 DP_CONTEXT(CDevCommonControl::ContextEventStopDevSoundNotifications, CtxDevSound, DPLOCAL); |
|
382 DP_IN(); |
|
383 |
|
384 iDevAudio->iAudioStream->UnregisterAudioStreamObserver(*this); |
|
385 iGainControl->UnregisterAudioGainControlObserver(*this); |
|
386 iAudioCodecIf->UnregisterAudioCodecObserver(*this); |
|
387 iAudioCodecIf = NULL; |
|
388 |
|
389 DP_OUT(); |
|
390 } |
|
391 |
|
392 |
|
393 void CDevCommonControl::ContextEventPauseResumeSequenceDueToEmptyBuffers(TBool aFlush) // from CDevCommonControl |
|
394 { |
|
395 DP_CONTEXT(CDevCommonControl::ContextEventPauseResumeSequenceDueToEmptyBuffers, CtxDevSound, DPLOCAL); |
|
396 DP_IN(); |
|
397 |
|
398 TInt err(KErrNone); |
|
399 |
|
400 if (iPauseResumeSequenceDueToEmptyBuffers) |
|
401 { |
|
402 if (aFlush) |
|
403 { |
|
404 err = iDevAudio->iAudioStream->Flush(); |
|
405 } |
|
406 |
|
407 if ((err) or (aFlush==EFalse)) |
|
408 { |
|
409 iPauseResumeSequenceDueToEmptyBuffers = EFalse; |
|
410 iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, err); |
|
411 } |
|
412 } |
|
413 else |
|
414 { |
|
415 iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue); |
|
416 } |
|
417 |
|
418 DP_OUT(); |
|
419 } |
|
420 |
|
421 |
|
422 void CDevCommonControl::ContextEventStateDevSoundAdaptorUnloading() // from CDevCommonControl |
|
423 { |
|
424 DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorUnloading, CtxDevSound, DPLOCAL); |
|
425 DP_IN(); |
|
426 |
|
427 // Due destruction sequence or reinitialization |
|
428 if (iDevAudio->iClosing or iDevAudio->iReinitializing) |
|
429 { |
|
430 TInt err = Uninitialize(); |
|
431 if (err and iDevAudio->iReinitializing) |
|
432 { |
|
433 ContextEventAsynchronousInitializeComplete(err); |
|
434 |
|
435 } |
|
436 |
|
437 DP_OUT(); |
|
438 return; |
|
439 } |
|
440 |
|
441 // Notify the user that ProcessingFinished is complete. |
|
442 // Stop call complete, sent callback. |
|
443 if (iCallbackFromAdaptor != KCallbackNone) |
|
444 { |
|
445 iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue); |
|
446 |
|
447 if (iCallbackFromAdaptor == KCallbackProcessingFinished) |
|
448 { |
|
449 FinishWithError(KErrUnderflow); |
|
450 } |
|
451 else if (iCallbackFromAdaptor == KCallbackProcessingUnitError) |
|
452 { |
|
453 FinishWithError(iProcessingUnitError); |
|
454 } |
|
455 |
|
456 iCallbackFromAdaptor = KCallbackNone; |
|
457 DP_OUT(); |
|
458 return; |
|
459 } |
|
460 |
|
461 // Error condition |
|
462 if (iErrorCondition) |
|
463 { |
|
464 FinishWithError(iErrorCondition); |
|
465 iErrorCondition = KErrNone; |
|
466 } |
|
467 else |
|
468 { |
|
469 |
|
470 iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue); |
|
471 } |
|
472 |
|
473 DP_OUT(); |
|
474 } |
|
475 |
|
476 |
|
477 void CDevCommonControl::ContextEventStateDevSoundAdaptorLoading() // from CDevCommonControl |
|
478 { |
|
479 DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorLoading, CtxDevSound, DPLOCAL); |
|
480 DP_IN(); |
|
481 |
|
482 iDevAudio->RequestGainAndBalance(this); // TODO handle error |
|
483 |
|
484 TInt err = iDevAudio->iAudioStream->Activate(); |
|
485 if (err) |
|
486 { |
|
487 DP_OUT(); |
|
488 return; |
|
489 } |
|
490 |
|
491 err = iDevAudio->CommitAudioContext(); |
|
492 if (err) |
|
493 { |
|
494 ContextEventAsynchronousPlayCompletion(err); |
|
495 DP_OUT(); |
|
496 return; |
|
497 } |
|
498 |
|
499 iDevAudio->iActiveState = EDevSoundAdaptorActivating; |
|
500 iAdaptationObserver->AsynchronousOperationComplete(KErrNone, EFalse); |
|
501 |
|
502 DP_OUT(); |
|
503 } |
|
504 |
|
505 |
|
506 void CDevCommonControl::ContextEventStateDevSoundAdaptorStopping() // from CDevCommonControl |
|
507 { |
|
508 DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorStopping, CtxDevSound, DPLOCAL); |
|
509 DP_IN(); |
|
510 |
|
511 TInt err = Unload(); |
|
512 if (err) |
|
513 { |
|
514 DP0(DLINFO,"Commit failed during stopping"); |
|
515 FinishWithError(err); |
|
516 } |
|
517 |
|
518 __ASSERT_DEBUG(err==KErrNone, Panic(ECommitFailedDuringStop)); |
|
519 |
|
520 DP_OUT(); |
|
521 } |
|
522 |
|
523 |
|
524 void CDevCommonControl::ContextEventStateDevSoundAdaptorBeingPreempted() // from CDevCommonControl |
|
525 { |
|
526 DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorBeingPreempted, CtxDevSound, DPLOCAL); |
|
527 DP_IN(); |
|
528 |
|
529 __ASSERT_DEBUG(iDevAudio->iActiveStreamState == EInitialized, Panic(EStreamBeingDemotedToEIdle)); |
|
530 FinishWithError(KErrInUse); |
|
531 if (iIgnoreAsyncOpComplete) |
|
532 { |
|
533 iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); |
|
534 iIgnoreAsyncOpComplete=EFalse; |
|
535 DP_OUT(); |
|
536 return; |
|
537 } |
|
538 |
|
539 ContextEventPauseResumeSequenceDueToEmptyBuffers(EFalse); |
|
540 |
|
541 DP_OUT(); |
|
542 } |
|
543 |
|
544 |
|
545 void CDevCommonControl::ContextEventStateDevSoundAdaptorUninitializing() // from CDevCommonControl |
|
546 { |
|
547 DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorUninitializing, CtxDevSound, DPLOCAL); |
|
548 DP_IN(); |
|
549 TInt err = RemoveProcessingUnits(); |
|
550 |
|
551 if (err == KErrNone) |
|
552 { |
|
553 iDevAudio->iActiveState = EDevSoundAdaptorRemovingProcessingUnits; |
|
554 } |
|
555 else if (iDevAudio->iReinitializing) |
|
556 { |
|
557 ContextEventAsynchronousInitializeComplete(err); |
|
558 } |
|
559 |
|
560 DP_OUT(); |
|
561 } |
|
562 |
|
563 |
|
564 void CDevCommonControl::ContextEventErrorStateDevSoundAdaptorActivating(TInt aError) // from CDevCommonControl |
|
565 { |
|
566 DP_CONTEXT(CDevCommonControl::ContextEventErrorStateDevSoundAdaptorActivating, CtxDevSound, DPLOCAL); |
|
567 DP_IN(); |
|
568 |
|
569 // If the resume operation fails as result of EmptyBuffers |
|
570 // Notify about operation complete through CallbackFromAdaptorReceived |
|
571 // and continue to allow client to receive PlayError() |
|
572 if (iPauseResumeSequenceDueToEmptyBuffers) |
|
573 { |
|
574 iPauseResumeSequenceDueToEmptyBuffers = EFalse; |
|
575 iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, KErrNone); |
|
576 } |
|
577 |
|
578 iErrorCondition = aError; |
|
579 |
|
580 TInt err = Unload(); |
|
581 if (err) |
|
582 { |
|
583 DP0(DLINFO,"Commit failed during stopping"); |
|
584 FinishWithError(err); |
|
585 } |
|
586 __ASSERT_DEBUG(err==KErrNone, Panic(ECommitFailedDuringStop)); |
|
587 |
|
588 DP_OUT(); |
|
589 } |
|
590 |
|
591 |
|
592 void CDevCommonControl::ContextEventErrorStateDevSoundAdaptorBeingPreempted() // from CDevCommonControl |
|
593 { |
|
594 DP_CONTEXT(CDevCommonControl::ContextEventErrorStateDevSoundAdaptorBeingPreempted, CtxDevSound, DPLOCAL); |
|
595 DP_IN(); |
|
596 |
|
597 __ASSERT_DEBUG(iDevAudio->iActiveStreamState == EInitialized, Panic(EStreamBeingDemotedToEIdle)); |
|
598 FinishWithError(KErrInUse); |
|
599 |
|
600 if(iIgnoreAsyncOpComplete) |
|
601 { |
|
602 iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); |
|
603 } |
|
604 |
|
605 DP_OUT(); |
|
606 } |
|
607 |
|
608 |
|
609 void CDevCommonControl::ContextEventUpdateWithoutStateEventNoError() // from CDevCommonControl |
|
610 { |
|
611 DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithoutStateEventNoError, CtxDevSound, DPLOCAL); |
|
612 DP2_IN("iActiveState=%d iIgnoreAsyncOpComplete=%d",iDevAudio->iActiveState, iIgnoreAsyncOpComplete); |
|
613 |
|
614 if (iDevAudio->iActiveState != EDevSoundAdaptorRemovingProcessingUnits) |
|
615 { |
|
616 if (iIgnoreAsyncOpComplete) |
|
617 { |
|
618 iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); |
|
619 iIgnoreAsyncOpComplete = EFalse; |
|
620 } |
|
621 else |
|
622 { |
|
623 iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue); |
|
624 } |
|
625 DP_OUT(); |
|
626 return; |
|
627 } |
|
628 |
|
629 //If the Commit cycle when going into EDevSoundAdaptorRemovingProcessingUnits fails due to pre-emption |
|
630 //clash then we re-apply the client request again. |
|
631 if (iDevAudio->iActiveState == EDevSoundAdaptorRemovingProcessingUnits && iIgnoreAsyncOpComplete) |
|
632 { |
|
633 //Pop front of queue to re-apply the request again via CMMFDevSoundSession::DequeueRequest |
|
634 //from the callback into CMMFDevSoundSession below: |
|
635 iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); |
|
636 iIgnoreAsyncOpComplete = EFalse; |
|
637 DP_OUT(); |
|
638 return; |
|
639 } |
|
640 |
|
641 iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised; |
|
642 |
|
643 if (iDevAudio->iReinitializing) |
|
644 { |
|
645 ContextEventStopDevSoundNotifications(); |
|
646 |
|
647 TInt err = iDevAudio->Initialize(iDevAudio->iTargetFormat, iDevAudio->iTargetMode); |
|
648 if(err) |
|
649 { |
|
650 ContextEventAsynchronousInitializeComplete(err); |
|
651 } |
|
652 |
|
653 iDevAudio->iReinitializing = EFalse; |
|
654 DP_OUT(); |
|
655 return; |
|
656 } |
|
657 |
|
658 iDevAudio->iClosing = EFalse; |
|
659 iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue); |
|
660 |
|
661 DP_OUT(); |
|
662 } |
|
663 |
|
664 |
|
665 void CDevCommonControl::ContextEventUpdateWithoutStateEventButWithError(TInt aError) // from CDevCommonControl |
|
666 { |
|
667 DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithoutStateEventButWithError, CtxDevSound, DPLOCAL); |
|
668 DP_IN(); |
|
669 |
|
670 //If flag is true below then it must be due to a stateless normal pre-emption or |
|
671 //stateless pre-emption clash scenario. |
|
672 if(iIgnoreAsyncOpComplete) |
|
673 { |
|
674 //If we are in pre-emption clash then callback below will retry the client request again. |
|
675 iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); // notify client of end of cycle |
|
676 iIgnoreAsyncOpComplete = EFalse; |
|
677 } |
|
678 else |
|
679 { |
|
680 TDevSoundAdaptorState previousState = iDevAudio->iPreviousState; |
|
681 |
|
682 DP3(DLINFO,"Error with no state change, state %d, previous %d, error %d during Commit cycle", |
|
683 iDevAudio->iActiveState, previousState, aError); |
|
684 |
|
685 // We can end up here for a number of reasons. For non "mid states", this is |
|
686 // a standard error scenario. For some mid-states (e.g. Activating, Loading etc), |
|
687 // when we try and "promote" the state, this happens when the promotion is rejected |
|
688 // and we handle thus accordingly. For other mid-states the situation is less clear |
|
689 // and we call AsynchronousOperationComplete() with the error assuming the parent |
|
690 // session will deal with it. Whatever we don't want to stay in a mid-state, so |
|
691 // rewind to the previous ("normal") one if we are in one. |
|
692 |
|
693 // Longer term TODO. If the code were refactored so that the InitializeComplete(), |
|
694 // PlayError() etc callback came from AsynchronousOperationComplete() then the |
|
695 // following code might be simpler. Most of the time (at least) we get here because |
|
696 // we are doing a session function, and we can use the function to determine what |
|
697 // to do more easily than relying on the state. As it is, for some mid-states we |
|
698 // try and work out what error code to generate. Not clear this covers 100% cases, |
|
699 // although demotion transitions should not fail, so the problem cases might not occur. |
|
700 // |
|
701 |
|
702 //If we reach this condition then it is because of rejection/error during Commit cycle. |
|
703 switch (iDevAudio->iActiveState) |
|
704 { |
|
705 case EDevSoundAdaptorInitialising: |
|
706 { |
|
707 iDevAudio->iActiveState = previousState; |
|
708 ContextEventAsynchronousInitializeComplete(aError); |
|
709 break; |
|
710 } |
|
711 case EDevSoundAdaptorLoading: |
|
712 { |
|
713 iDevAudio->iActiveState = previousState; |
|
714 ContextEventAsynchronousPlayCompletion(aError); |
|
715 break; |
|
716 } |
|
717 case EDevSoundAdaptorActivating: |
|
718 { |
|
719 iDevAudio->iActiveState = previousState; |
|
720 ContextEventAsynchronousPlayCompletion(aError); |
|
721 break; |
|
722 } |
|
723 case EDevSoundAdaptorRemovingProcessingUnits: |
|
724 case EDevSoundAdaptorUninitialising: |
|
725 case EDevSoundAdaptorUnloading: |
|
726 case EDevSoundAdaptorStopping: |
|
727 case EDevSoundAdaptorPausing: |
|
728 { |
|
729 DP2(DLINFO,"Unexpected mid state [%d] when handling error [%d] during Commit cycle, workback", iDevAudio->iActiveState, aError); |
|
730 iDevAudio->iActiveState = previousState; |
|
731 iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue); |
|
732 break; |
|
733 } |
|
734 default: |
|
735 { |
|
736 DP2(DLINFO,"Unexpected state [%d] when handling error [%d] during Commit cycle", iDevAudio->iActiveState, aError); |
|
737 iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue); |
|
738 } |
|
739 } |
|
740 } |
|
741 |
|
742 DP_OUT(); |
|
743 } |
|
744 |
|
745 |
|
746 void CDevCommonControl::ContextEventUpdateWithStateEventNoError() // from CDevCommonControl |
|
747 { |
|
748 DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithStateEventNoError, CtxDevSound, DPLOCAL); |
|
749 DP_IN(); |
|
750 |
|
751 switch (iDevAudio->iActiveState) |
|
752 { |
|
753 case EDevSoundAdaptorUninitialising: |
|
754 iDevAudio->iActiveState = EDevSoundAdaptorUnitialised_Uninitialised; |
|
755 ContextEventStateDevSoundAdaptorUninitializing(); |
|
756 break; |
|
757 |
|
758 case EDevSoundAdaptorInitialising: |
|
759 iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised; |
|
760 ContextEventAsynchronousInitializeComplete(KErrNone); |
|
761 break; |
|
762 |
|
763 case EDevSoundAdaptorUnloading: |
|
764 iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised; |
|
765 ContextEventStateDevSoundAdaptorUnloading(); |
|
766 break; |
|
767 |
|
768 case EDevSoundAdaptorLoading: |
|
769 iDevAudio->iActiveState = EDevSoundAdaptorGoingActive; |
|
770 ContextEventStateDevSoundAdaptorLoading(); |
|
771 break; |
|
772 |
|
773 case EDevSoundAdaptorStopping: |
|
774 iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Idle; |
|
775 ContextEventStateDevSoundAdaptorStopping(); |
|
776 break; |
|
777 |
|
778 case EDevSoundAdaptorActivating: |
|
779 iDevAudio->iActiveState = EDevSoundAdaptorActive_Active; |
|
780 ContextEventPauseResumeSequenceDueToEmptyBuffers(EFalse); |
|
781 break; |
|
782 |
|
783 case EDevSoundAdaptorPausing: |
|
784 iDevAudio->iActiveState = EDevSoundAdaptorPaused_Primed; |
|
785 ContextEventPauseResumeSequenceDueToEmptyBuffers(ETrue); |
|
786 break; |
|
787 |
|
788 case EDevSoundAdaptorBeingPreempted: |
|
789 iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised; |
|
790 ContextEventStateDevSoundAdaptorBeingPreempted(); |
|
791 break; |
|
792 |
|
793 default: |
|
794 break; |
|
795 } |
|
796 |
|
797 DP_OUT(); |
|
798 } |
|
799 |
|
800 |
|
801 void CDevCommonControl::ContextEventUpdateWithStateEventAndError(TInt aError) // from CDevCommonControl |
|
802 { |
|
803 DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithStateEventAndError, CtxDevSound, DPLOCAL); |
|
804 DP_IN(); |
|
805 |
|
806 DP1(DLERR,"ContextEventUpdateWithStateEventAndError error=%d", aError); |
|
807 |
|
808 switch(iDevAudio->iActiveState) |
|
809 { |
|
810 case EDevSoundAdaptorInitialising: |
|
811 iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised; |
|
812 iAdaptationObserver->InitializeComplete(aError); |
|
813 break; |
|
814 |
|
815 case EDevSoundAdaptorLoading: |
|
816 iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised; |
|
817 FinishWithError(aError); |
|
818 break; |
|
819 |
|
820 case EDevSoundAdaptorActivating: |
|
821 iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Idle; |
|
822 ContextEventErrorStateDevSoundAdaptorActivating(aError); |
|
823 break; |
|
824 |
|
825 case EDevSoundAdaptorBeingPreempted: |
|
826 iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised; |
|
827 ContextEventErrorStateDevSoundAdaptorBeingPreempted(); |
|
828 break; |
|
829 |
|
830 default: |
|
831 break; |
|
832 } |
|
833 |
|
834 iCallbackFromAdaptor = KCallbackNone; |
|
835 |
|
836 if(!iIgnoreAsyncOpComplete) |
|
837 { |
|
838 iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue); |
|
839 } |
|
840 else |
|
841 { |
|
842 iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); |
|
843 iIgnoreAsyncOpComplete=EFalse; |
|
844 } |
|
845 |
|
846 DP_OUT(); |
|
847 } |
|
848 |
|
849 |
|
850 // end of file |