os/mm/devsound/devsoundrefplugin/src/platsec/server/AudioServer/MmfDevSoundSessionBody.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include <e32base.h>
sl@0
    17
#ifdef SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
    18
#include <OMX_Core.h>
sl@0
    19
#endif // SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
    20
#include "MmfDevSoundSessionBody.h"
sl@0
    21
#include "MmfDevSoundSessionXtnd.h"
sl@0
    22
#include "MmfDevSoundServer.h"
sl@0
    23
#include <mdaaudiotoneplayer.h>
sl@0
    24
#include <mmf/server/mmfdatabuffer.h>
sl@0
    25
#include <mmffourcc.h>
sl@0
    26
#include <mmfhwdeviceimplementationuids.hrh>
sl@0
    27
#include <mmf/server/mmfswcodecwrappercustominterfacesuids.hrh> // KUidRefDevSoundTaskConfig & KMmfUidEmptyBuffersCustomInterface
sl@0
    28
#include <mmf/server/mmfdevsoundcustominterfacesupport.h>
sl@0
    29
sl@0
    30
const TUid KEmptyBuffersCustomInterfaceTypeUid	= {KMmfUidEmptyBuffersCustomInterface};
sl@0
    31
sl@0
    32
/*
sl@0
    33
 *
sl@0
    34
 *	Default Constructor.
sl@0
    35
 *
sl@0
    36
 *	No default implementation. CMMFDevSoundProxy implements 2-phase construction.
sl@0
    37
 *
sl@0
    38
 */
sl@0
    39
CMMFDevSoundSvrImp::CMMFDevSoundSvrImp(CMMFDevSoundSessionXtnd* aParent)
sl@0
    40
: iParent(*aParent)
sl@0
    41
	{
sl@0
    42
	iMode= EMMFDevSoundStateIdle;
sl@0
    43
	//Set reasonable default values for DTMF 
sl@0
    44
	iDTMFGen.SetToneDurations(250000,50000,250000);
sl@0
    45
	}
sl@0
    46
sl@0
    47
/*
sl@0
    48
 *
sl@0
    49
 *	Destructor.
sl@0
    50
 *
sl@0
    51
 *	Deletes all objects and releases all resource owned by this
sl@0
    52
 *	instance.
sl@0
    53
 *
sl@0
    54
 */
sl@0
    55
CMMFDevSoundSvrImp::~CMMFDevSoundSvrImp()
sl@0
    56
	{
sl@0
    57
	delete iToneBuffer1;
sl@0
    58
	delete iToneBuffer2;
sl@0
    59
	delete iDevSoundEventHandler; 
sl@0
    60
	if( iAudioPolicyProxy != NULL)
sl@0
    61
		{
sl@0
    62
		iAudioPolicyProxy->Close(); 
sl@0
    63
		delete iAudioPolicyProxy;
sl@0
    64
		}
sl@0
    65
	delete iDevSoundUtil;
sl@0
    66
	delete iFixedSequences;
sl@0
    67
	delete iCMMFHwDevice;
sl@0
    68
#ifdef SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
    69
	OMX_Deinit();
sl@0
    70
#endif // SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
    71
	}
sl@0
    72
sl@0
    73
/*
sl@0
    74
 *
sl@0
    75
 *	Constructs, and returns a pointer to, a new CMMFDevSoundSvrImp object.
sl@0
    76
 *
sl@0
    77
 *	Leaves on failure.
sl@0
    78
 *
sl@0
    79
 */
sl@0
    80
CMMFDevSoundSvrImp* CMMFDevSoundSvrImp::NewL(CMMFDevSoundSessionXtnd* aParent)
sl@0
    81
	{
sl@0
    82
	CMMFDevSoundSvrImp* self = new (ELeave) CMMFDevSoundSvrImp(aParent);
sl@0
    83
	return self;
sl@0
    84
	}
sl@0
    85
sl@0
    86
/*
sl@0
    87
 *
sl@0
    88
 *	3rd phase constructor - assumes that iParent has already been set up properly
sl@0
    89
 *                          (During ConstructL() it has yet to be
sl@0
    90
 *
sl@0
    91
 */
sl@0
    92
void CMMFDevSoundSvrImp::Construct3L(RServer2& aPolicyServerHandle)
sl@0
    93
	{
sl@0
    94
	// all these data properties should be NULL, but add ASSERTs to verity
sl@0
    95
	ASSERT(iAudioPolicyProxy==NULL);
sl@0
    96
	iAudioPolicyProxy = new (ELeave) RMMFAudioPolicyProxy();
sl@0
    97
	ASSERT(iDevSoundEventHandler==NULL);
sl@0
    98
	iDevSoundEventHandler = CMMFDevSoundEventHandler::NewL(iAudioPolicyProxy);
sl@0
    99
	User::LeaveIfError(iAudioPolicyProxy->Open(aPolicyServerHandle));
sl@0
   100
	iDevSoundEventHandler->SetDevSoundInfo(&iParent);
sl@0
   101
sl@0
   102
	iDevSoundUtil = CMMFDevSoundUtility::NewL();
sl@0
   103
	// Initialize Fixed sequence related
sl@0
   104
	iDevSoundUtil->InitializeFixedSequenceL(&iFixedSequences);
sl@0
   105
	
sl@0
   106
#ifdef SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
   107
	OMX_Init();
sl@0
   108
#endif // SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
   109
	PreInitializeL();
sl@0
   110
	}
sl@0
   111
sl@0
   112
/**
sl@0
   113
 * internal procedure to perform all initialization prior to setting the 
sl@0
   114
 * data type 4CC code
sl@0
   115
 */
sl@0
   116
void CMMFDevSoundSvrImp::PreInitializeL()
sl@0
   117
	{
sl@0
   118
	// Set default values for priority settings: Note: Client must 
sl@0
   119
	// over ride default settings by calling SetPrioirtySettings
sl@0
   120
	iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
sl@0
   121
	iAudioPolicyPrioritySettings.iPref = EMdaPriorityPreferenceNone;
sl@0
   122
	iAudioPolicyPrioritySettings.iPriority = 0;
sl@0
   123
sl@0
   124
	// Get device capabilities and current settings from Audio Policy:
sl@0
   125
	User::LeaveIfError(iAudioPolicyProxy->GetPlayFormatsSupported(iPlayFormatsSupported));
sl@0
   126
	User::LeaveIfError(iAudioPolicyProxy->GetPlayFormat(iPlayFormat));
sl@0
   127
	User::LeaveIfError(iAudioPolicyProxy->GetRecordFormatsSupported(iRecordFormatsSupported));
sl@0
   128
	User::LeaveIfError(iAudioPolicyProxy->GetRecordFormat(iRecordFormat));
sl@0
   129
sl@0
   130
	//default to play until we know we are recording
sl@0
   131
	User::LeaveIfError(InitializeFormat(iPlayFormatsSupported, iPlayFormat));
sl@0
   132
	}
sl@0
   133
sl@0
   134
/*
sl@0
   135
 *
sl@0
   136
 *	Initializes CMMFDevSoundProxy object to play and record PCM16 raw audio data
sl@0
   137
 *	with sampling rate of 8 KHz.
sl@0
   138
 *
sl@0
   139
 *	On completion of Initialization, calls InitializeComplete() on
sl@0
   140
 *	aDevSoundObserver.
sl@0
   141
 *
sl@0
   142
 *	Leaves on failure.
sl@0
   143
 *
sl@0
   144
 *	@param	"MDevSoundObserver& aDevSoundObserver"
sl@0
   145
 *			A reference to DevSound Observer instance.
sl@0
   146
 *
sl@0
   147
 *	@param	"TMMFState aMode"
sl@0
   148
 *			Mode for which this object will be used.
sl@0
   149
 *
sl@0
   150
 */
sl@0
   151
void CMMFDevSoundSvrImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TMMFState aMode)
sl@0
   152
sl@0
   153
	{
sl@0
   154
	// if no HwDevice id specified, load default null implementation
sl@0
   155
	TUid rawUid = {KMmfUidHwDevicePCM16ToPCM16};
sl@0
   156
	InitializeL(aDevSoundObserver, rawUid, aMode);
sl@0
   157
	__ASSERT_DEBUG(!(iHasPolicy&&(iMode == EMMFDevSoundStatePlaying)), Panic(TMMFDevSoundSessionPolicyNotInvalidated));
sl@0
   158
	}
sl@0
   159
sl@0
   160
/*
sl@0
   161
 *
sl@0
   162
 *	Configure CMMFDevSoundProxy object for the settings in aConfig.
sl@0
   163
 *
sl@0
   164
 *	Use this to set sampling rate, Encoding and Mono/Stereo.
sl@0
   165
 *
sl@0
   166
 *	@param	"TMMFCapabilities& aConfig"
sl@0
   167
 *			Attribute values to which CMMFDevSoundProxy object will be configured to.
sl@0
   168
 *
sl@0
   169
 *  As part of defect 20796, the iRecordFormat has been set under the iPlayFormat, 
sl@0
   170
 *  before it was not set at all.
sl@0
   171
 *
sl@0
   172
 */
sl@0
   173
void CMMFDevSoundSvrImp::SetConfigL(const TMMFCapabilities& aConfig)
sl@0
   174
	{
sl@0
   175
	TUint attributeValue = aConfig.iRate;
sl@0
   176
	// WINS supports from 8000 Hz to 96000 Hz
sl@0
   177
	// The ToneGenerator currently supports sample rate of 8000Hz only. 
sl@0
   178
	if(iMode == EMMFDevSoundStateTonePlaying && (attributeValue != EMMFSampleRate8000Hz ))
sl@0
   179
		{
sl@0
   180
		User::Leave(KErrNotSupported);
sl@0
   181
		}
sl@0
   182
	
sl@0
   183
	if (attributeValue & EMMFSampleRate96000Hz) 
sl@0
   184
		{ 
sl@0
   185
		iPlayFormat().iRate = 96000; 
sl@0
   186
		iRecordFormat().iRate = 96000;
sl@0
   187
		iDeviceConfig.iRate = EMMFSampleRate96000Hz;
sl@0
   188
		}
sl@0
   189
	else if (attributeValue & EMMFSampleRate88200Hz) 
sl@0
   190
		{ 
sl@0
   191
		iPlayFormat().iRate = 88200; 
sl@0
   192
		iRecordFormat().iRate = 88200;
sl@0
   193
		iDeviceConfig.iRate = EMMFSampleRate88200Hz;
sl@0
   194
		}
sl@0
   195
	else if (attributeValue & EMMFSampleRate64000Hz) 
sl@0
   196
		{ 
sl@0
   197
		iPlayFormat().iRate = 64000; 
sl@0
   198
		iRecordFormat().iRate = 64000;
sl@0
   199
		iDeviceConfig.iRate = EMMFSampleRate64000Hz;
sl@0
   200
		}
sl@0
   201
	else if (attributeValue & EMMFSampleRate48000Hz) 
sl@0
   202
		{ 
sl@0
   203
		iPlayFormat().iRate = 48000; 
sl@0
   204
		iRecordFormat().iRate = 48000;
sl@0
   205
		iDeviceConfig.iRate = EMMFSampleRate48000Hz;
sl@0
   206
		}
sl@0
   207
	else if (attributeValue & EMMFSampleRate44100Hz) 
sl@0
   208
		{ 
sl@0
   209
		iPlayFormat().iRate = 44100; 
sl@0
   210
		iRecordFormat().iRate = 44100;
sl@0
   211
		iDeviceConfig.iRate = EMMFSampleRate44100Hz;
sl@0
   212
		}
sl@0
   213
	else if (attributeValue & EMMFSampleRate32000Hz) 
sl@0
   214
		{ 
sl@0
   215
		iPlayFormat().iRate = 32000; 
sl@0
   216
		iRecordFormat().iRate = 32000; 
sl@0
   217
		iDeviceConfig.iRate = EMMFSampleRate32000Hz;
sl@0
   218
		}
sl@0
   219
	else if (attributeValue & EMMFSampleRate24000Hz)
sl@0
   220
		{
sl@0
   221
		iPlayFormat().iRate = 
sl@0
   222
		iRecordFormat().iRate = 24000;
sl@0
   223
		iDeviceConfig.iRate = EMMFSampleRate24000Hz;
sl@0
   224
		}
sl@0
   225
	else if (attributeValue & EMMFSampleRate22050Hz)
sl@0
   226
		{ 
sl@0
   227
		iPlayFormat().iRate = 22050; 
sl@0
   228
		iRecordFormat().iRate = 22050; 
sl@0
   229
		iDeviceConfig.iRate = EMMFSampleRate22050Hz;
sl@0
   230
		}
sl@0
   231
	else if (attributeValue & EMMFSampleRate16000Hz)
sl@0
   232
		{
sl@0
   233
		iPlayFormat().iRate = 16000;
sl@0
   234
		iRecordFormat().iRate = 16000; 
sl@0
   235
		iDeviceConfig.iRate = EMMFSampleRate16000Hz;
sl@0
   236
		}
sl@0
   237
	else if (attributeValue & EMMFSampleRate12000Hz)
sl@0
   238
		{
sl@0
   239
		iPlayFormat().iRate = 
sl@0
   240
		iRecordFormat().iRate = 12000;
sl@0
   241
		iDeviceConfig.iRate = EMMFSampleRate12000Hz;
sl@0
   242
		}
sl@0
   243
	else if (attributeValue & EMMFSampleRate11025Hz)
sl@0
   244
		{
sl@0
   245
		iPlayFormat().iRate = 11025;
sl@0
   246
		iRecordFormat().iRate = 11025;
sl@0
   247
		iDeviceConfig.iRate = EMMFSampleRate11025Hz;
sl@0
   248
		}
sl@0
   249
	else if (attributeValue & EMMFSampleRate8000Hz)
sl@0
   250
		{
sl@0
   251
		iPlayFormat().iRate = 8000;
sl@0
   252
		iRecordFormat().iRate = 8000;
sl@0
   253
		iDeviceConfig.iRate = EMMFSampleRate8000Hz;
sl@0
   254
		}
sl@0
   255
	else if (attributeValue) 
sl@0
   256
		{ //if no attribute value assume its not set
sl@0
   257
		User::Leave(KErrNotSupported);
sl@0
   258
		}
sl@0
   259
sl@0
   260
	attributeValue = aConfig.iEncoding;
sl@0
   261
	// Map from MMF Encoding enums to RMdaDevSound enum
sl@0
   262
	if(attributeValue & EMMFSoundEncoding8BitPCM) 
sl@0
   263
		{
sl@0
   264
		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
sl@0
   265
		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
sl@0
   266
		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitPCM;
sl@0
   267
		}
sl@0
   268
	else if(attributeValue & EMMFSoundEncoding8BitALaw)
sl@0
   269
		{
sl@0
   270
		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
sl@0
   271
		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
sl@0
   272
		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitALaw;
sl@0
   273
		}
sl@0
   274
	else if(attributeValue & EMMFSoundEncoding8BitMuLaw) 
sl@0
   275
		{
sl@0
   276
		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
sl@0
   277
		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
sl@0
   278
		iDeviceConfig.iEncoding = EMMFSoundEncoding8BitMuLaw;
sl@0
   279
		}
sl@0
   280
	else if(attributeValue & EMMFSoundEncoding16BitPCM)
sl@0
   281
		{
sl@0
   282
		iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
sl@0
   283
		iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
sl@0
   284
		iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
sl@0
   285
		}
sl@0
   286
	else if (attributeValue) 
sl@0
   287
		{ //if no attribute value assume its not set
sl@0
   288
		User::Leave(KErrNotSupported);
sl@0
   289
		}
sl@0
   290
sl@0
   291
	// Mono/Stereo settings
sl@0
   292
	attributeValue = aConfig.iChannels;
sl@0
   293
	if(iMode == EMMFDevSoundStateTonePlaying && (attributeValue != EMMFMono ))
sl@0
   294
		{
sl@0
   295
		User::Leave(KErrNotSupported);
sl@0
   296
		}
sl@0
   297
	if(attributeValue & EMMFStereo) 
sl@0
   298
		{
sl@0
   299
		iPlayFormat().iChannels = 2;
sl@0
   300
		iRecordFormat().iChannels = 2;
sl@0
   301
		iDeviceConfig.iChannels = EMMFStereo;
sl@0
   302
		}
sl@0
   303
	else if(attributeValue & EMMFMono)
sl@0
   304
		{
sl@0
   305
		iPlayFormat().iChannels = 1;
sl@0
   306
		iRecordFormat().iChannels = 1;
sl@0
   307
		iDeviceConfig.iChannels = EMMFMono;
sl@0
   308
		}
sl@0
   309
	else if (attributeValue) 
sl@0
   310
		{ //if no attribute value assume its not set
sl@0
   311
		User::Leave(KErrNotSupported);
sl@0
   312
		}
sl@0
   313
	}
