os/mm/devsound/sounddevbt/src/swcodecwrapper/mmfBtSwCodecWrapper.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/mm/devsound/sounddevbt/src/swcodecwrapper/mmfBtSwCodecWrapper.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,893 @@
     1.4 +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "mmfbtswcodecwrapper.h"
    1.20 +#include "mmfBtSwCodecPlayDataPath.h"
    1.21 +#include "mmfBtSwCodecRecordDataPath.h"
    1.22 +#include "mmfBtSwCodecConvertDataPath.h"
    1.23 +#include <mmfswcodecwrappercustominterfacesuids.hrh>
    1.24 +#include "mmfBtswcodecwrapperCustomInterfaces.h"
    1.25 +#include "MMFBtRoutingSoundDevice.h"
    1.26 +#include <mmfpaniccodes.h>
    1.27 +
    1.28 +
    1.29 +/*
    1.30 + *	AO to handle RSD initialisation
    1.31 + *
    1.32 + */
    1.33 +CRoutingSoundDeviceOpenHandler* CRoutingSoundDeviceOpenHandler::NewL(CMMFSwCodecWrapper* aObserver)
    1.34 +	{
    1.35 +	CRoutingSoundDeviceOpenHandler* self = new(ELeave) CRoutingSoundDeviceOpenHandler(aObserver);
    1.36 +	CleanupStack::PushL(self);
    1.37 +	self->ConstructL();
    1.38 +	CleanupStack::Pop(self);
    1.39 +	return self;
    1.40 +	}
    1.41 +	
    1.42 +CRoutingSoundDeviceOpenHandler::~CRoutingSoundDeviceOpenHandler()
    1.43 +	{
    1.44 +	Cancel();
    1.45 +	}
    1.46 +		
    1.47 +void CRoutingSoundDeviceOpenHandler::RunL()
    1.48 +	{
    1.49 +	TInt err = iStatus.Int();
    1.50 +	if (iObserver)
    1.51 +		{
    1.52 +		iObserver->OpenComplete(err);
    1.53 +		}
    1.54 +	}
    1.55 +	
    1.56 +void CRoutingSoundDeviceOpenHandler::DoCancel()
    1.57 +	{
    1.58 +	if (iObserver)
    1.59 +		{
    1.60 +		iObserver->OpenComplete(KErrCancel);
    1.61 +		}
    1.62 +	}
    1.63 +	
    1.64 +CRoutingSoundDeviceOpenHandler::CRoutingSoundDeviceOpenHandler(CMMFSwCodecWrapper* aObserver) :
    1.65 +															 	CActive(EPriorityStandard),
    1.66 +															 	iObserver(aObserver)								 	
    1.67 +														
    1.68 +	{
    1.69 +	CActiveScheduler::Add(this);	
    1.70 +	}
    1.71 +	
    1.72 +void CRoutingSoundDeviceOpenHandler::ConstructL()
    1.73 +	{
    1.74 +	}
    1.75 +
    1.76 +void CRoutingSoundDeviceOpenHandler::Start()
    1.77 +	{
    1.78 +	if (!IsActive())
    1.79 +		{
    1.80 +		SetActive();
    1.81 +		}
    1.82 +	}
    1.83 + 
    1.84 +
    1.85 +/**
    1.86 + * Internal panic
    1.87 + * @internalComponent
    1.88 + */
    1.89 +void Panic(TInt aPanicCode)
    1.90 +	{
    1.91 +	_LIT(KMMFSwCodecWrapperPanicCategory, "MMFSwCodecWrapper");
    1.92 +	User::Panic(KMMFSwCodecWrapperPanicCategory, aPanicCode);
    1.93 +	}
    1.94 +
    1.95 +
    1.96 +/**
    1.97 + * This method is not be exported as it is only 
    1.98 + * intended to be called within this DLL.
    1.99 + * It's purpose is to assign an CRoutingSoundPlayDevice to the play
   1.100 + * custom interface
   1.101 + * @internalComponent
   1.102 + */
   1.103 +void TPlayCustomInterface::SetDevice(CRoutingSoundPlayDevice* aDevice)
   1.104 +	{
   1.105 +	iDevice = aDevice;
   1.106 +	}
   1.107 +
   1.108 +void TPlayCustomInterface::SetVolume(TUint aVolume)
   1.109 +	{
   1.110 +	iVolume = aVolume;
   1.111 +	if (iDevice && iDevice->Handle())
   1.112 +		{
   1.113 +		iDevice->SetVolume(iVolume);
   1.114 +		}
   1.115 +	}
   1.116 +
   1.117 +/**
   1.118 + * Procedure to get the number of bytes played by the device driver
   1.119 + * If there is no handle available to the device driver then the 
   1.120 + * procedure returns the last known value
   1.121 + * @prototype
   1.122 + * @return number of bytes played
   1.123 + */
   1.124 +TUint TPlayCustomInterface::BytesPlayed()
   1.125 +	{
   1.126 +	if(iDevice)
   1.127 +		{
   1.128 +		if (iDevice->Handle())
   1.129 +			{
   1.130 +			iBytesPlayed = iDevice->BytesPlayed();
   1.131 +			}
   1.132 +		}
   1.133 +	return iBytesPlayed;
   1.134 +	}
   1.135 +	
   1.136 +TTaskConfig TPlayCustomInterface::Caps()
   1.137 +	{
   1.138 +	TTaskConfig taskConfig;
   1.139 +	taskConfig.iRate = 0;
   1.140 +	taskConfig.iStereoMode = 0;
   1.141 +	taskConfig.iUid = KUidRefDevSoundTaskConfig;
   1.142 +	
   1.143 +	if (iDevice && iDevice->Handle())
   1.144 +		{
   1.145 +		RArray<TUint> supportedSampleRates;
   1.146 +		RArray<TRange>supportedRateRanges;
   1.147 +		iDevice->GetSupportedSampleRates(supportedSampleRates,supportedRateRanges);	
   1.148 +		for (TUint i=0; i<supportedSampleRates.Count(); i++)
   1.149 +			{
   1.150 +			switch(supportedSampleRates[i])
   1.151 +				{
   1.152 +				case 8000:
   1.153 +					taskConfig.iRate |= ETask8000Hz;
   1.154 +					break;
   1.155 +				case 11025:
   1.156 +					taskConfig.iRate |= ETask11025Hz;
   1.157 +  					break;
   1.158 +				case 12000:
   1.159 +					taskConfig.iRate |= ETask12000Hz;
   1.160 +					break;
   1.161 +				case 16000:
   1.162 +					taskConfig.iRate |= ETask16000Hz;
   1.163 +					break;
   1.164 +				case 22050:
   1.165 +  					taskConfig.iRate |= ETask22050Hz;
   1.166 +  					break;
   1.167 +				case 24000:
   1.168 +  					taskConfig.iRate |= ETask24000Hz;
   1.169 +  					break;
   1.170 +				case 32000:
   1.171 +  					taskConfig.iRate |= ETask32000Hz;
   1.172 +  					break;
   1.173 +				case 44100:
   1.174 +					taskConfig.iRate |= ETask44100Hz;
   1.175 +  					break;
   1.176 +				case 48000:
   1.177 +					taskConfig.iRate |= ETask48000Hz;
   1.178 +					break;
   1.179 +				case 88200:
   1.180 +					taskConfig.iRate |= ETask88200Hz;
   1.181 +					break;
   1.182 +				case 96000:
   1.183 +					taskConfig.iRate |= ETask96000Hz;
   1.184 +					break;
   1.185 +				default: //do nothing
   1.186 +					break;	
   1.187 +				}//	switch(supportedSampleRates[i])
   1.188 +			supportedSampleRates.Close();
   1.189 +			supportedRateRanges.Close();
   1.190 +			}//for (TUint i=0; i<supportedSampleRates.Count(); i++)
   1.191 +		RArray<TUint> supportedChannels;
   1.192 +		TMMFStereoSupport stereoSupport;
   1.193 +		iDevice->GetSupportedChannels(supportedChannels,stereoSupport);	
   1.194 +		for (TUint i=0; i<supportedChannels.Count(); i++)
   1.195 +			{//note we don't have a TaskConfig enum for Joint stereo
   1.196 +			switch(supportedChannels[i])
   1.197 +				{
   1.198 +				case EMMFMono:
   1.199 +					taskConfig.iStereoMode |= ETaskMono;
   1.200 +					break;
   1.201 +				case EMMFStereo:
   1.202 +					if (stereoSupport == EMMFInterleavedOnly)
   1.203 +						{
   1.204 +						taskConfig.iStereoMode |= ETaskInterleaved;
   1.205 +						}
   1.206 +					else if (stereoSupport == EMMFNonInterleavedOnly)
   1.207 +						{
   1.208 +						taskConfig.iStereoMode |= ETaskNonInterleaved;
   1.209 +						}
   1.210 +					else if (stereoSupport == EMMFBothNonAndInterleaved)
   1.211 +						{
   1.212 +						taskConfig.iStereoMode |= (ETaskInterleaved|ETaskNonInterleaved);
   1.213 +						}
   1.214 +					break;
   1.215 +				default://do nothing
   1.216 +					break;
   1.217 +				}//switch(supportedChannels[i])
   1.218 +			supportedChannels.Close();
   1.219 +			}//	for (TUint i=0; i<supportedChannels.Count(); i++)
   1.220 +		}//if (iDevice && iDevice->Handle())
   1.221 +	return taskConfig;
   1.222 +	}
   1.223 +
   1.224 +/**
   1.225 + * Procedure to get the number of bytes recorded by the device  
   1.226 + * @prototype
   1.227 + * @return number of bytes recorded
   1.228 + */
   1.229 +TUint TRecordCustomInterface::BytesRecorded()
   1.230 +	{
   1.231 +	if(iDataPath)
   1.232 +		{
   1.233 +		iBytesRecorded = iDataPath->RecordedBytesCount();
   1.234 +		}
   1.235 +	return iBytesRecorded;
   1.236 +	}
   1.237 +
   1.238 +/**
   1.239 +Constructor.
   1.240 +*/
   1.241 +EXPORT_C CMMFSwCodecWrapper::CMMFSwCodecWrapper()
   1.242 +	{
   1.243 +	}
   1.244 +
   1.245 +/**
   1.246 +Destructor.
   1.247 +
   1.248 +The destructor is called by ECom framework allowing derived classes
   1.249 +to clean up implementation specific resources. The sound
   1.250 +device drivers are freed.
   1.251 +*/
   1.252 +EXPORT_C CMMFSwCodecWrapper::~CMMFSwCodecWrapper()
   1.253 +	{
   1.254 +	// AO to handle OpenDevice call
   1.255 +	if (iOpenHandler && iOpenHandler->IsActive())
   1.256 +		{
   1.257 +		iOpenHandler->Cancel();	
   1.258 +		}
   1.259 +	delete iOpenHandler;
   1.260 +	delete iRecordDevice;
   1.261 +	delete iPlayDevice;
   1.262 +	delete iDataPath;
   1.263 +	delete iCodec;
   1.264 +	delete iPlayCustomInterface;
   1.265 +	delete iRecordCustomInterface;
   1.266 +	}
   1.267 +	
   1.268 +/**
   1.269 +Initializes the hardware device tasks - in the case of a
   1.270 +sw codec wrapper 'hardware device' this consists of loading the
   1.271 +sound device drivers and creating the CMMFSwCodec.
   1.272 +
   1.273 +@param  aDevInfo
   1.274 +        Device initialization parameters.
   1.275 +        Only the iHwDeviceObserver is used for CMFSwCodecWrapper
   1.276 +        derived CMMFHwDevices.
   1.277 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
   1.278 +        another of the system-wide error codes.
   1.279 +*/
   1.280 +EXPORT_C TInt CMMFSwCodecWrapper::Init(THwDeviceInitParams& aDevInfo)
   1.281 +	{
   1.282 +	TRequestStatus status;
   1.283 +	Init(aDevInfo,status);
   1.284 +	User::WaitForRequest(status);
   1.285 +	return status.Int();
   1.286 +	}
   1.287 +
   1.288 +
   1.289 +/**
   1.290 +Initializes the hardware device tasks - in the case of a
   1.291 +sw codec wrapper 'hardware device' this consists of loading the
   1.292 +sound device drivers and creating the CMMFSwCodec.
   1.293 +
   1.294 +@param  aDevInfo
   1.295 +        Device initialization parameters.
   1.296 +        Only the iHwDeviceObserver is used for CMFSwCodecWrapper
   1.297 +        derived CMMFHwDevices.
   1.298 +@param	aStatus
   1.299 +		Status flag belonging to an Active Object that will have its
   1.300 +		RunL() called when this function completes
   1.301 +*/
   1.302 +EXPORT_C void CMMFSwCodecWrapper::Init(	THwDeviceInitParams &aDevInfo,
   1.303 +										TRequestStatus& aStatus)
   1.304 +	{
   1.305 +	aStatus = KRequestPending;
   1.306 +	TRequestStatus* status = &aStatus;
   1.307 +	if (!aDevInfo.iHwDeviceObserver)
   1.308 +		{
   1.309 +		User::RequestComplete(status, KErrArgument);
   1.310 +		return;
   1.311 +		}
   1.312 +	iHwDeviceObserver = aDevInfo.iHwDeviceObserver;
   1.313 +
   1.314 +	TInt err = KErrNone;
   1.315 +	if (aDevInfo.iOutStream.iConnection.iId)
   1.316 +		{
   1.317 +		iDeviceUid = TUid::Uid(aDevInfo.iOutStream.iConnection.iId);
   1.318 +		// Play device
   1.319 +		delete iPlayDevice;
   1.320 +		iPlayDevice  = NULL;
   1.321 +		TRAP(err, iPlayDevice = CRoutingSoundPlayDevice::NewL());
   1.322 +		if (err == KErrNone)
   1.323 +			{
   1.324 +			iPlayDevice->Initialize(iDeviceUid,
   1.325 +									aDevInfo.iOutStream.iDeviceName, *status);
   1.326 +			if (!iPlayCustomInterface)
   1.327 +				{
   1.328 +				TRAP(err,iPlayCustomInterface = new(ELeave)TPlayCustomInterface());
   1.329 +				if (err)
   1.330 +					{
   1.331 +					delete iPlayDevice;
   1.332 +					iPlayDevice = NULL;
   1.333 +					User::RequestComplete(status, err);
   1.334 +					return;
   1.335 +					}
   1.336 +				}
   1.337 +			static_cast<TPlayCustomInterface*>(iPlayCustomInterface)->SetDevice(iPlayDevice);	
   1.338 +			}
   1.339 +		}
   1.340 +	if (aDevInfo.iInStream.iConnection.iId)
   1.341 +		{
   1.342 +		iDeviceUid = TUid::Uid(aDevInfo.iInStream.iConnection.iId);
   1.343 +			// Record device
   1.344 +		TRAP(err, iRecordDevice = CRoutingSoundRecordDevice::NewL());
   1.345 +		if (err == KErrNone)
   1.346 +			{
   1.347 +			iRecordDevice->Initialize(iDeviceUid, KNullDesC8, *status);
   1.348 +			if (!iRecordCustomInterface)
   1.349 +				{
   1.350 +				TRAP(err,iRecordCustomInterface = new(ELeave)TRecordCustomInterface());
   1.351 +				if (err)
   1.352 +					{
   1.353 +					delete iRecordDevice;
   1.354 +					iRecordDevice = NULL;
   1.355 +					User::RequestComplete(status, err);
   1.356 +					return;
   1.357 +					}
   1.358 +				}
   1.359 +			}
   1.360 +		}
   1.361 +	
   1.362 +	iCodec = &(Codec()); //create codec
   1.363 +		
   1.364 +	//[ assert the post condition ]
   1.365 +	if (!iCodec)
   1.366 +		{
   1.367 +		err = KErrNotSupported;
   1.368 +		}
   1.369 +
   1.370 +	if (err != KErrNone)
   1.371 +		{
   1.372 +		User::RequestComplete(status, err);
   1.373 +		// Cancel initialisation too
   1.374 +		if (aDevInfo.iOutStream.iConnection.iId)
   1.375 +			{
   1.376 +			iPlayDevice->CancelInitialize(iDeviceUid);
   1.377 +			}
   1.378 +		if (aDevInfo.iInStream.iConnection.iId)
   1.379 +			{
   1.380 +			iRecordDevice->CancelInitialize(iDeviceUid);
   1.381 +			}		
   1.382 +		}		
   1.383 +	else if ((!aDevInfo.iOutStream.iConnection.iId)&& (!aDevInfo.iInStream.iConnection.iId))
   1.384 +		{
   1.385 +		//could be used for conversion so complete the request status
   1.386 +		User::RequestComplete(status, KErrNone);
   1.387 +		}
   1.388 +		
   1.389 +	}
   1.390 +
   1.391 +/**
   1.392 +Starts Encoding or Decoding task(s) based on the parameter specified.
   1.393 +
   1.394 +@param  aFuncCmd
   1.395 +        The device function specifying the requested service i.e. decode or encode
   1.396 +        where EDevEncode = Record, EDevDecode = Play and EDevNullFunc = Convert.
   1.397 +@param  aFlowCmd
   1.398 +        The device flow directions for requested service.
   1.399 +        This parameter is ignored for CMMFSwCodecWrapper CMMFHwDevicePlugins
   1.400 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
   1.401 +        another of the system-wide error codes.
   1.402 +*/
   1.403 +EXPORT_C TInt CMMFSwCodecWrapper::Start(TDeviceFunc aFuncCmd, TDeviceFlow /*aFlowCmd*/)
   1.404 +	{
   1.405 +	TInt error = KErrNone;
   1.406 +
   1.407 +	// [ precondition that aFuncCmd is valid]
   1.408 +	if (!((aFuncCmd == EDevEncode)|(aFuncCmd == EDevDecode)|(aFuncCmd == EDevNullFunc)))
   1.409 +		{
   1.410 +		return KErrArgument;
   1.411 +		}
   1.412 +
   1.413 +	// [ precondition that iCodec is present]
   1.414 +	if (!iCodec)
   1.415 +		{
   1.416 +		return KErrNotReady; //make sure the codec has been added
   1.417 +		}
   1.418 +
   1.419 +    switch (aFuncCmd)
   1.420 +        {
   1.421 +        case EDevEncode: // Audio record
   1.422 +			{
   1.423 +			error = StartEncode();
   1.424 +			}
   1.425 +            break;
   1.426 +        case EDevDecode: // Audio play
   1.427 +			{
   1.428 +			error = StartDecode();
   1.429 +			}
   1.430 +            break;
   1.431 +		case EDevNullFunc: //Audio Convert
   1.432 +			{
   1.433 +			error = StartConvert();
   1.434 +			}
   1.435 +			break;
   1.436 +        default:
   1.437 +            error = KErrNotSupported;
   1.438 +            break;
   1.439 +		}
   1.440 +
   1.441 +	//[ assert the post conditions ]
   1.442 +#ifdef DEBUG
   1.443 +	if (!error)
   1.444 +		{//only assert if no error otherwise post consitions not valid
   1.445 +		__ASSERT_DEBUG(iDataPath, Panic(EMMFSwCodecWrapperNoDataPath));
   1.446 +		if ((aFuncCmd == EDevEncode)||(aFuncCmd == EDevDecode))
   1.447 +			{
   1.448 +			__ASSERT_DEBUG(iDataPath->Device().Handle(), Panic(EMMFSwCodecWrapperNoDevice));
   1.449 +			}
   1.450 +		}
   1.451 +#endif
   1.452 +
   1.453 +	return error;
   1.454 +	}
   1.455 +
   1.456 +// Use AO to OpenDevice
   1.457 +TInt CMMFSwCodecWrapper::StartDecode()
   1.458 +	{
   1.459 +	TInt error = KErrNone;
   1.460 +
   1.461 +	//[ assert precondition that play custom interface is present]
   1.462 +	//if there is no play custom interface then the user of the CMMFSwCodecWrapper
   1.463 +	//cannot have set any of the custom settings such as sample rate.
   1.464 +	if (!iPlayCustomInterface)
   1.465 +		{
   1.466 +		return KErrNotReady;
   1.467 +		}
   1.468 +
   1.469 +	//play
   1.470 +	if (!iDataPath)
   1.471 +		{//create a datapath
   1.472 +		TRAP(error,iDataPath = CMMFSwCodecPlayDataPath::NewL(iPlayDevice, iDeviceUid));
   1.473 +		if ((iDataPath) && (error == KErrNone))
   1.474 +			{
   1.475 +			iDataPath->SetObserver(*iHwDeviceObserver);
   1.476 +			error = iDataPath->AddCodec(*iCodec);
   1.477 +			iDeviceBufferSize = iCodec->SinkBufferSize();
   1.478 +			static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->SetPlayCustomInterface(*iPlayCustomInterface);
   1.479 +			static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->SetConfigForAudioRamp(iSampleRate, iChannels);
   1.480 +			}
   1.481 +		}
   1.482 +
   1.483 +	if ((error == KErrNone) &&
   1.484 +		(iDataPath->State() != CMMFSwCodecDataPath::EPlaying))
   1.485 +		{
   1.486 +		TBool asynchOpen = EFalse;	// Ensure we only call OpenPlayComplete once
   1.487 +		//datapath was created ok and we are not playing
   1.488 +		if (iDataPath->State() == CMMFSwCodecDataPath::EStopped)
   1.489 +			{
   1.490 +			//starting from 'fresh so set sound device settings
   1.491 +  				
   1.492 +			// Create the AO OpenDevice handler
   1.493 +			if (!iOpenHandler)
   1.494 +				{
   1.495 +				TRAP(error, iOpenHandler = CRoutingSoundDeviceOpenHandler::NewL(this));				
   1.496 +				}
   1.497 +			if (!error)
   1.498 +				{
   1.499 + 				asynchOpen = ETrue;
   1.500 + 				iPlayDevice->SetBufferSize(iDeviceBufferSize);
   1.501 +				iOpenHandler->Start();
   1.502 +	 			static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->Device()->
   1.503 + 										OpenDevice(iDeviceUid, iOpenHandler->iStatus);
   1.504 +				}
   1.505 +			}
   1.506 +		if (!asynchOpen)
   1.507 +			{
   1.508 +			error = OpenPlayComplete(error);
   1.509 +			}
   1.510 +
   1.511 +		}//status == KErrNone
   1.512 +
   1.513 +	return error;
   1.514 +	}
   1.515 +
   1.516 +TInt CMMFSwCodecWrapper::StartEncode()
   1.517 +	{//record
   1.518 +
   1.519 +	//[ assert precondition that record custom interface is present]
   1.520 +	//if there is no record custom interface then the user of the CMMFSwCodecWrapper
   1.521 +	//cannot have set any of the custom settings such as sample rate.
   1.522 +	if (!iRecordCustomInterface)
   1.523 +		{
   1.524 +		return KErrNotReady;
   1.525 +		}
   1.526 +
   1.527 +	TInt error = KErrNone;
   1.528 +	if (!iDataPath)
   1.529 +		{
   1.530 +		TRAP(error,iDataPath = CMMFSwCodecRecordDataPath::NewL(iRecordDevice));
   1.531 +		if ((iDataPath)&&(error == KErrNone))
   1.532 +			{
   1.533 +			iDataPath->SetObserver(*iHwDeviceObserver);
   1.534 +			error = iDataPath->AddCodec(*iCodec);
   1.535 +			iDeviceBufferSize = (iCodec->SourceBufferSize());
   1.536 +			static_cast<TRecordCustomInterface*>(iRecordCustomInterface)->SetDataPath(static_cast<CMMFSwCodecRecordDataPath*>(iDataPath));
   1.537 +			}
   1.538 +		}
   1.539 +	if ((error == KErrNone)&&
   1.540 +		(iDataPath->State() != CMMFSwCodecDataPath::EPlaying))
   1.541 +		{
   1.542 +		TBool asynchOpen = EFalse;	// Ensure we only call OpenPlayComplete once
   1.543 +		if (!(static_cast<CMMFSwCodecRecordDataPath*>(iDataPath))->Device()->Handle())
   1.544 +  			{
   1.545 +			// Create the AO OpenDevice handler
   1.546 +			if (!iOpenHandler)
   1.547 +				{
   1.548 +				TRAP(error, iOpenHandler = CRoutingSoundDeviceOpenHandler::NewL(this));				
   1.549 +				}
   1.550 +			if (!error)
   1.551 +				{
   1.552 +				asynchOpen = ETrue;
   1.553 +				iRecordDevice->SetBufferSize(iDeviceBufferSize);
   1.554 +				iOpenHandler->Start();
   1.555 + 				static_cast<CMMFSwCodecRecordDataPath*>(iDataPath)->Device()->
   1.556 +									OpenDevice(iDeviceUid, iOpenHandler->iStatus);
   1.557 +				}
   1.558 +			}
   1.559 +			
   1.560 +		if (!asynchOpen)
   1.561 +			{
   1.562 +			error = OpenRecordComplete(error);
   1.563 +			}			
   1.564 +		}
   1.565 +
   1.566 +	return error;
   1.567 +	}
   1.568 +
   1.569 +TInt CMMFSwCodecWrapper::StartConvert()
   1.570 +	{//convert
   1.571 +
   1.572 +	TInt error = KErrNone;
   1.573 +	if (!iDataPath)
   1.574 +		{
   1.575 +		TRAP(error,iDataPath = CMMFSwCodecConvertDataPath::NewL());
   1.576 +		if ((iDataPath)&&(error == KErrNone))
   1.577 +			{
   1.578 +			iDataPath->SetObserver(*iHwDeviceObserver);
   1.579 +			error = iDataPath->AddCodec(*iCodec);
   1.580 +			}
   1.581 +		}
   1.582 +    if (error == KErrNone)
   1.583 +    	{
   1.584 +		error = iDataPath->Start();
   1.585 +    	}
   1.586 +	return error;
   1.587 +	}
   1.588 +
   1.589 +/**
   1.590 +Temporarily suspends the current task of decoding or encoding.
   1.591 +
   1.592 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
   1.593 +        another of the system-wide error codes.
   1.594 +*/
   1.595 +EXPORT_C TInt CMMFSwCodecWrapper::Pause()
   1.596 +	{
   1.597 +	// [ precondition that datapath exists ]
   1.598 +	if (!iDataPath)
   1.599 +		{
   1.600 +		return KErrNotReady;
   1.601 +		}
   1.602 +		
   1.603 +	iDataPath->Pause();
   1.604 +	return KErrNone;
   1.605 +	}
   1.606 +
   1.607 +/**
   1.608 +Stops the current on-going task.
   1.609 +
   1.610 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
   1.611 +        another of the system-wide error codes.
   1.612 +*/
   1.613 +EXPORT_C TInt CMMFSwCodecWrapper::Stop()
   1.614 +	{
   1.615 +	// [ precondition that datapath exists ]
   1.616 +	if (!iDataPath)
   1.617 +		{
   1.618 +		return KErrNotReady;
   1.619 +		}
   1.620 +	iDataPath->Stop();
   1.621 +	return KErrNone;
   1.622 +	}
   1.623 +
   1.624 +
   1.625 +/**
   1.626 +Stops and deletes the codec.
   1.627 +
   1.628 +This default implementation simply calls DeleteCodec() and then Stop()
   1.629 +but real hardware devices might use this method to free up resources.
   1.630 +
   1.631 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
   1.632 +        another of the system-wide error codes.
   1.633 +*/
   1.634 +EXPORT_C TInt CMMFSwCodecWrapper::StopAndDeleteCodec()
   1.635 +	{
   1.636 +	TInt stopError = Stop();
   1.637 +	TInt deleteError = DeleteCodec();
   1.638 +
   1.639 +	if (stopError != KErrNone)
   1.640 +		{
   1.641 +		return stopError;
   1.642 +		}
   1.643 +	else
   1.644 +		{
   1.645 +		return deleteError;
   1.646 +		}
   1.647 +	}
   1.648 +
   1.649 +/**
   1.650 +Deletes the codec
   1.651 +This default implementation does nothing
   1.652 +but real hardware devices might use this method to free up resources.
   1.653 +@return		Error code. KErrNone if successful
   1.654 +*/
   1.655 +EXPORT_C TInt CMMFSwCodecWrapper::DeleteCodec()
   1.656 +	{
   1.657 +	return KErrNone;
   1.658 +	}
   1.659 +
   1.660 +/**
   1.661 +Call this function to notify hardware device implementation that
   1.662 +data is available in aFillBufferPtr for decoding.
   1.663 +
   1.664 +@param aFillBufferPtr
   1.665 +       The data buffer filled by the observer.
   1.666 +
   1.667 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
   1.668 +        another of the system-wide error codes.
   1.669 +*/
   1.670 +EXPORT_C TInt CMMFSwCodecWrapper::ThisHwBufferFilled(CMMFBuffer& aFillBufferPtr)
   1.671 +	{
   1.672 +	TRAPD(err,iDataPath->BufferFilledL(STATIC_CAST(CMMFDataBuffer&, aFillBufferPtr)));
   1.673 +	return err;
   1.674 +	}
   1.675 +
   1.676 +/**
   1.677 +Call this function to notify hardware device implementation that
   1.678 +data in aEmptyBufferPtr from encoding is processed.
   1.679 +
   1.680 +@param  aBuffer
   1.681 +        The data buffer processed by observer.
   1.682 +
   1.683 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
   1.684 +        another of the system-wide error codes.
   1.685 +*/
   1.686 +EXPORT_C TInt CMMFSwCodecWrapper::ThisHwBufferEmptied(CMMFBuffer& aBuffer)
   1.687 +	{
   1.688 +	TRAPD(err,iDataPath->BufferEmptiedL(STATIC_CAST(CMMFDataBuffer&, aBuffer)));
   1.689 +	return err;
   1.690 +	}
   1.691 +
   1.692 +
   1.693 +/**
   1.694 +Retrieves a custom interface to the device.
   1.695 +The reference CMMFSwCodecWrapper supports two standard custom interfaces,
   1.696 +TPlayCustomInterface and TRecordCustomInterface.
   1.697 +
   1.698 +@param	aInterface
   1.699 +		Interface UID, defined with the custom interface.
   1.700 +		aInterface = KMmfPlayCustomInterface for TPlayCustomInterface,
   1.701 +		aInterface = KMmfRecordCustomInterface for TRecordCustomInterface.
   1.702 +		Actual device implementations of CMMFSwCodecWrapper may do this differently however.
   1.703 +@return A pointer to the interface implementation, or NULL if the device can not
   1.704 +		implement the interface requested. The return value must be cast to the
   1.705 +		correct type by the user.
   1.706 +*/
   1.707 +EXPORT_C TAny* CMMFSwCodecWrapper::CustomInterface(TUid aInterface)
   1.708 +	{
   1.709 +	TAny* ret = NULL;
   1.710 +	TInt err = KErrNone;
   1.711 +	if (aInterface.iUid == KMmfPlaySettingsCustomInterface)
   1.712 +		{
   1.713 +		if (!iPlayCustomInterface)
   1.714 +			{
   1.715 +			TRAP(err,iPlayCustomInterface = new(ELeave)TPlayCustomInterface());
   1.716 +			}
   1.717 +		if (err)
   1.718 +			{
   1.719 +			ret = NULL;
   1.720 +			}
   1.721 +		else
   1.722 +			{
   1.723 +			ret = static_cast<TAny*>(iPlayCustomInterface);
   1.724 +			}
   1.725 +		}
   1.726 +	else if (aInterface.iUid == KMmfRecordSettingsCustomInterface)
   1.727 +		{
   1.728 +		if (!iRecordCustomInterface)
   1.729 +			{
   1.730 +			TRAP(err,iRecordCustomInterface = new(ELeave)TRecordCustomInterface());
   1.731 +			}
   1.732 +		if (err)
   1.733 +			{
   1.734 +			ret = NULL;
   1.735 +			}
   1.736 +		else
   1.737 +			{
   1.738 +			ret = static_cast<TAny*>(iRecordCustomInterface);
   1.739 +			}
   1.740 +		}
   1.741 +
   1.742 +	return ret;
   1.743 +	}
   1.744 +
   1.745 +
   1.746 +/**
   1.747 +Used to configure the sample rate and stereo mode of a CMMFHwDevice plugin.
   1.748 +
   1.749 +The configuration of HwDevices is device specific and is not used in any of the reference
   1.750 +devices that return KErrNotSupported.
   1.751 +
   1.752 +@param  aConfig
   1.753 +        The device configuration.
   1.754 +*/
   1.755 +EXPORT_C TInt CMMFSwCodecWrapper::SetConfig(TTaskConfig& aConfig)
   1.756 +	{
   1.757 +	TInt err = KErrNone;
   1.758 +	if (aConfig.iUid != KUidRefDevSoundTaskConfig)
   1.759 +		return KErrArgument;
   1.760 +	iSampleRate = aConfig.iRate;//note we're cheating a bit
   1.761 +	//iRate is actually a bit map enum but an actual value
   1.762 +	//is more useful here
   1.763 +	TMMFStereoSupport stereoSupport = EMMFNone;
   1.764 +	if (aConfig.iStereoMode == ETaskMono)
   1.765 +		{
   1.766 +		iChannels = 1;
   1.767 +		}
   1.768 +	else if (aConfig.iStereoMode == ETaskInterleaved) 
   1.769 +		{
   1.770 +		iChannels = 2;
   1.771 +		stereoSupport = EMMFInterleavedOnly;
   1.772 +		}
   1.773 +	else //don't support non interleaved
   1.774 +		{
   1.775 +		return KErrNotSupported;
   1.776 +		}
   1.777 +		
   1.778 +	//set values on routing sound device
   1.779 +	if (iPlayDevice)
   1.780 +		{
   1.781 +		err = iPlayDevice->SetChannels(iChannels, stereoSupport);
   1.782 +		if (!err)
   1.783 +			{
   1.784 +			err = iPlayDevice->SetSampleRate(iSampleRate);
   1.785 +			}
   1.786 +		if (!err)
   1.787 +			{//we'll set the data type while were at it for now pcm16 only
   1.788 +			TFourCC fourCC = KMMFFourCCCodePCM16;
   1.789 +			err = iPlayDevice->SetDataType(fourCC);
   1.790 +			}
   1.791 +		}
   1.792 +	if ((iRecordDevice) && (!err))
   1.793 +		{
   1.794 +		err = iRecordDevice->SetChannels(iChannels, stereoSupport);
   1.795 +		if (!err)
   1.796 +			{
   1.797 +			err = iRecordDevice->SetSampleRate(iSampleRate);
   1.798 +			}
   1.799 +		}
   1.800 +	
   1.801 +	return err;
   1.802 +	}
   1.803 +
   1.804 +/**
   1.805 +Callback once CRoutingSoundPlayDevice or CRoutingSoundRecordDevice::Open has completed or continuation from
   1.806 +call to StartDecode / StartEncode, depending on the state.
   1.807 +
   1.808 +@internalTechnology
   1.809 +@param	aError
   1.810 +		The status of the device.
   1.811 +@return A standard Symbian wide error code.
   1.812 + */
   1.813 +TInt CMMFSwCodecWrapper::OpenComplete(TInt aError)
   1.814 +	{
   1.815 +	TInt err = KErrNotSupported;	//
   1.816 +	if (iPlayDevice)
   1.817 +		{
   1.818 +		err = OpenPlayComplete(aError);
   1.819 +		}
   1.820 +	else if (iRecordDevice)
   1.821 +		{
   1.822 +		err = OpenRecordComplete(aError);
   1.823 +		}
   1.824 +	return err;
   1.825 +	}
   1.826 +	
   1.827 +/**
   1.828 +Callback once CRoutingSoundPlayDevice::Open has completed or continuation from
   1.829 +call to StartDecode, depending on the state.
   1.830 +
   1.831 +@param	aError
   1.832 +		The status of the device.
   1.833 +@return A standard Symbian wide error code.
   1.834 + */
   1.835 +TInt CMMFSwCodecWrapper::OpenPlayComplete(TInt aError)
   1.836 +	{
   1.837 +	TInt error = aError;
   1.838 +	
   1.839 +	//datapath was created ok and we are not playing
   1.840 +	if (error == KErrNone && iDataPath->State() == CMMFSwCodecDataPath::EStopped)
   1.841 +		{
   1.842 +		//starting from fresh so set sound device settings
   1.843 +//		static_cast<TPlayCustomInterface*>(iPlayCustomInterface)->SetDevice(
   1.844 +//					static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->Device() );
   1.845 +		static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->Device()->SetVolume(iPlayCustomInterface->Volume());
   1.846 +		}
   1.847 +		
   1.848 +	// resuming from pause or ready to play
   1.849 +	if ((error == KErrNone) || (error == KErrInUse))
   1.850 +		{
   1.851 +		error = iDataPath->Start();
   1.852 +		}		
   1.853 +	
   1.854 +	return error;
   1.855 +	}
   1.856 +
   1.857 +/**
   1.858 +Callback once CRoutingSoundRecordDevice::Open has completed or continuation from
   1.859 +call to StartDecode, depending on the state.
   1.860 +
   1.861 +@param	aError
   1.862 +		The status of the device.
   1.863 +@return A standard Symbian wide error code.
   1.864 + */
   1.865 +TInt CMMFSwCodecWrapper::OpenRecordComplete(TInt aError)
   1.866 +	{
   1.867 +	TInt error = aError;
   1.868 +	
   1.869 +	//datapath was created ok and we are not playing
   1.870 +	if (error == KErrNone && iDataPath->State() == CMMFSwCodecDataPath::EStopped)
   1.871 +		{
   1.872 +		//set sound driver settings
   1.873 +		static_cast<CMMFSwCodecRecordDataPath*>(iDataPath)->Device()
   1.874 +												->SetGain(iRecordCustomInterface->Gain());
   1.875 +		/*
   1.876 +		// Sample rate
   1.877 +		(static_cast<CMMFSwCodecRecordDataPath*>(iDataPath))->Device()->SetSampleRate(iSampleRate);
   1.878 +		// Channels
   1.879 +		TMMFStereoSupport stereoSupport = EMMFNone;	// assume mono
   1.880 +		if (iChannels == 2)
   1.881 +			{
   1.882 +			// Assume interleaved only
   1.883 +			stereoSupport = EMMFInterleavedOnly;
   1.884 +			}
   1.885 +		error = (static_cast<CMMFSwCodecRecordDataPath*>(iDataPath))->Device()->SetChannels(iChannels, stereoSupport);
   1.886 +		*/
   1.887 +		}
   1.888 +
   1.889 +	// resuming from pause or ready to play
   1.890 +	if ((error == KErrNone) || (error == KErrInUse))
   1.891 +		{
   1.892 +		error = iDataPath->Start();
   1.893 +		}		
   1.894 +	
   1.895 +	return error;
   1.896 +	}