sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "MmfAudioController.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: const TUint KSampleRate8000Hz = 8000; sl@0: const TUint KSampleRate11025Hz = 11025; sl@0: const TUint KSampleRate12000Hz = 12000; sl@0: const TUint KSampleRate16000Hz = 16000; sl@0: const TUint KSampleRate22050Hz = 22050; sl@0: const TUint KSampleRate24000Hz = 24000; sl@0: const TUint KSampleRate32000Hz = 32000; sl@0: const TUint KSampleRate44100Hz = 44100; sl@0: const TUint KSampleRate48000Hz = 48000; sl@0: const TUint KSampleRate64000Hz = 64000; sl@0: const TUint KSampleRate88200Hz = 88200; sl@0: const TUint KSampleRate96000Hz = 96000; sl@0: const TUint KNumChannelsMono = 1; sl@0: const TUint KNumChannelsStereo = 2; sl@0: sl@0: /* sl@0: TMmfAudioControllerPanics is an enumeration with the following entries: sl@0: EBadArgument indicates a bad argument sl@0: EBadState indicates a state viaolation sl@0: EBadInvariant indicates an invariant violation sl@0: EBadReset indicates failed reset sl@0: EPostConditionViolation indicates a post condition violation sl@0: */ sl@0: enum TMmfAudioControllerPanics sl@0: { sl@0: EBadArgument, sl@0: EBadState, sl@0: EBadInvariant, sl@0: EBadReset, sl@0: EPostConditionViolation, sl@0: EStateNotConstructed, sl@0: EBadStateToGetDataSource, sl@0: ENoAudioInput, sl@0: EBadStateToGetDataSink, sl@0: ENoAudioOutput, sl@0: EBadStateForPrime, sl@0: ENoDataSource, sl@0: ENoDataSink, sl@0: EStateNotPrimed, sl@0: EBadResetState, sl@0: EBadStateToReset, sl@0: EStateNotReadyToPlay, sl@0: EBadPlayState, sl@0: EBadPauseState, sl@0: EBadStateToPause, sl@0: EBadStateToStop, sl@0: EBadStopState, sl@0: EBadStateToPosition, sl@0: EBadStatePosition, sl@0: EBadStateToSetPosition, sl@0: EBadStateSetPosition, sl@0: EBadStateToDuration, sl@0: EBadStateDuration, sl@0: EBadStateToGetNumberOfMetaDataEntries, sl@0: EBadStateGetNumberOfMetaDataEntries, sl@0: EBadStateToGetMetaDataEntries, sl@0: EBadStateGetMetaDataEntries, sl@0: EMetaEntryIsNull, sl@0: ENotReadyForDataSourceRemoval, sl@0: EBadDataSourceRemoval, sl@0: ENotReadyForDataSinkRemoval, sl@0: EBadDataSinkRemoval, sl@0: ENotReadyForCustomCommand, sl@0: EBadStateAfterNegotiate, sl@0: EBadStateToNegotiate, sl@0: EBadStateToSetPriority, sl@0: EBadPriorityState, sl@0: EBadStateToSendEventToClient, sl@0: EBadStateAfterSendEventToClient, sl@0: EBadStateToSetVolume, sl@0: EBadStateAfterVolumeSet, sl@0: EBadStateToGetMaxVolume, sl@0: EBadStateAfterGetMaxVolume, sl@0: EBadStateToGetVolume, sl@0: EBadStateAfterGetVolume, sl@0: EBadStateToSetVolumeRamp, sl@0: EBadStateAfterSetVolumeRamp, sl@0: EBadStateToSetBalance, sl@0: EBadStateAfterSetBalance, sl@0: EBadStateToGetBalance, sl@0: EBadStateAfterGetBalance, sl@0: EBadStateToSetGain, sl@0: EBadStateAfterGainSet, sl@0: EBadStateToGetMaxGain, sl@0: EBadStateAfterGetMaxGain, sl@0: EBadStateToGetGain, sl@0: EBadStateAfterGetGain, sl@0: EBadStateToGetRecordTimeAvailable, sl@0: EBadStateAfterGetRecordTimeAvailable, sl@0: ENoMemoryToRecord, sl@0: EBadStateToGetMaxFileSize, sl@0: EBadStateAfterGetMaxFileSize, sl@0: EBadStateToCrop, sl@0: EBadStateAfterCrop, sl@0: EBadStateToAddMetaDataEntry, sl@0: EBadStateAfterAddMetaDataEntry, sl@0: EBadStateToRemoveMetaDataEntry, sl@0: EBadStateAfterRemoveMetaDataEntry, sl@0: EBadStateToReplaceMetaDataEntry, sl@0: EBadStateAfterReplaceMetaDataEntry, sl@0: EBadStateToSetSourceSampleRate, sl@0: EBadStateAfterSetSourceSampleRate, sl@0: EBadStateToSetSourceNumChannels, sl@0: EBadStateAfterSetSourceNumChannels, sl@0: EBadStateToSetSourceFormat, sl@0: EBadStateAfterSetSourceFormat, sl@0: EBadStateToSetSinkSampleRate, sl@0: EBadStateAfterSetSinkSampleRate, sl@0: EBadStateToSetSinkNumChannels, sl@0: EBadStateAfterSetSinkNumChannels, sl@0: EBadStateToSetSinkFormat, sl@0: EBadStateAfterSetSinkFormat, sl@0: EBadStateToSetCodec, sl@0: EBadStateAfterSetCodec, sl@0: EBadStateToSetSourceBitRate, sl@0: EBadStateAfterSetSourceBitRate, sl@0: EBadStateToSetSinkBitRate, sl@0: EBadStateAfterSetSinkBitRate, sl@0: ESetRateIsNotSameAsBitRate, sl@0: EBadStateToGetSourceSampleRate, sl@0: EBadStateAfterGetSourceSampleRate, sl@0: EBadStateToGetSourceBitRate, sl@0: EBadStateAfterGetSourceBitRate, sl@0: EBadStateToGetSourceNumChannels, sl@0: EBadStateAfterGetSourceNumChannels, sl@0: EBadStateToGetSourceFormat, sl@0: EBadStateAfterGetSourceFormat, sl@0: EInvalidState, sl@0: EBadStateToRegisterAsClient, sl@0: EBadStateAfterRegisterAsClient, sl@0: EBadStateToCancelRegisterAsClient, sl@0: EBadStateAfterCancelRegisterAsClient, sl@0: EBadStateToGetResourceNotificationData, sl@0: EBadStateAfterGetResourceNotificationData, sl@0: EBadStateToResumePlay, sl@0: EBadStateAfterResumePlay, sl@0: }; sl@0: sl@0: /** sl@0: This method generates a panic sl@0: sl@0: @param aPanicCode sl@0: */ sl@0: void Panic(TInt aPanicCode) sl@0: { sl@0: _LIT(KMMFAudioControllerPanicCategory, "MMFAudioController"); sl@0: User::Panic(KMMFAudioControllerPanicCategory, aPanicCode); sl@0: } sl@0: sl@0: /** sl@0: * Static NewL sl@0: * sl@0: * @return CMMFAudioController* sl@0: */ sl@0: CMMFController* CMMFAudioController::NewL() sl@0: { sl@0: CMMFAudioController* self = new(ELeave) CMMFAudioController; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop( self ); sl@0: return STATIC_CAST( CMMFController*, self ); sl@0: } sl@0: sl@0: /** sl@0: * ConstructL sl@0: * sl@0: */ sl@0: void CMMFAudioController::ConstructL() sl@0: { sl@0: iDataSource = NULL; sl@0: iDataSink = NULL; sl@0: iDataPath = CMMFDataPath2::NewL(iMediaId, *this); sl@0: iSourceFormat = NULL; sl@0: iSinkFormat = NULL; sl@0: iSourceAndSinkAdded = EFalse; sl@0: iStoppingRecording = EFalse; sl@0: sl@0: sl@0: //iMediaId has already been set up sl@0: SetState( EStopped ); sl@0: //iPrioritySettings not initialised because they are held by the controller framework sl@0: sl@0: // Construct custom command parsers sl@0: CMMFAudioPlayDeviceCustomCommandParser* audPlayDevParser = CMMFAudioPlayDeviceCustomCommandParser::NewL(*this); sl@0: CleanupStack::PushL(audPlayDevParser); sl@0: AddCustomCommandParserL(*audPlayDevParser); sl@0: CleanupStack::Pop( audPlayDevParser ); sl@0: sl@0: CMMFAudioRecordDeviceCustomCommandParser* audRecDevParser = CMMFAudioRecordDeviceCustomCommandParser::NewL(*this); sl@0: CleanupStack::PushL(audRecDevParser); sl@0: AddCustomCommandParserL(*audRecDevParser); sl@0: CleanupStack::Pop(audRecDevParser); sl@0: sl@0: CMMFAudioPlayControllerCustomCommandParser* audPlayConParser = CMMFAudioPlayControllerCustomCommandParser::NewL(*this); sl@0: CleanupStack::PushL(audPlayConParser); sl@0: AddCustomCommandParserL(*audPlayConParser); sl@0: CleanupStack::Pop(audPlayConParser); sl@0: sl@0: CMMFAudioRecordControllerCustomCommandParser* audRecConParser = CMMFAudioRecordControllerCustomCommandParser::NewL(*this); sl@0: CleanupStack::PushL(audRecConParser); sl@0: AddCustomCommandParserL(*audRecConParser); sl@0: CleanupStack::Pop(audRecConParser); sl@0: sl@0: CMMFAudioControllerCustomCommandParser* audConParser = CMMFAudioControllerCustomCommandParser::NewL(*this); sl@0: CleanupStack::PushL(audConParser); sl@0: AddCustomCommandParserL(*audConParser); sl@0: CleanupStack::Pop(audConParser); sl@0: sl@0: CMMFDRMCustomCommandParser* drmParser = CMMFDRMCustomCommandParser::NewL(*this); sl@0: CleanupStack::PushL(drmParser); sl@0: AddCustomCommandParserL(*drmParser); sl@0: CleanupStack::Pop(drmParser); sl@0: sl@0: CMMFResourceNotificationCustomCommandParser* NotiParser = CMMFResourceNotificationCustomCommandParser::NewL(*this); sl@0: CleanupStack::PushL(NotiParser); sl@0: AddCustomCommandParserL(*NotiParser); sl@0: CleanupStack::Pop(NotiParser);//audio resource Notification Parser sl@0: sl@0: CMMFAudioPlayControllerSetRepeatsCustomCommandParser* audPlayConSetRepeatsParser = CMMFAudioPlayControllerSetRepeatsCustomCommandParser::NewL(*this); sl@0: CleanupStack::PushL(audPlayConSetRepeatsParser); sl@0: AddCustomCommandParserL(*audPlayConSetRepeatsParser); sl@0: CleanupStack::Pop(audPlayConSetRepeatsParser); sl@0: sl@0: sl@0: // [ assert the invariant now that we are constructed ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EStateNotConstructed)); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * CMMFAudioController sl@0: * sl@0: */ sl@0: sl@0: CMMFAudioController::CMMFAudioController() sl@0: : iMediaId(KUidMediaTypeAudio), sl@0: iDisableAutoIntent(EFalse), sl@0: iState(EStopped) sl@0: { sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * ~CMMFAudioController sl@0: * sl@0: */ sl@0: sl@0: CMMFAudioController::~CMMFAudioController() sl@0: { sl@0: // [ ensure we have logged off the thread ] sl@0: if( iDataPath ) sl@0: { sl@0: iDataPath->ResetL(); // this does not leave sl@0: } sl@0: delete iDataPath; sl@0: delete iSourceFormat; sl@0: delete iSinkFormat; sl@0: delete iStoppingMessage; sl@0: } sl@0: sl@0: /** sl@0: * AddDataSourceL sl@0: * sl@0: * Adds a data source to the controller sl@0: * sl@0: * @param aSource sl@0: * Preconditions: sl@0: * We are stopped sl@0: * Source does not already exist sl@0: * Postconditions: sl@0: * iDataSource != NULL sl@0: * iDataSourceAdded == ETrue sl@0: */ sl@0: void CMMFAudioController::AddDataSourceL(MDataSource& aSource) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetDataSource)); sl@0: sl@0: // [ precondition that the controller is stopped ] sl@0: if( State() != EStopped ) sl@0: User::Leave( KErrNotReady ); sl@0: sl@0: //[ precondition iData source is not already configured ] sl@0: if (iDataSource) sl@0: User::Leave(KErrAlreadyExists); sl@0: sl@0: // Note that this code is not generic for sources sl@0: // It it only checks for file, des clips and audio inputs sl@0: // If a new source type eg a Url Clip then this needs to be added to the supported source Uids sl@0: if ( SourceFormatRequired( aSource) ) sl@0: { sl@0: // Get the format from the Source if possible from no specific supplier sl@0: TRAPD(err, iSourceFormat = CMMFFormatDecode::NewL(&aSource, KNullDesC, iSourceFormatSupportsCustomInterfaces)); sl@0: //[ we want to complete silently for KErrNotSupported sl@0: // because there is a possibility that the client sl@0: // wants to add the data format later, see audio api for sl@0: // a description of this feature] sl@0: if ((err != KErrNotSupported) && (err != KErrNone)) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: } sl@0: else if (aSource.DataSourceType()==KUidMmfAudioInput) sl@0: { sl@0: //[ ensure that the audio input has a pointer to dev sound ] sl@0: CMMFAudioInput* audioInput = STATIC_CAST(CMMFAudioInput*, &aSource); sl@0: __ASSERT_ALWAYS( audioInput, Panic(ENoAudioInput)); sl@0: // [ lets load dev sound ] sl@0: User::LeaveIfError(audioInput->SourceThreadLogon( *this )); sl@0: } sl@0: else sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: //[ its now safe to set the source ] sl@0: iDataSource = &aSource ; sl@0: sl@0: //[ assert the post condition ] sl@0: __ASSERT_ALWAYS(iDataSource, Panic(EMMFAudioControllerPanicDataSourceDoesNotExist)); sl@0: sl@0: iDataSource->SetSourcePrioritySettings(iPrioritySettings); sl@0: } sl@0: sl@0: /** sl@0: * AddDataSinkL sl@0: * sl@0: * Adds a data sink to the controller sl@0: * sl@0: * @param aSink sl@0: * sl@0: */ sl@0: void CMMFAudioController::AddDataSinkL(MDataSink& aSink) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetDataSink)); sl@0: sl@0: // [ precondition that the controller is stopped ] sl@0: if( State() != EStopped ) sl@0: User::Leave( KErrNotReady ); sl@0: sl@0: // [ assert precondition that sink does not exist ] sl@0: if (iDataSink) sl@0: User::Leave(KErrAlreadyExists); sl@0: sl@0: sl@0: // Note that this code is not generic for sinks sl@0: // It it only checks for file,des clips and audio outputs sl@0: // If a new sink type eg a Url Clip then this needs to be added to the supported source Uids sl@0: if ( SinkFormatRequired( aSink ) ) sl@0: {//the sink is a clip sl@0: sl@0: // Get the format from the Sink if possible from no specific supplier sl@0: TRAPD(err, iSinkFormat = CMMFFormatEncode::NewL(&aSink, KNullDesC)); sl@0: //[ we want to complete silently for KErrNotSupported sl@0: // because there is a possibility that the client sl@0: // wants to add the data format later, see audio api for sl@0: // a description of this feature] sl@0: if ((err != KErrNotSupported) && (err != KErrNone)) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: } sl@0: else if (aSink.DataSinkType()==KUidMmfAudioOutput) sl@0: { sl@0: sl@0: //[ ensure that the audio output has a pointer to dev sound ] sl@0: CMMFAudioOutput* audioOutput = STATIC_CAST(CMMFAudioOutput*, &aSink); sl@0: __ASSERT_ALWAYS( audioOutput, Panic(ENoAudioOutput)); sl@0: // [ lets load dev sound ] sl@0: User::LeaveIfError(audioOutput->SinkThreadLogon( *this )); sl@0: if (IsSecureDrmModeL()) sl@0: { sl@0: User::LeaveIfError(audioOutput->SoundDevice().SetClientThreadInfo(ClientThreadIdL())); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: //[ now that we are sure we have not left we can update the sink sl@0: // transactionally ] sl@0: iDataSink = &aSink; sl@0: sl@0: // [ assert post conditions that a sink has been added ] sl@0: __ASSERT_ALWAYS(iDataSink, Panic(EMMFAudioControllerPanicDataSinkDoesNotExist)); sl@0: sl@0: iDataSink->SetSinkPrioritySettings(iPrioritySettings); sl@0: } sl@0: sl@0: /** sl@0: * PrimeL sl@0: * sl@0: * If Prime fails the client should reset the controller sl@0: * because as noted below this code is not transactional. sl@0: * sl@0: */ sl@0: void CMMFAudioController::PrimeL() sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateForPrime)); sl@0: sl@0: //[ assert the precondition ( in a friendly way for this api sl@0: // that we are either stopped or primed already ] sl@0: if(!(( State() == EStopped ) || (State() == EPrimed ))) sl@0: User::Leave( KErrNotReady ); sl@0: sl@0: // [ precondition we have a data source & sink ] sl@0: __ASSERT_ALWAYS( iDataSource, Panic( ENoDataSource)); sl@0: __ASSERT_ALWAYS( iDataSink, Panic( ENoDataSink)); sl@0: sl@0: sl@0: //[ precondition that we need a source format ] sl@0: if ( SourceFormatRequired(*iDataSource) && !(iSourceFormat)) sl@0: User::Leave( KErrNotSupported ); sl@0: sl@0: // [ check the precondition if we need a data sink format ] sl@0: if ( SinkFormatRequired(*iDataSink) && !( iSinkFormat )) sl@0: { sl@0: User::Leave( KErrNotSupported ); sl@0: } sl@0: sl@0: // [ ideally this code should be transaction based and sl@0: // if failure occurs we roll back to the previous state sl@0: // in the code below this is not the case and the controller sl@0: // can be left in an unstable state should any part of prime fail] sl@0: if (iState == EStopped) sl@0: { //datapath propagates prime to sink & source sl@0: sl@0: NegotiateL(); sl@0: sl@0: if (!iSourceAndSinkAdded) sl@0: { sl@0: //add data source and sinks to datapath - Note cant do this in AddDataSource/Sink sl@0: //because the sources and sinks aren't configured at this point sl@0: if (iSourceFormat) sl@0: iDataPath->AddDataSourceL(iSourceFormat); sl@0: else if (iDataSource) sl@0: iDataPath->AddDataSourceL(iDataSource); sl@0: if (iSinkFormat) sl@0: iDataPath->AddDataSinkL(iSinkFormat); sl@0: else if (iDataSink) sl@0: iDataPath->AddDataSinkL(iDataSink); sl@0: iSourceAndSinkAdded = ETrue ; sl@0: } sl@0: sl@0: iDataPath->PrimeL(); sl@0: sl@0: if (iSourceFormat) sl@0: { sl@0: //in case of imaadpcm format set the output block length sl@0: sl@0: TFourCC sourceFourCC = iSourceFormat->SourceDataTypeCode(TMediaId(KUidMediaTypeAudio)); sl@0: if ((sourceFourCC == KMMFFourCCCodeIMAD) && iSourceFormatSupportsCustomInterfaces) sl@0: { sl@0: CMMFFormatDecode2* decode2 = static_cast(iSourceFormat); sl@0: MMMFDecodeCustomInterfaceBlockLength* formatBlockLengthCI = static_cast(decode2->CustomInterface(KUidCustomInterfaceMmfDecodeBlockLength)); sl@0: if (formatBlockLengthCI) sl@0: { sl@0: TInt blockLength = formatBlockLengthCI->FileBlockLength(); sl@0: TInt err = iDataPath->SetBlockLength(blockLength); sl@0: sl@0: if ((err != KErrNone) && (iDataSink)) sl@0: { sl@0: MMMFAudioOutput* audioOutput = static_cast(iDataSink); sl@0: MMMFDevSoundCustomInterfaceFileBlockLength* fileBlockLengthCI = static_cast(audioOutput->SoundDevice().CustomInterface(KUidCustomInterfaceDevSoundFileBlockLength)); sl@0: sl@0: if (fileBlockLengthCI) sl@0: { sl@0: fileBlockLengthCI->SetFileBlockLength(blockLength); sl@0: err = KErrNone; sl@0: } sl@0: } sl@0: User::LeaveIfError(err); sl@0: } sl@0: } sl@0: } sl@0: sl@0: if ((iSinkFormat) && (!iSourceFormat)) sl@0: {//we are recording to a clip so the data path position is the sink sl@0: //need to set datapath position to end of format pos (incase sink clip already exists sl@0: TTimeIntervalMicroSeconds duration = iSinkFormat->Duration(iMediaId); sl@0: if (duration != TTimeIntervalMicroSeconds(0)) sl@0: {//the file already exists and has a duration so set data path position to the end of the file sl@0: iDataPath->SetPositionL(duration); sl@0: } sl@0: } sl@0: //[ it is now safe to make the transition to primed ] sl@0: SetState( EPrimed ); sl@0: } sl@0: else if (State() == EPrimed) sl@0: { //controller is already primed so just pass prime onto DP sl@0: iDataPath->PrimeL(); sl@0: } sl@0: sl@0: if (iDataSource->DataSourceType()==KUidMmfFileSource) sl@0: { sl@0: CMMFFile* file = static_cast(iDataSource); sl@0: // we only support protected files for playback sl@0: if (iDataSink->DataSinkType()!=KUidMmfAudioOutput && file->IsProtectedL()) sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: //[ assert the post condition that we are in the state primed] sl@0: __ASSERT_ALWAYS( SetState( EPrimed ), Panic( EPostConditionViolation )); sl@0: // [ assert the invariant] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EStateNotPrimed ) ); sl@0: } sl@0: sl@0: /** sl@0: * ResetL sl@0: * This method resets the controller sl@0: * sl@0: */ sl@0: void CMMFAudioController::ResetL() sl@0: { sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToReset ) ); sl@0: iIsPreemptionPause = EFalse; sl@0: // Stop recording if it's not stopped, sl@0: if (State() != EStopped) sl@0: { sl@0: iDataPath->Stop(); sl@0: SetState(EStopped); sl@0: } sl@0: iIsPaused = EFalse; sl@0: sl@0: // Remove references to source and sink sl@0: iDataPath->ResetL(); sl@0: sl@0: delete iSourceFormat; iSourceFormat = NULL ; sl@0: delete iSinkFormat; iSinkFormat = NULL ; sl@0: sl@0: //[ ensure loggoff of source and sink ] sl@0: iDataSource = NULL ; sl@0: iDataSink = NULL ; sl@0: iSourceAndSinkAdded = EFalse; sl@0: sl@0: // [ assert the invariant] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadResetState ) ); sl@0: sl@0: // [ assert the post condition sl@0: // state == stopped sl@0: // iDataSource is NULL sl@0: // iSourceFormat is NULL sl@0: // iSinkFormat is NULL ] sl@0: __ASSERT_ALWAYS( ResetPostCondition(), Panic( EBadReset )); sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadState)); sl@0: } sl@0: sl@0: /** sl@0: * ResetPostCondition sl@0: * This function determnines if the reset post condition is valid sl@0: * @internalTechnology sl@0: */ sl@0: TBool CMMFAudioController::ResetPostCondition() const sl@0: { sl@0: sl@0: TBool result = EFalse ; sl@0: if((iSourceFormat == NULL) && sl@0: (iDataSink == NULL) && sl@0: (iDataSource == NULL) && sl@0: (iSinkFormat == NULL) && sl@0: (State() == EStopped)) sl@0: { sl@0: result = ETrue; sl@0: } sl@0: sl@0: return result; sl@0: } sl@0: sl@0: sl@0: /** sl@0: * sl@0: * PlayL sl@0: * sl@0: */ sl@0: void CMMFAudioController::PlayL() sl@0: { sl@0: // [ assert the precondition that the sl@0: // play command is only activated in the primed state] sl@0: if ( State() != EPrimed) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: sl@0: // [ assert the Invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EStateNotReadyToPlay)); sl@0: sl@0: // if the position has already been set to the file's duration or sl@0: // beyond, then don't bother getting the datapath to play - this sl@0: // avoids sending empty buffers to DevSound sl@0: if (iDataSink->DataSinkType() == KUidMmfAudioOutput && sl@0: PositionL() >= DurationL()) sl@0: { sl@0: SendEventToClient(TMMFEvent(KMMFEventCategoryPlaybackComplete, KErrNone)); sl@0: return; sl@0: } sl@0: sl@0: // Execute play intent sl@0: // This must be done after PlayL, as the file might not be open yet sl@0: if(!iIsPreemptionPause) sl@0: { sl@0: if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource ) sl@0: { sl@0: CMMFFile* file = static_cast(iDataSource); sl@0: TInt err = file->ExecuteIntent(iIsPaused? ContentAccess::EContinue : ContentAccess::EPlay); sl@0: if (err != KErrNone) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: } sl@0: } sl@0: //[datapath propogates play to sink & source] sl@0: iDataPath->PlayL(); sl@0: iIsPreemptionPause = EFalse; sl@0: iIsPaused = EFalse; sl@0: SetState( EPlaying ); sl@0: sl@0: //[ assert the post condition we are playing ] sl@0: //No - this assumption is not always true if an error occurs eg OOM sl@0: //the state could be EStopped sl@0: // __ASSERT_ALWAYS( (State() == EPlaying ), Panic( EBadState)); sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadPlayState)); sl@0: } sl@0: sl@0: /** sl@0: * PauseL sl@0: * sl@0: */ sl@0: void CMMFAudioController::PauseL() sl@0: { sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToPause)); sl@0: sl@0: //[ assert the precondition that we are playing ] sl@0: if ( State() != EPlaying) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: if(!iIsPreemptionPause) sl@0: { sl@0: if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource) sl@0: { sl@0: CMMFFile* file = static_cast(iDataSource); sl@0: TInt err = file->ExecuteIntent(ContentAccess::EPause); sl@0: if (err != KErrNone) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: } sl@0: } sl@0: iIsPaused = ETrue; sl@0: //[ datapath propogates pause to sink & source ] sl@0: if(iIsPreemptionPause) sl@0: { sl@0: iDataPath->PreEmptionPause(); sl@0: } sl@0: else sl@0: { sl@0: iDataPath->Pause(); sl@0: } sl@0: SetState(EPrimed); sl@0: sl@0: //[ assert the post condition we are primed ] sl@0: __ASSERT_ALWAYS( (State() == EPrimed ), Panic( EBadState)); sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadPauseState)); sl@0: } sl@0: sl@0: /** sl@0: * StopL sl@0: * sl@0: */ sl@0: void CMMFAudioController::StopL(TMMFMessage& aMessage) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToStop)); sl@0: // [ precondition that we are not already stopped sl@0: // && if we are stopped do nothing. sl@0: //If we are stopping a recording, we need to give the datapath chance to sl@0: //process that data which has already been captured. We therefore stay in the EPlaying sl@0: //state, but use iStoppingRecording to indicate that we are stopping. sl@0: sl@0: if ((State() != EStopped) && !iStoppingRecording) sl@0: { sl@0: if((State() == EPlaying) && (iDataSource->DataSourceType()==KUidMmfAudioInput)) //we are recording sl@0: { sl@0: // datapath is requested to stop recording but process any alreay captured buffers, sl@0: // the pause method is used for this purpose and as such, the data path must sl@0: // determine that it is recording to be able to act accordingly. sl@0: // aMessgae is not completed until datapath advises that it has completed. sl@0: iDataPath->Pause(); sl@0: iStoppingMessage = CMMFMessageHolder::NewL(aMessage); sl@0: iStoppingRecording = ETrue; sl@0: } sl@0: else if(((State() == EPlaying) || iIsPaused) && (iDataSink->DataSinkType()==KUidMmfAudioOutput)) //we are playing sl@0: { sl@0: if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource) sl@0: { sl@0: CMMFFile* file = static_cast(iDataSource); sl@0: file->ExecuteIntent(ContentAccess::EStop); sl@0: } sl@0: // datapath propogates stop to sink & source sl@0: iDataPath->Stop(); sl@0: SetState(EStopped); sl@0: } sl@0: sl@0: else sl@0: { sl@0: // datapath propogates stop to sink & source sl@0: iDataPath->Stop(); sl@0: SetState(EStopped); sl@0: } sl@0: } sl@0: iIsPaused = EFalse; sl@0: iIsPreemptionPause = EFalse; sl@0: //complete message as request is complete. sl@0: if(State() == EStopped && !IsUnderTest()) sl@0: { sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStopState)); sl@0: } sl@0: sl@0: /** sl@0: * PositionL sl@0: * Preconditions: sl@0: * The Controller is in the state EPrimed sl@0: * @return TTimeIntervalMicroSeconds sl@0: * sl@0: */ sl@0: TTimeIntervalMicroSeconds CMMFAudioController::PositionL() const sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToPosition)); sl@0: // [ precondition that we are playing or primed ] sl@0: if( !((State() == EPrimed) || (State() == EPlaying))) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: TTimeIntervalMicroSeconds position = iDataPath->Position(); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStatePosition)); sl@0: sl@0: return position; sl@0: } sl@0: sl@0: /** sl@0: * SetPositionL sl@0: * sl@0: * @param aPosition sl@0: * sl@0: */ sl@0: void CMMFAudioController::SetPositionL(const TTimeIntervalMicroSeconds& aPosition) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetPosition)); sl@0: sl@0: // [ precondition that we are not already stopped ] sl@0: if (iState == EStopped) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ precondition that the position is >= 0 && <= Duration ] sl@0: { sl@0: TTimeIntervalMicroSeconds theDuration(0); sl@0: if (iSourceFormat) sl@0: { //if the source is a clip then the duration always refers to the source - even if the sink is a clip sl@0: theDuration = iSourceFormat->Duration(iMediaId); sl@0: } sl@0: else if (iSinkFormat) sl@0: { //duration of recorded clip sl@0: theDuration = iSinkFormat->Duration(iMediaId); sl@0: } sl@0: TTimeIntervalMicroSeconds theStart(0); sl@0: if( ( aPosition < theStart) || ( aPosition > theDuration) ) sl@0: //[ invalid position before start and after end] sl@0: User::Leave(KErrArgument); sl@0: } sl@0: sl@0: //[ set the position on the data path ] sl@0: sl@0: // if we're already playing, flush all the buffers by calling Stop(), sl@0: // PrimeL() and then PlayL() - otherwise we could be waiting a long time. sl@0: if (iDataSink->DataSinkType() == KUidMmfAudioOutput && iState == EPlaying) sl@0: { sl@0: CMMFAudioOutput* audioOutput = static_cast(iDataSink); sl@0: if(!audioOutput->IsResumeSupported()) sl@0: { sl@0: iDataPath->Stop(); sl@0: SetState(EStopped); sl@0: PrimeL(); sl@0: iDataPath->SetPositionL(aPosition); sl@0: iDataPath->RetainRepeatInfo(); sl@0: PlayL(); sl@0: } sl@0: else sl@0: { sl@0: iDataPath->Pause(); sl@0: // This empty buffers sl@0: User::LeaveIfError(audioOutput->SoundDevice().EmptyBuffers()); sl@0: iDataPath->SetPositionL(aPosition); sl@0: iDataPath->RetainRepeatInfo(); sl@0: // This does a DevSound resume sl@0: iDataPath->PlayL(); sl@0: } sl@0: } sl@0: else sl@0: iDataPath->SetPositionL(aPosition); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateSetPosition)); sl@0: sl@0: // [ post condition not checked ] sl@0: //[ we do not compare the set position with get postion sl@0: // because the interface to do so is poor ] sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * DurationL sl@0: * sl@0: * @returns TTimeIntervalMicroSeconds sl@0: * sl@0: */ sl@0: TTimeIntervalMicroSeconds CMMFAudioController::DurationL() const sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToDuration)); sl@0: sl@0: sl@0: // [ assert we have a format that supports duration ] sl@0: if( !( iSourceFormat || iSinkFormat ) ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ now do the real work of getting the duration ] sl@0: // ------------------------------------------------ sl@0: TTimeIntervalMicroSeconds theDuration(0); sl@0: if (iSourceFormat) sl@0: { //if the source is a clip then the duration always refers to the source - even if the sink is a clip sl@0: theDuration = iSourceFormat->Duration(iMediaId); sl@0: } sl@0: else if (iSinkFormat) sl@0: { //duration of recorded clip sl@0: theDuration = iSinkFormat->Duration(iMediaId); sl@0: } sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateDuration)); sl@0: sl@0: return theDuration; sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * GetNumberOfMetaDataEntriesL sl@0: * sl@0: * @param "TInt" sl@0: * sl@0: */ sl@0: void CMMFAudioController::GetNumberOfMetaDataEntriesL(TInt& aNumberOfEntries ) sl@0: { sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetNumberOfMetaDataEntries)); sl@0: sl@0: //[ precondition that we are in the primed state or stopped ] sl@0: if( !((State() == EPrimed) || ( State() == EStopped))) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: // [ precondition there is a sink format ] sl@0: if (!iDataSink) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: // [ precondition the sink format is an encode format ] sl@0: if ((iDataSink->DataSinkType()!=KUidMmfAudioOutput) && sl@0: (iDataSource->DataSourceType()!= KUidMmfAudioInput) ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: if (iDataSink->DataSinkType()==KUidMmfAudioOutput) sl@0: { sl@0: sl@0: //[ precondition the format exists ] sl@0: if( !iSourceFormat ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ Get the Number of meta data entries from the sink format ] sl@0: iSourceFormat->GetNumberOfMetaDataEntriesL( aNumberOfEntries ); sl@0: } sl@0: else if (iDataSource->DataSourceType()==KUidMmfAudioInput) sl@0: { sl@0: if( !iSinkFormat ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: iSinkFormat->GetNumberOfMetaDataEntriesL( aNumberOfEntries ); sl@0: } sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateGetNumberOfMetaDataEntries)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * GetMetaDataEntryL sl@0: * @param aIndex sl@0: * @returns "CMMFMetaDataEntry*" sl@0: */ sl@0: CMMFMetaDataEntry* CMMFAudioController::GetMetaDataEntryL(TInt aIndex ) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMetaDataEntries)); sl@0: sl@0: //[ precondition that we are in the primed state or stopped ] sl@0: if( !((State() == EPrimed) || ( State() == EStopped))) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: // [ precondition there is a sink format ] sl@0: if (!iDataSink) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: iDataSink->DataSinkType(); sl@0: iDataSource->DataSourceType(); sl@0: sl@0: // [ precondition the sink or source is either an audio output or input ] sl@0: if ((iDataSink->DataSinkType()!= KUidMmfAudioOutput) && sl@0: (iDataSource->DataSourceType()!= KUidMmfAudioInput )) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ Get the meta data entry from the sink format ] sl@0: CMMFMetaDataEntry* theEntry = NULL; sl@0: sl@0: if (iDataSink->DataSinkType()==KUidMmfAudioOutput) sl@0: { sl@0: //[ precondition the format exists ] sl@0: if( !iSourceFormat ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ Get the Number of meta data entries from the sink format ] sl@0: theEntry = iSourceFormat->MetaDataEntryL(aIndex); sl@0: } sl@0: else if (iDataSource->DataSourceType()==KUidMmfAudioInput) sl@0: { sl@0: //[ precondition the format exits ] sl@0: if( !iSinkFormat ) sl@0: User::Leave(KErrNotSupported); sl@0: theEntry = iSinkFormat->MetaDataEntryL(aIndex); sl@0: } sl@0: sl@0: //[ assert the post condition that the entry is not null ] sl@0: __ASSERT_ALWAYS( theEntry, Panic(EMetaEntryIsNull)); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateGetMetaDataEntries)); sl@0: sl@0: return theEntry; sl@0: } sl@0: sl@0: /** sl@0: * RemoveDataSourceL sl@0: * @param aDataSource sl@0: * sl@0: */ sl@0: void CMMFAudioController::RemoveDataSourceL(MDataSource& aDataSource ) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForDataSourceRemoval) ); sl@0: sl@0: //[ precondition is that we have a data source ] sl@0: if( !iDataSource ) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[precondition the data source is the data source we have] sl@0: if( iDataSource != &aDataSource ) sl@0: User::Leave(KErrArgument); sl@0: sl@0: //[ the controller is in the stopped state ] sl@0: if(State() != EStopped) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ remove the data sink from the controller and delete the format] sl@0: if( iSourceAndSinkAdded ) sl@0: { sl@0: __ASSERT_ALWAYS( iDataPath, Panic( EBadState )); sl@0: //[ Remove references to source and sink ] sl@0: iDataPath->ResetL(); sl@0: iSourceAndSinkAdded = EFalse ; sl@0: } sl@0: sl@0: // [ delete the data sink and format ] sl@0: iDataSource = NULL ; sl@0: delete iSourceFormat; sl@0: iSourceFormat = NULL; sl@0: sl@0: // [ assert postcondition we are stopped ] sl@0: __ASSERT_ALWAYS( (State() == EStopped), Panic(EPostConditionViolation) ); sl@0: sl@0: //[ assert postcondition the SourceAndSinkAdded is false ] sl@0: __ASSERT_ALWAYS( !iSourceAndSinkAdded, Panic( EPostConditionViolation )); sl@0: sl@0: //[ assert postcondition the data sinkformat is null ] sl@0: __ASSERT_ALWAYS( (iSourceFormat == NULL ), Panic( EPostConditionViolation )); sl@0: sl@0: //[ assert postcondition the data sink is null ] sl@0: __ASSERT_ALWAYS( (iDataSource == NULL ), Panic( EPostConditionViolation )); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadDataSourceRemoval)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * RemoveDataSinkL sl@0: * sl@0: * @param aDataSink sl@0: * sl@0: */ sl@0: void CMMFAudioController::RemoveDataSinkL(MDataSink& aDataSink ) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForDataSinkRemoval) ); sl@0: sl@0: //[ precondition is that we have a data sink ] sl@0: if( !iDataSink ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[precondition the data sink is the data sink we have] sl@0: if( iDataSink != &aDataSink ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ the controller is in the stopped state ] sl@0: if(State() != EStopped) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ remove the data sink from the controller and delete the format] sl@0: if( iSourceAndSinkAdded ) sl@0: { sl@0: __ASSERT_ALWAYS( iDataPath, Panic( EBadState )); sl@0: //[ Remove references to source and sink ] sl@0: iDataPath->ResetL(); sl@0: iSourceAndSinkAdded = EFalse ; sl@0: } sl@0: sl@0: // [ reset data sink referenece and remove the format ] sl@0: iDataSink = NULL ; sl@0: delete iSinkFormat; sl@0: iSinkFormat = NULL; sl@0: sl@0: // [ assert postcondition we are stopped ] sl@0: __ASSERT_ALWAYS( (State() == EStopped), Panic(EPostConditionViolation) ); sl@0: sl@0: //[ assert postcondition the SourceAndSinkAdded is false ] sl@0: __ASSERT_ALWAYS( !iSourceAndSinkAdded, Panic( EPostConditionViolation )); sl@0: sl@0: //[ assert postcondition the data sinkformat is null ] sl@0: __ASSERT_ALWAYS( (iSinkFormat == NULL ), Panic( EPostConditionViolation )); sl@0: sl@0: //[ assert postcondition the data sink is null ] sl@0: __ASSERT_ALWAYS( (iDataSink == NULL ), Panic( EPostConditionViolation )); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadDataSinkRemoval)); sl@0: } sl@0: sl@0: /** sl@0: * CustomCommand sl@0: * @param aMessage sl@0: */ sl@0: void CMMFAudioController::CustomCommand(TMMFMessage& aMessage) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForCustomCommand)); sl@0: // [ We do not have any custom commands ] sl@0: aMessage.Complete(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: * NegotiateL sl@0: * sl@0: */ sl@0: void CMMFAudioController::NegotiateL() sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToNegotiate)); sl@0: sl@0: //utility function used by custom to negotiate source sink settings after a change sl@0: if ((iSourceFormat)&&(iSinkFormat)) //convert sl@0: { sl@0: iSinkFormat->NegotiateL(*iSourceFormat); sl@0: iSourceFormat->NegotiateSourceL(*iSinkFormat); sl@0: iSinkFormat->NegotiateL(*iSourceFormat); sl@0: sl@0: // check for upsampling attempts sl@0: if (iSinkFormat->SampleRate() > iSourceFormat->SampleRate()) sl@0: { sl@0: // we don't support upsampling sl@0: User::Leave( KErrNotSupported ); sl@0: } sl@0: } sl@0: else if ((iDataSource)&&(iSinkFormat)) //record sl@0: { sl@0: // need two step negotiation for record sl@0: // first try to set the audio input settings to match the required settings for recording sl@0: iDataSource->NegotiateSourceL(*iSinkFormat); sl@0: // now call negotiateL on the sink in order to tell it what the audio input was set to. sl@0: iSinkFormat->NegotiateL(*iDataSource); sl@0: } sl@0: else if ((iSourceFormat)&&(iDataSink)) //play sl@0: { sl@0: iDataSink->NegotiateL(*iSourceFormat); sl@0: } sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterNegotiate)); sl@0: } sl@0: sl@0: /** sl@0: * SetPrioritySettings sl@0: * sl@0: * @param aPrioritySettings sl@0: */ sl@0: void CMMFAudioController::SetPrioritySettings(const TMMFPrioritySettings& aPrioritySettings) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetPriority)); sl@0: sl@0: //[ update the priority settings of the controller] sl@0: iPrioritySettings = aPrioritySettings; sl@0: sl@0: //pass settings on to source and sink sl@0: if (iDataSource) sl@0: { sl@0: iDataSource->SetSourcePrioritySettings(iPrioritySettings); sl@0: } sl@0: if (iDataSink) sl@0: { sl@0: iDataSink->SetSinkPrioritySettings(iPrioritySettings); sl@0: } sl@0: sl@0: // assert the post condition sl@0: //__ASSERT_ALWAYS( (iPrioritySettings == aPrioritySettings), Panic( )); sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadPriorityState)); sl@0: } sl@0: sl@0: /** sl@0: * SendEventToClient sl@0: * sl@0: * @param aEvent sl@0: */ sl@0: TInt CMMFAudioController::SendEventToClient(const TMMFEvent& aEvent) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSendEventToClient)); sl@0: sl@0: TMMFEvent controllerEvent; sl@0: //Were going to stop playing, force event type to be the correct type sl@0: controllerEvent.iEventType = KMMFEventCategoryPlaybackComplete; sl@0: controllerEvent.iErrorCode = aEvent.iErrorCode; sl@0: sl@0: sl@0: sl@0: //If we receive KErrNone from the DataPath, it indicates that it has sl@0: //successfully completed playing/converting/recording. sl@0: if ((aEvent.iEventType == KMMFEventCategoryPlaybackComplete) && sl@0: (aEvent.iErrorCode == KErrNone)) sl@0: { sl@0: if(iStoppingRecording) sl@0: { sl@0: iStoppingRecording = EFalse; sl@0: iDataPath->Stop(); sl@0: SetState( EStopped ); sl@0: sl@0: //complete the clients stop request sl@0: iStoppingMessage->Complete(KErrNone); sl@0: delete iStoppingMessage; iStoppingMessage=NULL; sl@0: sl@0: //we don't want to send an event to the client sl@0: return KErrNone; sl@0: } sl@0: else sl@0: {//datapath has reached end of file so set internal state to primed sl@0: SetState( EPrimed ); sl@0: } sl@0: } sl@0: //DevCR KEVN-7T5EHA sl@0: //If the client has not registered for the ARN, sl@0: //and a pre-emption happens we need to goto the Pause state sl@0: //instead of the Stop state. this should happen only in the case of playback. sl@0: //In case of recoding we goto the stop state. sl@0: else if(!iRegisterARN && sl@0: (aEvent.iErrorCode == KErrAccessDenied || aEvent.iErrorCode == KErrInUse ||aEvent.iErrorCode == KErrDied) sl@0: && (iDataSink->DataSinkType()==KUidMmfAudioOutput)) sl@0: { sl@0: //setting iIsPreemptionPause to true so that PauseL can make differentiate it from normal pause. sl@0: iIsPreemptionPause = ETrue; sl@0: TRAPD(err,PauseL()); sl@0: if(err != KErrNone) sl@0: { sl@0: iDataPath->Stop(); sl@0: SetState( EStopped ); sl@0: iIsPreemptionPause = EFalse; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if ( State()!= EStopped) sl@0: { sl@0: //datapath propogates stop to sink & source sl@0: iDataPath->Stop(); sl@0: SetState( EStopped ); sl@0: sl@0: if(iStoppingRecording) sl@0: {// an error has occurred while we were waiting for recording to stop, sl@0: //must complete clients request sl@0: iStoppingRecording = EFalse; sl@0: iStoppingMessage->Complete(aEvent.iErrorCode); sl@0: delete iStoppingMessage; iStoppingMessage=NULL; sl@0: } sl@0: } sl@0: } sl@0: if(!iIsPreemptionPause) sl@0: { sl@0: //should call ExecuteIntent to tell the DRM agent that playback has stopped sl@0: if (aEvent.iEventType == KMMFEventCategoryPlaybackComplete) sl@0: { sl@0: if ((iDataSink->DataSinkType() == KUidMmfAudioOutput)) sl@0: { sl@0: if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource) sl@0: { sl@0: CMMFFile* file = static_cast(iDataSource); sl@0: file->ExecuteIntent(ContentAccess::EStop); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: //now send event to client... sl@0: TInt result = KErrNone; sl@0: if(aEvent.iEventType == KMMFEventCategoryAudioResourceAvailable) sl@0: { sl@0: result = DoSendEventToClient(aEvent); sl@0: } sl@0: else sl@0: { sl@0: result = DoSendEventToClient(controllerEvent); sl@0: } sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSendEventToClient)); sl@0: sl@0: return result; sl@0: } sl@0: sl@0: sl@0: /** sl@0: * MapdSetVolumeL sl@0: * sl@0: * @param aVolume sl@0: * sl@0: */ sl@0: void CMMFAudioController::MapdSetVolumeL(TInt aVolume) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetVolume)); sl@0: sl@0: // [ precondition is true for state sl@0: // we can set the volume in any state ] sl@0: sl@0: //[ precondition we have a data sink ] sl@0: if (!iDataSink) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: // [ precondition that the data sink is an audio output ] sl@0: // Make sure that iDataSink is an Audio Output sl@0: if (iDataSink->DataSinkType() != KUidMmfAudioOutput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink); sl@0: sl@0: // [ assert the precondition that aVolume is in range ] sl@0: TInt maxVolume = audioOutput->SoundDevice().MaxVolume(); sl@0: if( ( aVolume < 0 ) || ( aVolume > maxVolume )) sl@0: User::Leave(KErrArgument); sl@0: sl@0: //[ set the volume on the device ] sl@0: audioOutput->SoundDevice().SetVolume(aVolume); sl@0: sl@0: //[ assert the post condition volume is equal to a volume] sl@0: TInt soundVolume = 0; sl@0: soundVolume = audioOutput->SoundDevice().Volume(); sl@0: sl@0: __ASSERT_ALWAYS( ( soundVolume == aVolume), Panic(EPostConditionViolation)); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterVolumeSet)); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MapdGetMaxVolumeL sl@0: * sl@0: * @param aMaxVolume sl@0: * sl@0: */ sl@0: void CMMFAudioController::MapdGetMaxVolumeL(TInt& aMaxVolume) sl@0: { sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxVolume)); sl@0: sl@0: //[ we can get max volume in any state ] sl@0: sl@0: // [ precondition we must have a data sink ] sl@0: if (!iDataSink) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ precondition the sink must be an audio output] sl@0: // Make sure that iDataSink is an Audio Output sl@0: if (iDataSink->DataSinkType() != KUidMmfAudioOutput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ get the volume from the device ] sl@0: MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink); sl@0: aMaxVolume = audioOutput->SoundDevice().MaxVolume(); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxVolume)); sl@0: sl@0: } sl@0: sl@0: sl@0: /** sl@0: * sl@0: * MapdGetVolumeL sl@0: * sl@0: * @param aVolume sl@0: * sl@0: */ sl@0: void CMMFAudioController::MapdGetVolumeL(TInt& aVolume) sl@0: { sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetVolume)); sl@0: sl@0: //[ precondition that we have a data sink ] sl@0: if (!iDataSink) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ precondition iDataSink is an Audio Output ] sl@0: if (iDataSink->DataSinkType() != KUidMmfAudioOutput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: // [ get the volume ] sl@0: MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink); sl@0: aVolume = audioOutput->SoundDevice().Volume(); sl@0: sl@0: // [ assert precondition that the volume is in range sl@0: // 0.. aMaxVolume ] sl@0: TInt aMaxVolume = audioOutput->SoundDevice().MaxVolume(); sl@0: __ASSERT_ALWAYS( (aVolume <= aMaxVolume), Panic(EBadState)); sl@0: __ASSERT_ALWAYS( (aVolume >= 0), Panic(EBadState)); sl@0: sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetVolume)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MapdSetVolumeRampL sl@0: * sl@0: * @param aRampDuration sl@0: * sl@0: */ sl@0: void CMMFAudioController::MapdSetVolumeRampL(const TTimeIntervalMicroSeconds& aRampDuration) sl@0: { sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetVolumeRamp)); sl@0: sl@0: //[ precondition that we have a data sink ] sl@0: if (!iDataSink) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: // [ precondition iDataSink is an Audio Output ] sl@0: if (iDataSink->DataSinkType() != KUidMmfAudioOutput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ set the volume ramp ] sl@0: MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink); sl@0: audioOutput->SoundDevice().SetVolumeRamp(aRampDuration); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSetVolumeRamp)); sl@0: sl@0: } sl@0: sl@0: sl@0: /** sl@0: * sl@0: * MapdSetBalanceL sl@0: * sl@0: * @param aBalance sl@0: * sl@0: */ sl@0: void CMMFAudioController::MapdSetBalanceL(TInt aBalance) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetBalance)); sl@0: sl@0: // [ precondition is that we have a data sink ] sl@0: if (!iDataSink) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: // [ precondition is that the data sink is an audio output] sl@0: if (iDataSink->DataSinkType() != KUidMmfAudioOutput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ get the audio output ] sl@0: MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink); sl@0: sl@0: // [ separate out left and right balance ] sl@0: TInt left = 0; sl@0: TInt right = 0; sl@0: CalculateLeftRightBalance( left, right, aBalance ); sl@0: sl@0: //[ set the balance ] sl@0: audioOutput->SoundDevice().SetPlayBalanceL(left, right); sl@0: sl@0: // [assert the post condition that the balance is set correctly] sl@0: TInt rightBalance = 0; sl@0: TInt leftBalance = 0; sl@0: audioOutput->SoundDevice().GetPlayBalanceL(leftBalance, rightBalance); sl@0: sl@0: //[ assert post condition holds] sl@0: TBool postCondition = (( rightBalance == right) && ( leftBalance == left)); sl@0: __ASSERT_ALWAYS( postCondition, Panic( EPostConditionViolation ) ); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetBalance)); sl@0: } sl@0: sl@0: /** sl@0: * CalculateLeftRightBalance sl@0: * @internalTechnology sl@0: * @param aLeft sl@0: * @param aRight sl@0: * @param aBalance sl@0: * Preconditions: sl@0: * !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight) sl@0: * y = m x + c sl@0: * aLeft = m ( aBalance ) + c sl@0: * when aBalance = KMMFBalanceMaxLeft aLeft = 100 sl@0: * when aBalance = KMMFBalanceMaxRight aLeft = 0 sl@0: * 100 = m( KMMFBalanceMaxLeft ) + c sl@0: * 0 = m( KMMFBalanceMaxRight ) + c sl@0: * c = -(KMMFBalanceMaxRight) m sl@0: * 100 = m(KMMFBalanceMaxLeft ) - m(KMMFBalanceMaxRight) sl@0: * m = 100/(KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) sl@0: * c = -(KMMFBalanceMaxRight) * 100 /(KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) sl@0: * aLeft = ( aBalance - KMMFBalanceMaxRight ) * 100 /( KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) sl@0: */ sl@0: void CMMFAudioController::CalculateLeftRightBalance( TInt& aLeft, TInt& aRight, TInt aBalance ) const sl@0: { sl@0: // Check the balance is within limits & modify to min or max values if necessary sl@0: if (aBalance < KMMFBalanceMaxLeft) sl@0: aBalance = KMMFBalanceMaxLeft; sl@0: if (aBalance > KMMFBalanceMaxRight) sl@0: aBalance = KMMFBalanceMaxRight; sl@0: sl@0: //[ Now separate percentage balances out from aBalance ] sl@0: aLeft = (100 * (aBalance-KMMFBalanceMaxRight)) / (KMMFBalanceMaxLeft-KMMFBalanceMaxRight); sl@0: aRight = 100 - aLeft; sl@0: sl@0: //[ assert post condition that left and right are within range ] sl@0: __ASSERT_ALWAYS( ( (aLeft <= 100) && (aLeft >= 0) ), Panic(EPostConditionViolation)); sl@0: __ASSERT_ALWAYS( ( (aRight <= 100) && (aRight >= 0) ), Panic(EPostConditionViolation)); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * MapdGetBalanceL sl@0: * @param aBalance sl@0: * sl@0: */ sl@0: void CMMFAudioController::MapdGetBalanceL(TInt& aBalance) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetBalance)); sl@0: sl@0: //[ precondition that we have a sink] sl@0: if (!iDataSink) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: // [ iDataSink is an Audio Output ] sl@0: if (iDataSink->DataSinkType() != KUidMmfAudioOutput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: // [ get the play balance ] sl@0: MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink); sl@0: TInt left = 50; // arbitrary values sl@0: TInt right = 50; sl@0: audioOutput->SoundDevice().GetPlayBalanceL(left, right); sl@0: CalculateBalance( aBalance, left, right ); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetBalance)); sl@0: } sl@0: sl@0: /** sl@0: * CalculateBalance sl@0: * @param aBalance sl@0: * @param aLeft sl@0: * @param aRight sl@0: * sl@0: * follows a simple straight line transformation sl@0: * y = m x + c sl@0: * m = (KMMFBalanceMaxLeft-KMMFBalanceMaxRight)/ 100 sl@0: * c = KMMFBalanceMaxRight sl@0: * by substitution sl@0: * when aLeft = 0 sl@0: * KMMFBalanceMaxRight = m * 0 + c sl@0: * c = KMMFBalanceMaxRight sl@0: * when aLeft = 100 sl@0: * KMMFBalanceMaxLeft = m * 100 + KMMFBalanceMaxRight sl@0: * m = ( KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) /100 sl@0: */ sl@0: void CMMFAudioController::CalculateBalance( TInt& aBalance, TInt aLeft, TInt aRight ) const sl@0: { sl@0: //[ assert pre conditions ] sl@0: __ASSERT_ALWAYS( (( 0 <= aLeft) && ( 100 >= aLeft)), Panic( EBadArgument) ); sl@0: __ASSERT_ALWAYS( (( 0 <= aRight) && ( 100 >= aRight)), Panic( EBadArgument) ); sl@0: sl@0: if ((aLeft > 0) && (aRight > 0)) sl@0: { sl@0: __ASSERT_ALWAYS( (( aLeft + aRight ) == 100 ), Panic( EBadArgument )); sl@0: aBalance = (aLeft * (KMMFBalanceMaxLeft-KMMFBalanceMaxRight))/100 + KMMFBalanceMaxRight; sl@0: } sl@0: else if ((aLeft == 0) && (aRight == 0)) sl@0: { sl@0: aBalance = 0; sl@0: } sl@0: else if ((aLeft == 0) && (aRight > 0)) sl@0: { sl@0: aBalance = 100; sl@0: } sl@0: else if ((aLeft > 0) && (aRight == 0)) sl@0: { sl@0: aBalance = -100; sl@0: } sl@0: sl@0: //[ assert post condition that aBalance is within limits ] sl@0: __ASSERT_ALWAYS( !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight), Panic(EBadArgument)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MardSetGainL sl@0: * @param aGain sl@0: * sl@0: */ sl@0: void CMMFAudioController::MardSetGainL(TInt aGain) sl@0: { sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetGain)); sl@0: sl@0: //[ precondition we are in the state stopped ] sl@0: if(State() != EStopped) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: // [ assert the precondition that we have a data sink ] sl@0: if (!iDataSource) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ assert the precondition that the data sink is an audio input ] sl@0: if (iDataSource->DataSourceType() != KUidMmfAudioInput) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: // Set gain of sound device sl@0: MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource); sl@0: audioInput->SoundDevice().SetGain(aGain); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGainSet)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MardGetMaxGainL sl@0: * @param aMaxGain sl@0: * sl@0: */ sl@0: void CMMFAudioController::MardGetMaxGainL(TInt& aMaxGain) sl@0: { sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxGain)); sl@0: sl@0: // [ assert the precondition that we have a source ] sl@0: if (!iDataSource) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ assert the precondition that iDataSink is an Audio Input] sl@0: if (iDataSource->DataSourceType() != KUidMmfAudioInput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource); sl@0: aMaxGain = audioInput->SoundDevice().MaxGain(); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxGain)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MardGetGainL sl@0: * @param aGain sl@0: * sl@0: */ sl@0: void CMMFAudioController::MardGetGainL(TInt& aGain) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetGain)); sl@0: sl@0: // [ assert the precondition that we have a sink ] sl@0: if (!iDataSource) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: // [ assert the precondition that we have an audio input sink] sl@0: if (iDataSource->DataSourceType() != KUidMmfAudioInput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource); sl@0: aGain = audioInput->SoundDevice().Gain(); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetGain)); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * sl@0: * MardSetBalanceL sl@0: * @param aBalance sl@0: */ sl@0: void CMMFAudioController::MardSetBalanceL(TInt aBalance) sl@0: { sl@0: // [ assert the invaraiant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetGain)); sl@0: sl@0: // [ precondition is that we have a data source ] sl@0: if (!iDataSource) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: sl@0: // [ precondition is that the balance is in range ] sl@0: // Make sure aBalance is in the range -100 <-> 100 sl@0: if (aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight) sl@0: User::Leave(KErrArgument); sl@0: sl@0: // [ precondition is that the data sink is an audio output] sl@0: if (iDataSource->DataSourceType() != KUidMmfAudioInput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: sl@0: //[ get the audio output ] sl@0: MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource); sl@0: sl@0: // [ separate out left and right balance ] sl@0: TInt left = 0; sl@0: TInt right = 0; sl@0: CalculateLeftRightBalance( left, right, aBalance ); sl@0: sl@0: //[ set the balance ] sl@0: audioInput->SoundDevice().SetRecordBalanceL(left, right); sl@0: sl@0: // [assert the post condition that the balance is set correctly] sl@0: TInt rightBalance = 0; sl@0: TInt leftBalance = 0; sl@0: audioInput->SoundDevice().GetRecordBalanceL(leftBalance, rightBalance); sl@0: sl@0: //[ assert post condition holds] sl@0: TBool postCondition = (( rightBalance == right) && ( leftBalance == left)); sl@0: __ASSERT_ALWAYS( postCondition, Panic( EPostConditionViolation ) ); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGainSet)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MardGetBalanceL sl@0: * @param aBalance sl@0: * sl@0: */ sl@0: void CMMFAudioController::MardGetBalanceL(TInt& aBalance) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetBalance)); sl@0: sl@0: // [ precondition is that we have a data source ] sl@0: if (!iDataSource) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: sl@0: // [ iDataSink is an Audio Output ] sl@0: if (iDataSource->DataSourceType() != KUidMmfAudioInput) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: // [ get the play balance ] sl@0: MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource); sl@0: TInt left = 50; // arbitrary values sl@0: TInt right = 50; sl@0: audioInput->SoundDevice().GetRecordBalanceL(left, right); sl@0: CalculateBalance( aBalance, left, right ); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetBalance)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MapcSetPlaybackWindowL sl@0: * @param aStart sl@0: * @param aEnd sl@0: * sl@0: */ sl@0: void CMMFAudioController::MapcSetPlaybackWindowL(const TTimeIntervalMicroSeconds& aStart, const TTimeIntervalMicroSeconds& aEnd) sl@0: { sl@0: iDataPath->SetPlayWindowL(aStart, aEnd); sl@0: } sl@0: sl@0: /** sl@0: * MapcDeletePlaybackWindowL sl@0: */ sl@0: void CMMFAudioController::MapcDeletePlaybackWindowL() sl@0: { sl@0: iDataPath->ClearPlayWindowL(); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * MapcSetRepeatsL sl@0: * @param aRepeatNumberOfTimes sl@0: * @param aTrailingSilence sl@0: * sl@0: */ sl@0: sl@0: TInt CMMFAudioController::MapcSetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence) sl@0: { sl@0: TInt err = KErrNone; sl@0: if (!iDataSink) sl@0: { sl@0: err = KErrNotReady; sl@0: } sl@0: else if (iDataSink->DataSinkType() != KUidMmfAudioOutput) sl@0: { sl@0: err = KErrNotSupported; sl@0: } sl@0: else sl@0: { sl@0: MMMFAudioOutput* audioOutput = static_cast(iDataSink); sl@0: if(audioOutput->SoundDevice().QueryIgnoresUnderflow()) sl@0: { sl@0: iDataPath->SetRepeats(aRepeatNumberOfTimes,aTrailingSilence); sl@0: iDataPath->SetDrmProperties(iDataSource, &iDisableAutoIntent); sl@0: } sl@0: else sl@0: { sl@0: err = KErrNotSupported; sl@0: } sl@0: } sl@0: return err; sl@0: } sl@0: sl@0: sl@0: /** sl@0: * MapcGetLoadingProgressL sl@0: */ sl@0: void CMMFAudioController::MapcGetLoadingProgressL(TInt& /*aPercentageComplete*/) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * MarcGetRecordTimeAvailableL sl@0: * @param aTime sl@0: * sl@0: */ sl@0: void CMMFAudioController::MarcGetRecordTimeAvailableL(TTimeIntervalMicroSeconds& aTime) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetRecordTimeAvailable)); sl@0: sl@0: //[ assert the precondition ( in a friendly way for this api sl@0: // that we minimally have a data sink ] sl@0: if( !iDataSink ) sl@0: User::Leave( KErrNotReady ); sl@0: sl@0: // Use the FormatEncode to get the bytes per second and the sink (clip) to get the bytes available sl@0: // return the calculated value. sl@0: if ((iDataSink->DataSinkType() != KUidMmfFileSink) && (iDataSink->DataSinkType() != KUidMmfDescriptorSink)) sl@0: User::Leave(KErrNotSupported) ; sl@0: sl@0: // [ max file size ] sl@0: //[ pre condition is that we have a sink ] sl@0: sl@0: // In order to get the record time available we need to take into consideration sl@0: // that there may be a max file size ] sl@0: TInt64 bytesFree = STATIC_CAST(CMMFClip*, iDataSink)->BytesFree() ; sl@0: TInt64 bytesPerSecond = TInt64(0); sl@0: //[ set default time available ] sl@0: aTime = TTimeIntervalMicroSeconds( 0 ) ; // just return zero sl@0: sl@0: if( iSinkFormat ) sl@0: { sl@0: TInt maxFileSize = STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->MaximumClipSize(); sl@0: //[ if maxFileSize > 0 we need to limit the bytes free to this value - size ] sl@0: if( maxFileSize > 0 ) sl@0: { sl@0: // [ strangely the size of data written is a TInt ] sl@0: TInt fileSize = STATIC_CAST(CMMFClip*, iDataSink)->Size(); sl@0: bytesFree = maxFileSize - fileSize; sl@0: // [ note it can occur that the fileSize id greater than the MaxFileSize sl@0: // due to someone setting the max file size on an existing file ] sl@0: if( bytesFree < 0 ) bytesFree = 0; sl@0: __ASSERT_DEBUG( ( bytesFree <= maxFileSize), Panic( ENoMemoryToRecord) ); sl@0: } sl@0: bytesPerSecond = STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->BytesPerSecond() ; sl@0: } sl@0: sl@0: //[ now lets perform the calculation of time available ] sl@0: if ( bytesPerSecond != TInt64(0) ) sl@0: { sl@0: aTime = TTimeIntervalMicroSeconds( bytesFree * KOneSecondInMicroSeconds / bytesPerSecond ) ; sl@0: } sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetRecordTimeAvailable)); sl@0: } sl@0: sl@0: /** sl@0: * MarcSetMaxDurationL sl@0: * @param aMaxDuration sl@0: */ sl@0: void CMMFAudioController::MarcSetMaxDurationL(const TTimeIntervalMicroSeconds& ) sl@0: { sl@0: //[ this method is deprecated and no longer supported ] sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: * MarcSetMaxFileSizeL sl@0: * @param aFileSize sl@0: * @precondition sl@0: * The argument aFileSize must be greater than -1 sl@0: * zero is used as a sentinel value which means that the file sl@0: * can grow without limit sl@0: */ sl@0: void CMMFAudioController::MarcSetMaxFileSizeL(TInt aFileSize ) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxFileSize)); sl@0: sl@0: //[ assert the state is not playing since this opens open sl@0: // nefarious posibilities sl@0: if(State() == EPlaying ) sl@0: User::Leave( KErrNotReady ); sl@0: sl@0: //[ assert we have a sink format ] sl@0: if( !iSinkFormat ) sl@0: User::Leave( KErrNotReady ); sl@0: sl@0: //[ assert file size > -2, as a basic sanity filter sl@0: // 0 is the sentinel value which allows a file to grow sl@0: // as needed.] sl@0: // [We use -1 to reset the value set earlier.] sl@0: if( aFileSize < -1 ) sl@0: { sl@0: User::Leave( KErrArgument ); sl@0: } sl@0: sl@0: //[ pre condition is that we have a sink ] sl@0: STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->SetMaximumClipSizeL( aFileSize ); sl@0: sl@0: // [ assert the post condition ] sl@0: // [since we have no means of querying the value sl@0: // we have to assume all went well for now or we left] sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxFileSize)); sl@0: } sl@0: sl@0: /** sl@0: * MarcCropL sl@0: * @param aToEnd sl@0: */ sl@0: void CMMFAudioController::MarcCropL(TBool aToEnd) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToCrop)); sl@0: sl@0: //[ precondition there is a sink format] sl@0: if (!iSinkFormat) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: iSinkFormat->CropL( PositionL(), aToEnd ); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterCrop)); sl@0: } sl@0: sl@0: /** sl@0: * MarcAddMetaDataEntryL sl@0: * @param aNewEntry sl@0: */ sl@0: void CMMFAudioController::MarcAddMetaDataEntryL(const CMMFMetaDataEntry& aNewEntry ) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToAddMetaDataEntry)); sl@0: sl@0: //[ precondition the format exists ] sl@0: if( !iSinkFormat ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ Add the meta data entry ] sl@0: iSinkFormat->AddMetaDataEntryL( aNewEntry ); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterAddMetaDataEntry)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MarcRemoveMetaDataEntryL sl@0: * @param aIndex sl@0: */ sl@0: void CMMFAudioController::MarcRemoveMetaDataEntryL(TInt aIndex) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToRemoveMetaDataEntry)); sl@0: sl@0: //[ precondition that we are in the primed state ] sl@0: if( State() != EPrimed) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ precondition the format exists ] sl@0: if( !iSinkFormat ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ remove the meta data entry ] sl@0: iSinkFormat->RemoveMetaDataEntry( aIndex ); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterRemoveMetaDataEntry)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MarcReplaceMetaDataEntryL sl@0: * @param aIndex sl@0: * @param aNewEntry sl@0: */ sl@0: void CMMFAudioController::MarcReplaceMetaDataEntryL(TInt aIndex, const CMMFMetaDataEntry& aNewEntry) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToReplaceMetaDataEntry)); sl@0: sl@0: //[ precondition that we are in the primed state ] sl@0: if( State() != EPrimed) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ precondition the format exists ] sl@0: if( !iSinkFormat ) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ replace meta data entry ] sl@0: iSinkFormat->ReplaceMetaDataEntryL( aIndex, aNewEntry ); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterReplaceMetaDataEntry)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MacSetSourceSampleRateL sl@0: * @param aSampleRate sl@0: */ sl@0: void CMMFAudioController::MacSetSourceSampleRateL(TUint aSampleRate) sl@0: { sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceSampleRate)); sl@0: sl@0: // [ assert the precondition we are stopped ] sl@0: if( State() != EStopped ) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: sl@0: if (iSourceFormat) sl@0: {//only applicable to formats sl@0: // don't throw an error if the clip already exists with a different sample rate sl@0: TInt error = iSourceFormat->SetSampleRate(aSampleRate); sl@0: if (error != KErrNone && error != KErrAlreadyExists) sl@0: User::Leave(error); sl@0: } sl@0: else sl@0: {//during recording, sample rate cannot be set directly on the datasource. It is set via NegotiateL sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: // [assert the post condition ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceSampleRate)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MacSetSourceNumChannelsL sl@0: * @param aNumChannels sl@0: */ sl@0: void CMMFAudioController::MacSetSourceNumChannelsL(TUint aNumChannels) sl@0: { sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceNumChannels)); sl@0: sl@0: // [assert the precondition that we are stopped ] sl@0: if( State() != EStopped ) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: if (iSourceFormat) sl@0: {//only applicable to formats sl@0: // don't throw an error if the clip already exists with a different number of channels sl@0: TInt error = iSourceFormat->SetNumChannels(aNumChannels); sl@0: if (error != KErrNone && error != KErrAlreadyExists) sl@0: User::Leave(error); sl@0: } sl@0: else sl@0: {//during recording, channels cannot be set directly on the datasource. It is set via NegotiateL sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: // [ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceNumChannels)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MacSetSourceFormatL sl@0: * @param aFormatUid sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacSetSourceFormatL(TUid aFormatUid) sl@0: { sl@0: //[ assert the invaraint ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceFormat)); sl@0: sl@0: // [ precondition that the controller is stopped ] sl@0: if( State() != EStopped ) sl@0: User::Leave( KErrNotReady ); sl@0: sl@0: //[ precondition that the data source exists] sl@0: if (!iDataSource) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ precondition that we need a format ] sl@0: if( !SourceFormatRequired( *iDataSource ) ) sl@0: User::Leave(KErrNotSupported); //cant set source format if source isn't a clip sl@0: sl@0: //[ if the format exists and the uid of the requested sl@0: // format is the same as the existing format then simply sl@0: // return otherwise create a new format ] sl@0: if( !((iSourceFormat) && ( iSourceFormat->ImplementationUid() == aFormatUid))) sl@0: { sl@0: // [ delete the old format regardless ] sl@0: delete iSourceFormat; sl@0: iSourceFormat = NULL; sl@0: iSourceFormat = CMMFFormatDecode::NewL(aFormatUid, iDataSource); sl@0: } sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceFormat)); sl@0: sl@0: //[ assert the post condition that a source format has been constructed ] sl@0: __ASSERT_ALWAYS( (iSourceFormat != NULL), Panic( EPostConditionViolation )); sl@0: } sl@0: sl@0: /** sl@0: * MacSetSinkSampleRateL sl@0: * @param aSampleRate sl@0: */ sl@0: void CMMFAudioController::MacSetSinkSampleRateL(TUint aSampleRate) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkSampleRate)); sl@0: sl@0: // [ assert the precondition that we are stopped ] sl@0: if (State() != EStopped ) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: if (iSinkFormat) sl@0: {//only applicable to formats sl@0: // don't throw an error if the clip already exists with a different sample rate sl@0: TInt error = iSinkFormat->SetSampleRate(aSampleRate); sl@0: if (error != KErrNone && error != KErrAlreadyExists) sl@0: User::Leave(error); sl@0: } sl@0: else sl@0: {//during playing, sample rate cannot be set directly on the datasink. It is set via NegotiateL sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkSampleRate)); sl@0: } sl@0: sl@0: /** sl@0: * MacSetSinkNumChannelsL sl@0: * @param aNumChannels sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacSetSinkNumChannelsL(TUint aNumChannels) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkNumChannels)); sl@0: sl@0: // [ assert the precondition that we are stopped ] sl@0: if (State() != EStopped ) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: if (iSinkFormat) sl@0: {//only applicable to formats sl@0: // don't throw an error if the clip already exists with a different number of channels sl@0: TInt error = iSinkFormat->SetNumChannels(aNumChannels); sl@0: if (error != KErrNone && error != KErrAlreadyExists) sl@0: User::Leave(error); sl@0: } sl@0: else sl@0: {//during playing, channels cannot be set directly on the datasink. It is set via NegotiateL sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: // [assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkNumChannels)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * MacSetSinkFormatL sl@0: * @param aFormatUid sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacSetSinkFormatL(TUid aFormatUid) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkFormat)); sl@0: sl@0: // [ precondition that the controller is stopped ] sl@0: if( State() != EStopped ) sl@0: User::Leave( KErrNotReady ); sl@0: sl@0: //[ precondition that the data sink exists] sl@0: if (!iDataSink) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ precondition that we need a format ] sl@0: if (!SinkFormatRequired( *iDataSink)) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //[ if the format exists and the uid of the requested sl@0: // format is the same as the existing format then simply sl@0: // return ] sl@0: if( !((iSinkFormat) && ( iSinkFormat->ImplementationUid() == aFormatUid))) sl@0: { sl@0: // [ delete the old format regardless ] sl@0: delete iSinkFormat; sl@0: iSinkFormat = NULL; sl@0: iSinkFormat = CMMFFormatEncode::NewL(aFormatUid, iDataSink); sl@0: } sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkFormat)); sl@0: sl@0: //[ assert the post condition that a sink format has been constructed ] sl@0: __ASSERT_ALWAYS( (iSinkFormat != NULL), Panic( EPostConditionViolation )); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * MacSetCodecL sl@0: * @param aSourceDataType sl@0: * @param aSinkDataType sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacSetCodecL(TFourCC aSourceDataType, TFourCC aSinkDataType) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetCodec)); sl@0: sl@0: //[ assert the precondition ] sl@0: if(State() != EStopped) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //pre condition that we have a source format or sink format sl@0: if (!iSourceFormat && !iSinkFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: //don't set codec directly -just set source & sink fourCC codes sl@0: //[ ] sl@0: TInt error(KErrNone); sl@0: if ((iSinkFormat)&&(aSinkDataType != KMMFFourCCCodeNULL)) sl@0: { sl@0: error = iSinkFormat->SetSinkDataTypeCode(aSinkDataType,iMediaId); sl@0: } sl@0: if ((iSourceFormat)&&(!error)&&(aSourceDataType != KMMFFourCCCodeNULL)) sl@0: { sl@0: error = iSourceFormat->SetSourceDataTypeCode(aSourceDataType,iMediaId); sl@0: } sl@0: sl@0: //[ leave if we are not ready or there was an error ] sl@0: User::LeaveIfError(error); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSetCodec)); sl@0: } sl@0: sl@0: /** sl@0: * MacSetSourceBitRateL sl@0: * @param "TUint" sl@0: * Sets the source bit rate sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacSetSourceBitRateL(TUint aBitRate) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetSourceBitRate)); sl@0: sl@0: //[ assert the precondition ] sl@0: if(State() != EStopped) sl@0: User::Leave(KErrNotReady); sl@0: sl@0: //[ pre condition that we have a source format] sl@0: if (!iSourceFormat) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //only applicable to formats sl@0: User::LeaveIfError(iSourceFormat->SetBitRate(aBitRate)); sl@0: sl@0: //[ assert the set bit rate is the bit rate ] sl@0: __ASSERT_ALWAYS( (aBitRate == iSourceFormat->BitRate()), Panic( EPostConditionViolation )); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceBitRate)); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * sl@0: * MacSetSourceDataTypeL sl@0: * @param "TFourCC" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacSetSourceDataTypeL(TFourCC aDataType) sl@0: { sl@0: //pre condition we have a source format sl@0: if (!iSourceFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: MacSetCodecL(aDataType, KMMFFourCCCodeNULL); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacSetSinkBitRateL sl@0: * @param "TUint" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacSetSinkBitRateL(TUint aRate) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkBitRate)); sl@0: sl@0: // [ assert we are stopped ] sl@0: if( State() != EStopped) sl@0: User::Leave( KErrNotReady ); sl@0: sl@0: //[ pre condition we have a sink format ] sl@0: if (!iSinkFormat) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //only applicable to formats sl@0: User::LeaveIfError(iSinkFormat->SetBitRate(aRate)); sl@0: sl@0: //[ assert the set bit rate is the bit rate ] sl@0: __ASSERT_ALWAYS( (aRate == iSinkFormat->BitRate()), Panic( ESetRateIsNotSameAsBitRate)); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkBitRate)); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacSetSinkDataTypeL sl@0: * @param "TFourCC" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacSetSinkDataTypeL(TFourCC aDataType) sl@0: { sl@0: //precondition is that we have a sink format sl@0: if (!iSinkFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: MacSetCodecL(KMMFFourCCCodeNULL, aDataType); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSourceSampleRateL sl@0: * @param "TUint" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSourceSampleRateL(TUint& aRate) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceSampleRate)); sl@0: sl@0: //precondition is that we have a source format sl@0: if (!iSourceFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aRate = iSourceFormat->SampleRate(); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceSampleRate)); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSourceBitRateL sl@0: * @param "TUint" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSourceBitRateL(TUint& aRate) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceBitRate)); sl@0: sl@0: // Can only query formats for bit rate - devsound doesn't do bit rates. sl@0: if (!iSourceFormat) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: aRate = iSourceFormat->BitRate(); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceBitRate)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSourceNumChannelsL sl@0: * @param "TUint&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSourceNumChannelsL(TUint& aNumChannels) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceNumChannels)); sl@0: sl@0: //precondition is that we have a source format sl@0: if (!iSourceFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aNumChannels = iSourceFormat->NumChannels(); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceNumChannels)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSourceFormatL sl@0: * @param "TUid" sl@0: */ sl@0: void CMMFAudioController::MacGetSourceFormatL(TUid& aFormat) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceFormat)); sl@0: sl@0: //[ precondition we have a format ] sl@0: if (!iSourceFormat) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: // [ get the source format uid ] sl@0: aFormat = iSourceFormat->ImplementationUid(); sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceFormat)); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSourceDataTypeL sl@0: * @param "TFourCC&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSourceDataTypeL(TFourCC& aDataType) sl@0: { sl@0: //precondition is that we have a source format sl@0: if (!iSourceFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aDataType = iSourceFormat->SourceDataTypeCode(TMediaId(KUidMediaTypeAudio)); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSinkSampleRateL sl@0: * @param "TUint&" sl@0: * sl@0: */ sl@0: sl@0: void CMMFAudioController::MacGetSinkSampleRateL(TUint& aRate) sl@0: { sl@0: //precondition is that we have a sink format sl@0: if (!iSinkFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aRate = iSinkFormat->SampleRate(); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSinkBitRateL sl@0: * @param "TUint&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSinkBitRateL(TUint& aRate) sl@0: { sl@0: if (iSinkFormat) sl@0: aRate = iSinkFormat->BitRate(); sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSinkNumChannelsL sl@0: * @param "TUint&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSinkNumChannelsL(TUint& aNumChannels) sl@0: { sl@0: //precondition is that we have a sink format sl@0: if (!iSinkFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aNumChannels = iSinkFormat->NumChannels(); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSinkFormatL sl@0: * @param "TUid&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSinkFormatL(TUid& aFormat) sl@0: { sl@0: if (iSinkFormat) sl@0: aFormat = iSinkFormat->ImplementationUid(); sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSinkDataTypeL sl@0: * @param "TFourCC&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSinkDataTypeL(TFourCC& aDataType) sl@0: { sl@0: //precondition is that we have a sink format sl@0: if (!iSinkFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aDataType = iSinkFormat->SinkDataTypeCode(TMediaId(KUidMediaTypeAudio)); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSupportedSourceSampleRatesL sl@0: * @param "RArray&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSupportedSourceSampleRatesL(RArray& aSupportedRates) sl@0: { sl@0: //precondition is that we have a source format sl@0: if (!iSourceFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aSupportedRates.Reset(); sl@0: iSourceFormat->GetSupportedSampleRatesL(aSupportedRates); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MacGetSupportedSourceBitRatesL sl@0: * @param "RArray&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSupportedSourceBitRatesL(RArray& aSupportedRates) sl@0: { sl@0: aSupportedRates.Reset(); sl@0: if (iSourceFormat) sl@0: iSourceFormat->GetSupportedBitRatesL(aSupportedRates); sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /*** sl@0: * sl@0: * MacGetSupportedSourceNumChannelsL sl@0: * @param "RArray&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSupportedSourceNumChannelsL(RArray& aSupportedChannels) sl@0: { sl@0: //precondition is that we have a source format sl@0: if (!iSourceFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aSupportedChannels.Reset(); sl@0: iSourceFormat->GetSupportedNumChannelsL(aSupportedChannels); sl@0: } sl@0: sl@0: /*** sl@0: * sl@0: * MacGetSupportedSourceDataTypesL sl@0: * @param "RArray&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSupportedSourceDataTypesL(RArray& aSupportedDataTypes) sl@0: { sl@0: //precondition is that we have a source format sl@0: if (!iSourceFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aSupportedDataTypes.Reset(); sl@0: iSourceFormat->GetSupportedDataTypesL(TMediaId(KUidMediaTypeAudio), aSupportedDataTypes); sl@0: } sl@0: sl@0: /*** sl@0: * sl@0: * MacGetSupportedSinkSampleRatesL sl@0: * @param "RArray& " sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSupportedSinkSampleRatesL(RArray& aSupportedRates) sl@0: { sl@0: //precondition is that we have a sink format sl@0: if (!iSinkFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aSupportedRates.Reset(); sl@0: iSinkFormat->GetSupportedSampleRatesL(aSupportedRates); sl@0: } sl@0: sl@0: /*** sl@0: * sl@0: * MacGetSupportedSinkBitRatesL sl@0: * @param RArray& sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSupportedSinkBitRatesL(RArray& aSupportedRates) sl@0: { sl@0: if (iSinkFormat) sl@0: iSinkFormat->GetSupportedBitRatesL(aSupportedRates); sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /*** sl@0: * sl@0: * MacGetSupportedSinkNumChannelsL sl@0: * @param RArray& sl@0: * sl@0: */ sl@0: void CMMFAudioController::MacGetSupportedSinkNumChannelsL(RArray& aSupportedChannels) sl@0: { sl@0: //precondition is that we have a sink format sl@0: if (!iSinkFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aSupportedChannels.Reset(); sl@0: iSinkFormat->GetSupportedNumChannelsL(aSupportedChannels); sl@0: } sl@0: sl@0: /*** sl@0: * sl@0: * MacGetSupportedSinkDataTypesL sl@0: * @param "RArray&" sl@0: */ sl@0: void CMMFAudioController::MacGetSupportedSinkDataTypesL(RArray& aSupportedDataTypes) sl@0: { sl@0: //precondition is that we have a sink format sl@0: if (!iSinkFormat) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: aSupportedDataTypes.Reset(); sl@0: iSinkFormat->GetSupportedDataTypesL(TMediaId(KUidMediaTypeAudio), aSupportedDataTypes); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * ConvertFromDevSoundCapsToSampleRatesL sl@0: * @param "const TMMFCapabilities& " sl@0: * @param "RArray&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::ConvertFromDevSoundCapsToSampleRatesL(const TMMFCapabilities& aDevSoundCaps, RArray& aSampleRates) sl@0: { sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate8000Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate8000Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate11025Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate11025Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate12000Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate12000Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate16000Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate16000Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate22050Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate22050Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate24000Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate24000Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate32000Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate32000Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate44100Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate44100Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate48000Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate48000Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate64000Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate64000Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate88200Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate88200Hz)); sl@0: if (aDevSoundCaps.iRate & EMMFSampleRate96000Hz) sl@0: User::LeaveIfError(aSampleRates.Append(KSampleRate96000Hz)); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * ConvertFromDevSoundCapsToNumChannelsL sl@0: * @param "const TMMFCapabilities&" sl@0: * @param "RArray&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::ConvertFromDevSoundCapsToNumChannelsL(const TMMFCapabilities& aDevSoundCaps, RArray& aNumChannels) sl@0: { sl@0: if (aDevSoundCaps.iChannels & EMMFMono) sl@0: User::LeaveIfError(aNumChannels.Append(KNumChannelsMono)); sl@0: if (aDevSoundCaps.iChannels & EMMFStereo) sl@0: User::LeaveIfError(aNumChannels.Append(KNumChannelsStereo)); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * ConvertFromDevSoundCapsToDataTypesL sl@0: * @param "const TMMFCapabilities&" sl@0: * @param "TMMFCapabilities& aDevSoundCaps, RArray&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::ConvertFromDevSoundCapsToDataTypesL(const TMMFCapabilities& aDevSoundCaps, RArray& aDataTypes) sl@0: { sl@0: if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitPCM) sl@0: User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM8)); sl@0: if (aDevSoundCaps.iEncoding & EMMFSoundEncoding16BitPCM) sl@0: User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM16)); sl@0: if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitALaw) sl@0: User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeALAW)); sl@0: if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitMuLaw) sl@0: User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeMuLAW)); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * ConvertFromSampleRateToDevSoundCapsL sl@0: * @param "TUint" sl@0: * @param "TMMFCapabilities&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::ConvertFromSampleRateToDevSoundCapsL(TUint aSampleRate, TMMFCapabilities& aDevSoundCaps) sl@0: { sl@0: if (aSampleRate == KSampleRate8000Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate8000Hz; sl@0: else if (aSampleRate == KSampleRate11025Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate11025Hz; sl@0: else if (aSampleRate == KSampleRate12000Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate12000Hz; sl@0: else if (aSampleRate == KSampleRate16000Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate16000Hz; sl@0: else if (aSampleRate == KSampleRate22050Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate22050Hz; sl@0: else if (aSampleRate == KSampleRate24000Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate24000Hz; sl@0: else if (aSampleRate == KSampleRate32000Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate32000Hz; sl@0: else if (aSampleRate == KSampleRate44100Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate44100Hz; sl@0: else if (aSampleRate == KSampleRate48000Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate48000Hz; sl@0: else if (aSampleRate == KSampleRate64000Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate64000Hz; sl@0: else if (aSampleRate == KSampleRate88200Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate88200Hz; sl@0: else if (aSampleRate == KSampleRate96000Hz) sl@0: aDevSoundCaps.iRate = EMMFSampleRate96000Hz; sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * ConvertFromNumChannelsToDevSoundCapsL sl@0: * @param "TUint" sl@0: * @param "TMMFCapabilities&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::ConvertFromNumChannelsToDevSoundCapsL(TUint aNumChannels, TMMFCapabilities& aDevSoundCaps) sl@0: { sl@0: if (aNumChannels == KNumChannelsMono) sl@0: aDevSoundCaps.iChannels = EMMFMono; sl@0: else if (aNumChannels == KNumChannelsStereo) sl@0: aDevSoundCaps.iChannels = EMMFStereo; sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * ConvertFromDataTypeToDevSoundCapsL sl@0: * @param "TFourCC" sl@0: * @param "TMMFCapabilities&" sl@0: * sl@0: */ sl@0: void CMMFAudioController::ConvertFromDataTypeToDevSoundCapsL(TFourCC aDataType, TMMFCapabilities& aDevSoundCaps) sl@0: { sl@0: if (aDataType == KMMFFourCCCodePCM8) sl@0: aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitPCM; sl@0: else if (aDataType == KMMFFourCCCodePCM16) sl@0: aDevSoundCaps.iEncoding = EMMFSoundEncoding16BitPCM; sl@0: else if (aDataType == KMMFFourCCCodeALAW) sl@0: aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitALaw; sl@0: else if (aDataType == KMMFFourCCCodeMuLAW) sl@0: aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitMuLaw; sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: * IsValidStateTransition sl@0: * The function validates a state transition from iState to aState sl@0: * and returns ETrue if the transition is allowed. sl@0: * @internalTechnology sl@0: * @param TControllerState sl@0: * @returns "TBool" sl@0: */ sl@0: TBool CMMFAudioController::IsValidStateTransition( TControllerState aState ) const sl@0: { sl@0: TBool result = ETrue ; sl@0: //[ assert the precondition that aState is a valid State ] sl@0: __ASSERT_ALWAYS( IsValidState(aState), Panic( EBadArgument ) ); sl@0: //[ assert the invariant that iState is a valid State ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EInvalidState )); sl@0: sl@0: // [ check the valid state transitions ] sl@0: // the only invalid transition is sl@0: // stopped to playing sl@0: if( ( iState == EStopped ) && ( aState == EPlaying )) sl@0: { sl@0: result = EFalse ; sl@0: } sl@0: sl@0: //[ assert the invariant that iState is a valid State ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EInvalidState )); sl@0: sl@0: return result ; sl@0: } sl@0: sl@0: /* sl@0: * Invariant sl@0: * @internalTechnology sl@0: * @returns "TBool" sl@0: * This function returns whether the invariant is valid sl@0: */ sl@0: TBool CMMFAudioController::Invariant() const sl@0: { sl@0: //[ The invariant is for now defined sl@0: // as simply being in the correct state and sl@0: // having iDataPath defined ] sl@0: return ( iDataPath )&& IsValidState( iState); sl@0: } sl@0: sl@0: /* sl@0: * SetState sl@0: * This function sets the state of the controller. sl@0: * @internalTechnology sl@0: * @returns "TBool" sl@0: */ sl@0: TBool CMMFAudioController::SetState(TControllerState aState) sl@0: { sl@0: TBool result = ETrue; sl@0: //[ assert the precondition that the state is a valid state ] sl@0: __ASSERT_ALWAYS( IsValidState( aState), Panic( EBadArgument ) ); sl@0: //[ assert the invariant the current state is valid ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadState ) ); sl@0: //[ only allow valid state transitions ] sl@0: if( IsValidStateTransition( aState ) ) sl@0: { sl@0: //[ valid state transition set the state] sl@0: iState = aState ; sl@0: } sl@0: else sl@0: { sl@0: //[ invalid state transition return EFalse ] sl@0: result = EFalse; sl@0: } sl@0: // [ assert the invariant on the state ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadState )); sl@0: sl@0: return result ; sl@0: } sl@0: sl@0: /* sl@0: * IsValidState sl@0: * checks whether a state is a valid sl@0: * @internalTechnology sl@0: * @returns "TBool" sl@0: * @param TControllerState sl@0: */ sl@0: TBool CMMFAudioController::IsValidState( TControllerState aState ) const sl@0: { sl@0: TBool result = EFalse; sl@0: if(( aState >= EStopped ) && ( aState <= EPlaying )) sl@0: { sl@0: result = ETrue; sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: /** sl@0: * State sl@0: * The function State returns the current state of the audio controller sl@0: * @internalTechnology sl@0: * @returns "TControllerState" sl@0: */ sl@0: CMMFAudioController::TControllerState CMMFAudioController::State() const sl@0: { sl@0: __ASSERT_ALWAYS( Invariant(), Panic( EBadState ) ); sl@0: return iState; sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * SinkFormatRequired sl@0: * sl@0: */ sl@0: TBool CMMFAudioController::SinkFormatRequired( MDataSink& aDataSink ) const sl@0: { sl@0: return (aDataSink.DataSinkType()==KUidMmfFileSink || sl@0: aDataSink.DataSinkType()==KUidMmfDescriptorSink); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * SourceFormatRequired sl@0: * sl@0: */ sl@0: sl@0: TBool CMMFAudioController::SourceFormatRequired(MDataSource& aDataSource) const sl@0: { sl@0: return (aDataSource.DataSourceType()==KUidMmfFileSource || sl@0: aDataSource.DataSourceType()==KUidMmfDescriptorSource); sl@0: } sl@0: sl@0: TInt CMMFAudioController::MdcEvaluateIntent(ContentAccess::TIntent aIntent) sl@0: { sl@0: if (iDataSource->DataSourceType()==KUidMmfFileSource) sl@0: { sl@0: CMMFFile* file = static_cast(iDataSource); sl@0: TInt err = file->EvaluateIntent(aIntent); sl@0: return err; sl@0: } sl@0: else sl@0: { sl@0: // Evaluating intent will always succeed on sinks that sl@0: // don't support DRM sl@0: return KErrNone; sl@0: } sl@0: sl@0: } sl@0: sl@0: TInt CMMFAudioController::MdcExecuteIntent(ContentAccess::TIntent aIntent) sl@0: { sl@0: if (iDataSource->DataSourceType()==KUidMmfFileSource) sl@0: { sl@0: CMMFFile* file = static_cast(iDataSource); sl@0: TInt err = file->ExecuteIntent(aIntent); sl@0: return err; sl@0: } sl@0: else sl@0: { sl@0: // Executing intent will always succeed on sinks that sl@0: // don't support DRM sl@0: return KErrNone; sl@0: } sl@0: } sl@0: sl@0: TInt CMMFAudioController::MdcDisableAutomaticIntent(TBool aDisableAutoIntent) sl@0: { sl@0: iDisableAutoIntent = aDisableAutoIntent; sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt CMMFAudioController::MdcSetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue) sl@0: { sl@0: if (iDataSource->DataSourceType()==KUidMmfFileSource) sl@0: { sl@0: CMMFFile* file = static_cast(iDataSource); sl@0: TInt err = file->SetAgentProperty(aProperty, aValue); sl@0: return err; sl@0: } sl@0: else sl@0: { sl@0: return KErrNone; sl@0: } sl@0: } sl@0: sl@0: void CMMFAudioController::MarnRegisterAsClientL(TUid aEventType,const TDesC8& aNotificationRegistrationData) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToRegisterAsClient)); sl@0: //[ precondition that we have a sink] sl@0: if (!iDataSink) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: //[register the notification ] sl@0: MMMFAudioOutput* audioOutput = static_cast(iDataSink); sl@0: TInt err = audioOutput->SoundDevice().RegisterAsClient(aEventType, aNotificationRegistrationData); sl@0: User::LeaveIfError(err); sl@0: iRegisterARN = ETrue; sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterRegisterAsClient)); sl@0: } sl@0: sl@0: void CMMFAudioController::MarnCancelRegisterAsClientL(TUid aEventType) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToCancelRegisterAsClient)); sl@0: //[ precondition that we have a sink] sl@0: if (!iDataSink) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: //[cancel the notification ] sl@0: MMMFAudioOutput* audioOutput = static_cast(iDataSink); sl@0: TInt err = audioOutput->SoundDevice().CancelRegisterAsClient(aEventType); sl@0: User::LeaveIfError(err); sl@0: iRegisterARN = EFalse; sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterCancelRegisterAsClient)); sl@0: } sl@0: sl@0: void CMMFAudioController::MarnGetResourceNotificationDataL(TUid aEventType,TDes8& aNotificationData) sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetResourceNotificationData)); sl@0: //[ precondition that we have a sink] sl@0: if (!iDataSink) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: //[get the notification data] sl@0: MMMFAudioOutput* audioOutput = static_cast(iDataSink); sl@0: TMMFTimeIntervalMicroSecondsPckg pckg; sl@0: TInt err = audioOutput->SoundDevice().GetResourceNotificationData(aEventType, pckg); sl@0: User::LeaveIfError(err); sl@0: sl@0: // aNotificationData is a package buffer returned as TMMFTimeIntervalMicroSecondsPckg, sl@0: // but the contents should be converted to an integer and interpreted as the sl@0: // data returned is samples played, but not as a microsecond value. sl@0: // As the client expects a position (in microseconds from the beginning sl@0: // of the clip) we need to convert the data depending on the sample rate sl@0: // Potential issue if using the number of samples played with VBR sampling. sl@0: RArray array; sl@0: CleanupClosePushL(array); sl@0: ConvertFromDevSoundCapsToSampleRatesL(audioOutput->SoundDevice().Config(), array); sl@0: // Should only ever have 1 entry in the array sl@0: ASSERT(array.Count() == 1); sl@0: TUint rate = array[0]; sl@0: if (rate) sl@0: { sl@0: // Convert the given number of samples using the sample rate sl@0: const TInt KMicroSecsInOneSec = 1000000; sl@0: TTimeIntervalMicroSeconds value = pckg(); sl@0: value = TTimeIntervalMicroSeconds(value.Int64() * KMicroSecsInOneSec / rate); sl@0: pckg() = value; sl@0: } sl@0: else sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: aNotificationData = pckg; sl@0: CleanupStack::PopAndDestroy();//array sl@0: sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetResourceNotificationData)); sl@0: } sl@0: sl@0: void CMMFAudioController::MarnWillResumePlayL() sl@0: { sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToResumePlay)); sl@0: //[ precondition that we have a sink] sl@0: if (!iDataSink) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: //[wait for the client to resume ] sl@0: MMMFAudioOutput* audioOutput = static_cast(iDataSink); sl@0: TInt err = audioOutput->SoundDevice().WillResumePlay(); sl@0: User::LeaveIfError(err); sl@0: //[ assert the invariant ] sl@0: __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterResumePlay)); sl@0: }