sl@0
   314
sl@0
   315
/*
sl@0
   316
 *
sl@0
   317
 *	Changes the current playback volume to a specified value.
sl@0
   318
 *
sl@0
   319
 *	The volume can be changed before or during playback and is effective
sl@0
   320
 *	immediately.
sl@0
   321
 *
sl@0
   322
 *	@param	"TInt aVolume"
sl@0
   323
 *			The volume setting. This can be any value from zero to the value
sl@0
   324
 *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
sl@0
   325
 *			volume is not within this range, the volume is automatically set to
sl@0
   326
 *			minimum or maximum value based on the value that is being passed.
sl@0
   327
 *			Setting a zero value mutes the sound. Setting the maximum value
sl@0
   328
 *			results in the loudest possible sound.
sl@0
   329
 *
sl@0
   330
 */
sl@0
   331
void CMMFDevSoundSvrImp::SetVolume(TInt aVolume)
sl@0
   332
	{
sl@0
   333
sl@0
   334
	// Check and make sure that the volume is in valid range
sl@0
   335
	if (aVolume < 0)
sl@0
   336
		aVolume = 0;
sl@0
   337
sl@0
   338
	if (aVolume > MaxVolume())
sl@0
   339
		aVolume = MaxVolume();
sl@0
   340
sl@0
   341
	iVolume = aVolume;
sl@0
   342
sl@0
   343
	SetDeviceVolume(iVolume);
sl@0
   344
	}
sl@0
   345
sl@0
   346
/*
sl@0
   347
 *
sl@0
   348
 *	Changes the current recording gain to a specified value.
sl@0
   349
 *
sl@0
   350
 *	The gain can be changed before or during recording and is effective
sl@0
   351
 *	immediately.
sl@0
   352
 *
sl@0
   353
 *	@param	"TInt aGain"
sl@0
   354
 *			The volume setting. This can be any value from zero to the value
sl@0
   355
 *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
sl@0
   356
 *			volume is not within this range, the gain is automatically set to
sl@0
   357
 *			minimum or maximum value based on the value that is being passed.
sl@0
   358
 *			Setting a zero value mutes the sound. Setting the maximum value
sl@0
   359
 *			results in the loudest possible sound.
sl@0
   360
 *
sl@0
   361
 */
sl@0
   362
void CMMFDevSoundSvrImp::SetGain(TInt aGain)
sl@0
   363
	{
sl@0
   364
	// make sure it falls with the correct range
sl@0
   365
	TInt maxGain = iRecordFormatsSupported().iMaxVolume;
sl@0
   366
	if (aGain > maxGain)
sl@0
   367
		aGain = maxGain;
sl@0
   368
	else if (aGain < 0)
sl@0
   369
		aGain = 0;
sl@0
   370
	iGain = aGain;
sl@0
   371
	SetDeviceRecordLevel(iGain);
sl@0
   372
	}
sl@0
   373
sl@0
   374
/*
sl@0
   375
 *
sl@0
   376
 *	Sets the speaker balance for playing.
sl@0
   377
 *
sl@0
   378
 *	The speaker balance can be changed before or during playback and is
sl@0
   379
 *	effective immediately.
sl@0
   380
 *
sl@0
   381
 *	@param	"TInt& aLeftPercentage"
sl@0
   382
 *			On return contains left speaker volume perecentage. This can be any
sl@0
   383
 *			value from zero to 100. Setting a zero value mutes the sound on left
sl@0
   384
 *			speaker.
sl@0
   385
 *
sl@0
   386
 *	@param	"TInt& aRightPercentage"
sl@0
   387
 *			On return contains right speaker volume perecentage. This can be any
sl@0
   388
 *			value from zero to 100. Setting a zero value mutes the sound on
sl@0
   389
 *			right speaker.
sl@0
   390
 *
sl@0
   391
 */
sl@0
   392
void CMMFDevSoundSvrImp::SetPlayBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
sl@0
   393
	{
sl@0
   394
	if (aLeftPercentage < 0)
sl@0
   395
		aLeftPercentage = 0;
sl@0
   396
	else if (aLeftPercentage > 100)
sl@0
   397
		aLeftPercentage = 100;
sl@0
   398
	if (aRightPercentage < 0)
sl@0
   399
		aRightPercentage = 0;
sl@0
   400
	else if (aRightPercentage > 100)
sl@0
   401
		aRightPercentage = 100;
sl@0
   402
	iLeftPlayBalance = aLeftPercentage;
sl@0
   403
	iRightPlayBalance = aRightPercentage;
sl@0
   404
	}
sl@0
   405
sl@0
   406
/*
sl@0
   407
 *
sl@0
   408
 *	Sets the microphone gain balance for recording.
sl@0
   409
 *
sl@0
   410
 *	The microphone gain balance can be changed before or during recording and
sl@0
   411
 *	is effective immediately.
sl@0
   412
 *
sl@0
   413
 *	@param	"TInt aLeftPercentage"
sl@0
   414
 *			Left microphone gain precentage. This can be any value from zero to
sl@0
   415
 *			100. Setting a zero value mutes the gain on left microphone.
sl@0
   416
 *
sl@0
   417
 *	@param	"TInt aRightPercentage"
sl@0
   418
 *			Right microphone gain precentage. This can be any value from zero to
sl@0
   419
 *			100. Setting a zero value mutes the gain on right microphone.
sl@0
   420
 *
sl@0
   421
 */
sl@0
   422
void CMMFDevSoundSvrImp::SetRecordBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
sl@0
   423
	{
sl@0
   424
	if (aLeftPercentage < 0)
sl@0
   425
		aLeftPercentage = 0;
sl@0
   426
	else if (aLeftPercentage > 100)
sl@0
   427
		aLeftPercentage = 100;
sl@0
   428
	if (aRightPercentage < 0)
sl@0
   429
		aRightPercentage = 0;
sl@0
   430
	else if (aRightPercentage > 100)
sl@0
   431
		aRightPercentage = 100;
sl@0
   432
	iLeftRecordBalance = aLeftPercentage;
sl@0
   433
	iRightRecordBalance = aRightPercentage;
sl@0
   434
	}
sl@0
   435
sl@0
   436
/*
sl@0
   437
 *
sl@0
   438
 *	Initializes audio device and start play process. This method queries and
sl@0
   439
 *	acquires the audio policy before initializing audio device. If there was an
sl@0
   440
 *	error during policy initialization, PlayError() method will be called on
sl@0
   441
 *	the observer with error code KErrAccessDenied, otherwise BufferToBeFilled()
sl@0
   442
 *	method will be called with a buffer reference. After reading data into the
sl@0
   443
 *	buffer reference passed, the client should call PlayData() to play data.
sl@0
   444
 *
sl@0
   445
 *	The amount of data that can be played is specified in
sl@0
   446
 *	CMMFBuffer::RequestSize(). Any data that is read into buffer beyond this
sl@0
   447
 *	size will be ignored.
sl@0
   448
 *
sl@0
   449
 *	Leaves on failure.
sl@0
   450
 *
sl@0
   451
 */
sl@0
   452
void CMMFDevSoundSvrImp::PlayInitL()
sl@0
   453
	{
sl@0
   454
	if (!iDevSoundObserver)
sl@0
   455
		User::Leave(KErrNotReady);
sl@0
   456
sl@0
   457
	if (iAudioPolicyPrioritySettings.iState == EMMFStatePlayData)
sl@0
   458
		{
sl@0
   459
		// If policy has not been obtaing then ignore the request.
sl@0
   460
		// If it has then do a stop and start action on HW device
sl@0
   461
		// without informing policy.
sl@0
   462
		
sl@0
   463
		if (iHasPolicy)
sl@0
   464
			{
sl@0
   465
			if (iCMMFHwDevice)
sl@0
   466
				{
sl@0
   467
				TInt err = iCMMFHwDevice->Stop();
sl@0
   468
				if (err == KErrNone)
sl@0
   469
					{
sl@0
   470
					err = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
sl@0
   471
					}
sl@0
   472
				
sl@0
   473
				if (err != KErrNone)
sl@0
   474
					{
sl@0
   475
					Error(err);
sl@0
   476
					}
sl@0
   477
				}
sl@0
   478
			}
sl@0
   479
		return;
sl@0
   480
		}
sl@0
   481
sl@0
   482
	// Get audio policy
sl@0
   483
	iAudioPolicyPrioritySettings.iState = EMMFStatePlayData;
sl@0
   484
	RequestPolicy();
sl@0
   485
	}
sl@0
   486
sl@0
   487
/*
sl@0
   488
 *
sl@0
   489
 *	Initializes audio device and start record process. 
sl@0
   490
 *  This method:
sl@0
   491
 *  1. Queries and acquires the audio policy before initializing audio device. 
sl@0
   492
 *     If there was an error during policy initialization, RecordError() method will 
sl@0
   493
 *     be called on the observer with error code KErrAccessDenied, otherwise BufferToBeEmptied()
sl@0
   494
 *	   method will be called with a buffer reference. This buffer contains recorded
sl@0
   495
 *	   or encoded data. After processing data in the buffer reference passed, the
sl@0
   496
 *	   client should call RecordData() to continue recording process.
sl@0
   497
 *
sl@0
   498
 *  2. Checks if the requesting client process has a UserEnvironment capability.
sl@0
   499
 *     If it does not, the audio device will not be initialized and an error 
sl@0
   500
 *     code KErrAccessDenied will be sent to the client.
sl@0
   501
 *
sl@0
   502
 *	The amount of data that is available is specified in
sl@0
   503
 *	CMMFBuffer::RequestSize().
sl@0
   504
 *
sl@0
   505
 *	Leaves on failure.
sl@0
   506
 *
sl@0
   507
 */
sl@0
   508
void CMMFDevSoundSvrImp::RecordInitL(const RMmfIpcMessage& aMessage)
sl@0
   509
	{
sl@0
   510
	if (!iDevSoundObserver)
sl@0
   511
		User::Leave(KErrNotReady);
sl@0
   512
	
sl@0
   513
	// Checkes if the client has the UserEnvironment capability
sl@0
   514
	if (!aMessage.HasCapability(ECapabilityUserEnvironment))
sl@0
   515
		{
sl@0
   516
		User::Leave(KErrPermissionDenied);
sl@0
   517
		}
sl@0
   518
sl@0
   519
	if (iAudioPolicyPrioritySettings.iState == EMMFStateRecordData)
sl@0
   520
		{
sl@0
   521
		if (iHasPolicy)
sl@0
   522
			{
sl@0
   523
			if (iCMMFHwDevice)
sl@0
   524
				{
sl@0
   525
				TInt err = iCMMFHwDevice->Stop();
sl@0
   526
				if (err == KErrNone)
sl@0
   527
					{
sl@0
   528
					err = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
sl@0
   529
					}
sl@0
   530
				
sl@0
   531
				if (err != KErrNone)
sl@0
   532
					{
sl@0
   533
					Error(err);
sl@0
   534
					}
sl@0
   535
				
sl@0
   536
				if (iHwDeviceBuffer)
sl@0
   537
					{
sl@0
   538
					iHwDeviceBuffer->SetLastBuffer(EFalse);
sl@0
   539
					}
sl@0
   540
				}
sl@0
   541
			}
sl@0
   542
		
sl@0
   543
		return;
sl@0
   544
		}
sl@0
   545
sl@0
   546
	// Get audio policy
sl@0
   547
	iAudioPolicyPrioritySettings.iState = EMMFStateRecordData;
sl@0
   548
	RequestPolicy();
sl@0
   549
	}
