devsound/sounddevbt/src/swcodecwrapper/mmfBtSwCodecWrapper.cpp
changeset 0 40261b775718
--- /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;
+	}