os/mm/devsound/sounddevbt/PlatSec/src/Server/AudioServer/MmfBtDevSoundSessionBody.cpp
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 + ********************************************************************************/