sl@0
   550
sl@0
   551
/*
sl@0
   552
 *
sl@0
   553
 *	Plays data in the buffer at the current volume. The client should fill
sl@0
   554
 *	the buffer with audio data before calling this method. The Observer gets
sl@0
   555
 *	reference to buffer along with callback BufferToBeFilled(). When playing of
sl@0
   556
 *	the audio sample is complete, successfully or otherwise, the method
sl@0
   557
 *	PlayError() on observer is called.
sl@0
   558
 *
sl@0
   559
 */
sl@0
   560
TBool CMMFDevSoundSvrImp::PlayData(const RMmfIpcMessage& aMessage)
sl@0
   561
	{
sl@0
   562
	ASSERT(iDevSoundObserver);
sl@0
   563
sl@0
   564
	if (iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
sl@0
   565
		{
sl@0
   566
		// Initialisation has been successful but an error (possibly underflow) has occurred
sl@0
   567
		// which the controller has yet to respond to and that has changed the state to stopped.
sl@0
   568
		// Allow the call to complete and processing to continue...  
sl@0
   569
		return ETrue;
sl@0
   570
		}
sl@0
   571
sl@0
   572
	if((iAudioPolicyPrioritySettings.iState != EMMFStatePlayData) && (iAudioPolicyPrioritySettings.iState != EMMFStatePaused))
sl@0
   573
		{
sl@0
   574
		PanicClient(aMessage, EMMFDevSoundPlayDataWithoutInitialize);
sl@0
   575
		return EFalse;
sl@0
   576
		}
sl@0
   577
	if (iMode== EMMFDevSoundStateIdle)
sl@0
   578
		{
sl@0
   579
		return ETrue;
sl@0
   580
		}
sl@0
   581
	TInt error = KErrNone;
sl@0
   582
    if(iCMMFHwDevice)
sl@0
   583
	    {
sl@0
   584
		if (iPaused)
sl@0
   585
			{
sl@0
   586
			iPaused = EFalse;
sl@0
   587
			//note PlayData does not leave or return an error code so the Start() fails we cannot
sl@0
   588
			//report the error back at this point
sl@0
   589
			error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);//restart hw device after pause
sl@0
   590
			}
sl@0
   591
	   else if ((iMode == EMMFDevSoundStatePlaying) && iHasPolicy)
sl@0
   592
		    {
sl@0
   593
		    TInt len = iHwDeviceBuffer->Data().Length();
sl@0
   594
		    if (iHwDeviceBuffer->LastBuffer())
sl@0
   595
		    	{
sl@0
   596
		    	iLastBufferReceived = ETrue;
sl@0
   597
		    	}
sl@0
   598
			// Pass the data buffer to HwDevice
sl@0
   599
			error = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
sl@0
   600
            }
sl@0
   601
		}
sl@0
   602
	if (error != KErrNone)
sl@0
   603
		{
sl@0
   604
		Error(error);
sl@0
   605
		if(iCMMFHwDevice)
sl@0
   606
			{
sl@0
   607
			iCMMFHwDevice->Stop();	
sl@0
   608
			}
sl@0
   609
sl@0
   610
		}
sl@0
   611
	return ETrue;
sl@0
   612
	}
sl@0
   613
 
sl@0
   614
/*
sl@0
   615
 *
sl@0
   616
 *	Stops the ongoing operation (Play, Record, TonePlay, Convert)
sl@0
   617
 *
sl@0
   618
 */
sl@0
   619
void CMMFDevSoundSvrImp::Stop()
sl@0
   620
	{
sl@0
   621
	iPaused = EFalse;
sl@0
   622
sl@0
   623
	if (!iHasPolicy)
sl@0
   624
		{
sl@0
   625
		UpdatePolicyState(EMMFStateStopped);
sl@0
   626
		return;
sl@0
   627
		}
sl@0
   628
sl@0
   629
	 // Stop the hw device first - this unloads sound drivers
sl@0
   630
    if (iCMMFHwDevice)
sl@0
   631
    	{
sl@0
   632
		iCMMFHwDevice->Stop();
sl@0
   633
		}
sl@0
   634
sl@0
   635
	iDevSoundEventHandler->CancelReceiveEvents();
sl@0
   636
sl@0
   637
	UpdatePolicyState(EMMFStateStopped);
sl@0
   638
	__ASSERT_DEBUG(!(iHasPolicy&&(iMode == EMMFDevSoundStatePlaying)), Panic(TMMFDevSoundSessionPolicyNotInvalidated)); 
sl@0
   639
	}
sl@0
   640
sl@0
   641
/*
sl@0
   642
 *
sl@0
   643
 *	Temporarily Stops the ongoing operation (Play, Record, TonePlay, Convert)
sl@0
   644
 *
sl@0
   645
 */
sl@0
   646
void CMMFDevSoundSvrImp::Pause()
sl@0
   647
	{
sl@0
   648
	iPaused = ETrue;
sl@0
   649
sl@0
   650
	if (!iHasPolicy)
sl@0
   651
		{
sl@0
   652
		return;
sl@0
   653
		}
sl@0
   654
sl@0
   655
	// Pause the HW device first
sl@0
   656
	if (iCMMFHwDevice)
sl@0
   657
		{
sl@0
   658
		iCMMFHwDevice->Pause();
sl@0
   659
		}
sl@0
   660
	}
sl@0
   661
sl@0
   662
/*
sl@0
   663
 *
sl@0
   664
 *	Returns the sample recorded so far.
sl@0
   665
 *
sl@0
   666
 *	@return "TInt"
sl@0
   667
 *			Returns the samples recorded.
sl@0
   668
 *
sl@0
   669
 */
sl@0
   670
TInt CMMFDevSoundSvrImp::SamplesRecorded()
sl@0
   671
	{
sl@0
   672
	TInt samples = 0;
sl@0
   673
	
sl@0
   674
	if(iRecordCustomInterface)
sl@0
   675
		{
sl@0
   676
		samples = iRecordCustomInterface->BytesRecorded();
sl@0
   677
		if(NumberOfChannels() > 1)
sl@0
   678
			{
sl@0
   679
			samples /= NumberOfChannels();
sl@0
   680
			}
sl@0
   681
		if(BytesPerAudioSample() > 1)
sl@0
   682
			{
sl@0
   683
			samples /= BytesPerAudioSample();
sl@0
   684
			}
sl@0
   685
		}
sl@0
   686
sl@0
   687
	return samples;
sl@0
   688
	}
sl@0
   689
sl@0
   690
/*
sl@0
   691
 *
sl@0
   692
 *	Returns the sample played so far.
sl@0
   693
 *
sl@0
   694
 *	@return "TInt"
sl@0
   695
 *			Returns the samples recorded.
sl@0
   696
 *
sl@0
   697
 */
sl@0
   698
TInt CMMFDevSoundSvrImp::SamplesPlayed()
sl@0
   699
	{
sl@0
   700
	TInt samples = 0;
sl@0
   701
	if(iPlayCustomInterface)
sl@0
   702
		{
sl@0
   703
		TUint bytesPlayed = iPlayCustomInterface->BytesPlayed();
sl@0
   704
		if (bytesPlayed)
sl@0
   705
			iPlayedBytesCount = bytesPlayed;
sl@0
   706
sl@0
   707
		samples = iPlayedBytesCount;
sl@0
   708
		if(NumberOfChannels() > 1)
sl@0
   709
			samples /= NumberOfChannels();
sl@0
   710
sl@0
   711
		if(BytesPerAudioSample() > 1)
sl@0
   712
			samples /= BytesPerAudioSample();
sl@0
   713
		}
sl@0
   714
	//note always pcm16 becuase the iPlayedBytesCount originates from 
sl@0
   715
	//RMdaDevSound which is always pcm16
sl@0
   716
	return samples; //each sample is 2 bytes
sl@0
   717
	}
sl@0
   718
sl@0
   719
sl@0
   720
/*
sl@0
   721
 *
sl@0
   722
 *	Initializes audio device and start playing tone. Tone is played with
sl@0
   723
 *	frequency and for duration specified.
sl@0
   724
 *
sl@0
   725
 *	Leaves on failure.
sl@0
   726
 *
sl@0
   727
 *	@param	"TInt aFrequency"
sl@0
   728
 *			Frequency at with the tone will be played.
sl@0
   729
 *
sl@0
   730
 *	@param	"TTimeIntervalMicroSeconds& aDuration"
sl@0
   731
 *			The period over which the tone will be played. A zero value causes
sl@0
   732
 *			the no tone to be played (Verify this with test app).
sl@0
   733
 *
sl@0
   734
 */
sl@0
   735
void CMMFDevSoundSvrImp::PlayToneL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration)
sl@0
   736
	{
sl@0
   737
	if (iMode != EMMFDevSoundStateTonePlaying)
sl@0
   738
		{
sl@0
   739
		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
sl@0
   740
		}
sl@0
   741
sl@0
   742
	// Check whether frequency and duration is valid or not
sl@0
   743
	TInt64 zeroInt64(0);
sl@0
   744
	if ((aFrequency<0) || (aDuration.Int64() < zeroInt64))
sl@0
   745
		{
sl@0
   746
		User::Leave(KErrArgument);
sl@0
   747
		}
sl@0
   748
sl@0
   749
	if (!iDevSoundObserver)
sl@0
   750
		{
sl@0
   751
		User::Leave(KErrNotReady);
sl@0
   752
		}
sl@0
   753
sl@0
   754
	iToneGen.SetFrequencyAndDuration(aFrequency,aDuration);
sl@0
   755
sl@0
   756
	// Get audio policy
sl@0
   757
	iAudioPolicyPrioritySettings.iState = EMMFStatePlayTone;
sl@0
   758
	RequestPolicy();
sl@0
   759
	}
sl@0
   760
sl@0
   761
/*
sl@0
   762
 *	Initializes audio device and start playing a dual tone. 
sl@0
   763
 *  The tone consists of two sine waves of different frequencies summed together
sl@0
   764
 *  Dual Tone is played with specified frequencies and for specified duration.
sl@0
   765
 *
sl@0
   766
 *	@param	"aFrequencyOne"
sl@0
   767
 *			First frequency of dual tone
sl@0
   768
 *
sl@0
   769
 *	@param	"aFrequencyTwo"
sl@0
   770
 *			Second frequency of dual tone
sl@0
   771
 *
sl@0
   772
 *	@param	"aDuration"
sl@0
   773
 *			The period over which the tone will be played. A zero value causes
sl@0
   774
 *			the no tone to be played (Verify this with test app).
sl@0
   775
 */
sl@0
   776
void CMMFDevSoundSvrImp::PlayDualToneL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration)
sl@0
   777
	{
sl@0
   778
	if (!iDevSoundObserver)
sl@0
   779
		{
sl@0
   780
		User::Leave(KErrNotReady);
sl@0
   781
		}
sl@0
   782
	
sl@0
   783
	// Check whether frequencies and duration are valid or not
sl@0
   784
	TInt64 zeroInt64(0);
sl@0
   785
	if ((aFrequencyOne<0) || (aFrequencyTwo<0) || (aDuration.Int64() < zeroInt64))
sl@0
   786
		{
sl@0
   787
		iDevSoundObserver->ToneFinished(KErrArgument);
sl@0
   788
		return;
sl@0
   789
		}
sl@0
   790
sl@0
   791
sl@0
   792
	iDualToneGen.SetFrequencyAndDuration(aFrequencyOne, aFrequencyTwo, aDuration);
sl@0
   793
sl@0
   794
	// Get audio policy
sl@0
   795
	iAudioPolicyPrioritySettings.iState = EMMFStatePlayDualTone;
sl@0
   796
	RequestPolicy();
sl@0
   797
	}
sl@0
   798
sl@0
   799
/*
sl@0
   800
 *
sl@0
   801
 *	Initializes audio device and start playing DTMF string aDTMFString.
sl@0
   802
 *
sl@0
   803
 *	Leaves on failure.
sl@0
   804
 *
sl@0
   805
 *	@param	"TDesC& aDTMFString"
sl@0
   806
 *			DTMF sequence in a descriptor.
sl@0
   807
 *
sl@0
   808
 */
sl@0
   809
void CMMFDevSoundSvrImp::PlayDTMFStringL(const TDesC& aDTMFString)
sl@0
   810
	{
sl@0
   811
	if (!iDevSoundObserver)
sl@0
   812
		User::Leave(KErrNotReady);
sl@0
   813
sl@0
   814
	if (iMode!= EMMFDevSoundStateTonePlaying)
sl@0
   815
		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
sl@0
   816
sl@0
   817
	iDTMFGen.SetString(aDTMFString);
sl@0
   818
sl@0
   819
	// Get audio policy
sl@0
   820
	iAudioPolicyPrioritySettings.iState = EMMFStatePlayDTMFString;
sl@0
   821
	RequestPolicy();
sl@0
   822
	}
sl@0
   823
sl@0
   824
