mmlibs/mmfw/src/Plugin/Controller/Audio/MmfAudioController.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 #include <mmf/server/mmfformat.h>
       
    18 #include <mmf/server/mmfclip.h>
       
    19 #include <mdaaudiosampleeditor.h>
       
    20 #include <mmfcontrollerimplementationuids.hrh>
       
    21 #include <mmf/common/mmffourcc.h>
       
    22 #include <mmf/common/mmfpaniccodes.h>
       
    23 #include "MmfAudioController.h"
       
    24 #include <mmf/server/mmffile.h>
       
    25 #include <mmf/server/mmfformatstandardcustominterfaces.h>
       
    26 #include <mmf/server/devsoundstandardcustominterfaces.h>
       
    27 #include <mmf/server/mmfdatapath2.h>
       
    28 
       
    29 const TUint KSampleRate8000Hz = 8000;
       
    30 const TUint KSampleRate11025Hz = 11025;
       
    31 const TUint KSampleRate12000Hz = 12000;
       
    32 const TUint KSampleRate16000Hz = 16000;
       
    33 const TUint KSampleRate22050Hz = 22050;
       
    34 const TUint KSampleRate24000Hz = 24000;
       
    35 const TUint KSampleRate32000Hz = 32000;
       
    36 const TUint KSampleRate44100Hz = 44100;
       
    37 const TUint KSampleRate48000Hz = 48000;
       
    38 const TUint KSampleRate64000Hz = 64000;
       
    39 const TUint KSampleRate88200Hz = 88200;
       
    40 const TUint KSampleRate96000Hz = 96000;
       
    41 const TUint KNumChannelsMono = 1;
       
    42 const TUint KNumChannelsStereo = 2;
       
    43 
       
    44 /*
       
    45  TMmfAudioControllerPanics is an enumeration with the following entries:
       
    46  EBadArgument indicates a bad argument
       
    47  EBadState indicates a state viaolation
       
    48  EBadInvariant indicates an invariant violation
       
    49  EBadReset indicates failed reset
       
    50  EPostConditionViolation indicates a post condition violation
       
    51 */
       
    52 enum TMmfAudioControllerPanics
       
    53 	{
       
    54 	EBadArgument,
       
    55 	EBadState,
       
    56 	EBadInvariant,
       
    57 	EBadReset,
       
    58 	EPostConditionViolation,
       
    59 	EStateNotConstructed,
       
    60 	EBadStateToGetDataSource,
       
    61 	ENoAudioInput,
       
    62 	EBadStateToGetDataSink,
       
    63 	ENoAudioOutput,
       
    64 	EBadStateForPrime,
       
    65 	ENoDataSource,
       
    66 	ENoDataSink,
       
    67 	EStateNotPrimed,
       
    68 	EBadResetState,
       
    69 	EBadStateToReset,
       
    70 	EStateNotReadyToPlay,
       
    71 	EBadPlayState,
       
    72 	EBadPauseState,
       
    73 	EBadStateToPause,
       
    74 	EBadStateToStop,
       
    75 	EBadStopState,
       
    76 	EBadStateToPosition,
       
    77 	EBadStatePosition,
       
    78 	EBadStateToSetPosition,
       
    79 	EBadStateSetPosition,
       
    80 	EBadStateToDuration,
       
    81 	EBadStateDuration,
       
    82 	EBadStateToGetNumberOfMetaDataEntries,
       
    83 	EBadStateGetNumberOfMetaDataEntries,
       
    84 	EBadStateToGetMetaDataEntries,
       
    85 	EBadStateGetMetaDataEntries,
       
    86 	EMetaEntryIsNull,
       
    87 	ENotReadyForDataSourceRemoval,
       
    88 	EBadDataSourceRemoval,
       
    89 	ENotReadyForDataSinkRemoval,
       
    90 	EBadDataSinkRemoval,
       
    91 	ENotReadyForCustomCommand,
       
    92 	EBadStateAfterNegotiate,
       
    93 	EBadStateToNegotiate,
       
    94 	EBadStateToSetPriority,
       
    95 	EBadPriorityState,
       
    96 	EBadStateToSendEventToClient,
       
    97 	EBadStateAfterSendEventToClient,
       
    98 	EBadStateToSetVolume,
       
    99 	EBadStateAfterVolumeSet,
       
   100 	EBadStateToGetMaxVolume,
       
   101 	EBadStateAfterGetMaxVolume,
       
   102 	EBadStateToGetVolume,
       
   103 	EBadStateAfterGetVolume,
       
   104 	EBadStateToSetVolumeRamp,
       
   105 	EBadStateAfterSetVolumeRamp,
       
   106 	EBadStateToSetBalance,
       
   107 	EBadStateAfterSetBalance,
       
   108 	EBadStateToGetBalance,
       
   109 	EBadStateAfterGetBalance,
       
   110 	EBadStateToSetGain,
       
   111 	EBadStateAfterGainSet,
       
   112 	EBadStateToGetMaxGain,
       
   113 	EBadStateAfterGetMaxGain,
       
   114 	EBadStateToGetGain,
       
   115 	EBadStateAfterGetGain,
       
   116 	EBadStateToGetRecordTimeAvailable,
       
   117 	EBadStateAfterGetRecordTimeAvailable,
       
   118 	ENoMemoryToRecord,
       
   119 	EBadStateToGetMaxFileSize,
       
   120 	EBadStateAfterGetMaxFileSize,
       
   121 	EBadStateToCrop,
       
   122 	EBadStateAfterCrop,
       
   123 	EBadStateToAddMetaDataEntry,
       
   124 	EBadStateAfterAddMetaDataEntry,
       
   125 	EBadStateToRemoveMetaDataEntry,
       
   126 	EBadStateAfterRemoveMetaDataEntry,
       
   127 	EBadStateToReplaceMetaDataEntry,
       
   128 	EBadStateAfterReplaceMetaDataEntry,
       
   129 	EBadStateToSetSourceSampleRate,
       
   130 	EBadStateAfterSetSourceSampleRate,
       
   131 	EBadStateToSetSourceNumChannels,
       
   132 	EBadStateAfterSetSourceNumChannels,
       
   133 	EBadStateToSetSourceFormat,
       
   134 	EBadStateAfterSetSourceFormat,
       
   135 	EBadStateToSetSinkSampleRate,
       
   136 	EBadStateAfterSetSinkSampleRate,
       
   137 	EBadStateToSetSinkNumChannels,
       
   138 	EBadStateAfterSetSinkNumChannels,
       
   139 	EBadStateToSetSinkFormat,
       
   140 	EBadStateAfterSetSinkFormat,
       
   141 	EBadStateToSetCodec,
       
   142 	EBadStateAfterSetCodec,
       
   143 	EBadStateToSetSourceBitRate,
       
   144 	EBadStateAfterSetSourceBitRate,
       
   145 	EBadStateToSetSinkBitRate,
       
   146 	EBadStateAfterSetSinkBitRate,
       
   147 	ESetRateIsNotSameAsBitRate,
       
   148 	EBadStateToGetSourceSampleRate,
       
   149 	EBadStateAfterGetSourceSampleRate,
       
   150 	EBadStateToGetSourceBitRate,
       
   151 	EBadStateAfterGetSourceBitRate,
       
   152 	EBadStateToGetSourceNumChannels,
       
   153 	EBadStateAfterGetSourceNumChannels,
       
   154 	EBadStateToGetSourceFormat,
       
   155 	EBadStateAfterGetSourceFormat,
       
   156 	EInvalidState,
       
   157 	EBadStateToRegisterAsClient,
       
   158 	EBadStateAfterRegisterAsClient,
       
   159 	EBadStateToCancelRegisterAsClient,
       
   160 	EBadStateAfterCancelRegisterAsClient,
       
   161 	EBadStateToGetResourceNotificationData,
       
   162 	EBadStateAfterGetResourceNotificationData,
       
   163 	EBadStateToResumePlay,
       
   164 	EBadStateAfterResumePlay,
       
   165 	};
       
   166 
       
   167 /**
       
   168 This method generates a panic
       
   169 
       
   170 @param aPanicCode
       
   171 */
       
   172 void Panic(TInt aPanicCode)
       
   173 	{
       
   174 	_LIT(KMMFAudioControllerPanicCategory, "MMFAudioController");
       
   175 	User::Panic(KMMFAudioControllerPanicCategory, aPanicCode);
       
   176 	}
       
   177 
       
   178 /**
       
   179  * Static NewL
       
   180  *
       
   181  * @return CMMFAudioController*
       
   182  */
       
   183 CMMFController* CMMFAudioController::NewL()
       
   184 	{
       
   185 	CMMFAudioController* self = new(ELeave) CMMFAudioController;
       
   186 	CleanupStack::PushL(self);
       
   187 	self->ConstructL();
       
   188 	CleanupStack::Pop( self );
       
   189 	return STATIC_CAST( CMMFController*, self );
       
   190 	}
       
   191 
       
   192 /**
       
   193 * ConstructL 
       
   194 * 
       
   195 */
       
   196 void CMMFAudioController::ConstructL()
       
   197 	{
       
   198 	iDataSource         = NULL;
       
   199 	iDataSink           = NULL;
       
   200 	iDataPath           = CMMFDataPath2::NewL(iMediaId, *this);
       
   201 	iSourceFormat       = NULL;
       
   202 	iSinkFormat         = NULL;
       
   203 	iSourceAndSinkAdded = EFalse;
       
   204 	iStoppingRecording  = EFalse;
       
   205 
       
   206 
       
   207 	//iMediaId has already been set up 
       
   208 	SetState( EStopped );
       
   209 	//iPrioritySettings  not initialised because they are held by the controller framework
       
   210 
       
   211 	// Construct custom command parsers
       
   212 	CMMFAudioPlayDeviceCustomCommandParser* audPlayDevParser = CMMFAudioPlayDeviceCustomCommandParser::NewL(*this);
       
   213 	CleanupStack::PushL(audPlayDevParser);
       
   214 	AddCustomCommandParserL(*audPlayDevParser);
       
   215 	CleanupStack::Pop( audPlayDevParser );
       
   216 
       
   217 	CMMFAudioRecordDeviceCustomCommandParser* audRecDevParser = CMMFAudioRecordDeviceCustomCommandParser::NewL(*this);
       
   218 	CleanupStack::PushL(audRecDevParser);
       
   219 	AddCustomCommandParserL(*audRecDevParser);
       
   220 	CleanupStack::Pop(audRecDevParser);
       
   221 
       
   222 	CMMFAudioPlayControllerCustomCommandParser* audPlayConParser = CMMFAudioPlayControllerCustomCommandParser::NewL(*this);
       
   223 	CleanupStack::PushL(audPlayConParser);
       
   224 	AddCustomCommandParserL(*audPlayConParser);
       
   225 	CleanupStack::Pop(audPlayConParser);
       
   226 
       
   227 	CMMFAudioRecordControllerCustomCommandParser* audRecConParser = CMMFAudioRecordControllerCustomCommandParser::NewL(*this);
       
   228 	CleanupStack::PushL(audRecConParser);
       
   229 	AddCustomCommandParserL(*audRecConParser);
       
   230 	CleanupStack::Pop(audRecConParser);
       
   231 
       
   232 	CMMFAudioControllerCustomCommandParser* audConParser = CMMFAudioControllerCustomCommandParser::NewL(*this);
       
   233 	CleanupStack::PushL(audConParser);
       
   234 	AddCustomCommandParserL(*audConParser);
       
   235 	CleanupStack::Pop(audConParser);
       
   236 	
       
   237 	CMMFDRMCustomCommandParser* drmParser = CMMFDRMCustomCommandParser::NewL(*this);
       
   238 	CleanupStack::PushL(drmParser);
       
   239 	AddCustomCommandParserL(*drmParser);
       
   240 	CleanupStack::Pop(drmParser);
       
   241 
       
   242 	CMMFResourceNotificationCustomCommandParser* NotiParser = CMMFResourceNotificationCustomCommandParser::NewL(*this);
       
   243 	CleanupStack::PushL(NotiParser);
       
   244 	AddCustomCommandParserL(*NotiParser);
       
   245 	CleanupStack::Pop(NotiParser);//audio resource Notification Parser
       
   246 	
       
   247 	CMMFAudioPlayControllerSetRepeatsCustomCommandParser* audPlayConSetRepeatsParser = CMMFAudioPlayControllerSetRepeatsCustomCommandParser::NewL(*this);
       
   248 	CleanupStack::PushL(audPlayConSetRepeatsParser);
       
   249 	AddCustomCommandParserL(*audPlayConSetRepeatsParser);
       
   250 	CleanupStack::Pop(audPlayConSetRepeatsParser);
       
   251 	
       
   252 
       
   253 	// [ assert the invariant now that we are constructed ]
       
   254 	__ASSERT_ALWAYS( Invariant(), Panic( EStateNotConstructed));
       
   255 	}
       
   256 
       
   257 /**
       
   258 *
       
   259 * CMMFAudioController
       
   260 *
       
   261 */
       
   262 
       
   263 CMMFAudioController::CMMFAudioController() 
       
   264 	: iMediaId(KUidMediaTypeAudio),
       
   265 	  iDisableAutoIntent(EFalse),
       
   266 	  iState(EStopped)
       
   267 	{
       
   268 	}
       
   269 
       
   270 /**
       
   271 *
       
   272 * ~CMMFAudioController
       
   273 *
       
   274 */
       
   275 
       
   276 CMMFAudioController::~CMMFAudioController()
       
   277 	{
       
   278 	// [ ensure we have logged off the thread ]
       
   279 	if( iDataPath ) 	
       
   280 		{
       
   281 		iDataPath->ResetL();	// this does not leave
       
   282 		}
       
   283 	delete iDataPath;
       
   284 	delete iSourceFormat;
       
   285 	delete iSinkFormat;
       
   286 	delete iStoppingMessage;
       
   287 	}
       
   288 
       
   289 /**
       
   290  *  AddDataSourceL
       
   291  *
       
   292  *	Adds a data source to the controller
       
   293  *
       
   294  *	@param aSource
       
   295  * Preconditions:
       
   296  * We are stopped
       
   297  * Source does not already exist
       
   298  * Postconditions:
       
   299  * iDataSource != NULL
       
   300  * iDataSourceAdded == ETrue
       
   301  */
       
   302 void CMMFAudioController::AddDataSourceL(MDataSource& aSource)
       
   303 	{
       
   304 	//[ assert the invariant ]
       
   305 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetDataSource));
       
   306 
       
   307 	// [ precondition that the controller is stopped ]
       
   308     if( State() != EStopped )
       
   309 		User::Leave( KErrNotReady );
       
   310 	
       
   311 	//[ precondition iData source is not already configured ]
       
   312 	if (iDataSource)
       
   313 		User::Leave(KErrAlreadyExists);
       
   314 
       
   315 	// Note that this code is not generic for sources
       
   316 	// It it only checks for file, des clips and audio inputs
       
   317 	// If a new source type eg a Url Clip then this needs to be added to the supported source Uids
       
   318 	if ( SourceFormatRequired( aSource) ) 
       
   319 		{
       
   320 		// Get the format from the Source if possible from no specific supplier
       
   321 		TRAPD(err, iSourceFormat = CMMFFormatDecode::NewL(&aSource, KNullDesC, iSourceFormatSupportsCustomInterfaces));
       
   322 		//[ we want to complete silently for KErrNotSupported
       
   323 		// because there is a possibility that the client
       
   324 		// wants to add the data format later, see audio api for
       
   325 		// a description of this feature]
       
   326 		if ((err != KErrNotSupported) && (err != KErrNone))
       
   327 			{
       
   328 			User::Leave(err);
       
   329 			}
       
   330 		}
       
   331 	else if (aSource.DataSourceType()==KUidMmfAudioInput)
       
   332 		{
       
   333 		//[ ensure that the audio input has a pointer to dev sound ]
       
   334 		CMMFAudioInput* audioInput = STATIC_CAST(CMMFAudioInput*, &aSource);
       
   335 		__ASSERT_ALWAYS( audioInput, Panic(ENoAudioInput));
       
   336 		// [ lets load dev sound ]
       
   337 		User::LeaveIfError(audioInput->SourceThreadLogon( *this ));
       
   338 		}
       
   339 	else
       
   340 		{
       
   341 		User::Leave(KErrNotSupported);
       
   342 		}
       
   343 
       
   344 	//[ its now safe to set the source ]
       
   345 	iDataSource = &aSource ;
       
   346 
       
   347 	//[ assert the post condition ]
       
   348 	__ASSERT_ALWAYS(iDataSource, Panic(EMMFAudioControllerPanicDataSourceDoesNotExist));
       
   349 
       
   350 	iDataSource->SetSourcePrioritySettings(iPrioritySettings);
       
   351 	}
       
   352 
       
   353 /**
       
   354  *  AddDataSinkL
       
   355  *
       
   356  *	Adds a data sink to the controller
       
   357  *
       
   358  *	@param aSink
       
   359  *
       
   360  */
       
   361 void CMMFAudioController::AddDataSinkL(MDataSink& aSink)
       
   362 	{
       
   363 	//[ assert the invariant ]
       
   364 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetDataSink));
       
   365 
       
   366 	// [ precondition that the controller is stopped ]
       
   367     if( State() != EStopped )
       
   368 		User::Leave( KErrNotReady );
       
   369 
       
   370 	// [ assert precondition that sink does not exist ]
       
   371 	if (iDataSink)
       
   372 		User::Leave(KErrAlreadyExists);
       
   373 
       
   374 
       
   375 	// Note that this code is not generic for sinks
       
   376 	// It it only checks for file,des clips and audio outputs
       
   377 	// If a new sink type eg a Url Clip then this needs to be added to the supported source Uids
       
   378 	if ( SinkFormatRequired( aSink ) )
       
   379 		{//the sink is a clip
       
   380 
       
   381 		// Get the format from the Sink if possible from no specific supplier
       
   382 		TRAPD(err, iSinkFormat = CMMFFormatEncode::NewL(&aSink, KNullDesC));
       
   383 		//[ we want to complete silently for KErrNotSupported
       
   384 		// because there is a possibility that the client
       
   385 		// wants to add the data format later, see audio api for
       
   386 		// a description of this feature]
       
   387 		if ((err != KErrNotSupported) && (err != KErrNone))
       
   388 			{
       
   389 			User::Leave(err);
       
   390 			}
       
   391 		}
       
   392 	else if (aSink.DataSinkType()==KUidMmfAudioOutput)
       
   393 		{
       
   394 
       
   395 		//[ ensure that the audio output has a pointer to dev sound ]
       
   396 		CMMFAudioOutput* audioOutput = STATIC_CAST(CMMFAudioOutput*, &aSink);
       
   397 		__ASSERT_ALWAYS( audioOutput, Panic(ENoAudioOutput));
       
   398 		// [ lets load dev sound ]
       
   399 		User::LeaveIfError(audioOutput->SinkThreadLogon( *this ));
       
   400 		if (IsSecureDrmModeL())
       
   401     		{
       
   402     		User::LeaveIfError(audioOutput->SoundDevice().SetClientThreadInfo(ClientThreadIdL()));
       
   403     		} 
       
   404 		}
       
   405 	else
       
   406 		{
       
   407 		User::Leave(KErrNotSupported);
       
   408 		}
       
   409 
       
   410 	//[ now that we are sure we have not left we can update the sink
       
   411 	// transactionally ]
       
   412 	iDataSink = &aSink;
       
   413 
       
   414 	// [ assert post conditions that a sink has been added ]
       
   415 	__ASSERT_ALWAYS(iDataSink, Panic(EMMFAudioControllerPanicDataSinkDoesNotExist));
       
   416 
       
   417 	iDataSink->SetSinkPrioritySettings(iPrioritySettings);
       
   418 	}
       
   419 
       
   420 /**
       
   421  *  PrimeL
       
   422  *
       
   423  *  If Prime fails the client should reset the controller
       
   424  *  because as noted below this code is not transactional.
       
   425  *
       
   426  */
       
   427 void CMMFAudioController::PrimeL()
       
   428 	{
       
   429 	//[ assert the invariant ]
       
   430 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateForPrime));
       
   431 
       
   432 	//[ assert the precondition ( in a friendly way for this api 
       
   433 	// that we are either stopped or primed already ]
       
   434 	if(!(( State() == EStopped ) || (State() == EPrimed )))
       
   435 		User::Leave( KErrNotReady );
       
   436 
       
   437 	// [ precondition we have a data source & sink ]
       
   438 	__ASSERT_ALWAYS( iDataSource, Panic( ENoDataSource));
       
   439 	__ASSERT_ALWAYS( iDataSink, Panic( ENoDataSink));
       
   440 
       
   441 
       
   442 	//[ precondition that we need a source format ]
       
   443 	if ( SourceFormatRequired(*iDataSource) && !(iSourceFormat))
       
   444 		User::Leave( KErrNotSupported );
       
   445 
       
   446 	// [ check the precondition if we need a data sink format ]
       
   447 	if ( SinkFormatRequired(*iDataSink) && !( iSinkFormat ))
       
   448 		{
       
   449 		User::Leave( KErrNotSupported );
       
   450 		}
       
   451 
       
   452 	// [ ideally this code should be transaction based and
       
   453 	//   if failure occurs we roll back to the previous state
       
   454 	// in the code below this is not the case and the controller
       
   455 	// can be left in an unstable state should any part of prime fail]
       
   456 	if (iState == EStopped)
       
   457 		{ //datapath propagates prime to sink & source
       
   458 		
       
   459 		NegotiateL();
       
   460 
       
   461 		if (!iSourceAndSinkAdded)
       
   462 			{
       
   463 			//add data source and sinks to datapath - Note cant do this in AddDataSource/Sink
       
   464 			//because the sources and sinks aren't configured at this point
       
   465 			if (iSourceFormat)
       
   466 				iDataPath->AddDataSourceL(iSourceFormat);
       
   467 			else if (iDataSource)
       
   468 				iDataPath->AddDataSourceL(iDataSource);
       
   469 			if (iSinkFormat)
       
   470 				iDataPath->AddDataSinkL(iSinkFormat);
       
   471 			else if (iDataSink)
       
   472 				iDataPath->AddDataSinkL(iDataSink);
       
   473 			iSourceAndSinkAdded = ETrue ;
       
   474 			}
       
   475 		
       
   476 		iDataPath->PrimeL();
       
   477 		
       
   478 		if (iSourceFormat)
       
   479 			{
       
   480 			//in case of imaadpcm format set the output block length
       
   481 			
       
   482 			TFourCC sourceFourCC = iSourceFormat->SourceDataTypeCode(TMediaId(KUidMediaTypeAudio));
       
   483 			if ((sourceFourCC == KMMFFourCCCodeIMAD) && iSourceFormatSupportsCustomInterfaces)
       
   484 				{
       
   485 				CMMFFormatDecode2* decode2 = static_cast<CMMFFormatDecode2*>(iSourceFormat);
       
   486 				MMMFDecodeCustomInterfaceBlockLength* formatBlockLengthCI = static_cast<MMMFDecodeCustomInterfaceBlockLength*>(decode2->CustomInterface(KUidCustomInterfaceMmfDecodeBlockLength));
       
   487 				if (formatBlockLengthCI)
       
   488 					{
       
   489 					TInt blockLength = formatBlockLengthCI->FileBlockLength();
       
   490 					TInt err = iDataPath->SetBlockLength(blockLength);
       
   491 					
       
   492 					if ((err != KErrNone) && (iDataSink))
       
   493 						{
       
   494 						MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
       
   495 						MMMFDevSoundCustomInterfaceFileBlockLength* fileBlockLengthCI = static_cast<MMMFDevSoundCustomInterfaceFileBlockLength*>(audioOutput->SoundDevice().CustomInterface(KUidCustomInterfaceDevSoundFileBlockLength));
       
   496 
       
   497 						if (fileBlockLengthCI)
       
   498 							{
       
   499 							fileBlockLengthCI->SetFileBlockLength(blockLength);
       
   500 							err = KErrNone;
       
   501 							}
       
   502 						}
       
   503 					User::LeaveIfError(err);
       
   504 					}
       
   505 				}
       
   506 			}
       
   507 			
       
   508 		if ((iSinkFormat) && (!iSourceFormat))
       
   509 			{//we are recording to a clip so the data path position is the sink
       
   510 			//need to set datapath position to end of format pos (incase sink clip already exists
       
   511 			TTimeIntervalMicroSeconds duration = iSinkFormat->Duration(iMediaId);
       
   512 			if (duration != TTimeIntervalMicroSeconds(0))
       
   513 				{//the file already exists and has a duration so set data path position to the end of the file
       
   514 				iDataPath->SetPositionL(duration);
       
   515 				}
       
   516 			}
       
   517 		//[ it is now safe to make the transition to primed ]
       
   518 		SetState( EPrimed );		
       
   519 		}
       
   520 	else if (State() == EPrimed)
       
   521 		{ //controller is already primed so just pass prime onto DP
       
   522 		iDataPath->PrimeL();
       
   523 		}
       
   524 
       
   525 	if (iDataSource->DataSourceType()==KUidMmfFileSource)
       
   526 		{
       
   527 		CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
       
   528 		// we only support protected files for playback
       
   529 		if (iDataSink->DataSinkType()!=KUidMmfAudioOutput && file->IsProtectedL())
       
   530 			User::Leave(KErrNotSupported);
       
   531 		}
       
   532 
       
   533 	//[ assert the post condition that we are in the state primed]
       
   534 	__ASSERT_ALWAYS( SetState( EPrimed ), Panic( EPostConditionViolation ));
       
   535 	// [ assert the invariant]
       
   536 	__ASSERT_ALWAYS( Invariant(), Panic( EStateNotPrimed ) );
       
   537 	}
       
   538 
       
   539 /**
       
   540  *  ResetL
       
   541  *  This method resets the controller
       
   542  *
       
   543  */
       
   544 void CMMFAudioController::ResetL()
       
   545 	{
       
   546 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToReset ) );
       
   547 	iIsPreemptionPause = EFalse;
       
   548 	// Stop recording if it's not stopped,
       
   549 	if (State() != EStopped)
       
   550 		{
       
   551 		iDataPath->Stop();
       
   552 		SetState(EStopped);
       
   553 		}
       
   554 	iIsPaused = EFalse;
       
   555 	
       
   556 	// Remove references to source and sink
       
   557 	iDataPath->ResetL();
       
   558 
       
   559 	delete iSourceFormat; iSourceFormat = NULL  ;
       
   560 	delete iSinkFormat;	iSinkFormat = NULL  ;
       
   561 
       
   562 	//[ ensure loggoff of source and sink ]
       
   563 	iDataSource = NULL ;
       
   564 	iDataSink = NULL ;
       
   565 	iSourceAndSinkAdded = EFalse;
       
   566 
       
   567 	// [ assert the invariant]
       
   568 	__ASSERT_ALWAYS( Invariant(), Panic( EBadResetState ) );
       
   569 
       
   570 	// [ assert the post condition
       
   571 	//   state == stopped
       
   572 	//   iDataSource is NULL
       
   573 	//   iSourceFormat is NULL
       
   574 	//   iSinkFormat is NULL ]
       
   575 	__ASSERT_ALWAYS( ResetPostCondition(), Panic( EBadReset ));
       
   576 	__ASSERT_ALWAYS( Invariant(), Panic(EBadState));
       
   577 	}
       
   578 
       
   579 /**
       
   580 * ResetPostCondition
       
   581 * This function determnines if the reset post condition is valid
       
   582 * @internalTechnology
       
   583 */
       
   584 TBool CMMFAudioController::ResetPostCondition() const
       
   585 	{
       
   586 
       
   587      TBool result = EFalse ;
       
   588 	if((iSourceFormat     == NULL)  &&
       
   589 	(iDataSink            == NULL)  &&
       
   590 	(iDataSource          == NULL)  && 
       
   591 	(iSinkFormat          == NULL)  &&
       
   592 	(State() == EStopped))
       
   593 		{
       
   594          result = ETrue;
       
   595 		}
       
   596 
       
   597     return result;
       
   598 	}
       
   599 
       
   600 
       
   601 /**
       
   602  *
       
   603  * PlayL
       
   604  *
       
   605  */
       
   606 void CMMFAudioController::PlayL()
       
   607 	{
       
   608 	// [ assert the precondition that the
       
   609 	//   play command is only activated in the primed state]
       
   610 	if ( State() != EPrimed)
       
   611 		{
       
   612 		User::Leave(KErrNotReady);
       
   613 		}
       
   614 
       
   615 	// [ assert the Invariant ]
       
   616 	__ASSERT_ALWAYS( Invariant(), Panic(EStateNotReadyToPlay));
       
   617 
       
   618 	// if the position has already been set to the file's duration or 
       
   619 	// beyond, then don't bother getting the datapath to play - this 
       
   620 	// avoids sending empty buffers to DevSound
       
   621 	if (iDataSink->DataSinkType() == KUidMmfAudioOutput && 
       
   622 		PositionL() >= DurationL())
       
   623 		{
       
   624 		SendEventToClient(TMMFEvent(KMMFEventCategoryPlaybackComplete, KErrNone));
       
   625 		return;
       
   626 		}
       
   627 
       
   628 	// Execute play intent
       
   629 	// This must be done after PlayL, as the file might not be open yet
       
   630 	if(!iIsPreemptionPause)
       
   631 		{
       
   632 		if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource )
       
   633 			{
       
   634 			CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
       
   635 			TInt err = file->ExecuteIntent(iIsPaused? ContentAccess::EContinue : ContentAccess::EPlay);
       
   636 			if (err != KErrNone)
       
   637 				{
       
   638 				User::Leave(err);
       
   639 				}
       
   640 			}
       
   641 		}
       
   642 	//[datapath propogates play to sink & source]
       
   643 	iDataPath->PlayL();
       
   644 	iIsPreemptionPause = EFalse;
       
   645 	iIsPaused = EFalse;
       
   646 	SetState( EPlaying );
       
   647 	
       
   648 	//[ assert the post condition we are playing ]
       
   649 	//No - this assumption is not always true if an error occurs eg OOM
       
   650 	//the state could be EStopped
       
   651 	//	__ASSERT_ALWAYS( (State() == EPlaying ), Panic( EBadState));
       
   652 	//[ assert the invariant ]
       
   653 	__ASSERT_ALWAYS( Invariant(), Panic(EBadPlayState));
       
   654 	}
       
   655 
       
   656 /**
       
   657  *  PauseL
       
   658  *
       
   659  */
       
   660 void CMMFAudioController::PauseL()
       
   661 	{
       
   662 	// [ assert the invariant ]
       
   663 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToPause));
       
   664 	
       
   665 	//[ assert the precondition that we are playing ]
       
   666 	if ( State() != EPlaying)
       
   667 		{
       
   668 		User::Leave(KErrNotReady);
       
   669 		}
       
   670 	if(!iIsPreemptionPause)
       
   671 		{
       
   672 		if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource)
       
   673 			{
       
   674 			CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
       
   675 			TInt err = file->ExecuteIntent(ContentAccess::EPause);
       
   676 			if (err != KErrNone)
       
   677 				{
       
   678 				User::Leave(err);
       
   679 				}
       
   680 			}
       
   681 		}
       
   682 	iIsPaused = ETrue;
       
   683 	//[ datapath propogates pause to sink & source ]
       
   684 	if(iIsPreemptionPause)
       
   685 	    {
       
   686 	    iDataPath->PreEmptionPause();
       
   687 	    }
       
   688 	else
       
   689 	    {
       
   690 	    iDataPath->Pause();
       
   691 	    }
       
   692 	SetState(EPrimed);
       
   693 	
       
   694 	//[ assert the post condition we are primed ]
       
   695 	__ASSERT_ALWAYS( (State() == EPrimed ), Panic( EBadState));
       
   696 	//[ assert the invariant ]
       
   697 	__ASSERT_ALWAYS( Invariant(), Panic(EBadPauseState));
       
   698 	}
       
   699 
       
   700 /**
       
   701  *  StopL
       
   702  *
       
   703  */
       
   704 void CMMFAudioController::StopL(TMMFMessage& aMessage)
       
   705 	{
       
   706 	//[ assert the invariant ]
       
   707 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToStop));
       
   708 	// [ precondition that we are not already stopped 
       
   709 	// && if we are stopped do nothing.
       
   710 	//If we are stopping a recording, we need to give the datapath chance to 
       
   711 	//process that data which has already been captured. We therefore stay in the EPlaying
       
   712 	//state, but use iStoppingRecording to indicate that we are stopping.
       
   713 
       
   714 	if ((State() != EStopped) && !iStoppingRecording)
       
   715 		{
       
   716 		if((State() == EPlaying) && (iDataSource->DataSourceType()==KUidMmfAudioInput)) //we are recording
       
   717 			{
       
   718 			// datapath is requested to stop recording but process any alreay captured buffers,
       
   719 			// the pause method is used for this purpose and as such, the data path must 
       
   720 			// determine that it is recording to be able to act accordingly.
       
   721 			// aMessgae is not completed until datapath advises that it has completed.
       
   722 			iDataPath->Pause();
       
   723 			iStoppingMessage = CMMFMessageHolder::NewL(aMessage);
       
   724 			iStoppingRecording = ETrue;
       
   725 			}
       
   726 		else if(((State() == EPlaying) || iIsPaused) && (iDataSink->DataSinkType()==KUidMmfAudioOutput)) //we are playing
       
   727 			{
       
   728 			if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource)
       
   729 					{
       
   730 					CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
       
   731 					file->ExecuteIntent(ContentAccess::EStop);
       
   732 					}
       
   733 			//  datapath propogates stop to sink & source
       
   734 			iDataPath->Stop();
       
   735 			SetState(EStopped);
       
   736 			}
       
   737 		
       
   738 		else
       
   739 			{
       
   740 			//  datapath propogates stop to sink & source
       
   741 			iDataPath->Stop();
       
   742 			SetState(EStopped);
       
   743 			}
       
   744 		}
       
   745 	iIsPaused = EFalse;
       
   746 	iIsPreemptionPause = EFalse;
       
   747 	//complete message as request is complete.
       
   748 	if(State() == EStopped && !IsUnderTest())
       
   749 		{
       
   750 		aMessage.Complete(KErrNone);
       
   751 		}
       
   752 
       
   753 	//[ assert the invariant ]
       
   754 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStopState));
       
   755 	}
       
   756 
       
   757 /**
       
   758  *  PositionL
       
   759  * Preconditions:
       
   760  * The Controller is in the state EPrimed
       
   761  * @return TTimeIntervalMicroSeconds
       
   762  *
       
   763  */
       
   764 TTimeIntervalMicroSeconds CMMFAudioController::PositionL() const
       
   765 	{
       
   766 	//[ assert the invariant ]
       
   767 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToPosition));
       
   768 	// [ precondition that we are playing or primed ]
       
   769 	if( !((State() == EPrimed) || (State() == EPlaying)))
       
   770 			User::Leave(KErrNotReady);
       
   771 
       
   772     TTimeIntervalMicroSeconds position = iDataPath->Position();
       
   773 	
       
   774 	//[ assert the invariant ]
       
   775 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStatePosition));
       
   776 	
       
   777 	return position;
       
   778 	}
       
   779 
       
   780 /**
       
   781 * SetPositionL
       
   782 *
       
   783 * @param aPosition
       
   784 *
       
   785 */
       
   786 void CMMFAudioController::SetPositionL(const TTimeIntervalMicroSeconds& aPosition)
       
   787 	{
       
   788 	//[ assert the invariant ]
       
   789 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetPosition));
       
   790 	
       
   791 	// [ precondition that we are not already stopped ]
       
   792 	if (iState == EStopped)
       
   793 		User::Leave(KErrNotReady);
       
   794 
       
   795 	//[ precondition that the position is >= 0 && <= Duration ]
       
   796 		{
       
   797 		TTimeIntervalMicroSeconds theDuration(0);
       
   798 		if (iSourceFormat)
       
   799 			{ //if the source is a clip then the duration always refers to the source - even if the sink is a clip
       
   800 			theDuration = iSourceFormat->Duration(iMediaId);
       
   801 			}
       
   802 		else if (iSinkFormat)
       
   803 			{ //duration of recorded clip
       
   804 			theDuration = iSinkFormat->Duration(iMediaId);
       
   805 			}
       
   806 		TTimeIntervalMicroSeconds theStart(0);
       
   807 		if( ( aPosition < theStart) || ( aPosition > theDuration) )
       
   808 			//[ invalid position before start and after end]
       
   809 			User::Leave(KErrArgument); 
       
   810 		}
       
   811 
       
   812 	//[ set the position on the data path ]
       
   813 
       
   814 	// if we're already playing, flush all the buffers by calling Stop(), 
       
   815 	// PrimeL() and then PlayL() - otherwise we could be waiting a long time.
       
   816 	if (iDataSink->DataSinkType() == KUidMmfAudioOutput && iState == EPlaying)
       
   817 		{
       
   818 		CMMFAudioOutput* audioOutput = static_cast<CMMFAudioOutput*>(iDataSink);
       
   819 		if(!audioOutput->IsResumeSupported())
       
   820 			{
       
   821 			iDataPath->Stop();
       
   822 			SetState(EStopped);
       
   823 			PrimeL();
       
   824 			iDataPath->SetPositionL(aPosition);
       
   825 			iDataPath->RetainRepeatInfo();
       
   826 			PlayL();
       
   827 			}
       
   828 		else
       
   829 			{
       
   830 			iDataPath->Pause();
       
   831 			// This empty buffers
       
   832 			User::LeaveIfError(audioOutput->SoundDevice().EmptyBuffers());
       
   833 			iDataPath->SetPositionL(aPosition);
       
   834 			iDataPath->RetainRepeatInfo();
       
   835 			// This does a DevSound resume 
       
   836 			iDataPath->PlayL(); 
       
   837 			}
       
   838 		}
       
   839 	else
       
   840 		iDataPath->SetPositionL(aPosition);
       
   841 	
       
   842 	//[ assert the invariant ]
       
   843 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateSetPosition));
       
   844 
       
   845     // [ post condition not checked ]
       
   846 	//[ we do not compare the set position with get postion
       
   847     //  because the interface to do so is poor ]
       
   848 	}
       
   849 
       
   850 /**
       
   851 *
       
   852 * DurationL
       
   853 *
       
   854 * @returns TTimeIntervalMicroSeconds 
       
   855 *
       
   856 */
       
   857 TTimeIntervalMicroSeconds CMMFAudioController::DurationL() const
       
   858 	{
       
   859 	//[ assert the invariant ]
       
   860 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToDuration));
       
   861 
       
   862 
       
   863 	// [ assert we have a format that supports duration ]
       
   864 	if( !( iSourceFormat || iSinkFormat ) )
       
   865 		User::Leave(KErrNotSupported);
       
   866 	
       
   867 	//[ now do the real work of getting the duration ]
       
   868 	// ------------------------------------------------
       
   869 	TTimeIntervalMicroSeconds theDuration(0);
       
   870 	if (iSourceFormat)
       
   871 		{ //if the source is a clip then the duration always refers to the source - even if the sink is a clip
       
   872 		theDuration = iSourceFormat->Duration(iMediaId);
       
   873 		}
       
   874 	else if (iSinkFormat)
       
   875 		{ //duration of recorded clip
       
   876 		theDuration = iSinkFormat->Duration(iMediaId);
       
   877 		}
       
   878 
       
   879 	//[ assert the invariant ]
       
   880 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateDuration));
       
   881 
       
   882 	return theDuration; 
       
   883 	}
       
   884 
       
   885 /**
       
   886 *
       
   887 * GetNumberOfMetaDataEntriesL
       
   888 *
       
   889 * @param "TInt"
       
   890 *
       
   891 */
       
   892 void CMMFAudioController::GetNumberOfMetaDataEntriesL(TInt& aNumberOfEntries )
       
   893 	{
       
   894 
       
   895 	//[ assert the invariant ]
       
   896 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetNumberOfMetaDataEntries));
       
   897 
       
   898 	//[ precondition that we are in the primed state or stopped ]
       
   899 	if( !((State() == EPrimed) || ( State() == EStopped)))
       
   900 		User::Leave(KErrNotReady);
       
   901 
       
   902     // [ precondition there is a sink format ]
       
   903 	if (!iDataSink)
       
   904 		User::Leave(KErrNotSupported);
       
   905 
       
   906 	// [ precondition the sink format is an encode format ]
       
   907 	if ((iDataSink->DataSinkType()!=KUidMmfAudioOutput) &&
       
   908 		(iDataSource->DataSourceType()!= KUidMmfAudioInput) )
       
   909 		User::Leave(KErrNotSupported);
       
   910 
       
   911 	if (iDataSink->DataSinkType()==KUidMmfAudioOutput)
       
   912 		{
       
   913 
       
   914 		//[ precondition the format exists ]
       
   915 		if( !iSourceFormat )
       
   916 			User::Leave(KErrNotSupported);
       
   917 
       
   918 		//[ Get the Number of meta data entries from the sink format ]
       
   919 		iSourceFormat->GetNumberOfMetaDataEntriesL( aNumberOfEntries );
       
   920 		}
       
   921 	else if (iDataSource->DataSourceType()==KUidMmfAudioInput)
       
   922 		{
       
   923 		if( !iSinkFormat )
       
   924 			User::Leave(KErrNotSupported);
       
   925 
       
   926 		iSinkFormat->GetNumberOfMetaDataEntriesL( aNumberOfEntries );
       
   927 		}
       
   928 
       
   929 	//[ assert the invariant ]
       
   930 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateGetNumberOfMetaDataEntries));
       
   931 
       
   932 	}
       
   933 
       
   934 /**
       
   935 * GetMetaDataEntryL
       
   936 * @param aIndex
       
   937 * @returns "CMMFMetaDataEntry*"
       
   938 */
       
   939 CMMFMetaDataEntry* CMMFAudioController::GetMetaDataEntryL(TInt aIndex )
       
   940 	{
       
   941 		//[ assert the invariant ]
       
   942 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMetaDataEntries));
       
   943 
       
   944 	//[ precondition that we are in the primed state or stopped ]
       
   945 	if( !((State() == EPrimed) || ( State() == EStopped)))
       
   946 		User::Leave(KErrNotReady);
       
   947 
       
   948     // [ precondition there is a sink format ]
       
   949 	if (!iDataSink)
       
   950 		User::Leave(KErrNotSupported);
       
   951 
       
   952 	iDataSink->DataSinkType();
       
   953 	iDataSource->DataSourceType();
       
   954 
       
   955 	// [ precondition the sink or source is either an audio output or input ]
       
   956 	if ((iDataSink->DataSinkType()!= KUidMmfAudioOutput) &&
       
   957 		(iDataSource->DataSourceType()!= KUidMmfAudioInput ))
       
   958 		User::Leave(KErrNotSupported);
       
   959 
       
   960 	//[ Get the meta data entry from the sink format ]
       
   961 	CMMFMetaDataEntry*  theEntry = NULL;
       
   962 
       
   963 	if (iDataSink->DataSinkType()==KUidMmfAudioOutput)
       
   964 		{ 
       
   965 		//[ precondition the format exists ]
       
   966 		if( !iSourceFormat )
       
   967 			User::Leave(KErrNotSupported);
       
   968 
       
   969 		//[ Get the Number of meta data entries from the sink format ]
       
   970 		theEntry = iSourceFormat->MetaDataEntryL(aIndex);
       
   971 		}
       
   972 	else if (iDataSource->DataSourceType()==KUidMmfAudioInput)
       
   973 		{
       
   974 		//[ precondition the format exits ]
       
   975 		if( !iSinkFormat )
       
   976 			User::Leave(KErrNotSupported);
       
   977 		theEntry = iSinkFormat->MetaDataEntryL(aIndex);
       
   978 		}
       
   979 
       
   980 	//[ assert the post condition that the entry is not null ]
       
   981 	__ASSERT_ALWAYS( theEntry, Panic(EMetaEntryIsNull));
       
   982 
       
   983 	//[ assert the invariant ]
       
   984 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateGetMetaDataEntries));
       
   985 
       
   986 	return theEntry;
       
   987 	}
       
   988 
       
   989 /**
       
   990 * RemoveDataSourceL
       
   991 * @param aDataSource
       
   992 * 
       
   993 */
       
   994 void CMMFAudioController::RemoveDataSourceL(MDataSource& aDataSource )
       
   995 	{
       
   996 	//[ assert the invariant ]
       
   997 	__ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForDataSourceRemoval) );
       
   998 
       
   999 	//[ precondition is that we have a data source ]
       
  1000 	if( !iDataSource )
       
  1001 		User::Leave(KErrNotReady);
       
  1002 
       
  1003 	//[precondition the data source is the data source we have]
       
  1004 	if( iDataSource != &aDataSource )
       
  1005 		User::Leave(KErrArgument);
       
  1006 
       
  1007 	//[ the controller is in the stopped state ]
       
  1008 	if(State() != EStopped)
       
  1009 		User::Leave(KErrNotReady);
       
  1010 
       
  1011 	//[ remove the data sink from the controller and delete the format]
       
  1012      if( iSourceAndSinkAdded )
       
  1013 		 {
       
  1014          __ASSERT_ALWAYS( iDataPath, Panic( EBadState )); 
       
  1015 	     //[ Remove references to source and sink ]
       
  1016 	     iDataPath->ResetL();
       
  1017 		 iSourceAndSinkAdded = EFalse ;
       
  1018 		 }
       
  1019 
       
  1020 	 // [ delete the data sink and format ]
       
  1021 	 iDataSource = NULL ;
       
  1022 	 delete iSourceFormat;
       
  1023 	 iSourceFormat = NULL;
       
  1024 		
       
  1025 	// [ assert postcondition we are stopped ]
       
  1026 	__ASSERT_ALWAYS( (State() == EStopped), Panic(EPostConditionViolation) );
       
  1027 
       
  1028 	//[ assert postcondition the SourceAndSinkAdded is false ]
       
  1029 	__ASSERT_ALWAYS( !iSourceAndSinkAdded, Panic( EPostConditionViolation ));
       
  1030 	
       
  1031 	//[ assert postcondition the data sinkformat  is null ]
       
  1032 	__ASSERT_ALWAYS( (iSourceFormat == NULL ), Panic( EPostConditionViolation ));
       
  1033 
       
  1034 	//[ assert postcondition the data sink  is null ]
       
  1035 	__ASSERT_ALWAYS( (iDataSource == NULL ), Panic( EPostConditionViolation ));
       
  1036 
       
  1037 	//[ assert the invariant ]
       
  1038 	__ASSERT_ALWAYS( Invariant(), Panic(EBadDataSourceRemoval));
       
  1039 
       
  1040 	}
       
  1041 
       
  1042 /**
       
  1043 * RemoveDataSinkL
       
  1044 * 
       
  1045 * @param aDataSink
       
  1046 *
       
  1047 */
       
  1048 void CMMFAudioController::RemoveDataSinkL(MDataSink& aDataSink )
       
  1049 	{
       
  1050 	//[ assert the invariant ]
       
  1051 	__ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForDataSinkRemoval) );
       
  1052 
       
  1053 	//[ precondition is that we have a data sink ]
       
  1054 	if( !iDataSink )
       
  1055 		User::Leave(KErrNotSupported);
       
  1056 
       
  1057 	//[precondition the data sink is the data sink we have]
       
  1058 	if( iDataSink != &aDataSink )
       
  1059 		User::Leave(KErrNotSupported);
       
  1060 
       
  1061 	//[ the controller is in the stopped state ]
       
  1062 	if(State() != EStopped)
       
  1063 		User::Leave(KErrNotReady);
       
  1064 
       
  1065 	//[ remove the data sink from the controller and delete the format]
       
  1066      if( iSourceAndSinkAdded )
       
  1067 		 {
       
  1068          __ASSERT_ALWAYS( iDataPath, Panic( EBadState ));
       
  1069          //[ Remove references to source and sink ]
       
  1070 	     iDataPath->ResetL();
       
  1071 		 iSourceAndSinkAdded = EFalse ;
       
  1072 		 }
       
  1073 
       
  1074 	 // [ reset data sink referenece and remove the format ]
       
  1075 	 iDataSink = NULL ;
       
  1076 	 delete iSinkFormat;
       
  1077 	 iSinkFormat = NULL;
       
  1078 		
       
  1079 	// [ assert postcondition we are stopped ]
       
  1080 	__ASSERT_ALWAYS( (State() == EStopped), Panic(EPostConditionViolation) );
       
  1081 
       
  1082 	//[ assert postcondition the SourceAndSinkAdded is false ]
       
  1083 	__ASSERT_ALWAYS( !iSourceAndSinkAdded, Panic( EPostConditionViolation ));
       
  1084 	
       
  1085 	//[ assert postcondition the data sinkformat  is null ]
       
  1086 	__ASSERT_ALWAYS( (iSinkFormat == NULL ), Panic( EPostConditionViolation ));
       
  1087 
       
  1088 	//[ assert postcondition the data sink  is null ]
       
  1089 	__ASSERT_ALWAYS( (iDataSink == NULL ), Panic( EPostConditionViolation ));
       
  1090 
       
  1091 	//[ assert the invariant ]
       
  1092 	__ASSERT_ALWAYS( Invariant(), Panic(EBadDataSinkRemoval));
       
  1093 	}
       
  1094 
       
  1095 /**
       
  1096  *  CustomCommand
       
  1097  *  @param aMessage
       
  1098  */
       
  1099 void CMMFAudioController::CustomCommand(TMMFMessage& aMessage)
       
  1100 	{
       
  1101 	//[ assert the invariant ]
       
  1102 	__ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForCustomCommand));
       
  1103 	// [ We do not have any custom commands ]
       
  1104 	aMessage.Complete(KErrNotSupported);
       
  1105 	}
       
  1106 
       
  1107 /**
       
  1108 * NegotiateL
       
  1109 * 
       
  1110 */
       
  1111 void CMMFAudioController::NegotiateL()
       
  1112 	{
       
  1113 	//[ assert the invariant ]
       
  1114 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToNegotiate));
       
  1115 
       
  1116 	//utility function used by custom to negotiate source sink settings after a change
       
  1117 	if ((iSourceFormat)&&(iSinkFormat)) //convert
       
  1118 		{
       
  1119 		iSinkFormat->NegotiateL(*iSourceFormat);
       
  1120 		iSourceFormat->NegotiateSourceL(*iSinkFormat);
       
  1121 		iSinkFormat->NegotiateL(*iSourceFormat);
       
  1122 
       
  1123 		// check for upsampling attempts
       
  1124 		if (iSinkFormat->SampleRate() > iSourceFormat->SampleRate())
       
  1125 			{
       
  1126 			// we don't support upsampling
       
  1127 			User::Leave( KErrNotSupported );
       
  1128 			}
       
  1129 		}
       
  1130 	else if ((iDataSource)&&(iSinkFormat)) //record
       
  1131 		{
       
  1132 		// need two step negotiation for record
       
  1133 		// first try to set the audio input settings to match the required settings for recording
       
  1134 		iDataSource->NegotiateSourceL(*iSinkFormat);
       
  1135 		// now call negotiateL on the sink in order to tell it what the audio input was set to.
       
  1136 		iSinkFormat->NegotiateL(*iDataSource);
       
  1137 		}
       
  1138 	else if ((iSourceFormat)&&(iDataSink)) //play
       
  1139 		{	
       
  1140 		iDataSink->NegotiateL(*iSourceFormat);
       
  1141 		}
       
  1142 	//[ assert the invariant ]
       
  1143 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterNegotiate));
       
  1144 	}
       
  1145 
       
  1146 /**
       
  1147  *  SetPrioritySettings
       
  1148  *
       
  1149  *	@param aPrioritySettings
       
  1150  */
       
  1151 void CMMFAudioController::SetPrioritySettings(const TMMFPrioritySettings& aPrioritySettings)
       
  1152 	{
       
  1153 	//[ assert the invariant ]
       
  1154 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetPriority));
       
  1155 
       
  1156 	//[ update the priority settings of the controller]
       
  1157 	iPrioritySettings = aPrioritySettings;
       
  1158 
       
  1159 	//pass settings on to source and sink
       
  1160 	if (iDataSource)
       
  1161 		{
       
  1162 		iDataSource->SetSourcePrioritySettings(iPrioritySettings);
       
  1163 		}
       
  1164 	if (iDataSink)
       
  1165 		{
       
  1166 		iDataSink->SetSinkPrioritySettings(iPrioritySettings);
       
  1167 		}
       
  1168 
       
  1169     // assert the post condition
       
  1170 	//__ASSERT_ALWAYS( (iPrioritySettings == aPrioritySettings), Panic( ));
       
  1171 	//[ assert the invariant ]
       
  1172 	__ASSERT_ALWAYS( Invariant(), Panic(EBadPriorityState));
       
  1173 	}
       
  1174 
       
  1175 /**
       
  1176  *  SendEventToClient
       
  1177  *
       
  1178  *	@param aEvent
       
  1179  */
       
  1180 TInt CMMFAudioController::SendEventToClient(const TMMFEvent& aEvent)
       
  1181 	{
       
  1182 	//[ assert the invariant ]
       
  1183 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSendEventToClient));
       
  1184 
       
  1185 	TMMFEvent controllerEvent;
       
  1186 	//Were going to stop playing, force event type to be the correct type
       
  1187 	controllerEvent.iEventType = KMMFEventCategoryPlaybackComplete;
       
  1188 	controllerEvent.iErrorCode = aEvent.iErrorCode;
       
  1189 
       
  1190 
       
  1191 
       
  1192 	//If we receive KErrNone from the DataPath, it indicates that it has 
       
  1193 	//successfully completed playing/converting/recording.
       
  1194 	if ((aEvent.iEventType == KMMFEventCategoryPlaybackComplete) && 
       
  1195 		(aEvent.iErrorCode == KErrNone))
       
  1196 		{
       
  1197 		if(iStoppingRecording)
       
  1198 			{
       
  1199 			iStoppingRecording = EFalse;
       
  1200 			iDataPath->Stop();
       
  1201 			SetState( EStopped );
       
  1202 			
       
  1203 			//complete the clients stop request
       
  1204 			iStoppingMessage->Complete(KErrNone);
       
  1205 			delete iStoppingMessage; iStoppingMessage=NULL;
       
  1206 
       
  1207 			//we don't want to send an event to the client
       
  1208 			return KErrNone;
       
  1209 			}
       
  1210 		else
       
  1211 			{//datapath has reached end of file so set internal state to primed
       
  1212 			SetState( EPrimed );
       
  1213 			}
       
  1214 		}
       
  1215     //DevCR KEVN-7T5EHA
       
  1216     //If the client has not registered for the ARN, 
       
  1217     //and a pre-emption happens we need to goto the Pause state
       
  1218     //instead of the Stop state. this should happen only in the case of playback. 
       
  1219 	//In case of recoding we goto the stop state.
       
  1220 	else if(!iRegisterARN && 
       
  1221         (aEvent.iErrorCode == KErrAccessDenied || aEvent.iErrorCode == KErrInUse ||aEvent.iErrorCode == KErrDied)
       
  1222         &&  (iDataSink->DataSinkType()==KUidMmfAudioOutput))
       
  1223         {
       
  1224         //setting iIsPreemptionPause to true so that PauseL can make differentiate it from normal pause.
       
  1225         iIsPreemptionPause = ETrue;
       
  1226 		TRAPD(err,PauseL());
       
  1227 		if(err != KErrNone)
       
  1228 		    {
       
  1229 			iDataPath->Stop();
       
  1230 			SetState( EStopped );
       
  1231 			iIsPreemptionPause = EFalse;
       
  1232 		    }
       
  1233         }
       
  1234 	else
       
  1235 		{
       
  1236 		if ( State()!= EStopped)
       
  1237 			{
       
  1238 			//datapath propogates stop to sink & source
       
  1239 			iDataPath->Stop();
       
  1240 			SetState( EStopped );
       
  1241 
       
  1242 			if(iStoppingRecording)
       
  1243 				{// an error has occurred while we were waiting for recording to stop, 
       
  1244 				 //must complete clients request
       
  1245 				iStoppingRecording = EFalse;
       
  1246 				iStoppingMessage->Complete(aEvent.iErrorCode);
       
  1247 				delete iStoppingMessage; iStoppingMessage=NULL;
       
  1248 				}
       
  1249 			}
       
  1250 		}
       
  1251 	if(!iIsPreemptionPause)
       
  1252 		{
       
  1253 		//should call ExecuteIntent to tell the DRM agent that playback has stopped 	
       
  1254 		if (aEvent.iEventType == KMMFEventCategoryPlaybackComplete) 
       
  1255 			{
       
  1256 			if ((iDataSink->DataSinkType() == KUidMmfAudioOutput)) 
       
  1257 				{		
       
  1258 				if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource)
       
  1259 					{
       
  1260 					CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
       
  1261 					file->ExecuteIntent(ContentAccess::EStop);
       
  1262 					}
       
  1263 				}
       
  1264 			}
       
  1265 		}
       
  1266 
       
  1267 	//now send event to client...
       
  1268 	TInt result = KErrNone;
       
  1269 	if(aEvent.iEventType == KMMFEventCategoryAudioResourceAvailable)
       
  1270 		{
       
  1271 		result = DoSendEventToClient(aEvent);	
       
  1272 		}
       
  1273 	else
       
  1274 		{
       
  1275 		result = DoSendEventToClient(controllerEvent);
       
  1276 		}
       
  1277 	
       
  1278 	//[ assert the invariant ]
       
  1279 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSendEventToClient));
       
  1280 
       
  1281 	return result;
       
  1282 	}
       
  1283 
       
  1284 
       
  1285 /**
       
  1286 * MapdSetVolumeL
       
  1287 *
       
  1288 *  @param aVolume
       
  1289 *
       
  1290 */
       
  1291 void CMMFAudioController::MapdSetVolumeL(TInt aVolume)
       
  1292 	{
       
  1293 	//[ assert the invariant ]
       
  1294 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetVolume));
       
  1295 
       
  1296 	// [  precondition is true for state 
       
  1297 	//    we can set the volume in any state ]
       
  1298 
       
  1299 	//[ precondition we have a data sink ]
       
  1300 	if (!iDataSink)
       
  1301 		User::Leave(KErrNotReady);
       
  1302 
       
  1303     // [ precondition that the data sink is an audio output ]
       
  1304 	// Make sure that iDataSink is an Audio Output
       
  1305 	if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
       
  1306 				User::Leave(KErrNotSupported);
       
  1307 
       
  1308 	MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
       
  1309 
       
  1310 	// [ assert the precondition that aVolume is in range ]
       
  1311 	TInt maxVolume = audioOutput->SoundDevice().MaxVolume();
       
  1312 	if( ( aVolume < 0 ) || ( aVolume > maxVolume ))
       
  1313 			User::Leave(KErrArgument);
       
  1314 	
       
  1315 	//[ set the volume on the device ]
       
  1316 	audioOutput->SoundDevice().SetVolume(aVolume);
       
  1317 
       
  1318 	//[ assert the post condition volume is equal to a volume]
       
  1319 	TInt soundVolume = 0;
       
  1320 	soundVolume = audioOutput->SoundDevice().Volume();
       
  1321 
       
  1322     __ASSERT_ALWAYS( ( soundVolume == aVolume), Panic(EPostConditionViolation));
       
  1323 
       
  1324 	//[ assert the invariant ]
       
  1325 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterVolumeSet));
       
  1326 	}
       
  1327 
       
  1328 /**
       
  1329 *
       
  1330 * MapdGetMaxVolumeL
       
  1331 *
       
  1332 * @param aMaxVolume
       
  1333 *
       
  1334 */
       
  1335 void CMMFAudioController::MapdGetMaxVolumeL(TInt& aMaxVolume)
       
  1336 	{
       
  1337 	// [ assert the invariant ]
       
  1338 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxVolume));
       
  1339 
       
  1340 	//[ we can get max volume in any state ]
       
  1341 
       
  1342 	// [ precondition we must have a data sink ]
       
  1343 	if (!iDataSink)
       
  1344 		User::Leave(KErrNotReady);
       
  1345 
       
  1346 	//[ precondition the sink must be an audio output]
       
  1347 	// Make sure that iDataSink is an Audio Output
       
  1348 	if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
       
  1349 			User::Leave(KErrNotSupported);
       
  1350 
       
  1351 	//[ get the volume from the device ]
       
  1352 	MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);	
       
  1353 	aMaxVolume = audioOutput->SoundDevice().MaxVolume();
       
  1354 
       
  1355 	//[ assert the invariant ]
       
  1356 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxVolume));
       
  1357 
       
  1358 	}
       
  1359 
       
  1360 
       
  1361 /**
       
  1362 *
       
  1363 * MapdGetVolumeL
       
  1364 *
       
  1365 * @param aVolume
       
  1366 *
       
  1367 */
       
  1368 void CMMFAudioController::MapdGetVolumeL(TInt& aVolume)
       
  1369 	{
       
  1370 	// [ assert the invariant ]
       
  1371 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetVolume));
       
  1372 
       
  1373 	//[  precondition that we have a data sink ]
       
  1374 	if (!iDataSink)
       
  1375 		User::Leave(KErrNotReady);
       
  1376 
       
  1377 	//[ precondition iDataSink is an Audio Output ]
       
  1378 	if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
       
  1379 		User::Leave(KErrNotSupported);
       
  1380 
       
  1381 	// [ get the volume ]
       
  1382 	MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
       
  1383 	aVolume = audioOutput->SoundDevice().Volume();
       
  1384 	
       
  1385 	// [ assert precondition that the volume is in range
       
  1386 	//     0.. aMaxVolume ]
       
  1387 	TInt aMaxVolume = audioOutput->SoundDevice().MaxVolume();
       
  1388 	__ASSERT_ALWAYS( (aVolume <= aMaxVolume), Panic(EBadState));
       
  1389 	__ASSERT_ALWAYS( (aVolume >= 0), Panic(EBadState));
       
  1390 
       
  1391 	// [ assert the invariant ]
       
  1392 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetVolume));
       
  1393 
       
  1394 	}
       
  1395 
       
  1396 /**
       
  1397 *
       
  1398 * MapdSetVolumeRampL
       
  1399 *
       
  1400 * @param aRampDuration
       
  1401 *
       
  1402 */
       
  1403 void CMMFAudioController::MapdSetVolumeRampL(const TTimeIntervalMicroSeconds& aRampDuration)
       
  1404 	{
       
  1405      // [ assert the invariant ]
       
  1406 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetVolumeRamp));
       
  1407 
       
  1408 	//[ precondition that we have a data sink ]
       
  1409 	if (!iDataSink)
       
  1410 		User::Leave(KErrNotReady);
       
  1411 
       
  1412 	// [ precondition iDataSink is an Audio Output ]
       
  1413 	if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
       
  1414 		User::Leave(KErrNotSupported);
       
  1415 
       
  1416 	//[ set the volume ramp ]
       
  1417 	MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
       
  1418 	audioOutput->SoundDevice().SetVolumeRamp(aRampDuration);
       
  1419 	
       
  1420 	//[ assert the invariant ]
       
  1421 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSetVolumeRamp));
       
  1422 		
       
  1423 	}
       
  1424 
       
  1425 
       
  1426 /**
       
  1427 *
       
  1428 * MapdSetBalanceL
       
  1429 *
       
  1430 * @param aBalance
       
  1431 *
       
  1432 */
       
  1433 void CMMFAudioController::MapdSetBalanceL(TInt aBalance)
       
  1434 	{
       
  1435 	//[ assert the invariant ]
       
  1436 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetBalance));
       
  1437 
       
  1438 	// [ precondition is that we have a data sink ]
       
  1439 	if (!iDataSink)
       
  1440 		User::Leave(KErrNotReady);
       
  1441 	
       
  1442 	// [ precondition is that the data sink is an audio output]
       
  1443 	if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
       
  1444 		User::Leave(KErrNotSupported);
       
  1445 	
       
  1446 	//[ get the audio output ]
       
  1447 	MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
       
  1448 
       
  1449 	// [ separate out left and right balance ]
       
  1450 	TInt left  = 0;
       
  1451 	TInt right = 0;
       
  1452 	CalculateLeftRightBalance( left, right, aBalance );
       
  1453 	
       
  1454 	//[ set the balance ]
       
  1455 	audioOutput->SoundDevice().SetPlayBalanceL(left, right); 
       
  1456 
       
  1457 	// [assert the post condition that the balance is set correctly]
       
  1458 	TInt rightBalance = 0;
       
  1459 	TInt leftBalance  = 0;
       
  1460 	audioOutput->SoundDevice().GetPlayBalanceL(leftBalance, rightBalance); 
       
  1461 
       
  1462 	//[ assert post condition holds]
       
  1463 	TBool postCondition = (( rightBalance == right) && ( leftBalance == left));
       
  1464 	__ASSERT_ALWAYS( postCondition, Panic( EPostConditionViolation ) );
       
  1465 
       
  1466 	//[ assert the invariant ]
       
  1467 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetBalance));
       
  1468 	}
       
  1469 
       
  1470 /**
       
  1471 * CalculateLeftRightBalance
       
  1472 * @internalTechnology
       
  1473 * @param aLeft
       
  1474 * @param aRight
       
  1475 * @param aBalance
       
  1476 * Preconditions:
       
  1477 * !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight)
       
  1478 * y = m x + c
       
  1479 * aLeft = m ( aBalance ) + c
       
  1480 * when aBalance = KMMFBalanceMaxLeft   aLeft = 100
       
  1481 * when aBalance = KMMFBalanceMaxRight  aLeft = 0
       
  1482 * 100 = m( KMMFBalanceMaxLeft ) + c
       
  1483 * 0   = m( KMMFBalanceMaxRight ) + c 
       
  1484 * c = -(KMMFBalanceMaxRight) m
       
  1485 * 100 = m(KMMFBalanceMaxLeft ) - m(KMMFBalanceMaxRight)
       
  1486 * m = 100/(KMMFBalanceMaxLeft - KMMFBalanceMaxRight )
       
  1487 * c = -(KMMFBalanceMaxRight) * 100 /(KMMFBalanceMaxLeft - KMMFBalanceMaxRight )
       
  1488 * aLeft = ( aBalance - KMMFBalanceMaxRight ) * 100 /( KMMFBalanceMaxLeft - KMMFBalanceMaxRight )
       
  1489 */
       
  1490 void CMMFAudioController::CalculateLeftRightBalance( TInt& aLeft, TInt& aRight, TInt aBalance ) const
       
  1491 	{
       
  1492 	// Check the balance is within limits & modify to min or max values if necessary
       
  1493 	if (aBalance < KMMFBalanceMaxLeft)
       
  1494 		aBalance = KMMFBalanceMaxLeft;
       
  1495 	if (aBalance > KMMFBalanceMaxRight)
       
  1496 		aBalance = KMMFBalanceMaxRight;
       
  1497 	
       
  1498 	//[ Now separate percentage balances out from aBalance ]
       
  1499 	 aLeft = (100 * (aBalance-KMMFBalanceMaxRight)) / (KMMFBalanceMaxLeft-KMMFBalanceMaxRight);
       
  1500      aRight = 100 - aLeft;
       
  1501 
       
  1502 	 //[ assert post condition that left and right are within range ]
       
  1503 	 __ASSERT_ALWAYS( ( (aLeft <= 100) && (aLeft >= 0) ), Panic(EPostConditionViolation));
       
  1504 	 __ASSERT_ALWAYS( ( (aRight <= 100) && (aRight >= 0) ), Panic(EPostConditionViolation));
       
  1505 	}
       
  1506 
       
  1507 
       
  1508 /**
       
  1509 * MapdGetBalanceL
       
  1510 * @param aBalance
       
  1511 *
       
  1512 */
       
  1513 void CMMFAudioController::MapdGetBalanceL(TInt& aBalance)
       
  1514 	{
       
  1515 	//[ assert the invariant ]
       
  1516 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetBalance));
       
  1517 
       
  1518 	//[ precondition that we have a sink]
       
  1519 	if (!iDataSink)
       
  1520 		User::Leave(KErrNotReady);
       
  1521 	
       
  1522 	// [ iDataSink is an Audio Output ]
       
  1523 	if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
       
  1524 		User::Leave(KErrNotSupported);
       
  1525 	
       
  1526 	// [ get the play balance ]
       
  1527 	MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
       
  1528 	TInt left = 50; // arbitrary values 
       
  1529 	TInt right = 50;
       
  1530 	audioOutput->SoundDevice().GetPlayBalanceL(left, right); 
       
  1531     CalculateBalance( aBalance, left, right );
       
  1532 
       
  1533 	//[ assert the invariant ]
       
  1534 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetBalance));
       
  1535 	}
       
  1536 
       
  1537 /**
       
  1538 * CalculateBalance
       
  1539 * @param aBalance
       
  1540 * @param aLeft
       
  1541 * @param aRight
       
  1542 *
       
  1543 * follows a simple straight line transformation
       
  1544 * y = m x + c
       
  1545 * m = (KMMFBalanceMaxLeft-KMMFBalanceMaxRight)/ 100 
       
  1546 * c = KMMFBalanceMaxRight
       
  1547 * by substitution
       
  1548 * when aLeft = 0
       
  1549 *   KMMFBalanceMaxRight = m * 0 + c
       
  1550 *   c = KMMFBalanceMaxRight
       
  1551 * when aLeft = 100
       
  1552 * KMMFBalanceMaxLeft = m * 100 + KMMFBalanceMaxRight
       
  1553 * m = ( KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) /100
       
  1554 */
       
  1555 void CMMFAudioController::CalculateBalance( TInt& aBalance, TInt aLeft, TInt aRight ) const
       
  1556 	{
       
  1557 	//[ assert pre conditions ]
       
  1558 	__ASSERT_ALWAYS( (( 0 <= aLeft) && ( 100 >= aLeft)), Panic( EBadArgument) );
       
  1559 	__ASSERT_ALWAYS( (( 0 <= aRight) && ( 100 >= aRight)), Panic( EBadArgument) );
       
  1560 	
       
  1561 	if ((aLeft > 0) && (aRight > 0))
       
  1562 		{
       
  1563 		__ASSERT_ALWAYS( (( aLeft + aRight ) == 100 ), Panic( EBadArgument ));
       
  1564 		aBalance = (aLeft * (KMMFBalanceMaxLeft-KMMFBalanceMaxRight))/100 + KMMFBalanceMaxRight;
       
  1565 		}
       
  1566 	else if ((aLeft == 0) && (aRight == 0))
       
  1567 		{
       
  1568 		aBalance = 0;
       
  1569 		}
       
  1570 	else if ((aLeft == 0) && (aRight > 0))
       
  1571 		{
       
  1572 		aBalance = 100;
       
  1573 		}
       
  1574 	else if ((aLeft > 0) && (aRight == 0))
       
  1575 		{
       
  1576 		aBalance = -100;
       
  1577 		}
       
  1578 
       
  1579     //[ assert post condition that aBalance is within limits ]
       
  1580 	__ASSERT_ALWAYS( !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight), Panic(EBadArgument));
       
  1581 	
       
  1582 	}
       
  1583 
       
  1584 /**
       
  1585 * MardSetGainL
       
  1586 * @param aGain
       
  1587 *
       
  1588 */
       
  1589 void CMMFAudioController::MardSetGainL(TInt aGain)
       
  1590 	{
       
  1591 	// [ assert the invariant ]
       
  1592 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetGain));
       
  1593 
       
  1594 	//[ precondition we are in the state stopped ]
       
  1595 	if(State() != EStopped)
       
  1596 		User::Leave(KErrNotReady);
       
  1597 	
       
  1598 	// [ assert the precondition that we have a data sink ]
       
  1599 	if (!iDataSource)
       
  1600 		User::Leave(KErrNotSupported);
       
  1601 
       
  1602 	//[ assert the precondition that the data sink is an audio input ]
       
  1603 	if (iDataSource->DataSourceType() != KUidMmfAudioInput)
       
  1604 		User::Leave(KErrNotReady);
       
  1605 
       
  1606 	// Set gain of sound device
       
  1607 	MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
       
  1608 	audioInput->SoundDevice().SetGain(aGain);
       
  1609 	
       
  1610 	//[ assert the invariant ]
       
  1611 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGainSet));
       
  1612 
       
  1613 	}
       
  1614 		
       
  1615 /**
       
  1616 * MardGetMaxGainL
       
  1617 * @param aMaxGain
       
  1618 *
       
  1619 */
       
  1620 void CMMFAudioController::MardGetMaxGainL(TInt& aMaxGain)
       
  1621 	{
       
  1622 	// [ assert the invariant ]
       
  1623 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxGain));
       
  1624 
       
  1625 	// [ assert the precondition that we have a source ]
       
  1626 	if (!iDataSource)
       
  1627 		User::Leave(KErrNotReady);
       
  1628 
       
  1629 	//[ assert the precondition that iDataSink is an Audio Input]
       
  1630 	if (iDataSource->DataSourceType() != KUidMmfAudioInput)
       
  1631 		User::Leave(KErrNotSupported);
       
  1632 
       
  1633 	MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
       
  1634 	aMaxGain = audioInput->SoundDevice().MaxGain();
       
  1635 
       
  1636 	//[ assert the invariant ]
       
  1637 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxGain));
       
  1638 	
       
  1639 	}
       
  1640 
       
  1641 /**
       
  1642 * MardGetGainL
       
  1643 * @param aGain
       
  1644 *
       
  1645 */
       
  1646 void CMMFAudioController::MardGetGainL(TInt& aGain)
       
  1647 	{
       
  1648 	//[ assert the invariant ]
       
  1649 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetGain));
       
  1650 
       
  1651 	// [ assert the precondition that we have a sink ]
       
  1652 	if (!iDataSource)
       
  1653 		User::Leave(KErrNotReady);
       
  1654 
       
  1655 	// [ assert the precondition that we have an audio input sink]
       
  1656 	if (iDataSource->DataSourceType() != KUidMmfAudioInput)
       
  1657 			User::Leave(KErrNotSupported);
       
  1658 
       
  1659 	MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
       
  1660 	aGain = audioInput->SoundDevice().Gain();
       
  1661 		
       
  1662 	//[ assert the invariant ]
       
  1663 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetGain));
       
  1664 	}
       
  1665 
       
  1666 
       
  1667 /**
       
  1668  *
       
  1669  * MardSetBalanceL
       
  1670  *   @param aBalance
       
  1671  */
       
  1672 void CMMFAudioController::MardSetBalanceL(TInt aBalance)
       
  1673 	{
       
  1674 	// [ assert the invaraiant ]
       
  1675 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetGain));
       
  1676 
       
  1677 	// [ precondition is that we have a data source ]
       
  1678 	if (!iDataSource)
       
  1679 		{
       
  1680 		User::Leave(KErrNotReady);
       
  1681 		}
       
  1682 	
       
  1683 	// [ precondition is that the balance is in range ]
       
  1684 	// Make sure aBalance is in the range -100 <-> 100
       
  1685 	if (aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight)
       
  1686 		User::Leave(KErrArgument);
       
  1687 	
       
  1688 	// [ precondition is that the data sink is an audio output]
       
  1689 	if (iDataSource->DataSourceType() != KUidMmfAudioInput)
       
  1690 		User::Leave(KErrNotSupported);
       
  1691 	
       
  1692     
       
  1693 	//[ get the audio output ]
       
  1694 	MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
       
  1695 
       
  1696 	// [ separate out left and right balance ]
       
  1697 	TInt left  = 0;
       
  1698 	TInt right = 0;
       
  1699 	CalculateLeftRightBalance( left, right, aBalance );
       
  1700 	
       
  1701 	//[ set the balance ]
       
  1702 	audioInput->SoundDevice().SetRecordBalanceL(left, right); 
       
  1703 
       
  1704 	// [assert the post condition that the balance is set correctly]
       
  1705 	TInt rightBalance = 0;
       
  1706 	TInt leftBalance  = 0;
       
  1707 	audioInput->SoundDevice().GetRecordBalanceL(leftBalance, rightBalance); 
       
  1708 
       
  1709 	//[ assert post condition holds]
       
  1710 	TBool postCondition = (( rightBalance == right) && ( leftBalance == left));
       
  1711 	__ASSERT_ALWAYS( postCondition, Panic( EPostConditionViolation ) );
       
  1712 
       
  1713 	//[ assert the invariant ]
       
  1714 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGainSet));
       
  1715 	
       
  1716 	}
       
  1717 
       
  1718 /**
       
  1719 *
       
  1720 * MardGetBalanceL
       
  1721 * @param aBalance
       
  1722 *
       
  1723 */
       
  1724 void CMMFAudioController::MardGetBalanceL(TInt& aBalance)
       
  1725 	{
       
  1726 	//[ assert the invariant ]
       
  1727 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetBalance));
       
  1728 
       
  1729 	// [ precondition is that we have a data source ]
       
  1730 	if (!iDataSource)
       
  1731 		{
       
  1732 		User::Leave(KErrNotReady);
       
  1733 		}		
       
  1734 	
       
  1735 	// [ iDataSink is an Audio Output ]
       
  1736 	if (iDataSource->DataSourceType() != KUidMmfAudioInput)
       
  1737 		User::Leave(KErrNotSupported);
       
  1738 	
       
  1739 	// [ get the play balance ]
       
  1740 	MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
       
  1741 	TInt left = 50; // arbitrary values 
       
  1742 	TInt right = 50;
       
  1743 	audioInput->SoundDevice().GetRecordBalanceL(left, right); 
       
  1744     CalculateBalance( aBalance, left, right );
       
  1745 
       
  1746 	//[ assert the invariant ]
       
  1747 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetBalance));
       
  1748 
       
  1749 	}
       
  1750 
       
  1751 /**
       
  1752 * MapcSetPlaybackWindowL
       
  1753 * @param aStart
       
  1754 * @param aEnd
       
  1755 *
       
  1756 */
       
  1757 void CMMFAudioController::MapcSetPlaybackWindowL(const TTimeIntervalMicroSeconds& aStart, const TTimeIntervalMicroSeconds& aEnd)
       
  1758 	{
       
  1759 	iDataPath->SetPlayWindowL(aStart, aEnd);
       
  1760 	}
       
  1761 
       
  1762 /**
       
  1763 * MapcDeletePlaybackWindowL
       
  1764 */
       
  1765 void CMMFAudioController::MapcDeletePlaybackWindowL()
       
  1766 	{
       
  1767 	iDataPath->ClearPlayWindowL();
       
  1768 	}
       
  1769 
       
  1770 
       
  1771 /**
       
  1772 * MapcSetRepeatsL
       
  1773 * @param aRepeatNumberOfTimes
       
  1774 * @param aTrailingSilence
       
  1775 *
       
  1776 */
       
  1777 
       
  1778 TInt CMMFAudioController::MapcSetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence)
       
  1779 	{
       
  1780 	TInt err = KErrNone;
       
  1781 	if (!iDataSink)
       
  1782 		{
       
  1783 		err = KErrNotReady;
       
  1784 		}		
       
  1785 	else if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
       
  1786 		{
       
  1787 		err = KErrNotSupported;
       
  1788 		}
       
  1789 	else
       
  1790 		{
       
  1791 		MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
       
  1792 		if(audioOutput->SoundDevice().QueryIgnoresUnderflow())
       
  1793 			{
       
  1794 			iDataPath->SetRepeats(aRepeatNumberOfTimes,aTrailingSilence);
       
  1795 			iDataPath->SetDrmProperties(iDataSource, &iDisableAutoIntent);
       
  1796 			}
       
  1797 		else
       
  1798 			{
       
  1799 			err = KErrNotSupported;
       
  1800 			}
       
  1801 		}
       
  1802 	return err;
       
  1803 	}
       
  1804 	
       
  1805 
       
  1806 /**
       
  1807 * MapcGetLoadingProgressL
       
  1808 */
       
  1809 void CMMFAudioController::MapcGetLoadingProgressL(TInt& /*aPercentageComplete*/)
       
  1810 	{
       
  1811 	User::Leave(KErrNotSupported);
       
  1812 	}
       
  1813 
       
  1814 
       
  1815 /**
       
  1816 * MarcGetRecordTimeAvailableL
       
  1817 * @param aTime
       
  1818 *
       
  1819 */
       
  1820 void CMMFAudioController::MarcGetRecordTimeAvailableL(TTimeIntervalMicroSeconds& aTime)
       
  1821 	{
       
  1822 	//[ assert the invariant ]
       
  1823 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetRecordTimeAvailable));
       
  1824 	
       
  1825 	//[ assert the precondition ( in a friendly way for this api 
       
  1826 	// that we minimally have a data sink ]
       
  1827 	if( !iDataSink )
       
  1828 		User::Leave( KErrNotReady );
       
  1829 	
       
  1830 	// Use the FormatEncode to get the bytes per second and the sink (clip) to get the bytes available
       
  1831 	// return the calculated value.
       
  1832 	if	((iDataSink->DataSinkType() != KUidMmfFileSink) && (iDataSink->DataSinkType() != KUidMmfDescriptorSink))
       
  1833 		User::Leave(KErrNotSupported) ;
       
  1834 	
       
  1835 	// [ max file size ]
       
  1836 	//[ pre condition is that we have a sink ]
       
  1837    	
       
  1838 	// In order to get the record time available we need to take into consideration
       
  1839 	// that there may be a max file size ]
       
  1840 	TInt64 bytesFree       = STATIC_CAST(CMMFClip*, iDataSink)->BytesFree() ;
       
  1841 	TInt64 bytesPerSecond  = TInt64(0);
       
  1842 	//[ set default time available ]
       
  1843 	       aTime           = TTimeIntervalMicroSeconds( 0 ) ; // just return zero
       
  1844 
       
  1845 	if( iSinkFormat )
       
  1846 		{
       
  1847 		TInt maxFileSize = STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->MaximumClipSize();
       
  1848 		//[ if maxFileSize > 0 we need to limit the bytes free to this value - size ]
       
  1849 		if( maxFileSize > 0 )
       
  1850 			{
       
  1851 			// [ strangely the size of data written is a TInt ]
       
  1852 			TInt fileSize = STATIC_CAST(CMMFClip*, iDataSink)->Size();
       
  1853 			bytesFree = maxFileSize - fileSize;
       
  1854 			// [ note it can occur that the fileSize id greater than the MaxFileSize
       
  1855 			//  due to someone setting the max file size on an existing file ]
       
  1856 			if( bytesFree < 0 ) bytesFree = 0;
       
  1857 			__ASSERT_DEBUG( ( bytesFree <= maxFileSize), Panic(	ENoMemoryToRecord) );
       
  1858 			}		
       
  1859 		bytesPerSecond = STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->BytesPerSecond() ;
       
  1860 		}
       
  1861 
       
  1862 	//[ now lets perform the calculation of time available ]
       
  1863 	if ( bytesPerSecond != TInt64(0) )
       
  1864 		{
       
  1865 		aTime = TTimeIntervalMicroSeconds( bytesFree * KOneSecondInMicroSeconds / bytesPerSecond ) ;
       
  1866 		}
       
  1867 	
       
  1868 	//[ assert the invariant ]
       
  1869 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetRecordTimeAvailable));
       
  1870 	}
       
  1871 
       
  1872 /**
       
  1873 * MarcSetMaxDurationL
       
  1874 * @param aMaxDuration
       
  1875 */
       
  1876 void CMMFAudioController::MarcSetMaxDurationL(const TTimeIntervalMicroSeconds& )
       
  1877 	{
       
  1878 	//[ this method is deprecated and no longer supported ]
       
  1879 	User::Leave(KErrNotSupported);
       
  1880 	}
       
  1881 
       
  1882 /**
       
  1883 * MarcSetMaxFileSizeL
       
  1884 * @param aFileSize
       
  1885 * @precondition 
       
  1886 * The argument aFileSize must be greater than -1
       
  1887 * zero is used as a sentinel value which means that the file
       
  1888 * can grow without limit
       
  1889 */
       
  1890 void CMMFAudioController::MarcSetMaxFileSizeL(TInt aFileSize )
       
  1891 	{
       
  1892 	//[ assert the invariant ]
       
  1893 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxFileSize));
       
  1894 
       
  1895 	//[ assert the state is not playing since this opens open 
       
  1896 	// nefarious posibilities
       
  1897 	if(State() == EPlaying )
       
  1898 		User::Leave( KErrNotReady );
       
  1899 	
       
  1900 	//[ assert we have a sink format ]
       
  1901 	if( !iSinkFormat )
       
  1902 		User::Leave( KErrNotReady );
       
  1903 
       
  1904 	//[ assert file size > -2, as a basic sanity filter
       
  1905 	// 0 is the sentinel value which allows a file to grow
       
  1906 	// as needed.]
       
  1907 	// [We use -1 to reset the value set earlier.]
       
  1908 	if( aFileSize < -1 )
       
  1909 		{
       
  1910 		User::Leave( KErrArgument );
       
  1911 		}
       
  1912 
       
  1913     //[ pre condition is that we have a sink ]
       
  1914     STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->SetMaximumClipSizeL( aFileSize );
       
  1915 
       
  1916 	// [ assert the post condition ]
       
  1917 	// [since we have no means of querying the value
       
  1918 	// we have to assume all went well for now or we left]
       
  1919 
       
  1920 	//[ assert the invariant ]
       
  1921 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxFileSize));
       
  1922 	}
       
  1923 
       
  1924 /**
       
  1925 * MarcCropL
       
  1926 * @param aToEnd
       
  1927 */
       
  1928 void CMMFAudioController::MarcCropL(TBool aToEnd)
       
  1929 	{
       
  1930 	//[ assert the invariant ]
       
  1931 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToCrop));
       
  1932 
       
  1933 	//[ precondition there is a sink format]
       
  1934 	if (!iSinkFormat)
       
  1935 		User::Leave(KErrNotSupported);
       
  1936 
       
  1937 	iSinkFormat->CropL( PositionL(), aToEnd );
       
  1938 
       
  1939 	//[ assert the invariant ]
       
  1940 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterCrop));
       
  1941 	}
       
  1942 
       
  1943 /**
       
  1944 * MarcAddMetaDataEntryL
       
  1945 * @param aNewEntry
       
  1946 */
       
  1947 void CMMFAudioController::MarcAddMetaDataEntryL(const CMMFMetaDataEntry& aNewEntry )
       
  1948 	{
       
  1949 	//[ assert the invariant ]
       
  1950 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToAddMetaDataEntry));
       
  1951 
       
  1952 	//[ precondition the format exists ]
       
  1953 	if( !iSinkFormat )
       
  1954 		User::Leave(KErrNotSupported);
       
  1955 
       
  1956 	//[ Add the meta data entry ]
       
  1957 	iSinkFormat->AddMetaDataEntryL( aNewEntry );
       
  1958 
       
  1959 	//[ assert the invariant ]
       
  1960 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterAddMetaDataEntry));
       
  1961 
       
  1962 	}
       
  1963 
       
  1964 /**
       
  1965 * MarcRemoveMetaDataEntryL
       
  1966 * @param aIndex
       
  1967 */
       
  1968 void CMMFAudioController::MarcRemoveMetaDataEntryL(TInt aIndex)
       
  1969 	{
       
  1970 	//[ assert the invariant ]
       
  1971 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToRemoveMetaDataEntry));
       
  1972 
       
  1973 	//[ precondition that we are in the primed state ]
       
  1974 	if( State() != EPrimed)
       
  1975 		User::Leave(KErrNotReady);
       
  1976 
       
  1977     //[ precondition the format exists ]
       
  1978 	if( !iSinkFormat )
       
  1979 		User::Leave(KErrNotSupported);
       
  1980 
       
  1981 	//[ remove the meta data entry ]
       
  1982 	iSinkFormat->RemoveMetaDataEntry( aIndex );
       
  1983 
       
  1984 	//[ assert the invariant ]
       
  1985 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterRemoveMetaDataEntry));
       
  1986 
       
  1987 	}
       
  1988 
       
  1989 /**
       
  1990 * MarcReplaceMetaDataEntryL
       
  1991 * @param aIndex
       
  1992 * @param aNewEntry
       
  1993 */
       
  1994 void CMMFAudioController::MarcReplaceMetaDataEntryL(TInt aIndex, const CMMFMetaDataEntry& aNewEntry)
       
  1995 	{
       
  1996 	//[ assert the invariant ]
       
  1997 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToReplaceMetaDataEntry));
       
  1998 
       
  1999 	//[ precondition that we are in the primed state ]
       
  2000 	if( State() != EPrimed)
       
  2001 		User::Leave(KErrNotReady);
       
  2002 
       
  2003    	//[ precondition the format exists ]
       
  2004 	if( !iSinkFormat )
       
  2005 		User::Leave(KErrNotSupported);
       
  2006 
       
  2007 	//[ replace meta data entry ]
       
  2008 	iSinkFormat->ReplaceMetaDataEntryL( aIndex, aNewEntry );
       
  2009 
       
  2010 	//[ assert the invariant ]
       
  2011 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterReplaceMetaDataEntry));
       
  2012 
       
  2013 	}
       
  2014 
       
  2015 /**
       
  2016 * MacSetSourceSampleRateL
       
  2017 * @param aSampleRate
       
  2018 */
       
  2019 void CMMFAudioController::MacSetSourceSampleRateL(TUint aSampleRate)
       
  2020 	{
       
  2021 	// [ assert the invariant ]
       
  2022 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceSampleRate));
       
  2023 	
       
  2024 	// [ assert the precondition we are stopped ]
       
  2025 	if( State() != EStopped )
       
  2026 		User::Leave(KErrNotReady);
       
  2027 
       
  2028 
       
  2029 	if (iSourceFormat)
       
  2030 		{//only applicable to formats
       
  2031 		// don't throw an error if the clip already exists with a different sample rate
       
  2032 		TInt error = iSourceFormat->SetSampleRate(aSampleRate);
       
  2033 		if (error != KErrNone && error != KErrAlreadyExists)
       
  2034 			User::Leave(error);
       
  2035 		}
       
  2036 	else 
       
  2037 		{//during recording, sample rate cannot be set directly on the datasource. It is set via NegotiateL
       
  2038 		User::Leave(KErrNotSupported);
       
  2039 		}
       
  2040 	
       
  2041 	// [assert the post condition ]
       
  2042 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceSampleRate));
       
  2043 
       
  2044 	}
       
  2045 
       
  2046 /**
       
  2047 * MacSetSourceNumChannelsL
       
  2048 * @param aNumChannels
       
  2049 */
       
  2050 void CMMFAudioController::MacSetSourceNumChannelsL(TUint aNumChannels)
       
  2051 	{
       
  2052 	// [ assert the invariant ]
       
  2053 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceNumChannels));
       
  2054   
       
  2055 	// [assert the precondition that we are stopped ]
       
  2056 	if( State() != EStopped )
       
  2057 		User::Leave(KErrNotReady);
       
  2058 
       
  2059 	if (iSourceFormat)
       
  2060 		{//only applicable to formats
       
  2061 		// don't throw an error if the clip already exists with a different number of channels
       
  2062 		TInt error = iSourceFormat->SetNumChannels(aNumChannels);
       
  2063 		if (error != KErrNone && error != KErrAlreadyExists)
       
  2064 			User::Leave(error);
       
  2065 		}
       
  2066 	else 
       
  2067 		{//during recording, channels cannot be set directly on the datasource. It is set via NegotiateL
       
  2068 		User::Leave(KErrNotSupported);
       
  2069 		}
       
  2070 	
       
  2071 	// [ assert the invariant ]
       
  2072 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceNumChannels)); 
       
  2073 
       
  2074 	}
       
  2075 
       
  2076 /**
       
  2077 * MacSetSourceFormatL
       
  2078 * @param aFormatUid
       
  2079 *
       
  2080 */
       
  2081 void CMMFAudioController::MacSetSourceFormatL(TUid aFormatUid)
       
  2082 	{
       
  2083      //[ assert the invaraint ]
       
  2084 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceFormat)); 
       
  2085 	
       
  2086 	// [ precondition that the controller is stopped ]
       
  2087     if( State() != EStopped )
       
  2088 		User::Leave( KErrNotReady );
       
  2089 
       
  2090 	//[ precondition that the data source exists]
       
  2091 	if (!iDataSource)
       
  2092 		User::Leave(KErrNotReady);
       
  2093 	
       
  2094 	//[ precondition that we need a format ]
       
  2095 	if( !SourceFormatRequired( *iDataSource ) )
       
  2096 		User::Leave(KErrNotSupported); //cant set source format if source isn't a clip
       
  2097 
       
  2098 	//[ if the format exists and the uid of the requested
       
  2099 	//	format is the same as the existing format then simply 
       
  2100 	// return otherwise create a new format ]
       
  2101 	if( !((iSourceFormat) && ( iSourceFormat->ImplementationUid() == aFormatUid)))
       
  2102 		{
       
  2103 		// [ delete the old format regardless ]
       
  2104 		delete iSourceFormat;
       
  2105 		iSourceFormat = NULL;
       
  2106 		iSourceFormat = CMMFFormatDecode::NewL(aFormatUid, iDataSource);
       
  2107 		}
       
  2108 
       
  2109 	//[ assert the invariant ]
       
  2110 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceFormat)); 
       
  2111 
       
  2112 	//[ assert the post condition that a source format has been constructed ]
       
  2113 	__ASSERT_ALWAYS( (iSourceFormat != NULL), Panic( EPostConditionViolation ));
       
  2114 	}
       
  2115 
       
  2116 /**
       
  2117 * MacSetSinkSampleRateL
       
  2118 * @param aSampleRate
       
  2119 */
       
  2120 void CMMFAudioController::MacSetSinkSampleRateL(TUint aSampleRate)
       
  2121 	{
       
  2122 	//[ assert the invariant ]
       
  2123 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkSampleRate));
       
  2124 
       
  2125 	// [ assert the precondition that we are stopped ]
       
  2126 	if (State() != EStopped )
       
  2127 		User::Leave(KErrNotReady);
       
  2128 
       
  2129 	if (iSinkFormat)
       
  2130 		{//only applicable to formats
       
  2131 		// don't throw an error if the clip already exists with a different sample rate
       
  2132 		TInt error = iSinkFormat->SetSampleRate(aSampleRate);
       
  2133 		if (error != KErrNone && error != KErrAlreadyExists)
       
  2134 			User::Leave(error);
       
  2135 		}
       
  2136 	else 
       
  2137 		{//during playing, sample rate cannot be set directly on the datasink. It is set via NegotiateL
       
  2138 		User::Leave(KErrNotSupported);
       
  2139 		}
       
  2140 
       
  2141 	//[ assert the invariant ]
       
  2142 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkSampleRate));
       
  2143 	}
       
  2144 
       
  2145 /**
       
  2146 * MacSetSinkNumChannelsL
       
  2147 * @param aNumChannels
       
  2148 *
       
  2149 */
       
  2150 void CMMFAudioController::MacSetSinkNumChannelsL(TUint aNumChannels)
       
  2151 	{
       
  2152 	//[ assert the invariant ]
       
  2153 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkNumChannels));
       
  2154 
       
  2155 	// [ assert the precondition that we are stopped ]
       
  2156 	if (State() != EStopped )
       
  2157 		User::Leave(KErrNotReady);
       
  2158 
       
  2159 	if (iSinkFormat)
       
  2160 		{//only applicable to formats
       
  2161 		// don't throw an error if the clip already exists with a different number of channels
       
  2162 		TInt error = iSinkFormat->SetNumChannels(aNumChannels);
       
  2163 		if (error != KErrNone && error != KErrAlreadyExists)
       
  2164 			User::Leave(error);
       
  2165 		}
       
  2166 	else 
       
  2167 		{//during playing, channels cannot be set directly on the datasink. It is set via NegotiateL
       
  2168 		User::Leave(KErrNotSupported);
       
  2169 		}
       
  2170 
       
  2171 	// [assert the invariant ]
       
  2172 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkNumChannels));
       
  2173 
       
  2174 	}
       
  2175 
       
  2176 /**
       
  2177 * MacSetSinkFormatL 
       
  2178 * @param aFormatUid
       
  2179 *
       
  2180 */
       
  2181 void CMMFAudioController::MacSetSinkFormatL(TUid aFormatUid)
       
  2182 	{
       
  2183     //[ assert the invariant ]
       
  2184 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkFormat));
       
  2185 
       
  2186 	// [ precondition that the controller is stopped ]
       
  2187     if( State() != EStopped )
       
  2188 		User::Leave( KErrNotReady );
       
  2189 
       
  2190 	//[ precondition that the data sink exists]
       
  2191 	if (!iDataSink)
       
  2192 		User::Leave(KErrNotReady);
       
  2193 
       
  2194 	//[ precondition that we need a format ]
       
  2195 	if (!SinkFormatRequired( *iDataSink))
       
  2196 		User::Leave(KErrNotSupported);
       
  2197 
       
  2198 	//[ if the format exists and the uid of the requested
       
  2199 	//	format is the same as the existing format then simply 
       
  2200 	// return ]
       
  2201 	if( !((iSinkFormat) && ( iSinkFormat->ImplementationUid() == aFormatUid)))
       
  2202 		{
       
  2203 		// [ delete the old format regardless ]
       
  2204 		delete iSinkFormat;
       
  2205 		iSinkFormat = NULL;
       
  2206 		iSinkFormat = CMMFFormatEncode::NewL(aFormatUid, iDataSink);
       
  2207 		}
       
  2208 
       
  2209 	//[ assert the invariant ]
       
  2210 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkFormat));
       
  2211 
       
  2212 	//[ assert the post condition that a sink format has been constructed ]
       
  2213 	__ASSERT_ALWAYS( (iSinkFormat != NULL), Panic( EPostConditionViolation ));
       
  2214 	}
       
  2215 
       
  2216 
       
  2217 /**
       
  2218 * MacSetCodecL
       
  2219 * @param aSourceDataType
       
  2220 * @param aSinkDataType
       
  2221 *
       
  2222 */
       
  2223 void CMMFAudioController::MacSetCodecL(TFourCC aSourceDataType, TFourCC aSinkDataType)
       
  2224 	{
       
  2225 	//[ assert the invariant ]
       
  2226 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetCodec));
       
  2227 
       
  2228 	//[ assert the precondition ]
       
  2229 	if(State() != EStopped)
       
  2230 		User::Leave(KErrNotReady);
       
  2231 	
       
  2232 	//pre condition that we have a source format or sink format
       
  2233 	if (!iSourceFormat && !iSinkFormat)
       
  2234 		{
       
  2235 		User::Leave(KErrNotSupported);
       
  2236 		}
       
  2237 	//don't set codec directly  -just set source & sink fourCC codes
       
  2238 	//[  ]
       
  2239 	TInt error(KErrNone);
       
  2240 	if ((iSinkFormat)&&(aSinkDataType != KMMFFourCCCodeNULL))
       
  2241 		{
       
  2242 		error = iSinkFormat->SetSinkDataTypeCode(aSinkDataType,iMediaId);
       
  2243 		}
       
  2244 	if ((iSourceFormat)&&(!error)&&(aSourceDataType != KMMFFourCCCodeNULL))
       
  2245 		{
       
  2246 		error = iSourceFormat->SetSourceDataTypeCode(aSourceDataType,iMediaId);
       
  2247 		}
       
  2248 	
       
  2249 	//[ leave if we are not ready or there was an error ]
       
  2250 	User::LeaveIfError(error);
       
  2251 
       
  2252 	//[ assert the invariant ]
       
  2253 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSetCodec));
       
  2254 	}
       
  2255 
       
  2256 /**
       
  2257 * MacSetSourceBitRateL
       
  2258 * @param "TUint"
       
  2259 * Sets the source bit rate
       
  2260 *
       
  2261 */
       
  2262 void CMMFAudioController::MacSetSourceBitRateL(TUint aBitRate)
       
  2263 	{
       
  2264 	//[ assert the invariant ]
       
  2265 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetSourceBitRate));
       
  2266 
       
  2267 	//[ assert the precondition ]
       
  2268 	if(State() != EStopped)
       
  2269 		User::Leave(KErrNotReady);
       
  2270 
       
  2271 	//[ pre condition  that we have a source format]
       
  2272 	if (!iSourceFormat)
       
  2273 		User::Leave(KErrNotSupported);
       
  2274 
       
  2275 	//only applicable to formats
       
  2276 	User::LeaveIfError(iSourceFormat->SetBitRate(aBitRate));
       
  2277 
       
  2278 	//[ assert the set bit rate is the bit rate ]
       
  2279 	__ASSERT_ALWAYS( (aBitRate == iSourceFormat->BitRate()), Panic( EPostConditionViolation ));
       
  2280 		
       
  2281 	//[ assert the invariant ]
       
  2282 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceBitRate));
       
  2283 	}
       
  2284 
       
  2285 
       
  2286 /**
       
  2287 *
       
  2288 * MacSetSourceDataTypeL
       
  2289 * @param "TFourCC"
       
  2290 *
       
  2291 */
       
  2292 void CMMFAudioController::MacSetSourceDataTypeL(TFourCC aDataType)
       
  2293 	{
       
  2294 	//pre condition we have a source format
       
  2295 	if (!iSourceFormat)
       
  2296 		{
       
  2297 		User::Leave(KErrNotSupported);
       
  2298 		}
       
  2299 		
       
  2300 	MacSetCodecL(aDataType, KMMFFourCCCodeNULL);
       
  2301 	}
       
  2302 
       
  2303 /**
       
  2304 *
       
  2305 * MacSetSinkBitRateL
       
  2306 * @param "TUint"
       
  2307 *
       
  2308 */
       
  2309 void CMMFAudioController::MacSetSinkBitRateL(TUint aRate)
       
  2310 	{
       
  2311 	//[ assert the invariant ]
       
  2312 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkBitRate));
       
  2313 
       
  2314     // [ assert we are stopped ]
       
  2315 	if( State() != EStopped)
       
  2316 		User::Leave( KErrNotReady );
       
  2317 
       
  2318 	//[ pre condition we have a sink format ]
       
  2319 	if (!iSinkFormat)
       
  2320 		User::Leave(KErrNotSupported);
       
  2321 
       
  2322 	//only applicable to formats
       
  2323 	User::LeaveIfError(iSinkFormat->SetBitRate(aRate));
       
  2324 
       
  2325 	//[ assert the set bit rate is the bit rate ]
       
  2326 	__ASSERT_ALWAYS( (aRate == iSinkFormat->BitRate()), Panic( ESetRateIsNotSameAsBitRate));
       
  2327 
       
  2328 	//[ assert the invariant ]
       
  2329 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkBitRate));
       
  2330 	}
       
  2331 
       
  2332 /**
       
  2333 *
       
  2334 * MacSetSinkDataTypeL
       
  2335 * @param "TFourCC"
       
  2336 *
       
  2337 */
       
  2338 void CMMFAudioController::MacSetSinkDataTypeL(TFourCC aDataType)
       
  2339 	{
       
  2340 	//precondition is that we have a sink format
       
  2341 	if (!iSinkFormat)
       
  2342 		{
       
  2343 		User::Leave(KErrNotSupported);
       
  2344 		}
       
  2345 	
       
  2346 	MacSetCodecL(KMMFFourCCCodeNULL, aDataType);
       
  2347 	}
       
  2348 
       
  2349 /**
       
  2350 *
       
  2351 * MacGetSourceSampleRateL
       
  2352 * @param "TUint"
       
  2353 * 
       
  2354 */
       
  2355 void CMMFAudioController::MacGetSourceSampleRateL(TUint& aRate)
       
  2356 	{
       
  2357 	//[ assert the invariant ]
       
  2358 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceSampleRate));
       
  2359 
       
  2360 	//precondition is that we have a source format
       
  2361 	if (!iSourceFormat)
       
  2362 		{
       
  2363 		User::Leave(KErrNotSupported);
       
  2364 		}
       
  2365 		
       
  2366 	aRate = iSourceFormat->SampleRate();
       
  2367 
       
  2368 	//[ assert the invariant ]
       
  2369 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceSampleRate));
       
  2370 	}
       
  2371 
       
  2372 /**
       
  2373 *
       
  2374 * MacGetSourceBitRateL
       
  2375 * @param "TUint"
       
  2376 *
       
  2377 */
       
  2378 void CMMFAudioController::MacGetSourceBitRateL(TUint& aRate)
       
  2379 	{
       
  2380 	//[ assert the invariant ]
       
  2381 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceBitRate));
       
  2382 
       
  2383 	// Can only query formats for bit rate - devsound doesn't do bit rates.
       
  2384 	if (!iSourceFormat)
       
  2385 		User::Leave(KErrNotSupported);
       
  2386 
       
  2387 	aRate = iSourceFormat->BitRate();
       
  2388 	
       
  2389 	//[ assert the invariant ]
       
  2390 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceBitRate));
       
  2391 	
       
  2392 	}
       
  2393 
       
  2394 /**
       
  2395 *
       
  2396 * MacGetSourceNumChannelsL
       
  2397 * @param "TUint&"
       
  2398 *
       
  2399 */
       
  2400 void CMMFAudioController::MacGetSourceNumChannelsL(TUint& aNumChannels)
       
  2401 	{
       
  2402 	//[ assert the invariant ]
       
  2403 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceNumChannels));
       
  2404 
       
  2405 	//precondition is that we have a source format
       
  2406 	if (!iSourceFormat)
       
  2407 		{
       
  2408 		User::Leave(KErrNotSupported);
       
  2409 		}
       
  2410 		
       
  2411 	aNumChannels = iSourceFormat->NumChannels();
       
  2412 		
       
  2413 	//[ assert the invariant ]
       
  2414 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceNumChannels));
       
  2415 
       
  2416 	}
       
  2417 
       
  2418 /**
       
  2419 *
       
  2420 * MacGetSourceFormatL
       
  2421 * @param "TUid"
       
  2422 */
       
  2423 void CMMFAudioController::MacGetSourceFormatL(TUid& aFormat)
       
  2424 	{
       
  2425 	//[ assert the invariant ]
       
  2426 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceFormat));
       
  2427 
       
  2428 	//[ precondition we have a format ]
       
  2429 	if (!iSourceFormat)
       
  2430 		User::Leave(KErrNotSupported);
       
  2431 
       
  2432 	// [ get the source format uid ]
       
  2433 	aFormat = iSourceFormat->ImplementationUid();
       
  2434 
       
  2435 	//[ assert the invariant ]
       
  2436 	__ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceFormat));
       
  2437 	
       
  2438 	}
       
  2439 
       
  2440 /**
       
  2441 *
       
  2442 * MacGetSourceDataTypeL
       
  2443 * @param "TFourCC&"
       
  2444 *
       
  2445 */
       
  2446 void CMMFAudioController::MacGetSourceDataTypeL(TFourCC& aDataType)
       
  2447 	{
       
  2448 	//precondition is that we have a source format
       
  2449 	if (!iSourceFormat)
       
  2450 		{
       
  2451 		User::Leave(KErrNotSupported);
       
  2452 		}
       
  2453 	
       
  2454 	aDataType = iSourceFormat->SourceDataTypeCode(TMediaId(KUidMediaTypeAudio));
       
  2455 	}
       
  2456 
       
  2457 /**
       
  2458 *
       
  2459 * MacGetSinkSampleRateL
       
  2460 * @param "TUint&"
       
  2461 *
       
  2462 */
       
  2463 
       
  2464 void CMMFAudioController::MacGetSinkSampleRateL(TUint& aRate)
       
  2465 	{
       
  2466 	//precondition is that we have a sink format
       
  2467 	if (!iSinkFormat)
       
  2468 		{
       
  2469 		User::Leave(KErrNotSupported);
       
  2470 		}
       
  2471 	
       
  2472 	aRate = iSinkFormat->SampleRate();
       
  2473 	}
       
  2474 
       
  2475 /**
       
  2476 *
       
  2477 * MacGetSinkBitRateL
       
  2478 * @param "TUint&"
       
  2479 *
       
  2480 */
       
  2481 void CMMFAudioController::MacGetSinkBitRateL(TUint& aRate)
       
  2482 	{
       
  2483 	if (iSinkFormat)
       
  2484 		aRate = iSinkFormat->BitRate();
       
  2485 	else
       
  2486 		User::Leave(KErrNotSupported);
       
  2487 	}
       
  2488 
       
  2489 /**
       
  2490 *
       
  2491 * MacGetSinkNumChannelsL
       
  2492 * @param "TUint&"
       
  2493 *
       
  2494 */
       
  2495 void CMMFAudioController::MacGetSinkNumChannelsL(TUint& aNumChannels)
       
  2496 	{
       
  2497 	//precondition is that we have a sink format
       
  2498 	if (!iSinkFormat)
       
  2499 		{
       
  2500 		User::Leave(KErrNotSupported);
       
  2501 		}
       
  2502 	
       
  2503 	aNumChannels = iSinkFormat->NumChannels();
       
  2504 	}
       
  2505 
       
  2506 /**
       
  2507 *
       
  2508 * MacGetSinkFormatL
       
  2509 * @param "TUid&"
       
  2510 *
       
  2511 */
       
  2512 void CMMFAudioController::MacGetSinkFormatL(TUid& aFormat)
       
  2513 	{
       
  2514 	if (iSinkFormat)
       
  2515 		aFormat = iSinkFormat->ImplementationUid();
       
  2516 	else 
       
  2517 		User::Leave(KErrNotSupported);
       
  2518 	}
       
  2519 
       
  2520 /**
       
  2521 *
       
  2522 * MacGetSinkDataTypeL
       
  2523 * @param "TFourCC&"
       
  2524 *
       
  2525 */
       
  2526 void CMMFAudioController::MacGetSinkDataTypeL(TFourCC& aDataType)
       
  2527 	{
       
  2528 	//precondition is that we have a sink format
       
  2529 	if (!iSinkFormat)
       
  2530 		{
       
  2531 		User::Leave(KErrNotSupported);
       
  2532 		}
       
  2533 		
       
  2534 	aDataType = iSinkFormat->SinkDataTypeCode(TMediaId(KUidMediaTypeAudio));
       
  2535 	}
       
  2536 
       
  2537 /**
       
  2538 * 
       
  2539 * MacGetSupportedSourceSampleRatesL
       
  2540 * @param "RArray<TUint>&"
       
  2541 * 
       
  2542 */
       
  2543 void CMMFAudioController::MacGetSupportedSourceSampleRatesL(RArray<TUint>& aSupportedRates)
       
  2544 	{
       
  2545 	//precondition is that we have a source format
       
  2546 	if (!iSourceFormat)
       
  2547 		{
       
  2548 		User::Leave(KErrNotSupported);
       
  2549 		}
       
  2550 	
       
  2551 	aSupportedRates.Reset();
       
  2552 	iSourceFormat->GetSupportedSampleRatesL(aSupportedRates);
       
  2553 	}
       
  2554 
       
  2555 /**
       
  2556 *
       
  2557 * MacGetSupportedSourceBitRatesL
       
  2558 * @param "RArray<TUint>&"
       
  2559 *
       
  2560 */
       
  2561 void CMMFAudioController::MacGetSupportedSourceBitRatesL(RArray<TUint>& aSupportedRates)
       
  2562 	{
       
  2563 	aSupportedRates.Reset();
       
  2564 	if (iSourceFormat)
       
  2565 		iSourceFormat->GetSupportedBitRatesL(aSupportedRates);
       
  2566 	else
       
  2567 		User::Leave(KErrNotSupported);
       
  2568 	}
       
  2569 
       
  2570 /***
       
  2571 *
       
  2572 * MacGetSupportedSourceNumChannelsL
       
  2573 * @param "RArray<TUint>&"
       
  2574 *
       
  2575 */
       
  2576 void CMMFAudioController::MacGetSupportedSourceNumChannelsL(RArray<TUint>& aSupportedChannels)
       
  2577 	{
       
  2578 	//precondition is that we have a source format
       
  2579 	if (!iSourceFormat)
       
  2580 		{
       
  2581 		User::Leave(KErrNotSupported);
       
  2582 		}
       
  2583 	
       
  2584 	aSupportedChannels.Reset();
       
  2585 	iSourceFormat->GetSupportedNumChannelsL(aSupportedChannels);
       
  2586 	}
       
  2587 
       
  2588 /***
       
  2589 *
       
  2590 * MacGetSupportedSourceDataTypesL
       
  2591 * @param "RArray<TFourCC>&"
       
  2592 *
       
  2593 */
       
  2594 void CMMFAudioController::MacGetSupportedSourceDataTypesL(RArray<TFourCC>& aSupportedDataTypes)
       
  2595 	{
       
  2596 	//precondition is that we have a source format
       
  2597 	if (!iSourceFormat)
       
  2598 		{
       
  2599 		User::Leave(KErrNotSupported);
       
  2600 		}
       
  2601 	
       
  2602 	aSupportedDataTypes.Reset();
       
  2603 	iSourceFormat->GetSupportedDataTypesL(TMediaId(KUidMediaTypeAudio), aSupportedDataTypes);
       
  2604 	}
       
  2605 
       
  2606 /***
       
  2607 *
       
  2608 * MacGetSupportedSinkSampleRatesL
       
  2609 * @param "RArray<TUint>& "
       
  2610 *
       
  2611 */
       
  2612 void CMMFAudioController::MacGetSupportedSinkSampleRatesL(RArray<TUint>& aSupportedRates)
       
  2613 	{
       
  2614 	//precondition is that we have a sink format
       
  2615 	if (!iSinkFormat)
       
  2616 		{
       
  2617 		User::Leave(KErrNotSupported);
       
  2618 		}
       
  2619 	
       
  2620 	aSupportedRates.Reset();
       
  2621 	iSinkFormat->GetSupportedSampleRatesL(aSupportedRates);	
       
  2622 	}
       
  2623 
       
  2624 /***
       
  2625 *
       
  2626 * MacGetSupportedSinkBitRatesL
       
  2627 * @param RArray<TUint>& 
       
  2628 *
       
  2629 */
       
  2630 void CMMFAudioController::MacGetSupportedSinkBitRatesL(RArray<TUint>& aSupportedRates)
       
  2631 	{
       
  2632 	if (iSinkFormat)
       
  2633 		iSinkFormat->GetSupportedBitRatesL(aSupportedRates);
       
  2634 	else
       
  2635 		User::Leave(KErrNotSupported);
       
  2636 	}
       
  2637 
       
  2638 /***
       
  2639 *
       
  2640 * MacGetSupportedSinkNumChannelsL
       
  2641 * @param RArray<TUint>&
       
  2642 *
       
  2643 */
       
  2644 void CMMFAudioController::MacGetSupportedSinkNumChannelsL(RArray<TUint>& aSupportedChannels)
       
  2645 	{
       
  2646 	//precondition is that we have a sink format
       
  2647 	if (!iSinkFormat)
       
  2648 		{
       
  2649 		User::Leave(KErrNotSupported);
       
  2650 		}
       
  2651 	
       
  2652 	aSupportedChannels.Reset();
       
  2653 	iSinkFormat->GetSupportedNumChannelsL(aSupportedChannels);
       
  2654 	}
       
  2655 
       
  2656 /***
       
  2657 *
       
  2658 * MacGetSupportedSinkDataTypesL
       
  2659 * @param "RArray<TFourCC>&"
       
  2660 */
       
  2661 void CMMFAudioController::MacGetSupportedSinkDataTypesL(RArray<TFourCC>& aSupportedDataTypes)
       
  2662 	{
       
  2663 	//precondition is that we have a sink format
       
  2664 	if (!iSinkFormat)
       
  2665 		{
       
  2666 		User::Leave(KErrNotSupported);
       
  2667 		}
       
  2668 		
       
  2669 	aSupportedDataTypes.Reset();
       
  2670 	iSinkFormat->GetSupportedDataTypesL(TMediaId(KUidMediaTypeAudio), aSupportedDataTypes);
       
  2671 	}
       
  2672 
       
  2673 /**
       
  2674 *
       
  2675 * ConvertFromDevSoundCapsToSampleRatesL
       
  2676 * @param "const TMMFCapabilities& "
       
  2677 * @param "RArray<TUint>&"
       
  2678 *
       
  2679 */
       
  2680 void CMMFAudioController::ConvertFromDevSoundCapsToSampleRatesL(const TMMFCapabilities& aDevSoundCaps, RArray<TUint>& aSampleRates)
       
  2681 	{
       
  2682 	if (aDevSoundCaps.iRate & EMMFSampleRate8000Hz)
       
  2683 		User::LeaveIfError(aSampleRates.Append(KSampleRate8000Hz));
       
  2684 	if (aDevSoundCaps.iRate & EMMFSampleRate11025Hz)
       
  2685 		User::LeaveIfError(aSampleRates.Append(KSampleRate11025Hz));
       
  2686 	if (aDevSoundCaps.iRate & EMMFSampleRate12000Hz)
       
  2687 		User::LeaveIfError(aSampleRates.Append(KSampleRate12000Hz));
       
  2688 	if (aDevSoundCaps.iRate & EMMFSampleRate16000Hz)
       
  2689 		User::LeaveIfError(aSampleRates.Append(KSampleRate16000Hz));
       
  2690 	if (aDevSoundCaps.iRate & EMMFSampleRate22050Hz)
       
  2691 		User::LeaveIfError(aSampleRates.Append(KSampleRate22050Hz));
       
  2692 	if (aDevSoundCaps.iRate & EMMFSampleRate24000Hz)
       
  2693 		User::LeaveIfError(aSampleRates.Append(KSampleRate24000Hz));
       
  2694 	if (aDevSoundCaps.iRate & EMMFSampleRate32000Hz)
       
  2695 		User::LeaveIfError(aSampleRates.Append(KSampleRate32000Hz));
       
  2696 	if (aDevSoundCaps.iRate & EMMFSampleRate44100Hz)
       
  2697 		User::LeaveIfError(aSampleRates.Append(KSampleRate44100Hz));
       
  2698 	if (aDevSoundCaps.iRate & EMMFSampleRate48000Hz)
       
  2699 		User::LeaveIfError(aSampleRates.Append(KSampleRate48000Hz));
       
  2700 	if (aDevSoundCaps.iRate & EMMFSampleRate64000Hz)
       
  2701 		User::LeaveIfError(aSampleRates.Append(KSampleRate64000Hz));
       
  2702 	if (aDevSoundCaps.iRate & EMMFSampleRate88200Hz)
       
  2703 		User::LeaveIfError(aSampleRates.Append(KSampleRate88200Hz));
       
  2704 	if (aDevSoundCaps.iRate & EMMFSampleRate96000Hz)
       
  2705 		User::LeaveIfError(aSampleRates.Append(KSampleRate96000Hz));
       
  2706 	}
       
  2707 
       
  2708 /**
       
  2709 *
       
  2710 * ConvertFromDevSoundCapsToNumChannelsL
       
  2711 * @param "const TMMFCapabilities&"
       
  2712 * @param "RArray<TUint>&"
       
  2713 *
       
  2714 */
       
  2715 void CMMFAudioController::ConvertFromDevSoundCapsToNumChannelsL(const TMMFCapabilities& aDevSoundCaps, RArray<TUint>& aNumChannels)
       
  2716 	{
       
  2717 	if (aDevSoundCaps.iChannels & EMMFMono)
       
  2718 		User::LeaveIfError(aNumChannels.Append(KNumChannelsMono));
       
  2719 	if (aDevSoundCaps.iChannels & EMMFStereo)
       
  2720 		User::LeaveIfError(aNumChannels.Append(KNumChannelsStereo));
       
  2721 	}
       
  2722 
       
  2723 /**
       
  2724 *
       
  2725 * ConvertFromDevSoundCapsToDataTypesL
       
  2726 * @param "const TMMFCapabilities&"
       
  2727 * @param "TMMFCapabilities& aDevSoundCaps, RArray<TFourCC>&"
       
  2728 *
       
  2729 */
       
  2730 void CMMFAudioController::ConvertFromDevSoundCapsToDataTypesL(const TMMFCapabilities& aDevSoundCaps, RArray<TFourCC>& aDataTypes)
       
  2731 	{
       
  2732 	if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitPCM)
       
  2733 		User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM8));
       
  2734 	if (aDevSoundCaps.iEncoding & EMMFSoundEncoding16BitPCM)
       
  2735 		User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM16));
       
  2736 	if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitALaw)
       
  2737 		User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeALAW));
       
  2738 	if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitMuLaw)
       
  2739 		User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeMuLAW));
       
  2740 	}
       
  2741 
       
  2742 /**
       
  2743 *
       
  2744 * ConvertFromSampleRateToDevSoundCapsL
       
  2745 * @param "TUint"
       
  2746 * @param "TMMFCapabilities&"
       
  2747 *
       
  2748 */
       
  2749 void CMMFAudioController::ConvertFromSampleRateToDevSoundCapsL(TUint aSampleRate, TMMFCapabilities& aDevSoundCaps)
       
  2750 	{
       
  2751 	if (aSampleRate == KSampleRate8000Hz)
       
  2752 		aDevSoundCaps.iRate = EMMFSampleRate8000Hz;
       
  2753 	else if (aSampleRate == KSampleRate11025Hz)
       
  2754 		aDevSoundCaps.iRate = EMMFSampleRate11025Hz;
       
  2755 	else if (aSampleRate == KSampleRate12000Hz)
       
  2756 		aDevSoundCaps.iRate = EMMFSampleRate12000Hz;
       
  2757 	else if (aSampleRate == KSampleRate16000Hz)
       
  2758 		aDevSoundCaps.iRate = EMMFSampleRate16000Hz;
       
  2759 	else if (aSampleRate == KSampleRate22050Hz)
       
  2760 		aDevSoundCaps.iRate = EMMFSampleRate22050Hz;
       
  2761 	else if (aSampleRate == KSampleRate24000Hz)
       
  2762 		aDevSoundCaps.iRate = EMMFSampleRate24000Hz;
       
  2763 	else if (aSampleRate == KSampleRate32000Hz)
       
  2764 		aDevSoundCaps.iRate = EMMFSampleRate32000Hz;
       
  2765 	else if (aSampleRate == KSampleRate44100Hz)
       
  2766 		aDevSoundCaps.iRate = EMMFSampleRate44100Hz;
       
  2767 	else if (aSampleRate == KSampleRate48000Hz)
       
  2768 		aDevSoundCaps.iRate = EMMFSampleRate48000Hz;
       
  2769 	else if (aSampleRate == KSampleRate64000Hz)
       
  2770 		aDevSoundCaps.iRate = EMMFSampleRate64000Hz;
       
  2771 	else if (aSampleRate == KSampleRate88200Hz)
       
  2772 		aDevSoundCaps.iRate = EMMFSampleRate88200Hz;
       
  2773 	else if (aSampleRate == KSampleRate96000Hz)
       
  2774 		aDevSoundCaps.iRate = EMMFSampleRate96000Hz;
       
  2775 	else
       
  2776 		User::Leave(KErrNotSupported);
       
  2777 	}
       
  2778 
       
  2779 /**
       
  2780 *
       
  2781 * ConvertFromNumChannelsToDevSoundCapsL
       
  2782 * @param "TUint"
       
  2783 * @param  "TMMFCapabilities&"
       
  2784 *
       
  2785 */
       
  2786 void CMMFAudioController::ConvertFromNumChannelsToDevSoundCapsL(TUint aNumChannels, TMMFCapabilities& aDevSoundCaps)
       
  2787 	{
       
  2788 	if (aNumChannels == KNumChannelsMono)
       
  2789 		aDevSoundCaps.iChannels = EMMFMono;
       
  2790 	else if (aNumChannels == KNumChannelsStereo)
       
  2791 		aDevSoundCaps.iChannels = EMMFStereo;
       
  2792 	else
       
  2793 		User::Leave(KErrNotSupported);
       
  2794 	}
       
  2795 
       
  2796 /**
       
  2797 *
       
  2798 * ConvertFromDataTypeToDevSoundCapsL
       
  2799 * @param "TFourCC"
       
  2800 * @param "TMMFCapabilities&"
       
  2801 *
       
  2802 */
       
  2803 void CMMFAudioController::ConvertFromDataTypeToDevSoundCapsL(TFourCC aDataType, TMMFCapabilities& aDevSoundCaps)
       
  2804 	{
       
  2805 	if (aDataType == KMMFFourCCCodePCM8)
       
  2806 		aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitPCM;
       
  2807 	else if (aDataType == KMMFFourCCCodePCM16)
       
  2808 		aDevSoundCaps.iEncoding = EMMFSoundEncoding16BitPCM;
       
  2809 	else if (aDataType == KMMFFourCCCodeALAW)
       
  2810 		aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitALaw;
       
  2811 	else if (aDataType == KMMFFourCCCodeMuLAW)
       
  2812 		aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitMuLaw;
       
  2813 	else
       
  2814 		User::Leave(KErrNotSupported);
       
  2815 	}
       
  2816 
       
  2817 /**
       
  2818 * IsValidStateTransition
       
  2819 * The function validates a state transition from iState to aState
       
  2820 * and returns ETrue if the transition is allowed.
       
  2821 * @internalTechnology
       
  2822 * @param TControllerState
       
  2823 * @returns "TBool"
       
  2824 */
       
  2825 TBool CMMFAudioController::IsValidStateTransition( TControllerState aState ) const
       
  2826 	{
       
  2827 	 TBool result = ETrue ;
       
  2828 	//[ assert the precondition that aState is a valid State ]
       
  2829 	__ASSERT_ALWAYS( IsValidState(aState), Panic( EBadArgument ) );
       
  2830 	//[ assert the invariant that iState is a valid State ]
       
  2831 	__ASSERT_ALWAYS( Invariant(), Panic( EInvalidState ));
       
  2832 
       
  2833 	// [ check the valid state transitions ]
       
  2834 	  // the only invalid transition is
       
  2835 	  // stopped to playing
       
  2836 	if( ( iState == EStopped ) && ( aState == EPlaying ))
       
  2837 		{
       
  2838          result = EFalse ;
       
  2839 		}
       
  2840   
       
  2841 	//[ assert the invariant that iState is a valid State ]
       
  2842 	__ASSERT_ALWAYS( Invariant(), Panic( EInvalidState ));
       
  2843 
       
  2844 	return result ;
       
  2845 	}
       
  2846 
       
  2847 /*
       
  2848 * Invariant
       
  2849 * @internalTechnology
       
  2850 * @returns "TBool"
       
  2851 * This function returns whether the invariant is valid
       
  2852 */
       
  2853 TBool  CMMFAudioController::Invariant() const
       
  2854 	{
       
  2855 	//[ The invariant is for now defined 
       
  2856 	// as simply being in the correct state and
       
  2857 	// having iDataPath defined ]
       
  2858 	return ( iDataPath )&& IsValidState( iState);
       
  2859 	}
       
  2860 
       
  2861 /*
       
  2862 * SetState
       
  2863 *  This function sets the state of the controller.
       
  2864 * @internalTechnology
       
  2865 * @returns "TBool"
       
  2866 */
       
  2867 TBool CMMFAudioController::SetState(TControllerState aState)
       
  2868 	{
       
  2869 	TBool result = ETrue;
       
  2870 	//[ assert the precondition that the state is a valid state ]
       
  2871    	__ASSERT_ALWAYS( IsValidState( aState),  Panic( EBadArgument ) );
       
  2872 	//[ assert the invariant the current state is valid ]
       
  2873 	__ASSERT_ALWAYS( Invariant(),  Panic( EBadState ) );
       
  2874     //[ only allow valid state transitions ]
       
  2875 	if( IsValidStateTransition( aState ) )	
       
  2876 		{
       
  2877 		//[ valid state transition set the state]
       
  2878 		iState = aState ;
       
  2879 		}
       
  2880 	else
       
  2881 		{
       
  2882 		//[ invalid state transition return EFalse ]
       
  2883 		result = EFalse;         
       
  2884 		}
       
  2885 	// [ assert the invariant on the state ]
       
  2886 	__ASSERT_ALWAYS( Invariant(), Panic( EBadState ));
       
  2887 	
       
  2888 	return result ;
       
  2889 	}
       
  2890 
       
  2891 /*
       
  2892 * IsValidState 
       
  2893 * checks whether a state is a valid 
       
  2894 * @internalTechnology
       
  2895 * @returns "TBool"
       
  2896 * @param TControllerState
       
  2897 */
       
  2898 TBool  CMMFAudioController::IsValidState( TControllerState aState ) const 
       
  2899 	{
       
  2900 	TBool result = EFalse;
       
  2901      if(( aState >= EStopped ) && ( aState <= EPlaying ))
       
  2902 		 {
       
  2903           result = ETrue;
       
  2904 		 }
       
  2905 	 return result;
       
  2906 	}
       
  2907 
       
  2908 /**
       
  2909 * State
       
  2910 * The function State returns the current state of the audio controller
       
  2911 * @internalTechnology
       
  2912 * @returns "TControllerState"
       
  2913 */
       
  2914 CMMFAudioController::TControllerState CMMFAudioController::State() const
       
  2915 	{
       
  2916 	__ASSERT_ALWAYS( Invariant(), Panic( EBadState ) );
       
  2917 	return iState;
       
  2918 	}
       
  2919 
       
  2920 /**
       
  2921 *
       
  2922 * SinkFormatRequired
       
  2923 *
       
  2924 */
       
  2925 TBool CMMFAudioController::SinkFormatRequired( MDataSink& aDataSink ) const
       
  2926 	{
       
  2927      return (aDataSink.DataSinkType()==KUidMmfFileSink || 
       
  2928 		     aDataSink.DataSinkType()==KUidMmfDescriptorSink);
       
  2929 	}
       
  2930 
       
  2931 /**
       
  2932 *
       
  2933 * SourceFormatRequired
       
  2934 *
       
  2935 */
       
  2936 
       
  2937 TBool CMMFAudioController::SourceFormatRequired(MDataSource& aDataSource) const
       
  2938 	{
       
  2939 	return (aDataSource.DataSourceType()==KUidMmfFileSource || 
       
  2940 		    aDataSource.DataSourceType()==KUidMmfDescriptorSource);
       
  2941 	}
       
  2942 	
       
  2943 TInt CMMFAudioController::MdcEvaluateIntent(ContentAccess::TIntent aIntent) 
       
  2944 	{
       
  2945 	if (iDataSource->DataSourceType()==KUidMmfFileSource)
       
  2946 		{
       
  2947 		CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
       
  2948 		TInt err = file->EvaluateIntent(aIntent);
       
  2949 		return err;
       
  2950 		}
       
  2951 	else
       
  2952 		{
       
  2953 		// Evaluating intent will always succeed on sinks that 
       
  2954 		// don't support DRM
       
  2955 		return KErrNone;
       
  2956 		}
       
  2957 	
       
  2958 	}
       
  2959 	
       
  2960 TInt CMMFAudioController::MdcExecuteIntent(ContentAccess::TIntent aIntent)
       
  2961 	{
       
  2962 	if (iDataSource->DataSourceType()==KUidMmfFileSource)
       
  2963 		{
       
  2964 		CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
       
  2965 		TInt err = file->ExecuteIntent(aIntent);
       
  2966 		return err;
       
  2967 		}
       
  2968 	else
       
  2969 		{
       
  2970 		// Executing intent will always succeed on sinks that 
       
  2971 		// don't support DRM
       
  2972 		return KErrNone;
       
  2973 		}
       
  2974 	}
       
  2975 	
       
  2976 TInt CMMFAudioController::MdcDisableAutomaticIntent(TBool aDisableAutoIntent)
       
  2977 	{
       
  2978 	iDisableAutoIntent = aDisableAutoIntent;
       
  2979 	return KErrNone;
       
  2980 	}
       
  2981 	
       
  2982 	
       
  2983 TInt CMMFAudioController::MdcSetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
       
  2984 	{
       
  2985 	if (iDataSource->DataSourceType()==KUidMmfFileSource)
       
  2986 		{
       
  2987 		CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
       
  2988 		TInt err = file->SetAgentProperty(aProperty, aValue);
       
  2989 		return err;
       
  2990 		}
       
  2991 	else
       
  2992 		{
       
  2993 		return KErrNone;
       
  2994 		}
       
  2995 	}
       
  2996 
       
  2997 void CMMFAudioController::MarnRegisterAsClientL(TUid aEventType,const TDesC8& aNotificationRegistrationData)
       
  2998 	{
       
  2999 	//[ assert the invariant ]
       
  3000 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToRegisterAsClient));
       
  3001 	//[ precondition that we have a sink]
       
  3002 	if (!iDataSink)
       
  3003 		{	
       
  3004 		User::Leave(KErrNotReady);
       
  3005 		}
       
  3006 	//[register the notification ]
       
  3007 	MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
       
  3008 	TInt err = audioOutput->SoundDevice().RegisterAsClient(aEventType, aNotificationRegistrationData);
       
  3009 	User::LeaveIfError(err);
       
  3010 	iRegisterARN = ETrue;
       
  3011 	//[ assert the invariant ]
       
  3012 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterRegisterAsClient));
       
  3013 	}
       
  3014 	
       
  3015 void CMMFAudioController::MarnCancelRegisterAsClientL(TUid aEventType)
       
  3016 	{
       
  3017 	//[ assert the invariant ]
       
  3018 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToCancelRegisterAsClient));
       
  3019 	//[ precondition that we have a sink]
       
  3020 	if (!iDataSink)
       
  3021 		{
       
  3022 		User::Leave(KErrNotReady);			
       
  3023 		}
       
  3024 	//[cancel the notification ]
       
  3025 	MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
       
  3026 	TInt err = audioOutput->SoundDevice().CancelRegisterAsClient(aEventType);
       
  3027 	User::LeaveIfError(err);
       
  3028     iRegisterARN = EFalse;
       
  3029 	//[ assert the invariant ]
       
  3030 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterCancelRegisterAsClient));
       
  3031 	}
       
  3032 
       
  3033 void CMMFAudioController::MarnGetResourceNotificationDataL(TUid aEventType,TDes8& aNotificationData)
       
  3034 	{
       
  3035 	//[ assert the invariant ]
       
  3036 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetResourceNotificationData));
       
  3037 	//[ precondition that we have a sink]
       
  3038 	if (!iDataSink)
       
  3039 		{
       
  3040 		User::Leave(KErrNotReady);
       
  3041 		}
       
  3042 	//[get the notification data]
       
  3043 	MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
       
  3044 	TMMFTimeIntervalMicroSecondsPckg pckg;
       
  3045 	TInt err = audioOutput->SoundDevice().GetResourceNotificationData(aEventType, pckg);
       
  3046 	User::LeaveIfError(err);
       
  3047 	
       
  3048 	// aNotificationData is a package buffer returned as TMMFTimeIntervalMicroSecondsPckg,
       
  3049 	// but the contents should be converted to an integer and interpreted as the 
       
  3050 	// data returned is samples played, but not as a microsecond value.
       
  3051 	// As the client expects a position (in microseconds from the beginning
       
  3052 	// of the clip) we need to convert the data depending on the sample rate
       
  3053 	// Potential issue if using the number of samples played with VBR sampling.
       
  3054 	RArray<TUint> array;
       
  3055 	CleanupClosePushL(array);
       
  3056 	ConvertFromDevSoundCapsToSampleRatesL(audioOutput->SoundDevice().Config(), array);
       
  3057 	// Should only ever have 1 entry in the array
       
  3058 	ASSERT(array.Count() == 1);
       
  3059 	TUint rate = array[0];
       
  3060 	if (rate)
       
  3061 		{
       
  3062 		// Convert the given number of samples using the sample rate
       
  3063 		const TInt KMicroSecsInOneSec = 1000000;
       
  3064 		TTimeIntervalMicroSeconds value = pckg();
       
  3065 		value = TTimeIntervalMicroSeconds(value.Int64() * KMicroSecsInOneSec / rate);
       
  3066 		pckg() = value;
       
  3067 		}
       
  3068 	else
       
  3069 		{
       
  3070 		User::Leave(KErrArgument);
       
  3071 		}
       
  3072 	aNotificationData = pckg;
       
  3073 	CleanupStack::PopAndDestroy();//array
       
  3074 
       
  3075 	//[ assert the invariant ]
       
  3076 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetResourceNotificationData));
       
  3077 	}
       
  3078 
       
  3079 void CMMFAudioController::MarnWillResumePlayL()
       
  3080 	{
       
  3081 	//[ assert the invariant ]
       
  3082 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateToResumePlay));
       
  3083 	//[ precondition that we have a sink]
       
  3084 	if (!iDataSink)
       
  3085 		{
       
  3086 		User::Leave(KErrNotReady);
       
  3087 		}
       
  3088 	//[wait for the client to resume ]
       
  3089 	MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
       
  3090 	TInt err = audioOutput->SoundDevice().WillResumePlay();
       
  3091 	User::LeaveIfError(err);
       
  3092 	//[ assert the invariant ]
       
  3093 	__ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterResumePlay));
       
  3094 	}