os/mm/devsound/sounddevbt/PlatSec/src/Server/AudioServer/MmfBtDevSoundSessionBody.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/mm/devsound/sounddevbt/PlatSec/src/Server/AudioServer/MmfBtDevSoundSessionBody.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1958 @@
     1.4 +// Copyright (c) 2001-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 <e32base.h>
    1.20 +#include "MmfBtDevSoundSessionBody.h"
    1.21 +#include "MmfBtDevSoundSessionXtnd.h"
    1.22 +
    1.23 +#include <mdaaudiotoneplayer.h>
    1.24 +#include <mmf/server/mmfdatabuffer.h>
    1.25 +#include <mmffourcc.h>
    1.26 +#include <mmfbthwdeviceimplementationuids.hrh>
    1.27 +#include <mmfbtswcodecwrappercustominterfacesuids.hrh> // KUidBtRefDevSoundTaskConfig
    1.28 +
    1.29 +
    1.30 +/*
    1.31 + *	AO to handle RSD initialisation
    1.32 + *
    1.33 + */
    1.34 +CRoutingSoundDeviceHandler* CRoutingSoundDeviceHandler::NewL(MDevSoundObserver* aObserver)
    1.35 +	{
    1.36 +	CRoutingSoundDeviceHandler* self = new(ELeave) CRoutingSoundDeviceHandler(aObserver);
    1.37 +	CleanupStack::PushL(self);
    1.38 +	self->ConstructL();
    1.39 +	CleanupStack::Pop(self);
    1.40 +	return self;
    1.41 +	}
    1.42 +	
    1.43 +CRoutingSoundDeviceHandler::~CRoutingSoundDeviceHandler()
    1.44 +	{
    1.45 +	Cancel();
    1.46 +	}
    1.47 +		
    1.48 +void CRoutingSoundDeviceHandler::RunL()
    1.49 +	{
    1.50 +	TInt err = iStatus.Int();
    1.51 +	if (iObserver)
    1.52 +		{
    1.53 +		iObserver->InitializeComplete(err);
    1.54 +		}		
    1.55 +	}
    1.56 +	
    1.57 +void CRoutingSoundDeviceHandler::DoCancel()
    1.58 +	{
    1.59 +	if (iObserver)
    1.60 +		{
    1.61 +		iObserver->InitializeComplete(KErrCancel);
    1.62 +		}
    1.63 +	}
    1.64 +	
    1.65 +CRoutingSoundDeviceHandler::CRoutingSoundDeviceHandler(MDevSoundObserver* aObserver) :
    1.66 +														CActive(EPriorityStandard),
    1.67 +													 	iObserver(aObserver)
    1.68 +	{
    1.69 +	CActiveScheduler::Add(this);	
    1.70 +	}
    1.71 +	
    1.72 +void CRoutingSoundDeviceHandler::ConstructL()
    1.73 +	{
    1.74 +	}
    1.75 +
    1.76 +void CRoutingSoundDeviceHandler::Start()
    1.77 +	{
    1.78 +	if (!IsActive())
    1.79 +		{
    1.80 +		SetActive();
    1.81 +		}
    1.82 +	}
    1.83 +	
    1.84 +/*
    1.85 + *
    1.86 + *	Default Constructor.
    1.87 + *
    1.88 + *	No default implementation. CMMFDevSoundProxy implements 2-phase construction.
    1.89 + *
    1.90 + */
    1.91 +CMMFDevSoundSvrImp::CMMFDevSoundSvrImp(CMMFDevSoundSessionXtnd* aParent)
    1.92 +: iParent(*aParent)
    1.93 +	{
    1.94 +	iMode= EMMFStateIdle;
    1.95 +	//Set reasonable default values for DTMF 
    1.96 +	iDTMFGen.SetToneDurations(250000,50000,250000);
    1.97 +	}
    1.98 +
    1.99 +/*
   1.100 + *
   1.101 + *	Destructor.
   1.102 + *
   1.103 + *	Deletes all objects and releases all resource owned by this
   1.104 + *	instance.
   1.105 + *
   1.106 + */
   1.107 +CMMFDevSoundSvrImp::~CMMFDevSoundSvrImp()
   1.108 +	{
   1.109 +	delete iRSDHandler;
   1.110 +	delete iToneBuffer1;
   1.111 +	delete iToneBuffer2;
   1.112 +	delete iDevSoundEventHandler; 
   1.113 +	if( iAudioPolicyProxy != NULL)
   1.114 +		{
   1.115 +		iAudioPolicyProxy->Close(); 
   1.116 +		delete iAudioPolicyProxy;
   1.117 +		}
   1.118 +	delete iDevSoundUtil;
   1.119 +	delete iFixedSequences;
   1.120 +	delete iCMMFHwDevice;
   1.121 +	}
   1.122 +
   1.123 +/*
   1.124 + *
   1.125 + *	Constructs, and returns a pointer to, a new CMMFDevSoundSvrImp object.
   1.126 + *
   1.127 + *	Leaves on failure.
   1.128 + *
   1.129 + */
   1.130 +CMMFDevSoundSvrImp* CMMFDevSoundSvrImp::NewL(CMMFDevSoundSessionXtnd* aParent)
   1.131 +	{
   1.132 +	CMMFDevSoundSvrImp* self = new (ELeave) CMMFDevSoundSvrImp(aParent);
   1.133 +	return self;
   1.134 +	}
   1.135 +
   1.136 +/*
   1.137 + *
   1.138 + *	3rd phase constructor - assumes that iParent has already been set up properly
   1.139 + *                          (During ConstructL() it has yet to be
   1.140 + *
   1.141 + */
   1.142 +void CMMFDevSoundSvrImp::Construct3L(RServer2& aPolicyServerHandle)
   1.143 +	{
   1.144 +	// all these data properties should be NULL, but add ASSERTs to verity
   1.145 +	ASSERT(iAudioPolicyProxy==NULL);
   1.146 +	iAudioPolicyProxy = new (ELeave) RMMFAudioPolicyProxy();
   1.147 +	ASSERT(iDevSoundEventHandler==NULL);
   1.148 +	iDevSoundEventHandler = CMMFDevSoundEventHandler::NewL(iAudioPolicyProxy);
   1.149 +	User::LeaveIfError(iAudioPolicyProxy->Open(aPolicyServerHandle));
   1.150 +	iDevSoundEventHandler->SetDevSoundInfo(&iParent);
   1.151 +
   1.152 +	iDevSoundUtil = CMMFDevSoundUtility::NewL();
   1.153 +	// Initialize Fixed sequence related
   1.154 +	iDevSoundUtil->InitializeFixedSequenceL(&iFixedSequences);
   1.155 +
   1.156 +	// Add RSD handler construction here.
   1.157 +	iRSDHandler = CRoutingSoundDeviceHandler::NewL(&iParent);
   1.158 +	
   1.159 +	PreInitializeL();
   1.160 +	}
   1.161 +
   1.162 +/**
   1.163 + * internal procedure to perform all initialization prior to setting the 
   1.164 + * data type 4CC code
   1.165 + */
   1.166 +void CMMFDevSoundSvrImp::PreInitializeL()
   1.167 +	{
   1.168 +	// Set default values for priority settings: Note: Client must 
   1.169 +	// over ride default settings by calling SetPrioirtySettings
   1.170 +	iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
   1.171 +	iAudioPolicyPrioritySettings.iPref = EMdaPriorityPreferenceNone;
   1.172 +	iAudioPolicyPrioritySettings.iPriority = 0;
   1.173 +
   1.174 +	// Get device capabilities and current settings from Audio Policy:
   1.175 +	iAudioPolicyProxy->GetPlayFormatsSupported(iPlayFormatsSupported);
   1.176 +	iAudioPolicyProxy->GetPlayFormat(iPlayFormat);
   1.177 +	iAudioPolicyProxy->GetRecordFormatsSupported(iRecordFormatsSupported);
   1.178 +	iAudioPolicyProxy->GetRecordFormat(iRecordFormat);
   1.179 +
   1.180 +	//default to play until we know we are recording
   1.181 +	User::LeaveIfError(InitializeFormat(iPlayFormatsSupported, iPlayFormat));
   1.182 +	}
   1.183 +
   1.184 +/*
   1.185 + *
   1.186 + *	Initializes CMMFDevSoundProxy object to play and record PCM16 raw audio data
   1.187 + *	with sampling rate of 8 KHz.
   1.188 + *
   1.189 + *	On completion of Initialization, calls InitializeComplete() on
   1.190 + *	aDevSoundObserver.
   1.191 + *
   1.192 + *	Leaves on failure.
   1.193 + *
   1.194 + *	@param	"MDevSoundObserver& aDevSoundObserver"
   1.195 + *			A reference to DevSound Observer instance.
   1.196 + *
   1.197 + *	@param	"TMMFState aMode"
   1.198 + *			Mode for which this object will be used.
   1.199 + *
   1.200 + */
   1.201 +void CMMFDevSoundSvrImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TMMFState aMode)
   1.202 +
   1.203 +	{
   1.204 +	// if no HwDevice id specified, load default null implementation
   1.205 +	TUid rawUid = {KMmfUidBtHwDevicePCM16ToPCM16};
   1.206 +	InitializeL(aDevSoundObserver, rawUid, aMode);
   1.207 +	}
   1.208 +
   1.209 +/*
   1.210 + *
   1.211 + *	Configure CMMFDevSoundProxy object for the settings in aConfig.
   1.212 + *
   1.213 + *	Use this to set sampling rate, Encoding and Mono/Stereo.
   1.214 + *
   1.215 + *	@param	"TMMFCapabilities& aConfig"
   1.216 + *			Attribute values to which CMMFDevSoundProxy object will be configured to.
   1.217 + *
   1.218 + *  As part of defect 20796, the iRecordFormat has been set under the iPlayFormat, 
   1.219 + *  before it was not set at all.
   1.220 + *
   1.221 + */
   1.222 +void CMMFDevSoundSvrImp::SetConfigL(const TMMFCapabilities& aConfig)
   1.223 +	{
   1.224 +	TUint attributeValue = aConfig.iRate;
   1.225 +	// WINS supports from 8000 Hz to 96000 Hz
   1.226 +	if (attributeValue & EMMFSampleRate96000Hz) 
   1.227 +		{ 
   1.228 +		iPlayFormat().iRate = 96000; 
   1.229 +		iRecordFormat().iRate = 96000;
   1.230 +		iDeviceConfig.iRate = EMMFSampleRate96000Hz;
   1.231 +		}
   1.232 +	else if (attributeValue & EMMFSampleRate88200Hz) 
   1.233 +		{ 
   1.234 +		iPlayFormat().iRate = 88200; 
   1.235 +		iRecordFormat().iRate = 88200;
   1.236 +		iDeviceConfig.iRate = EMMFSampleRate88200Hz;
   1.237 +		}
   1.238 +	else if (attributeValue & EMMFSampleRate64000Hz) 
   1.239 +		{ 
   1.240 +		iPlayFormat().iRate = 64000; 
   1.241 +		iRecordFormat().iRate = 64000;
   1.242 +		iDeviceConfig.iRate = EMMFSampleRate64000Hz;
   1.243 +		}
   1.244 +	else if (attributeValue & EMMFSampleRate48000Hz) 
   1.245 +		{ 
   1.246 +		iPlayFormat().iRate = 48000; 
   1.247 +		iRecordFormat().iRate = 48000;
   1.248 +		iDeviceConfig.iRate = EMMFSampleRate48000Hz;
   1.249 +		}
   1.250 +	else if (attributeValue & EMMFSampleRate44100Hz) 
   1.251 +		{ 
   1.252 +		iPlayFormat().iRate = 44100; 
   1.253 +		iRecordFormat().iRate = 44100;
   1.254 +		iDeviceConfig.iRate = EMMFSampleRate44100Hz;
   1.255 +		}
   1.256 +	else if (attributeValue & EMMFSampleRate32000Hz) 
   1.257 +		{ 
   1.258 +		iPlayFormat().iRate = 32000; 
   1.259 +		iRecordFormat().iRate = 32000; 
   1.260 +		iDeviceConfig.iRate = EMMFSampleRate32000Hz;
   1.261 +		}
   1.262 +	else if (attributeValue & EMMFSampleRate24000Hz)
   1.263 +		{
   1.264 +		iPlayFormat().iRate = 
   1.265 +		iRecordFormat().iRate = 24000;
   1.266 +		iDeviceConfig.iRate = EMMFSampleRate24000Hz;
   1.267 +		}
   1.268 +	else if (attributeValue & EMMFSampleRate22050Hz)
   1.269 +		{ 
   1.270 +		iPlayFormat().iRate = 22050; 
   1.271 +		iRecordFormat().iRate = 22050; 
   1.272 +		iDeviceConfig.iRate = EMMFSampleRate22050Hz;
   1.273 +		}
   1.274 +	else if (attributeValue & EMMFSampleRate16000Hz)
   1.275 +		{
   1.276 +		iPlayFormat().iRate = 16000;
   1.277 +		iRecordFormat().iRate = 16000; 
   1.278 +		iDeviceConfig.iRate = EMMFSampleRate16000Hz;
   1.279 +		}
   1.280 +	else if (attributeValue & EMMFSampleRate12000Hz)
   1.281 +		{
   1.282 +		iPlayFormat().iRate = 
   1.283 +		iRecordFormat().iRate = 12000;
   1.284 +		iDeviceConfig.iRate = EMMFSampleRate12000Hz;
   1.285 +		}
   1.286 +	else if (attributeValue & EMMFSampleRate11025Hz)
   1.287 +		{
   1.288 +		iPlayFormat().iRate = 11025;
   1.289 +		iRecordFormat().iRate = 11025;
   1.290 +		iDeviceConfig.iRate = EMMFSampleRate11025Hz;
   1.291 +		}
   1.292 +	else if (attributeValue & EMMFSampleRate8000Hz)
   1.293 +		{
   1.294 +		iPlayFormat().iRate = 8000;
   1.295 +		iRecordFormat().iRate = 8000;
   1.296 +		iDeviceConfig.iRate = EMMFSampleRate8000Hz;
   1.297 +		}
   1.298 +	else if (attributeValue) 
   1.299 +		{ //if no attribute value assume its not set
   1.300 +		User::Leave(KErrNotSupported);
   1.301 +		}
   1.302 +
   1.303 +	attributeValue = aConfig.iEncoding;
   1.304 +	// Map from MMF Encoding enums to RMdaDevSound enum
   1.305 +	if(attributeValue & EMMFSoundEncoding8BitPCM) 
   1.306 +		{
   1.307 +		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
   1.308 +		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
   1.309 +		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitPCM;
   1.310 +		}
   1.311 +	else if(attributeValue & EMMFSoundEncoding8BitALaw)
   1.312 +		{
   1.313 +		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
   1.314 +		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
   1.315 +		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitALaw;
   1.316 +		}
   1.317 +	else if(attributeValue & EMMFSoundEncoding8BitMuLaw) 
   1.318 +		{
   1.319 +		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
   1.320 +		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
   1.321 +		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitMuLaw;
   1.322 +		}
   1.323 +	else if(attributeValue & EMMFSoundEncoding16BitPCM)
   1.324 +		{
   1.325 +		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
   1.326 +		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
   1.327 +		iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
   1.328 +		}
   1.329 +	else if (attributeValue) 
   1.330 +		{ //if no attribute value assume its not set
   1.331 +		User::Leave(KErrNotSupported);
   1.332 +		}
   1.333 +
   1.334 +	// Mono/Stereo settings
   1.335 +	attributeValue = aConfig.iChannels;
   1.336 +	if(attributeValue & EMMFStereo) 
   1.337 +		{
   1.338 +		iPlayFormat().iChannels = 2;
   1.339 +		iRecordFormat().iChannels = 2;
   1.340 +		iDeviceConfig.iChannels = EMMFStereo;
   1.341 +		}
   1.342 +	else if(attributeValue & EMMFMono)
   1.343 +		{
   1.344 +		iPlayFormat().iChannels = 1;
   1.345 +		iRecordFormat().iChannels = 1;
   1.346 +		iDeviceConfig.iChannels = EMMFMono;
   1.347 +		}
   1.348 +	else if (attributeValue) 
   1.349 +		{ //if no attribute value assume its not set
   1.350 +		User::Leave(KErrNotSupported);
   1.351 +		}
   1.352 +	}
   1.353 +
   1.354 +/*
   1.355 + *
   1.356 + *	Changes the current playback volume to a specified value.
   1.357 + *
   1.358 + *	The volume can be changed before or during playback and is effective
   1.359 + *	immediately.
   1.360 + *
   1.361 + *	@param	"TInt aVolume"
   1.362 + *			The volume setting. This can be any value from zero to the value
   1.363 + *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
   1.364 + *			volume is not within this range, the volume is automatically set to
   1.365 + *			minimum or maximum value based on the value that is being passed.
   1.366 + *			Setting a zero value mutes the sound. Setting the maximum value
   1.367 + *			results in the loudest possible sound.
   1.368 + *
   1.369 + */
   1.370 +void CMMFDevSoundSvrImp::SetVolume(TInt aVolume)
   1.371 +	{
   1.372 +
   1.373 +	// Check and make sure that the volume is in valid range
   1.374 +	if (aVolume < 0)
   1.375 +		aVolume = 0;
   1.376 +
   1.377 +	if (aVolume > MaxVolume())
   1.378 +		aVolume = MaxVolume();
   1.379 +
   1.380 +	iVolume = aVolume;
   1.381 +
   1.382 +	SetDeviceVolume(iVolume);
   1.383 +	}
   1.384 +
   1.385 +/*
   1.386 + *
   1.387 + *	Changes the current recording gain to a specified value.
   1.388 + *
   1.389 + *	The gain can be changed before or during recording and is effective
   1.390 + *	immediately.
   1.391 + *
   1.392 + *	@param	"TInt aGain"
   1.393 + *			The volume setting. This can be any value from zero to the value
   1.394 + *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
   1.395 + *			volume is not within this range, the gain is automatically set to
   1.396 + *			minimum or maximum value based on the value that is being passed.
   1.397 + *			Setting a zero value mutes the sound. Setting the maximum value
   1.398 + *			results in the loudest possible sound.
   1.399 + *
   1.400 + */
   1.401 +void CMMFDevSoundSvrImp::SetGain(TInt aGain)
   1.402 +	{
   1.403 +	// make sure it falls with the correct range
   1.404 +	TInt maxGain = iRecordFormatsSupported().iMaxVolume;
   1.405 +	if (aGain > maxGain)
   1.406 +		aGain = maxGain;
   1.407 +	else if (aGain < 0)
   1.408 +		aGain = 0;
   1.409 +	iGain = aGain;
   1.410 +	SetDeviceRecordLevel(iGain);
   1.411 +	}
   1.412 +
   1.413 +/*
   1.414 + *
   1.415 + *	Sets the speaker balance for playing.
   1.416 + *
   1.417 + *	The speaker balance can be changed before or during playback and is
   1.418 + *	effective immediately.
   1.419 + *
   1.420 + *	@param	"TInt& aLeftPercentage"
   1.421 + *			On return contains left speaker volume perecentage. This can be any
   1.422 + *			value from zero to 100. Setting a zero value mutes the sound on left
   1.423 + *			speaker.
   1.424 + *
   1.425 + *	@param	"TInt& aRightPercentage"
   1.426 + *			On return contains right speaker volume perecentage. This can be any
   1.427 + *			value from zero to 100. Setting a zero value mutes the sound on
   1.428 + *			right speaker.
   1.429 + *
   1.430 + */
   1.431 +void CMMFDevSoundSvrImp::SetPlayBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
   1.432 +	{
   1.433 +	if (aLeftPercentage < 0)
   1.434 +		aLeftPercentage = 0;
   1.435 +	else if (aLeftPercentage > 100)
   1.436 +		aLeftPercentage = 100;
   1.437 +	if (aRightPercentage < 0)
   1.438 +		aRightPercentage = 0;
   1.439 +	else if (aRightPercentage > 100)
   1.440 +		aRightPercentage = 100;
   1.441 +	iLeftPlayBalance = aLeftPercentage;
   1.442 +	iRightPlayBalance = aRightPercentage;
   1.443 +	}
   1.444 +
   1.445 +/*
   1.446 + *
   1.447 + *	Sets the microphone gain balance for recording.
   1.448 + *
   1.449 + *	The microphone gain balance can be changed before or during recording and
   1.450 + *	is effective immediately.
   1.451 + *
   1.452 + *	@param	"TInt aLeftPercentage"
   1.453 + *			Left microphone gain precentage. This can be any value from zero to
   1.454 + *			100. Setting a zero value mutes the gain on left microphone.
   1.455 + *
   1.456 + *	@param	"TInt aRightPercentage"
   1.457 + *			Right microphone gain precentage. This can be any value from zero to
   1.458 + *			100. Setting a zero value mutes the gain on right microphone.
   1.459 + *
   1.460 + */
   1.461 +void CMMFDevSoundSvrImp::SetRecordBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
   1.462 +	{
   1.463 +	if (aLeftPercentage < 0)
   1.464 +		aLeftPercentage = 0;
   1.465 +	else if (aLeftPercentage > 100)
   1.466 +		aLeftPercentage = 100;
   1.467 +	if (aRightPercentage < 0)
   1.468 +		aRightPercentage = 0;
   1.469 +	else if (aRightPercentage > 100)
   1.470 +		aRightPercentage = 100;
   1.471 +	iLeftRecordBalance = aLeftPercentage;
   1.472 +	iRightRecordBalance = aRightPercentage;
   1.473 +	}
   1.474 +
   1.475 +/*
   1.476 + *
   1.477 + *	Initializes audio device and start play process. This method queries and
   1.478 + *	acquires the audio policy before initializing audio device. If there was an
   1.479 + *	error during policy initialization, PlayError() method will be called on
   1.480 + *	the observer with error code KErrAccessDenied, otherwise BufferToBeFilled()
   1.481 + *	method will be called with a buffer reference. After reading data into the
   1.482 + *	buffer reference passed, the client should call PlayData() to play data.
   1.483 + *
   1.484 + *	The amount of data that can be played is specified in
   1.485 + *	CMMFBuffer::RequestSize(). Any data that is read into buffer beyond this
   1.486 + *	size will be ignored.
   1.487 + *
   1.488 + *	Leaves on failure.
   1.489 + *
   1.490 + */
   1.491 +void CMMFDevSoundSvrImp::PlayInitL()
   1.492 +	{
   1.493 +	if (!iDevSoundObserver)
   1.494 +		User::Leave(KErrNotReady);
   1.495 +
   1.496 +	// Get audio policy
   1.497 +	iAudioPolicyPrioritySettings.iState = EMMFStatePlayData;
   1.498 +	RequestPolicy();
   1.499 +	}
   1.500 +
   1.501 +/*
   1.502 + *
   1.503 + *	Initializes audio device and start record process. 
   1.504 + *  This method:
   1.505 + *  1. Queries and acquires the audio policy before initializing audio device. 
   1.506 + *     If there was an error during policy initialization, RecordError() method will 
   1.507 + *     be called on the observer with error code KErrAccessDenied, otherwise BufferToBeEmptied()
   1.508 + *	   method will be called with a buffer reference. This buffer contains recorded
   1.509 + *	   or encoded data. After processing data in the buffer reference passed, the
   1.510 + *	   client should call RecordData() to continue recording process.
   1.511 + *
   1.512 + *  2. Checks if the requesting client process has a UserEnvironment capability.
   1.513 + *     If it does not, the audio device will not be initialized and an error 
   1.514 + *     code KErrAccessDenied will be sent to the client.
   1.515 + *
   1.516 + *	The amount of data that is available is specified in
   1.517 + *	CMMFBuffer::RequestSize().
   1.518 + *
   1.519 + *	Leaves on failure.
   1.520 + *
   1.521 + */
   1.522 +void CMMFDevSoundSvrImp::RecordInitL(const RMmfIpcMessage& aMessage)
   1.523 +	{
   1.524 +	if (!iDevSoundObserver)
   1.525 +		User::Leave(KErrNotReady);
   1.526 +	
   1.527 +	// Checkes if the client has the UserEnvironment capability
   1.528 +	if (!aMessage.HasCapability(ECapabilityUserEnvironment))
   1.529 +		{
   1.530 +		User::Leave(KErrPermissionDenied);
   1.531 +		}
   1.532 +	
   1.533 +	// Get audio policy
   1.534 +	iAudioPolicyPrioritySettings.iState = EMMFStateRecordData;
   1.535 +	RequestPolicy();
   1.536 +	}
   1.537 +
   1.538 +/*
   1.539 + *
   1.540 + *	Plays data in the buffer at the current volume. The client should fill
   1.541 + *	the buffer with audio data before calling this method. The Observer gets
   1.542 + *	reference to buffer along with callback BufferToBeFilled(). When playing of
   1.543 + *	the audio sample is complete, successfully or otherwise, the method
   1.544 + *	PlayError() on observer is called.
   1.545 + *
   1.546 + */
   1.547 +void CMMFDevSoundSvrImp::PlayData()
   1.548 +	{
   1.549 +	ASSERT(iDevSoundObserver);
   1.550 +
   1.551 +	if (iMode== EMMFStateIdle)
   1.552 +		return;
   1.553 +
   1.554 +	TInt error = KErrNone;
   1.555 +
   1.556 +    if(iCMMFHwDevice)
   1.557 +	    {
   1.558 +		if (iPaused)
   1.559 +			{
   1.560 +			iPaused = EFalse;
   1.561 +			//note PlayData does not leave or return an error code so the Start() fails we cannot
   1.562 +			//report the error back at this point
   1.563 +			error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);//restart hw device after pause
   1.564 +			}
   1.565 +	   else if(iMode== EMMFStatePlaying)
   1.566 +		    {
   1.567 +		    TInt len = iHwDeviceBuffer->Data().Length();
   1.568 +		    iPlayedBytesCount += len;
   1.569 +		    if (iHwDeviceBuffer->LastBuffer())
   1.570 +			    iLastBufferReceived = ETrue;
   1.571 +
   1.572 +
   1.573 +            if (iMode== EMMFStatePlaying)
   1.574 +                // Pass the data buffer to HwDevice
   1.575 +                error = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
   1.576 +            }
   1.577 +		}
   1.578 +	if (error != KErrNone)
   1.579 +		iDevSoundObserver->PlayError(error);
   1.580 +	}
   1.581 +
   1.582 +/*
   1.583 + *
   1.584 + *	Stops the ongoing operation (Play, Record, TonePlay, Convert)
   1.585 + *
   1.586 + */
   1.587 +void CMMFDevSoundSvrImp::Stop()
   1.588 +	{
   1.589 +	iPaused = EFalse;
   1.590 +
   1.591 +	if (iMode== EMMFStateIdle)
   1.592 +		return;
   1.593 +
   1.594 +	 // Stop the hw device first - this unloads sound drivers
   1.595 +    if(iCMMFHwDevice)
   1.596 +		iCMMFHwDevice->Stop();
   1.597 +
   1.598 +	iDevSoundEventHandler->CancelReceiveEvents();
   1.599 +
   1.600 +	iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
   1.601 +	UpdatePolicyState();
   1.602 +	}
   1.603 +
   1.604 +/*
   1.605 + *
   1.606 + *	Temporarily Stops the ongoing operation (Play, Record, TonePlay, Convert)
   1.607 + *
   1.608 + */
   1.609 +void CMMFDevSoundSvrImp::Pause()
   1.610 +	{
   1.611 +	iPaused = ETrue;
   1.612 +
   1.613 +	if (iMode== EMMFStateIdle)
   1.614 +		return;
   1.615 +
   1.616 +	// Pause the HW device first
   1.617 +	if(iCMMFHwDevice)
   1.618 +		iCMMFHwDevice->Pause();
   1.619 +	
   1.620 +	// defer policy update until buffers have been flushed
   1.621 +	if ((iMode == EMMFStatePlaying) || (iMode == EMMFStateTonePlaying))
   1.622 +		{
   1.623 +		iDevSoundEventHandler->CancelReceiveEvents();
   1.624 +		
   1.625 +		iAudioPolicyPrioritySettings.iState = EMMFStatePaused;
   1.626 +		UpdatePolicyState();
   1.627 +		}
   1.628 +	}
   1.629 +
   1.630 +/*
   1.631 + *
   1.632 + *	Returns the sample recorded so far.
   1.633 + *
   1.634 + *	@return "TInt"
   1.635 + *			Returns the samples recorded.
   1.636 + *
   1.637 + */
   1.638 +TInt CMMFDevSoundSvrImp::SamplesRecorded()
   1.639 +	{
   1.640 +	TInt samples = 0;
   1.641 +	
   1.642 +	if(iRecordCustomInterface)
   1.643 +		{
   1.644 +		samples = iRecordCustomInterface->BytesRecorded();
   1.645 +		if(NumberOfChannels() > 1)
   1.646 +			{
   1.647 +			samples /= NumberOfChannels();
   1.648 +			}
   1.649 +		if(BytesPerAudioSample() > 1)
   1.650 +			{
   1.651 +			samples /= BytesPerAudioSample();
   1.652 +			}
   1.653 +		}
   1.654 +
   1.655 +	return samples;
   1.656 +	}
   1.657 +
   1.658 +/*
   1.659 + *
   1.660 + *	Returns the sample played so far.
   1.661 + *
   1.662 + *	@return "TInt"
   1.663 + *			Returns the samples recorded.
   1.664 + *
   1.665 + */
   1.666 +TInt CMMFDevSoundSvrImp::SamplesPlayed()
   1.667 +	{
   1.668 +	TInt samples = 0;
   1.669 +	if(iPlayCustomInterface)
   1.670 +		{
   1.671 +		TUint bytesPlayed = iPlayCustomInterface->BytesPlayed();
   1.672 +		if (bytesPlayed)
   1.673 +			iPlayedBytesCount = bytesPlayed;
   1.674 +
   1.675 +		samples = iPlayedBytesCount;
   1.676 +		if(NumberOfChannels() > 1)
   1.677 +			samples /= NumberOfChannels();
   1.678 +
   1.679 +		if(BytesPerAudioSample() > 1)
   1.680 +			samples /= BytesPerAudioSample();
   1.681 +		}
   1.682 +	//note always pcm16 becuase the iPlayedBytesCount originates from 
   1.683 +	//RMdaDevSound which is always pcm16
   1.684 +	return samples; //each sample is 2 bytes
   1.685 +	}
   1.686 +
   1.687 +
   1.688 +/*
   1.689 + *
   1.690 + *	Initializes audio device and start playing tone. Tone is played with
   1.691 + *	frequency and for duration specified.
   1.692 + *
   1.693 + *	Leaves on failure.
   1.694 + *
   1.695 + *	@param	"TInt aFrequency"
   1.696 + *			Frequency at with the tone will be played.
   1.697 + *
   1.698 + *	@param	"TTimeIntervalMicroSeconds& aDuration"
   1.699 + *			The period over which the tone will be played. A zero value causes
   1.700 + *			the no tone to be played (Verify this with test app).
   1.701 + *
   1.702 + */
   1.703 +void CMMFDevSoundSvrImp::PlayToneL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration)
   1.704 +	{
   1.705 +	if (iMode!= EMMFStateTonePlaying)
   1.706 +		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
   1.707 +
   1.708 +	// Check whether frequency and duration is valid or not
   1.709 +	TInt64 zeroInt64(0);
   1.710 +	if ((aFrequency<0) || (aDuration.Int64() < zeroInt64))
   1.711 +		User::Leave(KErrArgument);
   1.712 +
   1.713 +	if (!iDevSoundObserver)
   1.714 +		User::Leave(KErrNotReady);
   1.715 +
   1.716 +	iToneGen.SetFrequencyAndDuration(aFrequency,aDuration);
   1.717 +
   1.718 +	// Get audio policy
   1.719 +	iAudioPolicyPrioritySettings.iState = EMMFStatePlayTone;
   1.720 +	RequestPolicy();
   1.721 +	}
   1.722 +
   1.723 +/*
   1.724 + *	Initializes audio device and start playing a dual tone. 
   1.725 + *  The tone consists of two sine waves of different frequencies summed together
   1.726 + *  Dual Tone is played with specified frequencies and for specified duration.
   1.727 + *
   1.728 + *	@param	"aFrequencyOne"
   1.729 + *			First frequency of dual tone
   1.730 + *
   1.731 + *	@param	"aFrequencyTwo"
   1.732 + *			Second frequency of dual tone
   1.733 + *
   1.734 + *	@param	"aDuration"
   1.735 + *			The period over which the tone will be played. A zero value causes
   1.736 + *			the no tone to be played (Verify this with test app).
   1.737 + */
   1.738 +void CMMFDevSoundSvrImp::PlayDualToneL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration)
   1.739 +	{
   1.740 +
   1.741 +	// Check whether frequencies and duration are valid or not
   1.742 +	TInt64 zeroInt64(0);
   1.743 +	if ((aFrequencyOne<0) || (aFrequencyTwo<0) || (aDuration.Int64() < zeroInt64))
   1.744 +		User::Leave(KErrArgument);
   1.745 +
   1.746 +	if (!iDevSoundObserver)
   1.747 +		User::Leave(KErrNotReady);
   1.748 +
   1.749 +	iDualToneGen.SetFrequencyAndDuration(aFrequencyOne, aFrequencyTwo, aDuration);
   1.750 +
   1.751 +	// Get audio policy
   1.752 +	iAudioPolicyPrioritySettings.iState = EMMFStatePlayDualTone;
   1.753 +	RequestPolicy();
   1.754 +	}
   1.755 +
   1.756 +/*
   1.757 + *
   1.758 + *	Initializes audio device and start playing DTMF string aDTMFString.
   1.759 + *
   1.760 + *	Leaves on failure.
   1.761 + *
   1.762 + *	@param	"TDesC& aDTMFString"
   1.763 + *			DTMF sequence in a descriptor.
   1.764 + *
   1.765 + */
   1.766 +void CMMFDevSoundSvrImp::PlayDTMFStringL(const TDesC& aDTMFString)
   1.767 +	{
   1.768 +	if (!iDevSoundObserver)
   1.769 +		User::Leave(KErrNotReady);
   1.770 +
   1.771 +	if (iMode!= EMMFStateTonePlaying)
   1.772 +		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
   1.773 +
   1.774 +	iDTMFGen.SetString(aDTMFString);
   1.775 +
   1.776 +	// Get audio policy
   1.777 +	iAudioPolicyPrioritySettings.iState = EMMFStatePlayDTMFString;
   1.778 +	RequestPolicy();
   1.779 +	}
   1.780 +
   1.781 +/*
   1.782 + *
   1.783 + *	Initializes audio device and start playing tone sequence.
   1.784 + *
   1.785 + *	Leaves on failure.
   1.786 + *
   1.787 + *	@param	"TDesC8& aData"
   1.788 + *			Tone sequence in a descriptor.
   1.789 + *
   1.790 + */
   1.791 +void CMMFDevSoundSvrImp::PlayToneSequenceL(const TDesC8& aData)
   1.792 +	{
   1.793 +	if (!iDevSoundObserver)
   1.794 +		User::Leave(KErrNotReady);
   1.795 +
   1.796 +	if (iMode!= EMMFStateTonePlaying)
   1.797 +		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
   1.798 +
   1.799 +	// Check whether the sequence is valid or not
   1.800 +	if (!iDevSoundUtil->RecognizeSequence(aData))
   1.801 +		User::Leave(KErrCorrupt);
   1.802 +
   1.803 +	iSequenceGen.SetSequenceData(aData);
   1.804 +
   1.805 +	// Get audio policy
   1.806 +	iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
   1.807 +	RequestPolicy();
   1.808 +	}
   1.809 +
   1.810 +/*
   1.811 + *
   1.812 + *	Initializes audio device and start playing the specified pre-defined tone
   1.813 + *	sequence.
   1.814 + *
   1.815 + *	Leaves on failure.
   1.816 + *
   1.817 + *	@param	"TInt aSequenceNumber"
   1.818 + *			The index identifying the specific pre-defined tone sequence. Index
   1.819 + *			values are relative to zero.
   1.820 + *			This can be any value from zero to the value returned by a call to
   1.821 + *			CMdaAudioPlayerUtility::FixedSequenceCount() - 1.
   1.822 + *			The function raises a panic if sequence number is not within this
   1.823 + *			range.
   1.824 + *
   1.825 + */
   1.826 +void CMMFDevSoundSvrImp::PlayFixedSequenceL(TInt aSequenceNumber)
   1.827 +	{
   1.828 +	if (!iDevSoundObserver)
   1.829 +		User::Leave(KErrNotReady);
   1.830 +
   1.831 +	if (iMode!= EMMFStateTonePlaying)
   1.832 +		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
   1.833 +
   1.834 +	ASSERT((aSequenceNumber >= 0)&&(aSequenceNumber < iFixedSequences->Count()));
   1.835 +
   1.836 +	iFixedSequence.Set(iFixedSequences->MdcaPoint(aSequenceNumber));
   1.837 +	iSequenceGen.SetSequenceData(iFixedSequence);
   1.838 +
   1.839 +	// Get audio policy
   1.840 +	iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
   1.841 +	RequestPolicy();
   1.842 +	}
   1.843 +
   1.844 +/*
   1.845 + *
   1.846 + *	Defines the duration of tone on, tone off and tone pause to be used during the
   1.847 + *	DTMF tone playback operation.
   1.848 + *
   1.849 + *	Supported only during tone playing.
   1.850 + *
   1.851 + *	@param	"TTimeIntervalMicroSeconds32& aToneOnLength"
   1.852 + *			The period over which the tone will be played. If this is set to
   1.853 + *			zero, then the tone is not played.
   1.854 + *
   1.855 + *	@param	"TTimeIntervalMicroSeconds32& aToneOffLength"
   1.856 + *			The period over which the no tone will be played.
   1.857 + *
   1.858 + *	@param	"TTimeIntervalMicroSeconds32& aPauseLength"
   1.859 + *			The period over which the tone playing will be paused.
   1.860 + *
   1.861 + */
   1.862 +void CMMFDevSoundSvrImp::SetDTMFLengths(TTimeIntervalMicroSeconds32& aToneOnLength,
   1.863 +								TTimeIntervalMicroSeconds32& aToneOffLength,
   1.864 +								TTimeIntervalMicroSeconds32& aPauseLength) 
   1.865 +	{
   1.866 +
   1.867 +	if(aToneOnLength.Int() < KMdaInfiniteDurationDTMFToneOnLength)
   1.868 +		aToneOnLength = TTimeIntervalMicroSeconds32(0);
   1.869 +	if(aToneOffLength.Int() < 0)
   1.870 +		aToneOffLength = TTimeIntervalMicroSeconds32(0);
   1.871 +	if(aPauseLength.Int() < 0)
   1.872 +		aPauseLength = TTimeIntervalMicroSeconds32(0);
   1.873 +
   1.874 +	iDTMFGen.SetToneDurations(aToneOnLength,aToneOffLength,aPauseLength);
   1.875 +	}
   1.876 +
   1.877 +/*
   1.878 + *
   1.879 + *	Defines the period over which the volume level is to rise smoothly from
   1.880 + *	nothing to the normal volume level.
   1.881 + *
   1.882 + *	@param	"TTimeIntervalMicroSeconds& aRampDuration"
   1.883 + *			The period over which the volume is to rise. A zero value causes 
   1.884 + *			the tone sample to be played at the normal level for the full
   1.885 + *			duration of the playback. A value, which is longer than the duration
   1.886 + *			of the tone sample, that the sample never reaches its normal
   1.887 + *			volume level.
   1.888 + *
   1.889 + *
   1.890 + */
   1.891 +void CMMFDevSoundSvrImp::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
   1.892 +	{
   1.893 +	// save ramp duration for tone generator
   1.894 +	iRampDuration = aRampDuration;
   1.895 +
   1.896 +	SetDeviceVolumeRamp(iRampDuration);
   1.897 +	}
   1.898 +
   1.899 +/**
   1.900 + *	Sets volume ramp on HwDevice.
   1.901 + */
   1.902 +TInt CMMFDevSoundSvrImp::SetDeviceVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
   1.903 +	{
   1.904 +	TInt error = KErrNone;
   1.905 +	if (iPlayCustomInterface) 
   1.906 +		iPlayCustomInterface->SetVolumeRamp(aRampDuration);
   1.907 +	else
   1.908 +		error = KErrNotReady;
   1.909 +	return error;
   1.910 +    }
   1.911 +
   1.912 +/**
   1.913 + *	@see sounddevice.h
   1.914 + */
   1.915 +void CMMFDevSoundSvrImp::GetSupportedInputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
   1.916 +	{
   1.917 +	//aPrioritySettings not used on ref DevSound
   1.918 +	//search for playing datatypes
   1.919 +	iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStatePlaying);
   1.920 +	}
   1.921 +
   1.922 +/**
   1.923 + *	@see sounddevice.h
   1.924 + */
   1.925 +void CMMFDevSoundSvrImp::GetSupportedOutputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
   1.926 +	{
   1.927 +	//aPrioritySettings not used on ref DevSound
   1.928 +	// search for recording datatypes
   1.929 +	iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStateRecording);
   1.930 +	}
   1.931 +	
   1.932 +TInt CMMFDevSoundSvrImp::RegisterAsClient(TUid aEventType, const TDesC8& aNotificationRegistrationData)
   1.933 +	{	
   1.934 +	return iAudioPolicyProxy->RequestResourceNotification(aEventType,aNotificationRegistrationData);
   1.935 +	}
   1.936 +	
   1.937 +TInt CMMFDevSoundSvrImp::CancelRegisterAsClient(TUid aEventType)
   1.938 +	{	
   1.939 +	return iAudioPolicyProxy->CancelRequestResourceNotification(aEventType);
   1.940 +	}
   1.941 +
   1.942 +TInt CMMFDevSoundSvrImp::GetResourceNotificationData(TUid aEventType, TDes8& aNotificationData)
   1.943 +	{	
   1.944 +	TInt err = KErrNone;
   1.945 +	err = iAudioPolicyProxy->IsRegisteredResourceNotification(aEventType);
   1.946 +	if(err == KErrNone)
   1.947 +		{
   1.948 +		aNotificationData.Num(SamplesPlayed());
   1.949 +		}
   1.950 +	return err;
   1.951 +	}
   1.952 +	
   1.953 +TInt CMMFDevSoundSvrImp::WillResumePlay()
   1.954 +	{
   1.955 +	return iAudioPolicyProxy->StopNotification();
   1.956 +	}	
   1.957 +
   1.958 +/********************************************************************************
   1.959 + *				Implementations of Non Exported public functions begins here	*
   1.960 + ********************************************************************************/
   1.961 +
   1.962 +//
   1.963 +//				Audio Policy specific implementation begins here				//
   1.964 +//
   1.965 +
   1.966 +/*
   1.967 + *
   1.968 + *	Called by Audio Policy Server when a request to play is approved by the 
   1.969 + *	Audio Policy Server.
   1.970 + *
   1.971 + *	Leaves on failure??.
   1.972 + *
   1.973 + */
   1.974 +void CMMFDevSoundSvrImp::StartPlayDataL()
   1.975 +	{
   1.976 +	ASSERT(iMode== EMMFStatePlaying);
   1.977 +
   1.978 +	TInt error = KErrNone;
   1.979 +
   1.980 +	if(iCMMFHwDevice)
   1.981 +		{
   1.982 +        // Set volume and play format values
   1.983 +        error = SetPlayFormat(iPlayFormat);
   1.984 +        if (error == KErrNone)
   1.985 +			error = SetDeviceVolume(iVolume);
   1.986 +        if (error == KErrNone)
   1.987 +			error = SetDeviceVolumeRamp(iRampDuration);
   1.988 +
   1.989 +		// Initialize attribute values
   1.990 +		iPlayedBytesCount = 0;
   1.991 +		iLastBufferReceived = EFalse;
   1.992 +
   1.993 +        // Start HwDevice
   1.994 +        if (error == KErrNone)
   1.995 +	        error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
   1.996 +		}
   1.997 +	else
   1.998 +		error = KErrNotReady;
   1.999 +
  1.1000 +	if (error != KErrNone)
  1.1001 +		iDevSoundObserver->PlayError(error);
  1.1002 +	}
  1.1003 +
  1.1004 +/*
  1.1005 + *
  1.1006 + *	Called by Audio Policy Server when a request to record is approved by the 
  1.1007 + *	Audio Policy Server.
  1.1008 + *
  1.1009 + *	Leaves on failure.
  1.1010 + *
  1.1011 + */
  1.1012 +void CMMFDevSoundSvrImp::StartRecordDataL()
  1.1013 +	{
  1.1014 +	ASSERT(iMode== EMMFStateRecording);
  1.1015 +
  1.1016 +	 if(iCMMFHwDevice)
  1.1017 +		{
  1.1018 +        TInt error = KErrNone;
  1.1019 +        error = SetRecordFormat(iRecordFormat);
  1.1020 +		if (error != KErrNone)
  1.1021 +			{
  1.1022 +			iDevSoundObserver->RecordError(error);
  1.1023 +			return;
  1.1024 +			}
  1.1025 +        error = SetDeviceRecordLevel(iGain);
  1.1026 +		if (error != KErrNone)
  1.1027 +			{
  1.1028 +			iDevSoundObserver->RecordError(error);
  1.1029 +			return;
  1.1030 +			}
  1.1031 +
  1.1032 +        // Initialize attribute values
  1.1033 +		iRecordedBytesCount = 0;
  1.1034 +
  1.1035 +        error = iCMMFHwDevice->Start(EDevEncode, EDevInFlow);
  1.1036 +		if (iHwDeviceBuffer)
  1.1037 +			iHwDeviceBuffer->SetLastBuffer(EFalse);
  1.1038 +
  1.1039 +		if (error != KErrNone)
  1.1040 +			{
  1.1041 +			iDevSoundObserver->RecordError(error);
  1.1042 +			return;
  1.1043 +			}
  1.1044 +        }
  1.1045 +	else
  1.1046 +		iDevSoundObserver->RecordError(KErrNotReady);
  1.1047 +	}
  1.1048 +
  1.1049 +/*
  1.1050 + *
  1.1051 + *	Called by Audio Policy Server when a request to play tone is approved by
  1.1052 + *	the Audio Policy Server.
  1.1053 + *
  1.1054 + *	Leaves on failure.
  1.1055 + *
  1.1056 + */
  1.1057 +void CMMFDevSoundSvrImp::StartPlayToneL()
  1.1058 +	{
  1.1059 +	ASSERT(iMode== EMMFStateTonePlaying);
  1.1060 +
  1.1061 +	 if(iCMMFHwDevice)
  1.1062 +		{
  1.1063 +        TInt error = KErrNone;
  1.1064 +        // Set volume and play format values
  1.1065 +        error = SetPlayFormat(iPlayFormat);
  1.1066 +		if (error != KErrNone)
  1.1067 +			{
  1.1068 +			iDevSoundObserver->ToneFinished(error);
  1.1069 +			return;
  1.1070 +			}
  1.1071 +        if (iHwDeviceID.iUid == KMmfUidBtHwDevicePCM16ToPCM16)
  1.1072 +            error = SetDeviceVolume(iVolume);
  1.1073 +		else
  1.1074 +			error = KErrGeneral;//hw device should always be pcm16 for tone
  1.1075 +
  1.1076 +		// turn off volume ramping - this is done in software below
  1.1077 +        if (error == KErrNone)
  1.1078 +			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
  1.1079 +
  1.1080 +        if (error != KErrNone)
  1.1081 +            {
  1.1082 +            iDevSoundObserver->ToneFinished(error);
  1.1083 +            return;
  1.1084 +            }
  1.1085 +
  1.1086 +        // Initialize attribute values
  1.1087 +		iPlayedBytesCount = 0;
  1.1088 +
  1.1089 +        // Configure tone generator
  1.1090 +        iToneGen.Configure(
  1.1091 +			iPlayFormat().iRate,
  1.1092 +			iPlayFormat().iChannels,
  1.1093 +		    iRepeatCount,
  1.1094 +			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
  1.1095 +			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
  1.1096 +			);
  1.1097 +
  1.1098 +		iCurrentGenerator = &iToneGen;
  1.1099 +
  1.1100 +        // Start playback
  1.1101 +        DoPlayL();
  1.1102 +               
  1.1103 +		}
  1.1104 +	else
  1.1105 +		iDevSoundObserver->ToneFinished(KErrNotReady);
  1.1106 +	}
  1.1107 +
  1.1108 +/*
  1.1109 + *
  1.1110 + *	Called by Audio Policy Server when a request to play a dual tone is approved by
  1.1111 + *	the Audio Policy Server.
  1.1112 + *
  1.1113 + */
  1.1114 +void CMMFDevSoundSvrImp::StartPlayDualToneL()
  1.1115 +	{
  1.1116 +	ASSERT(iMode== EMMFStateTonePlaying);
  1.1117 +
  1.1118 +	 if(iCMMFHwDevice)
  1.1119 +		{
  1.1120 +        TInt error = KErrNone;
  1.1121 +        // Set volume and play format values
  1.1122 +        error = SetPlayFormat(iPlayFormat);
  1.1123 +		if (error != KErrNone)
  1.1124 +			{
  1.1125 +			iDevSoundObserver->ToneFinished(error);
  1.1126 +			return;
  1.1127 +			}
  1.1128 +        if (iHwDeviceID.iUid == KMmfUidBtHwDevicePCM16ToPCM16)
  1.1129 +            error = SetDeviceVolume(iVolume);
  1.1130 +		else 
  1.1131 +			error = KErrGeneral;//hw device should always be pcm16 for tone
  1.1132 +
  1.1133 +		// turn off volume ramping - this is done in software below
  1.1134 +        if (error == KErrNone)
  1.1135 +			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
  1.1136 +
  1.1137 +        if (error != KErrNone)
  1.1138 +            {
  1.1139 +            iDevSoundObserver->ToneFinished(error);
  1.1140 +            return;
  1.1141 +            }
  1.1142 +
  1.1143 +        // Initialize attribute values
  1.1144 +		iPlayedBytesCount = 0;
  1.1145 +
  1.1146 +        // Configure dual tone generator
  1.1147 +		iDualToneGen.Configure(
  1.1148 +			iPlayFormat().iRate,
  1.1149 +			iPlayFormat().iChannels,
  1.1150 +			iRepeatCount,
  1.1151 +			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds),
  1.1152 +			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds)
  1.1153 +			);
  1.1154 +
  1.1155 +		iCurrentGenerator = &iDualToneGen;
  1.1156 +
  1.1157 +        // Start playback
  1.1158 +        DoPlayL();
  1.1159 +		}
  1.1160 +	else
  1.1161 +		iDevSoundObserver->ToneFinished(KErrNotReady);
  1.1162 +	}
  1.1163 +
  1.1164 +/*
  1.1165 + *
  1.1166 + *	Called by Audio Policy Server when a request to play DTMF String is approved
  1.1167 + *	by the Audio Policy Server.
  1.1168 + *
  1.1169 + *	Leaves on failure.
  1.1170 + *
  1.1171 + */
  1.1172 +void CMMFDevSoundSvrImp::StartPlayDTMFStringL()
  1.1173 +	{
  1.1174 +
  1.1175 +	ASSERT(iMode== EMMFStateTonePlaying);
  1.1176 +
  1.1177 +	if(iCMMFHwDevice)
  1.1178 +		{
  1.1179 +        TInt error = KErrNone;
  1.1180 +        // Set volume and play format values
  1.1181 +        error = SetPlayFormat(iPlayFormat);
  1.1182 +		if (error != KErrNone)
  1.1183 +            {
  1.1184 +            iDevSoundObserver->ToneFinished(error);
  1.1185 +            return;
  1.1186 +            }
  1.1187 +        error = SetDeviceVolume(iVolume);
  1.1188 +
  1.1189 +		// turn off volume ramping - this is done in software below
  1.1190 +        if (error == KErrNone)
  1.1191 +			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
  1.1192 +
  1.1193 +        if (error != KErrNone)
  1.1194 +            {
  1.1195 +            iDevSoundObserver->ToneFinished(error);
  1.1196 +            return;
  1.1197 +            }
  1.1198 +
  1.1199 +        // Initialize attribute values
  1.1200 +		iPlayedBytesCount = 0;
  1.1201 +
  1.1202 +	    iDTMFGen.Configure(
  1.1203 +			iPlayFormat().iRate,
  1.1204 +			iPlayFormat().iChannels,
  1.1205 +		    iRepeatCount,
  1.1206 +			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
  1.1207 +		    I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
  1.1208 +			);
  1.1209 +
  1.1210 +		iCurrentGenerator = &iDTMFGen;
  1.1211 +
  1.1212 +        // Start playback
  1.1213 +		//need to trap this as we can leave with KErrUnderflow
  1.1214 +		//if there was no data to play - the error has already
  1.1215 +		//been sent to the observer and we don't want to call RunError
  1.1216 +        TRAP(error,DoPlayL());
  1.1217 +		if ((error != KErrUnderflow)&&(error != KErrNone))
  1.1218 +			{
  1.1219 +			User::Leave(error);
  1.1220 +			}
  1.1221 +		}
  1.1222 +	else
  1.1223 +		iDevSoundObserver->ToneFinished(KErrNotReady);
  1.1224 +	}
  1.1225 +
  1.1226 +/*
  1.1227 + *
  1.1228 + *	Called by Audio Policy Server when a request to play tone sequence is
  1.1229 + *	approved by the Audio Policy Server.
  1.1230 + *
  1.1231 + *	Leaves on failure.
  1.1232 + *
  1.1233 + */
  1.1234 +void CMMFDevSoundSvrImp::StartPlayToneSequenceL()
  1.1235 +	{
  1.1236 +	ASSERT(iMode== EMMFStateTonePlaying);
  1.1237 +
  1.1238 +	if(iCMMFHwDevice)
  1.1239 +		{
  1.1240 +        TInt error = KErrNone;
  1.1241 +        // Set volume and play format values
  1.1242 +        if (iHwDeviceID.iUid == KMmfUidBtHwDevicePCM16ToPCM16)
  1.1243 +            error = SetPlayFormat(iPlayFormat);
  1.1244 +			else error = KErrGeneral;//hw device should always be pcm16 for tone
  1.1245 +		if (error != KErrNone)
  1.1246 +            {
  1.1247 +            iDevSoundObserver->ToneFinished(error);
  1.1248 +            return;
  1.1249 +            }
  1.1250 +
  1.1251 +        if (iHwDeviceID.iUid == KMmfUidBtHwDevicePCM16ToPCM16)
  1.1252 +            error = SetDeviceVolume(iVolume);
  1.1253 +		else 
  1.1254 +			error = KErrGeneral;//hw device should always be pcm16 for tone
  1.1255 +
  1.1256 +		// turn off volume ramping - this is done in software below
  1.1257 +        if (error == KErrNone)
  1.1258 +			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
  1.1259 +
  1.1260 +        if (error != KErrNone)
  1.1261 +            {
  1.1262 +            iDevSoundObserver->ToneFinished(error);
  1.1263 +            return;
  1.1264 +            }
  1.1265 +
  1.1266 +        // Initialize attribute values
  1.1267 +		iPlayedBytesCount = 0;
  1.1268 +
  1.1269 +		iSequenceGen.Configure(
  1.1270 +			iPlayFormat().iRate,
  1.1271 +			iPlayFormat().iChannels,
  1.1272 +			iRepeatCount,
  1.1273 +			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
  1.1274 +			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
  1.1275 +			);
  1.1276 +
  1.1277 +		iCurrentGenerator = &iSequenceGen;
  1.1278 +
  1.1279 +        // Start playback
  1.1280 +        DoPlayL();
  1.1281 +		}
  1.1282 +	else
  1.1283 +		iDevSoundObserver->ToneFinished(KErrNotReady);
  1.1284 +	}
  1.1285 +
  1.1286 +/*
  1.1287 + *
  1.1288 + *	Called by Audio Policy Server when the current DevSound instance looses the
  1.1289 + *	policy because of another instance with a higher priority wants the device.
  1.1290 + *
  1.1291 + */
  1.1292 +void CMMFDevSoundSvrImp::SendEventToClient(const TMMFEvent& aEvent)
  1.1293 +	{
  1.1294 +	switch (iMode)
  1.1295 +		{
  1.1296 +		case EMMFStatePlaying:
  1.1297 +		case EMMFStateTonePlaying:
  1.1298 +		case EMMFStatePlayToneSequence:
  1.1299 +		case EMMFStateRecording:
  1.1300 +			{
  1.1301 +			Error(aEvent.iErrorCode);//Updates Bytes played informs client
  1.1302 +			iCMMFHwDevice->Stop();//unloads sound device
  1.1303 +			Stopped();//Updates policy		
  1.1304 +			iMode = EMMFStateIdle;
  1.1305 +			iAudioPolicyProxy->LaunchRequests();
  1.1306 +			break;
  1.1307 +			}
  1.1308 +		case EMMFStateIdle:
  1.1309 +			{	
  1.1310 +			iMode = EMMFStatePlaying;
  1.1311 +			iDevSoundObserver->SendEventToClient(aEvent);
  1.1312 +			break;
  1.1313 +			}
  1.1314 +		default:
  1.1315 +			break;
  1.1316 +		}
  1.1317 +	// Have audio Policy launch higher priority request:
  1.1318 +	}
  1.1319 +
  1.1320 +
  1.1321 +/**
  1.1322 + *
  1.1323 + *	Sets volume on HwDevice.
  1.1324 + *	
  1.1325 + *	@return	"TInt"
  1.1326 + *			Error value returned by HwDevice.
  1.1327 + *
  1.1328 + */
  1.1329 +TInt CMMFDevSoundSvrImp::SetDeviceVolume(TInt aVolume)
  1.1330 +	{
  1.1331 +	TInt error = KErrNone;
  1.1332 +	if (iPlayCustomInterface) 
  1.1333 +		iPlayCustomInterface->SetVolume(aVolume);
  1.1334 +	else error = KErrNotReady;
  1.1335 +	return error;
  1.1336 +    }
  1.1337 +
  1.1338 +/**
  1.1339 + *
  1.1340 + *	Sets PlayFormat on HwDevice.
  1.1341 + *	
  1.1342 + *
  1.1343 + *	@return	"TInt"
  1.1344 + *			Error value returned by HwDevice.
  1.1345 + *
  1.1346 + */
  1.1347 +TInt CMMFDevSoundSvrImp::SetPlayFormat(RMdaDevSound::TCurrentSoundFormatBuf& aPlayFormat)
  1.1348 +	{
  1.1349 +	TInt error = KErrNone;
  1.1350 +	if (iCMMFHwDevice)
  1.1351 +		{
  1.1352 +		TTaskConfig taskConfig;
  1.1353 +		taskConfig.iUid = KUidBtRefDevSoundTaskConfig;
  1.1354 +		taskConfig.iRate = aPlayFormat().iRate;
  1.1355 +		
  1.1356 +		if (aPlayFormat().iChannels == 1)
  1.1357 +			{
  1.1358 +			taskConfig.iStereoMode = ETaskMono;
  1.1359 +			}
  1.1360 +		else if (aPlayFormat().iChannels == 2)
  1.1361 +			{
  1.1362 +			taskConfig.iStereoMode = ETaskInterleaved;
  1.1363 +			}
  1.1364 +		else
  1.1365 +			{
  1.1366 +			return KErrArgument;
  1.1367 +			}
  1.1368 +
  1.1369 +		error = iCMMFHwDevice->SetConfig(taskConfig);
  1.1370 +		//note the iEncoding and iBufferSize are already determined by the 
  1.1371 +		//CMMFHwDevice plugin and so are not set.
  1.1372 +		}
  1.1373 +	else
  1.1374 +		{
  1.1375 +		error = KErrNotReady;
  1.1376 +		}
  1.1377 +	return error;
  1.1378 +    }
  1.1379 +
  1.1380 +
  1.1381 +/**
  1.1382 + *
  1.1383 + *	Sets RecordFormat on HwDevice.
  1.1384 + *	
  1.1385 + *
  1.1386 + *	@return	"TInt"
  1.1387 + *			Error value returned by HwDevice.
  1.1388 + *
  1.1389 + */
  1.1390 +TInt CMMFDevSoundSvrImp::SetRecordFormat(RMdaDevSound::TCurrentSoundFormatBuf& aRecordFormat)
  1.1391 +	{
  1.1392 +	TInt error = KErrNone;
  1.1393 +	if (iCMMFHwDevice)
  1.1394 +		{
  1.1395 +		TTaskConfig taskConfig;
  1.1396 +		taskConfig.iUid = KUidBtRefDevSoundTaskConfig;
  1.1397 +		taskConfig.iRate = aRecordFormat().iRate;
  1.1398 +
  1.1399 +		if (aRecordFormat().iChannels == 1)
  1.1400 +			{
  1.1401 +			taskConfig.iStereoMode = ETaskMono;
  1.1402 +			}
  1.1403 +		else if (aRecordFormat().iChannels == 2)
  1.1404 +			{
  1.1405 +			taskConfig.iStereoMode = ETaskInterleaved;
  1.1406 +			}
  1.1407 +		else
  1.1408 +			{
  1.1409 +			return KErrArgument;
  1.1410 +			}
  1.1411 +
  1.1412 +		error = iCMMFHwDevice->SetConfig(taskConfig);
  1.1413 +		//note the iEncoding and iBufferSize are already determined by the 
  1.1414 +		//CMMFHwDevice plugin and so are not set.
  1.1415 +		}
  1.1416 +	else
  1.1417 +		{
  1.1418 +		error = KErrNotReady;
  1.1419 +		}
  1.1420 +	return error;
  1.1421 +    }
  1.1422 +
  1.1423 +
  1.1424 +/**
  1.1425 + *
  1.1426 + *	Sets record level on HwDevice.
  1.1427 + *	
  1.1428 + *
  1.1429 + *	@return	"TInt"
  1.1430 + *			Error value returned by HwDevice.
  1.1431 + *
  1.1432 + */
  1.1433 +TInt CMMFDevSoundSvrImp::SetDeviceRecordLevel(TInt aGain)
  1.1434 +	{
  1.1435 +	TInt error = KErrNone;
  1.1436 +	if (iRecordCustomInterface) 
  1.1437 +		iRecordCustomInterface->SetGain(aGain);
  1.1438 +	else error = KErrNotReady;
  1.1439 +	return error;
  1.1440 +
  1.1441 +    }
  1.1442 +
  1.1443 +
  1.1444 +/**
  1.1445 + *
  1.1446 + *	MMMFHwDeviceObserver mixin implementation.
  1.1447 + *
  1.1448 + *	The CMMFHwDevice implementation object calls this method during decoding
  1.1449 + *	(playing), when it needs the encoded data in the buffer
  1.1450 + *	aHwDataBuffer.
  1.1451 + *
  1.1452 + *	@return	"TInt"
  1.1453 + *			Error code. KErrNone if success.
  1.1454 + *
  1.1455 + */
  1.1456 +TInt CMMFDevSoundSvrImp::FillThisHwBuffer(CMMFBuffer& aHwDataBuffer)
  1.1457 +	{
  1.1458 +	TInt err = KErrNone;
  1.1459 +    // Keep a reference to this Hw data Buffer. We need to send the 
  1.1460 +	// reference back to HwDevice implementation
  1.1461 +	iHwDeviceBuffer = static_cast<CMMFDataBuffer*> (&aHwDataBuffer);
  1.1462 +	// Set the request length, From HwDevice this comes with buffer
  1.1463 +	// length.
  1.1464 +	TInt len = iHwDeviceBuffer->Data().MaxLength();
  1.1465 +	// Ignore error. since buffer size = Buffer Length 
  1.1466 +	TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
  1.1467 +
  1.1468 +	if (iMode== EMMFStatePlaying) // Get Data from Observer
  1.1469 +		{
  1.1470 +		if (iLastBufferReceived)
  1.1471 +			{
  1.1472 +			iHwDeviceBuffer->Data().SetLength(0);
  1.1473 +			// Pass the buffer to the he device
  1.1474 +            err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
  1.1475 +			}
  1.1476 +		else
  1.1477 +			// Pass the buffer to the observer
  1.1478 +			iDevSoundObserver->BufferToBeFilled(&aHwDataBuffer);
  1.1479 +		}
  1.1480 +	else if (iMode== EMMFStateTonePlaying)
  1.1481 +		{
  1.1482 +        // Hw device will call this method right after its Start was called.
  1.1483 +        // When it calls this for the first time it hasn't played one single
  1.1484 +        // buffer yet so check that.
  1.1485 +        // In this case there's no need to set the active buffer as it's already
  1.1486 +        // waiting to be played.
  1.1487 +        if (!iFirstCallFromHwDevice)
  1.1488 +            SetActiveToneBuffer();
  1.1489 +
  1.1490 +		// If there is no data in the active buffer, tone play is finished.
  1.1491 +		// DevSound just have to wait for completion event from audio device.
  1.1492 +		if (iActiveToneBuffer->Data().Length() > 0)
  1.1493 +            { 
  1.1494 +			TInt tonelen = iActiveToneBuffer->Data().Length();
  1.1495 +
  1.1496 +			// don't enter more data than can be handled by the receiving buffer
  1.1497 +			if (len >= tonelen) len = tonelen;
  1.1498 +
  1.1499 +            // Copy data from tone buffer to hw device buffer
  1.1500 +            Mem::Copy((TAny*)(iHwDeviceBuffer->Data().Ptr()), (TAny*)(iActiveToneBuffer->Data().Ptr()), len);
  1.1501 +            
  1.1502 +            iHwDeviceBuffer->Data().SetLength(len);
  1.1503 +            // Play data and try to generate next data block
  1.1504 +			err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
  1.1505 +            if (err != KErrNone)
  1.1506 +            	return err;
  1.1507 +            // Check again whether this is the first call from Hw device.
  1.1508 +            // FillFreeToneBuffer assumes the iActiveToneBuffer has already
  1.1509 +            // been played.
  1.1510 +            if (!iFirstCallFromHwDevice)
  1.1511 +                err = FillFreeToneBuffer();
  1.1512 +            else
  1.1513 +                iFirstCallFromHwDevice = EFalse;  // Reset flag
  1.1514 +
  1.1515 + 			}
  1.1516 +		else if (iFirstCallFromHwDevice)
  1.1517 +			{//we have no data in the tone buffer and thus have no 
  1.1518 +			//outstanding requests to play
  1.1519 +			err = KErrUnderflow; //simulate underrun
  1.1520 +			}
  1.1521 +
  1.1522 +	
  1.1523 +		// If there was an error filling the buffer could be corrupt data
  1.1524 +		// notify the client and stop playing.Set err to KErrNone. 
  1.1525 +		if (err != KErrNone)
  1.1526 +			{
  1.1527 +			Error(err);//Updates Bytes played informs client
  1.1528 +			err = KErrNone;
  1.1529 +			iCMMFHwDevice->Stop();//unloads sound device
  1.1530 +			Stopped();//Updates policy
  1.1531 +            }
  1.1532 +		}
  1.1533 +	else
  1.1534 +		{
  1.1535 +		err = KErrGeneral;
  1.1536 +		iDevSoundObserver->PlayError(KErrGeneral);
  1.1537 +		}
  1.1538 +	return err;
  1.1539 +	}
  1.1540 +
  1.1541 +
  1.1542 +/**
  1.1543 + *
  1.1544 + *	MMMFHwDeviceObserver mixin implementation.
  1.1545 + *
  1.1546 + *	The CMMFHwDevice implementation object calls this method during encoding
  1.1547 + *	(recording), when it fills the buffer aHwDataBuffer with
  1.1548 + *	encoded data.
  1.1549 + *
  1.1550 + *	@return	"TInt"
  1.1551 + *			Error code. KErrNone if success.
  1.1552 + *
  1.1553 + */
  1.1554 +TInt CMMFDevSoundSvrImp::EmptyThisHwBuffer(CMMFBuffer& aHwDataBuffer)
  1.1555 +	{
  1.1556 +	TInt err = KErrNone;
  1.1557 +	if(iMode== EMMFStateRecording)
  1.1558 +		{
  1.1559 +		// Keep a reference to this Hw data Buffer. We need to send the 
  1.1560 +		// reference back to HwDevice implementation
  1.1561 +		iHwDeviceBuffer = static_cast<CMMFDataBuffer*>(&aHwDataBuffer);
  1.1562 +
  1.1563 +		// Set the request length, From HwDevice this comes with buffer
  1.1564 +		// length. MMF will use RequestSize attribute of the buffer.
  1.1565 +		// We can avoid this by setting in HwDevice implemenation
  1.1566 +		TInt len = iHwDeviceBuffer->Data().Length();
  1.1567 +		iRecordedBytesCount += len;
  1.1568 +		TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
  1.1569 +	
  1.1570 +		// if we're pausing (i.e. flushing) set the last buffer flag
  1.1571 +		// when we get an empty buffer from the logical driver
  1.1572 +		if(iPaused  && iHwDeviceBuffer->Data().Length() == 0)
  1.1573 +		{
  1.1574 +		iPaused = EFalse;
  1.1575 +
  1.1576 +		iHwDeviceBuffer->SetLastBuffer(ETrue);
  1.1577 +
  1.1578 +		iDevSoundEventHandler->CancelReceiveEvents();
  1.1579 +
  1.1580 +		iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
  1.1581 +		UpdatePolicyState();
  1.1582 +		}
  1.1583 +
  1.1584 +		// Send Data from Observer
  1.1585 +		iDevSoundObserver->BufferToBeEmptied(iHwDeviceBuffer);
  1.1586 +		}
  1.1587 +	else
  1.1588 +		{
  1.1589 +		err = KErrGeneral;
  1.1590 +		iDevSoundObserver->RecordError(KErrGeneral);
  1.1591 +		}
  1.1592 +
  1.1593 +	return err;
  1.1594 +	}
  1.1595 +
  1.1596 +
  1.1597 +/**
  1.1598 + *
  1.1599 + *	MMMFHwDeviceObserver mixin implementation.
  1.1600 + *
  1.1601 + *	The CMMFHwDevice implementation object calls this method when a message from
  1.1602 + *	the hardware device implementation is received.
  1.1603 + *
  1.1604 + *	@return	"TInt"
  1.1605 + *			Error code. KErrNone if success.
  1.1606 + *
  1.1607 + */
  1.1608 +TInt CMMFDevSoundSvrImp::MsgFromHwDevice(TUid aMessageType, const TDesC8& /*aMsg*/)
  1.1609 +	{
  1.1610 +	TInt result = KErrNotSupported;
  1.1611 +	if (aMessageType.iUid == KMmfHwDeviceObserverUpdateBytesPlayed)
  1.1612 +		{//this is used by sw codec wrapper to request a bytes played update
  1.1613 +		//bytes played won't be updated in Stopped() or Error() on sw cdoec wrapper
  1.1614 +		//as the sound device is closed. Non swCodec wrapper Hw device plugins
  1.1615 +		//can get there bytes updated on Stopped() and/or Error()
  1.1616 +		UpdateBytesPlayed();
  1.1617 +		result = KErrNone;
  1.1618 +		}
  1.1619 +	return result;
  1.1620 +	}
  1.1621 +
  1.1622 +/**
  1.1623 + *
  1.1624 + *	MMMFHwDeviceObserver mixin implementation.
  1.1625 + *
  1.1626 + *	The CMMFHwDevice implementation object calls this method when the current
  1.1627 + *	encode or decode task is finished or stopped.  The policy state is updated
  1.1628 + *
  1.1629 + */
  1.1630 +void CMMFDevSoundSvrImp::Stopped()
  1.1631 +	{
  1.1632 +	//for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
  1.1633 +	//but non Swcodec wrappers hw devices may do it differently
  1.1634 +	//also don't know if non Swcodec wrap hw device will call Stopped or Error first
  1.1635 +	UpdateBytesPlayed();
  1.1636 +
  1.1637 +	iLastBufferReceived = EFalse;
  1.1638 +	iAudioPolicyPrioritySettings.iState = EMMFStateCompleted;
  1.1639 +	UpdatePolicyState();
  1.1640 +	}
  1.1641 +
  1.1642 +/**
  1.1643 + *  MMMFHwDeviceObserver mixin implementation
  1.1644 + *  Processes error from hw device
  1.1645 + */
  1.1646 +void CMMFDevSoundSvrImp::Error(TInt aError)
  1.1647 +	{
  1.1648 +	if (iMode== EMMFStatePlaying)
  1.1649 +		{
  1.1650 +		//for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
  1.1651 +		//but non Swcodec wrappers hw devices may do it differently
  1.1652 +		//also don't know if non Swcodec wrap hw device will call Stopped or Error first
  1.1653 +		UpdateBytesPlayed();
  1.1654 +
  1.1655 +        	iDevSoundObserver->PlayError(aError);		
  1.1656 +        	iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
  1.1657 +        	UpdatePolicyState();
  1.1658 +		}
  1.1659 +	else if (iMode== EMMFStateRecording)
  1.1660 +		{
  1.1661 +        iDevSoundObserver->RecordError(aError);
  1.1662 +		}
  1.1663 +	else if (iMode== EMMFStateTonePlaying)
  1.1664 +		{
  1.1665 +        iDevSoundObserver->ToneFinished(aError);
  1.1666 +		}
  1.1667 +	//else can't handle error
  1.1668 +	}
  1.1669 +
  1.1670 +
  1.1671 +/********************************************************************************
  1.1672 + *				Non Exported public functions ends here							*
  1.1673 + ********************************************************************************/
  1.1674 +
  1.1675 +
  1.1676 +/********************************************************************************
  1.1677 + *				Private functions begins here									*
  1.1678 + ********************************************************************************/
  1.1679 +
  1.1680 +TInt CMMFDevSoundSvrImp::InitializeFormat(RMdaDevSound::TSoundFormatsSupportedBuf& aSupportedFormat,
  1.1681 +		RMdaDevSound::TCurrentSoundFormatBuf& aFormat)
  1.1682 +	{
  1.1683 +	// Choose an encoding
  1.1684 +	TUint32 enc = aSupportedFormat().iEncodings;
  1.1685 +	// Always defaults to this
  1.1686 +	if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
  1.1687 +		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
  1.1688 +	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
  1.1689 +		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
  1.1690 +	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
  1.1691 +		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
  1.1692 +	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
  1.1693 +		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
  1.1694 +
  1.1695 +	// default to Monophonic playback:
  1.1696 +	aFormat().iChannels=1;
  1.1697 +
  1.1698 +	// Store the device capabilities (WINS supports from 8000 Hz to 44100 Hz)
  1.1699 +	if ((aSupportedFormat().iMinRate <= 8000) && (8000 <= aSupportedFormat().iMaxRate))
  1.1700 +		iDeviceCapabilities.iRate = EMMFSampleRate8000Hz;
  1.1701 +	if ((aSupportedFormat().iMinRate <= 11025) && (11025 <= aSupportedFormat().iMaxRate))
  1.1702 +		iDeviceCapabilities.iRate |= EMMFSampleRate11025Hz;
  1.1703 +	if ((aSupportedFormat().iMinRate <= 12000) && (12000 <= aSupportedFormat().iMaxRate))
  1.1704 +		iDeviceCapabilities.iRate |= EMMFSampleRate12000Hz;
  1.1705 +	if ((aSupportedFormat().iMinRate <= 16000) && (16000 <= aSupportedFormat().iMaxRate))
  1.1706 +		iDeviceCapabilities.iRate |= EMMFSampleRate16000Hz;
  1.1707 +	if ((aSupportedFormat().iMinRate <= 22050) && (22050 <= aSupportedFormat().iMaxRate))
  1.1708 +		iDeviceCapabilities.iRate |= EMMFSampleRate22050Hz;
  1.1709 +	if ((aSupportedFormat().iMinRate <= 24000) && (24000 <= aSupportedFormat().iMaxRate))
  1.1710 +		iDeviceCapabilities.iRate |= EMMFSampleRate24000Hz;
  1.1711 +	if ((aSupportedFormat().iMinRate <= 32000) && (32000 <= aSupportedFormat().iMaxRate))
  1.1712 +		iDeviceCapabilities.iRate |= EMMFSampleRate32000Hz;
  1.1713 +	if ((aSupportedFormat().iMinRate <= 44100) && (44100 <= aSupportedFormat().iMaxRate))
  1.1714 +		iDeviceCapabilities.iRate |= EMMFSampleRate44100Hz;
  1.1715 +	if ((aSupportedFormat().iMinRate <= 48000) && (48000 <= aSupportedFormat().iMaxRate))
  1.1716 +		iDeviceCapabilities.iRate |= EMMFSampleRate48000Hz;
  1.1717 +	if ((aSupportedFormat().iMinRate <= 64000) && (64000 <= aSupportedFormat().iMaxRate))
  1.1718 +		iDeviceCapabilities.iRate |= EMMFSampleRate64000Hz;
  1.1719 +	if ((aSupportedFormat().iMinRate <= 88200) && (88200 <= aSupportedFormat().iMaxRate))
  1.1720 +		iDeviceCapabilities.iRate |= EMMFSampleRate88200Hz;
  1.1721 +	if ((aSupportedFormat().iMinRate <= 96000) && (96000 <= aSupportedFormat().iMaxRate))
  1.1722 +		iDeviceCapabilities.iRate |= EMMFSampleRate96000Hz;
  1.1723 +
  1.1724 +	// Store the encodings supported
  1.1725 +	iDeviceCapabilities.iEncoding = 0;
  1.1726 +	if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
  1.1727 +		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding16BitPCM;
  1.1728 +	if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
  1.1729 +		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitALaw;
  1.1730 +	if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
  1.1731 +		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitMuLaw;
  1.1732 +	if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
  1.1733 +		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitPCM;
  1.1734 +
  1.1735 +	// Mono and Stereo support
  1.1736 +	if (aSupportedFormat().iChannels == 2)
  1.1737 +		iDeviceCapabilities.iChannels = EMMFStereo;
  1.1738 +	iDeviceCapabilities.iChannels |= EMMFMono;
  1.1739 +
  1.1740 +	iDeviceCapabilities.iBufferSize = aSupportedFormat().iMaxBufferSize;
  1.1741 +	// Default
  1.1742 +	iDeviceConfig.iRate = EMMFSampleRate8000Hz;
  1.1743 +	iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
  1.1744 +	iDeviceConfig.iChannels = EMMFMono;
  1.1745 +
  1.1746 +	return KErrNone;
  1.1747 +	}
  1.1748 +
  1.1749 +/*
  1.1750 + *
  1.1751 + *	Makes request to Policy Server (asynchronous call)
  1.1752 + *
  1.1753 + */
  1.1754 +void CMMFDevSoundSvrImp::RequestPolicy()
  1.1755 +	{
  1.1756 +	iDevSoundEventHandler->CancelReceiveEvents();
  1.1757 +	iDevSoundEventHandler->ReceiveEvents();
  1.1758 +	iAudioPolicyPrioritySettings.iCapabilities = iParent.CheckClientCapabilities();
  1.1759 +	iAudioPolicyProxy->MakeRequest(iAudioPolicyPrioritySettings);
  1.1760 +	}
  1.1761 +
  1.1762 +/*
  1.1763 + *
  1.1764 + *	Creates buffer and begin playback using the specified tone generator.
  1.1765 + *
  1.1766 + */
  1.1767 +void CMMFDevSoundSvrImp::DoPlayL()
  1.1768 +	{
  1.1769 +	// Delete any buffer from previous call and try to create maximum buffer 
  1.1770 +	// size. Double Buffer the Tone data.
  1.1771 +	if (iToneBuffer1)
  1.1772 +		{
  1.1773 +		delete iToneBuffer1; 
  1.1774 +		iToneBuffer1 = NULL; 
  1.1775 +		}
  1.1776 +	//note the tone buffer needs to be the same as the pcm16->pcm16 'null'
  1.1777 +	//hw device plugin
  1.1778 +	// Buffer size = (SampleRate * BytesPerSample * Channels) / 4
  1.1779 +	TInt useBufferOfSize = ((SamplingFrequency() * 2 * NumberOfChannels())/KDevSoundFramesPerSecond + (KDevSoundDeltaFrameSize-1)) &~ (KDevSoundDeltaFrameSize-1);
  1.1780 +	//clamp buffer to desired limits
  1.1781 +	if(useBufferOfSize < KDevSoundMinFrameSize) 
  1.1782 +		useBufferOfSize = KDevSoundMinFrameSize;
  1.1783 +	else if(useBufferOfSize > KDevSoundMaxFrameSize) 
  1.1784 +		useBufferOfSize = KDevSoundMaxFrameSize;
  1.1785 +
  1.1786 +	//clamp buffer to limits of hardware
  1.1787 +	if(useBufferOfSize < Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize))
  1.1788 +		useBufferOfSize = Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize);
  1.1789 +	else if(useBufferOfSize > Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize))
  1.1790 +		useBufferOfSize = Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize);
  1.1791 +
  1.1792 +	iToneBuffer1 = CMMFDataBuffer::NewL(useBufferOfSize);
  1.1793 +	User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer1->Data()));
  1.1794 +
  1.1795 +	if (iToneBuffer2)
  1.1796 +		{
  1.1797 +		delete iToneBuffer2; 
  1.1798 +		iToneBuffer2 = NULL;
  1.1799 +		}
  1.1800 +	iToneBuffer2 = CMMFDataBuffer::NewL(useBufferOfSize);
  1.1801 +	User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer2->Data()));
  1.1802 +
  1.1803 +	// Assign active buffer
  1.1804 +	iActiveToneBuffer = iToneBuffer1;
  1.1805 +
  1.1806 +	// Hw device hasn't played anything yet so don't change
  1.1807 +    // active buffer. This is checked in FillThisHwBuffer.
  1.1808 +    iFirstCallFromHwDevice = ETrue;
  1.1809 +
  1.1810 +    // Start HwDevice to play data
  1.1811 +    User::LeaveIfError(iCMMFHwDevice->Start(EDevDecode, EDevOutFlow));
  1.1812 +	
  1.1813 +	}
  1.1814 +
  1.1815 +/*
  1.1816 + *
  1.1817 + *	This method assigns the other buffer as active buffer. The tone audio 
  1.1818 + *	generator should fill data in the other buffer by now.
  1.1819 + *
  1.1820 + */
  1.1821 +void CMMFDevSoundSvrImp::SetActiveToneBuffer()
  1.1822 +	{
  1.1823 +	if (iActiveToneBuffer == iToneBuffer1)
  1.1824 +		iActiveToneBuffer = iToneBuffer2;
  1.1825 +	else if (iActiveToneBuffer == iToneBuffer2)
  1.1826 +		iActiveToneBuffer = iToneBuffer1;
  1.1827 +	}
  1.1828 +
  1.1829 +/*
  1.1830 + *
  1.1831 + *	This method fills data into the free buffer.
  1.1832 + *
  1.1833 + *	@return	"TInt"
  1.1834 + *			Error code. KErrNone if success.
  1.1835 + *
  1.1836 + */
  1.1837 +TInt CMMFDevSoundSvrImp::FillFreeToneBuffer()
  1.1838 +	{
  1.1839 +	TInt err(KErrNone);
  1.1840 +	if (iActiveToneBuffer == iToneBuffer1)
  1.1841 +		err = iCurrentGenerator->FillBuffer(iToneBuffer2->Data());
  1.1842 +	else if (iActiveToneBuffer == iToneBuffer2)
  1.1843 +		err = iCurrentGenerator->FillBuffer(iToneBuffer1->Data());
  1.1844 +	return err;
  1.1845 +	}
  1.1846 +
  1.1847 +/*
  1.1848 + *
  1.1849 + *	Updates the policy state based on Audio policy settings of this devsound instance
  1.1850 + *
  1.1851 + */
  1.1852 +TInt CMMFDevSoundSvrImp::UpdatePolicyState()
  1.1853 +	{
  1.1854 +	TInt error = iAudioPolicyProxy->UpdateState(iAudioPolicyPrioritySettings);
  1.1855 +	return error;
  1.1856 +	}
  1.1857 +
  1.1858 +/*
  1.1859 + *
  1.1860 + *	Initializes audio device node by setting volume, and sampling rate.
  1.1861 + *
  1.1862 + *	@return	"TInt"
  1.1863 + *			Error Code. KErrNone if success.
  1.1864 + *
  1.1865 + */
  1.1866 +TInt CMMFDevSoundSvrImp::InitTask()
  1.1867 +	{
  1.1868 +	// No Implementation
  1.1869 +	return KErrNone;
  1.1870 +	}
  1.1871 +
  1.1872 +
  1.1873 +
  1.1874 +/*
  1.1875 + *
  1.1876 + *	Returns an integer representing Sampling Frequency the device is currently
  1.1877 + *	configured to.
  1.1878 + *
  1.1879 + *	@return	"TInt"
  1.1880 + *			Sampling Frequency.
  1.1881 + *
  1.1882 + */
  1.1883 +TInt CMMFDevSoundSvrImp::SamplingFrequency()
  1.1884 +	{
  1.1885 +	if(iDeviceConfig.iRate == EMMFSampleRate8000Hz)
  1.1886 +		return 8000;
  1.1887 +	else if(iDeviceConfig.iRate == EMMFSampleRate11025Hz)
  1.1888 +		return 11025;
  1.1889 +	else if(iDeviceConfig.iRate == EMMFSampleRate12000Hz)
  1.1890 +		return 12000;
  1.1891 +	else if(iDeviceConfig.iRate == EMMFSampleRate16000Hz)
  1.1892 +		return 16000;
  1.1893 +	else if(iDeviceConfig.iRate == EMMFSampleRate22050Hz)
  1.1894 +		return 22050;
  1.1895 +	else if(iDeviceConfig.iRate == EMMFSampleRate24000Hz)
  1.1896 +		return 24000;
  1.1897 +	else if(iDeviceConfig.iRate == EMMFSampleRate32000Hz)
  1.1898 +		return 32000;
  1.1899 +	else if(iDeviceConfig.iRate == EMMFSampleRate44100Hz)
  1.1900 +		return 44100;
  1.1901 +	else if(iDeviceConfig.iRate == EMMFSampleRate48000Hz)
  1.1902 +		return 48000;
  1.1903 +	else if(iDeviceConfig.iRate == EMMFSampleRate88200Hz)
  1.1904 +		return 88200;
  1.1905 +	else if(iDeviceConfig.iRate == EMMFSampleRate96000Hz)
  1.1906 +		return 96000;
  1.1907 +	else
  1.1908 +		return 8000; //default
  1.1909 +	}
  1.1910 + 
  1.1911 +/*
  1.1912 + *
  1.1913 + *	Returns an integer representing number of channels the device is currently
  1.1914 + *	configured to.
  1.1915 + *
  1.1916 + *	@return	"TInt"
  1.1917 + *			Number of audio channels 1 if mono, 2 if stereo.
  1.1918 + *
  1.1919 + */
  1.1920 +TInt CMMFDevSoundSvrImp::NumberOfChannels()
  1.1921 +	{
  1.1922 +	if(iDeviceConfig.iChannels == EMMFMono)
  1.1923 +		return 1;
  1.1924 +	else
  1.1925 +		return 2;
  1.1926 +	}
  1.1927 +
  1.1928 +/*
  1.1929 + *
  1.1930 + *	Returns an integer representing number of bytes in each audio sample
  1.1931 + *	
  1.1932 + *
  1.1933 + *	@return	"TInt"
  1.1934 + *			Number of of bytes in each audio sample.
  1.1935 + *
  1.1936 + */
  1.1937 +TInt CMMFDevSoundSvrImp::BytesPerAudioSample()
  1.1938 +	{
  1.1939 +	TInt bytes=1;
  1.1940 +	switch (iDeviceConfig.iEncoding)
  1.1941 +		{
  1.1942 +		case EMMFSoundEncoding8BitPCM:
  1.1943 +		case EMMFSoundEncoding8BitALaw:
  1.1944 +		case EMMFSoundEncoding8BitMuLaw:
  1.1945 +			{
  1.1946 +			bytes=1;
  1.1947 +			}
  1.1948 +		break;
  1.1949 +		case EMMFSoundEncoding16BitPCM:
  1.1950 +			{
  1.1951 +			bytes=2;
  1.1952 +			}
  1.1953 +		break;
  1.1954 +		}
  1.1955 +	return bytes;
  1.1956 +	}
  1.1957 +
  1.1958 +
  1.1959 +/********************************************************************************
  1.1960 + *				Private functions ends here										*
  1.1961 + ********************************************************************************/