os/mm/mmhais/refacladapt/src/tonehwdevice/tonehwdevice.cpp
changeset 0 bde4ae8d615e
     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 +	}