Update contrib.
1 // Copyright (c) 2002-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <mmf/server/mmfformat.h>
18 #include <mmf/server/mmfclip.h>
19 #include <mdaaudiosampleeditor.h>
20 #include <mmfcontrollerimplementationuids.hrh>
21 #include <mmf/common/mmffourcc.h>
22 #include <mmf/common/mmfpaniccodes.h>
23 #include "MmfAudioController.h"
24 #include <mmf/server/mmffile.h>
25 #include <mmf/server/mmfformatstandardcustominterfaces.h>
26 #include <mmf/server/devsoundstandardcustominterfaces.h>
27 #include <mmf/server/mmfdatapath2.h>
29 const TUint KSampleRate8000Hz = 8000;
30 const TUint KSampleRate11025Hz = 11025;
31 const TUint KSampleRate12000Hz = 12000;
32 const TUint KSampleRate16000Hz = 16000;
33 const TUint KSampleRate22050Hz = 22050;
34 const TUint KSampleRate24000Hz = 24000;
35 const TUint KSampleRate32000Hz = 32000;
36 const TUint KSampleRate44100Hz = 44100;
37 const TUint KSampleRate48000Hz = 48000;
38 const TUint KSampleRate64000Hz = 64000;
39 const TUint KSampleRate88200Hz = 88200;
40 const TUint KSampleRate96000Hz = 96000;
41 const TUint KNumChannelsMono = 1;
42 const TUint KNumChannelsStereo = 2;
45 TMmfAudioControllerPanics is an enumeration with the following entries:
46 EBadArgument indicates a bad argument
47 EBadState indicates a state viaolation
48 EBadInvariant indicates an invariant violation
49 EBadReset indicates failed reset
50 EPostConditionViolation indicates a post condition violation
52 enum TMmfAudioControllerPanics
58 EPostConditionViolation,
60 EBadStateToGetDataSource,
62 EBadStateToGetDataSink,
78 EBadStateToSetPosition,
82 EBadStateToGetNumberOfMetaDataEntries,
83 EBadStateGetNumberOfMetaDataEntries,
84 EBadStateToGetMetaDataEntries,
85 EBadStateGetMetaDataEntries,
87 ENotReadyForDataSourceRemoval,
88 EBadDataSourceRemoval,
89 ENotReadyForDataSinkRemoval,
91 ENotReadyForCustomCommand,
92 EBadStateAfterNegotiate,
94 EBadStateToSetPriority,
96 EBadStateToSendEventToClient,
97 EBadStateAfterSendEventToClient,
99 EBadStateAfterVolumeSet,
100 EBadStateToGetMaxVolume,
101 EBadStateAfterGetMaxVolume,
102 EBadStateToGetVolume,
103 EBadStateAfterGetVolume,
104 EBadStateToSetVolumeRamp,
105 EBadStateAfterSetVolumeRamp,
106 EBadStateToSetBalance,
107 EBadStateAfterSetBalance,
108 EBadStateToGetBalance,
109 EBadStateAfterGetBalance,
111 EBadStateAfterGainSet,
112 EBadStateToGetMaxGain,
113 EBadStateAfterGetMaxGain,
115 EBadStateAfterGetGain,
116 EBadStateToGetRecordTimeAvailable,
117 EBadStateAfterGetRecordTimeAvailable,
119 EBadStateToGetMaxFileSize,
120 EBadStateAfterGetMaxFileSize,
123 EBadStateToAddMetaDataEntry,
124 EBadStateAfterAddMetaDataEntry,
125 EBadStateToRemoveMetaDataEntry,
126 EBadStateAfterRemoveMetaDataEntry,
127 EBadStateToReplaceMetaDataEntry,
128 EBadStateAfterReplaceMetaDataEntry,
129 EBadStateToSetSourceSampleRate,
130 EBadStateAfterSetSourceSampleRate,
131 EBadStateToSetSourceNumChannels,
132 EBadStateAfterSetSourceNumChannels,
133 EBadStateToSetSourceFormat,
134 EBadStateAfterSetSourceFormat,
135 EBadStateToSetSinkSampleRate,
136 EBadStateAfterSetSinkSampleRate,
137 EBadStateToSetSinkNumChannels,
138 EBadStateAfterSetSinkNumChannels,
139 EBadStateToSetSinkFormat,
140 EBadStateAfterSetSinkFormat,
142 EBadStateAfterSetCodec,
143 EBadStateToSetSourceBitRate,
144 EBadStateAfterSetSourceBitRate,
145 EBadStateToSetSinkBitRate,
146 EBadStateAfterSetSinkBitRate,
147 ESetRateIsNotSameAsBitRate,
148 EBadStateToGetSourceSampleRate,
149 EBadStateAfterGetSourceSampleRate,
150 EBadStateToGetSourceBitRate,
151 EBadStateAfterGetSourceBitRate,
152 EBadStateToGetSourceNumChannels,
153 EBadStateAfterGetSourceNumChannels,
154 EBadStateToGetSourceFormat,
155 EBadStateAfterGetSourceFormat,
157 EBadStateToRegisterAsClient,
158 EBadStateAfterRegisterAsClient,
159 EBadStateToCancelRegisterAsClient,
160 EBadStateAfterCancelRegisterAsClient,
161 EBadStateToGetResourceNotificationData,
162 EBadStateAfterGetResourceNotificationData,
163 EBadStateToResumePlay,
164 EBadStateAfterResumePlay,
168 This method generates a panic
172 void Panic(TInt aPanicCode)
174 _LIT(KMMFAudioControllerPanicCategory, "MMFAudioController");
175 User::Panic(KMMFAudioControllerPanicCategory, aPanicCode);
181 * @return CMMFAudioController*
183 CMMFController* CMMFAudioController::NewL()
185 CMMFAudioController* self = new(ELeave) CMMFAudioController;
186 CleanupStack::PushL(self);
188 CleanupStack::Pop( self );
189 return STATIC_CAST( CMMFController*, self );
196 void CMMFAudioController::ConstructL()
200 iDataPath = CMMFDataPath2::NewL(iMediaId, *this);
201 iSourceFormat = NULL;
203 iSourceAndSinkAdded = EFalse;
204 iStoppingRecording = EFalse;
207 //iMediaId has already been set up
208 SetState( EStopped );
209 //iPrioritySettings not initialised because they are held by the controller framework
211 // Construct custom command parsers
212 CMMFAudioPlayDeviceCustomCommandParser* audPlayDevParser = CMMFAudioPlayDeviceCustomCommandParser::NewL(*this);
213 CleanupStack::PushL(audPlayDevParser);
214 AddCustomCommandParserL(*audPlayDevParser);
215 CleanupStack::Pop( audPlayDevParser );
217 CMMFAudioRecordDeviceCustomCommandParser* audRecDevParser = CMMFAudioRecordDeviceCustomCommandParser::NewL(*this);
218 CleanupStack::PushL(audRecDevParser);
219 AddCustomCommandParserL(*audRecDevParser);
220 CleanupStack::Pop(audRecDevParser);
222 CMMFAudioPlayControllerCustomCommandParser* audPlayConParser = CMMFAudioPlayControllerCustomCommandParser::NewL(*this);
223 CleanupStack::PushL(audPlayConParser);
224 AddCustomCommandParserL(*audPlayConParser);
225 CleanupStack::Pop(audPlayConParser);
227 CMMFAudioRecordControllerCustomCommandParser* audRecConParser = CMMFAudioRecordControllerCustomCommandParser::NewL(*this);
228 CleanupStack::PushL(audRecConParser);
229 AddCustomCommandParserL(*audRecConParser);
230 CleanupStack::Pop(audRecConParser);
232 CMMFAudioControllerCustomCommandParser* audConParser = CMMFAudioControllerCustomCommandParser::NewL(*this);
233 CleanupStack::PushL(audConParser);
234 AddCustomCommandParserL(*audConParser);
235 CleanupStack::Pop(audConParser);
237 CMMFDRMCustomCommandParser* drmParser = CMMFDRMCustomCommandParser::NewL(*this);
238 CleanupStack::PushL(drmParser);
239 AddCustomCommandParserL(*drmParser);
240 CleanupStack::Pop(drmParser);
242 CMMFResourceNotificationCustomCommandParser* NotiParser = CMMFResourceNotificationCustomCommandParser::NewL(*this);
243 CleanupStack::PushL(NotiParser);
244 AddCustomCommandParserL(*NotiParser);
245 CleanupStack::Pop(NotiParser);//audio resource Notification Parser
247 CMMFAudioPlayControllerSetRepeatsCustomCommandParser* audPlayConSetRepeatsParser = CMMFAudioPlayControllerSetRepeatsCustomCommandParser::NewL(*this);
248 CleanupStack::PushL(audPlayConSetRepeatsParser);
249 AddCustomCommandParserL(*audPlayConSetRepeatsParser);
250 CleanupStack::Pop(audPlayConSetRepeatsParser);
253 // [ assert the invariant now that we are constructed ]
254 __ASSERT_ALWAYS( Invariant(), Panic( EStateNotConstructed));
259 * CMMFAudioController
263 CMMFAudioController::CMMFAudioController()
264 : iMediaId(KUidMediaTypeAudio),
265 iDisableAutoIntent(EFalse),
272 * ~CMMFAudioController
276 CMMFAudioController::~CMMFAudioController()
278 // [ ensure we have logged off the thread ]
281 iDataPath->ResetL(); // this does not leave
284 delete iSourceFormat;
286 delete iStoppingMessage;
292 * Adds a data source to the controller
297 * Source does not already exist
299 * iDataSource != NULL
300 * iDataSourceAdded == ETrue
302 void CMMFAudioController::AddDataSourceL(MDataSource& aSource)
304 //[ assert the invariant ]
305 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetDataSource));
307 // [ precondition that the controller is stopped ]
308 if( State() != EStopped )
309 User::Leave( KErrNotReady );
311 //[ precondition iData source is not already configured ]
313 User::Leave(KErrAlreadyExists);
315 // Note that this code is not generic for sources
316 // It it only checks for file, des clips and audio inputs
317 // If a new source type eg a Url Clip then this needs to be added to the supported source Uids
318 if ( SourceFormatRequired( aSource) )
320 // Get the format from the Source if possible from no specific supplier
321 TRAPD(err, iSourceFormat = CMMFFormatDecode::NewL(&aSource, KNullDesC, iSourceFormatSupportsCustomInterfaces));
322 //[ we want to complete silently for KErrNotSupported
323 // because there is a possibility that the client
324 // wants to add the data format later, see audio api for
325 // a description of this feature]
326 if ((err != KErrNotSupported) && (err != KErrNone))
331 else if (aSource.DataSourceType()==KUidMmfAudioInput)
333 //[ ensure that the audio input has a pointer to dev sound ]
334 CMMFAudioInput* audioInput = STATIC_CAST(CMMFAudioInput*, &aSource);
335 __ASSERT_ALWAYS( audioInput, Panic(ENoAudioInput));
336 // [ lets load dev sound ]
337 User::LeaveIfError(audioInput->SourceThreadLogon( *this ));
341 User::Leave(KErrNotSupported);
344 //[ its now safe to set the source ]
345 iDataSource = &aSource ;
347 //[ assert the post condition ]
348 __ASSERT_ALWAYS(iDataSource, Panic(EMMFAudioControllerPanicDataSourceDoesNotExist));
350 iDataSource->SetSourcePrioritySettings(iPrioritySettings);
356 * Adds a data sink to the controller
361 void CMMFAudioController::AddDataSinkL(MDataSink& aSink)
363 //[ assert the invariant ]
364 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetDataSink));
366 // [ precondition that the controller is stopped ]
367 if( State() != EStopped )
368 User::Leave( KErrNotReady );
370 // [ assert precondition that sink does not exist ]
372 User::Leave(KErrAlreadyExists);
375 // Note that this code is not generic for sinks
376 // It it only checks for file,des clips and audio outputs
377 // If a new sink type eg a Url Clip then this needs to be added to the supported source Uids
378 if ( SinkFormatRequired( aSink ) )
379 {//the sink is a clip
381 // Get the format from the Sink if possible from no specific supplier
382 TRAPD(err, iSinkFormat = CMMFFormatEncode::NewL(&aSink, KNullDesC));
383 //[ we want to complete silently for KErrNotSupported
384 // because there is a possibility that the client
385 // wants to add the data format later, see audio api for
386 // a description of this feature]
387 if ((err != KErrNotSupported) && (err != KErrNone))
392 else if (aSink.DataSinkType()==KUidMmfAudioOutput)
395 //[ ensure that the audio output has a pointer to dev sound ]
396 CMMFAudioOutput* audioOutput = STATIC_CAST(CMMFAudioOutput*, &aSink);
397 __ASSERT_ALWAYS( audioOutput, Panic(ENoAudioOutput));
398 // [ lets load dev sound ]
399 User::LeaveIfError(audioOutput->SinkThreadLogon( *this ));
400 if (IsSecureDrmModeL())
402 User::LeaveIfError(audioOutput->SoundDevice().SetClientThreadInfo(ClientThreadIdL()));
407 User::Leave(KErrNotSupported);
410 //[ now that we are sure we have not left we can update the sink
414 // [ assert post conditions that a sink has been added ]
415 __ASSERT_ALWAYS(iDataSink, Panic(EMMFAudioControllerPanicDataSinkDoesNotExist));
417 iDataSink->SetSinkPrioritySettings(iPrioritySettings);
423 * If Prime fails the client should reset the controller
424 * because as noted below this code is not transactional.
427 void CMMFAudioController::PrimeL()
429 //[ assert the invariant ]
430 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateForPrime));
432 //[ assert the precondition ( in a friendly way for this api
433 // that we are either stopped or primed already ]
434 if(!(( State() == EStopped ) || (State() == EPrimed )))
435 User::Leave( KErrNotReady );
437 // [ precondition we have a data source & sink ]
438 __ASSERT_ALWAYS( iDataSource, Panic( ENoDataSource));
439 __ASSERT_ALWAYS( iDataSink, Panic( ENoDataSink));
442 //[ precondition that we need a source format ]
443 if ( SourceFormatRequired(*iDataSource) && !(iSourceFormat))
444 User::Leave( KErrNotSupported );
446 // [ check the precondition if we need a data sink format ]
447 if ( SinkFormatRequired(*iDataSink) && !( iSinkFormat ))
449 User::Leave( KErrNotSupported );
452 // [ ideally this code should be transaction based and
453 // if failure occurs we roll back to the previous state
454 // in the code below this is not the case and the controller
455 // can be left in an unstable state should any part of prime fail]
456 if (iState == EStopped)
457 { //datapath propagates prime to sink & source
461 if (!iSourceAndSinkAdded)
463 //add data source and sinks to datapath - Note cant do this in AddDataSource/Sink
464 //because the sources and sinks aren't configured at this point
466 iDataPath->AddDataSourceL(iSourceFormat);
467 else if (iDataSource)
468 iDataPath->AddDataSourceL(iDataSource);
470 iDataPath->AddDataSinkL(iSinkFormat);
472 iDataPath->AddDataSinkL(iDataSink);
473 iSourceAndSinkAdded = ETrue ;
480 //in case of imaadpcm format set the output block length
482 TFourCC sourceFourCC = iSourceFormat->SourceDataTypeCode(TMediaId(KUidMediaTypeAudio));
483 if ((sourceFourCC == KMMFFourCCCodeIMAD) && iSourceFormatSupportsCustomInterfaces)
485 CMMFFormatDecode2* decode2 = static_cast<CMMFFormatDecode2*>(iSourceFormat);
486 MMMFDecodeCustomInterfaceBlockLength* formatBlockLengthCI = static_cast<MMMFDecodeCustomInterfaceBlockLength*>(decode2->CustomInterface(KUidCustomInterfaceMmfDecodeBlockLength));
487 if (formatBlockLengthCI)
489 TInt blockLength = formatBlockLengthCI->FileBlockLength();
490 TInt err = iDataPath->SetBlockLength(blockLength);
492 if ((err != KErrNone) && (iDataSink))
494 MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
495 MMMFDevSoundCustomInterfaceFileBlockLength* fileBlockLengthCI = static_cast<MMMFDevSoundCustomInterfaceFileBlockLength*>(audioOutput->SoundDevice().CustomInterface(KUidCustomInterfaceDevSoundFileBlockLength));
497 if (fileBlockLengthCI)
499 fileBlockLengthCI->SetFileBlockLength(blockLength);
503 User::LeaveIfError(err);
508 if ((iSinkFormat) && (!iSourceFormat))
509 {//we are recording to a clip so the data path position is the sink
510 //need to set datapath position to end of format pos (incase sink clip already exists
511 TTimeIntervalMicroSeconds duration = iSinkFormat->Duration(iMediaId);
512 if (duration != TTimeIntervalMicroSeconds(0))
513 {//the file already exists and has a duration so set data path position to the end of the file
514 iDataPath->SetPositionL(duration);
517 //[ it is now safe to make the transition to primed ]
520 else if (State() == EPrimed)
521 { //controller is already primed so just pass prime onto DP
525 if (iDataSource->DataSourceType()==KUidMmfFileSource)
527 CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
528 // we only support protected files for playback
529 if (iDataSink->DataSinkType()!=KUidMmfAudioOutput && file->IsProtectedL())
530 User::Leave(KErrNotSupported);
533 //[ assert the post condition that we are in the state primed]
534 __ASSERT_ALWAYS( SetState( EPrimed ), Panic( EPostConditionViolation ));
535 // [ assert the invariant]
536 __ASSERT_ALWAYS( Invariant(), Panic( EStateNotPrimed ) );
541 * This method resets the controller
544 void CMMFAudioController::ResetL()
546 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToReset ) );
547 iIsPreemptionPause = EFalse;
548 // Stop recording if it's not stopped,
549 if (State() != EStopped)
556 // Remove references to source and sink
559 delete iSourceFormat; iSourceFormat = NULL ;
560 delete iSinkFormat; iSinkFormat = NULL ;
562 //[ ensure loggoff of source and sink ]
565 iSourceAndSinkAdded = EFalse;
567 // [ assert the invariant]
568 __ASSERT_ALWAYS( Invariant(), Panic( EBadResetState ) );
570 // [ assert the post condition
572 // iDataSource is NULL
573 // iSourceFormat is NULL
574 // iSinkFormat is NULL ]
575 __ASSERT_ALWAYS( ResetPostCondition(), Panic( EBadReset ));
576 __ASSERT_ALWAYS( Invariant(), Panic(EBadState));
581 * This function determnines if the reset post condition is valid
582 * @internalTechnology
584 TBool CMMFAudioController::ResetPostCondition() const
587 TBool result = EFalse ;
588 if((iSourceFormat == NULL) &&
589 (iDataSink == NULL) &&
590 (iDataSource == NULL) &&
591 (iSinkFormat == NULL) &&
592 (State() == EStopped))
606 void CMMFAudioController::PlayL()
608 // [ assert the precondition that the
609 // play command is only activated in the primed state]
610 if ( State() != EPrimed)
612 User::Leave(KErrNotReady);
615 // [ assert the Invariant ]
616 __ASSERT_ALWAYS( Invariant(), Panic(EStateNotReadyToPlay));
618 // if the position has already been set to the file's duration or
619 // beyond, then don't bother getting the datapath to play - this
620 // avoids sending empty buffers to DevSound
621 if (iDataSink->DataSinkType() == KUidMmfAudioOutput &&
622 PositionL() >= DurationL())
624 SendEventToClient(TMMFEvent(KMMFEventCategoryPlaybackComplete, KErrNone));
628 // Execute play intent
629 // This must be done after PlayL, as the file might not be open yet
630 if(!iIsPreemptionPause)
632 if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource )
634 CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
635 TInt err = file->ExecuteIntent(iIsPaused? ContentAccess::EContinue : ContentAccess::EPlay);
642 //[datapath propogates play to sink & source]
644 iIsPreemptionPause = EFalse;
646 SetState( EPlaying );
648 //[ assert the post condition we are playing ]
649 //No - this assumption is not always true if an error occurs eg OOM
650 //the state could be EStopped
651 // __ASSERT_ALWAYS( (State() == EPlaying ), Panic( EBadState));
652 //[ assert the invariant ]
653 __ASSERT_ALWAYS( Invariant(), Panic(EBadPlayState));
660 void CMMFAudioController::PauseL()
662 // [ assert the invariant ]
663 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToPause));
665 //[ assert the precondition that we are playing ]
666 if ( State() != EPlaying)
668 User::Leave(KErrNotReady);
670 if(!iIsPreemptionPause)
672 if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource)
674 CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
675 TInt err = file->ExecuteIntent(ContentAccess::EPause);
683 //[ datapath propogates pause to sink & source ]
684 if(iIsPreemptionPause)
686 iDataPath->PreEmptionPause();
694 //[ assert the post condition we are primed ]
695 __ASSERT_ALWAYS( (State() == EPrimed ), Panic( EBadState));
696 //[ assert the invariant ]
697 __ASSERT_ALWAYS( Invariant(), Panic(EBadPauseState));
704 void CMMFAudioController::StopL(TMMFMessage& aMessage)
706 //[ assert the invariant ]
707 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToStop));
708 // [ precondition that we are not already stopped
709 // && if we are stopped do nothing.
710 //If we are stopping a recording, we need to give the datapath chance to
711 //process that data which has already been captured. We therefore stay in the EPlaying
712 //state, but use iStoppingRecording to indicate that we are stopping.
714 if ((State() != EStopped) && !iStoppingRecording)
716 if((State() == EPlaying) && (iDataSource->DataSourceType()==KUidMmfAudioInput)) //we are recording
718 // datapath is requested to stop recording but process any alreay captured buffers,
719 // the pause method is used for this purpose and as such, the data path must
720 // determine that it is recording to be able to act accordingly.
721 // aMessgae is not completed until datapath advises that it has completed.
723 iStoppingMessage = CMMFMessageHolder::NewL(aMessage);
724 iStoppingRecording = ETrue;
726 else if(((State() == EPlaying) || iIsPaused) && (iDataSink->DataSinkType()==KUidMmfAudioOutput)) //we are playing
728 if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource)
730 CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
731 file->ExecuteIntent(ContentAccess::EStop);
733 // datapath propogates stop to sink & source
740 // datapath propogates stop to sink & source
746 iIsPreemptionPause = EFalse;
747 //complete message as request is complete.
748 if(State() == EStopped && !IsUnderTest())
750 aMessage.Complete(KErrNone);
753 //[ assert the invariant ]
754 __ASSERT_ALWAYS( Invariant(), Panic(EBadStopState));
760 * The Controller is in the state EPrimed
761 * @return TTimeIntervalMicroSeconds
764 TTimeIntervalMicroSeconds CMMFAudioController::PositionL() const
766 //[ assert the invariant ]
767 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToPosition));
768 // [ precondition that we are playing or primed ]
769 if( !((State() == EPrimed) || (State() == EPlaying)))
770 User::Leave(KErrNotReady);
772 TTimeIntervalMicroSeconds position = iDataPath->Position();
774 //[ assert the invariant ]
775 __ASSERT_ALWAYS( Invariant(), Panic(EBadStatePosition));
786 void CMMFAudioController::SetPositionL(const TTimeIntervalMicroSeconds& aPosition)
788 //[ assert the invariant ]
789 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetPosition));
791 // [ precondition that we are not already stopped ]
792 if (iState == EStopped)
793 User::Leave(KErrNotReady);
795 //[ precondition that the position is >= 0 && <= Duration ]
797 TTimeIntervalMicroSeconds theDuration(0);
799 { //if the source is a clip then the duration always refers to the source - even if the sink is a clip
800 theDuration = iSourceFormat->Duration(iMediaId);
802 else if (iSinkFormat)
803 { //duration of recorded clip
804 theDuration = iSinkFormat->Duration(iMediaId);
806 TTimeIntervalMicroSeconds theStart(0);
807 if( ( aPosition < theStart) || ( aPosition > theDuration) )
808 //[ invalid position before start and after end]
809 User::Leave(KErrArgument);
812 //[ set the position on the data path ]
814 // if we're already playing, flush all the buffers by calling Stop(),
815 // PrimeL() and then PlayL() - otherwise we could be waiting a long time.
816 if (iDataSink->DataSinkType() == KUidMmfAudioOutput && iState == EPlaying)
818 CMMFAudioOutput* audioOutput = static_cast<CMMFAudioOutput*>(iDataSink);
819 if(!audioOutput->IsResumeSupported())
824 iDataPath->SetPositionL(aPosition);
825 iDataPath->RetainRepeatInfo();
831 // This empty buffers
832 User::LeaveIfError(audioOutput->SoundDevice().EmptyBuffers());
833 iDataPath->SetPositionL(aPosition);
834 iDataPath->RetainRepeatInfo();
835 // This does a DevSound resume
840 iDataPath->SetPositionL(aPosition);
842 //[ assert the invariant ]
843 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateSetPosition));
845 // [ post condition not checked ]
846 //[ we do not compare the set position with get postion
847 // because the interface to do so is poor ]
854 * @returns TTimeIntervalMicroSeconds
857 TTimeIntervalMicroSeconds CMMFAudioController::DurationL() const
859 //[ assert the invariant ]
860 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToDuration));
863 // [ assert we have a format that supports duration ]
864 if( !( iSourceFormat || iSinkFormat ) )
865 User::Leave(KErrNotSupported);
867 //[ now do the real work of getting the duration ]
868 // ------------------------------------------------
869 TTimeIntervalMicroSeconds theDuration(0);
871 { //if the source is a clip then the duration always refers to the source - even if the sink is a clip
872 theDuration = iSourceFormat->Duration(iMediaId);
874 else if (iSinkFormat)
875 { //duration of recorded clip
876 theDuration = iSinkFormat->Duration(iMediaId);
879 //[ assert the invariant ]
880 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateDuration));
887 * GetNumberOfMetaDataEntriesL
892 void CMMFAudioController::GetNumberOfMetaDataEntriesL(TInt& aNumberOfEntries )
895 //[ assert the invariant ]
896 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetNumberOfMetaDataEntries));
898 //[ precondition that we are in the primed state or stopped ]
899 if( !((State() == EPrimed) || ( State() == EStopped)))
900 User::Leave(KErrNotReady);
902 // [ precondition there is a sink format ]
904 User::Leave(KErrNotSupported);
906 // [ precondition the sink format is an encode format ]
907 if ((iDataSink->DataSinkType()!=KUidMmfAudioOutput) &&
908 (iDataSource->DataSourceType()!= KUidMmfAudioInput) )
909 User::Leave(KErrNotSupported);
911 if (iDataSink->DataSinkType()==KUidMmfAudioOutput)
914 //[ precondition the format exists ]
916 User::Leave(KErrNotSupported);
918 //[ Get the Number of meta data entries from the sink format ]
919 iSourceFormat->GetNumberOfMetaDataEntriesL( aNumberOfEntries );
921 else if (iDataSource->DataSourceType()==KUidMmfAudioInput)
924 User::Leave(KErrNotSupported);
926 iSinkFormat->GetNumberOfMetaDataEntriesL( aNumberOfEntries );
929 //[ assert the invariant ]
930 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateGetNumberOfMetaDataEntries));
937 * @returns "CMMFMetaDataEntry*"
939 CMMFMetaDataEntry* CMMFAudioController::GetMetaDataEntryL(TInt aIndex )
941 //[ assert the invariant ]
942 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMetaDataEntries));
944 //[ precondition that we are in the primed state or stopped ]
945 if( !((State() == EPrimed) || ( State() == EStopped)))
946 User::Leave(KErrNotReady);
948 // [ precondition there is a sink format ]
950 User::Leave(KErrNotSupported);
952 iDataSink->DataSinkType();
953 iDataSource->DataSourceType();
955 // [ precondition the sink or source is either an audio output or input ]
956 if ((iDataSink->DataSinkType()!= KUidMmfAudioOutput) &&
957 (iDataSource->DataSourceType()!= KUidMmfAudioInput ))
958 User::Leave(KErrNotSupported);
960 //[ Get the meta data entry from the sink format ]
961 CMMFMetaDataEntry* theEntry = NULL;
963 if (iDataSink->DataSinkType()==KUidMmfAudioOutput)
965 //[ precondition the format exists ]
967 User::Leave(KErrNotSupported);
969 //[ Get the Number of meta data entries from the sink format ]
970 theEntry = iSourceFormat->MetaDataEntryL(aIndex);
972 else if (iDataSource->DataSourceType()==KUidMmfAudioInput)
974 //[ precondition the format exits ]
976 User::Leave(KErrNotSupported);
977 theEntry = iSinkFormat->MetaDataEntryL(aIndex);
980 //[ assert the post condition that the entry is not null ]
981 __ASSERT_ALWAYS( theEntry, Panic(EMetaEntryIsNull));
983 //[ assert the invariant ]
984 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateGetMetaDataEntries));
994 void CMMFAudioController::RemoveDataSourceL(MDataSource& aDataSource )
996 //[ assert the invariant ]
997 __ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForDataSourceRemoval) );
999 //[ precondition is that we have a data source ]
1001 User::Leave(KErrNotReady);
1003 //[precondition the data source is the data source we have]
1004 if( iDataSource != &aDataSource )
1005 User::Leave(KErrArgument);
1007 //[ the controller is in the stopped state ]
1008 if(State() != EStopped)
1009 User::Leave(KErrNotReady);
1011 //[ remove the data sink from the controller and delete the format]
1012 if( iSourceAndSinkAdded )
1014 __ASSERT_ALWAYS( iDataPath, Panic( EBadState ));
1015 //[ Remove references to source and sink ]
1016 iDataPath->ResetL();
1017 iSourceAndSinkAdded = EFalse ;
1020 // [ delete the data sink and format ]
1021 iDataSource = NULL ;
1022 delete iSourceFormat;
1023 iSourceFormat = NULL;
1025 // [ assert postcondition we are stopped ]
1026 __ASSERT_ALWAYS( (State() == EStopped), Panic(EPostConditionViolation) );
1028 //[ assert postcondition the SourceAndSinkAdded is false ]
1029 __ASSERT_ALWAYS( !iSourceAndSinkAdded, Panic( EPostConditionViolation ));
1031 //[ assert postcondition the data sinkformat is null ]
1032 __ASSERT_ALWAYS( (iSourceFormat == NULL ), Panic( EPostConditionViolation ));
1034 //[ assert postcondition the data sink is null ]
1035 __ASSERT_ALWAYS( (iDataSource == NULL ), Panic( EPostConditionViolation ));
1037 //[ assert the invariant ]
1038 __ASSERT_ALWAYS( Invariant(), Panic(EBadDataSourceRemoval));
1048 void CMMFAudioController::RemoveDataSinkL(MDataSink& aDataSink )
1050 //[ assert the invariant ]
1051 __ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForDataSinkRemoval) );
1053 //[ precondition is that we have a data sink ]
1055 User::Leave(KErrNotSupported);
1057 //[precondition the data sink is the data sink we have]
1058 if( iDataSink != &aDataSink )
1059 User::Leave(KErrNotSupported);
1061 //[ the controller is in the stopped state ]
1062 if(State() != EStopped)
1063 User::Leave(KErrNotReady);
1065 //[ remove the data sink from the controller and delete the format]
1066 if( iSourceAndSinkAdded )
1068 __ASSERT_ALWAYS( iDataPath, Panic( EBadState ));
1069 //[ Remove references to source and sink ]
1070 iDataPath->ResetL();
1071 iSourceAndSinkAdded = EFalse ;
1074 // [ reset data sink referenece and remove the format ]
1079 // [ assert postcondition we are stopped ]
1080 __ASSERT_ALWAYS( (State() == EStopped), Panic(EPostConditionViolation) );
1082 //[ assert postcondition the SourceAndSinkAdded is false ]
1083 __ASSERT_ALWAYS( !iSourceAndSinkAdded, Panic( EPostConditionViolation ));
1085 //[ assert postcondition the data sinkformat is null ]
1086 __ASSERT_ALWAYS( (iSinkFormat == NULL ), Panic( EPostConditionViolation ));
1088 //[ assert postcondition the data sink is null ]
1089 __ASSERT_ALWAYS( (iDataSink == NULL ), Panic( EPostConditionViolation ));
1091 //[ assert the invariant ]
1092 __ASSERT_ALWAYS( Invariant(), Panic(EBadDataSinkRemoval));
1099 void CMMFAudioController::CustomCommand(TMMFMessage& aMessage)
1101 //[ assert the invariant ]
1102 __ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForCustomCommand));
1103 // [ We do not have any custom commands ]
1104 aMessage.Complete(KErrNotSupported);
1111 void CMMFAudioController::NegotiateL()
1113 //[ assert the invariant ]
1114 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToNegotiate));
1116 //utility function used by custom to negotiate source sink settings after a change
1117 if ((iSourceFormat)&&(iSinkFormat)) //convert
1119 iSinkFormat->NegotiateL(*iSourceFormat);
1120 iSourceFormat->NegotiateSourceL(*iSinkFormat);
1121 iSinkFormat->NegotiateL(*iSourceFormat);
1123 // check for upsampling attempts
1124 if (iSinkFormat->SampleRate() > iSourceFormat->SampleRate())
1126 // we don't support upsampling
1127 User::Leave( KErrNotSupported );
1130 else if ((iDataSource)&&(iSinkFormat)) //record
1132 // need two step negotiation for record
1133 // first try to set the audio input settings to match the required settings for recording
1134 iDataSource->NegotiateSourceL(*iSinkFormat);
1135 // now call negotiateL on the sink in order to tell it what the audio input was set to.
1136 iSinkFormat->NegotiateL(*iDataSource);
1138 else if ((iSourceFormat)&&(iDataSink)) //play
1140 iDataSink->NegotiateL(*iSourceFormat);
1142 //[ assert the invariant ]
1143 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterNegotiate));
1147 * SetPrioritySettings
1149 * @param aPrioritySettings
1151 void CMMFAudioController::SetPrioritySettings(const TMMFPrioritySettings& aPrioritySettings)
1153 //[ assert the invariant ]
1154 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetPriority));
1156 //[ update the priority settings of the controller]
1157 iPrioritySettings = aPrioritySettings;
1159 //pass settings on to source and sink
1162 iDataSource->SetSourcePrioritySettings(iPrioritySettings);
1166 iDataSink->SetSinkPrioritySettings(iPrioritySettings);
1169 // assert the post condition
1170 //__ASSERT_ALWAYS( (iPrioritySettings == aPrioritySettings), Panic( ));
1171 //[ assert the invariant ]
1172 __ASSERT_ALWAYS( Invariant(), Panic(EBadPriorityState));
1180 TInt CMMFAudioController::SendEventToClient(const TMMFEvent& aEvent)
1182 //[ assert the invariant ]
1183 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSendEventToClient));
1185 TMMFEvent controllerEvent;
1186 //Were going to stop playing, force event type to be the correct type
1187 controllerEvent.iEventType = KMMFEventCategoryPlaybackComplete;
1188 controllerEvent.iErrorCode = aEvent.iErrorCode;
1192 //If we receive KErrNone from the DataPath, it indicates that it has
1193 //successfully completed playing/converting/recording.
1194 if ((aEvent.iEventType == KMMFEventCategoryPlaybackComplete) &&
1195 (aEvent.iErrorCode == KErrNone))
1197 if(iStoppingRecording)
1199 iStoppingRecording = EFalse;
1201 SetState( EStopped );
1203 //complete the clients stop request
1204 iStoppingMessage->Complete(KErrNone);
1205 delete iStoppingMessage; iStoppingMessage=NULL;
1207 //we don't want to send an event to the client
1211 {//datapath has reached end of file so set internal state to primed
1212 SetState( EPrimed );
1216 //If the client has not registered for the ARN,
1217 //and a pre-emption happens we need to goto the Pause state
1218 //instead of the Stop state. this should happen only in the case of playback.
1219 //In case of recoding we goto the stop state.
1220 else if(!iRegisterARN &&
1221 (aEvent.iErrorCode == KErrAccessDenied || aEvent.iErrorCode == KErrInUse ||aEvent.iErrorCode == KErrDied)
1222 && (iDataSink->DataSinkType()==KUidMmfAudioOutput))
1224 //setting iIsPreemptionPause to true so that PauseL can make differentiate it from normal pause.
1225 iIsPreemptionPause = ETrue;
1226 TRAPD(err,PauseL());
1230 SetState( EStopped );
1231 iIsPreemptionPause = EFalse;
1236 if ( State()!= EStopped)
1238 //datapath propogates stop to sink & source
1240 SetState( EStopped );
1242 if(iStoppingRecording)
1243 {// an error has occurred while we were waiting for recording to stop,
1244 //must complete clients request
1245 iStoppingRecording = EFalse;
1246 iStoppingMessage->Complete(aEvent.iErrorCode);
1247 delete iStoppingMessage; iStoppingMessage=NULL;
1251 if(!iIsPreemptionPause)
1253 //should call ExecuteIntent to tell the DRM agent that playback has stopped
1254 if (aEvent.iEventType == KMMFEventCategoryPlaybackComplete)
1256 if ((iDataSink->DataSinkType() == KUidMmfAudioOutput))
1258 if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource)
1260 CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
1261 file->ExecuteIntent(ContentAccess::EStop);
1267 //now send event to client...
1268 TInt result = KErrNone;
1269 if(aEvent.iEventType == KMMFEventCategoryAudioResourceAvailable)
1271 result = DoSendEventToClient(aEvent);
1275 result = DoSendEventToClient(controllerEvent);
1278 //[ assert the invariant ]
1279 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSendEventToClient));
1291 void CMMFAudioController::MapdSetVolumeL(TInt aVolume)
1293 //[ assert the invariant ]
1294 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetVolume));
1296 // [ precondition is true for state
1297 // we can set the volume in any state ]
1299 //[ precondition we have a data sink ]
1301 User::Leave(KErrNotReady);
1303 // [ precondition that the data sink is an audio output ]
1304 // Make sure that iDataSink is an Audio Output
1305 if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1306 User::Leave(KErrNotSupported);
1308 MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1310 // [ assert the precondition that aVolume is in range ]
1311 TInt maxVolume = audioOutput->SoundDevice().MaxVolume();
1312 if( ( aVolume < 0 ) || ( aVolume > maxVolume ))
1313 User::Leave(KErrArgument);
1315 //[ set the volume on the device ]
1316 audioOutput->SoundDevice().SetVolume(aVolume);
1318 //[ assert the post condition volume is equal to a volume]
1319 TInt soundVolume = 0;
1320 soundVolume = audioOutput->SoundDevice().Volume();
1322 __ASSERT_ALWAYS( ( soundVolume == aVolume), Panic(EPostConditionViolation));
1324 //[ assert the invariant ]
1325 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterVolumeSet));
1335 void CMMFAudioController::MapdGetMaxVolumeL(TInt& aMaxVolume)
1337 // [ assert the invariant ]
1338 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxVolume));
1340 //[ we can get max volume in any state ]
1342 // [ precondition we must have a data sink ]
1344 User::Leave(KErrNotReady);
1346 //[ precondition the sink must be an audio output]
1347 // Make sure that iDataSink is an Audio Output
1348 if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1349 User::Leave(KErrNotSupported);
1351 //[ get the volume from the device ]
1352 MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1353 aMaxVolume = audioOutput->SoundDevice().MaxVolume();
1355 //[ assert the invariant ]
1356 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxVolume));
1368 void CMMFAudioController::MapdGetVolumeL(TInt& aVolume)
1370 // [ assert the invariant ]
1371 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetVolume));
1373 //[ precondition that we have a data sink ]
1375 User::Leave(KErrNotReady);
1377 //[ precondition iDataSink is an Audio Output ]
1378 if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1379 User::Leave(KErrNotSupported);
1381 // [ get the volume ]
1382 MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1383 aVolume = audioOutput->SoundDevice().Volume();
1385 // [ assert precondition that the volume is in range
1387 TInt aMaxVolume = audioOutput->SoundDevice().MaxVolume();
1388 __ASSERT_ALWAYS( (aVolume <= aMaxVolume), Panic(EBadState));
1389 __ASSERT_ALWAYS( (aVolume >= 0), Panic(EBadState));
1391 // [ assert the invariant ]
1392 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetVolume));
1398 * MapdSetVolumeRampL
1400 * @param aRampDuration
1403 void CMMFAudioController::MapdSetVolumeRampL(const TTimeIntervalMicroSeconds& aRampDuration)
1405 // [ assert the invariant ]
1406 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetVolumeRamp));
1408 //[ precondition that we have a data sink ]
1410 User::Leave(KErrNotReady);
1412 // [ precondition iDataSink is an Audio Output ]
1413 if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1414 User::Leave(KErrNotSupported);
1416 //[ set the volume ramp ]
1417 MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1418 audioOutput->SoundDevice().SetVolumeRamp(aRampDuration);
1420 //[ assert the invariant ]
1421 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSetVolumeRamp));
1433 void CMMFAudioController::MapdSetBalanceL(TInt aBalance)
1435 //[ assert the invariant ]
1436 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetBalance));
1438 // [ precondition is that we have a data sink ]
1440 User::Leave(KErrNotReady);
1442 // [ precondition is that the data sink is an audio output]
1443 if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1444 User::Leave(KErrNotSupported);
1446 //[ get the audio output ]
1447 MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1449 // [ separate out left and right balance ]
1452 CalculateLeftRightBalance( left, right, aBalance );
1454 //[ set the balance ]
1455 audioOutput->SoundDevice().SetPlayBalanceL(left, right);
1457 // [assert the post condition that the balance is set correctly]
1458 TInt rightBalance = 0;
1459 TInt leftBalance = 0;
1460 audioOutput->SoundDevice().GetPlayBalanceL(leftBalance, rightBalance);
1462 //[ assert post condition holds]
1463 TBool postCondition = (( rightBalance == right) && ( leftBalance == left));
1464 __ASSERT_ALWAYS( postCondition, Panic( EPostConditionViolation ) );
1466 //[ assert the invariant ]
1467 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetBalance));
1471 * CalculateLeftRightBalance
1472 * @internalTechnology
1477 * !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight)
1479 * aLeft = m ( aBalance ) + c
1480 * when aBalance = KMMFBalanceMaxLeft aLeft = 100
1481 * when aBalance = KMMFBalanceMaxRight aLeft = 0
1482 * 100 = m( KMMFBalanceMaxLeft ) + c
1483 * 0 = m( KMMFBalanceMaxRight ) + c
1484 * c = -(KMMFBalanceMaxRight) m
1485 * 100 = m(KMMFBalanceMaxLeft ) - m(KMMFBalanceMaxRight)
1486 * m = 100/(KMMFBalanceMaxLeft - KMMFBalanceMaxRight )
1487 * c = -(KMMFBalanceMaxRight) * 100 /(KMMFBalanceMaxLeft - KMMFBalanceMaxRight )
1488 * aLeft = ( aBalance - KMMFBalanceMaxRight ) * 100 /( KMMFBalanceMaxLeft - KMMFBalanceMaxRight )
1490 void CMMFAudioController::CalculateLeftRightBalance( TInt& aLeft, TInt& aRight, TInt aBalance ) const
1492 // Check the balance is within limits & modify to min or max values if necessary
1493 if (aBalance < KMMFBalanceMaxLeft)
1494 aBalance = KMMFBalanceMaxLeft;
1495 if (aBalance > KMMFBalanceMaxRight)
1496 aBalance = KMMFBalanceMaxRight;
1498 //[ Now separate percentage balances out from aBalance ]
1499 aLeft = (100 * (aBalance-KMMFBalanceMaxRight)) / (KMMFBalanceMaxLeft-KMMFBalanceMaxRight);
1500 aRight = 100 - aLeft;
1502 //[ assert post condition that left and right are within range ]
1503 __ASSERT_ALWAYS( ( (aLeft <= 100) && (aLeft >= 0) ), Panic(EPostConditionViolation));
1504 __ASSERT_ALWAYS( ( (aRight <= 100) && (aRight >= 0) ), Panic(EPostConditionViolation));
1513 void CMMFAudioController::MapdGetBalanceL(TInt& aBalance)
1515 //[ assert the invariant ]
1516 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetBalance));
1518 //[ precondition that we have a sink]
1520 User::Leave(KErrNotReady);
1522 // [ iDataSink is an Audio Output ]
1523 if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1524 User::Leave(KErrNotSupported);
1526 // [ get the play balance ]
1527 MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1528 TInt left = 50; // arbitrary values
1530 audioOutput->SoundDevice().GetPlayBalanceL(left, right);
1531 CalculateBalance( aBalance, left, right );
1533 //[ assert the invariant ]
1534 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetBalance));
1543 * follows a simple straight line transformation
1545 * m = (KMMFBalanceMaxLeft-KMMFBalanceMaxRight)/ 100
1546 * c = KMMFBalanceMaxRight
1549 * KMMFBalanceMaxRight = m * 0 + c
1550 * c = KMMFBalanceMaxRight
1552 * KMMFBalanceMaxLeft = m * 100 + KMMFBalanceMaxRight
1553 * m = ( KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) /100
1555 void CMMFAudioController::CalculateBalance( TInt& aBalance, TInt aLeft, TInt aRight ) const
1557 //[ assert pre conditions ]
1558 __ASSERT_ALWAYS( (( 0 <= aLeft) && ( 100 >= aLeft)), Panic( EBadArgument) );
1559 __ASSERT_ALWAYS( (( 0 <= aRight) && ( 100 >= aRight)), Panic( EBadArgument) );
1561 if ((aLeft > 0) && (aRight > 0))
1563 __ASSERT_ALWAYS( (( aLeft + aRight ) == 100 ), Panic( EBadArgument ));
1564 aBalance = (aLeft * (KMMFBalanceMaxLeft-KMMFBalanceMaxRight))/100 + KMMFBalanceMaxRight;
1566 else if ((aLeft == 0) && (aRight == 0))
1570 else if ((aLeft == 0) && (aRight > 0))
1574 else if ((aLeft > 0) && (aRight == 0))
1579 //[ assert post condition that aBalance is within limits ]
1580 __ASSERT_ALWAYS( !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight), Panic(EBadArgument));
1589 void CMMFAudioController::MardSetGainL(TInt aGain)
1591 // [ assert the invariant ]
1592 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetGain));
1594 //[ precondition we are in the state stopped ]
1595 if(State() != EStopped)
1596 User::Leave(KErrNotReady);
1598 // [ assert the precondition that we have a data sink ]
1600 User::Leave(KErrNotSupported);
1602 //[ assert the precondition that the data sink is an audio input ]
1603 if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1604 User::Leave(KErrNotReady);
1606 // Set gain of sound device
1607 MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1608 audioInput->SoundDevice().SetGain(aGain);
1610 //[ assert the invariant ]
1611 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGainSet));
1620 void CMMFAudioController::MardGetMaxGainL(TInt& aMaxGain)
1622 // [ assert the invariant ]
1623 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxGain));
1625 // [ assert the precondition that we have a source ]
1627 User::Leave(KErrNotReady);
1629 //[ assert the precondition that iDataSink is an Audio Input]
1630 if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1631 User::Leave(KErrNotSupported);
1633 MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1634 aMaxGain = audioInput->SoundDevice().MaxGain();
1636 //[ assert the invariant ]
1637 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxGain));
1646 void CMMFAudioController::MardGetGainL(TInt& aGain)
1648 //[ assert the invariant ]
1649 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetGain));
1651 // [ assert the precondition that we have a sink ]
1653 User::Leave(KErrNotReady);
1655 // [ assert the precondition that we have an audio input sink]
1656 if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1657 User::Leave(KErrNotSupported);
1659 MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1660 aGain = audioInput->SoundDevice().Gain();
1662 //[ assert the invariant ]
1663 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetGain));
1672 void CMMFAudioController::MardSetBalanceL(TInt aBalance)
1674 // [ assert the invaraiant ]
1675 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetGain));
1677 // [ precondition is that we have a data source ]
1680 User::Leave(KErrNotReady);
1683 // [ precondition is that the balance is in range ]
1684 // Make sure aBalance is in the range -100 <-> 100
1685 if (aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight)
1686 User::Leave(KErrArgument);
1688 // [ precondition is that the data sink is an audio output]
1689 if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1690 User::Leave(KErrNotSupported);
1693 //[ get the audio output ]
1694 MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1696 // [ separate out left and right balance ]
1699 CalculateLeftRightBalance( left, right, aBalance );
1701 //[ set the balance ]
1702 audioInput->SoundDevice().SetRecordBalanceL(left, right);
1704 // [assert the post condition that the balance is set correctly]
1705 TInt rightBalance = 0;
1706 TInt leftBalance = 0;
1707 audioInput->SoundDevice().GetRecordBalanceL(leftBalance, rightBalance);
1709 //[ assert post condition holds]
1710 TBool postCondition = (( rightBalance == right) && ( leftBalance == left));
1711 __ASSERT_ALWAYS( postCondition, Panic( EPostConditionViolation ) );
1713 //[ assert the invariant ]
1714 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGainSet));
1724 void CMMFAudioController::MardGetBalanceL(TInt& aBalance)
1726 //[ assert the invariant ]
1727 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetBalance));
1729 // [ precondition is that we have a data source ]
1732 User::Leave(KErrNotReady);
1735 // [ iDataSink is an Audio Output ]
1736 if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1737 User::Leave(KErrNotSupported);
1739 // [ get the play balance ]
1740 MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1741 TInt left = 50; // arbitrary values
1743 audioInput->SoundDevice().GetRecordBalanceL(left, right);
1744 CalculateBalance( aBalance, left, right );
1746 //[ assert the invariant ]
1747 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetBalance));
1752 * MapcSetPlaybackWindowL
1757 void CMMFAudioController::MapcSetPlaybackWindowL(const TTimeIntervalMicroSeconds& aStart, const TTimeIntervalMicroSeconds& aEnd)
1759 iDataPath->SetPlayWindowL(aStart, aEnd);
1763 * MapcDeletePlaybackWindowL
1765 void CMMFAudioController::MapcDeletePlaybackWindowL()
1767 iDataPath->ClearPlayWindowL();
1773 * @param aRepeatNumberOfTimes
1774 * @param aTrailingSilence
1778 TInt CMMFAudioController::MapcSetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence)
1780 TInt err = KErrNone;
1785 else if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1787 err = KErrNotSupported;
1791 MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
1792 if(audioOutput->SoundDevice().QueryIgnoresUnderflow())
1794 iDataPath->SetRepeats(aRepeatNumberOfTimes,aTrailingSilence);
1795 iDataPath->SetDrmProperties(iDataSource, &iDisableAutoIntent);
1799 err = KErrNotSupported;
1807 * MapcGetLoadingProgressL
1809 void CMMFAudioController::MapcGetLoadingProgressL(TInt& /*aPercentageComplete*/)
1811 User::Leave(KErrNotSupported);
1816 * MarcGetRecordTimeAvailableL
1820 void CMMFAudioController::MarcGetRecordTimeAvailableL(TTimeIntervalMicroSeconds& aTime)
1822 //[ assert the invariant ]
1823 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetRecordTimeAvailable));
1825 //[ assert the precondition ( in a friendly way for this api
1826 // that we minimally have a data sink ]
1828 User::Leave( KErrNotReady );
1830 // Use the FormatEncode to get the bytes per second and the sink (clip) to get the bytes available
1831 // return the calculated value.
1832 if ((iDataSink->DataSinkType() != KUidMmfFileSink) && (iDataSink->DataSinkType() != KUidMmfDescriptorSink))
1833 User::Leave(KErrNotSupported) ;
1835 // [ max file size ]
1836 //[ pre condition is that we have a sink ]
1838 // In order to get the record time available we need to take into consideration
1839 // that there may be a max file size ]
1840 TInt64 bytesFree = STATIC_CAST(CMMFClip*, iDataSink)->BytesFree() ;
1841 TInt64 bytesPerSecond = TInt64(0);
1842 //[ set default time available ]
1843 aTime = TTimeIntervalMicroSeconds( 0 ) ; // just return zero
1847 TInt maxFileSize = STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->MaximumClipSize();
1848 //[ if maxFileSize > 0 we need to limit the bytes free to this value - size ]
1849 if( maxFileSize > 0 )
1851 // [ strangely the size of data written is a TInt ]
1852 TInt fileSize = STATIC_CAST(CMMFClip*, iDataSink)->Size();
1853 bytesFree = maxFileSize - fileSize;
1854 // [ note it can occur that the fileSize id greater than the MaxFileSize
1855 // due to someone setting the max file size on an existing file ]
1856 if( bytesFree < 0 ) bytesFree = 0;
1857 __ASSERT_DEBUG( ( bytesFree <= maxFileSize), Panic( ENoMemoryToRecord) );
1859 bytesPerSecond = STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->BytesPerSecond() ;
1862 //[ now lets perform the calculation of time available ]
1863 if ( bytesPerSecond != TInt64(0) )
1865 aTime = TTimeIntervalMicroSeconds( bytesFree * KOneSecondInMicroSeconds / bytesPerSecond ) ;
1868 //[ assert the invariant ]
1869 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetRecordTimeAvailable));
1873 * MarcSetMaxDurationL
1874 * @param aMaxDuration
1876 void CMMFAudioController::MarcSetMaxDurationL(const TTimeIntervalMicroSeconds& )
1878 //[ this method is deprecated and no longer supported ]
1879 User::Leave(KErrNotSupported);
1883 * MarcSetMaxFileSizeL
1886 * The argument aFileSize must be greater than -1
1887 * zero is used as a sentinel value which means that the file
1888 * can grow without limit
1890 void CMMFAudioController::MarcSetMaxFileSizeL(TInt aFileSize )
1892 //[ assert the invariant ]
1893 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxFileSize));
1895 //[ assert the state is not playing since this opens open
1896 // nefarious posibilities
1897 if(State() == EPlaying )
1898 User::Leave( KErrNotReady );
1900 //[ assert we have a sink format ]
1902 User::Leave( KErrNotReady );
1904 //[ assert file size > -2, as a basic sanity filter
1905 // 0 is the sentinel value which allows a file to grow
1907 // [We use -1 to reset the value set earlier.]
1908 if( aFileSize < -1 )
1910 User::Leave( KErrArgument );
1913 //[ pre condition is that we have a sink ]
1914 STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->SetMaximumClipSizeL( aFileSize );
1916 // [ assert the post condition ]
1917 // [since we have no means of querying the value
1918 // we have to assume all went well for now or we left]
1920 //[ assert the invariant ]
1921 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxFileSize));
1928 void CMMFAudioController::MarcCropL(TBool aToEnd)
1930 //[ assert the invariant ]
1931 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToCrop));
1933 //[ precondition there is a sink format]
1935 User::Leave(KErrNotSupported);
1937 iSinkFormat->CropL( PositionL(), aToEnd );
1939 //[ assert the invariant ]
1940 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterCrop));
1944 * MarcAddMetaDataEntryL
1947 void CMMFAudioController::MarcAddMetaDataEntryL(const CMMFMetaDataEntry& aNewEntry )
1949 //[ assert the invariant ]
1950 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToAddMetaDataEntry));
1952 //[ precondition the format exists ]
1954 User::Leave(KErrNotSupported);
1956 //[ Add the meta data entry ]
1957 iSinkFormat->AddMetaDataEntryL( aNewEntry );
1959 //[ assert the invariant ]
1960 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterAddMetaDataEntry));
1965 * MarcRemoveMetaDataEntryL
1968 void CMMFAudioController::MarcRemoveMetaDataEntryL(TInt aIndex)
1970 //[ assert the invariant ]
1971 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToRemoveMetaDataEntry));
1973 //[ precondition that we are in the primed state ]
1974 if( State() != EPrimed)
1975 User::Leave(KErrNotReady);
1977 //[ precondition the format exists ]
1979 User::Leave(KErrNotSupported);
1981 //[ remove the meta data entry ]
1982 iSinkFormat->RemoveMetaDataEntry( aIndex );
1984 //[ assert the invariant ]
1985 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterRemoveMetaDataEntry));
1990 * MarcReplaceMetaDataEntryL
1994 void CMMFAudioController::MarcReplaceMetaDataEntryL(TInt aIndex, const CMMFMetaDataEntry& aNewEntry)
1996 //[ assert the invariant ]
1997 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToReplaceMetaDataEntry));
1999 //[ precondition that we are in the primed state ]
2000 if( State() != EPrimed)
2001 User::Leave(KErrNotReady);
2003 //[ precondition the format exists ]
2005 User::Leave(KErrNotSupported);
2007 //[ replace meta data entry ]
2008 iSinkFormat->ReplaceMetaDataEntryL( aIndex, aNewEntry );
2010 //[ assert the invariant ]
2011 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterReplaceMetaDataEntry));
2016 * MacSetSourceSampleRateL
2017 * @param aSampleRate
2019 void CMMFAudioController::MacSetSourceSampleRateL(TUint aSampleRate)
2021 // [ assert the invariant ]
2022 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceSampleRate));
2024 // [ assert the precondition we are stopped ]
2025 if( State() != EStopped )
2026 User::Leave(KErrNotReady);
2030 {//only applicable to formats
2031 // don't throw an error if the clip already exists with a different sample rate
2032 TInt error = iSourceFormat->SetSampleRate(aSampleRate);
2033 if (error != KErrNone && error != KErrAlreadyExists)
2037 {//during recording, sample rate cannot be set directly on the datasource. It is set via NegotiateL
2038 User::Leave(KErrNotSupported);
2041 // [assert the post condition ]
2042 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceSampleRate));
2047 * MacSetSourceNumChannelsL
2048 * @param aNumChannels
2050 void CMMFAudioController::MacSetSourceNumChannelsL(TUint aNumChannels)
2052 // [ assert the invariant ]
2053 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceNumChannels));
2055 // [assert the precondition that we are stopped ]
2056 if( State() != EStopped )
2057 User::Leave(KErrNotReady);
2060 {//only applicable to formats
2061 // don't throw an error if the clip already exists with a different number of channels
2062 TInt error = iSourceFormat->SetNumChannels(aNumChannels);
2063 if (error != KErrNone && error != KErrAlreadyExists)
2067 {//during recording, channels cannot be set directly on the datasource. It is set via NegotiateL
2068 User::Leave(KErrNotSupported);
2071 // [ assert the invariant ]
2072 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceNumChannels));
2077 * MacSetSourceFormatL
2081 void CMMFAudioController::MacSetSourceFormatL(TUid aFormatUid)
2083 //[ assert the invaraint ]
2084 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceFormat));
2086 // [ precondition that the controller is stopped ]
2087 if( State() != EStopped )
2088 User::Leave( KErrNotReady );
2090 //[ precondition that the data source exists]
2092 User::Leave(KErrNotReady);
2094 //[ precondition that we need a format ]
2095 if( !SourceFormatRequired( *iDataSource ) )
2096 User::Leave(KErrNotSupported); //cant set source format if source isn't a clip
2098 //[ if the format exists and the uid of the requested
2099 // format is the same as the existing format then simply
2100 // return otherwise create a new format ]
2101 if( !((iSourceFormat) && ( iSourceFormat->ImplementationUid() == aFormatUid)))
2103 // [ delete the old format regardless ]
2104 delete iSourceFormat;
2105 iSourceFormat = NULL;
2106 iSourceFormat = CMMFFormatDecode::NewL(aFormatUid, iDataSource);
2109 //[ assert the invariant ]
2110 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceFormat));
2112 //[ assert the post condition that a source format has been constructed ]
2113 __ASSERT_ALWAYS( (iSourceFormat != NULL), Panic( EPostConditionViolation ));
2117 * MacSetSinkSampleRateL
2118 * @param aSampleRate
2120 void CMMFAudioController::MacSetSinkSampleRateL(TUint aSampleRate)
2122 //[ assert the invariant ]
2123 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkSampleRate));
2125 // [ assert the precondition that we are stopped ]
2126 if (State() != EStopped )
2127 User::Leave(KErrNotReady);
2130 {//only applicable to formats
2131 // don't throw an error if the clip already exists with a different sample rate
2132 TInt error = iSinkFormat->SetSampleRate(aSampleRate);
2133 if (error != KErrNone && error != KErrAlreadyExists)
2137 {//during playing, sample rate cannot be set directly on the datasink. It is set via NegotiateL
2138 User::Leave(KErrNotSupported);
2141 //[ assert the invariant ]
2142 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkSampleRate));
2146 * MacSetSinkNumChannelsL
2147 * @param aNumChannels
2150 void CMMFAudioController::MacSetSinkNumChannelsL(TUint aNumChannels)
2152 //[ assert the invariant ]
2153 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkNumChannels));
2155 // [ assert the precondition that we are stopped ]
2156 if (State() != EStopped )
2157 User::Leave(KErrNotReady);
2160 {//only applicable to formats
2161 // don't throw an error if the clip already exists with a different number of channels
2162 TInt error = iSinkFormat->SetNumChannels(aNumChannels);
2163 if (error != KErrNone && error != KErrAlreadyExists)
2167 {//during playing, channels cannot be set directly on the datasink. It is set via NegotiateL
2168 User::Leave(KErrNotSupported);
2171 // [assert the invariant ]
2172 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkNumChannels));
2181 void CMMFAudioController::MacSetSinkFormatL(TUid aFormatUid)
2183 //[ assert the invariant ]
2184 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkFormat));
2186 // [ precondition that the controller is stopped ]
2187 if( State() != EStopped )
2188 User::Leave( KErrNotReady );
2190 //[ precondition that the data sink exists]
2192 User::Leave(KErrNotReady);
2194 //[ precondition that we need a format ]
2195 if (!SinkFormatRequired( *iDataSink))
2196 User::Leave(KErrNotSupported);
2198 //[ if the format exists and the uid of the requested
2199 // format is the same as the existing format then simply
2201 if( !((iSinkFormat) && ( iSinkFormat->ImplementationUid() == aFormatUid)))
2203 // [ delete the old format regardless ]
2206 iSinkFormat = CMMFFormatEncode::NewL(aFormatUid, iDataSink);
2209 //[ assert the invariant ]
2210 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkFormat));
2212 //[ assert the post condition that a sink format has been constructed ]
2213 __ASSERT_ALWAYS( (iSinkFormat != NULL), Panic( EPostConditionViolation ));
2219 * @param aSourceDataType
2220 * @param aSinkDataType
2223 void CMMFAudioController::MacSetCodecL(TFourCC aSourceDataType, TFourCC aSinkDataType)
2225 //[ assert the invariant ]
2226 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetCodec));
2228 //[ assert the precondition ]
2229 if(State() != EStopped)
2230 User::Leave(KErrNotReady);
2232 //pre condition that we have a source format or sink format
2233 if (!iSourceFormat && !iSinkFormat)
2235 User::Leave(KErrNotSupported);
2237 //don't set codec directly -just set source & sink fourCC codes
2239 TInt error(KErrNone);
2240 if ((iSinkFormat)&&(aSinkDataType != KMMFFourCCCodeNULL))
2242 error = iSinkFormat->SetSinkDataTypeCode(aSinkDataType,iMediaId);
2244 if ((iSourceFormat)&&(!error)&&(aSourceDataType != KMMFFourCCCodeNULL))
2246 error = iSourceFormat->SetSourceDataTypeCode(aSourceDataType,iMediaId);
2249 //[ leave if we are not ready or there was an error ]
2250 User::LeaveIfError(error);
2252 //[ assert the invariant ]
2253 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSetCodec));
2257 * MacSetSourceBitRateL
2259 * Sets the source bit rate
2262 void CMMFAudioController::MacSetSourceBitRateL(TUint aBitRate)
2264 //[ assert the invariant ]
2265 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetSourceBitRate));
2267 //[ assert the precondition ]
2268 if(State() != EStopped)
2269 User::Leave(KErrNotReady);
2271 //[ pre condition that we have a source format]
2273 User::Leave(KErrNotSupported);
2275 //only applicable to formats
2276 User::LeaveIfError(iSourceFormat->SetBitRate(aBitRate));
2278 //[ assert the set bit rate is the bit rate ]
2279 __ASSERT_ALWAYS( (aBitRate == iSourceFormat->BitRate()), Panic( EPostConditionViolation ));
2281 //[ assert the invariant ]
2282 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceBitRate));
2288 * MacSetSourceDataTypeL
2292 void CMMFAudioController::MacSetSourceDataTypeL(TFourCC aDataType)
2294 //pre condition we have a source format
2297 User::Leave(KErrNotSupported);
2300 MacSetCodecL(aDataType, KMMFFourCCCodeNULL);
2305 * MacSetSinkBitRateL
2309 void CMMFAudioController::MacSetSinkBitRateL(TUint aRate)
2311 //[ assert the invariant ]
2312 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkBitRate));
2314 // [ assert we are stopped ]
2315 if( State() != EStopped)
2316 User::Leave( KErrNotReady );
2318 //[ pre condition we have a sink format ]
2320 User::Leave(KErrNotSupported);
2322 //only applicable to formats
2323 User::LeaveIfError(iSinkFormat->SetBitRate(aRate));
2325 //[ assert the set bit rate is the bit rate ]
2326 __ASSERT_ALWAYS( (aRate == iSinkFormat->BitRate()), Panic( ESetRateIsNotSameAsBitRate));
2328 //[ assert the invariant ]
2329 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkBitRate));
2334 * MacSetSinkDataTypeL
2338 void CMMFAudioController::MacSetSinkDataTypeL(TFourCC aDataType)
2340 //precondition is that we have a sink format
2343 User::Leave(KErrNotSupported);
2346 MacSetCodecL(KMMFFourCCCodeNULL, aDataType);
2351 * MacGetSourceSampleRateL
2355 void CMMFAudioController::MacGetSourceSampleRateL(TUint& aRate)
2357 //[ assert the invariant ]
2358 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceSampleRate));
2360 //precondition is that we have a source format
2363 User::Leave(KErrNotSupported);
2366 aRate = iSourceFormat->SampleRate();
2368 //[ assert the invariant ]
2369 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceSampleRate));
2374 * MacGetSourceBitRateL
2378 void CMMFAudioController::MacGetSourceBitRateL(TUint& aRate)
2380 //[ assert the invariant ]
2381 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceBitRate));
2383 // Can only query formats for bit rate - devsound doesn't do bit rates.
2385 User::Leave(KErrNotSupported);
2387 aRate = iSourceFormat->BitRate();
2389 //[ assert the invariant ]
2390 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceBitRate));
2396 * MacGetSourceNumChannelsL
2400 void CMMFAudioController::MacGetSourceNumChannelsL(TUint& aNumChannels)
2402 //[ assert the invariant ]
2403 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceNumChannels));
2405 //precondition is that we have a source format
2408 User::Leave(KErrNotSupported);
2411 aNumChannels = iSourceFormat->NumChannels();
2413 //[ assert the invariant ]
2414 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceNumChannels));
2420 * MacGetSourceFormatL
2423 void CMMFAudioController::MacGetSourceFormatL(TUid& aFormat)
2425 //[ assert the invariant ]
2426 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceFormat));
2428 //[ precondition we have a format ]
2430 User::Leave(KErrNotSupported);
2432 // [ get the source format uid ]
2433 aFormat = iSourceFormat->ImplementationUid();
2435 //[ assert the invariant ]
2436 __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceFormat));
2442 * MacGetSourceDataTypeL
2446 void CMMFAudioController::MacGetSourceDataTypeL(TFourCC& aDataType)
2448 //precondition is that we have a source format
2451 User::Leave(KErrNotSupported);
2454 aDataType = iSourceFormat->SourceDataTypeCode(TMediaId(KUidMediaTypeAudio));
2459 * MacGetSinkSampleRateL
2464 void CMMFAudioController::MacGetSinkSampleRateL(TUint& aRate)
2466 //precondition is that we have a sink format
2469 User::Leave(KErrNotSupported);
2472 aRate = iSinkFormat->SampleRate();
2477 * MacGetSinkBitRateL
2481 void CMMFAudioController::MacGetSinkBitRateL(TUint& aRate)
2484 aRate = iSinkFormat->BitRate();
2486 User::Leave(KErrNotSupported);
2491 * MacGetSinkNumChannelsL
2495 void CMMFAudioController::MacGetSinkNumChannelsL(TUint& aNumChannels)
2497 //precondition is that we have a sink format
2500 User::Leave(KErrNotSupported);
2503 aNumChannels = iSinkFormat->NumChannels();
2512 void CMMFAudioController::MacGetSinkFormatL(TUid& aFormat)
2515 aFormat = iSinkFormat->ImplementationUid();
2517 User::Leave(KErrNotSupported);
2522 * MacGetSinkDataTypeL
2526 void CMMFAudioController::MacGetSinkDataTypeL(TFourCC& aDataType)
2528 //precondition is that we have a sink format
2531 User::Leave(KErrNotSupported);
2534 aDataType = iSinkFormat->SinkDataTypeCode(TMediaId(KUidMediaTypeAudio));
2539 * MacGetSupportedSourceSampleRatesL
2540 * @param "RArray<TUint>&"
2543 void CMMFAudioController::MacGetSupportedSourceSampleRatesL(RArray<TUint>& aSupportedRates)
2545 //precondition is that we have a source format
2548 User::Leave(KErrNotSupported);
2551 aSupportedRates.Reset();
2552 iSourceFormat->GetSupportedSampleRatesL(aSupportedRates);
2557 * MacGetSupportedSourceBitRatesL
2558 * @param "RArray<TUint>&"
2561 void CMMFAudioController::MacGetSupportedSourceBitRatesL(RArray<TUint>& aSupportedRates)
2563 aSupportedRates.Reset();
2565 iSourceFormat->GetSupportedBitRatesL(aSupportedRates);
2567 User::Leave(KErrNotSupported);
2572 * MacGetSupportedSourceNumChannelsL
2573 * @param "RArray<TUint>&"
2576 void CMMFAudioController::MacGetSupportedSourceNumChannelsL(RArray<TUint>& aSupportedChannels)
2578 //precondition is that we have a source format
2581 User::Leave(KErrNotSupported);
2584 aSupportedChannels.Reset();
2585 iSourceFormat->GetSupportedNumChannelsL(aSupportedChannels);
2590 * MacGetSupportedSourceDataTypesL
2591 * @param "RArray<TFourCC>&"
2594 void CMMFAudioController::MacGetSupportedSourceDataTypesL(RArray<TFourCC>& aSupportedDataTypes)
2596 //precondition is that we have a source format
2599 User::Leave(KErrNotSupported);
2602 aSupportedDataTypes.Reset();
2603 iSourceFormat->GetSupportedDataTypesL(TMediaId(KUidMediaTypeAudio), aSupportedDataTypes);
2608 * MacGetSupportedSinkSampleRatesL
2609 * @param "RArray<TUint>& "
2612 void CMMFAudioController::MacGetSupportedSinkSampleRatesL(RArray<TUint>& aSupportedRates)
2614 //precondition is that we have a sink format
2617 User::Leave(KErrNotSupported);
2620 aSupportedRates.Reset();
2621 iSinkFormat->GetSupportedSampleRatesL(aSupportedRates);
2626 * MacGetSupportedSinkBitRatesL
2627 * @param RArray<TUint>&
2630 void CMMFAudioController::MacGetSupportedSinkBitRatesL(RArray<TUint>& aSupportedRates)
2633 iSinkFormat->GetSupportedBitRatesL(aSupportedRates);
2635 User::Leave(KErrNotSupported);
2640 * MacGetSupportedSinkNumChannelsL
2641 * @param RArray<TUint>&
2644 void CMMFAudioController::MacGetSupportedSinkNumChannelsL(RArray<TUint>& aSupportedChannels)
2646 //precondition is that we have a sink format
2649 User::Leave(KErrNotSupported);
2652 aSupportedChannels.Reset();
2653 iSinkFormat->GetSupportedNumChannelsL(aSupportedChannels);
2658 * MacGetSupportedSinkDataTypesL
2659 * @param "RArray<TFourCC>&"
2661 void CMMFAudioController::MacGetSupportedSinkDataTypesL(RArray<TFourCC>& aSupportedDataTypes)
2663 //precondition is that we have a sink format
2666 User::Leave(KErrNotSupported);
2669 aSupportedDataTypes.Reset();
2670 iSinkFormat->GetSupportedDataTypesL(TMediaId(KUidMediaTypeAudio), aSupportedDataTypes);
2675 * ConvertFromDevSoundCapsToSampleRatesL
2676 * @param "const TMMFCapabilities& "
2677 * @param "RArray<TUint>&"
2680 void CMMFAudioController::ConvertFromDevSoundCapsToSampleRatesL(const TMMFCapabilities& aDevSoundCaps, RArray<TUint>& aSampleRates)
2682 if (aDevSoundCaps.iRate & EMMFSampleRate8000Hz)
2683 User::LeaveIfError(aSampleRates.Append(KSampleRate8000Hz));
2684 if (aDevSoundCaps.iRate & EMMFSampleRate11025Hz)
2685 User::LeaveIfError(aSampleRates.Append(KSampleRate11025Hz));
2686 if (aDevSoundCaps.iRate & EMMFSampleRate12000Hz)
2687 User::LeaveIfError(aSampleRates.Append(KSampleRate12000Hz));
2688 if (aDevSoundCaps.iRate & EMMFSampleRate16000Hz)
2689 User::LeaveIfError(aSampleRates.Append(KSampleRate16000Hz));
2690 if (aDevSoundCaps.iRate & EMMFSampleRate22050Hz)
2691 User::LeaveIfError(aSampleRates.Append(KSampleRate22050Hz));
2692 if (aDevSoundCaps.iRate & EMMFSampleRate24000Hz)
2693 User::LeaveIfError(aSampleRates.Append(KSampleRate24000Hz));
2694 if (aDevSoundCaps.iRate & EMMFSampleRate32000Hz)
2695 User::LeaveIfError(aSampleRates.Append(KSampleRate32000Hz));
2696 if (aDevSoundCaps.iRate & EMMFSampleRate44100Hz)
2697 User::LeaveIfError(aSampleRates.Append(KSampleRate44100Hz));
2698 if (aDevSoundCaps.iRate & EMMFSampleRate48000Hz)
2699 User::LeaveIfError(aSampleRates.Append(KSampleRate48000Hz));
2700 if (aDevSoundCaps.iRate & EMMFSampleRate64000Hz)
2701 User::LeaveIfError(aSampleRates.Append(KSampleRate64000Hz));
2702 if (aDevSoundCaps.iRate & EMMFSampleRate88200Hz)
2703 User::LeaveIfError(aSampleRates.Append(KSampleRate88200Hz));
2704 if (aDevSoundCaps.iRate & EMMFSampleRate96000Hz)
2705 User::LeaveIfError(aSampleRates.Append(KSampleRate96000Hz));
2710 * ConvertFromDevSoundCapsToNumChannelsL
2711 * @param "const TMMFCapabilities&"
2712 * @param "RArray<TUint>&"
2715 void CMMFAudioController::ConvertFromDevSoundCapsToNumChannelsL(const TMMFCapabilities& aDevSoundCaps, RArray<TUint>& aNumChannels)
2717 if (aDevSoundCaps.iChannels & EMMFMono)
2718 User::LeaveIfError(aNumChannels.Append(KNumChannelsMono));
2719 if (aDevSoundCaps.iChannels & EMMFStereo)
2720 User::LeaveIfError(aNumChannels.Append(KNumChannelsStereo));
2725 * ConvertFromDevSoundCapsToDataTypesL
2726 * @param "const TMMFCapabilities&"
2727 * @param "TMMFCapabilities& aDevSoundCaps, RArray<TFourCC>&"
2730 void CMMFAudioController::ConvertFromDevSoundCapsToDataTypesL(const TMMFCapabilities& aDevSoundCaps, RArray<TFourCC>& aDataTypes)
2732 if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitPCM)
2733 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM8));
2734 if (aDevSoundCaps.iEncoding & EMMFSoundEncoding16BitPCM)
2735 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM16));
2736 if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitALaw)
2737 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeALAW));
2738 if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitMuLaw)
2739 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeMuLAW));
2744 * ConvertFromSampleRateToDevSoundCapsL
2746 * @param "TMMFCapabilities&"
2749 void CMMFAudioController::ConvertFromSampleRateToDevSoundCapsL(TUint aSampleRate, TMMFCapabilities& aDevSoundCaps)
2751 if (aSampleRate == KSampleRate8000Hz)
2752 aDevSoundCaps.iRate = EMMFSampleRate8000Hz;
2753 else if (aSampleRate == KSampleRate11025Hz)
2754 aDevSoundCaps.iRate = EMMFSampleRate11025Hz;
2755 else if (aSampleRate == KSampleRate12000Hz)
2756 aDevSoundCaps.iRate = EMMFSampleRate12000Hz;
2757 else if (aSampleRate == KSampleRate16000Hz)
2758 aDevSoundCaps.iRate = EMMFSampleRate16000Hz;
2759 else if (aSampleRate == KSampleRate22050Hz)
2760 aDevSoundCaps.iRate = EMMFSampleRate22050Hz;
2761 else if (aSampleRate == KSampleRate24000Hz)
2762 aDevSoundCaps.iRate = EMMFSampleRate24000Hz;
2763 else if (aSampleRate == KSampleRate32000Hz)
2764 aDevSoundCaps.iRate = EMMFSampleRate32000Hz;
2765 else if (aSampleRate == KSampleRate44100Hz)
2766 aDevSoundCaps.iRate = EMMFSampleRate44100Hz;
2767 else if (aSampleRate == KSampleRate48000Hz)
2768 aDevSoundCaps.iRate = EMMFSampleRate48000Hz;
2769 else if (aSampleRate == KSampleRate64000Hz)
2770 aDevSoundCaps.iRate = EMMFSampleRate64000Hz;
2771 else if (aSampleRate == KSampleRate88200Hz)
2772 aDevSoundCaps.iRate = EMMFSampleRate88200Hz;
2773 else if (aSampleRate == KSampleRate96000Hz)
2774 aDevSoundCaps.iRate = EMMFSampleRate96000Hz;
2776 User::Leave(KErrNotSupported);
2781 * ConvertFromNumChannelsToDevSoundCapsL
2783 * @param "TMMFCapabilities&"
2786 void CMMFAudioController::ConvertFromNumChannelsToDevSoundCapsL(TUint aNumChannels, TMMFCapabilities& aDevSoundCaps)
2788 if (aNumChannels == KNumChannelsMono)
2789 aDevSoundCaps.iChannels = EMMFMono;
2790 else if (aNumChannels == KNumChannelsStereo)
2791 aDevSoundCaps.iChannels = EMMFStereo;
2793 User::Leave(KErrNotSupported);
2798 * ConvertFromDataTypeToDevSoundCapsL
2800 * @param "TMMFCapabilities&"
2803 void CMMFAudioController::ConvertFromDataTypeToDevSoundCapsL(TFourCC aDataType, TMMFCapabilities& aDevSoundCaps)
2805 if (aDataType == KMMFFourCCCodePCM8)
2806 aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitPCM;
2807 else if (aDataType == KMMFFourCCCodePCM16)
2808 aDevSoundCaps.iEncoding = EMMFSoundEncoding16BitPCM;
2809 else if (aDataType == KMMFFourCCCodeALAW)
2810 aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitALaw;
2811 else if (aDataType == KMMFFourCCCodeMuLAW)
2812 aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitMuLaw;
2814 User::Leave(KErrNotSupported);
2818 * IsValidStateTransition
2819 * The function validates a state transition from iState to aState
2820 * and returns ETrue if the transition is allowed.
2821 * @internalTechnology
2822 * @param TControllerState
2825 TBool CMMFAudioController::IsValidStateTransition( TControllerState aState ) const
2827 TBool result = ETrue ;
2828 //[ assert the precondition that aState is a valid State ]
2829 __ASSERT_ALWAYS( IsValidState(aState), Panic( EBadArgument ) );
2830 //[ assert the invariant that iState is a valid State ]
2831 __ASSERT_ALWAYS( Invariant(), Panic( EInvalidState ));
2833 // [ check the valid state transitions ]
2834 // the only invalid transition is
2835 // stopped to playing
2836 if( ( iState == EStopped ) && ( aState == EPlaying ))
2841 //[ assert the invariant that iState is a valid State ]
2842 __ASSERT_ALWAYS( Invariant(), Panic( EInvalidState ));
2849 * @internalTechnology
2851 * This function returns whether the invariant is valid
2853 TBool CMMFAudioController::Invariant() const
2855 //[ The invariant is for now defined
2856 // as simply being in the correct state and
2857 // having iDataPath defined ]
2858 return ( iDataPath )&& IsValidState( iState);
2863 * This function sets the state of the controller.
2864 * @internalTechnology
2867 TBool CMMFAudioController::SetState(TControllerState aState)
2869 TBool result = ETrue;
2870 //[ assert the precondition that the state is a valid state ]
2871 __ASSERT_ALWAYS( IsValidState( aState), Panic( EBadArgument ) );
2872 //[ assert the invariant the current state is valid ]
2873 __ASSERT_ALWAYS( Invariant(), Panic( EBadState ) );
2874 //[ only allow valid state transitions ]
2875 if( IsValidStateTransition( aState ) )
2877 //[ valid state transition set the state]
2882 //[ invalid state transition return EFalse ]
2885 // [ assert the invariant on the state ]
2886 __ASSERT_ALWAYS( Invariant(), Panic( EBadState ));
2893 * checks whether a state is a valid
2894 * @internalTechnology
2896 * @param TControllerState
2898 TBool CMMFAudioController::IsValidState( TControllerState aState ) const
2900 TBool result = EFalse;
2901 if(( aState >= EStopped ) && ( aState <= EPlaying ))
2910 * The function State returns the current state of the audio controller
2911 * @internalTechnology
2912 * @returns "TControllerState"
2914 CMMFAudioController::TControllerState CMMFAudioController::State() const
2916 __ASSERT_ALWAYS( Invariant(), Panic( EBadState ) );
2922 * SinkFormatRequired
2925 TBool CMMFAudioController::SinkFormatRequired( MDataSink& aDataSink ) const
2927 return (aDataSink.DataSinkType()==KUidMmfFileSink ||
2928 aDataSink.DataSinkType()==KUidMmfDescriptorSink);
2933 * SourceFormatRequired
2937 TBool CMMFAudioController::SourceFormatRequired(MDataSource& aDataSource) const
2939 return (aDataSource.DataSourceType()==KUidMmfFileSource ||
2940 aDataSource.DataSourceType()==KUidMmfDescriptorSource);
2943 TInt CMMFAudioController::MdcEvaluateIntent(ContentAccess::TIntent aIntent)
2945 if (iDataSource->DataSourceType()==KUidMmfFileSource)
2947 CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
2948 TInt err = file->EvaluateIntent(aIntent);
2953 // Evaluating intent will always succeed on sinks that
2954 // don't support DRM
2960 TInt CMMFAudioController::MdcExecuteIntent(ContentAccess::TIntent aIntent)
2962 if (iDataSource->DataSourceType()==KUidMmfFileSource)
2964 CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
2965 TInt err = file->ExecuteIntent(aIntent);
2970 // Executing intent will always succeed on sinks that
2971 // don't support DRM
2976 TInt CMMFAudioController::MdcDisableAutomaticIntent(TBool aDisableAutoIntent)
2978 iDisableAutoIntent = aDisableAutoIntent;
2983 TInt CMMFAudioController::MdcSetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
2985 if (iDataSource->DataSourceType()==KUidMmfFileSource)
2987 CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
2988 TInt err = file->SetAgentProperty(aProperty, aValue);
2997 void CMMFAudioController::MarnRegisterAsClientL(TUid aEventType,const TDesC8& aNotificationRegistrationData)
2999 //[ assert the invariant ]
3000 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToRegisterAsClient));
3001 //[ precondition that we have a sink]
3004 User::Leave(KErrNotReady);
3006 //[register the notification ]
3007 MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
3008 TInt err = audioOutput->SoundDevice().RegisterAsClient(aEventType, aNotificationRegistrationData);
3009 User::LeaveIfError(err);
3010 iRegisterARN = ETrue;
3011 //[ assert the invariant ]
3012 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterRegisterAsClient));
3015 void CMMFAudioController::MarnCancelRegisterAsClientL(TUid aEventType)
3017 //[ assert the invariant ]
3018 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToCancelRegisterAsClient));
3019 //[ precondition that we have a sink]
3022 User::Leave(KErrNotReady);
3024 //[cancel the notification ]
3025 MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
3026 TInt err = audioOutput->SoundDevice().CancelRegisterAsClient(aEventType);
3027 User::LeaveIfError(err);
3028 iRegisterARN = EFalse;
3029 //[ assert the invariant ]
3030 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterCancelRegisterAsClient));
3033 void CMMFAudioController::MarnGetResourceNotificationDataL(TUid aEventType,TDes8& aNotificationData)
3035 //[ assert the invariant ]
3036 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetResourceNotificationData));
3037 //[ precondition that we have a sink]
3040 User::Leave(KErrNotReady);
3042 //[get the notification data]
3043 MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
3044 TMMFTimeIntervalMicroSecondsPckg pckg;
3045 TInt err = audioOutput->SoundDevice().GetResourceNotificationData(aEventType, pckg);
3046 User::LeaveIfError(err);
3048 // aNotificationData is a package buffer returned as TMMFTimeIntervalMicroSecondsPckg,
3049 // but the contents should be converted to an integer and interpreted as the
3050 // data returned is samples played, but not as a microsecond value.
3051 // As the client expects a position (in microseconds from the beginning
3052 // of the clip) we need to convert the data depending on the sample rate
3053 // Potential issue if using the number of samples played with VBR sampling.
3054 RArray<TUint> array;
3055 CleanupClosePushL(array);
3056 ConvertFromDevSoundCapsToSampleRatesL(audioOutput->SoundDevice().Config(), array);
3057 // Should only ever have 1 entry in the array
3058 ASSERT(array.Count() == 1);
3059 TUint rate = array[0];
3062 // Convert the given number of samples using the sample rate
3063 const TInt KMicroSecsInOneSec = 1000000;
3064 TTimeIntervalMicroSeconds value = pckg();
3065 value = TTimeIntervalMicroSeconds(value.Int64() * KMicroSecsInOneSec / rate);
3070 User::Leave(KErrArgument);
3072 aNotificationData = pckg;
3073 CleanupStack::PopAndDestroy();//array
3075 //[ assert the invariant ]
3076 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetResourceNotificationData));
3079 void CMMFAudioController::MarnWillResumePlayL()
3081 //[ assert the invariant ]
3082 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToResumePlay));
3083 //[ precondition that we have a sink]
3086 User::Leave(KErrNotReady);
3088 //[wait for the client to resume ]
3089 MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
3090 TInt err = audioOutput->SoundDevice().WillResumePlay();
3091 User::LeaveIfError(err);
3092 //[ assert the invariant ]
3093 __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterResumePlay));