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 + }