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 <mmf/server/mmfformat.h>
sl@0: #include <mmf/server/mmfclip.h>
sl@0: #include <mdaaudiosampleeditor.h>
sl@0: #include <mmfcontrollerimplementationuids.hrh>
sl@0: #include <mmf/common/mmffourcc.h>
sl@0: #include <mmf/common/mmfpaniccodes.h>
sl@0: #include "MmfAudioController.h"
sl@0: #include <mmf/server/mmffile.h>
sl@0: #include <mmf/server/mmfformatstandardcustominterfaces.h>
sl@0: #include <mmf/server/devsoundstandardcustominterfaces.h>
sl@0: #include <mmf/server/mmfdatapath2.h>
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<CMMFFormatDecode2*>(iSourceFormat);
sl@0: 				MMMFDecodeCustomInterfaceBlockLength* formatBlockLengthCI = static_cast<MMMFDecodeCustomInterfaceBlockLength*>(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<MMMFAudioOutput*>(iDataSink);
sl@0: 						MMMFDevSoundCustomInterfaceFileBlockLength* fileBlockLengthCI = static_cast<MMMFDevSoundCustomInterfaceFileBlockLength*>(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<CMMFFile*>(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<CMMFFile*>(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<CMMFFile*>(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<CMMFFile*>(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<CMMFAudioOutput*>(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<CMMFFile*>(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<MMMFAudioOutput*>(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<TUint>&"
sl@0: * 
sl@0: */
sl@0: void CMMFAudioController::MacGetSupportedSourceSampleRatesL(RArray<TUint>& 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<TUint>&"
sl@0: *
sl@0: */
sl@0: void CMMFAudioController::MacGetSupportedSourceBitRatesL(RArray<TUint>& 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<TUint>&"
sl@0: *
sl@0: */
sl@0: void CMMFAudioController::MacGetSupportedSourceNumChannelsL(RArray<TUint>& 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<TFourCC>&"
sl@0: *
sl@0: */
sl@0: void CMMFAudioController::MacGetSupportedSourceDataTypesL(RArray<TFourCC>& 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<TUint>& "
sl@0: *
sl@0: */
sl@0: void CMMFAudioController::MacGetSupportedSinkSampleRatesL(RArray<TUint>& 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<TUint>& 
sl@0: *
sl@0: */
sl@0: void CMMFAudioController::MacGetSupportedSinkBitRatesL(RArray<TUint>& 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<TUint>&
sl@0: *
sl@0: */
sl@0: void CMMFAudioController::MacGetSupportedSinkNumChannelsL(RArray<TUint>& 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<TFourCC>&"
sl@0: */
sl@0: void CMMFAudioController::MacGetSupportedSinkDataTypesL(RArray<TFourCC>& 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<TUint>&"
sl@0: *
sl@0: */
sl@0: void CMMFAudioController::ConvertFromDevSoundCapsToSampleRatesL(const TMMFCapabilities& aDevSoundCaps, RArray<TUint>& 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<TUint>&"
sl@0: *
sl@0: */
sl@0: void CMMFAudioController::ConvertFromDevSoundCapsToNumChannelsL(const TMMFCapabilities& aDevSoundCaps, RArray<TUint>& 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<TFourCC>&"
sl@0: *
sl@0: */
sl@0: void CMMFAudioController::ConvertFromDevSoundCapsToDataTypesL(const TMMFCapabilities& aDevSoundCaps, RArray<TFourCC>& 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<CMMFFile*>(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<CMMFFile*>(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<CMMFFile*>(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<MMMFAudioOutput*>(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<MMMFAudioOutput*>(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<MMMFAudioOutput*>(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<TUint> 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<MMMFAudioOutput*>(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: 	}