os/mm/devsound/devsoundrefplugin/src/platsec/server/AudioServer/MmfDevSoundSessionBody.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2001-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 #include <e32base.h>
    17 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
    18 #include <OMX_Core.h>
    19 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
    20 #include "MmfDevSoundSessionBody.h"
    21 #include "MmfDevSoundSessionXtnd.h"
    22 #include "MmfDevSoundServer.h"
    23 #include <mdaaudiotoneplayer.h>
    24 #include <mmf/server/mmfdatabuffer.h>
    25 #include <mmffourcc.h>
    26 #include <mmfhwdeviceimplementationuids.hrh>
    27 #include <mmf/server/mmfswcodecwrappercustominterfacesuids.hrh> // KUidRefDevSoundTaskConfig & KMmfUidEmptyBuffersCustomInterface
    28 #include <mmf/server/mmfdevsoundcustominterfacesupport.h>
    29 
    30 const TUid KEmptyBuffersCustomInterfaceTypeUid	= {KMmfUidEmptyBuffersCustomInterface};
    31 
    32 /*
    33  *
    34  *	Default Constructor.
    35  *
    36  *	No default implementation. CMMFDevSoundProxy implements 2-phase construction.
    37  *
    38  */
    39 CMMFDevSoundSvrImp::CMMFDevSoundSvrImp(CMMFDevSoundSessionXtnd* aParent)
    40 : iParent(*aParent)
    41 	{
    42 	iMode= EMMFDevSoundStateIdle;
    43 	//Set reasonable default values for DTMF 
    44 	iDTMFGen.SetToneDurations(250000,50000,250000);
    45 	}
    46 
    47 /*
    48  *
    49  *	Destructor.
    50  *
    51  *	Deletes all objects and releases all resource owned by this
    52  *	instance.
    53  *
    54  */
    55 CMMFDevSoundSvrImp::~CMMFDevSoundSvrImp()
    56 	{
    57 	delete iToneBuffer1;
    58 	delete iToneBuffer2;
    59 	delete iDevSoundEventHandler; 
    60 	if( iAudioPolicyProxy != NULL)
    61 		{
    62 		iAudioPolicyProxy->Close(); 
    63 		delete iAudioPolicyProxy;
    64 		}
    65 	delete iDevSoundUtil;
    66 	delete iFixedSequences;
    67 	delete iCMMFHwDevice;
    68 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
    69 	OMX_Deinit();
    70 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
    71 	}
    72 
    73 /*
    74  *
    75  *	Constructs, and returns a pointer to, a new CMMFDevSoundSvrImp object.
    76  *
    77  *	Leaves on failure.
    78  *
    79  */
    80 CMMFDevSoundSvrImp* CMMFDevSoundSvrImp::NewL(CMMFDevSoundSessionXtnd* aParent)
    81 	{
    82 	CMMFDevSoundSvrImp* self = new (ELeave) CMMFDevSoundSvrImp(aParent);
    83 	return self;
    84 	}
    85 
    86 /*
    87  *
    88  *	3rd phase constructor - assumes that iParent has already been set up properly
    89  *                          (During ConstructL() it has yet to be
    90  *
    91  */
    92 void CMMFDevSoundSvrImp::Construct3L(RServer2& aPolicyServerHandle)
    93 	{
    94 	// all these data properties should be NULL, but add ASSERTs to verity
    95 	ASSERT(iAudioPolicyProxy==NULL);
    96 	iAudioPolicyProxy = new (ELeave) RMMFAudioPolicyProxy();
    97 	ASSERT(iDevSoundEventHandler==NULL);
    98 	iDevSoundEventHandler = CMMFDevSoundEventHandler::NewL(iAudioPolicyProxy);
    99 	User::LeaveIfError(iAudioPolicyProxy->Open(aPolicyServerHandle));
   100 	iDevSoundEventHandler->SetDevSoundInfo(&iParent);
   101 
   102 	iDevSoundUtil = CMMFDevSoundUtility::NewL();
   103 	// Initialize Fixed sequence related
   104 	iDevSoundUtil->InitializeFixedSequenceL(&iFixedSequences);
   105 	
   106 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
   107 	OMX_Init();
   108 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
   109 	PreInitializeL();
   110 	}
   111 
   112 /**
   113  * internal procedure to perform all initialization prior to setting the 
   114  * data type 4CC code
   115  */
   116 void CMMFDevSoundSvrImp::PreInitializeL()
   117 	{
   118 	// Set default values for priority settings: Note: Client must 
   119 	// over ride default settings by calling SetPrioirtySettings
   120 	iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
   121 	iAudioPolicyPrioritySettings.iPref = EMdaPriorityPreferenceNone;
   122 	iAudioPolicyPrioritySettings.iPriority = 0;
   123 
   124 	// Get device capabilities and current settings from Audio Policy:
   125 	User::LeaveIfError(iAudioPolicyProxy->GetPlayFormatsSupported(iPlayFormatsSupported));
   126 	User::LeaveIfError(iAudioPolicyProxy->GetPlayFormat(iPlayFormat));
   127 	User::LeaveIfError(iAudioPolicyProxy->GetRecordFormatsSupported(iRecordFormatsSupported));
   128 	User::LeaveIfError(iAudioPolicyProxy->GetRecordFormat(iRecordFormat));
   129 
   130 	//default to play until we know we are recording
   131 	User::LeaveIfError(InitializeFormat(iPlayFormatsSupported, iPlayFormat));
   132 	}
   133 
   134 /*
   135  *
   136  *	Initializes CMMFDevSoundProxy object to play and record PCM16 raw audio data
   137  *	with sampling rate of 8 KHz.
   138  *
   139  *	On completion of Initialization, calls InitializeComplete() on
   140  *	aDevSoundObserver.
   141  *
   142  *	Leaves on failure.
   143  *
   144  *	@param	"MDevSoundObserver& aDevSoundObserver"
   145  *			A reference to DevSound Observer instance.
   146  *
   147  *	@param	"TMMFState aMode"
   148  *			Mode for which this object will be used.
   149  *
   150  */
   151 void CMMFDevSoundSvrImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TMMFState aMode)
   152 
   153 	{
   154 	// if no HwDevice id specified, load default null implementation
   155 	TUid rawUid = {KMmfUidHwDevicePCM16ToPCM16};
   156 	InitializeL(aDevSoundObserver, rawUid, aMode);
   157 	__ASSERT_DEBUG(!(iHasPolicy&&(iMode == EMMFDevSoundStatePlaying)), Panic(TMMFDevSoundSessionPolicyNotInvalidated));
   158 	}
   159 
   160 /*
   161  *
   162  *	Configure CMMFDevSoundProxy object for the settings in aConfig.
   163  *
   164  *	Use this to set sampling rate, Encoding and Mono/Stereo.
   165  *
   166  *	@param	"TMMFCapabilities& aConfig"
   167  *			Attribute values to which CMMFDevSoundProxy object will be configured to.
   168  *
   169  *  As part of defect 20796, the iRecordFormat has been set under the iPlayFormat, 
   170  *  before it was not set at all.
   171  *
   172  */
   173 void CMMFDevSoundSvrImp::SetConfigL(const TMMFCapabilities& aConfig)
   174 	{
   175 	TUint attributeValue = aConfig.iRate;
   176 	// WINS supports from 8000 Hz to 96000 Hz
   177 	// The ToneGenerator currently supports sample rate of 8000Hz only. 
   178 	if(iMode == EMMFDevSoundStateTonePlaying && (attributeValue != EMMFSampleRate8000Hz ))
   179 		{
   180 		User::Leave(KErrNotSupported);
   181 		}
   182 	
   183 	if (attributeValue & EMMFSampleRate96000Hz) 
   184 		{ 
   185 		iPlayFormat().iRate = 96000; 
   186 		iRecordFormat().iRate = 96000;
   187 		iDeviceConfig.iRate = EMMFSampleRate96000Hz;
   188 		}
   189 	else if (attributeValue & EMMFSampleRate88200Hz) 
   190 		{ 
   191 		iPlayFormat().iRate = 88200; 
   192 		iRecordFormat().iRate = 88200;
   193 		iDeviceConfig.iRate = EMMFSampleRate88200Hz;
   194 		}
   195 	else if (attributeValue & EMMFSampleRate64000Hz) 
   196 		{ 
   197 		iPlayFormat().iRate = 64000; 
   198 		iRecordFormat().iRate = 64000;
   199 		iDeviceConfig.iRate = EMMFSampleRate64000Hz;
   200 		}
   201 	else if (attributeValue & EMMFSampleRate48000Hz) 
   202 		{ 
   203 		iPlayFormat().iRate = 48000; 
   204 		iRecordFormat().iRate = 48000;
   205 		iDeviceConfig.iRate = EMMFSampleRate48000Hz;
   206 		}
   207 	else if (attributeValue & EMMFSampleRate44100Hz) 
   208 		{ 
   209 		iPlayFormat().iRate = 44100; 
   210 		iRecordFormat().iRate = 44100;
   211 		iDeviceConfig.iRate = EMMFSampleRate44100Hz;
   212 		}
   213 	else if (attributeValue & EMMFSampleRate32000Hz) 
   214 		{ 
   215 		iPlayFormat().iRate = 32000; 
   216 		iRecordFormat().iRate = 32000; 
   217 		iDeviceConfig.iRate = EMMFSampleRate32000Hz;
   218 		}
   219 	else if (attributeValue & EMMFSampleRate24000Hz)
   220 		{
   221 		iPlayFormat().iRate = 
   222 		iRecordFormat().iRate = 24000;
   223 		iDeviceConfig.iRate = EMMFSampleRate24000Hz;
   224 		}
   225 	else if (attributeValue & EMMFSampleRate22050Hz)
   226 		{ 
   227 		iPlayFormat().iRate = 22050; 
   228 		iRecordFormat().iRate = 22050; 
   229 		iDeviceConfig.iRate = EMMFSampleRate22050Hz;
   230 		}
   231 	else if (attributeValue & EMMFSampleRate16000Hz)
   232 		{
   233 		iPlayFormat().iRate = 16000;
   234 		iRecordFormat().iRate = 16000; 
   235 		iDeviceConfig.iRate = EMMFSampleRate16000Hz;
   236 		}
   237 	else if (attributeValue & EMMFSampleRate12000Hz)
   238 		{
   239 		iPlayFormat().iRate = 
   240 		iRecordFormat().iRate = 12000;
   241 		iDeviceConfig.iRate = EMMFSampleRate12000Hz;
   242 		}
   243 	else if (attributeValue & EMMFSampleRate11025Hz)
   244 		{
   245 		iPlayFormat().iRate = 11025;
   246 		iRecordFormat().iRate = 11025;
   247 		iDeviceConfig.iRate = EMMFSampleRate11025Hz;
   248 		}
   249 	else if (attributeValue & EMMFSampleRate8000Hz)
   250 		{
   251 		iPlayFormat().iRate = 8000;
   252 		iRecordFormat().iRate = 8000;
   253 		iDeviceConfig.iRate = EMMFSampleRate8000Hz;
   254 		}
   255 	else if (attributeValue) 
   256 		{ //if no attribute value assume its not set
   257 		User::Leave(KErrNotSupported);
   258 		}
   259 
   260 	attributeValue = aConfig.iEncoding;
   261 	// Map from MMF Encoding enums to RMdaDevSound enum
   262 	if(attributeValue & EMMFSoundEncoding8BitPCM) 
   263 		{
   264 		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
   265 		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
   266 		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitPCM;
   267 		}
   268 	else if(attributeValue & EMMFSoundEncoding8BitALaw)
   269 		{
   270 		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
   271 		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
   272 		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitALaw;
   273 		}
   274 	else if(attributeValue & EMMFSoundEncoding8BitMuLaw) 
   275 		{
   276 		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
   277 		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
   278 		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitMuLaw;
   279 		}
   280 	else if(attributeValue & EMMFSoundEncoding16BitPCM)
   281 		{
   282 		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
   283 		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
   284 		iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
   285 		}
   286 	else if (attributeValue) 
   287 		{ //if no attribute value assume its not set
   288 		User::Leave(KErrNotSupported);
   289 		}
   290 
   291 	// Mono/Stereo settings
   292 	attributeValue = aConfig.iChannels;
   293 	if(iMode == EMMFDevSoundStateTonePlaying && (attributeValue != EMMFMono ))
   294 		{
   295 		User::Leave(KErrNotSupported);
   296 		}
   297 	if(attributeValue & EMMFStereo) 
   298 		{
   299 		iPlayFormat().iChannels = 2;
   300 		iRecordFormat().iChannels = 2;
   301 		iDeviceConfig.iChannels = EMMFStereo;
   302 		}
   303 	else if(attributeValue & EMMFMono)
   304 		{
   305 		iPlayFormat().iChannels = 1;
   306 		iRecordFormat().iChannels = 1;
   307 		iDeviceConfig.iChannels = EMMFMono;
   308 		}
   309 	else if (attributeValue) 
   310 		{ //if no attribute value assume its not set
   311 		User::Leave(KErrNotSupported);
   312 		}
   313 	}
   314 
   315 /*
   316  *
   317  *	Changes the current playback volume to a specified value.
   318  *
   319  *	The volume can be changed before or during playback and is effective
   320  *	immediately.
   321  *
   322  *	@param	"TInt aVolume"
   323  *			The volume setting. This can be any value from zero to the value
   324  *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
   325  *			volume is not within this range, the volume is automatically set to
   326  *			minimum or maximum value based on the value that is being passed.
   327  *			Setting a zero value mutes the sound. Setting the maximum value
   328  *			results in the loudest possible sound.
   329  *
   330  */
   331 void CMMFDevSoundSvrImp::SetVolume(TInt aVolume)
   332 	{
   333 
   334 	// Check and make sure that the volume is in valid range
   335 	if (aVolume < 0)
   336 		aVolume = 0;
   337 
   338 	if (aVolume > MaxVolume())
   339 		aVolume = MaxVolume();
   340 
   341 	iVolume = aVolume;
   342 
   343 	SetDeviceVolume(iVolume);
   344 	}
   345 
   346 /*
   347  *
   348  *	Changes the current recording gain to a specified value.
   349  *
   350  *	The gain can be changed before or during recording and is effective
   351  *	immediately.
   352  *
   353  *	@param	"TInt aGain"
   354  *			The volume setting. This can be any value from zero to the value
   355  *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
   356  *			volume is not within this range, the gain is automatically set to
   357  *			minimum or maximum value based on the value that is being passed.
   358  *			Setting a zero value mutes the sound. Setting the maximum value
   359  *			results in the loudest possible sound.
   360  *
   361  */
   362 void CMMFDevSoundSvrImp::SetGain(TInt aGain)
   363 	{
   364 	// make sure it falls with the correct range
   365 	TInt maxGain = iRecordFormatsSupported().iMaxVolume;
   366 	if (aGain > maxGain)
   367 		aGain = maxGain;
   368 	else if (aGain < 0)
   369 		aGain = 0;
   370 	iGain = aGain;
   371 	SetDeviceRecordLevel(iGain);
   372 	}
   373 
   374 /*
   375  *
   376  *	Sets the speaker balance for playing.
   377  *
   378  *	The speaker balance can be changed before or during playback and is
   379  *	effective immediately.
   380  *
   381  *	@param	"TInt& aLeftPercentage"
   382  *			On return contains left speaker volume perecentage. This can be any
   383  *			value from zero to 100. Setting a zero value mutes the sound on left
   384  *			speaker.
   385  *
   386  *	@param	"TInt& aRightPercentage"
   387  *			On return contains right speaker volume perecentage. This can be any
   388  *			value from zero to 100. Setting a zero value mutes the sound on
   389  *			right speaker.
   390  *
   391  */
   392 void CMMFDevSoundSvrImp::SetPlayBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
   393 	{
   394 	if (aLeftPercentage < 0)
   395 		aLeftPercentage = 0;
   396 	else if (aLeftPercentage > 100)
   397 		aLeftPercentage = 100;
   398 	if (aRightPercentage < 0)
   399 		aRightPercentage = 0;
   400 	else if (aRightPercentage > 100)
   401 		aRightPercentage = 100;
   402 	iLeftPlayBalance = aLeftPercentage;
   403 	iRightPlayBalance = aRightPercentage;
   404 	}
   405 
   406 /*
   407  *
   408  *	Sets the microphone gain balance for recording.
   409  *
   410  *	The microphone gain balance can be changed before or during recording and
   411  *	is effective immediately.
   412  *
   413  *	@param	"TInt aLeftPercentage"
   414  *			Left microphone gain precentage. This can be any value from zero to
   415  *			100. Setting a zero value mutes the gain on left microphone.
   416  *
   417  *	@param	"TInt aRightPercentage"
   418  *			Right microphone gain precentage. This can be any value from zero to
   419  *			100. Setting a zero value mutes the gain on right microphone.
   420  *
   421  */
   422 void CMMFDevSoundSvrImp::SetRecordBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
   423 	{
   424 	if (aLeftPercentage < 0)
   425 		aLeftPercentage = 0;
   426 	else if (aLeftPercentage > 100)
   427 		aLeftPercentage = 100;
   428 	if (aRightPercentage < 0)
   429 		aRightPercentage = 0;
   430 	else if (aRightPercentage > 100)
   431 		aRightPercentage = 100;
   432 	iLeftRecordBalance = aLeftPercentage;
   433 	iRightRecordBalance = aRightPercentage;
   434 	}
   435 
   436 /*
   437  *
   438  *	Initializes audio device and start play process. This method queries and
   439  *	acquires the audio policy before initializing audio device. If there was an
   440  *	error during policy initialization, PlayError() method will be called on
   441  *	the observer with error code KErrAccessDenied, otherwise BufferToBeFilled()
   442  *	method will be called with a buffer reference. After reading data into the
   443  *	buffer reference passed, the client should call PlayData() to play data.
   444  *
   445  *	The amount of data that can be played is specified in
   446  *	CMMFBuffer::RequestSize(). Any data that is read into buffer beyond this
   447  *	size will be ignored.
   448  *
   449  *	Leaves on failure.
   450  *
   451  */
   452 void CMMFDevSoundSvrImp::PlayInitL()
   453 	{
   454 	if (!iDevSoundObserver)
   455 		User::Leave(KErrNotReady);
   456 
   457 	if (iAudioPolicyPrioritySettings.iState == EMMFStatePlayData)
   458 		{
   459 		// If policy has not been obtaing then ignore the request.
   460 		// If it has then do a stop and start action on HW device
   461 		// without informing policy.
   462 		
   463 		if (iHasPolicy)
   464 			{
   465 			if (iCMMFHwDevice)
   466 				{
   467 				TInt err = iCMMFHwDevice->Stop();
   468 				if (err == KErrNone)
   469 					{
   470 					err = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
   471 					}
   472 				
   473 				if (err != KErrNone)
   474 					{
   475 					Error(err);
   476 					}
   477 				}
   478 			}
   479 		return;
   480 		}
   481 
   482 	// Get audio policy
   483 	iAudioPolicyPrioritySettings.iState = EMMFStatePlayData;
   484 	RequestPolicy();
   485 	}
   486 
   487 /*
   488  *
   489  *	Initializes audio device and start record process. 
   490  *  This method:
   491  *  1. Queries and acquires the audio policy before initializing audio device. 
   492  *     If there was an error during policy initialization, RecordError() method will 
   493  *     be called on the observer with error code KErrAccessDenied, otherwise BufferToBeEmptied()
   494  *	   method will be called with a buffer reference. This buffer contains recorded
   495  *	   or encoded data. After processing data in the buffer reference passed, the
   496  *	   client should call RecordData() to continue recording process.
   497  *
   498  *  2. Checks if the requesting client process has a UserEnvironment capability.
   499  *     If it does not, the audio device will not be initialized and an error 
   500  *     code KErrAccessDenied will be sent to the client.
   501  *
   502  *	The amount of data that is available is specified in
   503  *	CMMFBuffer::RequestSize().
   504  *
   505  *	Leaves on failure.
   506  *
   507  */
   508 void CMMFDevSoundSvrImp::RecordInitL(const RMmfIpcMessage& aMessage)
   509 	{
   510 	if (!iDevSoundObserver)
   511 		User::Leave(KErrNotReady);
   512 	
   513 	// Checkes if the client has the UserEnvironment capability
   514 	if (!aMessage.HasCapability(ECapabilityUserEnvironment))
   515 		{
   516 		User::Leave(KErrPermissionDenied);
   517 		}
   518 
   519 	if (iAudioPolicyPrioritySettings.iState == EMMFStateRecordData)
   520 		{
   521 		if (iHasPolicy)
   522 			{
   523 			if (iCMMFHwDevice)
   524 				{
   525 				TInt err = iCMMFHwDevice->Stop();
   526 				if (err == KErrNone)
   527 					{
   528 					err = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
   529 					}
   530 				
   531 				if (err != KErrNone)
   532 					{
   533 					Error(err);
   534 					}
   535 				
   536 				if (iHwDeviceBuffer)
   537 					{
   538 					iHwDeviceBuffer->SetLastBuffer(EFalse);
   539 					}
   540 				}
   541 			}
   542 		
   543 		return;
   544 		}
   545 
   546 	// Get audio policy
   547 	iAudioPolicyPrioritySettings.iState = EMMFStateRecordData;
   548 	RequestPolicy();
   549 	}
   550 
   551 /*
   552  *
   553  *	Plays data in the buffer at the current volume. The client should fill
   554  *	the buffer with audio data before calling this method. The Observer gets
   555  *	reference to buffer along with callback BufferToBeFilled(). When playing of
   556  *	the audio sample is complete, successfully or otherwise, the method
   557  *	PlayError() on observer is called.
   558  *
   559  */
   560 TBool CMMFDevSoundSvrImp::PlayData(const RMmfIpcMessage& aMessage)
   561 	{
   562 	ASSERT(iDevSoundObserver);
   563 
   564 	if (iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
   565 		{
   566 		// Initialisation has been successful but an error (possibly underflow) has occurred
   567 		// which the controller has yet to respond to and that has changed the state to stopped.
   568 		// Allow the call to complete and processing to continue...  
   569 		return ETrue;
   570 		}
   571 
   572 	if((iAudioPolicyPrioritySettings.iState != EMMFStatePlayData) && (iAudioPolicyPrioritySettings.iState != EMMFStatePaused))
   573 		{
   574 		PanicClient(aMessage, EMMFDevSoundPlayDataWithoutInitialize);
   575 		return EFalse;
   576 		}
   577 	if (iMode== EMMFDevSoundStateIdle)
   578 		{
   579 		return ETrue;
   580 		}
   581 	TInt error = KErrNone;
   582     if(iCMMFHwDevice)
   583 	    {
   584 		if (iPaused)
   585 			{
   586 			iPaused = EFalse;
   587 			//note PlayData does not leave or return an error code so the Start() fails we cannot
   588 			//report the error back at this point
   589 			error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);//restart hw device after pause
   590 			}
   591 	   else if ((iMode == EMMFDevSoundStatePlaying) && iHasPolicy)
   592 		    {
   593 		    TInt len = iHwDeviceBuffer->Data().Length();
   594 		    if (iHwDeviceBuffer->LastBuffer())
   595 		    	{
   596 		    	iLastBufferReceived = ETrue;
   597 		    	}
   598 			// Pass the data buffer to HwDevice
   599 			error = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
   600             }
   601 		}
   602 	if (error != KErrNone)
   603 		{
   604 		Error(error);
   605 		if(iCMMFHwDevice)
   606 			{
   607 			iCMMFHwDevice->Stop();	
   608 			}
   609 
   610 		}
   611 	return ETrue;
   612 	}
   613  
   614 /*
   615  *
   616  *	Stops the ongoing operation (Play, Record, TonePlay, Convert)
   617  *
   618  */
   619 void CMMFDevSoundSvrImp::Stop()
   620 	{
   621 	iPaused = EFalse;
   622 
   623 	if (!iHasPolicy)
   624 		{
   625 		UpdatePolicyState(EMMFStateStopped);
   626 		return;
   627 		}
   628 
   629 	 // Stop the hw device first - this unloads sound drivers
   630     if (iCMMFHwDevice)
   631     	{
   632 		iCMMFHwDevice->Stop();
   633 		}
   634 
   635 	iDevSoundEventHandler->CancelReceiveEvents();
   636 
   637 	UpdatePolicyState(EMMFStateStopped);
   638 	__ASSERT_DEBUG(!(iHasPolicy&&(iMode == EMMFDevSoundStatePlaying)), Panic(TMMFDevSoundSessionPolicyNotInvalidated)); 
   639 	}
   640 
   641 /*
   642  *
   643  *	Temporarily Stops the ongoing operation (Play, Record, TonePlay, Convert)
   644  *
   645  */
   646 void CMMFDevSoundSvrImp::Pause()
   647 	{
   648 	iPaused = ETrue;
   649 
   650 	if (!iHasPolicy)
   651 		{
   652 		return;
   653 		}
   654 
   655 	// Pause the HW device first
   656 	if (iCMMFHwDevice)
   657 		{
   658 		iCMMFHwDevice->Pause();
   659 		}
   660 	}
   661 
   662 /*
   663  *
   664  *	Returns the sample recorded so far.
   665  *
   666  *	@return "TInt"
   667  *			Returns the samples recorded.
   668  *
   669  */
   670 TInt CMMFDevSoundSvrImp::SamplesRecorded()
   671 	{
   672 	TInt samples = 0;
   673 	
   674 	if(iRecordCustomInterface)
   675 		{
   676 		samples = iRecordCustomInterface->BytesRecorded();
   677 		if(NumberOfChannels() > 1)
   678 			{
   679 			samples /= NumberOfChannels();
   680 			}
   681 		if(BytesPerAudioSample() > 1)
   682 			{
   683 			samples /= BytesPerAudioSample();
   684 			}
   685 		}
   686 
   687 	return samples;
   688 	}
   689 
   690 /*
   691  *
   692  *	Returns the sample played so far.
   693  *
   694  *	@return "TInt"
   695  *			Returns the samples recorded.
   696  *
   697  */
   698 TInt CMMFDevSoundSvrImp::SamplesPlayed()
   699 	{
   700 	TInt samples = 0;
   701 	if(iPlayCustomInterface)
   702 		{
   703 		TUint bytesPlayed = iPlayCustomInterface->BytesPlayed();
   704 		if (bytesPlayed)
   705 			iPlayedBytesCount = bytesPlayed;
   706 
   707 		samples = iPlayedBytesCount;
   708 		if(NumberOfChannels() > 1)
   709 			samples /= NumberOfChannels();
   710 
   711 		if(BytesPerAudioSample() > 1)
   712 			samples /= BytesPerAudioSample();
   713 		}
   714 	//note always pcm16 becuase the iPlayedBytesCount originates from 
   715 	//RMdaDevSound which is always pcm16
   716 	return samples; //each sample is 2 bytes
   717 	}
   718 
   719 
   720 /*
   721  *
   722  *	Initializes audio device and start playing tone. Tone is played with
   723  *	frequency and for duration specified.
   724  *
   725  *	Leaves on failure.
   726  *
   727  *	@param	"TInt aFrequency"
   728  *			Frequency at with the tone will be played.
   729  *
   730  *	@param	"TTimeIntervalMicroSeconds& aDuration"
   731  *			The period over which the tone will be played. A zero value causes
   732  *			the no tone to be played (Verify this with test app).
   733  *
   734  */
   735 void CMMFDevSoundSvrImp::PlayToneL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration)
   736 	{
   737 	if (iMode != EMMFDevSoundStateTonePlaying)
   738 		{
   739 		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
   740 		}
   741 
   742 	// Check whether frequency and duration is valid or not
   743 	TInt64 zeroInt64(0);
   744 	if ((aFrequency<0) || (aDuration.Int64() < zeroInt64))
   745 		{
   746 		User::Leave(KErrArgument);
   747 		}
   748 
   749 	if (!iDevSoundObserver)
   750 		{
   751 		User::Leave(KErrNotReady);
   752 		}
   753 
   754 	iToneGen.SetFrequencyAndDuration(aFrequency,aDuration);
   755 
   756 	// Get audio policy
   757 	iAudioPolicyPrioritySettings.iState = EMMFStatePlayTone;
   758 	RequestPolicy();
   759 	}
   760 
   761 /*
   762  *	Initializes audio device and start playing a dual tone. 
   763  *  The tone consists of two sine waves of different frequencies summed together
   764  *  Dual Tone is played with specified frequencies and for specified duration.
   765  *
   766  *	@param	"aFrequencyOne"
   767  *			First frequency of dual tone
   768  *
   769  *	@param	"aFrequencyTwo"
   770  *			Second frequency of dual tone
   771  *
   772  *	@param	"aDuration"
   773  *			The period over which the tone will be played. A zero value causes
   774  *			the no tone to be played (Verify this with test app).
   775  */
   776 void CMMFDevSoundSvrImp::PlayDualToneL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration)
   777 	{
   778 	if (!iDevSoundObserver)
   779 		{
   780 		User::Leave(KErrNotReady);
   781 		}
   782 	
   783 	// Check whether frequencies and duration are valid or not
   784 	TInt64 zeroInt64(0);
   785 	if ((aFrequencyOne<0) || (aFrequencyTwo<0) || (aDuration.Int64() < zeroInt64))
   786 		{
   787 		iDevSoundObserver->ToneFinished(KErrArgument);
   788 		return;
   789 		}
   790 
   791 
   792 	iDualToneGen.SetFrequencyAndDuration(aFrequencyOne, aFrequencyTwo, aDuration);
   793 
   794 	// Get audio policy
   795 	iAudioPolicyPrioritySettings.iState = EMMFStatePlayDualTone;
   796 	RequestPolicy();
   797 	}
   798 
   799 /*
   800  *
   801  *	Initializes audio device and start playing DTMF string aDTMFString.
   802  *
   803  *	Leaves on failure.
   804  *
   805  *	@param	"TDesC& aDTMFString"
   806  *			DTMF sequence in a descriptor.
   807  *
   808  */
   809 void CMMFDevSoundSvrImp::PlayDTMFStringL(const TDesC& aDTMFString)
   810 	{
   811 	if (!iDevSoundObserver)
   812 		User::Leave(KErrNotReady);
   813 
   814 	if (iMode!= EMMFDevSoundStateTonePlaying)
   815 		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
   816 
   817 	iDTMFGen.SetString(aDTMFString);
   818 
   819 	// Get audio policy
   820 	iAudioPolicyPrioritySettings.iState = EMMFStatePlayDTMFString;
   821 	RequestPolicy();
   822 	}
   823 
   824 /*
   825  *
   826  *	Initializes audio device and start playing tone sequence.
   827  *
   828  *	Leaves on failure.
   829  *
   830  *	@param	"TDesC8& aData"
   831  *			Tone sequence in a descriptor.
   832  *
   833  */
   834 void CMMFDevSoundSvrImp::PlayToneSequenceL(const TDesC8& aData)
   835 	{
   836 	if (!iDevSoundObserver)
   837 		User::Leave(KErrNotReady);
   838 
   839 	if (iMode!= EMMFDevSoundStateTonePlaying)
   840 		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
   841 
   842 	// Check whether the sequence is valid or not
   843 	if (!iDevSoundUtil->RecognizeSequence(aData))
   844 		User::Leave(KErrCorrupt);
   845 
   846 	iSequenceGen.SetSequenceData(aData);
   847 
   848 	// Get audio policy
   849 	iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
   850 	RequestPolicy();
   851 	}
   852 
   853 /*
   854  *
   855  *	Initializes audio device and start playing the specified pre-defined tone
   856  *	sequence.
   857  *
   858  *	Leaves on failure.
   859  *
   860  *	@param	"TInt aSequenceNumber"
   861  *			The index identifying the specific pre-defined tone sequence. Index
   862  *			values are relative to zero.
   863  *			This can be any value from zero to the value returned by a call to
   864  *			FixedSequenceCount() - 1.
   865  *			The function raises a panic if sequence number is not within this
   866  *			range.
   867  *
   868  *	@see	FixesSequenceCount()
   869  *
   870  */
   871 void CMMFDevSoundSvrImp::PlayFixedSequenceL(TInt aSequenceNumber)
   872 	{
   873 	if (!iDevSoundObserver)
   874 		User::Leave(KErrNotReady);
   875 
   876 	if (iMode!= EMMFDevSoundStateTonePlaying)
   877 		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
   878 
   879 	ASSERT((aSequenceNumber >= 0)&&(aSequenceNumber < iFixedSequences->Count()));
   880 
   881 	iFixedSequence.Set(iFixedSequences->MdcaPoint(aSequenceNumber));
   882 	iSequenceGen.SetSequenceData(iFixedSequence);
   883 
   884 	// Get audio policy
   885 	iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
   886 	RequestPolicy();
   887 	}
   888 
   889 /*
   890  *
   891  *	Defines the duration of tone on, tone off and tone pause to be used during the
   892  *	DTMF tone playback operation.
   893  *
   894  *	Supported only during tone playing.
   895  *
   896  *	@param	"TTimeIntervalMicroSeconds32& aToneOnLength"
   897  *			The period over which the tone will be played. If this is set to
   898  *			zero, then the tone is not played.
   899  *
   900  *	@param	"TTimeIntervalMicroSeconds32& aToneOffLength"
   901  *			The period over which the no tone will be played.
   902  *
   903  *	@param	"TTimeIntervalMicroSeconds32& aPauseLength"
   904  *			The period over which the tone playing will be paused.
   905  *
   906  */
   907 void CMMFDevSoundSvrImp::SetDTMFLengths(TTimeIntervalMicroSeconds32& aToneOnLength,
   908 								TTimeIntervalMicroSeconds32& aToneOffLength,
   909 								TTimeIntervalMicroSeconds32& aPauseLength) 
   910 	{
   911 
   912 	if(aToneOnLength.Int() < KMdaInfiniteDurationDTMFToneOnLength)
   913 		aToneOnLength = TTimeIntervalMicroSeconds32(0);
   914 	if(aToneOffLength.Int() < 0)
   915 		aToneOffLength = TTimeIntervalMicroSeconds32(0);
   916 	if(aPauseLength.Int() < 0)
   917 		aPauseLength = TTimeIntervalMicroSeconds32(0);
   918 
   919 	iDTMFGen.SetToneDurations(aToneOnLength,aToneOffLength,aPauseLength);
   920 	}
   921 
   922 /*
   923  *
   924  *	Defines the period over which the volume level is to rise smoothly from
   925  *	nothing to the normal volume level.
   926  *
   927  *	@param	"TTimeIntervalMicroSeconds& aRampDuration"
   928  *			The period over which the volume is to rise. A zero value causes 
   929  *			the tone sample to be played at the normal level for the full
   930  *			duration of the playback. A value, which is longer than the duration
   931  *			of the tone sample, that the sample never reaches its normal
   932  *			volume level.
   933  *
   934  *
   935  */
   936 void CMMFDevSoundSvrImp::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
   937 	{
   938 	// save ramp duration for tone generator
   939 	iRampDuration = aRampDuration;
   940 
   941 	SetDeviceVolumeRamp(iRampDuration);
   942 	}
   943 
   944 /**
   945  *	Sets volume ramp on HwDevice.
   946  */
   947 TInt CMMFDevSoundSvrImp::SetDeviceVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
   948 	{
   949 	TInt error = KErrNone;
   950 	if (iPlayCustomInterface) 
   951 		iPlayCustomInterface->SetVolumeRamp(aRampDuration);
   952 	else
   953 		error = KErrNotReady;
   954 	return error;
   955     }
   956 
   957 /**
   958  *	@see sounddevice.h
   959  */
   960 void CMMFDevSoundSvrImp::GetSupportedInputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
   961 	{
   962 	//aPrioritySettings not used on ref DevSound
   963 	//search for playing datatypes
   964 	iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStatePlaying);
   965 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
   966 	// append list of codec plugins
   967 	iDevSoundUtil->SeekCodecPluginsL(aSupportedDataTypes, EMMFStatePlaying, ETrue);
   968 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
   969 	}
   970 
   971 /**
   972  *	@see sounddevice.h
   973  */
   974 void CMMFDevSoundSvrImp::GetSupportedOutputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
   975 	{
   976 	//aPrioritySettings not used on ref DevSound
   977 	// search for recording datatypes
   978 	iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStateRecording);
   979 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
   980 	// append list of codec plugins
   981 	iDevSoundUtil->SeekCodecPluginsL(aSupportedDataTypes, EMMFStateRecording, ETrue);
   982 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
   983 	}
   984 	
   985 TInt CMMFDevSoundSvrImp::RegisterAsClient(TUid aEventType, const TDesC8& aNotificationRegistrationData)
   986 	{	
   987 	return iAudioPolicyProxy->RequestResourceNotification(aEventType,aNotificationRegistrationData);
   988 	}
   989 	
   990 TInt CMMFDevSoundSvrImp::CancelRegisterAsClient(TUid aEventType)
   991 	{	
   992 	return iAudioPolicyProxy->CancelRequestResourceNotification(aEventType);
   993 	}
   994 
   995 TInt CMMFDevSoundSvrImp::GetResourceNotificationData(TUid aEventType, TDes8& aNotificationData)
   996 	{	
   997 	TInt err = KErrNone;
   998 	err = iAudioPolicyProxy->IsRegisteredResourceNotification(aEventType);
   999 	if(err == KErrNone)
  1000 		{
  1001 		TMMFTimeIntervalMicroSecondsPckg pckg = TTimeIntervalMicroSeconds(SamplesPlayed());
  1002 		aNotificationData.Copy(pckg);
  1003 		}
  1004 	return err;
  1005 	}
  1006 	
  1007 TInt CMMFDevSoundSvrImp::WillResumePlay()
  1008 	{
  1009 	return iAudioPolicyProxy->StopNotification();
  1010 	}	
  1011 	
  1012 TInt CMMFDevSoundSvrImp::EmptyBuffers()
  1013 	{
  1014 	TInt err = KErrNone;
  1015 	if (iMode != EMMFStatePlaying)
  1016 		{
  1017 		return KErrNotSupported;
  1018 		}
  1019 	if (!iCMMFHwDevice)
  1020 		{
  1021 		return KErrNotReady;			
  1022 		}	
  1023 	MEmptyBuffersCustomInterface* emptybuffers = reinterpret_cast<MEmptyBuffersCustomInterface*>(iCMMFHwDevice->CustomInterface(KEmptyBuffersCustomInterfaceTypeUid));	
  1024 	if (emptybuffers)
  1025     	{
  1026        	err = emptybuffers->EmptyBuffers();
  1027      	}
  1028     else
  1029 		{
  1030      	err = KErrNotSupported;
  1031      	}
  1032     return err;	
  1033 	}	
  1034 
  1035 TInt CMMFDevSoundSvrImp::GetTimePlayed(TTimeIntervalMicroSeconds& aTime)
  1036 	{
  1037 	TInt err = KErrNone;
  1038 	TTimeIntervalMicroSeconds time(0);
  1039 	if(iCMMFHwDevice)
  1040 		{
  1041 		if(!iTimePlayedCustomInterface)
  1042 			{
  1043 			iTimePlayedCustomInterface = reinterpret_cast<MTimePlayedCustomInterface*>(iCMMFHwDevice->CustomInterface(KTimePlayedCustomInterfaceTypeUid));
  1044 			if(iTimePlayedCustomInterface == NULL)
  1045 				{
  1046 				return KErrNotSupported;
  1047 				}
  1048 			}
  1049 		err = iTimePlayedCustomInterface->GetTimePlayed(time);
  1050 	    if(err == KErrNone && time.Int64() > 0)
  1051 	    	{
  1052 	    	iTimePlayed = time.Int64();
  1053 	    	}
  1054 		}
  1055 	aTime = iTimePlayed.Int64();
  1056 	return err;
  1057 	}
  1058 
  1059 /********************************************************************************
  1060  *				Implementations of Non Exported public functions begins here	*
  1061  ********************************************************************************/
  1062 
  1063 //
  1064 //				Audio Policy specific implementation begins here				//
  1065 //
  1066 
  1067 /*
  1068  *
  1069  *	Called by Audio Policy Server when a request to play is approved by the 
  1070  *	Audio Policy Server.
  1071  *
  1072  *	Leaves on failure??.
  1073  *
  1074  */
  1075 void CMMFDevSoundSvrImp::StartPlayDataL()
  1076 	{
  1077 	ASSERT(iMode== EMMFDevSoundStatePlaying);
  1078 	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
  1079 		{
  1080 		return;
  1081 		}
  1082 	iHasPolicy = ETrue;
  1083 
  1084 	TInt error = KErrNone;
  1085 
  1086 	if(iCMMFHwDevice)
  1087 		{
  1088 		UpdatePolicyState(EMMFStatePlayData);		
  1089         // Set volume and play format values
  1090         error = SetPlayFormat(iPlayFormat);
  1091         if (error == KErrNone)
  1092 			error = SetDeviceVolume(iVolume);
  1093         if (error == KErrNone)
  1094 			error = SetDeviceVolumeRamp(iRampDuration);
  1095 
  1096 		// Initialize attribute values
  1097 		iPlayedBytesCount = 0;
  1098 		iTimePlayed = 0;
  1099 		iLastBufferReceived = EFalse;
  1100 
  1101         // Start HwDevice
  1102         if (error == KErrNone)
  1103 	        error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
  1104 		}
  1105 	else
  1106 		error = KErrNotReady;
  1107 	
  1108 	if (error != KErrNone)
  1109 		{
  1110 		Error(error);
  1111 
  1112 		}
  1113 	}
  1114 
  1115 /*
  1116  *
  1117  *	Called by Audio Policy Server when a request to record is approved by the 
  1118  *	Audio Policy Server.
  1119  *
  1120  *	Leaves on failure.
  1121  *
  1122  */
  1123 void CMMFDevSoundSvrImp::StartRecordDataL()
  1124 	{
  1125 	ASSERT(iMode== EMMFDevSoundStateRecording);
  1126 	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
  1127 		{
  1128 		return;
  1129 		}
  1130 	iHasPolicy = ETrue;
  1131 
  1132 	 if(iCMMFHwDevice)
  1133 		{
  1134 		UpdatePolicyState(EMMFStateRecordData);
  1135         TInt error = KErrNone;
  1136         error = SetRecordFormat(iRecordFormat);
  1137 		if (error != KErrNone)
  1138 			{
  1139 			Error(error);
  1140 			return;
  1141 
  1142 			}
  1143         error = SetDeviceRecordLevel(iGain);
  1144 		if (error != KErrNone)
  1145 			{
  1146 			Error(error);
  1147 			return;
  1148 
  1149 			}
  1150         error = iCMMFHwDevice->Start(EDevEncode, EDevInFlow);
  1151 		if (iHwDeviceBuffer)
  1152 			iHwDeviceBuffer->SetLastBuffer(EFalse);
  1153 
  1154 		if (error != KErrNone)
  1155 			{
  1156 			Error(error);
  1157 			return;
  1158 			}
  1159         }
  1160 	else
  1161 		iDevSoundObserver->RecordError(KErrNotReady);
  1162 	}
  1163 
  1164 /*
  1165  *
  1166  *	Called by Audio Policy Server when a request to play tone is approved by
  1167  *	the Audio Policy Server.
  1168  *
  1169  *	Leaves on failure.
  1170  *
  1171  */
  1172 void CMMFDevSoundSvrImp::StartPlayToneL()
  1173 	{
  1174 	ASSERT(iMode == EMMFDevSoundStateTonePlaying);
  1175 	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
  1176 		{
  1177 		return;
  1178 		}
  1179 	iHasPolicy = ETrue;
  1180 	
  1181 	if(iCMMFHwDevice)
  1182 		{
  1183 		UpdatePolicyState(EMMFStatePlayTone);
  1184         TInt error = KErrNone;
  1185         // Set volume and play format values
  1186         error = SetPlayFormat(iPlayFormat);
  1187 		if (error != KErrNone)
  1188 			{
  1189 			Error(error);
  1190 			return;
  1191 
  1192 			}
  1193         if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
  1194             error = SetDeviceVolume(iVolume);
  1195 		else
  1196 			error = KErrGeneral;//hw device should always be pcm16 for tone
  1197 
  1198 		// turn off volume ramping - this is done in software below
  1199         if (error == KErrNone)
  1200 			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
  1201 
  1202         if (error != KErrNone)
  1203             {
  1204             Error(error);
  1205             return;
  1206 
  1207             }
  1208 
  1209         // Initialize attribute values
  1210 		iPlayedBytesCount = 0;
  1211 		iTimePlayed = 0;
  1212         // Configure tone generator
  1213         iToneGen.Configure(
  1214 			iPlayFormat().iRate,
  1215 			iPlayFormat().iChannels,
  1216 		    iRepeatCount,
  1217 			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
  1218 			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
  1219 			);
  1220 
  1221 		iCurrentGenerator = &iToneGen;
  1222 
  1223         // Start playback
  1224         DoPlayL();
  1225 		}
  1226 	else
  1227 		iDevSoundObserver->ToneFinished(KErrNotReady);
  1228 	}
  1229 
  1230 /*
  1231  *
  1232  *	Called by Audio Policy Server when a request to play a dual tone is approved by
  1233  *	the Audio Policy Server.
  1234  *
  1235  */
  1236 void CMMFDevSoundSvrImp::StartPlayDualToneL()
  1237 	{
  1238 	ASSERT(iMode == EMMFDevSoundStateTonePlaying);
  1239 	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
  1240 		{
  1241 		return;
  1242 		}
  1243 	iHasPolicy = ETrue;
  1244 
  1245 	 if(iCMMFHwDevice)
  1246 		{
  1247 		UpdatePolicyState(EMMFStatePlayDualTone);
  1248         TInt error = KErrNone;
  1249         // Set volume and play format values
  1250         error = SetPlayFormat(iPlayFormat);
  1251 		if (error != KErrNone)
  1252 			{
  1253 			Error(error);
  1254 			return;
  1255 			}
  1256         if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
  1257             error = SetDeviceVolume(iVolume);
  1258 		else 
  1259 			error = KErrGeneral;//hw device should always be pcm16 for tone
  1260 
  1261 		// turn off volume ramping - this is done in software below
  1262         if (error == KErrNone)
  1263 			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
  1264 
  1265         if (error != KErrNone)
  1266             {
  1267             Error(error);
  1268             return;
  1269 
  1270             }
  1271 
  1272         // Initialize attribute values
  1273 		iPlayedBytesCount = 0;
  1274 		iTimePlayed = 0;
  1275         // Configure dual tone generator
  1276 		iDualToneGen.Configure(
  1277 			iPlayFormat().iRate,
  1278 			iPlayFormat().iChannels,
  1279 			iRepeatCount,
  1280 			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds),
  1281 			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds)
  1282 			);
  1283 
  1284 		iCurrentGenerator = &iDualToneGen;
  1285 
  1286         // Start playback
  1287         DoPlayL();
  1288 		}
  1289 	else
  1290 		iDevSoundObserver->ToneFinished(KErrNotReady);
  1291 	}
  1292 
  1293 /*
  1294  *
  1295  *	Called by Audio Policy Server when a request to play DTMF String is approved
  1296  *	by the Audio Policy Server.
  1297  *
  1298  *	Leaves on failure.
  1299  *
  1300  */
  1301 void CMMFDevSoundSvrImp::StartPlayDTMFStringL()
  1302 	{
  1303 	ASSERT(iMode == EMMFDevSoundStateTonePlaying);
  1304 	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
  1305 		{
  1306 		return;
  1307 		}
  1308 	iHasPolicy = ETrue;
  1309 
  1310 	if(iCMMFHwDevice)
  1311 		{
  1312 		UpdatePolicyState(EMMFStatePlayDTMFString);
  1313         TInt error = KErrNone;
  1314         // Set volume and play format values
  1315         error = SetPlayFormat(iPlayFormat);
  1316 		if (error != KErrNone)
  1317             {
  1318             Error(error);
  1319             return;
  1320 
  1321             }
  1322         error = SetDeviceVolume(iVolume);
  1323 
  1324 		// turn off volume ramping - this is done in software below
  1325         if (error == KErrNone)
  1326 			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
  1327 
  1328         if (error != KErrNone)
  1329             {
  1330             Error(error);
  1331             return;
  1332             }
  1333 
  1334         // Initialize attribute values
  1335 		iPlayedBytesCount = 0;
  1336 		iTimePlayed = 0;
  1337 	    iDTMFGen.Configure(
  1338 			iPlayFormat().iRate,
  1339 			iPlayFormat().iChannels,
  1340 		    iRepeatCount,
  1341 			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
  1342 		    I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
  1343 			);
  1344 
  1345 		iCurrentGenerator = &iDTMFGen;
  1346 
  1347         // Start playback
  1348 		//need to trap this as we can leave with KErrUnderflow
  1349 		//if there was no data to play - the error has already
  1350 		//been sent to the observer and we don't want to call RunError
  1351         TRAP(error,DoPlayL());
  1352 		if ((error != KErrUnderflow)&&(error != KErrNone))
  1353 			{
  1354 			User::Leave(error);
  1355 			}
  1356 		}
  1357 	else
  1358 		iDevSoundObserver->ToneFinished(KErrNotReady);
  1359 	}
  1360 
  1361 /*
  1362  *
  1363  *	Called by Audio Policy Server when a request to play tone sequence is
  1364  *	approved by the Audio Policy Server.
  1365  *
  1366  *	Leaves on failure.
  1367  *
  1368  */
  1369 void CMMFDevSoundSvrImp::StartPlayToneSequenceL()
  1370 	{
  1371 	ASSERT(iMode == EMMFDevSoundStateTonePlaying);
  1372 	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
  1373 		{
  1374 		return;
  1375 		}
  1376 	iHasPolicy = ETrue;
  1377 
  1378 	if(iCMMFHwDevice)
  1379 		{
  1380 		UpdatePolicyState(EMMFStatePlayToneSequence);
  1381         TInt error = KErrNone;
  1382         // Set volume and play format values
  1383         if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
  1384             error = SetPlayFormat(iPlayFormat);
  1385 			else error = KErrGeneral;//hw device should always be pcm16 for tone
  1386 		if (error != KErrNone)
  1387             {
  1388             Error(error);
  1389             return;
  1390             }
  1391 
  1392         if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
  1393             error = SetDeviceVolume(iVolume);
  1394 		else 
  1395 			error = KErrGeneral;//hw device should always be pcm16 for tone
  1396 
  1397 		// turn off volume ramping - this is done in software below
  1398         if (error == KErrNone)
  1399 			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
  1400 
  1401         if (error != KErrNone)
  1402             {
  1403             Error(error);
  1404             return;
  1405             }
  1406 
  1407         // Initialize attribute values
  1408 		iPlayedBytesCount = 0;
  1409 		iTimePlayed = 0;
  1410 		iSequenceGen.Configure(
  1411 			iPlayFormat().iRate,
  1412 			iPlayFormat().iChannels,
  1413 			iRepeatCount,
  1414 			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
  1415 			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
  1416 			);
  1417 
  1418 		iCurrentGenerator = &iSequenceGen;
  1419 
  1420         // Start playback
  1421         DoPlayL();
  1422 		}
  1423 	else
  1424 		iDevSoundObserver->ToneFinished(KErrNotReady);
  1425 	}
  1426 
  1427 /*
  1428  *
  1429  *	Called by Audio Policy Server when the current DevSound instance looses the
  1430  *	policy because of another instance with a higher priority wants the device.
  1431  *
  1432  */
  1433 void CMMFDevSoundSvrImp::SendEventToClient(const TMMFEvent& aEvent)
  1434 	{
  1435 	if (aEvent.iErrorCode != KErrNone)
  1436 		{
  1437 		iHasPolicy = EFalse;
  1438 		if (iMode == EMMFDevSoundStatePlaying)
  1439 			{
  1440 			UpdateBytesPlayed();
  1441 			iDevSoundObserver->PlayError(aEvent.iErrorCode);
  1442 			UpdatePolicyState(EMMFStateStopped);
  1443 			}
  1444 		else if (iMode == EMMFDevSoundStateRecording)
  1445 			{
  1446 			iDevSoundObserver->RecordError(aEvent.iErrorCode);
  1447 			UpdatePolicyState(EMMFStateStopped);
  1448 			}
  1449 		else if (iMode == EMMFDevSoundStateTonePlaying)
  1450 			{
  1451 			iDevSoundObserver->ToneFinished(aEvent.iErrorCode);
  1452 			}			
  1453 		iCMMFHwDevice->Stop();//unloads sound device
  1454 		// Have audio Policy launch higher priority request
  1455 		iAudioPolicyProxy->LaunchRequests();
  1456 		}
  1457 	else
  1458 		{
  1459 		iHasPolicy = ETrue;
  1460 		iDevSoundObserver->SendEventToClient(aEvent);
  1461 		}
  1462 	}
  1463 
  1464 
  1465 /**
  1466  *
  1467  *	Sets volume on HwDevice.
  1468  *	
  1469  *	@return	"TInt"
  1470  *			Error value returned by HwDevice.
  1471  *
  1472  */
  1473 TInt CMMFDevSoundSvrImp::SetDeviceVolume(TInt aVolume)
  1474 	{
  1475 	TInt error = KErrNone;
  1476 	if (iPlayCustomInterface) 
  1477 		iPlayCustomInterface->SetVolume(aVolume);
  1478 	else error = KErrNotReady;
  1479 	return error;
  1480     }
  1481 
  1482 /**
  1483  *
  1484  *	Sets PlayFormat on HwDevice.
  1485  *	
  1486  *
  1487  *	@return	"TInt"
  1488  *			Error value returned by HwDevice.
  1489  *
  1490  */
  1491 TInt CMMFDevSoundSvrImp::SetPlayFormat(RMdaDevSound::TCurrentSoundFormatBuf& aPlayFormat)
  1492 	{
  1493 	TInt error = KErrNone;
  1494 	if (iCMMFHwDevice)
  1495 		{
  1496 		TTaskConfig taskConfig;
  1497 		taskConfig.iUid = KUidRefDevSoundTaskConfig;
  1498 		taskConfig.iRate = aPlayFormat().iRate;
  1499 		
  1500 		if (aPlayFormat().iChannels == 1)
  1501 			{
  1502 			taskConfig.iStereoMode = ETaskMono;
  1503 			}
  1504 		else if (aPlayFormat().iChannels == 2)
  1505 			{
  1506 			taskConfig.iStereoMode = ETaskInterleaved;
  1507 			}
  1508 		else
  1509 			{
  1510 			return KErrArgument;
  1511 			}
  1512 
  1513 		error = iCMMFHwDevice->SetConfig(taskConfig);
  1514 		//note the iEncoding and iBufferSize are already determined by the 
  1515 		//CMMFHwDevice plugin and so are not set.
  1516 		}
  1517 	else
  1518 		{
  1519 		error = KErrNotReady;
  1520 		}
  1521 	return error;
  1522     }
  1523 
  1524 
  1525 /**
  1526  *
  1527  *	Sets RecordFormat on HwDevice.
  1528  *	
  1529  *
  1530  *	@return	"TInt"
  1531  *			Error value returned by HwDevice.
  1532  *
  1533  */
  1534 TInt CMMFDevSoundSvrImp::SetRecordFormat(RMdaDevSound::TCurrentSoundFormatBuf& aRecordFormat)
  1535 	{
  1536 	TInt error = KErrNone;
  1537 	if (iCMMFHwDevice)
  1538 		{
  1539 		TTaskConfig taskConfig;
  1540 		taskConfig.iUid = KUidRefDevSoundTaskConfig;
  1541 		taskConfig.iRate = aRecordFormat().iRate;
  1542 
  1543 		if (aRecordFormat().iChannels == 1)
  1544 			{
  1545 			taskConfig.iStereoMode = ETaskMono;
  1546 			}
  1547 		else if (aRecordFormat().iChannels == 2)
  1548 			{
  1549 			taskConfig.iStereoMode = ETaskInterleaved;
  1550 			}
  1551 		else
  1552 			{
  1553 			return KErrArgument;
  1554 			}
  1555 
  1556 		error = iCMMFHwDevice->SetConfig(taskConfig);
  1557 		//note the iEncoding and iBufferSize are already determined by the 
  1558 		//CMMFHwDevice plugin and so are not set.
  1559 		}
  1560 	else
  1561 		{
  1562 		error = KErrNotReady;
  1563 		}
  1564 	return error;
  1565     }
  1566 
  1567 
  1568 /**
  1569  *
  1570  *	Sets record level on HwDevice.
  1571  *	
  1572  *
  1573  *	@return	"TInt"
  1574  *			Error value returned by HwDevice.
  1575  *
  1576  */
  1577 TInt CMMFDevSoundSvrImp::SetDeviceRecordLevel(TInt aGain)
  1578 	{
  1579 	TInt error = KErrNone;
  1580 	if (iRecordCustomInterface) 
  1581 		iRecordCustomInterface->SetGain(aGain);
  1582 	else error = KErrNotReady;
  1583 	return error;
  1584 
  1585     }
  1586 
  1587 
  1588 /**
  1589  *
  1590  *	MMMFHwDeviceObserver mixin implementation.
  1591  *
  1592  *	The CMMFHwDevice implementation object calls this method during decoding
  1593  *	(playing), when it needs the encoded data in the buffer
  1594  *	aHwDataBuffer.
  1595  *
  1596  *	@return	"TInt"
  1597  *			Error code. KErrNone if success.
  1598  *
  1599  */
  1600 TInt CMMFDevSoundSvrImp::FillThisHwBuffer(CMMFBuffer& aHwDataBuffer)
  1601 	{
  1602 	TInt err = KErrNone;
  1603     // Keep a reference to this Hw data Buffer. We need to send the 
  1604 	// reference back to HwDevice implementation
  1605 	iHwDeviceBuffer = static_cast<CMMFDataBuffer*> (&aHwDataBuffer);
  1606 	// Set the request length, From HwDevice this comes with buffer
  1607 	// length.
  1608 	TInt len = iHwDeviceBuffer->Data().MaxLength();
  1609 	// Ignore error. since buffer size = Buffer Length 
  1610 	TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
  1611 
  1612 	if (iMode== EMMFDevSoundStatePlaying) // Get Data from Observer
  1613 		{
  1614 		if (iLastBufferReceived)
  1615 			{
  1616 			iHwDeviceBuffer->Data().SetLength(0);
  1617 			// Pass the buffer to the he device
  1618             err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
  1619 			}
  1620 		else
  1621 			// Pass the buffer to the observer
  1622 			iDevSoundObserver->BufferToBeFilled(&aHwDataBuffer);
  1623 		}
  1624 	else if (iMode == EMMFDevSoundStateTonePlaying)
  1625 		{
  1626         // Hw device will call this method right after its Start was called.
  1627         // When it calls this for the first time it hasn't played one single
  1628         // buffer yet so check that.
  1629         // In this case there's no need to set the active buffer as it's already
  1630         // waiting to be played.
  1631         if (!iFirstCallFromHwDevice)
  1632             SetActiveToneBuffer();
  1633 
  1634 		// If there is no data in the active buffer, tone play is finished.
  1635 		// DevSound just have to wait for completion event from audio device.
  1636 		if (iActiveToneBuffer->Data().Length() > 0)
  1637             { 
  1638 			TInt tonelen = iActiveToneBuffer->Data().Length();
  1639 
  1640 			// don't enter more data than can be handled by the receiving buffer
  1641 			if (len >= tonelen) len = tonelen;
  1642 
  1643             // Copy data from tone buffer to hw device buffer
  1644             Mem::Copy((TAny*)(iHwDeviceBuffer->Data().Ptr()), (TAny*)(iActiveToneBuffer->Data().Ptr()), len);
  1645             
  1646             iHwDeviceBuffer->Data().SetLength(len);
  1647             // Play data and try to generate next data block
  1648 			err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
  1649             if (err != KErrNone)
  1650             	return err;
  1651             // Check again whether this is the first call from Hw device.
  1652             // FillFreeToneBuffer assumes the iActiveToneBuffer has already
  1653             // been played.
  1654             if (!iFirstCallFromHwDevice)
  1655                 err = FillFreeToneBuffer();
  1656             else
  1657                 iFirstCallFromHwDevice = EFalse;  // Reset flag
  1658 
  1659  			}
  1660 		else if (iFirstCallFromHwDevice)
  1661 			{//we have no data in the tone buffer and thus have no 
  1662 			//outstanding requests to play
  1663 			err = KErrUnderflow; //simulate underrun
  1664 			}
  1665 		else
  1666 			{
  1667 			iHwDeviceBuffer->Data().SetLength(0);
  1668 			iHwDeviceBuffer->SetLastBuffer(ETrue);
  1669             // Send an empty last buffer to HwDevice to get a play completion event with KErrUnderflow
  1670 			err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
  1671 			}
  1672 	
  1673 		// If there was an error filling the buffer could be corrupt data
  1674 		// notify the client and stop playing.Set err to KErrNone. 
  1675 		if (err != KErrNone)
  1676 			{
  1677 			Error(err);//Updates Bytes played informs client
  1678 			err = KErrNone;
  1679 			iCMMFHwDevice->Stop();//unloads sound device
  1680             }
  1681 		}
  1682 	else
  1683 		{
  1684 		err = KErrGeneral;
  1685 		Error(err);
  1686 		iCMMFHwDevice->Stop();//unloads sound device
  1687 
  1688 		}
  1689 	return err;
  1690 	}
  1691 
  1692 
  1693 /**
  1694  *
  1695  *	MMMFHwDeviceObserver mixin implementation.
  1696  *
  1697  *	The CMMFHwDevice implementation object calls this method during encoding
  1698  *	(recording), when it fills the buffer aHwDataBuffer with
  1699  *	encoded data.
  1700  *
  1701  *	@return	"TInt"
  1702  *			Error code. KErrNone if success.
  1703  *
  1704  */
  1705 TInt CMMFDevSoundSvrImp::EmptyThisHwBuffer(CMMFBuffer& aHwDataBuffer)
  1706 	{
  1707 	TInt err = KErrNone;
  1708 	if(iMode== EMMFDevSoundStateRecording)
  1709 		{
  1710 		// Keep a reference to this Hw data Buffer. We need to send the 
  1711 		// reference back to HwDevice implementation
  1712 		iHwDeviceBuffer = static_cast<CMMFDataBuffer*>(&aHwDataBuffer);
  1713 
  1714 		// Set the request length, From HwDevice this comes with buffer
  1715 		// length. MMF will use RequestSize attribute of the buffer.
  1716 		// We can avoid this by setting in HwDevice implemenation
  1717 		TInt len = iHwDeviceBuffer->Data().Length();
  1718 		TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
  1719 	
  1720 		// if we're pausing (i.e. flushing) set the last buffer flag
  1721 		// when we get an empty buffer from the logical driver
  1722 		if(iPaused  && iHwDeviceBuffer->Data().Length() == 0)
  1723 		{
  1724 		iPaused = EFalse;
  1725 
  1726 		iHwDeviceBuffer->SetLastBuffer(ETrue);
  1727 
  1728 		iDevSoundEventHandler->CancelReceiveEvents();
  1729 
  1730 		}
  1731 
  1732 		// Send Data from Observer
  1733 		iDevSoundObserver->BufferToBeEmptied(iHwDeviceBuffer);
  1734 		}
  1735 	else
  1736 		{
  1737 		err = KErrGeneral;
  1738 		Error(err);
  1739 		iCMMFHwDevice->Stop();//unloads sound device
  1740 
  1741 		}
  1742 
  1743 	return err;
  1744 	}
  1745 
  1746 
  1747 /**
  1748  *
  1749  *	MMMFHwDeviceObserver mixin implementation.
  1750  *
  1751  *	The CMMFHwDevice implementation object calls this method when a message from
  1752  *	the hardware device implementation is received.
  1753  *
  1754  *	@return	"TInt"
  1755  *			Error code. KErrNone if success.
  1756  *
  1757  */
  1758 TInt CMMFDevSoundSvrImp::MsgFromHwDevice(TUid aMessageType, const TDesC8& /*aMsg*/)
  1759 	{
  1760 	TInt result = KErrNotSupported;
  1761 	if (aMessageType.iUid == KMmfHwDeviceObserverUpdateBytesPlayed)
  1762 		{//this is used by sw codec wrapper to request a bytes played update
  1763 		//bytes played won't be updated in Stopped() or Error() on sw cdoec wrapper
  1764 		//as the sound device is closed. Non swCodec wrapper Hw device plugins
  1765 		//can get there bytes updated on Stopped() and/or Error()
  1766 		UpdateBytesPlayed();
  1767 		result = KErrNone;
  1768 		}
  1769 	return result;
  1770 	}
  1771 
  1772 /**
  1773  *
  1774  *	MMMFHwDeviceObserver mixin implementation.
  1775  *
  1776  *	The CMMFHwDevice implementation object calls this method when the current
  1777  *	encode or decode task is finished or stopped.  The policy state is updated
  1778  *
  1779  */
  1780 void CMMFDevSoundSvrImp::Stopped()
  1781 	{
  1782 	//for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
  1783 	//but non Swcodec wrappers hw devices may do it differently
  1784 	//also don't know if non Swcodec wrap hw device will call Stopped or Error first
  1785 	UpdateBytesPlayed();
  1786 
  1787 	iLastBufferReceived = EFalse;
  1788 	UpdatePolicyState(EMMFStateCompleted);
  1789 	}
  1790 
  1791 /**
  1792  *  MMMFHwDeviceObserver mixin implementation
  1793  *  Processes error from hw device
  1794  */
  1795 void CMMFDevSoundSvrImp::Error(TInt aError)
  1796 	{
  1797 	if (iMode== EMMFDevSoundStatePlaying)
  1798 		{
  1799 		//for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
  1800 		//but non Swcodec wrappers hw devices may do it differently
  1801 		//also don't know if non Swcodec wrap hw device will call Stopped or Error first
  1802 		UpdateBytesPlayed();
  1803 
  1804         iDevSoundObserver->PlayError(aError);
  1805         UpdatePolicyState(EMMFStateStopped);
  1806 		}
  1807 	else if (iMode== EMMFDevSoundStateRecording)
  1808 		{
  1809         iDevSoundObserver->RecordError(aError);
  1810         UpdatePolicyState(EMMFStateStopped);
  1811 		}
  1812 	else if (iMode== EMMFDevSoundStateTonePlaying)
  1813 		{
  1814         iDevSoundObserver->ToneFinished(aError);
  1815         UpdatePolicyState(EMMFStateStopped);
  1816 		}
  1817 	//else can't handle error
  1818 	}
  1819 
  1820 
  1821 /********************************************************************************
  1822  *				Non Exported public functions ends here							*
  1823  ********************************************************************************/
  1824 
  1825 
  1826 /********************************************************************************
  1827  *				Private functions begins here									*
  1828  ********************************************************************************/
  1829 
  1830 TInt CMMFDevSoundSvrImp::InitializeFormat(RMdaDevSound::TSoundFormatsSupportedBuf& aSupportedFormat,
  1831 		RMdaDevSound::TCurrentSoundFormatBuf& aFormat)
  1832 	{
  1833 	// Choose an encoding
  1834 	TUint32 enc = aSupportedFormat().iEncodings;
  1835 	// Always defaults to this
  1836 	if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
  1837 		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
  1838 	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
  1839 		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
  1840 	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
  1841 		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
  1842 	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
  1843 		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
  1844 
  1845 	// default to Monophonic playback:
  1846 	aFormat().iChannels=1;
  1847 
  1848 	// Store the device capabilities (WINS supports from 8000 Hz to 44100 Hz)
  1849 	if ((aSupportedFormat().iMinRate <= 8000) && (8000 <= aSupportedFormat().iMaxRate))
  1850 		iDeviceCapabilities.iRate = EMMFSampleRate8000Hz;
  1851 	if ((aSupportedFormat().iMinRate <= 11025) && (11025 <= aSupportedFormat().iMaxRate))
  1852 		iDeviceCapabilities.iRate |= EMMFSampleRate11025Hz;
  1853 	if ((aSupportedFormat().iMinRate <= 12000) && (12000 <= aSupportedFormat().iMaxRate))
  1854 		iDeviceCapabilities.iRate |= EMMFSampleRate12000Hz;
  1855 	if ((aSupportedFormat().iMinRate <= 16000) && (16000 <= aSupportedFormat().iMaxRate))
  1856 		iDeviceCapabilities.iRate |= EMMFSampleRate16000Hz;
  1857 	if ((aSupportedFormat().iMinRate <= 22050) && (22050 <= aSupportedFormat().iMaxRate))
  1858 		iDeviceCapabilities.iRate |= EMMFSampleRate22050Hz;
  1859 	if ((aSupportedFormat().iMinRate <= 24000) && (24000 <= aSupportedFormat().iMaxRate))
  1860 		iDeviceCapabilities.iRate |= EMMFSampleRate24000Hz;
  1861 	if ((aSupportedFormat().iMinRate <= 32000) && (32000 <= aSupportedFormat().iMaxRate))
  1862 		iDeviceCapabilities.iRate |= EMMFSampleRate32000Hz;
  1863 	if ((aSupportedFormat().iMinRate <= 44100) && (44100 <= aSupportedFormat().iMaxRate))
  1864 		iDeviceCapabilities.iRate |= EMMFSampleRate44100Hz;
  1865 	if ((aSupportedFormat().iMinRate <= 48000) && (48000 <= aSupportedFormat().iMaxRate))
  1866 		iDeviceCapabilities.iRate |= EMMFSampleRate48000Hz;
  1867 	if ((aSupportedFormat().iMinRate <= 64000) && (64000 <= aSupportedFormat().iMaxRate))
  1868 		iDeviceCapabilities.iRate |= EMMFSampleRate64000Hz;
  1869 	if ((aSupportedFormat().iMinRate <= 88200) && (88200 <= aSupportedFormat().iMaxRate))
  1870 		iDeviceCapabilities.iRate |= EMMFSampleRate88200Hz;
  1871 	if ((aSupportedFormat().iMinRate <= 96000) && (96000 <= aSupportedFormat().iMaxRate))
  1872 		iDeviceCapabilities.iRate |= EMMFSampleRate96000Hz;
  1873 
  1874 	// Store the encodings supported
  1875 	iDeviceCapabilities.iEncoding = 0;
  1876 	if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
  1877 		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding16BitPCM;
  1878 	if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
  1879 		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitALaw;
  1880 	if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
  1881 		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitMuLaw;
  1882 	if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
  1883 		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitPCM;
  1884 
  1885 	// Mono and Stereo support
  1886 	if (aSupportedFormat().iChannels == 2)
  1887 		iDeviceCapabilities.iChannels = EMMFStereo;
  1888 	iDeviceCapabilities.iChannels |= EMMFMono;
  1889 
  1890 	iDeviceCapabilities.iBufferSize = aSupportedFormat().iMaxBufferSize;
  1891 	// Default
  1892 	iDeviceConfig.iRate = EMMFSampleRate8000Hz;
  1893 	iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
  1894 	iDeviceConfig.iChannels = EMMFMono;
  1895 
  1896 	return KErrNone;
  1897 	}
  1898 
  1899 /*
  1900  *
  1901  *	Makes request to Policy Server (asynchronous call)
  1902  *
  1903  */
  1904 void CMMFDevSoundSvrImp::RequestPolicy()
  1905 	{
  1906 	iDevSoundEventHandler->CancelReceiveEvents();
  1907 	iDevSoundEventHandler->ReceiveEvents();
  1908 	iAudioPolicyPrioritySettings.iCapabilities = iParent.CheckClientCapabilities();
  1909 	iAudioPolicyProxy->MakeRequest(iAudioPolicyPrioritySettings);
  1910 	}
  1911 
  1912 /*
  1913  *
  1914  *	Creates buffer and begin playback using the specified tone generator.
  1915  *
  1916  */
  1917 void CMMFDevSoundSvrImp::DoPlayL()
  1918 	{
  1919 	// Delete any buffer from previous call and try to create maximum buffer 
  1920 	// size. Double Buffer the Tone data.
  1921 	if (iToneBuffer1)
  1922 		{
  1923 		delete iToneBuffer1; 
  1924 		iToneBuffer1 = NULL; 
  1925 		}
  1926 	//note the tone buffer needs to be the same as the pcm16->pcm16 'null'
  1927 	//hw device plugin
  1928 	// Buffer size = (SampleRate * BytesPerSample * Channels) / 4
  1929 	TInt useBufferOfSize = ((SamplingFrequency() * 2 * NumberOfChannels())/KDevSoundFramesPerSecond + (KDevSoundDeltaFrameSize-1)) &~ (KDevSoundDeltaFrameSize-1);
  1930 	//clamp buffer to desired limits
  1931 	if(useBufferOfSize < KDevSoundMinFrameSize) 
  1932 		useBufferOfSize = KDevSoundMinFrameSize;
  1933 	else if(useBufferOfSize > KDevSoundMaxFrameSize) 
  1934 		useBufferOfSize = KDevSoundMaxFrameSize;
  1935 
  1936 	//clamp buffer to limits of hardware
  1937 	if(useBufferOfSize < Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize))
  1938 		useBufferOfSize = Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize);
  1939 	else if(useBufferOfSize > Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize))
  1940 		useBufferOfSize = Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize);
  1941 
  1942 	iToneBuffer1 = CMMFDataBuffer::NewL(useBufferOfSize);
  1943 	User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer1->Data()));
  1944 
  1945 	if (iToneBuffer2)
  1946 		{
  1947 		delete iToneBuffer2; 
  1948 		iToneBuffer2 = NULL;
  1949 		}
  1950 	iToneBuffer2 = CMMFDataBuffer::NewL(useBufferOfSize);
  1951 	User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer2->Data()));
  1952 
  1953 	// Assign active buffer
  1954 	iActiveToneBuffer = iToneBuffer1;
  1955 
  1956 	// Hw device hasn't played anything yet so don't change
  1957     // active buffer. This is checked in FillThisHwBuffer.
  1958     iFirstCallFromHwDevice = ETrue;
  1959 
  1960     // Start HwDevice to play data
  1961     User::LeaveIfError(iCMMFHwDevice->Start(EDevDecode, EDevOutFlow));
  1962 	
  1963 	}
  1964 
  1965 /*
  1966  *
  1967  *	This method assigns the other buffer as active buffer. The tone audio 
  1968  *	generator should fill data in the other buffer by now.
  1969  *
  1970  */
  1971 void CMMFDevSoundSvrImp::SetActiveToneBuffer()
  1972 	{
  1973 	if (iActiveToneBuffer == iToneBuffer1)
  1974 		iActiveToneBuffer = iToneBuffer2;
  1975 	else if (iActiveToneBuffer == iToneBuffer2)
  1976 		iActiveToneBuffer = iToneBuffer1;
  1977 	}
  1978 
  1979 /*
  1980  *
  1981  *	This method fills data into the free buffer.
  1982  *
  1983  *	@return	"TInt"
  1984  *			Error code. KErrNone if success.
  1985  *
  1986  */
  1987 TInt CMMFDevSoundSvrImp::FillFreeToneBuffer()
  1988 	{
  1989 	TInt err(KErrNone);
  1990 	if (iActiveToneBuffer == iToneBuffer1)
  1991 		err = iCurrentGenerator->FillBuffer(iToneBuffer2->Data());
  1992 	else if (iActiveToneBuffer == iToneBuffer2)
  1993 		err = iCurrentGenerator->FillBuffer(iToneBuffer1->Data());
  1994 	return err;
  1995 	}
  1996 
  1997 /*
  1998  *
  1999  *	Updates the policy state based on Audio policy settings of this devsound instance
  2000  *
  2001  */
  2002 TInt CMMFDevSoundSvrImp::UpdatePolicyState(TMMFAudioPolicyState aNewState)
  2003 	{
  2004 	iAudioPolicyPrioritySettings.iState = aNewState;
  2005 	TInt error = iAudioPolicyProxy->UpdateState(iAudioPolicyPrioritySettings);
  2006 	if ((error == KErrNone) && (aNewState == EMMFStateStopped))
  2007 		{
  2008 		iHasPolicy = EFalse;
  2009 		}
  2010 
  2011 	return error;
  2012 	}
  2013 
  2014 /*
  2015  *
  2016  *	Initializes audio device node by setting volume, and sampling rate.
  2017  *
  2018  *	@return	"TInt"
  2019  *			Error Code. KErrNone if success.
  2020  *
  2021  */
  2022 TInt CMMFDevSoundSvrImp::InitTask()
  2023 	{
  2024 	// No Implementation
  2025 	return KErrNone;
  2026 	}
  2027 
  2028 
  2029 
  2030 /*
  2031  *
  2032  *	Returns an integer representing Sampling Frequency the device is currently
  2033  *	configured to.
  2034  *
  2035  *	@return	"TInt"
  2036  *			Sampling Frequency.
  2037  *
  2038  */
  2039 TInt CMMFDevSoundSvrImp::SamplingFrequency()
  2040 	{
  2041 	if(iDeviceConfig.iRate == EMMFSampleRate8000Hz)
  2042 		return 8000;
  2043 	else if(iDeviceConfig.iRate == EMMFSampleRate11025Hz)
  2044 		return 11025;
  2045 	else if(iDeviceConfig.iRate == EMMFSampleRate12000Hz)
  2046 		return 12000;
  2047 	else if(iDeviceConfig.iRate == EMMFSampleRate16000Hz)
  2048 		return 16000;
  2049 	else if(iDeviceConfig.iRate == EMMFSampleRate22050Hz)
  2050 		return 22050;
  2051 	else if(iDeviceConfig.iRate == EMMFSampleRate24000Hz)
  2052 		return 24000;
  2053 	else if(iDeviceConfig.iRate == EMMFSampleRate32000Hz)
  2054 		return 32000;
  2055 	else if(iDeviceConfig.iRate == EMMFSampleRate44100Hz)
  2056 		return 44100;
  2057 	else if(iDeviceConfig.iRate == EMMFSampleRate48000Hz)
  2058 		return 48000;
  2059 	else if(iDeviceConfig.iRate == EMMFSampleRate88200Hz)
  2060 		return 88200;
  2061 	else if(iDeviceConfig.iRate == EMMFSampleRate96000Hz)
  2062 		return 96000;
  2063 	else
  2064 		return 8000; //default
  2065 	}
  2066  
  2067 /*
  2068  *
  2069  *	Returns an integer representing number of channels the device is currently
  2070  *	configured to.
  2071  *
  2072  *	@return	"TInt"
  2073  *			Number of audio channels 1 if mono, 2 if stereo.
  2074  *
  2075  */
  2076 TInt CMMFDevSoundSvrImp::NumberOfChannels()
  2077 	{
  2078 	if(iDeviceConfig.iChannels == EMMFMono)
  2079 		return 1;
  2080 	else
  2081 		return 2;
  2082 	}
  2083 
  2084 /*
  2085  *
  2086  *	Returns an integer representing number of bytes in each audio sample
  2087  *	
  2088  *
  2089  *	@return	"TInt"
  2090  *			Number of of bytes in each audio sample.
  2091  *
  2092  */
  2093 TInt CMMFDevSoundSvrImp::BytesPerAudioSample()
  2094 	{
  2095 	TInt bytes=1;
  2096 	switch (iDeviceConfig.iEncoding)
  2097 		{
  2098 		case EMMFSoundEncoding8BitPCM:
  2099 		case EMMFSoundEncoding8BitALaw:
  2100 		case EMMFSoundEncoding8BitMuLaw:
  2101 			{
  2102 			bytes=1;
  2103 			}
  2104 		break;
  2105 		case EMMFSoundEncoding16BitPCM:
  2106 			{
  2107 			bytes=2;
  2108 			}
  2109 		break;
  2110 		}
  2111 	return bytes;
  2112 	}
  2113 
  2114 
  2115 /********************************************************************************
  2116  *				Private functions ends here										*
  2117  ********************************************************************************/
  2118 
  2119 
  2120 // CustomCommand* implementation:
  2121 // The following come through from the parent object intact - currently it seems
  2122 // easier to pass this through with an RMessage, as the result parameter (at least)
  2123 // is easier to deal with that way. This might change in the future. 
  2124 // [TODO - if we extended this to CMMFHwDevice, it might be easier to use some sort
  2125 // of TMMFCustomCommandParamBlock throughout, which as well as the uid, in params etc
  2126 // by value, also provided a virtual(?) function to set output param. Could then
  2127 // use in both plat sec and original code
  2128 
  2129 void CMMFDevSoundSvrImp::DoSyncCustomCommandL(const RMmfIpcMessage& aMessage)
  2130 	{
  2131 	TInt command = aMessage.Int0();
  2132 	
  2133 	// we don't support any commands at the momment
  2134 	User::Leave(KErrNotSupported);
  2135 	}
  2136 	
  2137 void CMMFDevSoundSvrImp::DoSyncCustomCommandResultL(const RMmfIpcMessage& aMessage)
  2138 	{
  2139 	TInt command = aMessage.Int0();
  2140 	
  2141 	// we don't support any commands at the momment
  2142 	User::Leave(KErrNotSupported);	
  2143 	}
  2144 	
  2145 void CMMFDevSoundSvrImp::DoAsyncCustomCommandL(const RMmfIpcMessage& aMessage)
  2146 	{
  2147 	TInt command = aMessage.Int0();
  2148 	
  2149 	// we don't support any commands at the momment
  2150 	User::Leave(KErrNotSupported); // this will still complete for an async message	
  2151 	}
  2152 	
  2153 void CMMFDevSoundSvrImp::DoAsyncCustomCommandResultL(const RMmfIpcMessage& aMessage)
  2154 	{
  2155 	TInt command = aMessage.Int0();
  2156 	
  2157 	// we don't support any commands at the moment
  2158 	User::Leave(KErrNotSupported); // this will still complete for an async message	
  2159 	}
  2160