/*
sl@0
   825
 *
sl@0
   826
 *	Initializes audio device and start playing tone sequence.
sl@0
   827
 *
sl@0
   828
 *	Leaves on failure.
sl@0
   829
 *
sl@0
   830
 *	@param	"TDesC8& aData"
sl@0
   831
 *			Tone sequence in a descriptor.
sl@0
   832
 *
sl@0
   833
 */
sl@0
   834
void CMMFDevSoundSvrImp::PlayToneSequenceL(const TDesC8& aData)
sl@0
   835
	{
sl@0
   836
	if (!iDevSoundObserver)
sl@0
   837
		User::Leave(KErrNotReady);
sl@0
   838
sl@0
   839
	if (iMode!= EMMFDevSoundStateTonePlaying)
sl@0
   840
		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
sl@0
   841
sl@0
   842
	// Check whether the sequence is valid or not
sl@0
   843
	if (!iDevSoundUtil->RecognizeSequence(aData))
sl@0
   844
		User::Leave(KErrCorrupt);
sl@0
   845
sl@0
   846
	iSequenceGen.SetSequenceData(aData);
sl@0
   847
sl@0
   848
	// Get audio policy
sl@0
   849
	iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
sl@0
   850
	RequestPolicy();
sl@0
   851
	}
sl@0
   852
sl@0
   853
/*
sl@0
   854
 *
sl@0
   855
 *	Initializes audio device and start playing the specified pre-defined tone
sl@0
   856
 *	sequence.
sl@0
   857
 *
sl@0
   858
 *	Leaves on failure.
sl@0
   859
 *
sl@0
   860
 *	@param	"TInt aSequenceNumber"
sl@0
   861
 *			The index identifying the specific pre-defined tone sequence. Index
sl@0
   862
 *			values are relative to zero.
sl@0
   863
 *			This can be any value from zero to the value returned by a call to
sl@0
   864
 *			FixedSequenceCount() - 1.
sl@0
   865
 *			The function raises a panic if sequence number is not within this
sl@0
   866
 *			range.
sl@0
   867
 *
sl@0
   868
 *	@see	FixesSequenceCount()
sl@0
   869
 *
sl@0
   870
 */
sl@0
   871
void CMMFDevSoundSvrImp::PlayFixedSequenceL(TInt aSequenceNumber)
sl@0
   872
	{
sl@0
   873
	if (!iDevSoundObserver)
sl@0
   874
		User::Leave(KErrNotReady);
sl@0
   875
sl@0
   876
	if (iMode!= EMMFDevSoundStateTonePlaying)
sl@0
   877
		User::Leave(KErrNotSupported); //tone playing only supported in tone play state
sl@0
   878
sl@0
   879
	ASSERT((aSequenceNumber >= 0)&&(aSequenceNumber < iFixedSequences->Count()));
sl@0
   880
sl@0
   881
	iFixedSequence.Set(iFixedSequences->MdcaPoint(aSequenceNumber));
sl@0
   882
	iSequenceGen.SetSequenceData(iFixedSequence);
sl@0
   883
sl@0
   884
	// Get audio policy
sl@0
   885
	iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
sl@0
   886
	RequestPolicy();
sl@0
   887
	}
sl@0
   888
sl@0
   889
/*
sl@0
   890
 *
sl@0
   891
 *	Defines the duration of tone on, tone off and tone pause to be used during the
sl@0
   892
 *	DTMF tone playback operation.
sl@0
   893
 *
sl@0
   894
 *	Supported only during tone playing.
sl@0
   895
 *
sl@0
   896
 *	@param	"TTimeIntervalMicroSeconds32& aToneOnLength"
sl@0
   897
 *			The period over which the tone will be played. If this is set to
sl@0
   898
 *			zero, then the tone is not played.
sl@0
   899
 *
sl@0
   900
 *	@param	"TTimeIntervalMicroSeconds32& aToneOffLength"
sl@0
   901
 *			The period over which the no tone will be played.
sl@0
   902
 *
sl@0
   903
 *	@param	"TTimeIntervalMicroSeconds32& aPauseLength"
sl@0
   904
 *			The period over which the tone playing will be paused.
sl@0
   905
 *
sl@0
   906
 */
sl@0
   907
void CMMFDevSoundSvrImp::SetDTMFLengths(TTimeIntervalMicroSeconds32& aToneOnLength,
sl@0
   908
								TTimeIntervalMicroSeconds32& aToneOffLength,
sl@0
   909
								TTimeIntervalMicroSeconds32& aPauseLength) 
sl@0
   910
	{
sl@0
   911
sl@0
   912
	if(aToneOnLength.Int() < KMdaInfiniteDurationDTMFToneOnLength)
sl@0
   913
		aToneOnLength = TTimeIntervalMicroSeconds32(0);
sl@0
   914
	if(aToneOffLength.Int() < 0)
sl@0
   915
		aToneOffLength = TTimeIntervalMicroSeconds32(0);
sl@0
   916
	if(aPauseLength.Int() < 0)
sl@0
   917
		aPauseLength = TTimeIntervalMicroSeconds32(0);
sl@0
   918
sl@0
   919
	iDTMFGen.SetToneDurations(aToneOnLength,aToneOffLength,aPauseLength);
sl@0
   920
	}
sl@0
   921
sl@0
   922
/*
sl@0
   923
 *
sl@0
   924
 *	Defines the period over which the volume level is to rise smoothly from
sl@0
   925
 *	nothing to the normal volume level.
sl@0
   926
 *
sl@0
   927
 *	@param	"TTimeIntervalMicroSeconds& aRampDuration"
sl@0
   928
 *			The period over which the volume is to rise. A zero value causes 
sl@0
   929
 *			the tone sample to be played at the normal level for the full
sl@0
   930
 *			duration of the playback. A value, which is longer than the duration
sl@0
   931
 *			of the tone sample, that the sample never reaches its normal
sl@0
   932
 *			volume level.
sl@0
   933
 *
sl@0
   934
 *
sl@0
   935
 */
sl@0
   936
void CMMFDevSoundSvrImp::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
sl@0
   937
	{
sl@0
   938
	// save ramp duration for tone generator
sl@0
   939
	iRampDuration = aRampDuration;
sl@0
   940
sl@0
   941
	SetDeviceVolumeRamp(iRampDuration);
sl@0
   942
	}
sl@0
   943
sl@0
   944
/**
sl@0
   945
 *	Sets volume ramp on HwDevice.
sl@0
   946
 */
sl@0
   947
TInt CMMFDevSoundSvrImp::SetDeviceVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
sl@0
   948
	{
sl@0
   949
	TInt error = KErrNone;
sl@0
   950
	if (iPlayCustomInterface) 
sl@0
   951
		iPlayCustomInterface->SetVolumeRamp(aRampDuration);
sl@0
   952
	else
sl@0
   953
		error = KErrNotReady;
sl@0
   954
	return error;
sl@0
   955
    }
sl@0
   956
sl@0
   957
/**
sl@0
   958
 *	@see sounddevice.h
sl@0
   959
 */
sl@0
   960
void CMMFDevSoundSvrImp::GetSupportedInputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
sl@0
   961
	{
sl@0
   962
	//aPrioritySettings not used on ref DevSound
sl@0
   963
	//search for playing datatypes
sl@0
   964
	iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStatePlaying);
sl@0
   965
#ifdef SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
   966
	// append list of codec plugins
sl@0
   967
	iDevSoundUtil->SeekCodecPluginsL(aSupportedDataTypes, EMMFStatePlaying, ETrue);
sl@0
   968
#endif // SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
   969
	}
sl@0
   970
sl@0
   971
/**
sl@0
   972
 *	@see sounddevice.h
sl@0
   973
 */
sl@0
   974
void CMMFDevSoundSvrImp::GetSupportedOutputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
sl@0
   975
	{
sl@0
   976
	//aPrioritySettings not used on ref DevSound
sl@0
   977
	// search for recording datatypes
sl@0
   978
	iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStateRecording);
sl@0
   979
#ifdef SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
   980
	// append list of codec plugins
sl@0
   981
	iDevSoundUtil->SeekCodecPluginsL(aSupportedDataTypes, EMMFStateRecording, ETrue);
sl@0
   982
#endif // SYMBIAN_MULTIMEDIA_CODEC_API
sl@0
   983
	}
sl@0
   984
	
sl@0
   985
TInt CMMFDevSoundSvrImp::RegisterAsClient(TUid aEventType, const TDesC8& aNotificationRegistrationData)
sl@0
   986
	{	
sl@0
   987
	return iAudioPolicyProxy->RequestResourceNotification(aEventType,aNotificationRegistrationData);
sl@0
   988
	}
sl@0
   989
	
sl@0
   990
TInt CMMFDevSoundSvrImp::CancelRegisterAsClient(TUid aEventType)
sl@0
   991
	{	
sl@0
   992
	return iAudioPolicyProxy->CancelRequestResourceNotification(aEventType);
sl@0
   993
	}
sl@0
   994
sl@0
   995
TInt CMMFDevSoundSvrImp::GetResourceNotificationData(TUid aEventType, TDes8& aNotificationData)
sl@0
   996
	{	
sl@0
   997
	TInt err = KErrNone;
sl@0
   998
	err = iAudioPolicyProxy->IsRegisteredResourceNotification(aEventType);
sl@0
   999
	if(err == KErrNone)
sl@0
  1000
		{
sl@0
  1001
		TMMFTimeIntervalMicroSecondsPckg pckg = TTimeIntervalMicroSeconds(SamplesPlayed());
sl@0
  1002
		aNotificationData.Copy(pckg);
sl@0
  1003
		}
sl@0
  1004
	return err;
sl@0
  1005
	}
sl@0
  1006
	
sl@0
  1007
TInt CMMFDevSoundSvrImp::WillResumePlay()
sl@0
  1008
	{
sl@0
  1009
	return iAudioPolicyProxy->StopNotification();
sl@0
  1010
	}	
sl@0
  1011
	
sl@0
  1012
TInt CMMFDevSoundSvrImp::EmptyBuffers()
sl@0
  1013
	{
sl@0
  1014
	TInt err = KErrNone;
sl@0
  1015
	if (iMode != EMMFStatePlaying)
sl@0
  1016
		{
sl@0
  1017
		return KErrNotSupported;
sl@0
  1018
		}
sl@0
  1019
	if (!iCMMFHwDevice)
sl@0
  1020
		{
sl@0
  1021
		return KErrNotReady;			
sl@0
  1022
		}	
sl@0
  1023
	MEmptyBuffersCustomInterface* emptybuffers = reinterpret_cast<MEmptyBuffersCustomInterface*>(iCMMFHwDevice->CustomInterface(KEmptyBuffersCustomInterfaceTypeUid));	
sl@0
  1024
	if (emptybuffers)
sl@0
  1025
    	{
sl@0
  1026
       	err = emptybuffers->EmptyBuffers();
sl@0
  1027
     	}
sl@0
  1028
    else
sl@0
  1029
		{
sl@0
  1030
     	err = KErrNotSupported;
sl@0
  1031
     	}
sl@0
  1032
    return err;	
sl@0
  1033
	}	
sl@0
  1034
sl@0
  1035
TInt CMMFDevSoundSvrImp::GetTimePlayed(TTimeIntervalMicroSeconds& aTime)
sl@0
  1036
	{
sl@0
  1037
	TInt err = KErrNone;
sl@0
  1038
	TTimeIntervalMicroSeconds time(0);
sl@0
  1039
	if(iCMMFHwDevice)
sl@0
  1040
		{
sl@0
  1041
		if(!iTimePlayedCustomInterface)
sl@0
  1042
			{
sl@0
  1043
			iTimePlayedCustomInterface = reinterpret_cast<MTimePlayedCustomInterface*>(iCMMFHwDevice->CustomInterface(KTimePlayedCustomInterfaceTypeUid));
sl@0
  1044
			if(iTimePlayedCustomInterface == NULL)
sl@0
  1045
				{
sl@0
  1046
				return KErrNotSupported;
sl@0
  1047
				}
sl@0
  1048
			}
sl@0
  1049
		err = iTimePlayedCustomInterface->GetTimePlayed(time);
sl@0
  1050
	    if(err == KErrNone && time.Int64() > 0)
sl@0
  1051
	    	{
sl@0
  1052
	    	iTimePlayed = time.Int64();
sl@0
  1053
	    	}
sl@0
  1054
		}
sl@0
  1055
	aTime = iTimePlayed.Int64();
sl@0
  1056
	return err;
sl@0
  1057
	}
sl@0
  1058
sl@0
  1059
/********************************************************************************
sl@0
  1060
 *				Implementations of Non Exported public functions begins here	*
sl@0
  1061
 ********************************************************************************/
sl@0
  1062
sl@0
  1063
//
sl@0
  1064
//				Audio Policy specific implementation begins here				//
sl@0
  1065
//
sl@0
  1066
sl@0
  1067
/*
sl@0
  1068
 *
sl@0
  1069
 *	Called by Audio Policy Server when a request to play is approved by the 
sl@0
  1070
 *	Audio Policy Server.
sl@0
  1071
 *
sl@0
  1072
 *	Leaves on failure??.
sl@0
  1073
 *
sl@0
  1074
 */
sl@0
  1075
