devsound/sounddevbt/PlatSec/src/Server/AudioServer/MmfBtDevSoundSessionBody.cpp
changeset 0 40261b775718
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/devsound/sounddevbt/PlatSec/src/Server/AudioServer/MmfBtDevSoundSessionBody.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,1958 @@
+// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32base.h>
+#include "MmfBtDevSoundSessionBody.h"
+#include "MmfBtDevSoundSessionXtnd.h"
+
+#include <mdaaudiotoneplayer.h>
+#include <mmf/server/mmfdatabuffer.h>
+#include <mmffourcc.h>
+#include <mmfbthwdeviceimplementationuids.hrh>
+#include <mmfbtswcodecwrappercustominterfacesuids.hrh> // KUidBtRefDevSoundTaskConfig
+
+
+/*
+ *	AO to handle RSD initialisation
+ *
+ */
+CRoutingSoundDeviceHandler* CRoutingSoundDeviceHandler::NewL(MDevSoundObserver* aObserver)
+	{
+	CRoutingSoundDeviceHandler* self = new(ELeave) CRoutingSoundDeviceHandler(aObserver);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+CRoutingSoundDeviceHandler::~CRoutingSoundDeviceHandler()
+	{
+	Cancel();
+	}
+		
+void CRoutingSoundDeviceHandler::RunL()
+	{
+	TInt err = iStatus.Int();
+	if (iObserver)
+		{
+		iObserver->InitializeComplete(err);
+		}		
+	}
+	
+void CRoutingSoundDeviceHandler::DoCancel()
+	{
+	if (iObserver)
+		{
+		iObserver->InitializeComplete(KErrCancel);
+		}
+	}
+	
+CRoutingSoundDeviceHandler::CRoutingSoundDeviceHandler(MDevSoundObserver* aObserver) :
+														CActive(EPriorityStandard),
+													 	iObserver(aObserver)
+	{
+	CActiveScheduler::Add(this);	
+	}
+	
+void CRoutingSoundDeviceHandler::ConstructL()
+	{
+	}
+
+void CRoutingSoundDeviceHandler::Start()
+	{
+	if (!IsActive())
+		{
+		SetActive();
+		}
+	}
+	
+/*
+ *
+ *	Default Constructor.
+ *
+ *	No default implementation. CMMFDevSoundProxy implements 2-phase construction.
+ *
+ */
+CMMFDevSoundSvrImp::CMMFDevSoundSvrImp(CMMFDevSoundSessionXtnd* aParent)
+: iParent(*aParent)
+	{
+	iMode= EMMFStateIdle;
+	//Set reasonable default values for DTMF 
+	iDTMFGen.SetToneDurations(250000,50000,250000);
+	}
+
+/*
+ *
+ *	Destructor.
+ *
+ *	Deletes all objects and releases all resource owned by this
+ *	instance.
+ *
+ */
+CMMFDevSoundSvrImp::~CMMFDevSoundSvrImp()
+	{
+	delete iRSDHandler;
+	delete iToneBuffer1;
+	delete iToneBuffer2;
+	delete iDevSoundEventHandler; 
+	if( iAudioPolicyProxy != NULL)
+		{
+		iAudioPolicyProxy->Close(); 
+		delete iAudioPolicyProxy;
+		}
+	delete iDevSoundUtil;
+	delete iFixedSequences;
+	delete iCMMFHwDevice;
+	}
+
+/*
+ *
+ *	Constructs, and returns a pointer to, a new CMMFDevSoundSvrImp object.
+ *
+ *	Leaves on failure.
+ *
+ */
+CMMFDevSoundSvrImp* CMMFDevSoundSvrImp::NewL(CMMFDevSoundSessionXtnd* aParent)
+	{
+	CMMFDevSoundSvrImp* self = new (ELeave) CMMFDevSoundSvrImp(aParent);
+	return self;
+	}
+
+/*
+ *
+ *	3rd phase constructor - assumes that iParent has already been set up properly
+ *                          (During ConstructL() it has yet to be
+ *
+ */
+void CMMFDevSoundSvrImp::Construct3L(RServer2& aPolicyServerHandle)
+	{
+	// all these data properties should be NULL, but add ASSERTs to verity
+	ASSERT(iAudioPolicyProxy==NULL);
+	iAudioPolicyProxy = new (ELeave) RMMFAudioPolicyProxy();
+	ASSERT(iDevSoundEventHandler==NULL);
+	iDevSoundEventHandler = CMMFDevSoundEventHandler::NewL(iAudioPolicyProxy);
+	User::LeaveIfError(iAudioPolicyProxy->Open(aPolicyServerHandle));
+	iDevSoundEventHandler->SetDevSoundInfo(&iParent);
+
+	iDevSoundUtil = CMMFDevSoundUtility::NewL();
+	// Initialize Fixed sequence related
+	iDevSoundUtil->InitializeFixedSequenceL(&iFixedSequences);
+
+	// Add RSD handler construction here.
+	iRSDHandler = CRoutingSoundDeviceHandler::NewL(&iParent);
+	
+	PreInitializeL();
+	}
+
+/**
+ * internal procedure to perform all initialization prior to setting the 
+ * data type 4CC code
+ */
+void CMMFDevSoundSvrImp::PreInitializeL()
+	{
+	// Set default values for priority settings: Note: Client must 
+	// over ride default settings by calling SetPrioirtySettings
+	iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
+	iAudioPolicyPrioritySettings.iPref = EMdaPriorityPreferenceNone;
+	iAudioPolicyPrioritySettings.iPriority = 0;
+
+	// Get device capabilities and current settings from Audio Policy:
+	iAudioPolicyProxy->GetPlayFormatsSupported(iPlayFormatsSupported);
+	iAudioPolicyProxy->GetPlayFormat(iPlayFormat);
+	iAudioPolicyProxy->GetRecordFormatsSupported(iRecordFormatsSupported);
+	iAudioPolicyProxy->GetRecordFormat(iRecordFormat);
+
+	//default to play until we know we are recording
+	User::LeaveIfError(InitializeFormat(iPlayFormatsSupported, iPlayFormat));
+	}
+
+/*
+ *
+ *	Initializes CMMFDevSoundProxy object to play and record PCM16 raw audio data
+ *	with sampling rate of 8 KHz.
+ *
+ *	On completion of Initialization, calls InitializeComplete() on
+ *	aDevSoundObserver.
+ *
+ *	Leaves on failure.
+ *
+ *	@param	"MDevSoundObserver& aDevSoundObserver"
+ *			A reference to DevSound Observer instance.
+ *
+ *	@param	"TMMFState aMode"
+ *			Mode for which this object will be used.
+ *
+ */
+void CMMFDevSoundSvrImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TMMFState aMode)
+
+	{
+	// if no HwDevice id specified, load default null implementation
+	TUid rawUid = {KMmfUidBtHwDevicePCM16ToPCM16};
+	InitializeL(aDevSoundObserver, rawUid, aMode);
+	}
+
+/*
+ *
+ *	Configure CMMFDevSoundProxy object for the settings in aConfig.
+ *
+ *	Use this to set sampling rate, Encoding and Mono/Stereo.
+ *
+ *	@param	"TMMFCapabilities& aConfig"
+ *			Attribute values to which CMMFDevSoundProxy object will be configured to.
+ *
+ *  As part of defect 20796, the iRecordFormat has been set under the iPlayFormat, 
+ *  before it was not set at all.
+ *
+ */
+void CMMFDevSoundSvrImp::SetConfigL(const TMMFCapabilities& aConfig)
+	{
+	TUint attributeValue = aConfig.iRate;
+	// WINS supports from 8000 Hz to 96000 Hz
+	if (attributeValue & EMMFSampleRate96000Hz) 
+		{ 
+		iPlayFormat().iRate = 96000; 
+		iRecordFormat().iRate = 96000;
+		iDeviceConfig.iRate = EMMFSampleRate96000Hz;
+		}
+	else if (attributeValue & EMMFSampleRate88200Hz) 
+		{ 
+		iPlayFormat().iRate = 88200; 
+		iRecordFormat().iRate = 88200;
+		iDeviceConfig.iRate = EMMFSampleRate88200Hz;
+		}
+	else if (attributeValue & EMMFSampleRate64000Hz) 
+		{ 
+		iPlayFormat().iRate = 64000; 
+		iRecordFormat().iRate = 64000;
+		iDeviceConfig.iRate = EMMFSampleRate64000Hz;
+		}
+	else if (attributeValue & EMMFSampleRate48000Hz) 
+		{ 
+		iPlayFormat().iRate = 48000; 
+		iRecordFormat().iRate = 48000;
+		iDeviceConfig.iRate = EMMFSampleRate48000Hz;
+		}
+	else if (attributeValue & EMMFSampleRate44100Hz) 
+		{ 
+		iPlayFormat().iRate = 44100; 
+		iRecordFormat().iRate = 44100;
+		iDeviceConfig.iRate = EMMFSampleRate44100Hz;
+		}
+	else if (attributeValue & EMMFSampleRate32000Hz) 
+		{ 
+		iPlayFormat().iRate = 32000; 
+		iRecordFormat().iRate = 32000; 
+		iDeviceConfig.iRate = EMMFSampleRate32000Hz;
+		}
+	else if (attributeValue & EMMFSampleRate24000Hz)
+		{
+		iPlayFormat().iRate = 
+		iRecordFormat().iRate = 24000;
+		iDeviceConfig.iRate = EMMFSampleRate24000Hz;
+		}
+	else if (attributeValue & EMMFSampleRate22050Hz)
+		{ 
+		iPlayFormat().iRate = 22050; 
+		iRecordFormat().iRate = 22050; 
+		iDeviceConfig.iRate = EMMFSampleRate22050Hz;
+		}
+	else if (attributeValue & EMMFSampleRate16000Hz)
+		{
+		iPlayFormat().iRate = 16000;
+		iRecordFormat().iRate = 16000; 
+		iDeviceConfig.iRate = EMMFSampleRate16000Hz;
+		}
+	else if (attributeValue & EMMFSampleRate12000Hz)
+		{
+		iPlayFormat().iRate = 
+		iRecordFormat().iRate = 12000;
+		iDeviceConfig.iRate = EMMFSampleRate12000Hz;
+		}
+	else if (attributeValue & EMMFSampleRate11025Hz)
+		{
+		iPlayFormat().iRate = 11025;
+		iRecordFormat().iRate = 11025;
+		iDeviceConfig.iRate = EMMFSampleRate11025Hz;
+		}
+	else if (attributeValue & EMMFSampleRate8000Hz)
+		{
+		iPlayFormat().iRate = 8000;
+		iRecordFormat().iRate = 8000;
+		iDeviceConfig.iRate = EMMFSampleRate8000Hz;
+		}
+	else if (attributeValue) 
+		{ //if no attribute value assume its not set
+		User::Leave(KErrNotSupported);
+		}
+
+	attributeValue = aConfig.iEncoding;
+	// Map from MMF Encoding enums to RMdaDevSound enum
+	if(attributeValue & EMMFSoundEncoding8BitPCM) 
+		{
+		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
+		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
+		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitPCM;
+		}
+	else if(attributeValue & EMMFSoundEncoding8BitALaw)
+		{
+		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
+		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
+		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitALaw;
+		}
+	else if(attributeValue & EMMFSoundEncoding8BitMuLaw) 
+		{
+		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
+		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
+		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitMuLaw;
+		}
+	else if(attributeValue & EMMFSoundEncoding16BitPCM)
+		{
+		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
+		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
+		iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
+		}
+	else if (attributeValue) 
+		{ //if no attribute value assume its not set
+		User::Leave(KErrNotSupported);
+		}
+
+	// Mono/Stereo settings
+	attributeValue = aConfig.iChannels;
+	if(attributeValue & EMMFStereo) 
+		{
+		iPlayFormat().iChannels = 2;
+		iRecordFormat().iChannels = 2;
+		iDeviceConfig.iChannels = EMMFStereo;
+		}
+	else if(attributeValue & EMMFMono)
+		{
+		iPlayFormat().iChannels = 1;
+		iRecordFormat().iChannels = 1;
+		iDeviceConfig.iChannels = EMMFMono;
+		}
+	else if (attributeValue) 
+		{ //if no attribute value assume its not set
+		User::Leave(KErrNotSupported);
+		}
+	}
+
+/*
+ *
+ *	Changes the current playback volume to a specified value.
+ *
+ *	The volume can be changed before or during playback and is effective
+ *	immediately.
+ *
+ *	@param	"TInt aVolume"
+ *			The volume setting. This can be any value from zero to the value
+ *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
+ *			volume is not within this range, the volume is automatically set to
+ *			minimum or maximum value based on the value that is being passed.
+ *			Setting a zero value mutes the sound. Setting the maximum value
+ *			results in the loudest possible sound.
+ *
+ */
+void CMMFDevSoundSvrImp::SetVolume(TInt aVolume)
+	{
+
+	// Check and make sure that the volume is in valid range
+	if (aVolume < 0)
+		aVolume = 0;
+
+	if (aVolume > MaxVolume())
+		aVolume = MaxVolume();
+
+	iVolume = aVolume;
+
+	SetDeviceVolume(iVolume);
+	}
+
+/*
+ *
+ *	Changes the current recording gain to a specified value.
+ *
+ *	The gain can be changed before or during recording and is effective
+ *	immediately.
+ *
+ *	@param	"TInt aGain"
+ *			The volume setting. This can be any value from zero to the value
+ *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
+ *			volume is not within this range, the gain is automatically set to
+ *			minimum or maximum value based on the value that is being passed.
+ *			Setting a zero value mutes the sound. Setting the maximum value
+ *			results in the loudest possible sound.
+ *
+ */
+void CMMFDevSoundSvrImp::SetGain(TInt aGain)
+	{
+	// make sure it falls with the correct range
+	TInt maxGain = iRecordFormatsSupported().iMaxVolume;
+	if (aGain > maxGain)
+		aGain = maxGain;
+	else if (aGain < 0)
+		aGain = 0;
+	iGain = aGain;
+	SetDeviceRecordLevel(iGain);
+	}
+
+/*
+ *
+ *	Sets the speaker balance for playing.
+ *
+ *	The speaker balance can be changed before or during playback and is
+ *	effective immediately.
+ *
+ *	@param	"TInt& aLeftPercentage"
+ *			On return contains left speaker volume perecentage. This can be any
+ *			value from zero to 100. Setting a zero value mutes the sound on left
+ *			speaker.
+ *
+ *	@param	"TInt& aRightPercentage"
+ *			On return contains right speaker volume perecentage. This can be any
+ *			value from zero to 100. Setting a zero value mutes the sound on
+ *			right speaker.
+ *
+ */
+void CMMFDevSoundSvrImp::SetPlayBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
+	{
+	if (aLeftPercentage < 0)
+		aLeftPercentage = 0;
+	else if (aLeftPercentage > 100)
+		aLeftPercentage = 100;
+	if (aRightPercentage < 0)
+		aRightPercentage = 0;
+	else if (aRightPercentage > 100)
+		aRightPercentage = 100;
+	iLeftPlayBalance = aLeftPercentage;
+	iRightPlayBalance = aRightPercentage;
+	}
+
+/*
+ *
+ *	Sets the microphone gain balance for recording.
+ *
+ *	The microphone gain balance can be changed before or during recording and
+ *	is effective immediately.
+ *
+ *	@param	"TInt aLeftPercentage"
+ *			Left microphone gain precentage. This can be any value from zero to
+ *			100. Setting a zero value mutes the gain on left microphone.
+ *
+ *	@param	"TInt aRightPercentage"
+ *			Right microphone gain precentage. This can be any value from zero to
+ *			100. Setting a zero value mutes the gain on right microphone.
+ *
+ */
+void CMMFDevSoundSvrImp::SetRecordBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
+	{
+	if (aLeftPercentage < 0)
+		aLeftPercentage = 0;
+	else if (aLeftPercentage > 100)
+		aLeftPercentage = 100;
+	if (aRightPercentage < 0)
+		aRightPercentage = 0;
+	else if (aRightPercentage > 100)
+		aRightPercentage = 100;
+	iLeftRecordBalance = aLeftPercentage;
+	iRightRecordBalance = aRightPercentage;
+	}
+
+/*
+ *
+ *	Initializes audio device and start play process. This method queries and
+ *	acquires the audio policy before initializing audio device. If there was an
+ *	error during policy initialization, PlayError() method will be called on
+ *	the observer with error code KErrAccessDenied, otherwise BufferToBeFilled()
+ *	method will be called with a buffer reference. After reading data into the
+ *	buffer reference passed, the client should call PlayData() to play data.
+ *
+ *	The amount of data that can be played is specified in
+ *	CMMFBuffer::RequestSize(). Any data that is read into buffer beyond this
+ *	size will be ignored.
+ *
+ *	Leaves on failure.
+ *
+ */
+void CMMFDevSoundSvrImp::PlayInitL()
+	{
+	if (!iDevSoundObserver)
+		User::Leave(KErrNotReady);
+
+	// Get audio policy
+	iAudioPolicyPrioritySettings.iState = EMMFStatePlayData;
+	RequestPolicy();
+	}
+
+/*
+ *
+ *	Initializes audio device and start record process. 
+ *  This method:
+ *  1. Queries and acquires the audio policy before initializing audio device. 
+ *     If there was an error during policy initialization, RecordError() method will 
+ *     be called on the observer with error code KErrAccessDenied, otherwise BufferToBeEmptied()
+ *	   method will be called with a buffer reference. This buffer contains recorded
+ *	   or encoded data. After processing data in the buffer reference passed, the
+ *	   client should call RecordData() to continue recording process.
+ *
+ *  2. Checks if the requesting client process has a UserEnvironment capability.
+ *     If it does not, the audio device will not be initialized and an error 
+ *     code KErrAccessDenied will be sent to the client.
+ *
+ *	The amount of data that is available is specified in
+ *	CMMFBuffer::RequestSize().
+ *
+ *	Leaves on failure.
+ *
+ */
+void CMMFDevSoundSvrImp::RecordInitL(const RMmfIpcMessage& aMessage)
+	{
+	if (!iDevSoundObserver)
+		User::Leave(KErrNotReady);
+	
+	// Checkes if the client has the UserEnvironment capability
+	if (!aMessage.HasCapability(ECapabilityUserEnvironment))
+		{
+		User::Leave(KErrPermissionDenied);
+		}
+	
+	// Get audio policy
+	iAudioPolicyPrioritySettings.iState = EMMFStateRecordData;
+	RequestPolicy();
+	}
+
+/*
+ *
+ *	Plays data in the buffer at the current volume. The client should fill
+ *	the buffer with audio data before calling this method. The Observer gets
+ *	reference to buffer along with callback BufferToBeFilled(). When playing of
+ *	the audio sample is complete, successfully or otherwise, the method
+ *	PlayError() on observer is called.
+ *
+ */
+void CMMFDevSoundSvrImp::PlayData()
+	{
+	ASSERT(iDevSoundObserver);
+
+	if (iMode== EMMFStateIdle)
+		return;
+
+	TInt error = KErrNone;
+
+    if(iCMMFHwDevice)
+	    {
+		if (iPaused)
+			{
+			iPaused = EFalse;
+			//note PlayData does not leave or return an error code so the Start() fails we cannot
+			//report the error back at this point
+			error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);//restart hw device after pause
+			}
+	   else if(iMode== EMMFStatePlaying)
+		    {
+		    TInt len = iHwDeviceBuffer->Data().Length();
+		    iPlayedBytesCount += len;
+		    if (iHwDeviceBuffer->LastBuffer())
+			    iLastBufferReceived = ETrue;
+
+
+            if (iMode== EMMFStatePlaying)
+                // Pass the data buffer to HwDevice
+                error = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
+            }
+		}
+	if (error != KErrNone)
+		iDevSoundObserver->PlayError(error);
+	}
+
+/*
+ *
+ *	Stops the ongoing operation (Play, Record, TonePlay, Convert)
+ *
+ */
+void CMMFDevSoundSvrImp::Stop()
+	{
+	iPaused = EFalse;
+
+	if (iMode== EMMFStateIdle)
+		return;
+
+	 // Stop the hw device first - this unloads sound drivers
+    if(iCMMFHwDevice)
+		iCMMFHwDevice->Stop();
+
+	iDevSoundEventHandler->CancelReceiveEvents();
+
+	iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
+	UpdatePolicyState();
+	}
+
+/*
+ *
+ *	Temporarily Stops the ongoing operation (Play, Record, TonePlay, Convert)
+ *
+ */
+void CMMFDevSoundSvrImp::Pause()
+	{
+	iPaused = ETrue;
+
+	if (iMode== EMMFStateIdle)
+		return;
+
+	// Pause the HW device first
+	if(iCMMFHwDevice)
+		iCMMFHwDevice->Pause();
+	
+	// defer policy update until buffers have been flushed
+	if ((iMode == EMMFStatePlaying) || (iMode == EMMFStateTonePlaying))
+		{
+		iDevSoundEventHandler->CancelReceiveEvents();
+		
+		iAudioPolicyPrioritySettings.iState = EMMFStatePaused;
+		UpdatePolicyState();
+		}
+	}
+
+/*
+ *
+ *	Returns the sample recorded so far.
+ *
+ *	@return "TInt"
+ *			Returns the samples recorded.
+ *
+ */
+TInt CMMFDevSoundSvrImp::SamplesRecorded()
+	{
+	TInt samples = 0;
+	
+	if(iRecordCustomInterface)
+		{
+		samples = iRecordCustomInterface->BytesRecorded();
+		if(NumberOfChannels() > 1)
+			{
+			samples /= NumberOfChannels();
+			}
+		if(BytesPerAudioSample() > 1)
+			{
+			samples /= BytesPerAudioSample();
+			}
+		}
+
+	return samples;
+	}
+
+/*
+ *
+ *	Returns the sample played so far.
+ *
+ *	@return "TInt"
+ *			Returns the samples recorded.
+ *
+ */
+TInt CMMFDevSoundSvrImp::SamplesPlayed()
+	{
+	TInt samples = 0;
+	if(iPlayCustomInterface)
+		{
+		TUint bytesPlayed = iPlayCustomInterface->BytesPlayed();
+		if (bytesPlayed)
+			iPlayedBytesCount = bytesPlayed;
+
+		samples = iPlayedBytesCount;
+		if(NumberOfChannels() > 1)
+			samples /= NumberOfChannels();
+
+		if(BytesPerAudioSample() > 1)
+			samples /= BytesPerAudioSample();
+		}
+	//note always pcm16 becuase the iPlayedBytesCount originates from 
+	//RMdaDevSound which is always pcm16
+	return samples; //each sample is 2 bytes
+	}
+
+
+/*
+ *
+ *	Initializes audio device and start playing tone. Tone is played with
+ *	frequency and for duration specified.
+ *
+ *	Leaves on failure.
+ *
+ *	@param	"TInt aFrequency"
+ *			Frequency at with the tone will be played.
+ *
+ *	@param	"TTimeIntervalMicroSeconds& aDuration"
+ *			The period over which the tone will be played. A zero value causes
+ *			the no tone to be played (Verify this with test app).
+ *
+ */
+void CMMFDevSoundSvrImp::PlayToneL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration)
+	{
+	if (iMode!= EMMFStateTonePlaying)
+		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
+
+	// Check whether frequency and duration is valid or not
+	TInt64 zeroInt64(0);
+	if ((aFrequency<0) || (aDuration.Int64() < zeroInt64))
+		User::Leave(KErrArgument);
+
+	if (!iDevSoundObserver)
+		User::Leave(KErrNotReady);
+
+	iToneGen.SetFrequencyAndDuration(aFrequency,aDuration);
+
+	// Get audio policy
+	iAudioPolicyPrioritySettings.iState = EMMFStatePlayTone;
+	RequestPolicy();
+	}
+
+/*
+ *	Initializes audio device and start playing a dual tone. 
+ *  The tone consists of two sine waves of different frequencies summed together
+ *  Dual Tone is played with specified frequencies and for specified duration.
+ *
+ *	@param	"aFrequencyOne"
+ *			First frequency of dual tone
+ *
+ *	@param	"aFrequencyTwo"
+ *			Second frequency of dual tone
+ *
+ *	@param	"aDuration"
+ *			The period over which the tone will be played. A zero value causes
+ *			the no tone to be played (Verify this with test app).
+ */
+void CMMFDevSoundSvrImp::PlayDualToneL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration)
+	{
+
+	// Check whether frequencies and duration are valid or not
+	TInt64 zeroInt64(0);
+	if ((aFrequencyOne<0) || (aFrequencyTwo<0) || (aDuration.Int64() < zeroInt64))
+		User::Leave(KErrArgument);
+
+	if (!iDevSoundObserver)
+		User::Leave(KErrNotReady);
+
+	iDualToneGen.SetFrequencyAndDuration(aFrequencyOne, aFrequencyTwo, aDuration);
+
+	// Get audio policy
+	iAudioPolicyPrioritySettings.iState = EMMFStatePlayDualTone;
+	RequestPolicy();
+	}
+
+/*
+ *
+ *	Initializes audio device and start playing DTMF string aDTMFString.
+ *
+ *	Leaves on failure.
+ *
+ *	@param	"TDesC& aDTMFString"
+ *			DTMF sequence in a descriptor.
+ *
+ */
+void CMMFDevSoundSvrImp::PlayDTMFStringL(const TDesC& aDTMFString)
+	{
+	if (!iDevSoundObserver)
+		User::Leave(KErrNotReady);
+
+	if (iMode!= EMMFStateTonePlaying)
+		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
+
+	iDTMFGen.SetString(aDTMFString);
+
+	// Get audio policy
+	iAudioPolicyPrioritySettings.iState = EMMFStatePlayDTMFString;
+	RequestPolicy();
+	}
+
+/*
+ *
+ *	Initializes audio device and start playing tone sequence.
+ *
+ *	Leaves on failure.
+ *
+ *	@param	"TDesC8& aData"
+ *			Tone sequence in a descriptor.
+ *
+ */
+void CMMFDevSoundSvrImp::PlayToneSequenceL(const TDesC8& aData)
+	{
+	if (!iDevSoundObserver)
+		User::Leave(KErrNotReady);
+
+	if (iMode!= EMMFStateTonePlaying)
+		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
+
+	// Check whether the sequence is valid or not
+	if (!iDevSoundUtil->RecognizeSequence(aData))
+		User::Leave(KErrCorrupt);
+
+	iSequenceGen.SetSequenceData(aData);
+
+	// Get audio policy
+	iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
+	RequestPolicy();
+	}
+
+/*
+ *
+ *	Initializes audio device and start playing the specified pre-defined tone
+ *	sequence.
+ *
+ *	Leaves on failure.
+ *
+ *	@param	"TInt aSequenceNumber"
+ *			The index identifying the specific pre-defined tone sequence. Index
+ *			values are relative to zero.
+ *			This can be any value from zero to the value returned by a call to
+ *			CMdaAudioPlayerUtility::FixedSequenceCount() - 1.
+ *			The function raises a panic if sequence number is not within this
+ *			range.
+ *
+ */
+void CMMFDevSoundSvrImp::PlayFixedSequenceL(TInt aSequenceNumber)
+	{
+	if (!iDevSoundObserver)
+		User::Leave(KErrNotReady);
+
+	if (iMode!= EMMFStateTonePlaying)
+		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
+
+	ASSERT((aSequenceNumber >= 0)&&(aSequenceNumber < iFixedSequences->Count()));
+
+	iFixedSequence.Set(iFixedSequences->MdcaPoint(aSequenceNumber));
+	iSequenceGen.SetSequenceData(iFixedSequence);
+
+	// Get audio policy
+	iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
+	RequestPolicy();
+	}
+
+/*
+ *
+ *	Defines the duration of tone on, tone off and tone pause to be used during the
+ *	DTMF tone playback operation.
+ *
+ *	Supported only during tone playing.
+ *
+ *	@param	"TTimeIntervalMicroSeconds32& aToneOnLength"
+ *			The period over which the tone will be played. If this is set to
+ *			zero, then the tone is not played.
+ *
+ *	@param	"TTimeIntervalMicroSeconds32& aToneOffLength"
+ *			The period over which the no tone will be played.
+ *
+ *	@param	"TTimeIntervalMicroSeconds32& aPauseLength"
+ *			The period over which the tone playing will be paused.
+ *
+ */
+void CMMFDevSoundSvrImp::SetDTMFLengths(TTimeIntervalMicroSeconds32& aToneOnLength,
+								TTimeIntervalMicroSeconds32& aToneOffLength,
+								TTimeIntervalMicroSeconds32& aPauseLength) 
+	{
+
+	if(aToneOnLength.Int() < KMdaInfiniteDurationDTMFToneOnLength)
+		aToneOnLength = TTimeIntervalMicroSeconds32(0);
+	if(aToneOffLength.Int() < 0)
+		aToneOffLength = TTimeIntervalMicroSeconds32(0);
+	if(aPauseLength.Int() < 0)
+		aPauseLength = TTimeIntervalMicroSeconds32(0);
+
+	iDTMFGen.SetToneDurations(aToneOnLength,aToneOffLength,aPauseLength);
+	}
+
+/*
+ *
+ *	Defines the period over which the volume level is to rise smoothly from
+ *	nothing to the normal volume level.
+ *
+ *	@param	"TTimeIntervalMicroSeconds& aRampDuration"
+ *			The period over which the volume is to rise. A zero value causes 
+ *			the tone sample to be played at the normal level for the full
+ *			duration of the playback. A value, which is longer than the duration
+ *			of the tone sample, that the sample never reaches its normal
+ *			volume level.
+ *
+ *
+ */
+void CMMFDevSoundSvrImp::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
+	{
+	// save ramp duration for tone generator
+	iRampDuration = aRampDuration;
+
+	SetDeviceVolumeRamp(iRampDuration);
+	}
+
+/**
+ *	Sets volume ramp on HwDevice.
+ */
+TInt CMMFDevSoundSvrImp::SetDeviceVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
+	{
+	TInt error = KErrNone;
+	if (iPlayCustomInterface) 
+		iPlayCustomInterface->SetVolumeRamp(aRampDuration);
+	else
+		error = KErrNotReady;
+	return error;
+    }
+
+/**
+ *	@see sounddevice.h
+ */
+void CMMFDevSoundSvrImp::GetSupportedInputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
+	{
+	//aPrioritySettings not used on ref DevSound
+	//search for playing datatypes
+	iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStatePlaying);
+	}
+
+/**
+ *	@see sounddevice.h
+ */
+void CMMFDevSoundSvrImp::GetSupportedOutputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
+	{
+	//aPrioritySettings not used on ref DevSound
+	// search for recording datatypes
+	iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStateRecording);
+	}
+	
+TInt CMMFDevSoundSvrImp::RegisterAsClient(TUid aEventType, const TDesC8& aNotificationRegistrationData)
+	{	
+	return iAudioPolicyProxy->RequestResourceNotification(aEventType,aNotificationRegistrationData);
+	}
+	
+TInt CMMFDevSoundSvrImp::CancelRegisterAsClient(TUid aEventType)
+	{	
+	return iAudioPolicyProxy->CancelRequestResourceNotification(aEventType);
+	}
+
+TInt CMMFDevSoundSvrImp::GetResourceNotificationData(TUid aEventType, TDes8& aNotificationData)
+	{	
+	TInt err = KErrNone;
+	err = iAudioPolicyProxy->IsRegisteredResourceNotification(aEventType);
+	if(err == KErrNone)
+		{
+		aNotificationData.Num(SamplesPlayed());
+		}
+	return err;
+	}
+	
+TInt CMMFDevSoundSvrImp::WillResumePlay()
+	{
+	return iAudioPolicyProxy->StopNotification();
+	}	
+
+/********************************************************************************
+ *				Implementations of Non Exported public functions begins here	*
+ ********************************************************************************/
+
+//
+//				Audio Policy specific implementation begins here				//
+//
+
+/*
+ *
+ *	Called by Audio Policy Server when a request to play is approved by the 
+ *	Audio Policy Server.
+ *
+ *	Leaves on failure??.
+ *
+ */
+void CMMFDevSoundSvrImp::StartPlayDataL()
+	{
+	ASSERT(iMode== EMMFStatePlaying);
+
+	TInt error = KErrNone;
+
+	if(iCMMFHwDevice)
+		{
+        // Set volume and play format values
+        error = SetPlayFormat(iPlayFormat);
+        if (error == KErrNone)
+			error = SetDeviceVolume(iVolume);
+        if (error == KErrNone)
+			error = SetDeviceVolumeRamp(iRampDuration);
+
+		// Initialize attribute values
+		iPlayedBytesCount = 0;
+		iLastBufferReceived = EFalse;
+
+        // Start HwDevice
+        if (error == KErrNone)
+	        error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
+		}
+	else
+		error = KErrNotReady;
+
+	if (error != KErrNone)
+		iDevSoundObserver->PlayError(error);
+	}
+
+/*
+ *
+ *	Called by Audio Policy Server when a request to record is approved by the 
+ *	Audio Policy Server.
+ *
+ *	Leaves on failure.
+ *
+ */
+void CMMFDevSoundSvrImp::StartRecordDataL()
+	{
+	ASSERT(iMode== EMMFStateRecording);
+
+	 if(iCMMFHwDevice)
+		{
+        TInt error = KErrNone;
+        error = SetRecordFormat(iRecordFormat);
+		if (error != KErrNone)
+			{
+			iDevSoundObserver->RecordError(error);
+			return;
+			}
+        error = SetDeviceRecordLevel(iGain);
+		if (error != KErrNone)
+			{
+			iDevSoundObserver->RecordError(error);
+			return;
+			}
+
+        // Initialize attribute values
+		iRecordedBytesCount = 0;
+
+        error = iCMMFHwDevice->Start(EDevEncode, EDevInFlow);
+		if (iHwDeviceBuffer)
+			iHwDeviceBuffer->SetLastBuffer(EFalse);
+
+		if (error != KErrNone)
+			{
+			iDevSoundObserver->RecordError(error);
+			return;
+			}
+        }
+	else
+		iDevSoundObserver->RecordError(KErrNotReady);
+	}
+
+/*
+ *
+ *	Called by Audio Policy Server when a request to play tone is approved by
+ *	the Audio Policy Server.
+ *
+ *	Leaves on failure.
+ *
+ */
+void CMMFDevSoundSvrImp::StartPlayToneL()
+	{
+	ASSERT(iMode== EMMFStateTonePlaying);
+
+	 if(iCMMFHwDevice)
+		{
+        TInt error = KErrNone;
+        // Set volume and play format values
+        error = SetPlayFormat(iPlayFormat);
+		if (error != KErrNone)
+			{
+			iDevSoundObserver->ToneFinished(error);
+			return;
+			}
+        if (iHwDeviceID.iUid == KMmfUidBtHwDevicePCM16ToPCM16)
+            error = SetDeviceVolume(iVolume);
+		else
+			error = KErrGeneral;//hw device should always be pcm16 for tone
+
+		// turn off volume ramping - this is done in software below
+        if (error == KErrNone)
+			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
+
+        if (error != KErrNone)
+            {
+            iDevSoundObserver->ToneFinished(error);
+            return;
+            }
+
+        // Initialize attribute values
+		iPlayedBytesCount = 0;
+
+        // Configure tone generator
+        iToneGen.Configure(
+			iPlayFormat().iRate,
+			iPlayFormat().iChannels,
+		    iRepeatCount,
+			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
+			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
+			);
+
+		iCurrentGenerator = &iToneGen;
+
+        // Start playback
+        DoPlayL();
+               
+		}
+	else
+		iDevSoundObserver->ToneFinished(KErrNotReady);
+	}
+
+/*
+ *
+ *	Called by Audio Policy Server when a request to play a dual tone is approved by
+ *	the Audio Policy Server.
+ *
+ */
+void CMMFDevSoundSvrImp::StartPlayDualToneL()
+	{
+	ASSERT(iMode== EMMFStateTonePlaying);
+
+	 if(iCMMFHwDevice)
+		{
+        TInt error = KErrNone;
+        // Set volume and play format values
+        error = SetPlayFormat(iPlayFormat);
+		if (error != KErrNone)
+			{
+			iDevSoundObserver->ToneFinished(error);
+			return;
+			}
+        if (iHwDeviceID.iUid == KMmfUidBtHwDevicePCM16ToPCM16)
+            error = SetDeviceVolume(iVolume);
+		else 
+			error = KErrGeneral;//hw device should always be pcm16 for tone
+
+		// turn off volume ramping - this is done in software below
+        if (error == KErrNone)
+			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
+
+        if (error != KErrNone)
+            {
+            iDevSoundObserver->ToneFinished(error);
+            return;
+            }
+
+        // Initialize attribute values
+		iPlayedBytesCount = 0;
+
+        // Configure dual tone generator
+		iDualToneGen.Configure(
+			iPlayFormat().iRate,
+			iPlayFormat().iChannels,
+			iRepeatCount,
+			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds),
+			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds)
+			);
+
+		iCurrentGenerator = &iDualToneGen;
+
+        // Start playback
+        DoPlayL();
+		}
+	else
+		iDevSoundObserver->ToneFinished(KErrNotReady);
+	}
+
+/*
+ *
+ *	Called by Audio Policy Server when a request to play DTMF String is approved
+ *	by the Audio Policy Server.
+ *
+ *	Leaves on failure.
+ *
+ */
+void CMMFDevSoundSvrImp::StartPlayDTMFStringL()
+	{
+
+	ASSERT(iMode== EMMFStateTonePlaying);
+
+	if(iCMMFHwDevice)
+		{
+        TInt error = KErrNone;
+        // Set volume and play format values
+        error = SetPlayFormat(iPlayFormat);
+		if (error != KErrNone)
+            {
+            iDevSoundObserver->ToneFinished(error);
+            return;
+            }
+        error = SetDeviceVolume(iVolume);
+
+		// turn off volume ramping - this is done in software below
+        if (error == KErrNone)
+			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
+
+        if (error != KErrNone)
+            {
+            iDevSoundObserver->ToneFinished(error);
+            return;
+            }
+
+        // Initialize attribute values
+		iPlayedBytesCount = 0;
+
+	    iDTMFGen.Configure(
+			iPlayFormat().iRate,
+			iPlayFormat().iChannels,
+		    iRepeatCount,
+			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
+		    I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
+			);
+
+		iCurrentGenerator = &iDTMFGen;
+
+        // Start playback
+		//need to trap this as we can leave with KErrUnderflow
+		//if there was no data to play - the error has already
+		//been sent to the observer and we don't want to call RunError
+        TRAP(error,DoPlayL());
+		if ((error != KErrUnderflow)&&(error != KErrNone))
+			{
+			User::Leave(error);
+			}
+		}
+	else
+		iDevSoundObserver->ToneFinished(KErrNotReady);
+	}
+
+/*
+ *
+ *	Called by Audio Policy Server when a request to play tone sequence is
+ *	approved by the Audio Policy Server.
+ *
+ *	Leaves on failure.
+ *
+ */
+void CMMFDevSoundSvrImp::StartPlayToneSequenceL()
+	{
+	ASSERT(iMode== EMMFStateTonePlaying);
+
+	if(iCMMFHwDevice)
+		{
+        TInt error = KErrNone;
+        // Set volume and play format values
+        if (iHwDeviceID.iUid == KMmfUidBtHwDevicePCM16ToPCM16)
+            error = SetPlayFormat(iPlayFormat);
+			else error = KErrGeneral;//hw device should always be pcm16 for tone
+		if (error != KErrNone)
+            {
+            iDevSoundObserver->ToneFinished(error);
+            return;
+            }
+
+        if (iHwDeviceID.iUid == KMmfUidBtHwDevicePCM16ToPCM16)
+            error = SetDeviceVolume(iVolume);
+		else 
+			error = KErrGeneral;//hw device should always be pcm16 for tone
+
+		// turn off volume ramping - this is done in software below
+        if (error == KErrNone)
+			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
+
+        if (error != KErrNone)
+            {
+            iDevSoundObserver->ToneFinished(error);
+            return;
+            }
+
+        // Initialize attribute values
+		iPlayedBytesCount = 0;
+
+		iSequenceGen.Configure(
+			iPlayFormat().iRate,
+			iPlayFormat().iChannels,
+			iRepeatCount,
+			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
+			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
+			);
+
+		iCurrentGenerator = &iSequenceGen;
+
+        // Start playback
+        DoPlayL();
+		}
+	else
+		iDevSoundObserver->ToneFinished(KErrNotReady);
+	}
+
+/*
+ *
+ *	Called by Audio Policy Server when the current DevSound instance looses the
+ *	policy because of another instance with a higher priority wants the device.
+ *
+ */
+void CMMFDevSoundSvrImp::SendEventToClient(const TMMFEvent& aEvent)
+	{
+	switch (iMode)
+		{
+		case EMMFStatePlaying:
+		case EMMFStateTonePlaying:
+		case EMMFStatePlayToneSequence:
+		case EMMFStateRecording:
+			{
+			Error(aEvent.iErrorCode);//Updates Bytes played informs client
+			iCMMFHwDevice->Stop();//unloads sound device
+			Stopped();//Updates policy		
+			iMode = EMMFStateIdle;
+			iAudioPolicyProxy->LaunchRequests();
+			break;
+			}
+		case EMMFStateIdle:
+			{	
+			iMode = EMMFStatePlaying;
+			iDevSoundObserver->SendEventToClient(aEvent);
+			break;
+			}
+		default:
+			break;
+		}
+	// Have audio Policy launch higher priority request:
+	}
+
+
+/**
+ *
+ *	Sets volume on HwDevice.
+ *	
+ *	@return	"TInt"
+ *			Error value returned by HwDevice.
+ *
+ */
+TInt CMMFDevSoundSvrImp::SetDeviceVolume(TInt aVolume)
+	{
+	TInt error = KErrNone;
+	if (iPlayCustomInterface) 
+		iPlayCustomInterface->SetVolume(aVolume);
+	else error = KErrNotReady;
+	return error;
+    }
+
+/**
+ *
+ *	Sets PlayFormat on HwDevice.
+ *	
+ *
+ *	@return	"TInt"
+ *			Error value returned by HwDevice.
+ *
+ */
+TInt CMMFDevSoundSvrImp::SetPlayFormat(RMdaDevSound::TCurrentSoundFormatBuf& aPlayFormat)
+	{
+	TInt error = KErrNone;
+	if (iCMMFHwDevice)
+		{
+		TTaskConfig taskConfig;
+		taskConfig.iUid = KUidBtRefDevSoundTaskConfig;
+		taskConfig.iRate = aPlayFormat().iRate;
+		
+		if (aPlayFormat().iChannels == 1)
+			{
+			taskConfig.iStereoMode = ETaskMono;
+			}
+		else if (aPlayFormat().iChannels == 2)
+			{
+			taskConfig.iStereoMode = ETaskInterleaved;
+			}
+		else
+			{
+			return KErrArgument;
+			}
+
+		error = iCMMFHwDevice->SetConfig(taskConfig);
+		//note the iEncoding and iBufferSize are already determined by the 
+		//CMMFHwDevice plugin and so are not set.
+		}
+	else
+		{
+		error = KErrNotReady;
+		}
+	return error;
+    }
+
+
+/**
+ *
+ *	Sets RecordFormat on HwDevice.
+ *	
+ *
+ *	@return	"TInt"
+ *			Error value returned by HwDevice.
+ *
+ */
+TInt CMMFDevSoundSvrImp::SetRecordFormat(RMdaDevSound::TCurrentSoundFormatBuf& aRecordFormat)
+	{
+	TInt error = KErrNone;
+	if (iCMMFHwDevice)
+		{
+		TTaskConfig taskConfig;
+		taskConfig.iUid = KUidBtRefDevSoundTaskConfig;
+		taskConfig.iRate = aRecordFormat().iRate;
+
+		if (aRecordFormat().iChannels == 1)
+			{
+			taskConfig.iStereoMode = ETaskMono;
+			}
+		else if (aRecordFormat().iChannels == 2)
+			{
+			taskConfig.iStereoMode = ETaskInterleaved;
+			}
+		else
+			{
+			return KErrArgument;
+			}
+
+		error = iCMMFHwDevice->SetConfig(taskConfig);
+		//note the iEncoding and iBufferSize are already determined by the 
+		//CMMFHwDevice plugin and so are not set.
+		}
+	else
+		{
+		error = KErrNotReady;
+		}
+	return error;
+    }
+
+
+/**
+ *
+ *	Sets record level on HwDevice.
+ *	
+ *
+ *	@return	"TInt"
+ *			Error value returned by HwDevice.
+ *
+ */
+TInt CMMFDevSoundSvrImp::SetDeviceRecordLevel(TInt aGain)
+	{
+	TInt error = KErrNone;
+	if (iRecordCustomInterface) 
+		iRecordCustomInterface->SetGain(aGain);
+	else error = KErrNotReady;
+	return error;
+
+    }
+
+
+/**
+ *
+ *	MMMFHwDeviceObserver mixin implementation.
+ *
+ *	The CMMFHwDevice implementation object calls this method during decoding
+ *	(playing), when it needs the encoded data in the buffer
+ *	aHwDataBuffer.
+ *
+ *	@return	"TInt"
+ *			Error code. KErrNone if success.
+ *
+ */
+TInt CMMFDevSoundSvrImp::FillThisHwBuffer(CMMFBuffer& aHwDataBuffer)
+	{
+	TInt err = KErrNone;
+    // Keep a reference to this Hw data Buffer. We need to send the 
+	// reference back to HwDevice implementation
+	iHwDeviceBuffer = static_cast<CMMFDataBuffer*> (&aHwDataBuffer);
+	// Set the request length, From HwDevice this comes with buffer
+	// length.
+	TInt len = iHwDeviceBuffer->Data().MaxLength();
+	// Ignore error. since buffer size = Buffer Length 
+	TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
+
+	if (iMode== EMMFStatePlaying) // Get Data from Observer
+		{
+		if (iLastBufferReceived)
+			{
+			iHwDeviceBuffer->Data().SetLength(0);
+			// Pass the buffer to the he device
+            err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
+			}
+		else
+			// Pass the buffer to the observer
+			iDevSoundObserver->BufferToBeFilled(&aHwDataBuffer);
+		}
+	else if (iMode== EMMFStateTonePlaying)
+		{
+        // Hw device will call this method right after its Start was called.
+        // When it calls this for the first time it hasn't played one single
+        // buffer yet so check that.
+        // In this case there's no need to set the active buffer as it's already
+        // waiting to be played.
+        if (!iFirstCallFromHwDevice)
+            SetActiveToneBuffer();
+
+		// If there is no data in the active buffer, tone play is finished.
+		// DevSound just have to wait for completion event from audio device.
+		if (iActiveToneBuffer->Data().Length() > 0)
+            { 
+			TInt tonelen = iActiveToneBuffer->Data().Length();
+
+			// don't enter more data than can be handled by the receiving buffer
+			if (len >= tonelen) len = tonelen;
+
+            // Copy data from tone buffer to hw device buffer
+            Mem::Copy((TAny*)(iHwDeviceBuffer->Data().Ptr()), (TAny*)(iActiveToneBuffer->Data().Ptr()), len);
+            
+            iHwDeviceBuffer->Data().SetLength(len);
+            // Play data and try to generate next data block
+			err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
+            if (err != KErrNone)
+            	return err;
+            // Check again whether this is the first call from Hw device.
+            // FillFreeToneBuffer assumes the iActiveToneBuffer has already
+            // been played.
+            if (!iFirstCallFromHwDevice)
+                err = FillFreeToneBuffer();
+            else
+                iFirstCallFromHwDevice = EFalse;  // Reset flag
+
+ 			}
+		else if (iFirstCallFromHwDevice)
+			{//we have no data in the tone buffer and thus have no 
+			//outstanding requests to play
+			err = KErrUnderflow; //simulate underrun
+			}
+
+	
+		// If there was an error filling the buffer could be corrupt data
+		// notify the client and stop playing.Set err to KErrNone. 
+		if (err != KErrNone)
+			{
+			Error(err);//Updates Bytes played informs client
+			err = KErrNone;
+			iCMMFHwDevice->Stop();//unloads sound device
+			Stopped();//Updates policy
+            }
+		}
+	else
+		{
+		err = KErrGeneral;
+		iDevSoundObserver->PlayError(KErrGeneral);
+		}
+	return err;
+	}
+
+
+/**
+ *
+ *	MMMFHwDeviceObserver mixin implementation.
+ *
+ *	The CMMFHwDevice implementation object calls this method during encoding
+ *	(recording), when it fills the buffer aHwDataBuffer with
+ *	encoded data.
+ *
+ *	@return	"TInt"
+ *			Error code. KErrNone if success.
+ *
+ */
+TInt CMMFDevSoundSvrImp::EmptyThisHwBuffer(CMMFBuffer& aHwDataBuffer)
+	{
+	TInt err = KErrNone;
+	if(iMode== EMMFStateRecording)
+		{
+		// Keep a reference to this Hw data Buffer. We need to send the 
+		// reference back to HwDevice implementation
+		iHwDeviceBuffer = static_cast<CMMFDataBuffer*>(&aHwDataBuffer);
+
+		// Set the request length, From HwDevice this comes with buffer
+		// length. MMF will use RequestSize attribute of the buffer.
+		// We can avoid this by setting in HwDevice implemenation
+		TInt len = iHwDeviceBuffer->Data().Length();
+		iRecordedBytesCount += len;
+		TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
+	
+		// if we're pausing (i.e. flushing) set the last buffer flag
+		// when we get an empty buffer from the logical driver
+		if(iPaused  && iHwDeviceBuffer->Data().Length() == 0)
+		{
+		iPaused = EFalse;
+
+		iHwDeviceBuffer->SetLastBuffer(ETrue);
+
+		iDevSoundEventHandler->CancelReceiveEvents();
+
+		iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
+		UpdatePolicyState();
+		}
+
+		// Send Data from Observer
+		iDevSoundObserver->BufferToBeEmptied(iHwDeviceBuffer);
+		}
+	else
+		{
+		err = KErrGeneral;
+		iDevSoundObserver->RecordError(KErrGeneral);
+		}
+
+	return err;
+	}
+
+
+/**
+ *
+ *	MMMFHwDeviceObserver mixin implementation.
+ *
+ *	The CMMFHwDevice implementation object calls this method when a message from
+ *	the hardware device implementation is received.
+ *
+ *	@return	"TInt"
+ *			Error code. KErrNone if success.
+ *
+ */
+TInt CMMFDevSoundSvrImp::MsgFromHwDevice(TUid aMessageType, const TDesC8& /*aMsg*/)
+	{
+	TInt result = KErrNotSupported;
+	if (aMessageType.iUid == KMmfHwDeviceObserverUpdateBytesPlayed)
+		{//this is used by sw codec wrapper to request a bytes played update
+		//bytes played won't be updated in Stopped() or Error() on sw cdoec wrapper
+		//as the sound device is closed. Non swCodec wrapper Hw device plugins
+		//can get there bytes updated on Stopped() and/or Error()
+		UpdateBytesPlayed();
+		result = KErrNone;
+		}
+	return result;
+	}
+
+/**
+ *
+ *	MMMFHwDeviceObserver mixin implementation.
+ *
+ *	The CMMFHwDevice implementation object calls this method when the current
+ *	encode or decode task is finished or stopped.  The policy state is updated
+ *
+ */
+void CMMFDevSoundSvrImp::Stopped()
+	{
+	//for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
+	//but non Swcodec wrappers hw devices may do it differently
+	//also don't know if non Swcodec wrap hw device will call Stopped or Error first
+	UpdateBytesPlayed();
+
+	iLastBufferReceived = EFalse;
+	iAudioPolicyPrioritySettings.iState = EMMFStateCompleted;
+	UpdatePolicyState();
+	}
+
+/**
+ *  MMMFHwDeviceObserver mixin implementation
+ *  Processes error from hw device
+ */
+void CMMFDevSoundSvrImp::Error(TInt aError)
+	{
+	if (iMode== EMMFStatePlaying)
+		{
+		//for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
+		//but non Swcodec wrappers hw devices may do it differently
+		//also don't know if non Swcodec wrap hw device will call Stopped or Error first
+		UpdateBytesPlayed();
+
+        	iDevSoundObserver->PlayError(aError);		
+        	iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
+        	UpdatePolicyState();
+		}
+	else if (iMode== EMMFStateRecording)
+		{
+        iDevSoundObserver->RecordError(aError);
+		}
+	else if (iMode== EMMFStateTonePlaying)
+		{
+        iDevSoundObserver->ToneFinished(aError);
+		}
+	//else can't handle error
+	}
+
+
+/********************************************************************************
+ *				Non Exported public functions ends here							*
+ ********************************************************************************/
+
+
+/********************************************************************************
+ *				Private functions begins here									*
+ ********************************************************************************/
+
+TInt CMMFDevSoundSvrImp::InitializeFormat(RMdaDevSound::TSoundFormatsSupportedBuf& aSupportedFormat,
+		RMdaDevSound::TCurrentSoundFormatBuf& aFormat)
+	{
+	// Choose an encoding
+	TUint32 enc = aSupportedFormat().iEncodings;
+	// Always defaults to this
+	if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
+		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
+	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
+		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
+	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
+		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
+	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
+		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
+
+	// default to Monophonic playback:
+	aFormat().iChannels=1;
+
+	// Store the device capabilities (WINS supports from 8000 Hz to 44100 Hz)
+	if ((aSupportedFormat().iMinRate <= 8000) && (8000 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate = EMMFSampleRate8000Hz;
+	if ((aSupportedFormat().iMinRate <= 11025) && (11025 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate11025Hz;
+	if ((aSupportedFormat().iMinRate <= 12000) && (12000 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate12000Hz;
+	if ((aSupportedFormat().iMinRate <= 16000) && (16000 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate16000Hz;
+	if ((aSupportedFormat().iMinRate <= 22050) && (22050 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate22050Hz;
+	if ((aSupportedFormat().iMinRate <= 24000) && (24000 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate24000Hz;
+	if ((aSupportedFormat().iMinRate <= 32000) && (32000 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate32000Hz;
+	if ((aSupportedFormat().iMinRate <= 44100) && (44100 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate44100Hz;
+	if ((aSupportedFormat().iMinRate <= 48000) && (48000 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate48000Hz;
+	if ((aSupportedFormat().iMinRate <= 64000) && (64000 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate64000Hz;
+	if ((aSupportedFormat().iMinRate <= 88200) && (88200 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate88200Hz;
+	if ((aSupportedFormat().iMinRate <= 96000) && (96000 <= aSupportedFormat().iMaxRate))
+		iDeviceCapabilities.iRate |= EMMFSampleRate96000Hz;
+
+	// Store the encodings supported
+	iDeviceCapabilities.iEncoding = 0;
+	if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
+		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding16BitPCM;
+	if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
+		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitALaw;
+	if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
+		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitMuLaw;
+	if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
+		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitPCM;
+
+	// Mono and Stereo support
+	if (aSupportedFormat().iChannels == 2)
+		iDeviceCapabilities.iChannels = EMMFStereo;
+	iDeviceCapabilities.iChannels |= EMMFMono;
+
+	iDeviceCapabilities.iBufferSize = aSupportedFormat().iMaxBufferSize;
+	// Default
+	iDeviceConfig.iRate = EMMFSampleRate8000Hz;
+	iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
+	iDeviceConfig.iChannels = EMMFMono;
+
+	return KErrNone;
+	}
+
+/*
+ *
+ *	Makes request to Policy Server (asynchronous call)
+ *
+ */
+void CMMFDevSoundSvrImp::RequestPolicy()
+	{
+	iDevSoundEventHandler->CancelReceiveEvents();
+	iDevSoundEventHandler->ReceiveEvents();
+	iAudioPolicyPrioritySettings.iCapabilities = iParent.CheckClientCapabilities();
+	iAudioPolicyProxy->MakeRequest(iAudioPolicyPrioritySettings);
+	}
+
+/*
+ *
+ *	Creates buffer and begin playback using the specified tone generator.
+ *
+ */
+void CMMFDevSoundSvrImp::DoPlayL()
+	{
+	// Delete any buffer from previous call and try to create maximum buffer 
+	// size. Double Buffer the Tone data.
+	if (iToneBuffer1)
+		{
+		delete iToneBuffer1; 
+		iToneBuffer1 = NULL; 
+		}
+	//note the tone buffer needs to be the same as the pcm16->pcm16 'null'
+	//hw device plugin
+	// Buffer size = (SampleRate * BytesPerSample * Channels) / 4
+	TInt useBufferOfSize = ((SamplingFrequency() * 2 * NumberOfChannels())/KDevSoundFramesPerSecond + (KDevSoundDeltaFrameSize-1)) &~ (KDevSoundDeltaFrameSize-1);
+	//clamp buffer to desired limits
+	if(useBufferOfSize < KDevSoundMinFrameSize) 
+		useBufferOfSize = KDevSoundMinFrameSize;
+	else if(useBufferOfSize > KDevSoundMaxFrameSize) 
+		useBufferOfSize = KDevSoundMaxFrameSize;
+
+	//clamp buffer to limits of hardware
+	if(useBufferOfSize < Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize))
+		useBufferOfSize = Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize);
+	else if(useBufferOfSize > Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize))
+		useBufferOfSize = Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize);
+
+	iToneBuffer1 = CMMFDataBuffer::NewL(useBufferOfSize);
+	User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer1->Data()));
+
+	if (iToneBuffer2)
+		{
+		delete iToneBuffer2; 
+		iToneBuffer2 = NULL;
+		}
+	iToneBuffer2 = CMMFDataBuffer::NewL(useBufferOfSize);
+	User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer2->Data()));
+
+	// Assign active buffer
+	iActiveToneBuffer = iToneBuffer1;
+
+	// Hw device hasn't played anything yet so don't change
+    // active buffer. This is checked in FillThisHwBuffer.
+    iFirstCallFromHwDevice = ETrue;
+
+    // Start HwDevice to play data
+    User::LeaveIfError(iCMMFHwDevice->Start(EDevDecode, EDevOutFlow));
+	
+	}
+
+/*
+ *
+ *	This method assigns the other buffer as active buffer. The tone audio 
+ *	generator should fill data in the other buffer by now.
+ *
+ */
+void CMMFDevSoundSvrImp::SetActiveToneBuffer()
+	{
+	if (iActiveToneBuffer == iToneBuffer1)
+		iActiveToneBuffer = iToneBuffer2;
+	else if (iActiveToneBuffer == iToneBuffer2)
+		iActiveToneBuffer = iToneBuffer1;
+	}
+
+/*
+ *
+ *	This method fills data into the free buffer.
+ *
+ *	@return	"TInt"
+ *			Error code. KErrNone if success.
+ *
+ */
+TInt CMMFDevSoundSvrImp::FillFreeToneBuffer()
+	{
+	TInt err(KErrNone);
+	if (iActiveToneBuffer == iToneBuffer1)
+		err = iCurrentGenerator->FillBuffer(iToneBuffer2->Data());
+	else if (iActiveToneBuffer == iToneBuffer2)
+		err = iCurrentGenerator->FillBuffer(iToneBuffer1->Data());
+	return err;
+	}
+
+/*
+ *
+ *	Updates the policy state based on Audio policy settings of this devsound instance
+ *
+ */
+TInt CMMFDevSoundSvrImp::UpdatePolicyState()
+	{
+	TInt error = iAudioPolicyProxy->UpdateState(iAudioPolicyPrioritySettings);
+	return error;
+	}
+
+/*
+ *
+ *	Initializes audio device node by setting volume, and sampling rate.
+ *
+ *	@return	"TInt"
+ *			Error Code. KErrNone if success.
+ *
+ */
+TInt CMMFDevSoundSvrImp::InitTask()
+	{
+	// No Implementation
+	return KErrNone;
+	}
+
+
+
+/*
+ *
+ *	Returns an integer representing Sampling Frequency the device is currently
+ *	configured to.
+ *
+ *	@return	"TInt"
+ *			Sampling Frequency.
+ *
+ */
+TInt CMMFDevSoundSvrImp::SamplingFrequency()
+	{
+	if(iDeviceConfig.iRate == EMMFSampleRate8000Hz)
+		return 8000;
+	else if(iDeviceConfig.iRate == EMMFSampleRate11025Hz)
+		return 11025;
+	else if(iDeviceConfig.iRate == EMMFSampleRate12000Hz)
+		return 12000;
+	else if(iDeviceConfig.iRate == EMMFSampleRate16000Hz)
+		return 16000;
+	else if(iDeviceConfig.iRate == EMMFSampleRate22050Hz)
+		return 22050;
+	else if(iDeviceConfig.iRate == EMMFSampleRate24000Hz)
+		return 24000;
+	else if(iDeviceConfig.iRate == EMMFSampleRate32000Hz)
+		return 32000;
+	else if(iDeviceConfig.iRate == EMMFSampleRate44100Hz)
+		return 44100;
+	else if(iDeviceConfig.iRate == EMMFSampleRate48000Hz)
+		return 48000;
+	else if(iDeviceConfig.iRate == EMMFSampleRate88200Hz)
+		return 88200;
+	else if(iDeviceConfig.iRate == EMMFSampleRate96000Hz)
+		return 96000;
+	else
+		return 8000; //default
+	}
+ 
+/*
+ *
+ *	Returns an integer representing number of channels the device is currently
+ *	configured to.
+ *
+ *	@return	"TInt"
+ *			Number of audio channels 1 if mono, 2 if stereo.
+ *
+ */
+TInt CMMFDevSoundSvrImp::NumberOfChannels()
+	{
+	if(iDeviceConfig.iChannels == EMMFMono)
+		return 1;
+	else
+		return 2;
+	}
+
+/*
+ *
+ *	Returns an integer representing number of bytes in each audio sample
+ *	
+ *
+ *	@return	"TInt"
+ *			Number of of bytes in each audio sample.
+ *
+ */
+TInt CMMFDevSoundSvrImp::BytesPerAudioSample()
+	{
+	TInt bytes=1;
+	switch (iDeviceConfig.iEncoding)
+		{
+		case EMMFSoundEncoding8BitPCM:
+		case EMMFSoundEncoding8BitALaw:
+		case EMMFSoundEncoding8BitMuLaw:
+			{
+			bytes=1;
+			}
+		break;
+		case EMMFSoundEncoding16BitPCM:
+			{
+			bytes=2;
+			}
+		break;
+		}
+	return bytes;
+	}
+
+
+/********************************************************************************
+ *				Private functions ends here										*
+ ********************************************************************************/