mmhais/refacladapt/src/tonehwdevice/tonehwdevice.cpp
changeset 0 40261b775718
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmhais/refacladapt/src/tonehwdevice/tonehwdevice.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,1031 @@
+// tonehwdevice.cpp
+// Copyright (c) 2006-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 FILES
+#include <mmf/server/mmfhwdevice.h>
+#include "tonehwdevice.hrh" //for KUidToneHwDevice
+#include <ecom/implementationproxy.h> // For making it ECom plugin
+#include "tonehwdevice.h"
+
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES   
+
+// CONSTANTS
+const TImplementationProxy ImplementationTable[] =
+	{
+	IMPLEMENTATION_PROXY_ENTRY(KUidToneHwDevice,  CToneHwDevice::NewL),
+	};
+//current supported sample rate
+const TInt KSupportedSampleRate = 8000;
+
+// ---------------------------------------------------------------------------
+// Default constructor
+// ---------------------------------------------------------------------------
+//
+CToneHwDevice::CToneHwDevice()
+	{
+	DP_CONTEXT(CToneHwDevice::CToneHwDevice *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	DP_OUT();
+	}
+
+// -----------------------------------------------------------------------------
+// Symbian 2nd phase constructor
+// -----------------------------------------------------------------------------
+//
+void CToneHwDevice::ConstructL()
+	{
+	DP_CONTEXT(CToneHwDevice::ConstructL *CD0*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	iHwDataBufferFill = CMMFDataBuffer::NewL(sizeof(TToneData));
+	iHwDataBufferFill->SetLastBuffer(EFalse);
+	iHwDataBufferFill->Data().SetLength(sizeof(TToneData));
+	iHwDataBufferFill->SetRequestSizeL(sizeof(TToneData));
+
+	iCodec = new(ELeave)CToneCodec();
+
+	DP_OUT();
+	}
+
+// -----------------------------------------------------------------------------
+// Symbian constructor
+// -----------------------------------------------------------------------------
+//
+CToneHwDevice* CToneHwDevice::NewL()
+	{
+	DP_STATIC_CONTEXT(CToneHwDevice::NewL *CD0*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	CToneHwDevice* self = new (ELeave) CToneHwDevice();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	DP0_RET(self, "0x%x");
+	}
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CToneHwDevice::~CToneHwDevice()
+	{
+	DP_CONTEXT(CToneHwDevice::~CToneHwDevice *CD0*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	delete iHwDataBufferFill;
+	delete iCodec;
+	delete iPlayCustomInterface;
+
+	if(iDataPath)
+		{
+		delete iDataPath;
+		}
+
+	if(iToneBuffer1)
+		{
+		delete iToneBuffer1;
+		}
+	if(iToneBuffer2)
+		{
+		delete iToneBuffer2;
+		}
+	DP_OUT();
+	}
+
+/**
+*
+* Codec
+*
+*/
+CToneCodec& CToneHwDevice::Codec()
+	{
+	return *iCodec;
+	}
+
+// ---------------------------------------------------------------------------
+// from class CMMFHwDevice
+// CToneHwDevice::Init
+// ---------------------------------------------------------------------------
+//
+TInt CToneHwDevice::Init(THwDeviceInitParams& aDevInfo)
+	{
+	DP_CONTEXT(CToneHwDevice::Init *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	if (!iToneInitialized) // Check if tones is not initialized yet.
+		{
+		iToneInitialized = ETrue;
+		}
+
+	// [ precondition that aDevInfo has a valid observer ]
+	if (!aDevInfo.iHwDeviceObserver) 
+		{
+		DP0_RET(KErrArgument, "%d");
+		}
+
+	iHwDeviceObserver = aDevInfo.iHwDeviceObserver;
+
+	//[ assert the post condition ]
+	if (!iCodec)
+		{
+		DP0_RET(KErrNotSupported, "%d");
+		}
+
+	DP0_RET(KErrNone, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class CMMFHwDevice
+// CToneHwDevice::Start
+// ---------------------------------------------------------------------------
+//
+TInt CToneHwDevice::Start(TDeviceFunc /*aFuncCmd*/, TDeviceFlow /*aFlowCmd*/)
+	{
+	DP_CONTEXT(CToneHwDevice::Start *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	TInt error = KErrNone;
+		
+	// Start for first time OR resuming
+	if (!iTonePlaying || iDataPath->State() == CToneDataPath::EPaused)
+		{
+		iLastBuffer = EFalse;
+		//[ assert precondition that play custom interface is present]
+		//if there is no tone play custom interface then the user of the CToneHwDevice
+		//cannot have set any of the custom settings such as sample rate.
+		if (!iPlayCustomInterface)
+			{
+			DP0_RET(KErrNotReady, "%d");
+			}
+	
+		//play
+		if (!iDataPath)
+			{
+			//create a datapath
+			TRAP(error,iDataPath = CToneDataPath::NewL());
+			if ((iDataPath)&&(error == KErrNone))
+				{
+				ASSERT(iHwDeviceObserver);
+				iDataPath->SetObserver(*this);
+				error = iDataPath->AddCodec(*iCodec);
+				if (error == KErrNone)
+					{
+					iDeviceBufferSize = (iCodec->SinkBufferSize());
+					}
+				}
+			}
+		if ((error == KErrNone) && (iDataPath->State() != CToneDataPath::EPlaying))
+			{
+			//datapath was created ok and we are not playing
+			if (iDataPath->State() == CToneDataPath::EStopped)
+				{
+				// starting from 'fresh so set sound device settings
+				if (!iDataPath->Device().Handle())
+					{
+					//if Device() is called then we need a valid sound device handle
+					error = iDataPath->Device().Open();
+					if (error != KErrNone)
+						{
+						DP0_RET(error, "%d");
+						}
+						
+					}
+				static_cast<TToneCustomInterface*>(iPlayCustomInterface)->SetDevice(&(iDataPath->Device()));
+				
+				TUint iVol = iPlayCustomInterface->Volume();
+				iDataPath->Device().SetPlayVolume(iVol);
+							
+				soundDeviceSettings().iRate = iSampleRate;
+			
+				//this would normally be pcm16
+				soundDeviceSettings().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
+			
+				//1 = mono 2 = stereo
+				soundDeviceSettings().iChannels = iChannels;
+			
+				//tell sound driver what buffer size to expect
+				//it is up the the implementor to make use the device can support
+				//the required buffer size
+				soundDeviceSettings().iBufferSize = iDeviceBufferSize;
+				error = iDataPath->Device().SetPlayFormat(soundDeviceSettings);
+			
+				} // End of iDataPath->State() == CToneDataPath::EStopped
+			
+			//else resuming from pause	
+			if ((error == KErrNone)||(error == KErrInUse))
+				{
+				// Hw device hasn't played anything yet so don't change
+				// active buffer. This is checked in FillThisHwBuffer.
+				if(iDataPath->State() != CToneDataPath::EPaused)
+					{
+					iFirstCallFromHwDevice = ETrue;		
+					}
+				iTonePlaying = ETrue;
+				error = iDataPath->Start();
+				}
+			}//status == KErrNone       
+		}
+	else // if tone playback is already ongoing do nothing
+		{
+		DP0(DLINFO,"Previous tone call is not completed yet");
+		}
+	DP0_RET(error, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class CMMFHwDevice
+// CToneHwDevice::Stop
+// ---------------------------------------------------------------------------
+TInt CToneHwDevice::Stop()
+	{
+	DP_CONTEXT(CToneHwDevice::Stop *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	if (iTonePlaying) 
+		{
+		iTonePlaying = EFalse;
+		}
+	
+	if (!iDataPath)
+		{
+		DP0_RET(KErrNotReady, "%d");
+		}
+		
+	delete iDataPath;
+	iDataPath = NULL;
+	
+	//Setting device to NULL since after stop it doesn't exists any more
+	if(iPlayCustomInterface)
+		{
+		static_cast<TToneCustomInterface*>(iPlayCustomInterface)->SetDevice(NULL);
+		}
+	
+	DP0_RET(KErrNone, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class CMMFHwDevice
+// CToneHwDevice::Pause
+// ---------------------------------------------------------------------------
+//
+TInt CToneHwDevice::Pause()
+	{
+	DP_CONTEXT(CToneHwDevice::Pause *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	if (!iDataPath) 
+		{
+		DP0_RET(KErrNotReady, "%d");
+		}
+	iDataPath->Pause();
+	
+	DP0_RET(KErrNone, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class CMMFHwDevice
+// CToneHwDevice::StopAndDeleteCodec
+// ---------------------------------------------------------------------------
+//
+TInt CToneHwDevice::StopAndDeleteCodec()
+	{
+	DP_CONTEXT(CToneHwDevice::StopAndDeleteCodec *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	DP0_RET(KErrNotSupported, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class CMMFHwDevice
+// CToneHwDevice::DeleteCodec
+// ---------------------------------------------------------------------------
+//
+TInt CToneHwDevice::DeleteCodec()
+	{
+	DP_CONTEXT(CToneHwDevice::DeleteCodec *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	DP0_RET(KErrNotSupported, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class CMMFHwDevice
+// CToneHwDevice::SetConfig
+// ---------------------------------------------------------------------------
+//
+TInt CToneHwDevice::SetConfig(TTaskConfig& aConfig)
+	{
+	DP_CONTEXT(CToneHwDevice::SetConfig *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	if (aConfig.iUid != KUidRefDevSoundTaskConfig)
+		{
+		DP0_RET(KErrArgument, "%d");
+		}
+
+	if (aConfig.iRate != KSupportedSampleRate )
+		{
+		DP0_RET(KErrNotSupported, "%d");
+		}
+
+	iSampleRate = aConfig.iRate;
+
+	if (aConfig.iStereoMode == ETaskMono)
+		{
+		iChannels = 1;
+		}
+	else if (aConfig.iStereoMode == ETaskInterleaved || aConfig.iStereoMode == ETaskNonInterleaved)
+		{
+		iChannels = 2;
+		}
+	else
+		{
+		DP0_RET(KErrArgument, "%d");
+		}
+		
+	DP0_RET(KErrNone, "%d");
+	}
+
+// CToneHwDevice::FillThisHwBuffer
+// ---------------------------------------------------------------------------
+TInt CToneHwDevice::FillThisHwBuffer(CMMFBuffer& aHwBuffer)
+	{
+	DP_CONTEXT(CToneHwDevice::FillThisHwBuffer *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	
+	TInt err(KErrNone);
+	
+	if(iFirstCallFromHwDevice)
+		{
+		err = iHwDeviceObserver->FillThisHwBuffer(aHwBuffer);
+		}
+	else
+		{
+		err = ThisHwBufferFilled(aHwBuffer);
+		}
+	DP0_RET(err,"%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class CMMFHwDevice
+// CToneHwDevice::ThisHwBufferFilled
+// ---------------------------------------------------------------------------
+//
+TInt CToneHwDevice::ThisHwBufferFilled(CMMFBuffer& aMmfBuffer)
+	{
+	DP_CONTEXT(CToneHwDevice::ThisHwBufferFilled *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	TInt err = KErrNone;
+	CMMFDataBuffer* myBuffer = static_cast<CMMFDataBuffer*> (&aMmfBuffer);
+	// Set the request length, From HwDevice this comes with buffer
+	// length.
+	TInt len = myBuffer->Data().MaxLength();
+	// Ignore error. since buffer size = Buffer Length 
+	TRAP(err, myBuffer->SetRequestSizeL(len));
+
+	if(iFirstCallFromHwDevice)
+		{
+		myBuffer->SetLastBuffer(EFalse);
+		
+		Mem::Copy((TAny*)(&myToneData), (TAny*)(myBuffer->Data().Ptr()), sizeof(TToneData));
+		
+		err = ReadToneData();
+		if(err==KErrNone)
+			{
+			err= GenerateBufferData();
+			}
+		}
+	else
+		{
+		// 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.
+		SetActiveToneBuffer();
+		}
+
+	if (err == KErrNone)
+		{
+		// 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)
+			{
+			iActiveToneBuffer->SetLastBuffer(ETrue);
+			myBuffer->SetLastBuffer(ETrue);
+			iLastBuffer=ETrue;
+			}
+
+		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*)(myBuffer->Data().Ptr()), (TAny*)(iActiveToneBuffer->Data().Ptr()), len);
+			
+		myBuffer->Data().SetLength(len);
+
+		//Play data and try to generate next data block
+		TRAP(err,iDataPath->BufferFilledL(static_cast<CMMFDataBuffer&> (*myBuffer)));
+		if(err == KErrNone)
+			{
+			if(iLastBuffer)
+				{
+				// coverity[check_after_deref]
+				if(myBuffer)
+					{
+					myBuffer = NULL;
+					}
+				FreeBuffers();
+				iFirstCallFromHwDevice = EFalse;
+				}
+			else
+				{
+				// 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 
+					}
+				}
+			}
+		}
+	if ( err != KErrNone )
+		{
+		myBuffer->SetLastBuffer(ETrue);
+		myBuffer->Data().SetLength(0);
+		//Use error additional variable for sending last buffer so can still send Error(err)
+		TRAPD(datapathErr, iDataPath->BufferFilledL(static_cast<CMMFDataBuffer&> (*myBuffer)));
+		// coverity[check_after_deref]
+		if(myBuffer)
+			{
+			myBuffer = NULL;
+			}
+		FreeBuffers();
+		iFirstCallFromHwDevice = EFalse;
+		if ( datapathErr != KErrNone )
+			{
+			iHwDeviceObserver->Error(datapathErr);
+			DP0_RET(datapathErr, "%d");
+			}
+		iHwDeviceObserver->Error(err);
+		}
+	DP0_RET(err, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class MMMFHwDeviceObserver
+// CToneHwDevice::ThisHwBufferEmptied
+// ---------------------------------------------------------------------------
+TInt CToneHwDevice::ThisHwBufferEmptied(CMMFBuffer& /*aMmfBuffer*/)
+	{
+	DP_CONTEXT(CToneHwDevice::ThisHwBufferEmptied *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	DP0_RET(KErrNotSupported, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class MMMFHwDeviceObserver
+// CToneHwDevice::EmptyThisHwBuffer
+// ---------------------------------------------------------------------------
+TInt CToneHwDevice::EmptyThisHwBuffer(CMMFBuffer& /*aMmfBuffer*/)
+	{
+	DP_CONTEXT(CToneHwDevice::EmptyThisHwBuffer *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	DP0_RET(KErrNotSupported, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class MMMFHwDeviceObserver
+// CToneHwDevice::MsgFromHwDevice
+// ---------------------------------------------------------------------------
+TInt CToneHwDevice::MsgFromHwDevice(TUid aMessageType, const TDesC8& aMsg)
+	{
+	DP_CONTEXT(CToneHwDevice::MsgFromHwDevice *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	TInt err(KErrNone);
+	err = iHwDeviceObserver->MsgFromHwDevice(aMessageType, aMsg);
+	DP0_RET(err, "%d");
+	}
+
+// ---------------------------------------------------------------------------
+// from class MMMFHwDeviceObserver
+// CToneHwDevice::Stopped
+// ---------------------------------------------------------------------------
+void CToneHwDevice::Stopped()
+	{
+	DP_CONTEXT(CToneHwDevice::Stopped *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	iHwDeviceObserver->Stopped();
+	DP_OUT();
+	}
+
+// ---------------------------------------------------------------------------
+// from class MMMFHwDeviceObserver
+// CToneHwDevice::Error
+// ---------------------------------------------------------------------------
+void CToneHwDevice::Error(TInt aError)
+	{
+	DP_CONTEXT(CToneHwDevice::Error *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	iHwDeviceObserver->Error(aError);
+	DP_OUT();
+	}
+
+// ---------------------------------------------------------------------------
+// from class CMMFHwDevice
+// CToneHwDevice::CustomInterface
+// ---------------------------------------------------------------------------
+//
+TAny* CToneHwDevice::CustomInterface(TUid aInterfaceUid)
+	{
+	DP_CONTEXT(CToneHwDevice::CustomInterface *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	TAny* ret = NULL;
+	TInt err = KErrNone;
+
+	if (aInterfaceUid.iUid == KMmfPlaySettingsCustomInterface)
+		{
+		if (!iPlayCustomInterface)
+			{
+			TRAP(err,iPlayCustomInterface = new(ELeave)TToneCustomInterface());
+			}
+		if (err)
+			{
+			ret = NULL;
+			}
+		else
+			{
+			ret = static_cast<TAny*>(iPlayCustomInterface);
+			}
+		}
+	else if (aInterfaceUid == KIgnoreUnderflowCustomInterfaceTypeUid)
+		{
+		if (!iDataPath)
+			{
+			ret = NULL;			
+			}
+		else
+			{
+			ret = static_cast<CToneDataPath*>(iDataPath)->CustomInterface(aInterfaceUid);	
+			}	
+		}
+
+	DP_OUT();
+	return ret;
+	}
+
+TInt CToneHwDevice::ReadToneData()
+	{
+	DP_CONTEXT(CToneHwDevice::ReadToneData *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	TUint vol;
+	myToneData.GetType(iToneType);
+	TInt64 zeroInt64(0);
+	iFrequency1 = myToneData.GetFrequencyOne();
+	iFrequency2 = myToneData.GetFrequencyTwo();
+	myToneData.GetDuration(iDuration);
+
+	myToneData.GetRepeatTrailingSilence(iRepeatTrailingSilence);
+	iRepeatCount = myToneData.GetRepeatCount();
+	iRampDuration = iPlayCustomInterface->VolumeRamp();
+	vol = iPlayCustomInterface->Volume();
+	iDataPath->Device().SetPlayVolume(vol);
+	switch (iToneType)
+		{
+		case TToneData::ESimple:
+			DP0(DLINFO, "Playing simple tone");
+			iDataPath->Device().GetPlayFormat(soundDeviceSettings);
+			if((iFrequency1<0) || (iDuration.Int64() < zeroInt64))
+				{
+				iHwDeviceObserver->Error(KErrArgument);
+				DP0_RET(KErrArgument, "%d");
+				}
+			iToneGen.SetFrequencyAndDuration(iFrequency1,iDuration);
+			// Configure tone generator
+			iToneGen.Configure(
+				soundDeviceSettings().iRate,
+				soundDeviceSettings().iChannels,
+				iRepeatCount,
+				I64LOW((iRepeatTrailingSilence.Int64()*soundDeviceSettings().iRate)/1000000),
+				I64LOW((iRampDuration.Int64()*soundDeviceSettings().iRate)/1000000)
+				);
+			iCurrentGenerator = &iToneGen;
+			break;
+		case TToneData::EDual:
+			DP0(DLINFO, "Playing dual tone");
+			iDataPath->Device().GetPlayFormat(soundDeviceSettings);
+			if((iFrequency1<0) || (iFrequency2<0) || (iDuration.Int64() < zeroInt64))
+				{
+				iHwDeviceObserver->Error(KErrArgument);
+				DP0_RET(KErrArgument, "%d");
+				}
+			iDualToneGen.SetFrequencyAndDuration(iFrequency1, iFrequency2, iDuration);
+			// Configure dual tone generator
+			iDualToneGen.Configure(
+				soundDeviceSettings().iRate,
+				soundDeviceSettings().iChannels,
+				iRepeatCount,
+				I64LOW((iRepeatTrailingSilence.Int64()*soundDeviceSettings().iRate)/KOneMillionMicroSeconds),
+				I64LOW((iRampDuration.Int64()*soundDeviceSettings().iRate)/KOneMillionMicroSeconds)
+				);
+			iCurrentGenerator = &iDualToneGen;
+			break;
+		case TToneData::EDtmfString:
+			DP0(DLINFO, "Playing DTMF string");
+			myToneData.GetDtmfLenghts(myToneOnLength, myToneOffLength, myPauseLength);
+			iDTMFGen.SetToneDurations(myToneOnLength, myToneOffLength, myPauseLength);
+			iDTMFString = myToneData.GetDTMFString();
+			if(!ValidDTMFString(const_cast<TDesC&>(*iDTMFString)))
+				{
+				DP0(DLINFO, "Invalid DTMF String");
+				iHwDeviceObserver->Error(KErrCorrupt);
+				DP0_RET(KErrCorrupt, "%d");
+				}
+			iDTMFGen.SetString(const_cast<TDesC&>(*iDTMFString));
+			iDataPath->Device().GetPlayFormat(soundDeviceSettings);
+			iDTMFGen.Configure(
+				soundDeviceSettings().iRate,
+				soundDeviceSettings().iChannels,
+				iRepeatCount,
+				I64LOW((iRepeatTrailingSilence.Int64()*soundDeviceSettings().iRate)/1000000),
+				I64LOW((iRampDuration.Int64()*soundDeviceSettings().iRate)/1000000)
+				);
+			iCurrentGenerator = &iDTMFGen;
+			break;
+		case TToneData::ESequence:
+			DP0(DLINFO, "Playing tone sequence");
+			iSequenceData = myToneData.GetSequenceData();
+			// Check whether the sequence is signed or not
+			if (!RecognizeSequence(*iSequenceData))
+				{
+				DP0(DLINFO, "Invalid Sequence Sign");
+				iHwDeviceObserver->Error(KErrCorrupt);
+				DP0_RET(KErrCorrupt, "%d");
+				}
+			iSequenceGen.SetSequenceData(*iSequenceData);
+			iDataPath->Device().GetPlayFormat(soundDeviceSettings);
+			iSequenceGen.Configure(
+				soundDeviceSettings().iRate,
+				soundDeviceSettings().iChannels,
+				iRepeatCount,
+				I64LOW((iRepeatTrailingSilence.Int64()*soundDeviceSettings().iRate)/1000000),
+				I64LOW((iRampDuration.Int64()*soundDeviceSettings().iRate)/1000000)
+				);
+			iCurrentGenerator = &iSequenceGen;
+			break;
+		case TToneData::EFixedSequence:
+			DP0(DLINFO, "Playing FixedSequnce");
+			iHwDeviceObserver->Error(KErrNotSupported);
+			DP0_RET(KErrNotSupported, "%d");
+		default:
+			DP0_RET(KErrNotSupported, "%d");
+		}
+	DP0_RET(KErrNone, "%d");
+	}
+
+/*
+ *
+ *	Creates buffer and begin playback using the specified tone generator.
+ *
+ */
+TInt CToneHwDevice::GenerateBufferData()
+	{
+	DP_CONTEXT(CToneHwDevice::GenerateBufferData *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	
+	TInt err;
+	err = KErrNone;
+	
+	// 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;
+		}
+
+	TRAP(err, iToneBuffer1 = CMMFDataBuffer::NewL(useBufferOfSize));
+	if ( err != KErrNone )
+		{
+		DP0_RET(err, "%d");
+		}
+	
+	err = iCurrentGenerator->FillBuffer(iToneBuffer1->Data());
+	if(err!=KErrNone)
+		{
+		DP0_RET(err, "%d");
+		}
+
+	if (iToneBuffer2)
+		{
+		delete iToneBuffer2; 
+		iToneBuffer2 = NULL;
+		}
+		
+	TRAP(err, iToneBuffer2 = CMMFDataBuffer::NewL(useBufferOfSize));
+	if ( err != KErrNone )
+		{
+		DP0_RET(err, "%d");
+		}
+	
+	err = iCurrentGenerator->FillBuffer(iToneBuffer2->Data());
+	if(err!=KErrNone)
+		{
+		DP0_RET(err, "%d");
+		}
+
+	// Assign active buffer
+	iActiveToneBuffer = iToneBuffer1;
+	DP0_RET(KErrNone, "%d");
+	}
+
+/*
+ *
+ *	This method assigns the other buffer as active buffer. The tone audio 
+ *	generator should fill data in the other buffer by now.
+ *
+ */
+void CToneHwDevice::SetActiveToneBuffer()
+	{
+	if (iActiveToneBuffer == iToneBuffer1)
+		iActiveToneBuffer = iToneBuffer2;
+	else if (iActiveToneBuffer == iToneBuffer2)
+		iActiveToneBuffer = iToneBuffer1;
+	}
+
+	
+void CToneHwDevice::FreeBuffers()
+	{
+	if(iToneBuffer1)
+		{
+		delete iToneBuffer1;
+		iToneBuffer1 = NULL;
+		}
+	if(iToneBuffer2)
+		{
+		delete iToneBuffer2;
+		iToneBuffer2 = NULL;
+		}
+	}
+	
+	/*
+ *
+ *	Returns an integer representing Sampling Frequency the device is currently
+ *	configured to.
+ *
+ *	@return	"TInt"
+ *			Sampling Frequency.
+ *
+ */
+TInt CToneHwDevice::SamplingFrequency()
+	{
+	return iSampleRate;
+	}
+	
+/*
+ *
+ *	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 CToneHwDevice::NumberOfChannels()
+	{
+	if(iChannels == EMMFMono)
+		return 1;
+	else
+		return 2;
+	}
+	
+	/*
+ *
+ *	This method fills data into the free buffer.
+ *
+ *	@return	"TInt"
+ *			Error code. KErrNone if success.
+ *
+ */
+TInt CToneHwDevice::FillFreeToneBuffer()
+	{
+	TInt err(KErrNone);
+	if (iActiveToneBuffer == iToneBuffer1)
+		{
+		err = iCurrentGenerator->FillBuffer(iToneBuffer2->Data());
+		}
+	else if (iActiveToneBuffer == iToneBuffer2)
+		{
+		err = iCurrentGenerator->FillBuffer(iToneBuffer1->Data());
+		}
+	return err;
+	}
+
+TBool CToneHwDevice::RecognizeSequence(const TDesC8& aData)
+	{
+	// Reference plug-in only supports its own sequence format
+	_LIT8(KSequenceSignature,"SQNC");
+	if (aData.Length() > 4)
+		{
+		if (aData.Left(4) == KSequenceSignature)
+			{
+			return ETrue;
+			}
+		}
+	// Didn't recognise
+	return EFalse;
+	}
+
+TBool CToneHwDevice::ValidDTMFString(const TDesC& aDTMFString)
+	{
+	const TDesC* stringDTMF = &aDTMFString;;
+	TInt stringPos = 0;
+	if (stringPos == stringDTMF->Length())
+		{
+		return EFalse; // Finished. Nothing to do
+		}
+	do
+		{
+		TChar c((*stringDTMF)[stringPos++]);
+		if (static_cast<TUint> (c)=='#' || static_cast<TUint> (c)=='*' || static_cast<TUint> (c)==',' || c.IsHexDigit() || c.IsSpace())
+			{
+			//Do nothing, valid character
+			}
+		else
+			{
+			return EFalse;
+			}
+
+		}
+	while(stringPos < stringDTMF->Length());
+	return ETrue;
+	}
+
+
+/************************************************************************
+ *				TToneCustomInterface     								*
+ ************************************************************************/
+/**
+ * This method is not be exported as it is only 
+ * intended to be called within this DLL.
+ * It's purpose is to assign an RMdaDevSound to the play
+ * custom interface
+ * @internalComponent
+ */
+void TToneCustomInterface::SetDevice(RMdaDevSound* aDevice)
+	{
+	iDevice = aDevice;
+	}
+
+void TToneCustomInterface::SetVolume(TUint aVolume)
+	{
+	iVolume = aVolume;
+	if (iDevice && iDevice->Handle()!=0)
+		{
+		iDevice->SetPlayVolume(aVolume);
+		}
+	}
+	
+/**
+ * Procedure to get the number of bytes played by the device driver
+ * If there is no handle available to the device driver then the 
+ * procedure returns the last known value
+ * @released
+ * @return number of bytes played
+ */
+TUint TToneCustomInterface::BytesPlayed()
+	{
+	if(iDevice)
+		{
+		if (iDevice->Handle())
+			{
+			iBytesPlayed = iDevice->BytesPlayed();
+			}
+		}
+	return iBytesPlayed;
+	}
+
+
+//
+//       class CToneCodec            //
+//
+
+// ---------------------------------------------------------------------------
+// from class CToneCodec
+// CToneCodec::CToneCodec
+// ---------------------------------------------------------------------------
+//
+CToneCodec::CToneCodec()
+	{
+	}
+	
+// ---------------------------------------------------------------------------
+// from class CToneCodec
+// CToneCodec::~CToneCodec
+// ---------------------------------------------------------------------------
+//	
+CToneCodec::~CToneCodec()
+	{
+	}
+
+// ---------------------------------------------------------------------------
+// from class CToneCodec
+// CToneCodec::ConstructL
+// ---------------------------------------------------------------------------
+//	
+void CToneCodec::ConstructL()
+	{
+	}
+	
+
+// ---------------------------------------------------------------------------
+// from class CToneCodec
+// CToneCodec::ProcessL
+// ---------------------------------------------------------------------------
+//
+CToneCodec::TCodecProcessResult CToneCodec::ProcessL(const CMMFBuffer& /*aSource*/, CMMFBuffer& /*aDest*/)
+	{
+	//no processing required for null codec
+	User::Leave(KErrNotSupported); 
+	//to keep compiler happy
+	TCodecProcessResult result;
+	result.iCodecProcessStatus = TCodecProcessResult::EEndOfData;
+	result.iSrcBytesProcessed = 0;
+	result.iDstBytesAdded = 0;
+	return result;
+	}
+
+// ---------------------------------------------------------------------------
+// from class CToneCodec
+// CToneCodec::SourceBufferSize
+// ---------------------------------------------------------------------------
+//
+TUint CToneCodec::SourceBufferSize()
+	{
+	return KPCM16ToPCM16BufferSize;
+	}
+
+// ---------------------------------------------------------------------------
+// from class CToneCodec
+// CToneCodec::SinkBufferSize
+// ---------------------------------------------------------------------------
+//
+TUint CToneCodec::SinkBufferSize()
+	{
+	return KPCM16ToPCM16BufferSize;
+	}
+
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+/**
+* ImplementationGroupProxy
+* is called to get a pointer to the plugin's implementation table, or table
+* of functions used to instantiate the plugin.
+* @since
+* @param aTableCount returns the number of functions in the table.
+* @return retuns a pointer to the table.
+*/
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
+	{
+	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+	return ImplementationTable;
+	}