void CMMFDevSoundSvrImp::StartPlayDataL()
sl@0
  1076
	{
sl@0
  1077
	ASSERT(iMode== EMMFDevSoundStatePlaying);
sl@0
  1078
	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
sl@0
  1079
		{
sl@0
  1080
		return;
sl@0
  1081
		}
sl@0
  1082
	iHasPolicy = ETrue;
sl@0
  1083
sl@0
  1084
	TInt error = KErrNone;
sl@0
  1085
sl@0
  1086
	if(iCMMFHwDevice)
sl@0
  1087
		{
sl@0
  1088
		UpdatePolicyState(EMMFStatePlayData);		
sl@0
  1089
        // Set volume and play format values
sl@0
  1090
        error = SetPlayFormat(iPlayFormat);
sl@0
  1091
        if (error == KErrNone)
sl@0
  1092
			error = SetDeviceVolume(iVolume);
sl@0
  1093
        if (error == KErrNone)
sl@0
  1094
			error = SetDeviceVolumeRamp(iRampDuration);
sl@0
  1095
sl@0
  1096
		// Initialize attribute values
sl@0
  1097
		iPlayedBytesCount = 0;
sl@0
  1098
		iTimePlayed = 0;
sl@0
  1099
		iLastBufferReceived = EFalse;
sl@0
  1100
sl@0
  1101
        // Start HwDevice
sl@0
  1102
        if (error == KErrNone)
sl@0
  1103
	        error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
sl@0
  1104
		}
sl@0
  1105
	else
sl@0
  1106
		error = KErrNotReady;
sl@0
  1107
	
sl@0
  1108
	if (error != KErrNone)
sl@0
  1109
		{
sl@0
  1110
		Error(error);
sl@0
  1111
sl@0
  1112
		}
sl@0
  1113
	}
sl@0
  1114
sl@0
  1115
/*
sl@0
  1116
 *
sl@0
  1117
 *	Called by Audio Policy Server when a request to record is approved by the 
sl@0
  1118
 *	Audio Policy Server.
sl@0
  1119
 *
sl@0
  1120
 *	Leaves on failure.
sl@0
  1121
 *
sl@0
  1122
 */
sl@0
  1123
void CMMFDevSoundSvrImp::StartRecordDataL()
sl@0
  1124
	{
sl@0
  1125
	ASSERT(iMode== EMMFDevSoundStateRecording);
sl@0
  1126
	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
sl@0
  1127
		{
sl@0
  1128
		return;
sl@0
  1129
		}
sl@0
  1130
	iHasPolicy = ETrue;
sl@0
  1131
sl@0
  1132
	 if(iCMMFHwDevice)
sl@0
  1133
		{
sl@0
  1134
		UpdatePolicyState(EMMFStateRecordData);
sl@0
  1135
        TInt error = KErrNone;
sl@0
  1136
        error = SetRecordFormat(iRecordFormat);
sl@0
  1137
		if (error != KErrNone)
sl@0
  1138
			{
sl@0
  1139
			Error(error);
sl@0
  1140
			return;
sl@0
  1141
sl@0
  1142
			}
sl@0
  1143
        error = SetDeviceRecordLevel(iGain);
sl@0
  1144
		if (error != KErrNone)
sl@0
  1145
			{
sl@0
  1146
			Error(error);
sl@0
  1147
			return;
sl@0
  1148
sl@0
  1149
			}
sl@0
  1150
        error = iCMMFHwDevice->Start(EDevEncode, EDevInFlow);
sl@0
  1151
		if (iHwDeviceBuffer)
sl@0
  1152
			iHwDeviceBuffer->SetLastBuffer(EFalse);
sl@0
  1153
sl@0
  1154
		if (error != KErrNone)
sl@0
  1155
			{
sl@0
  1156
			Error(error);
sl@0
  1157
			return;
sl@0
  1158
			}
sl@0
  1159
        }
sl@0
  1160
	else
sl@0
  1161
		iDevSoundObserver->RecordError(KErrNotReady);
sl@0
  1162
	}
sl@0
  1163
sl@0
  1164
/*
sl@0
  1165
 *
sl@0
  1166
 *	Called by Audio Policy Server when a request to play tone is approved by
sl@0
  1167
 *	the Audio Policy Server.
sl@0
  1168
 *
sl@0
  1169
 *	Leaves on failure.
sl@0
  1170
 *
sl@0
  1171
 */
sl@0
  1172
void CMMFDevSoundSvrImp::StartPlayToneL()
sl@0
  1173
	{
sl@0
  1174
	ASSERT(iMode == EMMFDevSoundStateTonePlaying);
sl@0
  1175
	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
sl@0
  1176
		{
sl@0
  1177
		return;
sl@0
  1178
		}
sl@0
  1179
	iHasPolicy = ETrue;
sl@0
  1180
	
sl@0
  1181
	if(iCMMFHwDevice)
sl@0
  1182
		{
sl@0
  1183
		UpdatePolicyState(EMMFStatePlayTone);
sl@0
  1184
        TInt error = KErrNone;
sl@0
  1185
        // Set volume and play format values
sl@0
  1186
        error = SetPlayFormat(iPlayFormat);
sl@0
  1187
		if (error != KErrNone)
sl@0
  1188
			{
sl@0
  1189
			Error(error);
sl@0
  1190
			return;
sl@0
  1191
sl@0
  1192
			}
sl@0
  1193
        if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
sl@0
  1194
            error = SetDeviceVolume(iVolume);
sl@0
  1195
		else
sl@0
  1196
			error = KErrGeneral;//hw device should always be pcm16 for tone
sl@0
  1197
sl@0
  1198
		// turn off volume ramping - this is done in software below
sl@0
  1199
        if (error == KErrNone)
sl@0
  1200
			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
sl@0
  1201
sl@0
  1202
        if (error != KErrNone)
sl@0
  1203
            {
sl@0
  1204
            Error(error);
sl@0
  1205
            return;
sl@0
  1206
sl@0
  1207
            }
sl@0
  1208
sl@0
  1209
        // Initialize attribute values
sl@0
  1210
		iPlayedBytesCount = 0;
sl@0
  1211
		iTimePlayed = 0;
sl@0
  1212
        // Configure tone generator
sl@0
  1213
        iToneGen.Configure(
sl@0
  1214
			iPlayFormat().iRate,
sl@0
  1215
			iPlayFormat().iChannels,
sl@0
  1216
		    iRepeatCount,
sl@0
  1217
			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
sl@0
  1218
			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
sl@0
  1219
			);
sl@0
  1220
sl@0
  1221
		iCurrentGenerator = &iToneGen;
sl@0
  1222
sl@0
  1223
        // Start playback
sl@0
  1224
        DoPlayL();
sl@0
  1225
		}
sl@0
  1226
	else
sl@0
  1227
		iDevSoundObserver->ToneFinished(KErrNotReady);
sl@0
  1228
	}
sl@0
  1229
sl@0
  1230
/*
sl@0
  1231
 *
sl@0
  1232
 *	Called by Audio Policy Server when a request to play a dual tone is approved by
sl@0
  1233
 *	the Audio Policy Server.
sl@0
  1234
 *
sl@0
  1235
 */
sl@0
  1236
void CMMFDevSoundSvrImp::StartPlayDualToneL()
sl@0
  1237
	{
sl@0
  1238
	ASSERT(iMode == EMMFDevSoundStateTonePlaying);
sl@0
  1239
	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
sl@0
  1240
		{
sl@0
  1241
		return;
sl@0
  1242
		}
sl@0
  1243
	iHasPolicy = ETrue;
sl@0
  1244
sl@0
  1245
	 if(iCMMFHwDevice)
sl@0
  1246
		{
sl@0
  1247
		UpdatePolicyState(EMMFStatePlayDualTone);
sl@0
  1248
        TInt error = KErrNone;
sl@0
  1249
        // Set volume and play format values
sl@0
  1250
        error = SetPlayFormat(iPlayFormat);
sl@0
  1251
		if (error != KErrNone)
sl@0
  1252
			{
sl@0
  1253
			Error(error);
sl@0
  1254
			return;
sl@0
  1255
			}
sl@0
  1256
        if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
sl@0
  1257
            error = SetDeviceVolume(iVolume);
sl@0
  1258
		else 
sl@0
  1259
			error = KErrGeneral;//hw device should always be pcm16 for tone
sl@0
  1260
sl@0
  1261
		// turn off volume ramping - this is done in software below
sl@0
  1262
        if (error == KErrNone)
sl@0
  1263
			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
sl@0
  1264
sl@0
  1265
        if (error != KErrNone)
sl@0
  1266
            {
sl@0
  1267
            Error(error);
sl@0
  1268
            return;
sl@0
  1269
sl@0
  1270
            }
sl@0
  1271
sl@0
  1272
        // Initialize attribute values
sl@0
  1273
		iPlayedBytesCount = 0;
sl@0
  1274
		iTimePlayed = 0;
sl@0
  1275
        // Configure dual tone generator
sl@0
  1276
		iDualToneGen.Configure(
sl@0
  1277
			iPlayFormat().iRate,
sl@0
  1278
			iPlayFormat().iChannels,
sl@0
  1279
			iRepeatCount,
sl@0
  1280
			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds),
sl@0
  1281
			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds)
sl@0
  1282
			);
sl@0
  1283
sl@0
  1284
		iCurrentGenerator = &iDualToneGen;
sl@0
  1285
sl@0
  1286
        // Start playback
sl@0
  1287
        DoPlayL();
sl@0
  1288
		}
sl@0
  1289
	else
sl@0
  1290
		iDevSoundObserver->ToneFinished(KErrNotReady);
sl@0
  1291
	}
sl@0
  1292
sl@0
  1293
/*
sl@0
  1294
 *
sl@0
  1295
 *	Called by Audio Policy Server when a request to play DTMF String is approved
sl@0
  1296
 *	by the Audio Policy Server.
sl@0
  1297
 *
sl@0
  1298
 *	Leaves on failure.
sl@0
  1299
 *
sl@0
  1300
 */
sl@0
  1301
void CMMFDevSoundSvrImp::StartPlayDTMFStringL()
sl@0
  1302
	{
sl@0
  1303
	ASSERT(iMode == EMMFDevSoundStateTonePlaying);
sl@0
  1304
	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
sl@0
  1305
		{
sl@0
  1306
		return;
sl@0
  1307
		}
sl@0
  1308
	iHasPolicy = ETrue;
sl@0
  1309
sl@0
  1310
	if(iCMMFHwDevice)
sl@0
  1311
		{
sl@0
  1312
		UpdatePolicyState(EMMFStatePlayDTMFString);
sl@0
  1313
        TInt error = KErrNone;
sl@0
  1314
        // Set volume and play format values
sl@0
  1315
        error = SetPlayFormat(iPlayFormat);
sl@0
  1316
		if (error != KErrNone)
sl@0
  1317
            {
sl@0
  1318
            Error(error);
sl@0
  1319
            return;
sl@0
  1320
sl@0
  1321
            }
sl@0
  1322
        error = SetDeviceVolume(iVolume);
sl@0
  1323
sl@0
  1324
		// turn off volume ramping - this is done in software below
sl@0
  1325
        if (error == KErrNone)
sl@0
  1326
			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
sl@0
  1327
sl@0
  1328
        if (error != KErrNone)
sl@0
  1329
            {
sl@0
  1330
            Error(error);
sl@0
  1331
            return;
sl@0
  1332
            }
sl@0
  1333
sl@0
  1334
        // Initialize attribute values
sl@0
  1335
		iPlayedBytesCount = 0;
sl@0
  1336
		iTimePlayed = 0;
sl@0
  1337
	    iDTMFGen.Configure(
sl@0
  1338
			iPlayFormat().iRate,
sl@0
  1339
			iPlayFormat().iChannels,
sl@0
  1340
		    iRepeatCount,
sl@0
  1341
			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
sl@0
  1342
		    I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
sl@0
  1343
			);
sl@0
  1344
sl@0
  1345
		iCurrentGenerator = &iDTMFGen;
sl@0
  1346
sl@0
  1347
        // Start playback
sl@0
  1348
		//need to trap this as we can leave with KErrUnderflow
sl@0
  1349
		//if there was no data to play - the error has already
sl@0
  1350
		//been sent to the observer and we don't want to call RunError
sl@0
  1351
        TRAP(error,DoPlayL());
sl@0
  1352
		if ((error != KErrUnderflow)&&(error != KErrNone))
sl@0
  1353
			{
sl@0
  1354
			User::Leave(error);
sl@0
  1355
			}
sl@0
  1356
		}
sl@0
  1357
	else
sl@0
  1358
		iDevSoundObserver->ToneFinished(KErrNotReady);
sl@0
  1359
	}
sl@0
  1360
sl@0
  1361
/*
sl@0
  1362
 *
sl@0
  1363
 *	Called by Audio Policy Server when a request to play tone sequence is
sl@0
  1364
 *	approved by the Audio Policy Server.
sl@0
  1365
 *
sl@0
  1366
 *	Leaves on failure.
sl@0
  1367
 *
sl@0
  1368
 */
sl@0
  1369
void CMMFDevSoundSvrImp::StartPlayToneSequenceL()
sl@0
  1370
	{
sl@0
  1371
	ASSERT(iMode == EMMFDevSoundStateTonePlaying);
sl@0
  1372
	if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
sl@0
  1373
		{
sl@0
  1374
		return;
sl@0
  1375
		}
sl@0
  1376
	iHasPolicy = ETrue;
sl@0
  1377
sl@0
  1378
	if(iCMMFHwDevice)
sl@0
  1379
		{
sl@0
  1380
		UpdatePolicyState(EMMFStatePlayToneSequence);
sl@0
  1381
        TInt error = KErrNone;
sl@0
  1382
        // Set volume and play format values
sl@0
  1383
        if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
sl@0
  1384
            error = SetPlayFormat(iPlayFormat);
sl@0
  1385
			else error = KErrGeneral;//hw device should always be pcm16 for tone
sl@0
  1386
		if (error != KErrNone)
sl@0
  1387
            {
sl@0
  1388
            Error(error);
sl@0
  1389
            return;
sl@0
  1390
            }
sl@0
  1391
sl@0
  1392
        if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
sl@0
  1393
            error = SetDeviceVolume(iVolume);
sl@0
  1394
		else 
sl@0
  1395
			error = KErrGeneral;//hw device should always be pcm16 for tone
sl@0
  1396
sl@0
  1397
		// turn off volume ramping - this is done in software below
sl@0
  1398
        if (error == KErrNone)
sl@0
  1399
			error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
sl@0
  1400
sl@0
  1401
        if (error != KErrNone)
sl@0
  1402
            {
sl@0
  1403
            Error(error);
sl@0
  1404
            return;
sl@0
  1405
            }
sl@0
  1406
sl@0
  1407
        // Initialize attribute values
sl@0
  1408
		iPlayedBytesCount = 0;
sl@0
  1409
		iTimePlayed = 0;
sl@0
  1410
		iSequenceGen.Configure(
sl@0
  1411
			iPlayFormat().iRate,
sl@0
  1412
			iPlayFormat().iChannels,
sl@0
  1413
			iRepeatCount,
sl@0
  1414
			I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
sl@0
  1415
			I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
sl@0
  1416
			);
sl@0
  1417
sl@0
  1418
		iCurrentGenerator = &iSequenceGen;
sl@0
  1419
sl@0
  1420
        // Start playback
sl@0
  1421
        DoPlayL();
sl@0
  1422
		}
sl@0
  1423
	else
sl@0
  1424
		iDevSoundObserver->ToneFinished(KErrNotReady);
sl@0
  1425
	}
