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