1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmhais/refacladapt/src/tonehwdevice/tonehwdevice.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1031 @@
1.4 +// tonehwdevice.cpp
1.5 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +// All rights reserved.
1.7 +// This component and the accompanying materials are made available
1.8 +// under the terms of "Eclipse Public License v1.0"
1.9 +// which accompanies this distribution, and is available
1.10 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +//
1.12 +// Initial Contributors:
1.13 +// Nokia Corporation - initial contribution.
1.14 +//
1.15 +// Contributors:
1.16 +//
1.17 +// Description:
1.18 +//
1.19 +
1.20 +
1.21 +
1.22 +// INCLUDE FILES
1.23 +#include <mmf/server/mmfhwdevice.h>
1.24 +#include "tonehwdevice.hrh" //for KUidToneHwDevice
1.25 +#include <ecom/implementationproxy.h> // For making it ECom plugin
1.26 +#include "tonehwdevice.h"
1.27 +
1.28 +
1.29 +// EXTERNAL DATA STRUCTURES
1.30 +
1.31 +// EXTERNAL FUNCTION PROTOTYPES
1.32 +
1.33 +// CONSTANTS
1.34 +const TImplementationProxy ImplementationTable[] =
1.35 + {
1.36 + IMPLEMENTATION_PROXY_ENTRY(KUidToneHwDevice, CToneHwDevice::NewL),
1.37 + };
1.38 +//current supported sample rate
1.39 +const TInt KSupportedSampleRate = 8000;
1.40 +
1.41 +// ---------------------------------------------------------------------------
1.42 +// Default constructor
1.43 +// ---------------------------------------------------------------------------
1.44 +//
1.45 +CToneHwDevice::CToneHwDevice()
1.46 + {
1.47 + DP_CONTEXT(CToneHwDevice::CToneHwDevice *CD1*, CtxDevSound, DPLOCAL);
1.48 + DP_IN();
1.49 + DP_OUT();
1.50 + }
1.51 +
1.52 +// -----------------------------------------------------------------------------
1.53 +// Symbian 2nd phase constructor
1.54 +// -----------------------------------------------------------------------------
1.55 +//
1.56 +void CToneHwDevice::ConstructL()
1.57 + {
1.58 + DP_CONTEXT(CToneHwDevice::ConstructL *CD0*, CtxDevSound, DPLOCAL);
1.59 + DP_IN();
1.60 +
1.61 + iHwDataBufferFill = CMMFDataBuffer::NewL(sizeof(TToneData));
1.62 + iHwDataBufferFill->SetLastBuffer(EFalse);
1.63 + iHwDataBufferFill->Data().SetLength(sizeof(TToneData));
1.64 + iHwDataBufferFill->SetRequestSizeL(sizeof(TToneData));
1.65 +
1.66 + iCodec = new(ELeave)CToneCodec();
1.67 +
1.68 + DP_OUT();
1.69 + }
1.70 +
1.71 +// -----------------------------------------------------------------------------
1.72 +// Symbian constructor
1.73 +// -----------------------------------------------------------------------------
1.74 +//
1.75 +CToneHwDevice* CToneHwDevice::NewL()
1.76 + {
1.77 + DP_STATIC_CONTEXT(CToneHwDevice::NewL *CD0*, CtxDevSound, DPLOCAL);
1.78 + DP_IN();
1.79 + CToneHwDevice* self = new (ELeave) CToneHwDevice();
1.80 + CleanupStack::PushL(self);
1.81 + self->ConstructL();
1.82 + CleanupStack::Pop();
1.83 + DP0_RET(self, "0x%x");
1.84 + }
1.85 +
1.86 +// ---------------------------------------------------------------------------
1.87 +// Destructor
1.88 +// ---------------------------------------------------------------------------
1.89 +//
1.90 +CToneHwDevice::~CToneHwDevice()
1.91 + {
1.92 + DP_CONTEXT(CToneHwDevice::~CToneHwDevice *CD0*, CtxDevSound, DPLOCAL);
1.93 + DP_IN();
1.94 + delete iHwDataBufferFill;
1.95 + delete iCodec;
1.96 + delete iPlayCustomInterface;
1.97 +
1.98 + if(iDataPath)
1.99 + {
1.100 + delete iDataPath;
1.101 + }
1.102 +
1.103 + if(iToneBuffer1)
1.104 + {
1.105 + delete iToneBuffer1;
1.106 + }
1.107 + if(iToneBuffer2)
1.108 + {
1.109 + delete iToneBuffer2;
1.110 + }
1.111 + DP_OUT();
1.112 + }
1.113 +
1.114 +/**
1.115 +*
1.116 +* Codec
1.117 +*
1.118 +*/
1.119 +CToneCodec& CToneHwDevice::Codec()
1.120 + {
1.121 + return *iCodec;
1.122 + }
1.123 +
1.124 +// ---------------------------------------------------------------------------
1.125 +// from class CMMFHwDevice
1.126 +// CToneHwDevice::Init
1.127 +// ---------------------------------------------------------------------------
1.128 +//
1.129 +TInt CToneHwDevice::Init(THwDeviceInitParams& aDevInfo)
1.130 + {
1.131 + DP_CONTEXT(CToneHwDevice::Init *CD1*, CtxDevSound, DPLOCAL);
1.132 + DP_IN();
1.133 +
1.134 + if (!iToneInitialized) // Check if tones is not initialized yet.
1.135 + {
1.136 + iToneInitialized = ETrue;
1.137 + }
1.138 +
1.139 + // [ precondition that aDevInfo has a valid observer ]
1.140 + if (!aDevInfo.iHwDeviceObserver)
1.141 + {
1.142 + DP0_RET(KErrArgument, "%d");
1.143 + }
1.144 +
1.145 + iHwDeviceObserver = aDevInfo.iHwDeviceObserver;
1.146 +
1.147 + //[ assert the post condition ]
1.148 + if (!iCodec)
1.149 + {
1.150 + DP0_RET(KErrNotSupported, "%d");
1.151 + }
1.152 +
1.153 + DP0_RET(KErrNone, "%d");
1.154 + }
1.155 +
1.156 +// ---------------------------------------------------------------------------
1.157 +// from class CMMFHwDevice
1.158 +// CToneHwDevice::Start
1.159 +// ---------------------------------------------------------------------------
1.160 +//
1.161 +TInt CToneHwDevice::Start(TDeviceFunc /*aFuncCmd*/, TDeviceFlow /*aFlowCmd*/)
1.162 + {
1.163 + DP_CONTEXT(CToneHwDevice::Start *CD1*, CtxDevSound, DPLOCAL);
1.164 + DP_IN();
1.165 +
1.166 + TInt error = KErrNone;
1.167 +
1.168 + // Start for first time OR resuming
1.169 + if (!iTonePlaying || iDataPath->State() == CToneDataPath::EPaused)
1.170 + {
1.171 + iLastBuffer = EFalse;
1.172 + //[ assert precondition that play custom interface is present]
1.173 + //if there is no tone play custom interface then the user of the CToneHwDevice
1.174 + //cannot have set any of the custom settings such as sample rate.
1.175 + if (!iPlayCustomInterface)
1.176 + {
1.177 + DP0_RET(KErrNotReady, "%d");
1.178 + }
1.179 +
1.180 + //play
1.181 + if (!iDataPath)
1.182 + {
1.183 + //create a datapath
1.184 + TRAP(error,iDataPath = CToneDataPath::NewL());
1.185 + if ((iDataPath)&&(error == KErrNone))
1.186 + {
1.187 + ASSERT(iHwDeviceObserver);
1.188 + iDataPath->SetObserver(*this);
1.189 + error = iDataPath->AddCodec(*iCodec);
1.190 + if (error == KErrNone)
1.191 + {
1.192 + iDeviceBufferSize = (iCodec->SinkBufferSize());
1.193 + }
1.194 + }
1.195 + }
1.196 + if ((error == KErrNone) && (iDataPath->State() != CToneDataPath::EPlaying))
1.197 + {
1.198 + //datapath was created ok and we are not playing
1.199 + if (iDataPath->State() == CToneDataPath::EStopped)
1.200 + {
1.201 + // starting from 'fresh so set sound device settings
1.202 + if (!iDataPath->Device().Handle())
1.203 + {
1.204 + //if Device() is called then we need a valid sound device handle
1.205 + error = iDataPath->Device().Open();
1.206 + if (error != KErrNone)
1.207 + {
1.208 + DP0_RET(error, "%d");
1.209 + }
1.210 +
1.211 + }
1.212 + static_cast<TToneCustomInterface*>(iPlayCustomInterface)->SetDevice(&(iDataPath->Device()));
1.213 +
1.214 + TUint iVol = iPlayCustomInterface->Volume();
1.215 + iDataPath->Device().SetPlayVolume(iVol);
1.216 +
1.217 + soundDeviceSettings().iRate = iSampleRate;
1.218 +
1.219 + //this would normally be pcm16
1.220 + soundDeviceSettings().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
1.221 +
1.222 + //1 = mono 2 = stereo
1.223 + soundDeviceSettings().iChannels = iChannels;
1.224 +
1.225 + //tell sound driver what buffer size to expect
1.226 + //it is up the the implementor to make use the device can support
1.227 + //the required buffer size
1.228 + soundDeviceSettings().iBufferSize = iDeviceBufferSize;
1.229 + error = iDataPath->Device().SetPlayFormat(soundDeviceSettings);
1.230 +
1.231 + } // End of iDataPath->State() == CToneDataPath::EStopped
1.232 +
1.233 + //else resuming from pause
1.234 + if ((error == KErrNone)||(error == KErrInUse))
1.235 + {
1.236 + // Hw device hasn't played anything yet so don't change
1.237 + // active buffer. This is checked in FillThisHwBuffer.
1.238 + if(iDataPath->State() != CToneDataPath::EPaused)
1.239 + {
1.240 + iFirstCallFromHwDevice = ETrue;
1.241 + }
1.242 + iTonePlaying = ETrue;
1.243 + error = iDataPath->Start();
1.244 + }
1.245 + }//status == KErrNone
1.246 + }
1.247 + else // if tone playback is already ongoing do nothing
1.248 + {
1.249 + DP0(DLINFO,"Previous tone call is not completed yet");
1.250 + }
1.251 + DP0_RET(error, "%d");
1.252 + }
1.253 +
1.254 +// ---------------------------------------------------------------------------
1.255 +// from class CMMFHwDevice
1.256 +// CToneHwDevice::Stop
1.257 +// ---------------------------------------------------------------------------
1.258 +TInt CToneHwDevice::Stop()
1.259 + {
1.260 + DP_CONTEXT(CToneHwDevice::Stop *CD1*, CtxDevSound, DPLOCAL);
1.261 + DP_IN();
1.262 + if (iTonePlaying)
1.263 + {
1.264 + iTonePlaying = EFalse;
1.265 + }
1.266 +
1.267 + if (!iDataPath)
1.268 + {
1.269 + DP0_RET(KErrNotReady, "%d");
1.270 + }
1.271 +
1.272 + delete iDataPath;
1.273 + iDataPath = NULL;
1.274 +
1.275 + //Setting device to NULL since after stop it doesn't exists any more
1.276 + if(iPlayCustomInterface)
1.277 + {
1.278 + static_cast<TToneCustomInterface*>(iPlayCustomInterface)->SetDevice(NULL);
1.279 + }
1.280 +
1.281 + DP0_RET(KErrNone, "%d");
1.282 + }
1.283 +
1.284 +// ---------------------------------------------------------------------------
1.285 +// from class CMMFHwDevice
1.286 +// CToneHwDevice::Pause
1.287 +// ---------------------------------------------------------------------------
1.288 +//
1.289 +TInt CToneHwDevice::Pause()
1.290 + {
1.291 + DP_CONTEXT(CToneHwDevice::Pause *CD1*, CtxDevSound, DPLOCAL);
1.292 + DP_IN();
1.293 +
1.294 + if (!iDataPath)
1.295 + {
1.296 + DP0_RET(KErrNotReady, "%d");
1.297 + }
1.298 + iDataPath->Pause();
1.299 +
1.300 + DP0_RET(KErrNone, "%d");
1.301 + }
1.302 +
1.303 +// ---------------------------------------------------------------------------
1.304 +// from class CMMFHwDevice
1.305 +// CToneHwDevice::StopAndDeleteCodec
1.306 +// ---------------------------------------------------------------------------
1.307 +//
1.308 +TInt CToneHwDevice::StopAndDeleteCodec()
1.309 + {
1.310 + DP_CONTEXT(CToneHwDevice::StopAndDeleteCodec *CD1*, CtxDevSound, DPLOCAL);
1.311 + DP_IN();
1.312 + DP0_RET(KErrNotSupported, "%d");
1.313 + }
1.314 +
1.315 +// ---------------------------------------------------------------------------
1.316 +// from class CMMFHwDevice
1.317 +// CToneHwDevice::DeleteCodec
1.318 +// ---------------------------------------------------------------------------
1.319 +//
1.320 +TInt CToneHwDevice::DeleteCodec()
1.321 + {
1.322 + DP_CONTEXT(CToneHwDevice::DeleteCodec *CD1*, CtxDevSound, DPLOCAL);
1.323 + DP_IN();
1.324 + DP0_RET(KErrNotSupported, "%d");
1.325 + }
1.326 +
1.327 +// ---------------------------------------------------------------------------
1.328 +// from class CMMFHwDevice
1.329 +// CToneHwDevice::SetConfig
1.330 +// ---------------------------------------------------------------------------
1.331 +//
1.332 +TInt CToneHwDevice::SetConfig(TTaskConfig& aConfig)
1.333 + {
1.334 + DP_CONTEXT(CToneHwDevice::SetConfig *CD1*, CtxDevSound, DPLOCAL);
1.335 + DP_IN();
1.336 +
1.337 + if (aConfig.iUid != KUidRefDevSoundTaskConfig)
1.338 + {
1.339 + DP0_RET(KErrArgument, "%d");
1.340 + }
1.341 +
1.342 + if (aConfig.iRate != KSupportedSampleRate )
1.343 + {
1.344 + DP0_RET(KErrNotSupported, "%d");
1.345 + }
1.346 +
1.347 + iSampleRate = aConfig.iRate;
1.348 +
1.349 + if (aConfig.iStereoMode == ETaskMono)
1.350 + {
1.351 + iChannels = 1;
1.352 + }
1.353 + else if (aConfig.iStereoMode == ETaskInterleaved || aConfig.iStereoMode == ETaskNonInterleaved)
1.354 + {
1.355 + iChannels = 2;
1.356 + }
1.357 + else
1.358 + {
1.359 + DP0_RET(KErrArgument, "%d");
1.360 + }
1.361 +
1.362 + DP0_RET(KErrNone, "%d");
1.363 + }
1.364 +
1.365 +// CToneHwDevice::FillThisHwBuffer
1.366 +// ---------------------------------------------------------------------------
1.367 +TInt CToneHwDevice::FillThisHwBuffer(CMMFBuffer& aHwBuffer)
1.368 + {
1.369 + DP_CONTEXT(CToneHwDevice::FillThisHwBuffer *CD1*, CtxDevSound, DPLOCAL);
1.370 + DP_IN();
1.371 +
1.372 + TInt err(KErrNone);
1.373 +
1.374 + if(iFirstCallFromHwDevice)
1.375 + {
1.376 + err = iHwDeviceObserver->FillThisHwBuffer(aHwBuffer);
1.377 + }
1.378 + else
1.379 + {
1.380 + err = ThisHwBufferFilled(aHwBuffer);
1.381 + }
1.382 + DP0_RET(err,"%d");
1.383 + }
1.384 +
1.385 +// ---------------------------------------------------------------------------
1.386 +// from class CMMFHwDevice
1.387 +// CToneHwDevice::ThisHwBufferFilled
1.388 +// ---------------------------------------------------------------------------
1.389 +//
1.390 +TInt CToneHwDevice::ThisHwBufferFilled(CMMFBuffer& aMmfBuffer)
1.391 + {
1.392 + DP_CONTEXT(CToneHwDevice::ThisHwBufferFilled *CD1*, CtxDevSound, DPLOCAL);
1.393 + DP_IN();
1.394 +
1.395 + TInt err = KErrNone;
1.396 + CMMFDataBuffer* myBuffer = static_cast<CMMFDataBuffer*> (&aMmfBuffer);
1.397 + // Set the request length, From HwDevice this comes with buffer
1.398 + // length.
1.399 + TInt len = myBuffer->Data().MaxLength();
1.400 + // Ignore error. since buffer size = Buffer Length
1.401 + TRAP(err, myBuffer->SetRequestSizeL(len));
1.402 +
1.403 + if(iFirstCallFromHwDevice)
1.404 + {
1.405 + myBuffer->SetLastBuffer(EFalse);
1.406 +
1.407 + Mem::Copy((TAny*)(&myToneData), (TAny*)(myBuffer->Data().Ptr()), sizeof(TToneData));
1.408 +
1.409 + err = ReadToneData();
1.410 + if(err==KErrNone)
1.411 + {
1.412 + err= GenerateBufferData();
1.413 + }
1.414 + }
1.415 + else
1.416 + {
1.417 + // Hw device will call this method right after its Start was called.
1.418 + // When it calls this for the first time it hasn't played one single
1.419 + // buffer yet so check that.
1.420 + // In this case there's no need to set the active buffer as it's already
1.421 + // waiting to be played.
1.422 + SetActiveToneBuffer();
1.423 + }
1.424 +
1.425 + if (err == KErrNone)
1.426 + {
1.427 + // If there is no data in the active buffer, tone play is finished.
1.428 + // DevSound just have to wait for completion event from audio device.
1.429 + if (iActiveToneBuffer->Data().Length() == 0)
1.430 + {
1.431 + iActiveToneBuffer->SetLastBuffer(ETrue);
1.432 + myBuffer->SetLastBuffer(ETrue);
1.433 + iLastBuffer=ETrue;
1.434 + }
1.435 +
1.436 + TInt tonelen = iActiveToneBuffer->Data().Length();
1.437 +
1.438 + // don't enter more data than can be handled by the receiving buffer
1.439 + if (len >= tonelen)
1.440 + {
1.441 + len = tonelen;
1.442 + }
1.443 +
1.444 + // Copy data from tone buffer to hw device buffer
1.445 + Mem::Copy((TAny*)(myBuffer->Data().Ptr()), (TAny*)(iActiveToneBuffer->Data().Ptr()), len);
1.446 +
1.447 + myBuffer->Data().SetLength(len);
1.448 +
1.449 + //Play data and try to generate next data block
1.450 + TRAP(err,iDataPath->BufferFilledL(static_cast<CMMFDataBuffer&> (*myBuffer)));
1.451 + if(err == KErrNone)
1.452 + {
1.453 + if(iLastBuffer)
1.454 + {
1.455 + // coverity[check_after_deref]
1.456 + if(myBuffer)
1.457 + {
1.458 + myBuffer = NULL;
1.459 + }
1.460 + FreeBuffers();
1.461 + iFirstCallFromHwDevice = EFalse;
1.462 + }
1.463 + else
1.464 + {
1.465 + // Check again whether this is the first call from Hw device.
1.466 + // FillFreeToneBuffer assumes the iActiveToneBuffer has already
1.467 + // been played.
1.468 + if (!iFirstCallFromHwDevice)
1.469 + {
1.470 + err = FillFreeToneBuffer();
1.471 + }
1.472 + else
1.473 + {
1.474 + iFirstCallFromHwDevice = EFalse; // Reset flag
1.475 + }
1.476 + }
1.477 + }
1.478 + }
1.479 + if ( err != KErrNone )
1.480 + {
1.481 + myBuffer->SetLastBuffer(ETrue);
1.482 + myBuffer->Data().SetLength(0);
1.483 + //Use error additional variable for sending last buffer so can still send Error(err)
1.484 + TRAPD(datapathErr, iDataPath->BufferFilledL(static_cast<CMMFDataBuffer&> (*myBuffer)));
1.485 + // coverity[check_after_deref]
1.486 + if(myBuffer)
1.487 + {
1.488 + myBuffer = NULL;
1.489 + }
1.490 + FreeBuffers();
1.491 + iFirstCallFromHwDevice = EFalse;
1.492 + if ( datapathErr != KErrNone )
1.493 + {
1.494 + iHwDeviceObserver->Error(datapathErr);
1.495 + DP0_RET(datapathErr, "%d");
1.496 + }
1.497 + iHwDeviceObserver->Error(err);
1.498 + }
1.499 + DP0_RET(err, "%d");
1.500 + }
1.501 +
1.502 +// ---------------------------------------------------------------------------
1.503 +// from class MMMFHwDeviceObserver
1.504 +// CToneHwDevice::ThisHwBufferEmptied
1.505 +// ---------------------------------------------------------------------------
1.506 +TInt CToneHwDevice::ThisHwBufferEmptied(CMMFBuffer& /*aMmfBuffer*/)
1.507 + {
1.508 + DP_CONTEXT(CToneHwDevice::ThisHwBufferEmptied *CD1*, CtxDevSound, DPLOCAL);
1.509 + DP_IN();
1.510 + DP0_RET(KErrNotSupported, "%d");
1.511 + }
1.512 +
1.513 +// ---------------------------------------------------------------------------
1.514 +// from class MMMFHwDeviceObserver
1.515 +// CToneHwDevice::EmptyThisHwBuffer
1.516 +// ---------------------------------------------------------------------------
1.517 +TInt CToneHwDevice::EmptyThisHwBuffer(CMMFBuffer& /*aMmfBuffer*/)
1.518 + {
1.519 + DP_CONTEXT(CToneHwDevice::EmptyThisHwBuffer *CD1*, CtxDevSound, DPLOCAL);
1.520 + DP_IN();
1.521 + DP0_RET(KErrNotSupported, "%d");
1.522 + }
1.523 +
1.524 +// ---------------------------------------------------------------------------
1.525 +// from class MMMFHwDeviceObserver
1.526 +// CToneHwDevice::MsgFromHwDevice
1.527 +// ---------------------------------------------------------------------------
1.528 +TInt CToneHwDevice::MsgFromHwDevice(TUid aMessageType, const TDesC8& aMsg)
1.529 + {
1.530 + DP_CONTEXT(CToneHwDevice::MsgFromHwDevice *CD1*, CtxDevSound, DPLOCAL);
1.531 + DP_IN();
1.532 + TInt err(KErrNone);
1.533 + err = iHwDeviceObserver->MsgFromHwDevice(aMessageType, aMsg);
1.534 + DP0_RET(err, "%d");
1.535 + }
1.536 +
1.537 +// ---------------------------------------------------------------------------
1.538 +// from class MMMFHwDeviceObserver
1.539 +// CToneHwDevice::Stopped
1.540 +// ---------------------------------------------------------------------------
1.541 +void CToneHwDevice::Stopped()
1.542 + {
1.543 + DP_CONTEXT(CToneHwDevice::Stopped *CD1*, CtxDevSound, DPLOCAL);
1.544 + DP_IN();
1.545 + iHwDeviceObserver->Stopped();
1.546 + DP_OUT();
1.547 + }
1.548 +
1.549 +// ---------------------------------------------------------------------------
1.550 +// from class MMMFHwDeviceObserver
1.551 +// CToneHwDevice::Error
1.552 +// ---------------------------------------------------------------------------
1.553 +void CToneHwDevice::Error(TInt aError)
1.554 + {
1.555 + DP_CONTEXT(CToneHwDevice::Error *CD1*, CtxDevSound, DPLOCAL);
1.556 + DP_IN();
1.557 + iHwDeviceObserver->Error(aError);
1.558 + DP_OUT();
1.559 + }
1.560 +
1.561 +// ---------------------------------------------------------------------------
1.562 +// from class CMMFHwDevice
1.563 +// CToneHwDevice::CustomInterface
1.564 +// ---------------------------------------------------------------------------
1.565 +//
1.566 +TAny* CToneHwDevice::CustomInterface(TUid aInterfaceUid)
1.567 + {
1.568 + DP_CONTEXT(CToneHwDevice::CustomInterface *CD1*, CtxDevSound, DPLOCAL);
1.569 + DP_IN();
1.570 +
1.571 + TAny* ret = NULL;
1.572 + TInt err = KErrNone;
1.573 +
1.574 + if (aInterfaceUid.iUid == KMmfPlaySettingsCustomInterface)
1.575 + {
1.576 + if (!iPlayCustomInterface)
1.577 + {
1.578 + TRAP(err,iPlayCustomInterface = new(ELeave)TToneCustomInterface());
1.579 + }
1.580 + if (err)
1.581 + {
1.582 + ret = NULL;
1.583 + }
1.584 + else
1.585 + {
1.586 + ret = static_cast<TAny*>(iPlayCustomInterface);
1.587 + }
1.588 + }
1.589 + else if (aInterfaceUid == KIgnoreUnderflowCustomInterfaceTypeUid)
1.590 + {
1.591 + if (!iDataPath)
1.592 + {
1.593 + ret = NULL;
1.594 + }
1.595 + else
1.596 + {
1.597 + ret = static_cast<CToneDataPath*>(iDataPath)->CustomInterface(aInterfaceUid);
1.598 + }
1.599 + }
1.600 +
1.601 + DP_OUT();
1.602 + return ret;
1.603 + }
1.604 +
1.605 +TInt CToneHwDevice::ReadToneData()
1.606 + {
1.607 + DP_CONTEXT(CToneHwDevice::ReadToneData *CD1*, CtxDevSound, DPLOCAL);
1.608 + DP_IN();
1.609 +
1.610 + TUint vol;
1.611 + myToneData.GetType(iToneType);
1.612 + TInt64 zeroInt64(0);
1.613 + iFrequency1 = myToneData.GetFrequencyOne();
1.614 + iFrequency2 = myToneData.GetFrequencyTwo();
1.615 + myToneData.GetDuration(iDuration);
1.616 +
1.617 + myToneData.GetRepeatTrailingSilence(iRepeatTrailingSilence);
1.618 + iRepeatCount = myToneData.GetRepeatCount();
1.619 + iRampDuration = iPlayCustomInterface->VolumeRamp();
1.620 + vol = iPlayCustomInterface->Volume();
1.621 + iDataPath->Device().SetPlayVolume(vol);
1.622 + switch (iToneType)
1.623 + {
1.624 + case TToneData::ESimple:
1.625 + DP0(DLINFO, "Playing simple tone");
1.626 + iDataPath->Device().GetPlayFormat(soundDeviceSettings);
1.627 + if((iFrequency1<0) || (iDuration.Int64() < zeroInt64))
1.628 + {
1.629 + iHwDeviceObserver->Error(KErrArgument);
1.630 + DP0_RET(KErrArgument, "%d");
1.631 + }
1.632 + iToneGen.SetFrequencyAndDuration(iFrequency1,iDuration);
1.633 + // Configure tone generator
1.634 + iToneGen.Configure(
1.635 + soundDeviceSettings().iRate,
1.636 + soundDeviceSettings().iChannels,
1.637 + iRepeatCount,
1.638 + I64LOW((iRepeatTrailingSilence.Int64()*soundDeviceSettings().iRate)/1000000),
1.639 + I64LOW((iRampDuration.Int64()*soundDeviceSettings().iRate)/1000000)
1.640 + );
1.641 + iCurrentGenerator = &iToneGen;
1.642 + break;
1.643 + case TToneData::EDual:
1.644 + DP0(DLINFO, "Playing dual tone");
1.645 + iDataPath->Device().GetPlayFormat(soundDeviceSettings);
1.646 + if((iFrequency1<0) || (iFrequency2<0) || (iDuration.Int64() < zeroInt64))
1.647 + {
1.648 + iHwDeviceObserver->Error(KErrArgument);
1.649 + DP0_RET(KErrArgument, "%d");
1.650 + }
1.651 + iDualToneGen.SetFrequencyAndDuration(iFrequency1, iFrequency2, iDuration);
1.652 + // Configure dual tone generator
1.653 + iDualToneGen.Configure(
1.654 + soundDeviceSettings().iRate,
1.655 + soundDeviceSettings().iChannels,
1.656 + iRepeatCount,
1.657 + I64LOW((iRepeatTrailingSilence.Int64()*soundDeviceSettings().iRate)/KOneMillionMicroSeconds),
1.658 + I64LOW((iRampDuration.Int64()*soundDeviceSettings().iRate)/KOneMillionMicroSeconds)
1.659 + );
1.660 + iCurrentGenerator = &iDualToneGen;
1.661 + break;
1.662 + case TToneData::EDtmfString:
1.663 + DP0(DLINFO, "Playing DTMF string");
1.664 + myToneData.GetDtmfLenghts(myToneOnLength, myToneOffLength, myPauseLength);
1.665 + iDTMFGen.SetToneDurations(myToneOnLength, myToneOffLength, myPauseLength);
1.666 + iDTMFString = myToneData.GetDTMFString();
1.667 + if(!ValidDTMFString(const_cast<TDesC&>(*iDTMFString)))
1.668 + {
1.669 + DP0(DLINFO, "Invalid DTMF String");
1.670 + iHwDeviceObserver->Error(KErrCorrupt);
1.671 + DP0_RET(KErrCorrupt, "%d");
1.672 + }
1.673 + iDTMFGen.SetString(const_cast<TDesC&>(*iDTMFString));
1.674 + iDataPath->Device().GetPlayFormat(soundDeviceSettings);
1.675 + iDTMFGen.Configure(
1.676 + soundDeviceSettings().iRate,
1.677 + soundDeviceSettings().iChannels,
1.678 + iRepeatCount,
1.679 + I64LOW((iRepeatTrailingSilence.Int64()*soundDeviceSettings().iRate)/1000000),
1.680 + I64LOW((iRampDuration.Int64()*soundDeviceSettings().iRate)/1000000)
1.681 + );
1.682 + iCurrentGenerator = &iDTMFGen;
1.683 + break;
1.684 + case TToneData::ESequence:
1.685 + DP0(DLINFO, "Playing tone sequence");
1.686 + iSequenceData = myToneData.GetSequenceData();
1.687 + // Check whether the sequence is signed or not
1.688 + if (!RecognizeSequence(*iSequenceData))
1.689 + {
1.690 + DP0(DLINFO, "Invalid Sequence Sign");
1.691 + iHwDeviceObserver->Error(KErrCorrupt);
1.692 + DP0_RET(KErrCorrupt, "%d");
1.693 + }
1.694 + iSequenceGen.SetSequenceData(*iSequenceData);
1.695 + iDataPath->Device().GetPlayFormat(soundDeviceSettings);
1.696 + iSequenceGen.Configure(
1.697 + soundDeviceSettings().iRate,
1.698 + soundDeviceSettings().iChannels,
1.699 + iRepeatCount,
1.700 + I64LOW((iRepeatTrailingSilence.Int64()*soundDeviceSettings().iRate)/1000000),
1.701 + I64LOW((iRampDuration.Int64()*soundDeviceSettings().iRate)/1000000)
1.702 + );
1.703 + iCurrentGenerator = &iSequenceGen;
1.704 + break;
1.705 + case TToneData::EFixedSequence:
1.706 + DP0(DLINFO, "Playing FixedSequnce");
1.707 + iHwDeviceObserver->Error(KErrNotSupported);
1.708 + DP0_RET(KErrNotSupported, "%d");
1.709 + default:
1.710 + DP0_RET(KErrNotSupported, "%d");
1.711 + }
1.712 + DP0_RET(KErrNone, "%d");
1.713 + }
1.714 +
1.715 +/*
1.716 + *
1.717 + * Creates buffer and begin playback using the specified tone generator.
1.718 + *
1.719 + */
1.720 +TInt CToneHwDevice::GenerateBufferData()
1.721 + {
1.722 + DP_CONTEXT(CToneHwDevice::GenerateBufferData *CD1*, CtxDevSound, DPLOCAL);
1.723 + DP_IN();
1.724 +
1.725 + TInt err;
1.726 + err = KErrNone;
1.727 +
1.728 + // Delete any buffer from previous call and try to create maximum buffer
1.729 + // size. Double Buffer the Tone data.
1.730 + if (iToneBuffer1)
1.731 + {
1.732 + delete iToneBuffer1;
1.733 + iToneBuffer1 = NULL;
1.734 + }
1.735 + //note the tone buffer needs to be the same as the pcm16->pcm16 'null'
1.736 + //hw device plugin
1.737 + // Buffer size = (SampleRate * BytesPerSample * Channels) / 4
1.738 + TInt useBufferOfSize = ((SamplingFrequency() * 2 * NumberOfChannels())/KDevSoundFramesPerSecond + (KDevSoundDeltaFrameSize-1)) &~ (KDevSoundDeltaFrameSize-1);
1.739 + //clamp buffer to desired limits
1.740 + if(useBufferOfSize < KDevSoundMinFrameSize)
1.741 + {
1.742 + useBufferOfSize = KDevSoundMinFrameSize;
1.743 + }
1.744 + else if(useBufferOfSize > KDevSoundMaxFrameSize)
1.745 + {
1.746 + useBufferOfSize = KDevSoundMaxFrameSize;
1.747 + }
1.748 +
1.749 + TRAP(err, iToneBuffer1 = CMMFDataBuffer::NewL(useBufferOfSize));
1.750 + if ( err != KErrNone )
1.751 + {
1.752 + DP0_RET(err, "%d");
1.753 + }
1.754 +
1.755 + err = iCurrentGenerator->FillBuffer(iToneBuffer1->Data());
1.756 + if(err!=KErrNone)
1.757 + {
1.758 + DP0_RET(err, "%d");
1.759 + }
1.760 +
1.761 + if (iToneBuffer2)
1.762 + {
1.763 + delete iToneBuffer2;
1.764 + iToneBuffer2 = NULL;
1.765 + }
1.766 +
1.767 + TRAP(err, iToneBuffer2 = CMMFDataBuffer::NewL(useBufferOfSize));
1.768 + if ( err != KErrNone )
1.769 + {
1.770 + DP0_RET(err, "%d");
1.771 + }
1.772 +
1.773 + err = iCurrentGenerator->FillBuffer(iToneBuffer2->Data());
1.774 + if(err!=KErrNone)
1.775 + {
1.776 + DP0_RET(err, "%d");
1.777 + }
1.778 +
1.779 + // Assign active buffer
1.780 + iActiveToneBuffer = iToneBuffer1;
1.781 + DP0_RET(KErrNone, "%d");
1.782 + }
1.783 +
1.784 +/*
1.785 + *
1.786 + * This method assigns the other buffer as active buffer. The tone audio
1.787 + * generator should fill data in the other buffer by now.
1.788 + *
1.789 + */
1.790 +void CToneHwDevice::SetActiveToneBuffer()
1.791 + {
1.792 + if (iActiveToneBuffer == iToneBuffer1)
1.793 + iActiveToneBuffer = iToneBuffer2;
1.794 + else if (iActiveToneBuffer == iToneBuffer2)
1.795 + iActiveToneBuffer = iToneBuffer1;
1.796 + }
1.797 +
1.798 +
1.799 +void CToneHwDevice::FreeBuffers()
1.800 + {
1.801 + if(iToneBuffer1)
1.802 + {
1.803 + delete iToneBuffer1;
1.804 + iToneBuffer1 = NULL;
1.805 + }
1.806 + if(iToneBuffer2)
1.807 + {
1.808 + delete iToneBuffer2;
1.809 + iToneBuffer2 = NULL;
1.810 + }
1.811 + }
1.812 +
1.813 + /*
1.814 + *
1.815 + * Returns an integer representing Sampling Frequency the device is currently
1.816 + * configured to.
1.817 + *
1.818 + * @return "TInt"
1.819 + * Sampling Frequency.
1.820 + *
1.821 + */
1.822 +TInt CToneHwDevice::SamplingFrequency()
1.823 + {
1.824 + return iSampleRate;
1.825 + }
1.826 +
1.827 +/*
1.828 + *
1.829 + * Returns an integer representing number of channels the device is currently
1.830 + * configured to.
1.831 + *
1.832 + * @return "TInt"
1.833 + * Number of audio channels 1 if mono, 2 if stereo.
1.834 + *
1.835 + */
1.836 +TInt CToneHwDevice::NumberOfChannels()
1.837 + {
1.838 + if(iChannels == EMMFMono)
1.839 + return 1;
1.840 + else
1.841 + return 2;
1.842 + }
1.843 +
1.844 + /*
1.845 + *
1.846 + * This method fills data into the free buffer.
1.847 + *
1.848 + * @return "TInt"
1.849 + * Error code. KErrNone if success.
1.850 + *
1.851 + */
1.852 +TInt CToneHwDevice::FillFreeToneBuffer()
1.853 + {
1.854 + TInt err(KErrNone);
1.855 + if (iActiveToneBuffer == iToneBuffer1)
1.856 + {
1.857 + err = iCurrentGenerator->FillBuffer(iToneBuffer2->Data());
1.858 + }
1.859 + else if (iActiveToneBuffer == iToneBuffer2)
1.860 + {
1.861 + err = iCurrentGenerator->FillBuffer(iToneBuffer1->Data());
1.862 + }
1.863 + return err;
1.864 + }
1.865 +
1.866 +TBool CToneHwDevice::RecognizeSequence(const TDesC8& aData)
1.867 + {
1.868 + // Reference plug-in only supports its own sequence format
1.869 + _LIT8(KSequenceSignature,"SQNC");
1.870 + if (aData.Length() > 4)
1.871 + {
1.872 + if (aData.Left(4) == KSequenceSignature)
1.873 + {
1.874 + return ETrue;
1.875 + }
1.876 + }
1.877 + // Didn't recognise
1.878 + return EFalse;
1.879 + }
1.880 +
1.881 +TBool CToneHwDevice::ValidDTMFString(const TDesC& aDTMFString)
1.882 + {
1.883 + const TDesC* stringDTMF = &aDTMFString;;
1.884 + TInt stringPos = 0;
1.885 + if (stringPos == stringDTMF->Length())
1.886 + {
1.887 + return EFalse; // Finished. Nothing to do
1.888 + }
1.889 + do
1.890 + {
1.891 + TChar c((*stringDTMF)[stringPos++]);
1.892 + if (static_cast<TUint> (c)=='#' || static_cast<TUint> (c)=='*' || static_cast<TUint> (c)==',' || c.IsHexDigit() || c.IsSpace())
1.893 + {
1.894 + //Do nothing, valid character
1.895 + }
1.896 + else
1.897 + {
1.898 + return EFalse;
1.899 + }
1.900 +
1.901 + }
1.902 + while(stringPos < stringDTMF->Length());
1.903 + return ETrue;
1.904 + }
1.905 +
1.906 +
1.907 +/************************************************************************
1.908 + * TToneCustomInterface *
1.909 + ************************************************************************/
1.910 +/**
1.911 + * This method is not be exported as it is only
1.912 + * intended to be called within this DLL.
1.913 + * It's purpose is to assign an RMdaDevSound to the play
1.914 + * custom interface
1.915 + * @internalComponent
1.916 + */
1.917 +void TToneCustomInterface::SetDevice(RMdaDevSound* aDevice)
1.918 + {
1.919 + iDevice = aDevice;
1.920 + }
1.921 +
1.922 +void TToneCustomInterface::SetVolume(TUint aVolume)
1.923 + {
1.924 + iVolume = aVolume;
1.925 + if (iDevice && iDevice->Handle()!=0)
1.926 + {
1.927 + iDevice->SetPlayVolume(aVolume);
1.928 + }
1.929 + }
1.930 +
1.931 +/**
1.932 + * Procedure to get the number of bytes played by the device driver
1.933 + * If there is no handle available to the device driver then the
1.934 + * procedure returns the last known value
1.935 + * @released
1.936 + * @return number of bytes played
1.937 + */
1.938 +TUint TToneCustomInterface::BytesPlayed()
1.939 + {
1.940 + if(iDevice)
1.941 + {
1.942 + if (iDevice->Handle())
1.943 + {
1.944 + iBytesPlayed = iDevice->BytesPlayed();
1.945 + }
1.946 + }
1.947 + return iBytesPlayed;
1.948 + }
1.949 +
1.950 +
1.951 +//
1.952 +// class CToneCodec //
1.953 +//
1.954 +
1.955 +// ---------------------------------------------------------------------------
1.956 +// from class CToneCodec
1.957 +// CToneCodec::CToneCodec
1.958 +// ---------------------------------------------------------------------------
1.959 +//
1.960 +CToneCodec::CToneCodec()
1.961 + {
1.962 + }
1.963 +
1.964 +// ---------------------------------------------------------------------------
1.965 +// from class CToneCodec
1.966 +// CToneCodec::~CToneCodec
1.967 +// ---------------------------------------------------------------------------
1.968 +//
1.969 +CToneCodec::~CToneCodec()
1.970 + {
1.971 + }
1.972 +
1.973 +// ---------------------------------------------------------------------------
1.974 +// from class CToneCodec
1.975 +// CToneCodec::ConstructL
1.976 +// ---------------------------------------------------------------------------
1.977 +//
1.978 +void CToneCodec::ConstructL()
1.979 + {
1.980 + }
1.981 +
1.982 +
1.983 +// ---------------------------------------------------------------------------
1.984 +// from class CToneCodec
1.985 +// CToneCodec::ProcessL
1.986 +// ---------------------------------------------------------------------------
1.987 +//
1.988 +CToneCodec::TCodecProcessResult CToneCodec::ProcessL(const CMMFBuffer& /*aSource*/, CMMFBuffer& /*aDest*/)
1.989 + {
1.990 + //no processing required for null codec
1.991 + User::Leave(KErrNotSupported);
1.992 + //to keep compiler happy
1.993 + TCodecProcessResult result;
1.994 + result.iCodecProcessStatus = TCodecProcessResult::EEndOfData;
1.995 + result.iSrcBytesProcessed = 0;
1.996 + result.iDstBytesAdded = 0;
1.997 + return result;
1.998 + }
1.999 +
1.1000 +// ---------------------------------------------------------------------------
1.1001 +// from class CToneCodec
1.1002 +// CToneCodec::SourceBufferSize
1.1003 +// ---------------------------------------------------------------------------
1.1004 +//
1.1005 +TUint CToneCodec::SourceBufferSize()
1.1006 + {
1.1007 + return KPCM16ToPCM16BufferSize;
1.1008 + }
1.1009 +
1.1010 +// ---------------------------------------------------------------------------
1.1011 +// from class CToneCodec
1.1012 +// CToneCodec::SinkBufferSize
1.1013 +// ---------------------------------------------------------------------------
1.1014 +//
1.1015 +TUint CToneCodec::SinkBufferSize()
1.1016 + {
1.1017 + return KPCM16ToPCM16BufferSize;
1.1018 + }
1.1019 +
1.1020 +
1.1021 +// ========================== OTHER EXPORTED FUNCTIONS =========================
1.1022 +/**
1.1023 +* ImplementationGroupProxy
1.1024 +* is called to get a pointer to the plugin's implementation table, or table
1.1025 +* of functions used to instantiate the plugin.
1.1026 +* @since
1.1027 +* @param aTableCount returns the number of functions in the table.
1.1028 +* @return retuns a pointer to the table.
1.1029 +*/
1.1030 +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
1.1031 + {
1.1032 + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
1.1033 + return ImplementationTable;
1.1034 + }