sl@0
  1426
sl@0
  1427
/*
sl@0
  1428
 *
sl@0
  1429
 *	Called by Audio Policy Server when the current DevSound instance looses the
sl@0
  1430
 *	policy because of another instance with a higher priority wants the device.
sl@0
  1431
 *
sl@0
  1432
 */
sl@0
  1433
void CMMFDevSoundSvrImp::SendEventToClient(const TMMFEvent& aEvent)
sl@0
  1434
	{
sl@0
  1435
	if (aEvent.iErrorCode != KErrNone)
sl@0
  1436
		{
sl@0
  1437
		iHasPolicy = EFalse;
sl@0
  1438
		if (iMode == EMMFDevSoundStatePlaying)
sl@0
  1439
			{
sl@0
  1440
			UpdateBytesPlayed();
sl@0
  1441
			iDevSoundObserver->PlayError(aEvent.iErrorCode);
sl@0
  1442
			UpdatePolicyState(EMMFStateStopped);
sl@0
  1443
			}
sl@0
  1444
		else if (iMode == EMMFDevSoundStateRecording)
sl@0
  1445
			{
sl@0
  1446
			iDevSoundObserver->RecordError(aEvent.iErrorCode);
sl@0
  1447
			UpdatePolicyState(EMMFStateStopped);
sl@0
  1448
			}
sl@0
  1449
		else if (iMode == EMMFDevSoundStateTonePlaying)
sl@0
  1450
			{
sl@0
  1451
			iDevSoundObserver->ToneFinished(aEvent.iErrorCode);
sl@0
  1452
			}			
sl@0
  1453
		iCMMFHwDevice->Stop();//unloads sound device
sl@0
  1454
		// Have audio Policy launch higher priority request
sl@0
  1455
		iAudioPolicyProxy->LaunchRequests();
sl@0
  1456
		}
sl@0
  1457
	else
sl@0
  1458
		{
sl@0
  1459
		iHasPolicy = ETrue;
sl@0
  1460
		iDevSoundObserver->SendEventToClient(aEvent);
sl@0
  1461
		}
sl@0
  1462
	}
sl@0
  1463
sl@0
  1464
sl@0
  1465
/**
sl@0
  1466
 *
sl@0
  1467
 *	Sets volume on HwDevice.
sl@0
  1468
 *	
sl@0
  1469
 *	@return	"TInt"
sl@0
  1470
 *			Error value returned by HwDevice.
sl@0
  1471
 *
sl@0
  1472
 */
sl@0
  1473
TInt CMMFDevSoundSvrImp::SetDeviceVolume(TInt aVolume)
sl@0
  1474
	{
sl@0
  1475
	TInt error = KErrNone;
sl@0
  1476
	if (iPlayCustomInterface) 
sl@0
  1477
		iPlayCustomInterface->SetVolume(aVolume);
sl@0
  1478
	else error = KErrNotReady;
sl@0
  1479
	return error;
sl@0
  1480
    }
sl@0
  1481
sl@0
  1482
/**
sl@0
  1483
 *
sl@0
  1484
 *	Sets PlayFormat on HwDevice.
sl@0
  1485
 *	
sl@0
  1486
 *
sl@0
  1487
 *	@return	"TInt"
sl@0
  1488
 *			Error value returned by HwDevice.
sl@0
  1489
 *
sl@0
  1490
 */
sl@0
  1491
TInt CMMFDevSoundSvrImp::SetPlayFormat(RMdaDevSound::TCurrentSoundFormatBuf& aPlayFormat)
sl@0
  1492
	{
sl@0
  1493
	TInt error = KErrNone;
sl@0
  1494
	if (iCMMFHwDevice)
sl@0
  1495
		{
sl@0
  1496
		TTaskConfig taskConfig;
sl@0
  1497
		taskConfig.iUid = KUidRefDevSoundTaskConfig;
sl@0
  1498
		taskConfig.iRate = aPlayFormat().iRate;
sl@0
  1499
		
sl@0
  1500
		if (aPlayFormat().iChannels == 1)
sl@0
  1501
			{
sl@0
  1502
			taskConfig.iStereoMode = ETaskMono;
sl@0
  1503
			}
sl@0
  1504
		else if (aPlayFormat().iChannels == 2)
sl@0
  1505
			{
sl@0
  1506
			taskConfig.iStereoMode = ETaskInterleaved;
sl@0
  1507
			}
sl@0
  1508
		else
sl@0
  1509
			{
sl@0
  1510
			return KErrArgument;
sl@0
  1511
			}
sl@0
  1512
sl@0
  1513
		error = iCMMFHwDevice->SetConfig(taskConfig);
sl@0
  1514
		//note the iEncoding and iBufferSize are already determined by the 
sl@0
  1515
		//CMMFHwDevice plugin and so are not set.
sl@0
  1516
		}
sl@0
  1517
	else
sl@0
  1518
		{
sl@0
  1519
		error = KErrNotReady;
sl@0
  1520
		}
sl@0
  1521
	return error;
sl@0
  1522
    }
sl@0
  1523
sl@0
  1524
sl@0
  1525
/**
sl@0
  1526
 *
sl@0
  1527
 *	Sets RecordFormat on HwDevice.
sl@0
  1528
 *	
sl@0
  1529
 *
sl@0
  1530
 *	@return	"TInt"
sl@0
  1531
 *			Error value returned by HwDevice.
sl@0
  1532
 *
sl@0
  1533
 */
sl@0
  1534
TInt CMMFDevSoundSvrImp::SetRecordFormat(RMdaDevSound::TCurrentSoundFormatBuf& aRecordFormat)
sl@0
  1535
	{
sl@0
  1536
	TInt error = KErrNone;
sl@0
  1537
	if (iCMMFHwDevice)
sl@0
  1538
		{
sl@0
  1539
		TTaskConfig taskConfig;
sl@0
  1540
		taskConfig.iUid = KUidRefDevSoundTaskConfig;
sl@0
  1541
		taskConfig.iRate = aRecordFormat().iRate;
sl@0
  1542
sl@0
  1543
		if (aRecordFormat().iChannels == 1)
sl@0
  1544
			{
sl@0
  1545
			taskConfig.iStereoMode = ETaskMono;
sl@0
  1546
			}
sl@0
  1547
		else if (aRecordFormat().iChannels == 2)
sl@0
  1548
			{
sl@0
  1549
			taskConfig.iStereoMode = ETaskInterleaved;
sl@0
  1550
			}
sl@0
  1551
		else
sl@0
  1552
			{
sl@0
  1553
			return KErrArgument;
sl@0
  1554
			}
sl@0
  1555
sl@0
  1556
		error = iCMMFHwDevice->SetConfig(taskConfig);
sl@0
  1557
		//note the iEncoding and iBufferSize are already determined by the 
sl@0
  1558
		//CMMFHwDevice plugin and so are not set.
sl@0
  1559
		}
sl@0
  1560
	else
sl@0
  1561
		{
sl@0
  1562
		error = KErrNotReady;
sl@0
  1563
		}
sl@0
  1564
	return error;
sl@0
  1565
    }
sl@0
  1566
sl@0
  1567
sl@0
  1568
/**
sl@0
  1569
 *
sl@0
  1570
 *	Sets record level on HwDevice.
sl@0
  1571
 *	
sl@0
  1572
 *
sl@0
  1573
 *	@return	"TInt"
sl@0
  1574
 *			Error value returned by HwDevice.
sl@0
  1575
 *
sl@0
  1576
 */
sl@0
  1577
TInt CMMFDevSoundSvrImp::SetDeviceRecordLevel(TInt aGain)
sl@0
  1578
	{
sl@0
  1579
	TInt error = KErrNone;
sl@0
  1580
	if (iRecordCustomInterface) 
sl@0
  1581
		iRecordCustomInterface->SetGain(aGain);
sl@0
  1582
	else error = KErrNotReady;
sl@0
  1583
	return error;
sl@0
  1584
sl@0
  1585
    }
sl@0
  1586
sl@0
  1587
sl@0
  1588
/**
sl@0
  1589
 *
sl@0
  1590
 *	MMMFHwDeviceObserver mixin implementation.
sl@0
  1591
 *
sl@0
  1592
 *	The CMMFHwDevice implementation object calls this method during decoding
sl@0
  1593
 *	(playing), when it needs the encoded data in the buffer
sl@0
  1594
 *	aHwDataBuffer.
sl@0
  1595
 *
sl@0
  1596
 *	@return	"TInt"
sl@0
  1597
 *			Error code. KErrNone if success.
sl@0
  1598
 *
sl@0
  1599
 */
sl@0
  1600
TInt CMMFDevSoundSvrImp::FillThisHwBuffer(CMMFBuffer& aHwDataBuffer)
sl@0
  1601
	{
sl@0
  1602
	TInt err = KErrNone;
sl@0
  1603
    // Keep a reference to this Hw data Buffer. We need to send the 
sl@0
  1604
	// reference back to HwDevice implementation
sl@0
  1605
	iHwDeviceBuffer = static_cast<CMMFDataBuffer*> (&aHwDataBuffer);
sl@0
  1606
	// Set the request length, From HwDevice this comes with buffer
sl@0
  1607
	// length.
sl@0
  1608
	TInt len = iHwDeviceBuffer->Data().MaxLength();
sl@0
  1609
	// Ignore error. since buffer size = Buffer Length 
sl@0
  1610
	TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
sl@0
  1611
sl@0
  1612
	if (iMode== EMMFDevSoundStatePlaying) // Get Data from Observer
sl@0
  1613
		{
sl@0
  1614
		if (iLastBufferReceived)
sl@0
  1615
			{
sl@0
  1616
			iHwDeviceBuffer->Data().SetLength(0);
sl@0
  1617
			// Pass the buffer to the he device
sl@0
  1618
            err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
sl@0
  1619
			}
sl@0
  1620
		else
sl@0
  1621
			// Pass the buffer to the observer
sl@0
  1622
			iDevSoundObserver->BufferToBeFilled(&aHwDataBuffer);
sl@0
  1623
		}
sl@0
  1624
	else if (iMode == EMMFDevSoundStateTonePlaying)
sl@0
  1625
		{
sl@0
  1626
        // Hw device will call this method right after its Start was called.
sl@0
  1627
        // When it calls this for the first time it hasn't played one single
sl@0
  1628
        // buffer yet so check that.
sl@0
  1629
        // In this case there's no need to set the active buffer as it's already
sl@0
  1630
        // waiting to be played.
sl@0
  1631
        if (!iFirstCallFromHwDevice)
sl@0
  1632
            SetActiveToneBuffer();
sl@0
  1633
sl@0
  1634
		// If there is no data in the active buffer, tone play is finished.
sl@0
  1635
		// DevSound just have to wait for completion event from audio device.
sl@0
  1636
		if (iActiveToneBuffer->Data().Length() > 0)
sl@0
  1637
            { 
sl@0
  1638
			TInt tonelen = iActiveToneBuffer->Data().Length();
sl@0
  1639
sl@0
  1640
			// don't enter more data than can be handled by the receiving buffer
sl@0
  1641
			if (len >= tonelen) len = tonelen;
sl@0
  1642
sl@0
  1643
            // Copy data from tone buffer to hw device buffer
sl@0
  1644
            Mem::Copy((TAny*)(iHwDeviceBuffer->Data().Ptr()), (TAny*)(iActiveToneBuffer->Data().Ptr()), len);
sl@0
  1645
            
sl@0
  1646
            iHwDeviceBuffer->Data().SetLength(len);
sl@0
  1647
            // Play data and try to generate next data block
sl@0
  1648
			err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
sl@0
  1649
            if (err != KErrNone)
sl@0
  1650
            	return err;
sl@0
  1651
            // Check again whether this is the first call from Hw device.
sl@0
  1652
            // FillFreeToneBuffer assumes the iActiveToneBuffer has already
sl@0
  1653
            // been played.
sl@0
  1654
            if (!iFirstCallFromHwDevice)
sl@0
  1655
                err = FillFreeToneBuffer();
sl@0
  1656
            else
sl@0
  1657
                iFirstCallFromHwDevice = EFalse;  // Reset flag
sl@0
  1658
sl@0
  1659
 			}
sl@0
  1660
		else if (iFirstCallFromHwDevice)
sl@0
  1661
			{//we have no data in the tone buffer and thus have no 
sl@0
  1662
			//outstanding requests to play
sl@0
  1663
			err = KErrUnderflow; //simulate underrun
sl@0
  1664
			}
sl@0
  1665
		else
sl@0
  1666
			{
sl@0
  1667
			iHwDeviceBuffer->Data().SetLength(0);
sl@0
  1668
			iHwDeviceBuffer->SetLastBuffer(ETrue);
sl@0
  1669
            // Send an empty last buffer to HwDevice to get a play completion event with KErrUnderflow
sl@0
  1670
			err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
sl@0
  1671
			}
sl@0
  1672
	
sl@0
  1673
		// If there was an error filling the buffer could be corrupt data
sl@0
  1674
		// notify the client and stop playing.Set err to KErrNone. 
sl@0
  1675
		if (err != KErrNone)
sl@0
  1676
			{
sl@0
  1677
			Error(err);//Updates Bytes played informs client
sl@0
  1678
			err = KErrNone;
sl@0
  1679
			iCMMFHwDevice->Stop();//unloads sound device
sl@0
  1680
            }
sl@0
  1681
		}
sl@0
  1682
	else
sl@0
  1683
		{
sl@0
  1684
		err = KErrGeneral;
sl@0
  1685
		Error(err);
sl@0
  1686
		iCMMFHwDevice->Stop();//unloads sound device
sl@0
  1687
sl@0
  1688
		}
sl@0
  1689
	return err;
sl@0
  1690
	}
