|
1 //audiostream.cpp |
|
2 |
|
3 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 // All rights reserved. |
|
5 // This component and the accompanying materials are made available |
|
6 // under the terms of "Eclipse Public License v1.0" |
|
7 // which accompanies this distribution, and is available |
|
8 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
9 // |
|
10 // Initial Contributors: |
|
11 // Nokia Corporation - initial contribution. |
|
12 // |
|
13 // Contributors: |
|
14 // |
|
15 // Description: |
|
16 // |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 #include <a3f/a3fbase.h> |
|
22 #include <a3f/audioprocessingunittypeuids.h> |
|
23 #include <a3f/a3ffourcclookup.h> |
|
24 |
|
25 #include "audiostream.h" |
|
26 |
|
27 // PHYSICAL COMPONENTS |
|
28 #include "audiocodec.h" |
|
29 #include "audiostream.h" |
|
30 #include "buffersource.h" |
|
31 #include "buffersink.h" |
|
32 #include "audiodevicesource.h" |
|
33 #include "audiodevicesink.h" |
|
34 #include "audiogaincontrol.h" |
|
35 #include "maudiostreamadaptationobserver.h" |
|
36 |
|
37 #include <a3f/maudiodatasupplier.h> |
|
38 #include <a3f/maudiodataconsumer.h> |
|
39 |
|
40 #include "minputport.h" |
|
41 #include "moutputport.h" |
|
42 #include "audiocontext.h" |
|
43 |
|
44 #include <ecom/implementationproxy.h> |
|
45 |
|
46 |
|
47 |
|
48 const TInt KSampleRate8000Hz = 8000; |
|
49 |
|
50 // Map the interface implementation UIDs to implementation factory functions |
|
51 const TImplementationProxy ImplementationTable[] = |
|
52 { |
|
53 IMPLEMENTATION_PROXY_ENTRY(0x10283461, CAudioStream::NewL), |
|
54 }; |
|
55 |
|
56 |
|
57 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) |
|
58 { |
|
59 aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); |
|
60 return ImplementationTable; |
|
61 } |
|
62 |
|
63 // --------------------------------------------------------------------------- |
|
64 // Constructor |
|
65 // --------------------------------------------------------------------------- |
|
66 // |
|
67 CAudioStream::CAudioStream() |
|
68 : iCurrentStreamState(EUninitialized), |
|
69 iDesiredStreamState(EUninitialized) |
|
70 { |
|
71 TRACE_CREATE(); |
|
72 DP_CONTEXT(CAudioStream::CAudioStream *CD1*, CtxDevSound, DPLOCAL); |
|
73 DP_IN(); |
|
74 // Some init config values |
|
75 iSampleRateConfig = KSampleRate8000Hz; |
|
76 iModeConfig = KA3FModeMono; |
|
77 |
|
78 DP_OUT(); |
|
79 } |
|
80 |
|
81 // --------------------------------------------------------------------------- |
|
82 // Factory method |
|
83 // --------------------------------------------------------------------------- |
|
84 // |
|
85 CAudioStream* CAudioStream::NewL() |
|
86 { |
|
87 DP_STATIC_CONTEXT(CAudioStream::NewL *CD0*, CtxDevSound, DPLOCAL); |
|
88 DP_IN(); |
|
89 CAudioStream* self = new(ELeave)CAudioStream(); |
|
90 CleanupStack::PushL(self); |
|
91 self->ConstructL(); |
|
92 CleanupStack::Pop(self); |
|
93 DP0_RET(self, "0x%x"); |
|
94 } |
|
95 |
|
96 // --------------------------------------------------------------------------- |
|
97 // Second phase constructor |
|
98 // --------------------------------------------------------------------------- |
|
99 // |
|
100 void CAudioStream::ConstructL() |
|
101 { |
|
102 DP_CONTEXT(CAudioStream::ConstructL *CD1*, CtxDevSound, DPLOCAL); |
|
103 DP_IN(); |
|
104 DP_OUT(); |
|
105 } |
|
106 |
|
107 // --------------------------------------------------------------------------- |
|
108 // Destructor |
|
109 // --------------------------------------------------------------------------- |
|
110 // |
|
111 CAudioStream::~CAudioStream() |
|
112 { |
|
113 DP_CONTEXT(CAudioStream::~CAudioStream *CD1*, CtxDevSound, DPLOCAL); |
|
114 DP_IN(); |
|
115 |
|
116 iAudioStreamObservers.Close(); |
|
117 iAudioCodecObservers.Close(); |
|
118 // Just for now |
|
119 DeletePhysicalComponents(); |
|
120 REComSession::FinalClose(); |
|
121 DP_OUT(); |
|
122 } |
|
123 |
|
124 // --------------------------------------------------------------------------- |
|
125 // CAudioStream::RegisterAudioStreamObserver |
|
126 // --------------------------------------------------------------------------- |
|
127 // |
|
128 TInt CAudioStream::RegisterAudioStreamObserver(MAudioStreamAdaptationObserver& aObserver) |
|
129 { |
|
130 DP_CONTEXT(CAudioStream::RegisterAudioStreamObserver *CD1*, CtxDevSound, DPLOCAL); |
|
131 DP_IN(); |
|
132 TInt err = iAudioStreamObservers.Find(&aObserver); |
|
133 if(err == KErrNotFound) |
|
134 { |
|
135 err = iAudioStreamObservers.Append(&aObserver); |
|
136 } |
|
137 else |
|
138 { |
|
139 err = KErrAlreadyExists; |
|
140 } |
|
141 DP0_RET(err, "%d"); |
|
142 } |
|
143 |
|
144 // --------------------------------------------------------------------------- |
|
145 // CAudioStream::UnregisterAudioStreamObserver |
|
146 // --------------------------------------------------------------------------- |
|
147 // |
|
148 void CAudioStream::UnregisterAudioStreamObserver(MAudioStreamAdaptationObserver& aObserver) |
|
149 { |
|
150 DP_CONTEXT(CAudioStream::UnregisterAudioStreamObserver *CD1*, CtxDevSound, DPLOCAL); |
|
151 DP_IN(); |
|
152 TInt idxOrErr = iAudioStreamObservers.Find(&aObserver); |
|
153 if( idxOrErr != KErrNotFound ) |
|
154 { |
|
155 iAudioStreamObservers.Remove(idxOrErr); |
|
156 } |
|
157 DP_OUT(); |
|
158 } |
|
159 |
|
160 |
|
161 // --------------------------------------------------------------------------- |
|
162 // CAudioStream::SetFourCC |
|
163 // --------------------------------------------------------------------------- |
|
164 // |
|
165 void CAudioStream::SetFourCC(const CFourCCConvertor& aFourCCConvertor) |
|
166 { |
|
167 DP_CONTEXT(CAudioStream::SetFourCC *CD1*, CtxDevSound, DPLOCAL); |
|
168 DP_IN(); |
|
169 CFourCCConvertor& ref = const_cast<CFourCCConvertor&>(aFourCCConvertor); |
|
170 iFourCCConvertor = static_cast<CFourCCConvertor*>(static_cast<TAny*>(&ref)); |
|
171 DP_OUT(); |
|
172 } |
|
173 |
|
174 |
|
175 // --------------------------------------------------------------------------- |
|
176 // CAudioStream::UnregisterAudioStreamObserver |
|
177 // --------------------------------------------------------------------------- |
|
178 // |
|
179 void CAudioStream::UnregisterAllAudioStreamObserver() |
|
180 { |
|
181 DP_CONTEXT(CAudioStream::UnregisterAudioStreamObserver *CD1*, CtxDevSound, DPLOCAL); |
|
182 DP_IN(); |
|
183 |
|
184 iAudioStreamObservers.Reset(); |
|
185 |
|
186 DP_OUT(); |
|
187 } |
|
188 |
|
189 |
|
190 // --------------------------------------------------------------------------- |
|
191 // MMRC extension mechanism |
|
192 // --------------------------------------------------------------------------- |
|
193 TAny* CAudioStream::GetComponent(TUid aType) |
|
194 { |
|
195 TAny* ptr = NULL; |
|
196 MLogicalChain* clientDesiredChain = NULL; |
|
197 CAudioContext* context = static_cast<CAudioContext*>(iAudioContext); |
|
198 if(context) |
|
199 { |
|
200 clientDesiredChain = context->GetLogicalChain(0); |
|
201 } |
|
202 if (clientDesiredChain) |
|
203 { |
|
204 ptr = clientDesiredChain->GetComponent(aType); |
|
205 } |
|
206 return ptr; |
|
207 } |
|
208 |
|
209 // --------------------------------------------------------------------------- |
|
210 // CAudioStream::Message |
|
211 // --------------------------------------------------------------------------- |
|
212 TInt CAudioStream::Message(MLogicalChain& aCurrentChain, MLogicalChain& aDesiredChain, MAudioContext& aContext, TInt aFlags) |
|
213 { |
|
214 DP_CONTEXT(CAudioStream::Message *CD0*, CtxDevSound, DPLOCAL); |
|
215 DP_IN(); |
|
216 TInt err = KErrNone; |
|
217 |
|
218 iCurrentChain = &aCurrentChain; |
|
219 iDesiredChain = &aDesiredChain; |
|
220 |
|
221 TUint messageType = aDesiredChain.MessageType(); |
|
222 |
|
223 iAudioContext = &aContext; |
|
224 |
|
225 CAudioContext* audioContext = static_cast<CAudioContext*> (iAudioContext); |
|
226 // TO NOTIFY DIRECTLY CONTEXT |
|
227 MMultimediaResourceControlObserver* mmrcObserver = static_cast<MMultimediaResourceControlObserver*>(audioContext); |
|
228 |
|
229 // Register stream observer |
|
230 if (messageType & ERegisterStreamObserver != 0) |
|
231 { |
|
232 // Use MMRC extension mechanism |
|
233 TAny* ptr = GetComponent(KUidAudioStreamAdaptationObserver); |
|
234 MAudioStreamAdaptationObserver* observer = static_cast<MAudioStreamAdaptationObserver*>(ptr); |
|
235 if(observer) |
|
236 { |
|
237 err = RegisterAudioStreamObserver(*observer); |
|
238 } |
|
239 } |
|
240 |
|
241 // Register codec observer |
|
242 if (messageType & ERegisterCodecObserver != 0) |
|
243 { |
|
244 // Use MMRC extension mechanism |
|
245 TAny* ptr = GetComponent(KUidAudioCodecObserver); |
|
246 MAudioCodecObserver* observer = static_cast<MAudioCodecObserver*>(ptr); |
|
247 if (observer) |
|
248 { |
|
249 err = RegisterAudioCodecObserver(*observer); |
|
250 } |
|
251 } |
|
252 |
|
253 // Component creation |
|
254 TUint bit = messageType & EComponentCreation; |
|
255 if( (err == KErrNone) && (bit != 0) ) |
|
256 { |
|
257 CAudioContext* context = static_cast<CAudioContext*>(iAudioContext); |
|
258 MLogicalChain* clientDesiredChain = context->GetLogicalChain(0); |
|
259 err = CreatePhysicalComponents(*clientDesiredChain); |
|
260 |
|
261 // For Configuration |
|
262 if (err==KErrNone) |
|
263 { |
|
264 clientDesiredChain->SetAdaptationStream(*this); |
|
265 clientDesiredChain->SetStreamBufferControl(*this); |
|
266 } |
|
267 } |
|
268 |
|
269 // Component alteration |
|
270 // Changes that must be applied before stream state transition |
|
271 TBool configCodec = EFalse; |
|
272 bit = messageType & EComponentAlterationCodec; |
|
273 if( (err == KErrNone) && (bit != 0) ) |
|
274 { |
|
275 // Set Format |
|
276 if(iCodec) |
|
277 { |
|
278 TUid desiredCodecFormat = iDesiredChain->CodecFormat(); |
|
279 err = iCodec->SetFormat( desiredCodecFormat ); |
|
280 } |
|
281 |
|
282 if(err == KErrNone) |
|
283 { |
|
284 //if samplerate or mode has changed, update value and trigger callbacks at appropriate point |
|
285 if ((iDesiredChain->GetSampleRate() > 0) && (iDesiredChain->GetSampleRate() != iSampleRateConfig)) |
|
286 { |
|
287 iSampleRateConfig = iDesiredChain->GetSampleRate(); |
|
288 configCodec = ETrue; |
|
289 } |
|
290 if ((iDesiredChain->GetMode() != KNullUid) && (iDesiredChain->GetMode() != iModeConfig)) |
|
291 { |
|
292 iModeConfig = iDesiredChain->GetMode(); |
|
293 configCodec = ETrue; |
|
294 } |
|
295 } |
|
296 } |
|
297 |
|
298 |
|
299 bit = messageType & EComponentAlterationGain; |
|
300 if( (err == KErrNone) && (bit != 0) ) |
|
301 { |
|
302 // Apply volume ramp |
|
303 // Note that ramp operation and gain now are applied separately because current tone arquitecture |
|
304 // need the volume ramp to be set before start the tonehwdevice |
|
305 TTimeIntervalMicroSeconds currentRampTimeValue = 0; |
|
306 TUid currentRampTimeOperation(KNullUid); |
|
307 TTimeIntervalMicroSeconds desiredRampTimeValue = 0; |
|
308 TUid desiredRampTimeOperation(KNullUid); |
|
309 iCurrentChain->GetVolumeRampParameters(currentRampTimeOperation, currentRampTimeValue); |
|
310 iDesiredChain->GetVolumeRampParameters(desiredRampTimeOperation, desiredRampTimeValue); |
|
311 |
|
312 if(currentRampTimeOperation != desiredRampTimeOperation || |
|
313 currentRampTimeValue.Int64() != desiredRampTimeValue.Int64() ) |
|
314 { |
|
315 if (iGainControl) |
|
316 { |
|
317 err = iGainControl->ConfigureRamp(desiredRampTimeOperation, desiredRampTimeValue); |
|
318 } |
|
319 } |
|
320 } |
|
321 |
|
322 //Configuration request |
|
323 // Stream state |
|
324 TBool invokeStateEventCallback = EFalse; |
|
325 iDesiredStreamState = iDesiredChain->StreamState(); |
|
326 if( (err == KErrNone) && (iCurrentStreamState != iDesiredStreamState) ) |
|
327 { |
|
328 err = ChangeState(iCurrentStreamState, iDesiredStreamState); |
|
329 if (err == KErrNone) |
|
330 { |
|
331 iCurrentStreamState = iDesiredStreamState; |
|
332 } |
|
333 invokeStateEventCallback = ETrue; |
|
334 } |
|
335 |
|
336 // Component alteration |
|
337 // Changes that must be applied after stream state transition |
|
338 TBool gainUpdated = EFalse; |
|
339 bit = messageType & EComponentAlterationGain; |
|
340 if( (err == KErrNone) && (bit != 0) ) |
|
341 { |
|
342 TAny* ptr = GetComponent(KUidAudioGainControl); |
|
343 MAudioGainControl* gaincontrol = static_cast<MAudioGainControl*>(ptr); |
|
344 if (iGainControl && gaincontrol) |
|
345 { |
|
346 RArray<TAudioChannelGain> channels; |
|
347 TInt err = gaincontrol->GetGain(channels); |
|
348 if (channels.Count() != 0 ) |
|
349 { |
|
350 err = iGainControl->SetGain(channels); |
|
351 gainUpdated = ETrue; |
|
352 } |
|
353 channels.Close(); |
|
354 } |
|
355 } |
|
356 |
|
357 TBool invokeCodecCallbacks = EFalse; |
|
358 bit = messageType & EComponentAlterationCodec; |
|
359 if ( (err == KErrNone) && (bit != 0) && configCodec && (iCurrentStreamState == EInitialized) ) |
|
360 { |
|
361 //codec loading actually configures sample rate and mode |
|
362 ASSERT(iCodec); |
|
363 err = iCodec->Load(iSampleRateConfig, iModeConfig); |
|
364 iIsCodecConfig = (err == KErrNone); |
|
365 invokeCodecCallbacks = ETrue; |
|
366 if ( err != KErrNone ) |
|
367 { |
|
368 //get back to previous values in case of error |
|
369 iSampleRateConfig = iCurrentChain->GetSampleRate(); |
|
370 iModeConfig = iCurrentChain->GetMode(); |
|
371 } |
|
372 } |
|
373 |
|
374 // Component destruction |
|
375 bit = messageType & EComponentDestruction; |
|
376 if( (err == KErrNone) && (bit != 0) ) |
|
377 { |
|
378 DeletePhysicalComponents(); |
|
379 } |
|
380 |
|
381 TUint isStopping = aFlags & KServerStopping; |
|
382 TUint preemptionRequest = aFlags & KPreemptionRequest; |
|
383 |
|
384 // HERE WE CAN GUARANTEE THAT THE REQUEST IS SUCCESFUL |
|
385 // Notify context |
|
386 // 1ST CALLBACK |
|
387 if(!preemptionRequest) |
|
388 { |
|
389 mmrcObserver->ReceiveResourceUpdate(&aDesiredChain, KErrNone); |
|
390 } |
|
391 else |
|
392 { |
|
393 mmrcObserver->ReceivePreemptionUpdate(&aDesiredChain, err); |
|
394 } |
|
395 |
|
396 // Processing unit callbacks |
|
397 // Gain control |
|
398 // Note that due to error checking before applying any change |
|
399 // this callback always returned the error obtained by calling SetGain |
|
400 // or KErrNone |
|
401 if(gainUpdated) |
|
402 { |
|
403 if (iGainControl) |
|
404 { |
|
405 iGainControl->IssueGainChangedCallBack(err); |
|
406 } |
|
407 } |
|
408 |
|
409 // Stream |
|
410 if(invokeStateEventCallback) |
|
411 { |
|
412 invokeStateEventCallback = EFalse; |
|
413 for ( TUint idx(0); idx < iAudioStreamObservers.Count(); idx++ ) |
|
414 { |
|
415 if ( !isStopping ) |
|
416 { |
|
417 iAudioStreamObservers[idx]->StateEvent(err, iCurrentStreamState); |
|
418 } |
|
419 } |
|
420 } |
|
421 if( invokeCodecCallbacks && (iCurrentStreamState == EInitialized) ) |
|
422 { |
|
423 TInt count = iAudioCodecObservers.Count(); |
|
424 for ( TInt idx = 0; idx < count; idx++ ) |
|
425 { |
|
426 //TODO replace this functionality with the new mmrc |
|
427 iAudioCodecObservers[idx]->SampleRateSet(err); |
|
428 iAudioCodecObservers[idx]->ModeSet(err); |
|
429 } |
|
430 } |
|
431 |
|
432 // Now has no effect on context |
|
433 // But it's needed to let the MMRC know about the operation being completed |
|
434 // and in such way let it to know that |
|
435 for ( TUint idx(0); idx < iAudioStreamObservers.Count(); idx++ ) |
|
436 { |
|
437 if ( !isStopping ) |
|
438 { |
|
439 iAudioStreamObservers[idx]->PhysicalAdaptationEvent(EOperationComplete, err); |
|
440 } |
|
441 } |
|
442 |
|
443 // Don't need to send last callback sync |
|
444 // Let MMRC do it |
|
445 |
|
446 DP0_RET(err, "%d"); |
|
447 } |
|
448 |
|
449 // --------------------------------------------------------------------------- |
|
450 // CAudioStream::DeletePhysicalComponents |
|
451 // --------------------------------------------------------------------------- |
|
452 void CAudioStream::DeletePhysicalComponents() |
|
453 { |
|
454 DP_CONTEXT(CAudioStream::DeletePhysicalComponents *CD0*, CtxDevSound, DPLOCAL); |
|
455 DP_IN(); |
|
456 if(iBufferSource) |
|
457 { |
|
458 delete iBufferSource; |
|
459 iBufferSource = NULL; |
|
460 } |
|
461 if(iBufferSink) |
|
462 { |
|
463 delete iBufferSink; |
|
464 iBufferSink = NULL; |
|
465 } |
|
466 if(iCodec) |
|
467 { |
|
468 delete iCodec; |
|
469 iCodec = NULL; |
|
470 iIsCodecConfig = EFalse; |
|
471 } |
|
472 if(iGainControl) |
|
473 { |
|
474 delete iGainControl; |
|
475 iGainControl = NULL; |
|
476 } |
|
477 if(iDeviceSource) |
|
478 { |
|
479 delete iDeviceSource; |
|
480 iDeviceSource = NULL; |
|
481 } |
|
482 if(iDeviceSink) |
|
483 { |
|
484 delete iDeviceSink; |
|
485 iDeviceSink= NULL; |
|
486 } |
|
487 DP_OUT(); |
|
488 } |
|
489 |
|
490 |
|
491 // --------------------------------------------------------------------------- |
|
492 // CAudioStream::CreatePhysicalComponents |
|
493 // --------------------------------------------------------------------------- |
|
494 TInt CAudioStream::CreatePhysicalComponents(MLogicalChain& aDesiredChain) |
|
495 { |
|
496 DP_CONTEXT(CAudioStream::CreatePhysicalComponents *CD0*, CtxDevSound, DPLOCAL); |
|
497 DP_IN(); |
|
498 |
|
499 TInt err = KErrNone; |
|
500 TInt units = aDesiredChain.AudioProcessingUnitsCount(); |
|
501 TInt index=0; |
|
502 TUid typeId; |
|
503 |
|
504 for (index=0; index < units ; index++) |
|
505 { |
|
506 typeId = aDesiredChain.AudioProcessingUnitUid(index); |
|
507 |
|
508 // By the moment all components |
|
509 if (err == KErrNone) |
|
510 { |
|
511 if (typeId == KUidAudioDecoder || typeId == KUidAudioEncoder ) |
|
512 { |
|
513 if(!iCodec) |
|
514 { |
|
515 TRAP(err, iCodec = CAudioCodec::NewL(typeId, *iFourCCConvertor )); |
|
516 iIsCodecConfig = EFalse; |
|
517 iCodec->RegisterAudioCodecObserver(*this); |
|
518 TAny* ptr = GetComponent(KUidAudioCodecAdaptationObserver); |
|
519 MAudioCodecAdaptationObserver* observer = static_cast<MAudioCodecAdaptationObserver*>(ptr); |
|
520 if(observer) |
|
521 { |
|
522 iCodec->RegisterAudioCodecObserver(*observer); |
|
523 } |
|
524 // For HW custom interface |
|
525 aDesiredChain.SetCustomInterfaceProvider(*iCodec); |
|
526 } |
|
527 if(iGainControl) |
|
528 { |
|
529 iGainControl->SetHelper(*iCodec); |
|
530 } |
|
531 // This mechanism is temporary and must be replaced |
|
532 // with the Extension mechanism when the MMRC server |
|
533 aDesiredChain.SetStreamPositionControl(*iCodec); |
|
534 } |
|
535 else if (typeId == KUidMmfBufferSource) |
|
536 { |
|
537 if(!iBufferSource) |
|
538 { |
|
539 TRAP(err,iBufferSource = CBufferSource::NewL()); |
|
540 // This mechanism is temporary and must be replaced |
|
541 // with the Extension mechanism when the MMRC server |
|
542 aDesiredChain.SetAdaptationSource(*iBufferSource); |
|
543 /* |
|
544 TAny* ptr = aDesiredChain.GetComponent(KUidMmfBufferSource); |
|
545 MMMFAudioDataSupplier* supplier = static_cast<MMMFAudioDataSupplier*>(ptr); |
|
546 if(supplier) |
|
547 { |
|
548 iBufferSource->SetDataSupplier(*supplier); |
|
549 } |
|
550 */ |
|
551 } |
|
552 } |
|
553 else if (typeId == KUidMmfBufferSink) |
|
554 { |
|
555 if(!iBufferSink) |
|
556 { |
|
557 TRAP(err, iBufferSink = CBufferSink::NewL()); |
|
558 // This mechanism is temporary and must be replaced |
|
559 // with the Extension mechanism when the MMRC server |
|
560 aDesiredChain.SetAdaptationSink(*iBufferSink); |
|
561 } |
|
562 } |
|
563 else if (typeId == KUidAudioGainControl) |
|
564 { |
|
565 if(!iGainControl) |
|
566 { |
|
567 // This mechanism is temporary and must be replaced |
|
568 // with the Extension mechanism when the MMRC server |
|
569 TRAP(err, iGainControl = CAudioGainControl::NewL()); |
|
570 aDesiredChain.SetAdaptationGainControl(*iGainControl); |
|
571 } |
|
572 } |
|
573 else if (typeId == KUidAudioDeviceSink) |
|
574 { |
|
575 if(!iDeviceSink) |
|
576 { |
|
577 TRAP(err, iDeviceSink = CAudioDeviceSink::NewL()); |
|
578 } |
|
579 } |
|
580 else if (typeId == KUidAudioDeviceSource) |
|
581 { |
|
582 if(!iDeviceSource) |
|
583 { |
|
584 TRAP(err, iDeviceSource = CAudioDeviceSource::NewL()); |
|
585 } |
|
586 } |
|
587 else |
|
588 { |
|
589 err = KErrNotSupported; |
|
590 } |
|
591 } |
|
592 |
|
593 // Notify the observers |
|
594 for ( TUint idx(0); idx < iAudioStreamObservers.Count(); idx++ ) |
|
595 { |
|
596 iAudioStreamObservers[idx]->AddProcessingUnitComplete(typeId, err); |
|
597 } |
|
598 } |
|
599 DP0_RET(err, "%d"); |
|
600 } |
|
601 |
|
602 // --------------------------------------------------------------------------- |
|
603 // CAudioStream::CreateDataPath |
|
604 // --------------------------------------------------------------------------- |
|
605 TInt CAudioStream::CreateDataPath() |
|
606 { |
|
607 DP_CONTEXT(CAudioStream::CreateDataPath *CD1*, CtxDevSound, DPLOCAL); |
|
608 DP_IN(); |
|
609 TInt err(KErrNotReady); |
|
610 |
|
611 if(iBufferSource && iCodec) // && iSink && iGain) |
|
612 { |
|
613 // TMode == Decode |
|
614 if(KErrNone == iBufferSource->GetOutputPort(iOutputport) && KErrNone == iCodec->GetInputPort(iInputport)) |
|
615 { |
|
616 iOutputport->SetInput(iInputport); |
|
617 iInputport->SetOutput(iOutputport); |
|
618 err = KErrNone; |
|
619 } |
|
620 } |
|
621 else if(iBufferSink && iCodec) // && iSink && iGain) |
|
622 { |
|
623 //TMode == Encode |
|
624 if(KErrNone == iCodec->GetOutputPort(iOutputport) && KErrNone == iBufferSink->GetInputPort(iInputport)) |
|
625 { |
|
626 iOutputport->SetInput(iInputport); |
|
627 iInputport->SetOutput(iOutputport); |
|
628 err = KErrNone; |
|
629 } |
|
630 } |
|
631 DP0_RET(err, "%d"); |
|
632 } |
|
633 |
|
634 // --------------------------------------------------------------------------- |
|
635 // CAudioStream::DemolishDataPath |
|
636 // --------------------------------------------------------------------------- |
|
637 // |
|
638 TInt CAudioStream::DemolishDataPath() |
|
639 { |
|
640 DP_CONTEXT(CAudioStream::DemolishDataPath *CD1*, CtxDevSound, DPLOCAL); |
|
641 DP_IN(); |
|
642 iOutputport->RemoveInput(iInputport); |
|
643 iInputport->RemoveOutput(iOutputport); |
|
644 DP0_RET(KErrNone, "%d"); |
|
645 } |
|
646 |
|
647 // --------------------------------------------------------------------------- |
|
648 // CAudioStream::ChangeState |
|
649 // --------------------------------------------------------------------------- |
|
650 TInt CAudioStream::ChangeState(TAudioState aPreviousState, TAudioState aDesiredState) |
|
651 { |
|
652 DP_CONTEXT(CAudioStream::ChangeState *CD1*, CtxDevSound, DPLOCAL); |
|
653 DP_IN(); |
|
654 TInt err(KErrNone); |
|
655 iCurrentStreamState = aPreviousState; |
|
656 iDesiredStreamState = aDesiredState; |
|
657 |
|
658 switch (iDesiredStreamState) |
|
659 { |
|
660 case EInitialized: |
|
661 { |
|
662 if (iCurrentStreamState == EUninitialized) //Initialize |
|
663 { |
|
664 err = CreateDataPath(); |
|
665 if(err == KErrNone) |
|
666 { |
|
667 err = iCodec->Initialize(); |
|
668 } |
|
669 } |
|
670 else if( iCurrentStreamState == EIdle ) //codec unload (actually, unconfig) |
|
671 { |
|
672 iIsCodecConfig = EFalse; |
|
673 err = KErrNone; |
|
674 } |
|
675 // Preemption |
|
676 // This A3F adaptation allows going from Active/Primed directly to initialised |
|
677 // otherwise reference MMRC would need to handle those transitions separately |
|
678 else if(iCurrentStreamState == EActive || iCurrentStreamState == EPrimed) |
|
679 { |
|
680 // To Idle |
|
681 err = iCodec->Stop(); |
|
682 // To Initilised |
|
683 iIsCodecConfig = EFalse; |
|
684 } |
|
685 |
|
686 if(err == KErrNone) |
|
687 { |
|
688 iCurrentStreamState = EInitialized; |
|
689 } |
|
690 break; |
|
691 } |
|
692 case EIdle: |
|
693 { |
|
694 if ( (iCurrentStreamState == EInitialized) && !iIsCodecConfig ) |
|
695 { |
|
696 //codec loading actually configures sample rate and mode |
|
697 err = iCodec->Load(iSampleRateConfig, iModeConfig); |
|
698 iIsCodecConfig = (err == KErrNone); |
|
699 } |
|
700 else if (iCurrentStreamState == EActive) |
|
701 { |
|
702 err = iCodec->Stop(); |
|
703 } |
|
704 else if (iCurrentStreamState == EPrimed) |
|
705 { |
|
706 err = iCodec->Stop(); |
|
707 } |
|
708 |
|
709 if(err == KErrNone) |
|
710 { |
|
711 iTimeProcessed = 0; |
|
712 iCurrentStreamState = EIdle; |
|
713 } |
|
714 break; |
|
715 } |
|
716 case EPrimed: |
|
717 { |
|
718 if (iCurrentStreamState == EIdle) |
|
719 { |
|
720 DP0(DLINFO,"============== Stream is going from EIdle -> PRIMED"); |
|
721 DP0(DLINFO,"Nothing to be done"); |
|
722 } |
|
723 else if (iCurrentStreamState == EActive) |
|
724 { |
|
725 DP0(DLINFO,"============== Stream is going from EActive -> PRIMED"); |
|
726 err = iCodec->Pause(); |
|
727 } |
|
728 if(err == KErrNone) |
|
729 { |
|
730 iCurrentStreamState = EPrimed; |
|
731 } |
|
732 break; |
|
733 } |
|
734 case EActive: |
|
735 { |
|
736 if (iCurrentStreamState == EPrimed) //Activate from Primed |
|
737 { |
|
738 // Reusing AudioCodec::Start for resuming |
|
739 DP0(DLINFO,"============== Stream is going from EPrimed -> ACTIVE"); |
|
740 err = iCodec->Start(); |
|
741 } |
|
742 else if(iCurrentStreamState == EIdle) //Activate from Idle |
|
743 { |
|
744 DP0(DLINFO,"============== Stream is going from EIdle -> ACTIVATE"); |
|
745 err = iCodec->Start(); |
|
746 } |
|
747 |
|
748 if(err == KErrNone) |
|
749 { |
|
750 iCurrentStreamState = EActive; |
|
751 } |
|
752 break; |
|
753 } |
|
754 case EUninitialized: |
|
755 { |
|
756 err = DemolishDataPath(); |
|
757 if(err == KErrNone) |
|
758 { |
|
759 iCurrentStreamState = EUninitialized; |
|
760 } |
|
761 break; |
|
762 } |
|
763 case EDead: |
|
764 { |
|
765 err = DemolishDataPath(); |
|
766 if(err == KErrNone) |
|
767 { |
|
768 iCurrentStreamState = EDead; |
|
769 } |
|
770 break; |
|
771 } |
|
772 default: |
|
773 err = KErrNotSupported; |
|
774 DP1(DLINFO,"CAudioStream::ChangeState Unknown state! %d", iDesiredStreamState); |
|
775 break; |
|
776 } |
|
777 DP0_RET(err, "%d"); |
|
778 } |
|
779 |
|
780 TInt CAudioStream::FlushBuffers() |
|
781 { |
|
782 DP_CONTEXT(CAudioStream::FlushBuffers *CD1*, CtxDevSound, DPLOCAL); |
|
783 DP_IN(); |
|
784 |
|
785 TInt err = KErrNone; |
|
786 |
|
787 MOutputPort* outPort= static_cast<MOutputPort*>(iCodec); |
|
788 if(outPort) |
|
789 { |
|
790 outPort->FlushBuffer(this); |
|
791 } |
|
792 else |
|
793 { |
|
794 err = KErrNotReady; |
|
795 } |
|
796 err = KErrNone; |
|
797 DP0_RET(err, "%d"); |
|
798 } |
|
799 |
|
800 |
|
801 void CAudioStream::FlushComplete(TInt aError) |
|
802 { |
|
803 DP_CONTEXT(CAudioStream::FlushComplete *CD1*, CtxDevSound, DPLOCAL); |
|
804 DP_IN(); |
|
805 TUint count = iAudioStreamObservers.Count(); |
|
806 for ( TUint i(0); i < count; i++ ) |
|
807 { |
|
808 iAudioStreamObservers[i]->FlushComplete(aError); |
|
809 } |
|
810 DP_OUT(); |
|
811 } |
|
812 |
|
813 void CAudioStream::AllBuffersProcessed() |
|
814 { |
|
815 DP_CONTEXT(CAudioStream::AllBuffersProcessed *CD1*, CtxDevSound, DPLOCAL); |
|
816 DP_IN(); |
|
817 TUint count = iAudioStreamObservers.Count(); |
|
818 for ( TUint i(0); i < count; i++ ) |
|
819 { |
|
820 iAudioStreamObservers[i]->ProcessingFinished(); |
|
821 } |
|
822 DP_OUT(); |
|
823 } |
|
824 |
|
825 void CAudioStream::ProcessingUnitError(TInt /*aError*/) |
|
826 { |
|
827 DP_CONTEXT(CAudioStream::ProcessingUnitError *CD1*, CtxDevSound, DPLOCAL); |
|
828 DP_IN(); |
|
829 DP_OUT(); |
|
830 } |
|
831 |
|
832 // --------------------------------------------------------------------------- |
|
833 // CAudioStream::RegisterAudioCodecObserver |
|
834 // --------------------------------------------------------------------------- |
|
835 TInt CAudioStream::RegisterAudioCodecObserver(MAudioCodecObserver& aObserver) |
|
836 { |
|
837 DP_CONTEXT(CAudioStream::RegisterAudioCodecObserver *CD1*, CtxDevSound, DPLOCAL); |
|
838 DP_IN(); |
|
839 TInt err = iAudioCodecObservers.Find(&aObserver); |
|
840 if(err == KErrNotFound) |
|
841 { |
|
842 err = iAudioCodecObservers.Append(&aObserver); |
|
843 } |
|
844 else |
|
845 { |
|
846 err = KErrAlreadyExists; |
|
847 } |
|
848 DP0_RET(err, "%d"); |
|
849 } |
|
850 |
|
851 // --------------------------------------------------------------------------- |
|
852 // CAudioStream::UnregisterAudioCodecObserver |
|
853 // --------------------------------------------------------------------------- |
|
854 void CAudioStream::UnregisterAudioCodecObserver(MAudioCodecObserver& aObserver) |
|
855 { |
|
856 DP_CONTEXT(CAudioStream::UnregisterAudioCodecObserver *CD1*, CtxDevSound, DPLOCAL); |
|
857 DP_IN(); |
|
858 TInt idxOrErr = iAudioCodecObservers.Find(&aObserver); |
|
859 if( idxOrErr != KErrNotFound ) |
|
860 { |
|
861 iAudioCodecObservers.Remove(idxOrErr); |
|
862 } |
|
863 DP_OUT(); |
|
864 } |
|
865 |
|
866 void CAudioStream::GetSupportedAModesComplete(TInt /*aError*/) |
|
867 { |
|
868 DP_CONTEXT(CAudioStream::GetSupportedAModesComplete *CD1*, CtxDevSound, DPLOCAL); |
|
869 DP_IN(); |
|
870 DP_OUT(); |
|
871 } |
|
872 |
|
873 void CAudioStream::GetSupportedARatesComplete(TInt /*aError*/) |
|
874 { |
|
875 DP_CONTEXT(CAudioStream::GetSupportedARatesComplete *CD1*, CtxDevSound, DPLOCAL); |
|
876 DP_IN(); |
|
877 DP_OUT(); |
|
878 } |
|
879 |
|
880 // --------------------------------------------------------------------------- |
|
881 // CAudioStream::GetSupportedSampleRates |
|
882 // --------------------------------------------------------------------------- |
|
883 TInt CAudioStream::GetSupportedSampleRates(RArray<TInt>& aSupportedRates) |
|
884 { |
|
885 TInt err = (KErrNotReady); |
|
886 err = iCodec->SupportedRates(aSupportedRates); |
|
887 return err; |
|
888 } |
|
889 |
|
890 // --------------------------------------------------------------------------- |
|
891 // CAudioStream::GetSupportedModes |
|
892 // --------------------------------------------------------------------------- |
|
893 TInt CAudioStream::GetSupportedModes(RArray<TUid>& aSupportedModes) |
|
894 { |
|
895 TInt err = (KErrNotReady); |
|
896 err = iCodec->SupportedModes(aSupportedModes); |
|
897 return err; |
|
898 } |
|
899 |
|
900 // end of file |