--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/devsound/sounddevbt/src/swcodecwrapper/mmfBtSwCodecWrapper.cpp Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,893 @@
+// Copyright (c) 2005-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 "mmfbtswcodecwrapper.h"
+#include "mmfBtSwCodecPlayDataPath.h"
+#include "mmfBtSwCodecRecordDataPath.h"
+#include "mmfBtSwCodecConvertDataPath.h"
+#include <mmfswcodecwrappercustominterfacesuids.hrh>
+#include "mmfBtswcodecwrapperCustomInterfaces.h"
+#include "MMFBtRoutingSoundDevice.h"
+#include <mmfpaniccodes.h>
+
+
+/*
+ * AO to handle RSD initialisation
+ *
+ */
+CRoutingSoundDeviceOpenHandler* CRoutingSoundDeviceOpenHandler::NewL(CMMFSwCodecWrapper* aObserver)
+ {
+ CRoutingSoundDeviceOpenHandler* self = new(ELeave) CRoutingSoundDeviceOpenHandler(aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CRoutingSoundDeviceOpenHandler::~CRoutingSoundDeviceOpenHandler()
+ {
+ Cancel();
+ }
+
+void CRoutingSoundDeviceOpenHandler::RunL()
+ {
+ TInt err = iStatus.Int();
+ if (iObserver)
+ {
+ iObserver->OpenComplete(err);
+ }
+ }
+
+void CRoutingSoundDeviceOpenHandler::DoCancel()
+ {
+ if (iObserver)
+ {
+ iObserver->OpenComplete(KErrCancel);
+ }
+ }
+
+CRoutingSoundDeviceOpenHandler::CRoutingSoundDeviceOpenHandler(CMMFSwCodecWrapper* aObserver) :
+ CActive(EPriorityStandard),
+ iObserver(aObserver)
+
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CRoutingSoundDeviceOpenHandler::ConstructL()
+ {
+ }
+
+void CRoutingSoundDeviceOpenHandler::Start()
+ {
+ if (!IsActive())
+ {
+ SetActive();
+ }
+ }
+
+
+/**
+ * Internal panic
+ * @internalComponent
+ */
+void Panic(TInt aPanicCode)
+ {
+ _LIT(KMMFSwCodecWrapperPanicCategory, "MMFSwCodecWrapper");
+ User::Panic(KMMFSwCodecWrapperPanicCategory, aPanicCode);
+ }
+
+
+/**
+ * This method is not be exported as it is only
+ * intended to be called within this DLL.
+ * It's purpose is to assign an CRoutingSoundPlayDevice to the play
+ * custom interface
+ * @internalComponent
+ */
+void TPlayCustomInterface::SetDevice(CRoutingSoundPlayDevice* aDevice)
+ {
+ iDevice = aDevice;
+ }
+
+void TPlayCustomInterface::SetVolume(TUint aVolume)
+ {
+ iVolume = aVolume;
+ if (iDevice && iDevice->Handle())
+ {
+ iDevice->SetVolume(iVolume);
+ }
+ }
+
+/**
+ * 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
+ * @prototype
+ * @return number of bytes played
+ */
+TUint TPlayCustomInterface::BytesPlayed()
+ {
+ if(iDevice)
+ {
+ if (iDevice->Handle())
+ {
+ iBytesPlayed = iDevice->BytesPlayed();
+ }
+ }
+ return iBytesPlayed;
+ }
+
+TTaskConfig TPlayCustomInterface::Caps()
+ {
+ TTaskConfig taskConfig;
+ taskConfig.iRate = 0;
+ taskConfig.iStereoMode = 0;
+ taskConfig.iUid = KUidRefDevSoundTaskConfig;
+
+ if (iDevice && iDevice->Handle())
+ {
+ RArray<TUint> supportedSampleRates;
+ RArray<TRange>supportedRateRanges;
+ iDevice->GetSupportedSampleRates(supportedSampleRates,supportedRateRanges);
+ for (TUint i=0; i<supportedSampleRates.Count(); i++)
+ {
+ switch(supportedSampleRates[i])
+ {
+ case 8000:
+ taskConfig.iRate |= ETask8000Hz;
+ break;
+ case 11025:
+ taskConfig.iRate |= ETask11025Hz;
+ break;
+ case 12000:
+ taskConfig.iRate |= ETask12000Hz;
+ break;
+ case 16000:
+ taskConfig.iRate |= ETask16000Hz;
+ break;
+ case 22050:
+ taskConfig.iRate |= ETask22050Hz;
+ break;
+ case 24000:
+ taskConfig.iRate |= ETask24000Hz;
+ break;
+ case 32000:
+ taskConfig.iRate |= ETask32000Hz;
+ break;
+ case 44100:
+ taskConfig.iRate |= ETask44100Hz;
+ break;
+ case 48000:
+ taskConfig.iRate |= ETask48000Hz;
+ break;
+ case 88200:
+ taskConfig.iRate |= ETask88200Hz;
+ break;
+ case 96000:
+ taskConfig.iRate |= ETask96000Hz;
+ break;
+ default: //do nothing
+ break;
+ }// switch(supportedSampleRates[i])
+ supportedSampleRates.Close();
+ supportedRateRanges.Close();
+ }//for (TUint i=0; i<supportedSampleRates.Count(); i++)
+ RArray<TUint> supportedChannels;
+ TMMFStereoSupport stereoSupport;
+ iDevice->GetSupportedChannels(supportedChannels,stereoSupport);
+ for (TUint i=0; i<supportedChannels.Count(); i++)
+ {//note we don't have a TaskConfig enum for Joint stereo
+ switch(supportedChannels[i])
+ {
+ case EMMFMono:
+ taskConfig.iStereoMode |= ETaskMono;
+ break;
+ case EMMFStereo:
+ if (stereoSupport == EMMFInterleavedOnly)
+ {
+ taskConfig.iStereoMode |= ETaskInterleaved;
+ }
+ else if (stereoSupport == EMMFNonInterleavedOnly)
+ {
+ taskConfig.iStereoMode |= ETaskNonInterleaved;
+ }
+ else if (stereoSupport == EMMFBothNonAndInterleaved)
+ {
+ taskConfig.iStereoMode |= (ETaskInterleaved|ETaskNonInterleaved);
+ }
+ break;
+ default://do nothing
+ break;
+ }//switch(supportedChannels[i])
+ supportedChannels.Close();
+ }// for (TUint i=0; i<supportedChannels.Count(); i++)
+ }//if (iDevice && iDevice->Handle())
+ return taskConfig;
+ }
+
+/**
+ * Procedure to get the number of bytes recorded by the device
+ * @prototype
+ * @return number of bytes recorded
+ */
+TUint TRecordCustomInterface::BytesRecorded()
+ {
+ if(iDataPath)
+ {
+ iBytesRecorded = iDataPath->RecordedBytesCount();
+ }
+ return iBytesRecorded;
+ }
+
+/**
+Constructor.
+*/
+EXPORT_C CMMFSwCodecWrapper::CMMFSwCodecWrapper()
+ {
+ }
+
+/**
+Destructor.
+
+The destructor is called by ECom framework allowing derived classes
+to clean up implementation specific resources. The sound
+device drivers are freed.
+*/
+EXPORT_C CMMFSwCodecWrapper::~CMMFSwCodecWrapper()
+ {
+ // AO to handle OpenDevice call
+ if (iOpenHandler && iOpenHandler->IsActive())
+ {
+ iOpenHandler->Cancel();
+ }
+ delete iOpenHandler;
+ delete iRecordDevice;
+ delete iPlayDevice;
+ delete iDataPath;
+ delete iCodec;
+ delete iPlayCustomInterface;
+ delete iRecordCustomInterface;
+ }
+
+/**
+Initializes the hardware device tasks - in the case of a
+sw codec wrapper 'hardware device' this consists of loading the
+sound device drivers and creating the CMMFSwCodec.
+
+@param aDevInfo
+ Device initialization parameters.
+ Only the iHwDeviceObserver is used for CMFSwCodecWrapper
+ derived CMMFHwDevices.
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+ another of the system-wide error codes.
+*/
+EXPORT_C TInt CMMFSwCodecWrapper::Init(THwDeviceInitParams& aDevInfo)
+ {
+ TRequestStatus status;
+ Init(aDevInfo,status);
+ User::WaitForRequest(status);
+ return status.Int();
+ }
+
+
+/**
+Initializes the hardware device tasks - in the case of a
+sw codec wrapper 'hardware device' this consists of loading the
+sound device drivers and creating the CMMFSwCodec.
+
+@param aDevInfo
+ Device initialization parameters.
+ Only the iHwDeviceObserver is used for CMFSwCodecWrapper
+ derived CMMFHwDevices.
+@param aStatus
+ Status flag belonging to an Active Object that will have its
+ RunL() called when this function completes
+*/
+EXPORT_C void CMMFSwCodecWrapper::Init( THwDeviceInitParams &aDevInfo,
+ TRequestStatus& aStatus)
+ {
+ aStatus = KRequestPending;
+ TRequestStatus* status = &aStatus;
+ if (!aDevInfo.iHwDeviceObserver)
+ {
+ User::RequestComplete(status, KErrArgument);
+ return;
+ }
+ iHwDeviceObserver = aDevInfo.iHwDeviceObserver;
+
+ TInt err = KErrNone;
+ if (aDevInfo.iOutStream.iConnection.iId)
+ {
+ iDeviceUid = TUid::Uid(aDevInfo.iOutStream.iConnection.iId);
+ // Play device
+ delete iPlayDevice;
+ iPlayDevice = NULL;
+ TRAP(err, iPlayDevice = CRoutingSoundPlayDevice::NewL());
+ if (err == KErrNone)
+ {
+ iPlayDevice->Initialize(iDeviceUid,
+ aDevInfo.iOutStream.iDeviceName, *status);
+ if (!iPlayCustomInterface)
+ {
+ TRAP(err,iPlayCustomInterface = new(ELeave)TPlayCustomInterface());
+ if (err)
+ {
+ delete iPlayDevice;
+ iPlayDevice = NULL;
+ User::RequestComplete(status, err);
+ return;
+ }
+ }
+ static_cast<TPlayCustomInterface*>(iPlayCustomInterface)->SetDevice(iPlayDevice);
+ }
+ }
+ if (aDevInfo.iInStream.iConnection.iId)
+ {
+ iDeviceUid = TUid::Uid(aDevInfo.iInStream.iConnection.iId);
+ // Record device
+ TRAP(err, iRecordDevice = CRoutingSoundRecordDevice::NewL());
+ if (err == KErrNone)
+ {
+ iRecordDevice->Initialize(iDeviceUid, KNullDesC8, *status);
+ if (!iRecordCustomInterface)
+ {
+ TRAP(err,iRecordCustomInterface = new(ELeave)TRecordCustomInterface());
+ if (err)
+ {
+ delete iRecordDevice;
+ iRecordDevice = NULL;
+ User::RequestComplete(status, err);
+ return;
+ }
+ }
+ }
+ }
+
+ iCodec = &(Codec()); //create codec
+
+ //[ assert the post condition ]
+ if (!iCodec)
+ {
+ err = KErrNotSupported;
+ }
+
+ if (err != KErrNone)
+ {
+ User::RequestComplete(status, err);
+ // Cancel initialisation too
+ if (aDevInfo.iOutStream.iConnection.iId)
+ {
+ iPlayDevice->CancelInitialize(iDeviceUid);
+ }
+ if (aDevInfo.iInStream.iConnection.iId)
+ {
+ iRecordDevice->CancelInitialize(iDeviceUid);
+ }
+ }
+ else if ((!aDevInfo.iOutStream.iConnection.iId)&& (!aDevInfo.iInStream.iConnection.iId))
+ {
+ //could be used for conversion so complete the request status
+ User::RequestComplete(status, KErrNone);
+ }
+
+ }
+
+/**
+Starts Encoding or Decoding task(s) based on the parameter specified.
+
+@param aFuncCmd
+ The device function specifying the requested service i.e. decode or encode
+ where EDevEncode = Record, EDevDecode = Play and EDevNullFunc = Convert.
+@param aFlowCmd
+ The device flow directions for requested service.
+ This parameter is ignored for CMMFSwCodecWrapper CMMFHwDevicePlugins
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+ another of the system-wide error codes.
+*/
+EXPORT_C TInt CMMFSwCodecWrapper::Start(TDeviceFunc aFuncCmd, TDeviceFlow /*aFlowCmd*/)
+ {
+ TInt error = KErrNone;
+
+ // [ precondition that aFuncCmd is valid]
+ if (!((aFuncCmd == EDevEncode)|(aFuncCmd == EDevDecode)|(aFuncCmd == EDevNullFunc)))
+ {
+ return KErrArgument;
+ }
+
+ // [ precondition that iCodec is present]
+ if (!iCodec)
+ {
+ return KErrNotReady; //make sure the codec has been added
+ }
+
+ switch (aFuncCmd)
+ {
+ case EDevEncode: // Audio record
+ {
+ error = StartEncode();
+ }
+ break;
+ case EDevDecode: // Audio play
+ {
+ error = StartDecode();
+ }
+ break;
+ case EDevNullFunc: //Audio Convert
+ {
+ error = StartConvert();
+ }
+ break;
+ default:
+ error = KErrNotSupported;
+ break;
+ }
+
+ //[ assert the post conditions ]
+#ifdef DEBUG
+ if (!error)
+ {//only assert if no error otherwise post consitions not valid
+ __ASSERT_DEBUG(iDataPath, Panic(EMMFSwCodecWrapperNoDataPath));
+ if ((aFuncCmd == EDevEncode)||(aFuncCmd == EDevDecode))
+ {
+ __ASSERT_DEBUG(iDataPath->Device().Handle(), Panic(EMMFSwCodecWrapperNoDevice));
+ }
+ }
+#endif
+
+ return error;
+ }
+
+// Use AO to OpenDevice
+TInt CMMFSwCodecWrapper::StartDecode()
+ {
+ TInt error = KErrNone;
+
+ //[ assert precondition that play custom interface is present]
+ //if there is no play custom interface then the user of the CMMFSwCodecWrapper
+ //cannot have set any of the custom settings such as sample rate.
+ if (!iPlayCustomInterface)
+ {
+ return KErrNotReady;
+ }
+
+ //play
+ if (!iDataPath)
+ {//create a datapath
+ TRAP(error,iDataPath = CMMFSwCodecPlayDataPath::NewL(iPlayDevice, iDeviceUid));
+ if ((iDataPath) && (error == KErrNone))
+ {
+ iDataPath->SetObserver(*iHwDeviceObserver);
+ error = iDataPath->AddCodec(*iCodec);
+ iDeviceBufferSize = iCodec->SinkBufferSize();
+ static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->SetPlayCustomInterface(*iPlayCustomInterface);
+ static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->SetConfigForAudioRamp(iSampleRate, iChannels);
+ }
+ }
+
+ if ((error == KErrNone) &&
+ (iDataPath->State() != CMMFSwCodecDataPath::EPlaying))
+ {
+ TBool asynchOpen = EFalse; // Ensure we only call OpenPlayComplete once
+ //datapath was created ok and we are not playing
+ if (iDataPath->State() == CMMFSwCodecDataPath::EStopped)
+ {
+ //starting from 'fresh so set sound device settings
+
+ // Create the AO OpenDevice handler
+ if (!iOpenHandler)
+ {
+ TRAP(error, iOpenHandler = CRoutingSoundDeviceOpenHandler::NewL(this));
+ }
+ if (!error)
+ {
+ asynchOpen = ETrue;
+ iPlayDevice->SetBufferSize(iDeviceBufferSize);
+ iOpenHandler->Start();
+ static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->Device()->
+ OpenDevice(iDeviceUid, iOpenHandler->iStatus);
+ }
+ }
+ if (!asynchOpen)
+ {
+ error = OpenPlayComplete(error);
+ }
+
+ }//status == KErrNone
+
+ return error;
+ }
+
+TInt CMMFSwCodecWrapper::StartEncode()
+ {//record
+
+ //[ assert precondition that record custom interface is present]
+ //if there is no record custom interface then the user of the CMMFSwCodecWrapper
+ //cannot have set any of the custom settings such as sample rate.
+ if (!iRecordCustomInterface)
+ {
+ return KErrNotReady;
+ }
+
+ TInt error = KErrNone;
+ if (!iDataPath)
+ {
+ TRAP(error,iDataPath = CMMFSwCodecRecordDataPath::NewL(iRecordDevice));
+ if ((iDataPath)&&(error == KErrNone))
+ {
+ iDataPath->SetObserver(*iHwDeviceObserver);
+ error = iDataPath->AddCodec(*iCodec);
+ iDeviceBufferSize = (iCodec->SourceBufferSize());
+ static_cast<TRecordCustomInterface*>(iRecordCustomInterface)->SetDataPath(static_cast<CMMFSwCodecRecordDataPath*>(iDataPath));
+ }
+ }
+ if ((error == KErrNone)&&
+ (iDataPath->State() != CMMFSwCodecDataPath::EPlaying))
+ {
+ TBool asynchOpen = EFalse; // Ensure we only call OpenPlayComplete once
+ if (!(static_cast<CMMFSwCodecRecordDataPath*>(iDataPath))->Device()->Handle())
+ {
+ // Create the AO OpenDevice handler
+ if (!iOpenHandler)
+ {
+ TRAP(error, iOpenHandler = CRoutingSoundDeviceOpenHandler::NewL(this));
+ }
+ if (!error)
+ {
+ asynchOpen = ETrue;
+ iRecordDevice->SetBufferSize(iDeviceBufferSize);
+ iOpenHandler->Start();
+ static_cast<CMMFSwCodecRecordDataPath*>(iDataPath)->Device()->
+ OpenDevice(iDeviceUid, iOpenHandler->iStatus);
+ }
+ }
+
+ if (!asynchOpen)
+ {
+ error = OpenRecordComplete(error);
+ }
+ }
+
+ return error;
+ }
+
+TInt CMMFSwCodecWrapper::StartConvert()
+ {//convert
+
+ TInt error = KErrNone;
+ if (!iDataPath)
+ {
+ TRAP(error,iDataPath = CMMFSwCodecConvertDataPath::NewL());
+ if ((iDataPath)&&(error == KErrNone))
+ {
+ iDataPath->SetObserver(*iHwDeviceObserver);
+ error = iDataPath->AddCodec(*iCodec);
+ }
+ }
+ if (error == KErrNone)
+ {
+ error = iDataPath->Start();
+ }
+ return error;
+ }
+
+/**
+Temporarily suspends the current task of decoding or encoding.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+ another of the system-wide error codes.
+*/
+EXPORT_C TInt CMMFSwCodecWrapper::Pause()
+ {
+ // [ precondition that datapath exists ]
+ if (!iDataPath)
+ {
+ return KErrNotReady;
+ }
+
+ iDataPath->Pause();
+ return KErrNone;
+ }
+
+/**
+Stops the current on-going task.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+ another of the system-wide error codes.
+*/
+EXPORT_C TInt CMMFSwCodecWrapper::Stop()
+ {
+ // [ precondition that datapath exists ]
+ if (!iDataPath)
+ {
+ return KErrNotReady;
+ }
+ iDataPath->Stop();
+ return KErrNone;
+ }
+
+
+/**
+Stops and deletes the codec.
+
+This default implementation simply calls DeleteCodec() and then Stop()
+but real hardware devices might use this method to free up resources.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+ another of the system-wide error codes.
+*/
+EXPORT_C TInt CMMFSwCodecWrapper::StopAndDeleteCodec()
+ {
+ TInt stopError = Stop();
+ TInt deleteError = DeleteCodec();
+
+ if (stopError != KErrNone)
+ {
+ return stopError;
+ }
+ else
+ {
+ return deleteError;
+ }
+ }
+
+/**
+Deletes the codec
+This default implementation does nothing
+but real hardware devices might use this method to free up resources.
+@return Error code. KErrNone if successful
+*/
+EXPORT_C TInt CMMFSwCodecWrapper::DeleteCodec()
+ {
+ return KErrNone;
+ }
+
+/**
+Call this function to notify hardware device implementation that
+data is available in aFillBufferPtr for decoding.
+
+@param aFillBufferPtr
+ The data buffer filled by the observer.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+ another of the system-wide error codes.
+*/
+EXPORT_C TInt CMMFSwCodecWrapper::ThisHwBufferFilled(CMMFBuffer& aFillBufferPtr)
+ {
+ TRAPD(err,iDataPath->BufferFilledL(STATIC_CAST(CMMFDataBuffer&, aFillBufferPtr)));
+ return err;
+ }
+
+/**
+Call this function to notify hardware device implementation that
+data in aEmptyBufferPtr from encoding is processed.
+
+@param aBuffer
+ The data buffer processed by observer.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+ another of the system-wide error codes.
+*/
+EXPORT_C TInt CMMFSwCodecWrapper::ThisHwBufferEmptied(CMMFBuffer& aBuffer)
+ {
+ TRAPD(err,iDataPath->BufferEmptiedL(STATIC_CAST(CMMFDataBuffer&, aBuffer)));
+ return err;
+ }
+
+
+/**
+Retrieves a custom interface to the device.
+The reference CMMFSwCodecWrapper supports two standard custom interfaces,
+TPlayCustomInterface and TRecordCustomInterface.
+
+@param aInterface
+ Interface UID, defined with the custom interface.
+ aInterface = KMmfPlayCustomInterface for TPlayCustomInterface,
+ aInterface = KMmfRecordCustomInterface for TRecordCustomInterface.
+ Actual device implementations of CMMFSwCodecWrapper may do this differently however.
+@return A pointer to the interface implementation, or NULL if the device can not
+ implement the interface requested. The return value must be cast to the
+ correct type by the user.
+*/
+EXPORT_C TAny* CMMFSwCodecWrapper::CustomInterface(TUid aInterface)
+ {
+ TAny* ret = NULL;
+ TInt err = KErrNone;
+ if (aInterface.iUid == KMmfPlaySettingsCustomInterface)
+ {
+ if (!iPlayCustomInterface)
+ {
+ TRAP(err,iPlayCustomInterface = new(ELeave)TPlayCustomInterface());
+ }
+ if (err)
+ {
+ ret = NULL;
+ }
+ else
+ {
+ ret = static_cast<TAny*>(iPlayCustomInterface);
+ }
+ }
+ else if (aInterface.iUid == KMmfRecordSettingsCustomInterface)
+ {
+ if (!iRecordCustomInterface)
+ {
+ TRAP(err,iRecordCustomInterface = new(ELeave)TRecordCustomInterface());
+ }
+ if (err)
+ {
+ ret = NULL;
+ }
+ else
+ {
+ ret = static_cast<TAny*>(iRecordCustomInterface);
+ }
+ }
+
+ return ret;
+ }
+
+
+/**
+Used to configure the sample rate and stereo mode of a CMMFHwDevice plugin.
+
+The configuration of HwDevices is device specific and is not used in any of the reference
+devices that return KErrNotSupported.
+
+@param aConfig
+ The device configuration.
+*/
+EXPORT_C TInt CMMFSwCodecWrapper::SetConfig(TTaskConfig& aConfig)
+ {
+ TInt err = KErrNone;
+ if (aConfig.iUid != KUidRefDevSoundTaskConfig)
+ return KErrArgument;
+ iSampleRate = aConfig.iRate;//note we're cheating a bit
+ //iRate is actually a bit map enum but an actual value
+ //is more useful here
+ TMMFStereoSupport stereoSupport = EMMFNone;
+ if (aConfig.iStereoMode == ETaskMono)
+ {
+ iChannels = 1;
+ }
+ else if (aConfig.iStereoMode == ETaskInterleaved)
+ {
+ iChannels = 2;
+ stereoSupport = EMMFInterleavedOnly;
+ }
+ else //don't support non interleaved
+ {
+ return KErrNotSupported;
+ }
+
+ //set values on routing sound device
+ if (iPlayDevice)
+ {
+ err = iPlayDevice->SetChannels(iChannels, stereoSupport);
+ if (!err)
+ {
+ err = iPlayDevice->SetSampleRate(iSampleRate);
+ }
+ if (!err)
+ {//we'll set the data type while were at it for now pcm16 only
+ TFourCC fourCC = KMMFFourCCCodePCM16;
+ err = iPlayDevice->SetDataType(fourCC);
+ }
+ }
+ if ((iRecordDevice) && (!err))
+ {
+ err = iRecordDevice->SetChannels(iChannels, stereoSupport);
+ if (!err)
+ {
+ err = iRecordDevice->SetSampleRate(iSampleRate);
+ }
+ }
+
+ return err;
+ }
+
+/**
+Callback once CRoutingSoundPlayDevice or CRoutingSoundRecordDevice::Open has completed or continuation from
+call to StartDecode / StartEncode, depending on the state.
+
+@internalTechnology
+@param aError
+ The status of the device.
+@return A standard Symbian wide error code.
+ */
+TInt CMMFSwCodecWrapper::OpenComplete(TInt aError)
+ {
+ TInt err = KErrNotSupported; //
+ if (iPlayDevice)
+ {
+ err = OpenPlayComplete(aError);
+ }
+ else if (iRecordDevice)
+ {
+ err = OpenRecordComplete(aError);
+ }
+ return err;
+ }
+
+/**
+Callback once CRoutingSoundPlayDevice::Open has completed or continuation from
+call to StartDecode, depending on the state.
+
+@param aError
+ The status of the device.
+@return A standard Symbian wide error code.
+ */
+TInt CMMFSwCodecWrapper::OpenPlayComplete(TInt aError)
+ {
+ TInt error = aError;
+
+ //datapath was created ok and we are not playing
+ if (error == KErrNone && iDataPath->State() == CMMFSwCodecDataPath::EStopped)
+ {
+ //starting from fresh so set sound device settings
+// static_cast<TPlayCustomInterface*>(iPlayCustomInterface)->SetDevice(
+// static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->Device() );
+ static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->Device()->SetVolume(iPlayCustomInterface->Volume());
+ }
+
+ // resuming from pause or ready to play
+ if ((error == KErrNone) || (error == KErrInUse))
+ {
+ error = iDataPath->Start();
+ }
+
+ return error;
+ }
+
+/**
+Callback once CRoutingSoundRecordDevice::Open has completed or continuation from
+call to StartDecode, depending on the state.
+
+@param aError
+ The status of the device.
+@return A standard Symbian wide error code.
+ */
+TInt CMMFSwCodecWrapper::OpenRecordComplete(TInt aError)
+ {
+ TInt error = aError;
+
+ //datapath was created ok and we are not playing
+ if (error == KErrNone && iDataPath->State() == CMMFSwCodecDataPath::EStopped)
+ {
+ //set sound driver settings
+ static_cast<CMMFSwCodecRecordDataPath*>(iDataPath)->Device()
+ ->SetGain(iRecordCustomInterface->Gain());
+ /*
+ // Sample rate
+ (static_cast<CMMFSwCodecRecordDataPath*>(iDataPath))->Device()->SetSampleRate(iSampleRate);
+ // Channels
+ TMMFStereoSupport stereoSupport = EMMFNone; // assume mono
+ if (iChannels == 2)
+ {
+ // Assume interleaved only
+ stereoSupport = EMMFInterleavedOnly;
+ }
+ error = (static_cast<CMMFSwCodecRecordDataPath*>(iDataPath))->Device()->SetChannels(iChannels, stereoSupport);
+ */
+ }
+
+ // resuming from pause or ready to play
+ if ((error == KErrNone) || (error == KErrInUse))
+ {
+ error = iDataPath->Start();
+ }
+
+ return error;
+ }