sl@0
  1691
sl@0
  1692
sl@0
  1693
/**
sl@0
  1694
 *
sl@0
  1695
 *	MMMFHwDeviceObserver mixin implementation.
sl@0
  1696
 *
sl@0
  1697
 *	The CMMFHwDevice implementation object calls this method during encoding
sl@0
  1698
 *	(recording), when it fills the buffer aHwDataBuffer with
sl@0
  1699
 *	encoded data.
sl@0
  1700
 *
sl@0
  1701
 *	@return	"TInt"
sl@0
  1702
 *			Error code. KErrNone if success.
sl@0
  1703
 *
sl@0
  1704
 */
sl@0
  1705
TInt CMMFDevSoundSvrImp::EmptyThisHwBuffer(CMMFBuffer& aHwDataBuffer)
sl@0
  1706
	{
sl@0
  1707
	TInt err = KErrNone;
sl@0
  1708
	if(iMode== EMMFDevSoundStateRecording)
sl@0
  1709
		{
sl@0
  1710
		// Keep a reference to this Hw data Buffer. We need to send the 
sl@0
  1711
		// reference back to HwDevice implementation
sl@0
  1712
		iHwDeviceBuffer = static_cast<CMMFDataBuffer*>(&aHwDataBuffer);
sl@0
  1713
sl@0
  1714
		// Set the request length, From HwDevice this comes with buffer
sl@0
  1715
		// length. MMF will use RequestSize attribute of the buffer.
sl@0
  1716
		// We can avoid this by setting in HwDevice implemenation
sl@0
  1717
		TInt len = iHwDeviceBuffer->Data().Length();
sl@0
  1718
		TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
sl@0
  1719
	
sl@0
  1720
		// if we're pausing (i.e. flushing) set the last buffer flag
sl@0
  1721
		// when we get an empty buffer from the logical driver
sl@0
  1722
		if(iPaused  && iHwDeviceBuffer->Data().Length() == 0)
sl@0
  1723
		{
sl@0
  1724
		iPaused = EFalse;
sl@0
  1725
sl@0
  1726
		iHwDeviceBuffer->SetLastBuffer(ETrue);
sl@0
  1727
sl@0
  1728
		iDevSoundEventHandler->CancelReceiveEvents();
sl@0
  1729
sl@0
  1730
		}
sl@0
  1731
sl@0
  1732
		// Send Data from Observer
sl@0
  1733
		iDevSoundObserver->BufferToBeEmptied(iHwDeviceBuffer);
sl@0
  1734
		}
sl@0
  1735
	else
sl@0
  1736
		{
sl@0
  1737
		err = KErrGeneral;
sl@0
  1738
		Error(err);
sl@0
  1739
		iCMMFHwDevice->Stop();//unloads sound device
sl@0
  1740
sl@0
  1741
		}
sl@0
  1742
sl@0
  1743
	return err;
sl@0
  1744
	}
sl@0
  1745
sl@0
  1746
sl@0
  1747
/**
sl@0
  1748
 *
sl@0
  1749
 *	MMMFHwDeviceObserver mixin implementation.
sl@0
  1750
 *
sl@0
  1751
 *	The CMMFHwDevice implementation object calls this method when a message from
sl@0
  1752
 *	the hardware device implementation is received.
sl@0
  1753
 *
sl@0
  1754
 *	@return	"TInt"
sl@0
  1755
 *			Error code. KErrNone if success.
sl@0
  1756
 *
sl@0
  1757
 */
sl@0
  1758
TInt CMMFDevSoundSvrImp::MsgFromHwDevice(TUid aMessageType, const TDesC8& /*aMsg*/)
sl@0
  1759
	{
sl@0
  1760
	TInt result = KErrNotSupported;
sl@0
  1761
	if (aMessageType.iUid == KMmfHwDeviceObserverUpdateBytesPlayed)
sl@0
  1762
		{//this is used by sw codec wrapper to request a bytes played update
sl@0
  1763
		//bytes played won't be updated in Stopped() or Error() on sw cdoec wrapper
sl@0
  1764
		//as the sound device is closed. Non swCodec wrapper Hw device plugins
sl@0
  1765
		//can get there bytes updated on Stopped() and/or Error()
sl@0
  1766
		UpdateBytesPlayed();
sl@0
  1767
		result = KErrNone;
sl@0
  1768
		}
sl@0
  1769
	return result;
sl@0
  1770
	}
sl@0
  1771
sl@0
  1772
/**
sl@0
  1773
 *
sl@0
  1774
 *	MMMFHwDeviceObserver mixin implementation.
sl@0
  1775
 *
sl@0
  1776
 *	The CMMFHwDevice implementation object calls this method when the current
sl@0
  1777
 *	encode or decode task is finished or stopped.  The policy state is updated
sl@0
  1778
 *
sl@0
  1779
 */
sl@0
  1780
void CMMFDevSoundSvrImp::Stopped()
sl@0
  1781
	{
sl@0
  1782
	//for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
sl@0
  1783
	//but non Swcodec wrappers hw devices may do it differently
sl@0
  1784
	//also don't know if non Swcodec wrap hw device will call Stopped or Error first
sl@0
  1785
	UpdateBytesPlayed();
sl@0
  1786
sl@0
  1787
	iLastBufferReceived = EFalse;
sl@0
  1788
	UpdatePolicyState(EMMFStateCompleted);
sl@0
  1789
	}
sl@0
  1790
sl@0
  1791
/**
sl@0
  1792
 *  MMMFHwDeviceObserver mixin implementation
sl@0
  1793
 *  Processes error from hw device
sl@0
  1794
 */
sl@0
  1795
void CMMFDevSoundSvrImp::Error(TInt aError)
sl@0
  1796
	{
sl@0
  1797
	if (iMode== EMMFDevSoundStatePlaying)
sl@0
  1798
		{
sl@0
  1799
		//for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
sl@0
  1800
		//but non Swcodec wrappers hw devices may do it differently
sl@0
  1801
		//also don't know if non Swcodec wrap hw device will call Stopped or Error first
sl@0
  1802
		UpdateBytesPlayed();
sl@0
  1803
sl@0
  1804
        iDevSoundObserver->PlayError(aError);
sl@0
  1805
        UpdatePolicyState(EMMFStateStopped);
sl@0
  1806
		}
sl@0
  1807
	else if (iMode== EMMFDevSoundStateRecording)
sl@0
  1808
		{
sl@0
  1809
        iDevSoundObserver->RecordError(aError);
sl@0
  1810
        UpdatePolicyState(EMMFStateStopped);
sl@0
  1811
		}
sl@0
  1812
	else if (iMode== EMMFDevSoundStateTonePlaying)
sl@0
  1813
		{
sl@0
  1814
        iDevSoundObserver->ToneFinished(aError);
sl@0
  1815
        UpdatePolicyState(EMMFStateStopped);
sl@0
  1816
		}
sl@0
  1817
	//else can't handle error
sl@0
  1818
	}
sl@0
  1819
sl@0
  1820
sl@0
  1821
/********************************************************************************
sl@0
  1822
 *				Non Exported public functions ends here							*
sl@0
  1823
 ********************************************************************************/
sl@0
  1824
sl@0
  1825
sl@0
  1826
/********************************************************************************
sl@0
  1827
 *				Private functions begins here									*
sl@0
  1828
 ********************************************************************************/
sl@0
  1829
sl@0
  1830
TInt CMMFDevSoundSvrImp::InitializeFormat(RMdaDevSound::TSoundFormatsSupportedBuf& aSupportedFormat,
sl@0
  1831
		RMdaDevSound::TCurrentSoundFormatBuf& aFormat)
sl@0
  1832
	{
sl@0
  1833
	// Choose an encoding
sl@0
  1834
	TUint32 enc = aSupportedFormat().iEncodings;
sl@0
  1835
	// Always defaults to this
sl@0
  1836
	if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
sl@0
  1837
		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
sl@0
  1838
	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
sl@0
  1839
		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
sl@0
  1840
	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
sl@0
  1841
		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
sl@0
  1842
	else if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
sl@0
  1843
		aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
sl@0
  1844
sl@0
  1845
	// default to Monophonic playback:
sl@0
  1846
	aFormat().iChannels=1;
sl@0
  1847
sl@0
  1848
	// Store the device capabilities (WINS supports from 8000 Hz to 44100 Hz)
sl@0
  1849
	if ((aSupportedFormat().iMinRate <= 8000) && (8000 <= aSupportedFormat().iMaxRate))
sl@0
  1850
		iDeviceCapabilities.iRate = EMMFSampleRate8000Hz;
sl@0
  1851
	if ((aSupportedFormat().iMinRate <= 11025) && (11025 <= aSupportedFormat().iMaxRate))
sl@0
  1852
		iDeviceCapabilities.iRate |= EMMFSampleRate11025Hz;
sl@0
  1853
	if ((aSupportedFormat().iMinRate <= 12000) && (12000 <= aSupportedFormat().iMaxRate))
sl@0
  1854
		iDeviceCapabilities.iRate |= EMMFSampleRate12000Hz;
sl@0
  1855
	if ((aSupportedFormat().iMinRate <= 16000) && (16000 <= aSupportedFormat().iMaxRate))
sl@0
  1856
		iDeviceCapabilities.iRate |= EMMFSampleRate16000Hz;
sl@0
  1857
	if ((aSupportedFormat().iMinRate <= 22050) && (22050 <= aSupportedFormat().iMaxRate))
sl@0
  1858
		iDeviceCapabilities.iRate |= EMMFSampleRate22050Hz;
sl@0
  1859
	if ((aSupportedFormat().iMinRate <= 24000) && (24000 <= aSupportedFormat().iMaxRate))
sl@0
  1860
		iDeviceCapabilities.iRate |= EMMFSampleRate24000Hz;
sl@0
  1861
	if ((aSupportedFormat().iMinRate <= 32000) && (32000 <= aSupportedFormat().iMaxRate))
sl@0
  1862
		iDeviceCapabilities.iRate |= EMMFSampleRate32000Hz;
sl@0
  1863
	if ((aSupportedFormat().iMinRate <= 44100) && (44100 <= aSupportedFormat().iMaxRate))
sl@0
  1864
		iDeviceCapabilities.iRate |= EMMFSampleRate44100Hz;
sl@0
  1865
	if ((aSupportedFormat().iMinRate <= 48000) && (48000 <= aSupportedFormat().iMaxRate))
sl@0
  1866
		iDeviceCapabilities.iRate |= EMMFSampleRate48000Hz;
sl@0
  1867
	if ((aSupportedFormat().iMinRate <= 64000) && (64000 <= aSupportedFormat().iMaxRate))
sl@0
  1868
		iDeviceCapabilities.iRate |= EMMFSampleRate64000Hz;
sl@0
  1869
	if ((aSupportedFormat().iMinRate <= 88200) && (88200 <= aSupportedFormat().iMaxRate))
sl@0
  1870
		iDeviceCapabilities.iRate |= EMMFSampleRate88200Hz;
sl@0
  1871
	if ((aSupportedFormat().iMinRate <= 96000) && (96000 <= aSupportedFormat().iMaxRate))
sl@0
  1872
		iDeviceCapabilities.iRate |= EMMFSampleRate96000Hz;
sl@0
  1873
sl@0
  1874
	// Store the encodings supported
sl@0
  1875
	iDeviceCapabilities.iEncoding = 0;
sl@0
  1876
	if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
sl@0
  1877
		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding16BitPCM;
sl@0
  1878
	if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
sl@0
  1879
		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitALaw;
sl@0
  1880
	if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
sl@0
  1881
		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitMuLaw;
sl@0
  1882
	if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
sl@0
  1883
		iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitPCM;
sl@0
  1884
sl@0
  1885
	// Mono and Stereo support
sl@0
  1886
	if (aSupportedFormat().iChannels == 2)
sl@0
  1887
		iDeviceCapabilities.iChannels = EMMFStereo;
sl@0
  1888
	iDeviceCapabilities.iChannels |= EMMFMono;
sl@0
  1889
sl@0
  1890
	iDeviceCapabilities.iBufferSize = aSupportedFormat().iMaxBufferSize;
sl@0
  1891
	// Default
sl@0
  1892
	iDeviceConfig.iRate = EMMFSampleRate8000Hz;
sl@0
  1893
	iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
sl@0
  1894
	iDeviceConfig.iChannels = EMMFMono;
sl@0
  1895
sl@0
  1896
	return KErrNone;
sl@0
  1897
	}
sl@0
  1898
sl@0
  1899
/*
sl@0
  1900
 *
sl@0
  1901
 *	Makes request to Policy Server (asynchronous call)
sl@0
  1902
 *
sl@0
  1903
 */
sl@0
  1904
