diff -r 000000000000 -r 40261b775718 mmhais/refacladapt/src/tonehwdevice/tonehwdevice.cpp --- /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 +#include "tonehwdevice.hrh" //for KUidToneHwDevice +#include // 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(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(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 (&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 (*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 (*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(iPlayCustomInterface); + } + } + else if (aInterfaceUid == KIgnoreUnderflowCustomInterfaceTypeUid) + { + if (!iDataPath) + { + ret = NULL; + } + else + { + ret = static_cast(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(*iDTMFString))) + { + DP0(DLINFO, "Invalid DTMF String"); + iHwDeviceObserver->Error(KErrCorrupt); + DP0_RET(KErrCorrupt, "%d"); + } + iDTMFGen.SetString(const_cast(*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 (c)=='#' || static_cast (c)=='*' || static_cast (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; + }