--- /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;
+ }