void CMMFDevSoundSvrImp::RequestPolicy()
sl@0
  1905
	{
sl@0
  1906
	iDevSoundEventHandler->CancelReceiveEvents();
sl@0
  1907
	iDevSoundEventHandler->ReceiveEvents();
sl@0
  1908
	iAudioPolicyPrioritySettings.iCapabilities = iParent.CheckClientCapabilities();
sl@0
  1909
	iAudioPolicyProxy->MakeRequest(iAudioPolicyPrioritySettings);
sl@0
  1910
	}
sl@0
  1911
sl@0
  1912
/*
sl@0
  1913
 *
sl@0
  1914
 *	Creates buffer and begin playback using the specified tone generator.
sl@0
  1915
 *
sl@0
  1916
 */
sl@0
  1917
void CMMFDevSoundSvrImp::DoPlayL()
sl@0
  1918
	{
sl@0
  1919
	// Delete any buffer from previous call and try to create maximum buffer 
sl@0
  1920
	// size. Double Buffer the Tone data.
sl@0
  1921
	if (iToneBuffer1)
sl@0
  1922
		{
sl@0
  1923
		delete iToneBuffer1; 
sl@0
  1924
		iToneBuffer1 = NULL; 
sl@0
  1925
		}
sl@0
  1926
	//note the tone buffer needs to be the same as the pcm16->pcm16 'null'
sl@0
  1927
	//hw device plugin
sl@0
  1928
	// Buffer size = (SampleRate * BytesPerSample * Channels) / 4
sl@0
  1929
	TInt useBufferOfSize = ((SamplingFrequency() * 2 * NumberOfChannels())/KDevSoundFramesPerSecond + (KDevSoundDeltaFrameSize-1)) &~ (KDevSoundDeltaFrameSize-1);
sl@0
  1930
	//clamp buffer to desired limits
sl@0
  1931
	if(useBufferOfSize < KDevSoundMinFrameSize) 
sl@0
  1932
		useBufferOfSize = KDevSoundMinFrameSize;
sl@0
  1933
	else if(useBufferOfSize > KDevSoundMaxFrameSize) 
sl@0
  1934
		useBufferOfSize = KDevSoundMaxFrameSize;
sl@0
  1935
sl@0
  1936
	//clamp buffer to limits of hardware
sl@0
  1937
	if(useBufferOfSize < Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize))
sl@0
  1938
		useBufferOfSize = Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize);
sl@0
  1939
	else if(useBufferOfSize > Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize))
sl@0
  1940
		useBufferOfSize = Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize);
sl@0
  1941
sl@0
  1942
	iToneBuffer1 = CMMFDataBuffer::NewL(useBufferOfSize);
sl@0
  1943
	User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer1->Data()));
sl@0
  1944
sl@0
  1945
	if (iToneBuffer2)
sl@0
  1946
		{
sl@0
  1947
		delete iToneBuffer2; 
sl@0
  1948
		iToneBuffer2 = NULL;
sl@0
  1949
		}
sl@0
  1950
	iToneBuffer2 = CMMFDataBuffer::NewL(useBufferOfSize);
sl@0
  1951
	User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer2->Data()));
sl@0
  1952
sl@0
  1953
	// Assign active buffer
sl@0
  1954
	iActiveToneBuffer = iToneBuffer1;
sl@0
  1955
sl@0
  1956
	// Hw device hasn't played anything yet so don't change
sl@0
  1957
    // active buffer. This is checked in FillThisHwBuffer.
sl@0
  1958
    iFirstCallFromHwDevice = ETrue;
sl@0
  1959
sl@0
  1960
    // Start HwDevice to play data
sl@0
  1961
    User::LeaveIfError(iCMMFHwDevice->Start(EDevDecode, EDevOutFlow));
sl@0
  1962
	
sl@0
  1963
	}
sl@0
  1964
sl@0
  1965
/*
sl@0
  1966
 *
sl@0
  1967
 *	This method assigns the other buffer as active buffer. The tone audio 
sl@0
  1968
 *	generator should fill data in the other buffer by now.
sl@0
  1969
 *
sl@0
  1970
 */
sl@0
  1971
void CMMFDevSoundSvrImp::SetActiveToneBuffer()
sl@0
  1972
	{
sl@0
  1973
	if (iActiveToneBuffer == iToneBuffer1)
sl@0
  1974
		iActiveToneBuffer = iToneBuffer2;
sl@0
  1975
	else if (iActiveToneBuffer == iToneBuffer2)
sl@0
  1976
		iActiveToneBuffer = iToneBuffer1;
sl@0
  1977
	}
sl@0
  1978
sl@0
  1979
/*
sl@0
  1980
 *
sl@0
  1981
 *	This method fills data into the free buffer.
sl@0
  1982
 *
sl@0
  1983
 *	@return	"TInt"
sl@0
  1984
 *			Error code. KErrNone if success.
sl@0
  1985
 *
sl@0
  1986
 */
sl@0
  1987
TInt CMMFDevSoundSvrImp::FillFreeToneBuffer()
sl@0
  1988
	{
sl@0
  1989
	TInt err(KErrNone);
sl@0
  1990
	if (iActiveToneBuffer == iToneBuffer1)
sl@0
  1991
		err = iCurrentGenerator->FillBuffer(iToneBuffer2->Data());
sl@0
  1992
	else if (iActiveToneBuffer == iToneBuffer2)
sl@0
  1993
		err = iCurrentGenerator->FillBuffer(iToneBuffer1->Data());
sl@0
  1994
	return err;
sl@0
  1995
	}
sl@0
  1996
sl@0
  1997
/*
sl@0
  1998
 *
sl@0
  1999
 *	Updates the policy state based on Audio policy settings of this devsound instance
sl@0
  2000
 *
sl@0
  2001
 */
sl@0
  2002
TInt CMMFDevSoundSvrImp::UpdatePolicyState(TMMFAudioPolicyState aNewState)
sl@0
  2003
	{
sl@0
  2004
	iAudioPolicyPrioritySettings.iState = aNewState;
sl@0
  2005
	TInt error = iAudioPolicyProxy->UpdateState(iAudioPolicyPrioritySettings);
sl@0
  2006
	if ((error == KErrNone) && (aNewState == EMMFStateStopped))
sl@0
  2007
		{
sl@0
  2008
		iHasPolicy = EFalse;
sl@0
  2009
		}
sl@0
  2010
sl@0
  2011
	return error;
sl@0
  2012
	}
sl@0
  2013
sl@0
  2014
/*
sl@0
  2015
 *
sl@0
  2016
 *	Initializes audio device node by setting volume, and sampling rate.
sl@0
  2017
 *
sl@0
  2018
 *	@return	"TInt"
sl@0
  2019
 *			Error Code. KErrNone if success.
sl@0
  2020
 *
sl@0
  2021
 */
sl@0
  2022
TInt CMMFDevSoundSvrImp::InitTask()
sl@0
  2023
	{
sl@0
  2024
	// No Implementation
sl@0
  2025
	return KErrNone;
sl@0
  2026
	}
sl@0
  2027
sl@0
  2028
sl@0
  2029
sl@0
  2030
/*
sl@0
  2031
 *
sl@0
  2032
 *	Returns an integer representing Sampling Frequency the device is currently
sl@0
  2033
 *	configured to.
sl@0
  2034
 *
sl@0
  2035
 *	@return	"TInt"
sl@0
  2036
 *			Sampling Frequency.
sl@0
  2037
 *
sl@0
  2038
 */
sl@0
  2039
TInt CMMFDevSoundSvrImp::SamplingFrequency()
sl@0
  2040
	{
sl@0
  2041
	if(iDeviceConfig.iRate == EMMFSampleRate8000Hz)
sl@0
  2042
		return 8000;
sl@0
  2043
	else if(iDeviceConfig.iRate == EMMFSampleRate11025Hz)
sl@0
  2044
		return 11025;
sl@0
  2045
	else if(iDeviceConfig.iRate == EMMFSampleRate12000Hz)
sl@0
  2046
		return 12000;
sl@0
  2047
	else if(iDeviceConfig.iRate == EMMFSampleRate16000Hz)
sl@0
  2048
		return 16000;
sl@0
  2049
	else if(iDeviceConfig.iRate == EMMFSampleRate22050Hz)
sl@0
  2050
		return 22050;
sl@0
  2051
	else if(iDeviceConfig.iRate == EMMFSampleRate24000Hz)
sl@0
  2052
		return 24000;
sl@0
  2053
	else if(iDeviceConfig.iRate == EMMFSampleRate32000Hz)
sl@0
  2054
		return 32000;
sl@0
  2055
	else if(iDeviceConfig.iRate == EMMFSampleRate44100Hz)
sl@0
  2056
		return 44100;
sl@0
  2057
	else if(iDeviceConfig.iRate == EMMFSampleRate48000Hz)
sl@0
  2058
		return 48000;
sl@0
  2059
	else if(iDeviceConfig.iRate == EMMFSampleRate88200Hz)
sl@0
  2060
		return 88200;
sl@0
  2061
	else if(iDeviceConfig.iRate == EMMFSampleRate96000Hz)
sl@0
  2062
		return 96000;
sl@0
  2063
	else
sl@0
  2064
		return 8000; //default
sl@0
  2065
	}
sl@0
  2066
 
sl@0
  2067
/*
sl@0
  2068
 *
sl@0
  2069
 *	Returns an integer representing number of channels the device is currently
sl@0
  2070
 *	configured to.
sl@0
  2071
 *
sl@0
  2072
 *	@return	"TInt"
sl@0
  2073
 *			Number of audio channels 1 if mono, 2 if stereo.
sl@0
  2074
 *
sl@0
  2075
 */
sl@0
  2076
TInt CMMFDevSoundSvrImp::NumberOfChannels()
sl@0
  2077
	{
sl@0
  2078
	if(iDeviceConfig.iChannels == EMMFMono)
sl@0
  2079
		return 1;
sl@0
  2080
	else
sl@0
  2081
		return 2;
sl@0
  2082
	}
sl@0
  2083
sl@0
  2084
/*
sl@0
  2085
 *
sl@0
  2086
 *	Returns an integer representing number of bytes in each audio sample
sl@0
  2087
 *	
sl@0
  2088
 *
sl@0
  2089
 *	@return	"TInt"
sl@0
  2090
 *			Number of of bytes in each audio sample.
sl@0
  2091
 *
sl@0
  2092
 */
sl@0
  2093
TInt CMMFDevSoundSvrImp::BytesPerAudioSample()
sl@0
  2094
	{
sl@0
  2095
	TInt bytes=1;
sl@0
  2096
	switch (iDeviceConfig.iEncoding)
sl@0
  2097
		{
sl@0
  2098
		case EMMFSoundEncoding8BitPCM:
sl@0
  2099
		case EMMFSoundEncoding8BitALaw:
sl@0
  2100
		case EMMFSoundEncoding8BitMuLaw:
sl@0
  2101
			{
sl@0
  2102
			bytes=1;
sl@0
  2103
			}
sl@0
  2104
		break;
sl@0
  2105
		case EMMFSoundEncoding16BitPCM:
sl@0
  2106
			{
sl@0
  2107
			bytes=2;
sl@0
  2108
			}
sl@0
  2109
		break;
sl@0
  2110
		}
sl@0
  2111
	return bytes;
sl@0
  2112
	}
sl@0
  2113
sl@0
  2114
sl@0
  2115
/********************************************************************************
sl@0
  2116
 *				Private functions ends here										*
sl@0
  2117
 ********************************************************************************/
sl@0
  2118
sl@0
  2119
sl@0
  2120
// CustomCommand* implementation:
sl@0
  2121
// The following come through from the parent object intact - currently it seems
sl@0
  2122
// easier to pass this through with an RMessage, as the result parameter (at least)
sl@0
  2123
// is easier to deal with that way. This might change in the future. 
sl@0
  2124
// [TODO - if we extended this to CMMFHwDevice, it might be easier to use some sort
sl@0
  2125
// of TMMFCustomCommandParamBlock throughout, which as well as the uid, in params etc
sl@0
  2126
// by value, also provided a virtual(?) function to set output param. Could then
sl@0
  2127
// use in both plat sec and original code
sl@0
  2128
sl@0
  2129
void CMMFDevSoundSvrImp::DoSyncCustomCommandL(const RMmfIpcMessage& aMessage)
sl@0
  2130
	{
sl@0
  2131
	TInt command = aMessage.Int0();
sl@0
  2132
	
sl@0
  2133
	// we don't support any commands at the momment
sl@0
  2134
	User::Leave(KErrNotSupported);
sl@0
  2135
	}
sl@0
  2136
	
sl@0
  2137
void CMMFDevSoundSvrImp::DoSyncCustomCommandResultL(const RMmfIpcMessage& aMessage)
sl@0
  2138
	{
sl@0
  2139
	TInt command = aMessage.Int0();
sl@0
  2140
	
sl@0
  2141
	// we don't support any commands at the momment
sl@0
  2142
	User::Leave(KErrNotSupported);	
sl@0
  2143
	}
sl@0
  2144
	
sl@0
  2145
void CMMFDevSoundSvrImp::DoAsyncCustomCommandL(const RMmfIpcMessage& aMessage)
sl@0
  2146
	{
sl@0
  2147
	TInt command = aMessage.Int0();
sl@0
  2148
	
sl@0
  2149
	// we don't support any commands at the momment
sl@0
  2150
	User::Leave(KErrNotSupported); // this will still complete for an async message	
sl@0
  2151
	}
sl@0
  2152
	
sl@0
  2153
void CMMFDevSoundSvrImp::DoAsyncCustomCommandResultL(const RMmfIpcMessage& aMessage)
sl@0
  2154
	{
sl@0
  2155
	TInt command = aMessage.Int0();
sl@0
  2156
	
sl@0
  2157
	// we don't support any commands at the moment
sl@0
  2158
	User::Leave(KErrNotSupported); // this will still complete for an async message	
sl@0
  2159
	}
sl@0
  2160