1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmlibs/mmfw/src/Plugin/Controller/Audio/MmfAudioController.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,3094 @@
1.4 +// Copyright (c) 2002-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 +
1.20 +#include <mmf/server/mmfformat.h>
1.21 +#include <mmf/server/mmfclip.h>
1.22 +#include <mdaaudiosampleeditor.h>
1.23 +#include <mmfcontrollerimplementationuids.hrh>
1.24 +#include <mmf/common/mmffourcc.h>
1.25 +#include <mmf/common/mmfpaniccodes.h>
1.26 +#include "MmfAudioController.h"
1.27 +#include <mmf/server/mmffile.h>
1.28 +#include <mmf/server/mmfformatstandardcustominterfaces.h>
1.29 +#include <mmf/server/devsoundstandardcustominterfaces.h>
1.30 +#include <mmf/server/mmfdatapath2.h>
1.31 +
1.32 +const TUint KSampleRate8000Hz = 8000;
1.33 +const TUint KSampleRate11025Hz = 11025;
1.34 +const TUint KSampleRate12000Hz = 12000;
1.35 +const TUint KSampleRate16000Hz = 16000;
1.36 +const TUint KSampleRate22050Hz = 22050;
1.37 +const TUint KSampleRate24000Hz = 24000;
1.38 +const TUint KSampleRate32000Hz = 32000;
1.39 +const TUint KSampleRate44100Hz = 44100;
1.40 +const TUint KSampleRate48000Hz = 48000;
1.41 +const TUint KSampleRate64000Hz = 64000;
1.42 +const TUint KSampleRate88200Hz = 88200;
1.43 +const TUint KSampleRate96000Hz = 96000;
1.44 +const TUint KNumChannelsMono = 1;
1.45 +const TUint KNumChannelsStereo = 2;
1.46 +
1.47 +/*
1.48 + TMmfAudioControllerPanics is an enumeration with the following entries:
1.49 + EBadArgument indicates a bad argument
1.50 + EBadState indicates a state viaolation
1.51 + EBadInvariant indicates an invariant violation
1.52 + EBadReset indicates failed reset
1.53 + EPostConditionViolation indicates a post condition violation
1.54 +*/
1.55 +enum TMmfAudioControllerPanics
1.56 + {
1.57 + EBadArgument,
1.58 + EBadState,
1.59 + EBadInvariant,
1.60 + EBadReset,
1.61 + EPostConditionViolation,
1.62 + EStateNotConstructed,
1.63 + EBadStateToGetDataSource,
1.64 + ENoAudioInput,
1.65 + EBadStateToGetDataSink,
1.66 + ENoAudioOutput,
1.67 + EBadStateForPrime,
1.68 + ENoDataSource,
1.69 + ENoDataSink,
1.70 + EStateNotPrimed,
1.71 + EBadResetState,
1.72 + EBadStateToReset,
1.73 + EStateNotReadyToPlay,
1.74 + EBadPlayState,
1.75 + EBadPauseState,
1.76 + EBadStateToPause,
1.77 + EBadStateToStop,
1.78 + EBadStopState,
1.79 + EBadStateToPosition,
1.80 + EBadStatePosition,
1.81 + EBadStateToSetPosition,
1.82 + EBadStateSetPosition,
1.83 + EBadStateToDuration,
1.84 + EBadStateDuration,
1.85 + EBadStateToGetNumberOfMetaDataEntries,
1.86 + EBadStateGetNumberOfMetaDataEntries,
1.87 + EBadStateToGetMetaDataEntries,
1.88 + EBadStateGetMetaDataEntries,
1.89 + EMetaEntryIsNull,
1.90 + ENotReadyForDataSourceRemoval,
1.91 + EBadDataSourceRemoval,
1.92 + ENotReadyForDataSinkRemoval,
1.93 + EBadDataSinkRemoval,
1.94 + ENotReadyForCustomCommand,
1.95 + EBadStateAfterNegotiate,
1.96 + EBadStateToNegotiate,
1.97 + EBadStateToSetPriority,
1.98 + EBadPriorityState,
1.99 + EBadStateToSendEventToClient,
1.100 + EBadStateAfterSendEventToClient,
1.101 + EBadStateToSetVolume,
1.102 + EBadStateAfterVolumeSet,
1.103 + EBadStateToGetMaxVolume,
1.104 + EBadStateAfterGetMaxVolume,
1.105 + EBadStateToGetVolume,
1.106 + EBadStateAfterGetVolume,
1.107 + EBadStateToSetVolumeRamp,
1.108 + EBadStateAfterSetVolumeRamp,
1.109 + EBadStateToSetBalance,
1.110 + EBadStateAfterSetBalance,
1.111 + EBadStateToGetBalance,
1.112 + EBadStateAfterGetBalance,
1.113 + EBadStateToSetGain,
1.114 + EBadStateAfterGainSet,
1.115 + EBadStateToGetMaxGain,
1.116 + EBadStateAfterGetMaxGain,
1.117 + EBadStateToGetGain,
1.118 + EBadStateAfterGetGain,
1.119 + EBadStateToGetRecordTimeAvailable,
1.120 + EBadStateAfterGetRecordTimeAvailable,
1.121 + ENoMemoryToRecord,
1.122 + EBadStateToGetMaxFileSize,
1.123 + EBadStateAfterGetMaxFileSize,
1.124 + EBadStateToCrop,
1.125 + EBadStateAfterCrop,
1.126 + EBadStateToAddMetaDataEntry,
1.127 + EBadStateAfterAddMetaDataEntry,
1.128 + EBadStateToRemoveMetaDataEntry,
1.129 + EBadStateAfterRemoveMetaDataEntry,
1.130 + EBadStateToReplaceMetaDataEntry,
1.131 + EBadStateAfterReplaceMetaDataEntry,
1.132 + EBadStateToSetSourceSampleRate,
1.133 + EBadStateAfterSetSourceSampleRate,
1.134 + EBadStateToSetSourceNumChannels,
1.135 + EBadStateAfterSetSourceNumChannels,
1.136 + EBadStateToSetSourceFormat,
1.137 + EBadStateAfterSetSourceFormat,
1.138 + EBadStateToSetSinkSampleRate,
1.139 + EBadStateAfterSetSinkSampleRate,
1.140 + EBadStateToSetSinkNumChannels,
1.141 + EBadStateAfterSetSinkNumChannels,
1.142 + EBadStateToSetSinkFormat,
1.143 + EBadStateAfterSetSinkFormat,
1.144 + EBadStateToSetCodec,
1.145 + EBadStateAfterSetCodec,
1.146 + EBadStateToSetSourceBitRate,
1.147 + EBadStateAfterSetSourceBitRate,
1.148 + EBadStateToSetSinkBitRate,
1.149 + EBadStateAfterSetSinkBitRate,
1.150 + ESetRateIsNotSameAsBitRate,
1.151 + EBadStateToGetSourceSampleRate,
1.152 + EBadStateAfterGetSourceSampleRate,
1.153 + EBadStateToGetSourceBitRate,
1.154 + EBadStateAfterGetSourceBitRate,
1.155 + EBadStateToGetSourceNumChannels,
1.156 + EBadStateAfterGetSourceNumChannels,
1.157 + EBadStateToGetSourceFormat,
1.158 + EBadStateAfterGetSourceFormat,
1.159 + EInvalidState,
1.160 + EBadStateToRegisterAsClient,
1.161 + EBadStateAfterRegisterAsClient,
1.162 + EBadStateToCancelRegisterAsClient,
1.163 + EBadStateAfterCancelRegisterAsClient,
1.164 + EBadStateToGetResourceNotificationData,
1.165 + EBadStateAfterGetResourceNotificationData,
1.166 + EBadStateToResumePlay,
1.167 + EBadStateAfterResumePlay,
1.168 + };
1.169 +
1.170 +/**
1.171 +This method generates a panic
1.172 +
1.173 +@param aPanicCode
1.174 +*/
1.175 +void Panic(TInt aPanicCode)
1.176 + {
1.177 + _LIT(KMMFAudioControllerPanicCategory, "MMFAudioController");
1.178 + User::Panic(KMMFAudioControllerPanicCategory, aPanicCode);
1.179 + }
1.180 +
1.181 +/**
1.182 + * Static NewL
1.183 + *
1.184 + * @return CMMFAudioController*
1.185 + */
1.186 +CMMFController* CMMFAudioController::NewL()
1.187 + {
1.188 + CMMFAudioController* self = new(ELeave) CMMFAudioController;
1.189 + CleanupStack::PushL(self);
1.190 + self->ConstructL();
1.191 + CleanupStack::Pop( self );
1.192 + return STATIC_CAST( CMMFController*, self );
1.193 + }
1.194 +
1.195 +/**
1.196 +* ConstructL
1.197 +*
1.198 +*/
1.199 +void CMMFAudioController::ConstructL()
1.200 + {
1.201 + iDataSource = NULL;
1.202 + iDataSink = NULL;
1.203 + iDataPath = CMMFDataPath2::NewL(iMediaId, *this);
1.204 + iSourceFormat = NULL;
1.205 + iSinkFormat = NULL;
1.206 + iSourceAndSinkAdded = EFalse;
1.207 + iStoppingRecording = EFalse;
1.208 +
1.209 +
1.210 + //iMediaId has already been set up
1.211 + SetState( EStopped );
1.212 + //iPrioritySettings not initialised because they are held by the controller framework
1.213 +
1.214 + // Construct custom command parsers
1.215 + CMMFAudioPlayDeviceCustomCommandParser* audPlayDevParser = CMMFAudioPlayDeviceCustomCommandParser::NewL(*this);
1.216 + CleanupStack::PushL(audPlayDevParser);
1.217 + AddCustomCommandParserL(*audPlayDevParser);
1.218 + CleanupStack::Pop( audPlayDevParser );
1.219 +
1.220 + CMMFAudioRecordDeviceCustomCommandParser* audRecDevParser = CMMFAudioRecordDeviceCustomCommandParser::NewL(*this);
1.221 + CleanupStack::PushL(audRecDevParser);
1.222 + AddCustomCommandParserL(*audRecDevParser);
1.223 + CleanupStack::Pop(audRecDevParser);
1.224 +
1.225 + CMMFAudioPlayControllerCustomCommandParser* audPlayConParser = CMMFAudioPlayControllerCustomCommandParser::NewL(*this);
1.226 + CleanupStack::PushL(audPlayConParser);
1.227 + AddCustomCommandParserL(*audPlayConParser);
1.228 + CleanupStack::Pop(audPlayConParser);
1.229 +
1.230 + CMMFAudioRecordControllerCustomCommandParser* audRecConParser = CMMFAudioRecordControllerCustomCommandParser::NewL(*this);
1.231 + CleanupStack::PushL(audRecConParser);
1.232 + AddCustomCommandParserL(*audRecConParser);
1.233 + CleanupStack::Pop(audRecConParser);
1.234 +
1.235 + CMMFAudioControllerCustomCommandParser* audConParser = CMMFAudioControllerCustomCommandParser::NewL(*this);
1.236 + CleanupStack::PushL(audConParser);
1.237 + AddCustomCommandParserL(*audConParser);
1.238 + CleanupStack::Pop(audConParser);
1.239 +
1.240 + CMMFDRMCustomCommandParser* drmParser = CMMFDRMCustomCommandParser::NewL(*this);
1.241 + CleanupStack::PushL(drmParser);
1.242 + AddCustomCommandParserL(*drmParser);
1.243 + CleanupStack::Pop(drmParser);
1.244 +
1.245 + CMMFResourceNotificationCustomCommandParser* NotiParser = CMMFResourceNotificationCustomCommandParser::NewL(*this);
1.246 + CleanupStack::PushL(NotiParser);
1.247 + AddCustomCommandParserL(*NotiParser);
1.248 + CleanupStack::Pop(NotiParser);//audio resource Notification Parser
1.249 +
1.250 + CMMFAudioPlayControllerSetRepeatsCustomCommandParser* audPlayConSetRepeatsParser = CMMFAudioPlayControllerSetRepeatsCustomCommandParser::NewL(*this);
1.251 + CleanupStack::PushL(audPlayConSetRepeatsParser);
1.252 + AddCustomCommandParserL(*audPlayConSetRepeatsParser);
1.253 + CleanupStack::Pop(audPlayConSetRepeatsParser);
1.254 +
1.255 +
1.256 + // [ assert the invariant now that we are constructed ]
1.257 + __ASSERT_ALWAYS( Invariant(), Panic( EStateNotConstructed));
1.258 + }
1.259 +
1.260 +/**
1.261 +*
1.262 +* CMMFAudioController
1.263 +*
1.264 +*/
1.265 +
1.266 +CMMFAudioController::CMMFAudioController()
1.267 + : iMediaId(KUidMediaTypeAudio),
1.268 + iDisableAutoIntent(EFalse),
1.269 + iState(EStopped)
1.270 + {
1.271 + }
1.272 +
1.273 +/**
1.274 +*
1.275 +* ~CMMFAudioController
1.276 +*
1.277 +*/
1.278 +
1.279 +CMMFAudioController::~CMMFAudioController()
1.280 + {
1.281 + // [ ensure we have logged off the thread ]
1.282 + if( iDataPath )
1.283 + {
1.284 + iDataPath->ResetL(); // this does not leave
1.285 + }
1.286 + delete iDataPath;
1.287 + delete iSourceFormat;
1.288 + delete iSinkFormat;
1.289 + delete iStoppingMessage;
1.290 + }
1.291 +
1.292 +/**
1.293 + * AddDataSourceL
1.294 + *
1.295 + * Adds a data source to the controller
1.296 + *
1.297 + * @param aSource
1.298 + * Preconditions:
1.299 + * We are stopped
1.300 + * Source does not already exist
1.301 + * Postconditions:
1.302 + * iDataSource != NULL
1.303 + * iDataSourceAdded == ETrue
1.304 + */
1.305 +void CMMFAudioController::AddDataSourceL(MDataSource& aSource)
1.306 + {
1.307 + //[ assert the invariant ]
1.308 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetDataSource));
1.309 +
1.310 + // [ precondition that the controller is stopped ]
1.311 + if( State() != EStopped )
1.312 + User::Leave( KErrNotReady );
1.313 +
1.314 + //[ precondition iData source is not already configured ]
1.315 + if (iDataSource)
1.316 + User::Leave(KErrAlreadyExists);
1.317 +
1.318 + // Note that this code is not generic for sources
1.319 + // It it only checks for file, des clips and audio inputs
1.320 + // If a new source type eg a Url Clip then this needs to be added to the supported source Uids
1.321 + if ( SourceFormatRequired( aSource) )
1.322 + {
1.323 + // Get the format from the Source if possible from no specific supplier
1.324 + TRAPD(err, iSourceFormat = CMMFFormatDecode::NewL(&aSource, KNullDesC, iSourceFormatSupportsCustomInterfaces));
1.325 + //[ we want to complete silently for KErrNotSupported
1.326 + // because there is a possibility that the client
1.327 + // wants to add the data format later, see audio api for
1.328 + // a description of this feature]
1.329 + if ((err != KErrNotSupported) && (err != KErrNone))
1.330 + {
1.331 + User::Leave(err);
1.332 + }
1.333 + }
1.334 + else if (aSource.DataSourceType()==KUidMmfAudioInput)
1.335 + {
1.336 + //[ ensure that the audio input has a pointer to dev sound ]
1.337 + CMMFAudioInput* audioInput = STATIC_CAST(CMMFAudioInput*, &aSource);
1.338 + __ASSERT_ALWAYS( audioInput, Panic(ENoAudioInput));
1.339 + // [ lets load dev sound ]
1.340 + User::LeaveIfError(audioInput->SourceThreadLogon( *this ));
1.341 + }
1.342 + else
1.343 + {
1.344 + User::Leave(KErrNotSupported);
1.345 + }
1.346 +
1.347 + //[ its now safe to set the source ]
1.348 + iDataSource = &aSource ;
1.349 +
1.350 + //[ assert the post condition ]
1.351 + __ASSERT_ALWAYS(iDataSource, Panic(EMMFAudioControllerPanicDataSourceDoesNotExist));
1.352 +
1.353 + iDataSource->SetSourcePrioritySettings(iPrioritySettings);
1.354 + }
1.355 +
1.356 +/**
1.357 + * AddDataSinkL
1.358 + *
1.359 + * Adds a data sink to the controller
1.360 + *
1.361 + * @param aSink
1.362 + *
1.363 + */
1.364 +void CMMFAudioController::AddDataSinkL(MDataSink& aSink)
1.365 + {
1.366 + //[ assert the invariant ]
1.367 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetDataSink));
1.368 +
1.369 + // [ precondition that the controller is stopped ]
1.370 + if( State() != EStopped )
1.371 + User::Leave( KErrNotReady );
1.372 +
1.373 + // [ assert precondition that sink does not exist ]
1.374 + if (iDataSink)
1.375 + User::Leave(KErrAlreadyExists);
1.376 +
1.377 +
1.378 + // Note that this code is not generic for sinks
1.379 + // It it only checks for file,des clips and audio outputs
1.380 + // If a new sink type eg a Url Clip then this needs to be added to the supported source Uids
1.381 + if ( SinkFormatRequired( aSink ) )
1.382 + {//the sink is a clip
1.383 +
1.384 + // Get the format from the Sink if possible from no specific supplier
1.385 + TRAPD(err, iSinkFormat = CMMFFormatEncode::NewL(&aSink, KNullDesC));
1.386 + //[ we want to complete silently for KErrNotSupported
1.387 + // because there is a possibility that the client
1.388 + // wants to add the data format later, see audio api for
1.389 + // a description of this feature]
1.390 + if ((err != KErrNotSupported) && (err != KErrNone))
1.391 + {
1.392 + User::Leave(err);
1.393 + }
1.394 + }
1.395 + else if (aSink.DataSinkType()==KUidMmfAudioOutput)
1.396 + {
1.397 +
1.398 + //[ ensure that the audio output has a pointer to dev sound ]
1.399 + CMMFAudioOutput* audioOutput = STATIC_CAST(CMMFAudioOutput*, &aSink);
1.400 + __ASSERT_ALWAYS( audioOutput, Panic(ENoAudioOutput));
1.401 + // [ lets load dev sound ]
1.402 + User::LeaveIfError(audioOutput->SinkThreadLogon( *this ));
1.403 + if (IsSecureDrmModeL())
1.404 + {
1.405 + User::LeaveIfError(audioOutput->SoundDevice().SetClientThreadInfo(ClientThreadIdL()));
1.406 + }
1.407 + }
1.408 + else
1.409 + {
1.410 + User::Leave(KErrNotSupported);
1.411 + }
1.412 +
1.413 + //[ now that we are sure we have not left we can update the sink
1.414 + // transactionally ]
1.415 + iDataSink = &aSink;
1.416 +
1.417 + // [ assert post conditions that a sink has been added ]
1.418 + __ASSERT_ALWAYS(iDataSink, Panic(EMMFAudioControllerPanicDataSinkDoesNotExist));
1.419 +
1.420 + iDataSink->SetSinkPrioritySettings(iPrioritySettings);
1.421 + }
1.422 +
1.423 +/**
1.424 + * PrimeL
1.425 + *
1.426 + * If Prime fails the client should reset the controller
1.427 + * because as noted below this code is not transactional.
1.428 + *
1.429 + */
1.430 +void CMMFAudioController::PrimeL()
1.431 + {
1.432 + //[ assert the invariant ]
1.433 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateForPrime));
1.434 +
1.435 + //[ assert the precondition ( in a friendly way for this api
1.436 + // that we are either stopped or primed already ]
1.437 + if(!(( State() == EStopped ) || (State() == EPrimed )))
1.438 + User::Leave( KErrNotReady );
1.439 +
1.440 + // [ precondition we have a data source & sink ]
1.441 + __ASSERT_ALWAYS( iDataSource, Panic( ENoDataSource));
1.442 + __ASSERT_ALWAYS( iDataSink, Panic( ENoDataSink));
1.443 +
1.444 +
1.445 + //[ precondition that we need a source format ]
1.446 + if ( SourceFormatRequired(*iDataSource) && !(iSourceFormat))
1.447 + User::Leave( KErrNotSupported );
1.448 +
1.449 + // [ check the precondition if we need a data sink format ]
1.450 + if ( SinkFormatRequired(*iDataSink) && !( iSinkFormat ))
1.451 + {
1.452 + User::Leave( KErrNotSupported );
1.453 + }
1.454 +
1.455 + // [ ideally this code should be transaction based and
1.456 + // if failure occurs we roll back to the previous state
1.457 + // in the code below this is not the case and the controller
1.458 + // can be left in an unstable state should any part of prime fail]
1.459 + if (iState == EStopped)
1.460 + { //datapath propagates prime to sink & source
1.461 +
1.462 + NegotiateL();
1.463 +
1.464 + if (!iSourceAndSinkAdded)
1.465 + {
1.466 + //add data source and sinks to datapath - Note cant do this in AddDataSource/Sink
1.467 + //because the sources and sinks aren't configured at this point
1.468 + if (iSourceFormat)
1.469 + iDataPath->AddDataSourceL(iSourceFormat);
1.470 + else if (iDataSource)
1.471 + iDataPath->AddDataSourceL(iDataSource);
1.472 + if (iSinkFormat)
1.473 + iDataPath->AddDataSinkL(iSinkFormat);
1.474 + else if (iDataSink)
1.475 + iDataPath->AddDataSinkL(iDataSink);
1.476 + iSourceAndSinkAdded = ETrue ;
1.477 + }
1.478 +
1.479 + iDataPath->PrimeL();
1.480 +
1.481 + if (iSourceFormat)
1.482 + {
1.483 + //in case of imaadpcm format set the output block length
1.484 +
1.485 + TFourCC sourceFourCC = iSourceFormat->SourceDataTypeCode(TMediaId(KUidMediaTypeAudio));
1.486 + if ((sourceFourCC == KMMFFourCCCodeIMAD) && iSourceFormatSupportsCustomInterfaces)
1.487 + {
1.488 + CMMFFormatDecode2* decode2 = static_cast<CMMFFormatDecode2*>(iSourceFormat);
1.489 + MMMFDecodeCustomInterfaceBlockLength* formatBlockLengthCI = static_cast<MMMFDecodeCustomInterfaceBlockLength*>(decode2->CustomInterface(KUidCustomInterfaceMmfDecodeBlockLength));
1.490 + if (formatBlockLengthCI)
1.491 + {
1.492 + TInt blockLength = formatBlockLengthCI->FileBlockLength();
1.493 + TInt err = iDataPath->SetBlockLength(blockLength);
1.494 +
1.495 + if ((err != KErrNone) && (iDataSink))
1.496 + {
1.497 + MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
1.498 + MMMFDevSoundCustomInterfaceFileBlockLength* fileBlockLengthCI = static_cast<MMMFDevSoundCustomInterfaceFileBlockLength*>(audioOutput->SoundDevice().CustomInterface(KUidCustomInterfaceDevSoundFileBlockLength));
1.499 +
1.500 + if (fileBlockLengthCI)
1.501 + {
1.502 + fileBlockLengthCI->SetFileBlockLength(blockLength);
1.503 + err = KErrNone;
1.504 + }
1.505 + }
1.506 + User::LeaveIfError(err);
1.507 + }
1.508 + }
1.509 + }
1.510 +
1.511 + if ((iSinkFormat) && (!iSourceFormat))
1.512 + {//we are recording to a clip so the data path position is the sink
1.513 + //need to set datapath position to end of format pos (incase sink clip already exists
1.514 + TTimeIntervalMicroSeconds duration = iSinkFormat->Duration(iMediaId);
1.515 + if (duration != TTimeIntervalMicroSeconds(0))
1.516 + {//the file already exists and has a duration so set data path position to the end of the file
1.517 + iDataPath->SetPositionL(duration);
1.518 + }
1.519 + }
1.520 + //[ it is now safe to make the transition to primed ]
1.521 + SetState( EPrimed );
1.522 + }
1.523 + else if (State() == EPrimed)
1.524 + { //controller is already primed so just pass prime onto DP
1.525 + iDataPath->PrimeL();
1.526 + }
1.527 +
1.528 + if (iDataSource->DataSourceType()==KUidMmfFileSource)
1.529 + {
1.530 + CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
1.531 + // we only support protected files for playback
1.532 + if (iDataSink->DataSinkType()!=KUidMmfAudioOutput && file->IsProtectedL())
1.533 + User::Leave(KErrNotSupported);
1.534 + }
1.535 +
1.536 + //[ assert the post condition that we are in the state primed]
1.537 + __ASSERT_ALWAYS( SetState( EPrimed ), Panic( EPostConditionViolation ));
1.538 + // [ assert the invariant]
1.539 + __ASSERT_ALWAYS( Invariant(), Panic( EStateNotPrimed ) );
1.540 + }
1.541 +
1.542 +/**
1.543 + * ResetL
1.544 + * This method resets the controller
1.545 + *
1.546 + */
1.547 +void CMMFAudioController::ResetL()
1.548 + {
1.549 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToReset ) );
1.550 + iIsPreemptionPause = EFalse;
1.551 + // Stop recording if it's not stopped,
1.552 + if (State() != EStopped)
1.553 + {
1.554 + iDataPath->Stop();
1.555 + SetState(EStopped);
1.556 + }
1.557 + iIsPaused = EFalse;
1.558 +
1.559 + // Remove references to source and sink
1.560 + iDataPath->ResetL();
1.561 +
1.562 + delete iSourceFormat; iSourceFormat = NULL ;
1.563 + delete iSinkFormat; iSinkFormat = NULL ;
1.564 +
1.565 + //[ ensure loggoff of source and sink ]
1.566 + iDataSource = NULL ;
1.567 + iDataSink = NULL ;
1.568 + iSourceAndSinkAdded = EFalse;
1.569 +
1.570 + // [ assert the invariant]
1.571 + __ASSERT_ALWAYS( Invariant(), Panic( EBadResetState ) );
1.572 +
1.573 + // [ assert the post condition
1.574 + // state == stopped
1.575 + // iDataSource is NULL
1.576 + // iSourceFormat is NULL
1.577 + // iSinkFormat is NULL ]
1.578 + __ASSERT_ALWAYS( ResetPostCondition(), Panic( EBadReset ));
1.579 + __ASSERT_ALWAYS( Invariant(), Panic(EBadState));
1.580 + }
1.581 +
1.582 +/**
1.583 +* ResetPostCondition
1.584 +* This function determnines if the reset post condition is valid
1.585 +* @internalTechnology
1.586 +*/
1.587 +TBool CMMFAudioController::ResetPostCondition() const
1.588 + {
1.589 +
1.590 + TBool result = EFalse ;
1.591 + if((iSourceFormat == NULL) &&
1.592 + (iDataSink == NULL) &&
1.593 + (iDataSource == NULL) &&
1.594 + (iSinkFormat == NULL) &&
1.595 + (State() == EStopped))
1.596 + {
1.597 + result = ETrue;
1.598 + }
1.599 +
1.600 + return result;
1.601 + }
1.602 +
1.603 +
1.604 +/**
1.605 + *
1.606 + * PlayL
1.607 + *
1.608 + */
1.609 +void CMMFAudioController::PlayL()
1.610 + {
1.611 + // [ assert the precondition that the
1.612 + // play command is only activated in the primed state]
1.613 + if ( State() != EPrimed)
1.614 + {
1.615 + User::Leave(KErrNotReady);
1.616 + }
1.617 +
1.618 + // [ assert the Invariant ]
1.619 + __ASSERT_ALWAYS( Invariant(), Panic(EStateNotReadyToPlay));
1.620 +
1.621 + // if the position has already been set to the file's duration or
1.622 + // beyond, then don't bother getting the datapath to play - this
1.623 + // avoids sending empty buffers to DevSound
1.624 + if (iDataSink->DataSinkType() == KUidMmfAudioOutput &&
1.625 + PositionL() >= DurationL())
1.626 + {
1.627 + SendEventToClient(TMMFEvent(KMMFEventCategoryPlaybackComplete, KErrNone));
1.628 + return;
1.629 + }
1.630 +
1.631 + // Execute play intent
1.632 + // This must be done after PlayL, as the file might not be open yet
1.633 + if(!iIsPreemptionPause)
1.634 + {
1.635 + if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource )
1.636 + {
1.637 + CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
1.638 + TInt err = file->ExecuteIntent(iIsPaused? ContentAccess::EContinue : ContentAccess::EPlay);
1.639 + if (err != KErrNone)
1.640 + {
1.641 + User::Leave(err);
1.642 + }
1.643 + }
1.644 + }
1.645 + //[datapath propogates play to sink & source]
1.646 + iDataPath->PlayL();
1.647 + iIsPreemptionPause = EFalse;
1.648 + iIsPaused = EFalse;
1.649 + SetState( EPlaying );
1.650 +
1.651 + //[ assert the post condition we are playing ]
1.652 + //No - this assumption is not always true if an error occurs eg OOM
1.653 + //the state could be EStopped
1.654 + // __ASSERT_ALWAYS( (State() == EPlaying ), Panic( EBadState));
1.655 + //[ assert the invariant ]
1.656 + __ASSERT_ALWAYS( Invariant(), Panic(EBadPlayState));
1.657 + }
1.658 +
1.659 +/**
1.660 + * PauseL
1.661 + *
1.662 + */
1.663 +void CMMFAudioController::PauseL()
1.664 + {
1.665 + // [ assert the invariant ]
1.666 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToPause));
1.667 +
1.668 + //[ assert the precondition that we are playing ]
1.669 + if ( State() != EPlaying)
1.670 + {
1.671 + User::Leave(KErrNotReady);
1.672 + }
1.673 + if(!iIsPreemptionPause)
1.674 + {
1.675 + if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource)
1.676 + {
1.677 + CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
1.678 + TInt err = file->ExecuteIntent(ContentAccess::EPause);
1.679 + if (err != KErrNone)
1.680 + {
1.681 + User::Leave(err);
1.682 + }
1.683 + }
1.684 + }
1.685 + iIsPaused = ETrue;
1.686 + //[ datapath propogates pause to sink & source ]
1.687 + if(iIsPreemptionPause)
1.688 + {
1.689 + iDataPath->PreEmptionPause();
1.690 + }
1.691 + else
1.692 + {
1.693 + iDataPath->Pause();
1.694 + }
1.695 + SetState(EPrimed);
1.696 +
1.697 + //[ assert the post condition we are primed ]
1.698 + __ASSERT_ALWAYS( (State() == EPrimed ), Panic( EBadState));
1.699 + //[ assert the invariant ]
1.700 + __ASSERT_ALWAYS( Invariant(), Panic(EBadPauseState));
1.701 + }
1.702 +
1.703 +/**
1.704 + * StopL
1.705 + *
1.706 + */
1.707 +void CMMFAudioController::StopL(TMMFMessage& aMessage)
1.708 + {
1.709 + //[ assert the invariant ]
1.710 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToStop));
1.711 + // [ precondition that we are not already stopped
1.712 + // && if we are stopped do nothing.
1.713 + //If we are stopping a recording, we need to give the datapath chance to
1.714 + //process that data which has already been captured. We therefore stay in the EPlaying
1.715 + //state, but use iStoppingRecording to indicate that we are stopping.
1.716 +
1.717 + if ((State() != EStopped) && !iStoppingRecording)
1.718 + {
1.719 + if((State() == EPlaying) && (iDataSource->DataSourceType()==KUidMmfAudioInput)) //we are recording
1.720 + {
1.721 + // datapath is requested to stop recording but process any alreay captured buffers,
1.722 + // the pause method is used for this purpose and as such, the data path must
1.723 + // determine that it is recording to be able to act accordingly.
1.724 + // aMessgae is not completed until datapath advises that it has completed.
1.725 + iDataPath->Pause();
1.726 + iStoppingMessage = CMMFMessageHolder::NewL(aMessage);
1.727 + iStoppingRecording = ETrue;
1.728 + }
1.729 + else if(((State() == EPlaying) || iIsPaused) && (iDataSink->DataSinkType()==KUidMmfAudioOutput)) //we are playing
1.730 + {
1.731 + if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource)
1.732 + {
1.733 + CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
1.734 + file->ExecuteIntent(ContentAccess::EStop);
1.735 + }
1.736 + // datapath propogates stop to sink & source
1.737 + iDataPath->Stop();
1.738 + SetState(EStopped);
1.739 + }
1.740 +
1.741 + else
1.742 + {
1.743 + // datapath propogates stop to sink & source
1.744 + iDataPath->Stop();
1.745 + SetState(EStopped);
1.746 + }
1.747 + }
1.748 + iIsPaused = EFalse;
1.749 + iIsPreemptionPause = EFalse;
1.750 + //complete message as request is complete.
1.751 + if(State() == EStopped && !IsUnderTest())
1.752 + {
1.753 + aMessage.Complete(KErrNone);
1.754 + }
1.755 +
1.756 + //[ assert the invariant ]
1.757 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStopState));
1.758 + }
1.759 +
1.760 +/**
1.761 + * PositionL
1.762 + * Preconditions:
1.763 + * The Controller is in the state EPrimed
1.764 + * @return TTimeIntervalMicroSeconds
1.765 + *
1.766 + */
1.767 +TTimeIntervalMicroSeconds CMMFAudioController::PositionL() const
1.768 + {
1.769 + //[ assert the invariant ]
1.770 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToPosition));
1.771 + // [ precondition that we are playing or primed ]
1.772 + if( !((State() == EPrimed) || (State() == EPlaying)))
1.773 + User::Leave(KErrNotReady);
1.774 +
1.775 + TTimeIntervalMicroSeconds position = iDataPath->Position();
1.776 +
1.777 + //[ assert the invariant ]
1.778 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStatePosition));
1.779 +
1.780 + return position;
1.781 + }
1.782 +
1.783 +/**
1.784 +* SetPositionL
1.785 +*
1.786 +* @param aPosition
1.787 +*
1.788 +*/
1.789 +void CMMFAudioController::SetPositionL(const TTimeIntervalMicroSeconds& aPosition)
1.790 + {
1.791 + //[ assert the invariant ]
1.792 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetPosition));
1.793 +
1.794 + // [ precondition that we are not already stopped ]
1.795 + if (iState == EStopped)
1.796 + User::Leave(KErrNotReady);
1.797 +
1.798 + //[ precondition that the position is >= 0 && <= Duration ]
1.799 + {
1.800 + TTimeIntervalMicroSeconds theDuration(0);
1.801 + if (iSourceFormat)
1.802 + { //if the source is a clip then the duration always refers to the source - even if the sink is a clip
1.803 + theDuration = iSourceFormat->Duration(iMediaId);
1.804 + }
1.805 + else if (iSinkFormat)
1.806 + { //duration of recorded clip
1.807 + theDuration = iSinkFormat->Duration(iMediaId);
1.808 + }
1.809 + TTimeIntervalMicroSeconds theStart(0);
1.810 + if( ( aPosition < theStart) || ( aPosition > theDuration) )
1.811 + //[ invalid position before start and after end]
1.812 + User::Leave(KErrArgument);
1.813 + }
1.814 +
1.815 + //[ set the position on the data path ]
1.816 +
1.817 + // if we're already playing, flush all the buffers by calling Stop(),
1.818 + // PrimeL() and then PlayL() - otherwise we could be waiting a long time.
1.819 + if (iDataSink->DataSinkType() == KUidMmfAudioOutput && iState == EPlaying)
1.820 + {
1.821 + CMMFAudioOutput* audioOutput = static_cast<CMMFAudioOutput*>(iDataSink);
1.822 + if(!audioOutput->IsResumeSupported())
1.823 + {
1.824 + iDataPath->Stop();
1.825 + SetState(EStopped);
1.826 + PrimeL();
1.827 + iDataPath->SetPositionL(aPosition);
1.828 + iDataPath->RetainRepeatInfo();
1.829 + PlayL();
1.830 + }
1.831 + else
1.832 + {
1.833 + iDataPath->Pause();
1.834 + // This empty buffers
1.835 + User::LeaveIfError(audioOutput->SoundDevice().EmptyBuffers());
1.836 + iDataPath->SetPositionL(aPosition);
1.837 + iDataPath->RetainRepeatInfo();
1.838 + // This does a DevSound resume
1.839 + iDataPath->PlayL();
1.840 + }
1.841 + }
1.842 + else
1.843 + iDataPath->SetPositionL(aPosition);
1.844 +
1.845 + //[ assert the invariant ]
1.846 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateSetPosition));
1.847 +
1.848 + // [ post condition not checked ]
1.849 + //[ we do not compare the set position with get postion
1.850 + // because the interface to do so is poor ]
1.851 + }
1.852 +
1.853 +/**
1.854 +*
1.855 +* DurationL
1.856 +*
1.857 +* @returns TTimeIntervalMicroSeconds
1.858 +*
1.859 +*/
1.860 +TTimeIntervalMicroSeconds CMMFAudioController::DurationL() const
1.861 + {
1.862 + //[ assert the invariant ]
1.863 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToDuration));
1.864 +
1.865 +
1.866 + // [ assert we have a format that supports duration ]
1.867 + if( !( iSourceFormat || iSinkFormat ) )
1.868 + User::Leave(KErrNotSupported);
1.869 +
1.870 + //[ now do the real work of getting the duration ]
1.871 + // ------------------------------------------------
1.872 + TTimeIntervalMicroSeconds theDuration(0);
1.873 + if (iSourceFormat)
1.874 + { //if the source is a clip then the duration always refers to the source - even if the sink is a clip
1.875 + theDuration = iSourceFormat->Duration(iMediaId);
1.876 + }
1.877 + else if (iSinkFormat)
1.878 + { //duration of recorded clip
1.879 + theDuration = iSinkFormat->Duration(iMediaId);
1.880 + }
1.881 +
1.882 + //[ assert the invariant ]
1.883 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateDuration));
1.884 +
1.885 + return theDuration;
1.886 + }
1.887 +
1.888 +/**
1.889 +*
1.890 +* GetNumberOfMetaDataEntriesL
1.891 +*
1.892 +* @param "TInt"
1.893 +*
1.894 +*/
1.895 +void CMMFAudioController::GetNumberOfMetaDataEntriesL(TInt& aNumberOfEntries )
1.896 + {
1.897 +
1.898 + //[ assert the invariant ]
1.899 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetNumberOfMetaDataEntries));
1.900 +
1.901 + //[ precondition that we are in the primed state or stopped ]
1.902 + if( !((State() == EPrimed) || ( State() == EStopped)))
1.903 + User::Leave(KErrNotReady);
1.904 +
1.905 + // [ precondition there is a sink format ]
1.906 + if (!iDataSink)
1.907 + User::Leave(KErrNotSupported);
1.908 +
1.909 + // [ precondition the sink format is an encode format ]
1.910 + if ((iDataSink->DataSinkType()!=KUidMmfAudioOutput) &&
1.911 + (iDataSource->DataSourceType()!= KUidMmfAudioInput) )
1.912 + User::Leave(KErrNotSupported);
1.913 +
1.914 + if (iDataSink->DataSinkType()==KUidMmfAudioOutput)
1.915 + {
1.916 +
1.917 + //[ precondition the format exists ]
1.918 + if( !iSourceFormat )
1.919 + User::Leave(KErrNotSupported);
1.920 +
1.921 + //[ Get the Number of meta data entries from the sink format ]
1.922 + iSourceFormat->GetNumberOfMetaDataEntriesL( aNumberOfEntries );
1.923 + }
1.924 + else if (iDataSource->DataSourceType()==KUidMmfAudioInput)
1.925 + {
1.926 + if( !iSinkFormat )
1.927 + User::Leave(KErrNotSupported);
1.928 +
1.929 + iSinkFormat->GetNumberOfMetaDataEntriesL( aNumberOfEntries );
1.930 + }
1.931 +
1.932 + //[ assert the invariant ]
1.933 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateGetNumberOfMetaDataEntries));
1.934 +
1.935 + }
1.936 +
1.937 +/**
1.938 +* GetMetaDataEntryL
1.939 +* @param aIndex
1.940 +* @returns "CMMFMetaDataEntry*"
1.941 +*/
1.942 +CMMFMetaDataEntry* CMMFAudioController::GetMetaDataEntryL(TInt aIndex )
1.943 + {
1.944 + //[ assert the invariant ]
1.945 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMetaDataEntries));
1.946 +
1.947 + //[ precondition that we are in the primed state or stopped ]
1.948 + if( !((State() == EPrimed) || ( State() == EStopped)))
1.949 + User::Leave(KErrNotReady);
1.950 +
1.951 + // [ precondition there is a sink format ]
1.952 + if (!iDataSink)
1.953 + User::Leave(KErrNotSupported);
1.954 +
1.955 + iDataSink->DataSinkType();
1.956 + iDataSource->DataSourceType();
1.957 +
1.958 + // [ precondition the sink or source is either an audio output or input ]
1.959 + if ((iDataSink->DataSinkType()!= KUidMmfAudioOutput) &&
1.960 + (iDataSource->DataSourceType()!= KUidMmfAudioInput ))
1.961 + User::Leave(KErrNotSupported);
1.962 +
1.963 + //[ Get the meta data entry from the sink format ]
1.964 + CMMFMetaDataEntry* theEntry = NULL;
1.965 +
1.966 + if (iDataSink->DataSinkType()==KUidMmfAudioOutput)
1.967 + {
1.968 + //[ precondition the format exists ]
1.969 + if( !iSourceFormat )
1.970 + User::Leave(KErrNotSupported);
1.971 +
1.972 + //[ Get the Number of meta data entries from the sink format ]
1.973 + theEntry = iSourceFormat->MetaDataEntryL(aIndex);
1.974 + }
1.975 + else if (iDataSource->DataSourceType()==KUidMmfAudioInput)
1.976 + {
1.977 + //[ precondition the format exits ]
1.978 + if( !iSinkFormat )
1.979 + User::Leave(KErrNotSupported);
1.980 + theEntry = iSinkFormat->MetaDataEntryL(aIndex);
1.981 + }
1.982 +
1.983 + //[ assert the post condition that the entry is not null ]
1.984 + __ASSERT_ALWAYS( theEntry, Panic(EMetaEntryIsNull));
1.985 +
1.986 + //[ assert the invariant ]
1.987 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateGetMetaDataEntries));
1.988 +
1.989 + return theEntry;
1.990 + }
1.991 +
1.992 +/**
1.993 +* RemoveDataSourceL
1.994 +* @param aDataSource
1.995 +*
1.996 +*/
1.997 +void CMMFAudioController::RemoveDataSourceL(MDataSource& aDataSource )
1.998 + {
1.999 + //[ assert the invariant ]
1.1000 + __ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForDataSourceRemoval) );
1.1001 +
1.1002 + //[ precondition is that we have a data source ]
1.1003 + if( !iDataSource )
1.1004 + User::Leave(KErrNotReady);
1.1005 +
1.1006 + //[precondition the data source is the data source we have]
1.1007 + if( iDataSource != &aDataSource )
1.1008 + User::Leave(KErrArgument);
1.1009 +
1.1010 + //[ the controller is in the stopped state ]
1.1011 + if(State() != EStopped)
1.1012 + User::Leave(KErrNotReady);
1.1013 +
1.1014 + //[ remove the data sink from the controller and delete the format]
1.1015 + if( iSourceAndSinkAdded )
1.1016 + {
1.1017 + __ASSERT_ALWAYS( iDataPath, Panic( EBadState ));
1.1018 + //[ Remove references to source and sink ]
1.1019 + iDataPath->ResetL();
1.1020 + iSourceAndSinkAdded = EFalse ;
1.1021 + }
1.1022 +
1.1023 + // [ delete the data sink and format ]
1.1024 + iDataSource = NULL ;
1.1025 + delete iSourceFormat;
1.1026 + iSourceFormat = NULL;
1.1027 +
1.1028 + // [ assert postcondition we are stopped ]
1.1029 + __ASSERT_ALWAYS( (State() == EStopped), Panic(EPostConditionViolation) );
1.1030 +
1.1031 + //[ assert postcondition the SourceAndSinkAdded is false ]
1.1032 + __ASSERT_ALWAYS( !iSourceAndSinkAdded, Panic( EPostConditionViolation ));
1.1033 +
1.1034 + //[ assert postcondition the data sinkformat is null ]
1.1035 + __ASSERT_ALWAYS( (iSourceFormat == NULL ), Panic( EPostConditionViolation ));
1.1036 +
1.1037 + //[ assert postcondition the data sink is null ]
1.1038 + __ASSERT_ALWAYS( (iDataSource == NULL ), Panic( EPostConditionViolation ));
1.1039 +
1.1040 + //[ assert the invariant ]
1.1041 + __ASSERT_ALWAYS( Invariant(), Panic(EBadDataSourceRemoval));
1.1042 +
1.1043 + }
1.1044 +
1.1045 +/**
1.1046 +* RemoveDataSinkL
1.1047 +*
1.1048 +* @param aDataSink
1.1049 +*
1.1050 +*/
1.1051 +void CMMFAudioController::RemoveDataSinkL(MDataSink& aDataSink )
1.1052 + {
1.1053 + //[ assert the invariant ]
1.1054 + __ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForDataSinkRemoval) );
1.1055 +
1.1056 + //[ precondition is that we have a data sink ]
1.1057 + if( !iDataSink )
1.1058 + User::Leave(KErrNotSupported);
1.1059 +
1.1060 + //[precondition the data sink is the data sink we have]
1.1061 + if( iDataSink != &aDataSink )
1.1062 + User::Leave(KErrNotSupported);
1.1063 +
1.1064 + //[ the controller is in the stopped state ]
1.1065 + if(State() != EStopped)
1.1066 + User::Leave(KErrNotReady);
1.1067 +
1.1068 + //[ remove the data sink from the controller and delete the format]
1.1069 + if( iSourceAndSinkAdded )
1.1070 + {
1.1071 + __ASSERT_ALWAYS( iDataPath, Panic( EBadState ));
1.1072 + //[ Remove references to source and sink ]
1.1073 + iDataPath->ResetL();
1.1074 + iSourceAndSinkAdded = EFalse ;
1.1075 + }
1.1076 +
1.1077 + // [ reset data sink referenece and remove the format ]
1.1078 + iDataSink = NULL ;
1.1079 + delete iSinkFormat;
1.1080 + iSinkFormat = NULL;
1.1081 +
1.1082 + // [ assert postcondition we are stopped ]
1.1083 + __ASSERT_ALWAYS( (State() == EStopped), Panic(EPostConditionViolation) );
1.1084 +
1.1085 + //[ assert postcondition the SourceAndSinkAdded is false ]
1.1086 + __ASSERT_ALWAYS( !iSourceAndSinkAdded, Panic( EPostConditionViolation ));
1.1087 +
1.1088 + //[ assert postcondition the data sinkformat is null ]
1.1089 + __ASSERT_ALWAYS( (iSinkFormat == NULL ), Panic( EPostConditionViolation ));
1.1090 +
1.1091 + //[ assert postcondition the data sink is null ]
1.1092 + __ASSERT_ALWAYS( (iDataSink == NULL ), Panic( EPostConditionViolation ));
1.1093 +
1.1094 + //[ assert the invariant ]
1.1095 + __ASSERT_ALWAYS( Invariant(), Panic(EBadDataSinkRemoval));
1.1096 + }
1.1097 +
1.1098 +/**
1.1099 + * CustomCommand
1.1100 + * @param aMessage
1.1101 + */
1.1102 +void CMMFAudioController::CustomCommand(TMMFMessage& aMessage)
1.1103 + {
1.1104 + //[ assert the invariant ]
1.1105 + __ASSERT_ALWAYS( Invariant(), Panic(ENotReadyForCustomCommand));
1.1106 + // [ We do not have any custom commands ]
1.1107 + aMessage.Complete(KErrNotSupported);
1.1108 + }
1.1109 +
1.1110 +/**
1.1111 +* NegotiateL
1.1112 +*
1.1113 +*/
1.1114 +void CMMFAudioController::NegotiateL()
1.1115 + {
1.1116 + //[ assert the invariant ]
1.1117 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToNegotiate));
1.1118 +
1.1119 + //utility function used by custom to negotiate source sink settings after a change
1.1120 + if ((iSourceFormat)&&(iSinkFormat)) //convert
1.1121 + {
1.1122 + iSinkFormat->NegotiateL(*iSourceFormat);
1.1123 + iSourceFormat->NegotiateSourceL(*iSinkFormat);
1.1124 + iSinkFormat->NegotiateL(*iSourceFormat);
1.1125 +
1.1126 + // check for upsampling attempts
1.1127 + if (iSinkFormat->SampleRate() > iSourceFormat->SampleRate())
1.1128 + {
1.1129 + // we don't support upsampling
1.1130 + User::Leave( KErrNotSupported );
1.1131 + }
1.1132 + }
1.1133 + else if ((iDataSource)&&(iSinkFormat)) //record
1.1134 + {
1.1135 + // need two step negotiation for record
1.1136 + // first try to set the audio input settings to match the required settings for recording
1.1137 + iDataSource->NegotiateSourceL(*iSinkFormat);
1.1138 + // now call negotiateL on the sink in order to tell it what the audio input was set to.
1.1139 + iSinkFormat->NegotiateL(*iDataSource);
1.1140 + }
1.1141 + else if ((iSourceFormat)&&(iDataSink)) //play
1.1142 + {
1.1143 + iDataSink->NegotiateL(*iSourceFormat);
1.1144 + }
1.1145 + //[ assert the invariant ]
1.1146 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterNegotiate));
1.1147 + }
1.1148 +
1.1149 +/**
1.1150 + * SetPrioritySettings
1.1151 + *
1.1152 + * @param aPrioritySettings
1.1153 + */
1.1154 +void CMMFAudioController::SetPrioritySettings(const TMMFPrioritySettings& aPrioritySettings)
1.1155 + {
1.1156 + //[ assert the invariant ]
1.1157 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetPriority));
1.1158 +
1.1159 + //[ update the priority settings of the controller]
1.1160 + iPrioritySettings = aPrioritySettings;
1.1161 +
1.1162 + //pass settings on to source and sink
1.1163 + if (iDataSource)
1.1164 + {
1.1165 + iDataSource->SetSourcePrioritySettings(iPrioritySettings);
1.1166 + }
1.1167 + if (iDataSink)
1.1168 + {
1.1169 + iDataSink->SetSinkPrioritySettings(iPrioritySettings);
1.1170 + }
1.1171 +
1.1172 + // assert the post condition
1.1173 + //__ASSERT_ALWAYS( (iPrioritySettings == aPrioritySettings), Panic( ));
1.1174 + //[ assert the invariant ]
1.1175 + __ASSERT_ALWAYS( Invariant(), Panic(EBadPriorityState));
1.1176 + }
1.1177 +
1.1178 +/**
1.1179 + * SendEventToClient
1.1180 + *
1.1181 + * @param aEvent
1.1182 + */
1.1183 +TInt CMMFAudioController::SendEventToClient(const TMMFEvent& aEvent)
1.1184 + {
1.1185 + //[ assert the invariant ]
1.1186 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSendEventToClient));
1.1187 +
1.1188 + TMMFEvent controllerEvent;
1.1189 + //Were going to stop playing, force event type to be the correct type
1.1190 + controllerEvent.iEventType = KMMFEventCategoryPlaybackComplete;
1.1191 + controllerEvent.iErrorCode = aEvent.iErrorCode;
1.1192 +
1.1193 +
1.1194 +
1.1195 + //If we receive KErrNone from the DataPath, it indicates that it has
1.1196 + //successfully completed playing/converting/recording.
1.1197 + if ((aEvent.iEventType == KMMFEventCategoryPlaybackComplete) &&
1.1198 + (aEvent.iErrorCode == KErrNone))
1.1199 + {
1.1200 + if(iStoppingRecording)
1.1201 + {
1.1202 + iStoppingRecording = EFalse;
1.1203 + iDataPath->Stop();
1.1204 + SetState( EStopped );
1.1205 +
1.1206 + //complete the clients stop request
1.1207 + iStoppingMessage->Complete(KErrNone);
1.1208 + delete iStoppingMessage; iStoppingMessage=NULL;
1.1209 +
1.1210 + //we don't want to send an event to the client
1.1211 + return KErrNone;
1.1212 + }
1.1213 + else
1.1214 + {//datapath has reached end of file so set internal state to primed
1.1215 + SetState( EPrimed );
1.1216 + }
1.1217 + }
1.1218 + //DevCR KEVN-7T5EHA
1.1219 + //If the client has not registered for the ARN,
1.1220 + //and a pre-emption happens we need to goto the Pause state
1.1221 + //instead of the Stop state. this should happen only in the case of playback.
1.1222 + //In case of recoding we goto the stop state.
1.1223 + else if(!iRegisterARN &&
1.1224 + (aEvent.iErrorCode == KErrAccessDenied || aEvent.iErrorCode == KErrInUse ||aEvent.iErrorCode == KErrDied)
1.1225 + && (iDataSink->DataSinkType()==KUidMmfAudioOutput))
1.1226 + {
1.1227 + //setting iIsPreemptionPause to true so that PauseL can make differentiate it from normal pause.
1.1228 + iIsPreemptionPause = ETrue;
1.1229 + TRAPD(err,PauseL());
1.1230 + if(err != KErrNone)
1.1231 + {
1.1232 + iDataPath->Stop();
1.1233 + SetState( EStopped );
1.1234 + iIsPreemptionPause = EFalse;
1.1235 + }
1.1236 + }
1.1237 + else
1.1238 + {
1.1239 + if ( State()!= EStopped)
1.1240 + {
1.1241 + //datapath propogates stop to sink & source
1.1242 + iDataPath->Stop();
1.1243 + SetState( EStopped );
1.1244 +
1.1245 + if(iStoppingRecording)
1.1246 + {// an error has occurred while we were waiting for recording to stop,
1.1247 + //must complete clients request
1.1248 + iStoppingRecording = EFalse;
1.1249 + iStoppingMessage->Complete(aEvent.iErrorCode);
1.1250 + delete iStoppingMessage; iStoppingMessage=NULL;
1.1251 + }
1.1252 + }
1.1253 + }
1.1254 + if(!iIsPreemptionPause)
1.1255 + {
1.1256 + //should call ExecuteIntent to tell the DRM agent that playback has stopped
1.1257 + if (aEvent.iEventType == KMMFEventCategoryPlaybackComplete)
1.1258 + {
1.1259 + if ((iDataSink->DataSinkType() == KUidMmfAudioOutput))
1.1260 + {
1.1261 + if (!iDisableAutoIntent && iDataSource->DataSourceType()==KUidMmfFileSource)
1.1262 + {
1.1263 + CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
1.1264 + file->ExecuteIntent(ContentAccess::EStop);
1.1265 + }
1.1266 + }
1.1267 + }
1.1268 + }
1.1269 +
1.1270 + //now send event to client...
1.1271 + TInt result = KErrNone;
1.1272 + if(aEvent.iEventType == KMMFEventCategoryAudioResourceAvailable)
1.1273 + {
1.1274 + result = DoSendEventToClient(aEvent);
1.1275 + }
1.1276 + else
1.1277 + {
1.1278 + result = DoSendEventToClient(controllerEvent);
1.1279 + }
1.1280 +
1.1281 + //[ assert the invariant ]
1.1282 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSendEventToClient));
1.1283 +
1.1284 + return result;
1.1285 + }
1.1286 +
1.1287 +
1.1288 +/**
1.1289 +* MapdSetVolumeL
1.1290 +*
1.1291 +* @param aVolume
1.1292 +*
1.1293 +*/
1.1294 +void CMMFAudioController::MapdSetVolumeL(TInt aVolume)
1.1295 + {
1.1296 + //[ assert the invariant ]
1.1297 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetVolume));
1.1298 +
1.1299 + // [ precondition is true for state
1.1300 + // we can set the volume in any state ]
1.1301 +
1.1302 + //[ precondition we have a data sink ]
1.1303 + if (!iDataSink)
1.1304 + User::Leave(KErrNotReady);
1.1305 +
1.1306 + // [ precondition that the data sink is an audio output ]
1.1307 + // Make sure that iDataSink is an Audio Output
1.1308 + if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1.1309 + User::Leave(KErrNotSupported);
1.1310 +
1.1311 + MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1.1312 +
1.1313 + // [ assert the precondition that aVolume is in range ]
1.1314 + TInt maxVolume = audioOutput->SoundDevice().MaxVolume();
1.1315 + if( ( aVolume < 0 ) || ( aVolume > maxVolume ))
1.1316 + User::Leave(KErrArgument);
1.1317 +
1.1318 + //[ set the volume on the device ]
1.1319 + audioOutput->SoundDevice().SetVolume(aVolume);
1.1320 +
1.1321 + //[ assert the post condition volume is equal to a volume]
1.1322 + TInt soundVolume = 0;
1.1323 + soundVolume = audioOutput->SoundDevice().Volume();
1.1324 +
1.1325 + __ASSERT_ALWAYS( ( soundVolume == aVolume), Panic(EPostConditionViolation));
1.1326 +
1.1327 + //[ assert the invariant ]
1.1328 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterVolumeSet));
1.1329 + }
1.1330 +
1.1331 +/**
1.1332 +*
1.1333 +* MapdGetMaxVolumeL
1.1334 +*
1.1335 +* @param aMaxVolume
1.1336 +*
1.1337 +*/
1.1338 +void CMMFAudioController::MapdGetMaxVolumeL(TInt& aMaxVolume)
1.1339 + {
1.1340 + // [ assert the invariant ]
1.1341 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxVolume));
1.1342 +
1.1343 + //[ we can get max volume in any state ]
1.1344 +
1.1345 + // [ precondition we must have a data sink ]
1.1346 + if (!iDataSink)
1.1347 + User::Leave(KErrNotReady);
1.1348 +
1.1349 + //[ precondition the sink must be an audio output]
1.1350 + // Make sure that iDataSink is an Audio Output
1.1351 + if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1.1352 + User::Leave(KErrNotSupported);
1.1353 +
1.1354 + //[ get the volume from the device ]
1.1355 + MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1.1356 + aMaxVolume = audioOutput->SoundDevice().MaxVolume();
1.1357 +
1.1358 + //[ assert the invariant ]
1.1359 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxVolume));
1.1360 +
1.1361 + }
1.1362 +
1.1363 +
1.1364 +/**
1.1365 +*
1.1366 +* MapdGetVolumeL
1.1367 +*
1.1368 +* @param aVolume
1.1369 +*
1.1370 +*/
1.1371 +void CMMFAudioController::MapdGetVolumeL(TInt& aVolume)
1.1372 + {
1.1373 + // [ assert the invariant ]
1.1374 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetVolume));
1.1375 +
1.1376 + //[ precondition that we have a data sink ]
1.1377 + if (!iDataSink)
1.1378 + User::Leave(KErrNotReady);
1.1379 +
1.1380 + //[ precondition iDataSink is an Audio Output ]
1.1381 + if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1.1382 + User::Leave(KErrNotSupported);
1.1383 +
1.1384 + // [ get the volume ]
1.1385 + MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1.1386 + aVolume = audioOutput->SoundDevice().Volume();
1.1387 +
1.1388 + // [ assert precondition that the volume is in range
1.1389 + // 0.. aMaxVolume ]
1.1390 + TInt aMaxVolume = audioOutput->SoundDevice().MaxVolume();
1.1391 + __ASSERT_ALWAYS( (aVolume <= aMaxVolume), Panic(EBadState));
1.1392 + __ASSERT_ALWAYS( (aVolume >= 0), Panic(EBadState));
1.1393 +
1.1394 + // [ assert the invariant ]
1.1395 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetVolume));
1.1396 +
1.1397 + }
1.1398 +
1.1399 +/**
1.1400 +*
1.1401 +* MapdSetVolumeRampL
1.1402 +*
1.1403 +* @param aRampDuration
1.1404 +*
1.1405 +*/
1.1406 +void CMMFAudioController::MapdSetVolumeRampL(const TTimeIntervalMicroSeconds& aRampDuration)
1.1407 + {
1.1408 + // [ assert the invariant ]
1.1409 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetVolumeRamp));
1.1410 +
1.1411 + //[ precondition that we have a data sink ]
1.1412 + if (!iDataSink)
1.1413 + User::Leave(KErrNotReady);
1.1414 +
1.1415 + // [ precondition iDataSink is an Audio Output ]
1.1416 + if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1.1417 + User::Leave(KErrNotSupported);
1.1418 +
1.1419 + //[ set the volume ramp ]
1.1420 + MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1.1421 + audioOutput->SoundDevice().SetVolumeRamp(aRampDuration);
1.1422 +
1.1423 + //[ assert the invariant ]
1.1424 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSetVolumeRamp));
1.1425 +
1.1426 + }
1.1427 +
1.1428 +
1.1429 +/**
1.1430 +*
1.1431 +* MapdSetBalanceL
1.1432 +*
1.1433 +* @param aBalance
1.1434 +*
1.1435 +*/
1.1436 +void CMMFAudioController::MapdSetBalanceL(TInt aBalance)
1.1437 + {
1.1438 + //[ assert the invariant ]
1.1439 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetBalance));
1.1440 +
1.1441 + // [ precondition is that we have a data sink ]
1.1442 + if (!iDataSink)
1.1443 + User::Leave(KErrNotReady);
1.1444 +
1.1445 + // [ precondition is that the data sink is an audio output]
1.1446 + if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1.1447 + User::Leave(KErrNotSupported);
1.1448 +
1.1449 + //[ get the audio output ]
1.1450 + MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1.1451 +
1.1452 + // [ separate out left and right balance ]
1.1453 + TInt left = 0;
1.1454 + TInt right = 0;
1.1455 + CalculateLeftRightBalance( left, right, aBalance );
1.1456 +
1.1457 + //[ set the balance ]
1.1458 + audioOutput->SoundDevice().SetPlayBalanceL(left, right);
1.1459 +
1.1460 + // [assert the post condition that the balance is set correctly]
1.1461 + TInt rightBalance = 0;
1.1462 + TInt leftBalance = 0;
1.1463 + audioOutput->SoundDevice().GetPlayBalanceL(leftBalance, rightBalance);
1.1464 +
1.1465 + //[ assert post condition holds]
1.1466 + TBool postCondition = (( rightBalance == right) && ( leftBalance == left));
1.1467 + __ASSERT_ALWAYS( postCondition, Panic( EPostConditionViolation ) );
1.1468 +
1.1469 + //[ assert the invariant ]
1.1470 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetBalance));
1.1471 + }
1.1472 +
1.1473 +/**
1.1474 +* CalculateLeftRightBalance
1.1475 +* @internalTechnology
1.1476 +* @param aLeft
1.1477 +* @param aRight
1.1478 +* @param aBalance
1.1479 +* Preconditions:
1.1480 +* !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight)
1.1481 +* y = m x + c
1.1482 +* aLeft = m ( aBalance ) + c
1.1483 +* when aBalance = KMMFBalanceMaxLeft aLeft = 100
1.1484 +* when aBalance = KMMFBalanceMaxRight aLeft = 0
1.1485 +* 100 = m( KMMFBalanceMaxLeft ) + c
1.1486 +* 0 = m( KMMFBalanceMaxRight ) + c
1.1487 +* c = -(KMMFBalanceMaxRight) m
1.1488 +* 100 = m(KMMFBalanceMaxLeft ) - m(KMMFBalanceMaxRight)
1.1489 +* m = 100/(KMMFBalanceMaxLeft - KMMFBalanceMaxRight )
1.1490 +* c = -(KMMFBalanceMaxRight) * 100 /(KMMFBalanceMaxLeft - KMMFBalanceMaxRight )
1.1491 +* aLeft = ( aBalance - KMMFBalanceMaxRight ) * 100 /( KMMFBalanceMaxLeft - KMMFBalanceMaxRight )
1.1492 +*/
1.1493 +void CMMFAudioController::CalculateLeftRightBalance( TInt& aLeft, TInt& aRight, TInt aBalance ) const
1.1494 + {
1.1495 + // Check the balance is within limits & modify to min or max values if necessary
1.1496 + if (aBalance < KMMFBalanceMaxLeft)
1.1497 + aBalance = KMMFBalanceMaxLeft;
1.1498 + if (aBalance > KMMFBalanceMaxRight)
1.1499 + aBalance = KMMFBalanceMaxRight;
1.1500 +
1.1501 + //[ Now separate percentage balances out from aBalance ]
1.1502 + aLeft = (100 * (aBalance-KMMFBalanceMaxRight)) / (KMMFBalanceMaxLeft-KMMFBalanceMaxRight);
1.1503 + aRight = 100 - aLeft;
1.1504 +
1.1505 + //[ assert post condition that left and right are within range ]
1.1506 + __ASSERT_ALWAYS( ( (aLeft <= 100) && (aLeft >= 0) ), Panic(EPostConditionViolation));
1.1507 + __ASSERT_ALWAYS( ( (aRight <= 100) && (aRight >= 0) ), Panic(EPostConditionViolation));
1.1508 + }
1.1509 +
1.1510 +
1.1511 +/**
1.1512 +* MapdGetBalanceL
1.1513 +* @param aBalance
1.1514 +*
1.1515 +*/
1.1516 +void CMMFAudioController::MapdGetBalanceL(TInt& aBalance)
1.1517 + {
1.1518 + //[ assert the invariant ]
1.1519 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetBalance));
1.1520 +
1.1521 + //[ precondition that we have a sink]
1.1522 + if (!iDataSink)
1.1523 + User::Leave(KErrNotReady);
1.1524 +
1.1525 + // [ iDataSink is an Audio Output ]
1.1526 + if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1.1527 + User::Leave(KErrNotSupported);
1.1528 +
1.1529 + // [ get the play balance ]
1.1530 + MMMFAudioOutput* audioOutput = STATIC_CAST(MMMFAudioOutput*, iDataSink);
1.1531 + TInt left = 50; // arbitrary values
1.1532 + TInt right = 50;
1.1533 + audioOutput->SoundDevice().GetPlayBalanceL(left, right);
1.1534 + CalculateBalance( aBalance, left, right );
1.1535 +
1.1536 + //[ assert the invariant ]
1.1537 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetBalance));
1.1538 + }
1.1539 +
1.1540 +/**
1.1541 +* CalculateBalance
1.1542 +* @param aBalance
1.1543 +* @param aLeft
1.1544 +* @param aRight
1.1545 +*
1.1546 +* follows a simple straight line transformation
1.1547 +* y = m x + c
1.1548 +* m = (KMMFBalanceMaxLeft-KMMFBalanceMaxRight)/ 100
1.1549 +* c = KMMFBalanceMaxRight
1.1550 +* by substitution
1.1551 +* when aLeft = 0
1.1552 +* KMMFBalanceMaxRight = m * 0 + c
1.1553 +* c = KMMFBalanceMaxRight
1.1554 +* when aLeft = 100
1.1555 +* KMMFBalanceMaxLeft = m * 100 + KMMFBalanceMaxRight
1.1556 +* m = ( KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) /100
1.1557 +*/
1.1558 +void CMMFAudioController::CalculateBalance( TInt& aBalance, TInt aLeft, TInt aRight ) const
1.1559 + {
1.1560 + //[ assert pre conditions ]
1.1561 + __ASSERT_ALWAYS( (( 0 <= aLeft) && ( 100 >= aLeft)), Panic( EBadArgument) );
1.1562 + __ASSERT_ALWAYS( (( 0 <= aRight) && ( 100 >= aRight)), Panic( EBadArgument) );
1.1563 +
1.1564 + if ((aLeft > 0) && (aRight > 0))
1.1565 + {
1.1566 + __ASSERT_ALWAYS( (( aLeft + aRight ) == 100 ), Panic( EBadArgument ));
1.1567 + aBalance = (aLeft * (KMMFBalanceMaxLeft-KMMFBalanceMaxRight))/100 + KMMFBalanceMaxRight;
1.1568 + }
1.1569 + else if ((aLeft == 0) && (aRight == 0))
1.1570 + {
1.1571 + aBalance = 0;
1.1572 + }
1.1573 + else if ((aLeft == 0) && (aRight > 0))
1.1574 + {
1.1575 + aBalance = 100;
1.1576 + }
1.1577 + else if ((aLeft > 0) && (aRight == 0))
1.1578 + {
1.1579 + aBalance = -100;
1.1580 + }
1.1581 +
1.1582 + //[ assert post condition that aBalance is within limits ]
1.1583 + __ASSERT_ALWAYS( !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight), Panic(EBadArgument));
1.1584 +
1.1585 + }
1.1586 +
1.1587 +/**
1.1588 +* MardSetGainL
1.1589 +* @param aGain
1.1590 +*
1.1591 +*/
1.1592 +void CMMFAudioController::MardSetGainL(TInt aGain)
1.1593 + {
1.1594 + // [ assert the invariant ]
1.1595 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetGain));
1.1596 +
1.1597 + //[ precondition we are in the state stopped ]
1.1598 + if(State() != EStopped)
1.1599 + User::Leave(KErrNotReady);
1.1600 +
1.1601 + // [ assert the precondition that we have a data sink ]
1.1602 + if (!iDataSource)
1.1603 + User::Leave(KErrNotSupported);
1.1604 +
1.1605 + //[ assert the precondition that the data sink is an audio input ]
1.1606 + if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1.1607 + User::Leave(KErrNotReady);
1.1608 +
1.1609 + // Set gain of sound device
1.1610 + MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1.1611 + audioInput->SoundDevice().SetGain(aGain);
1.1612 +
1.1613 + //[ assert the invariant ]
1.1614 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGainSet));
1.1615 +
1.1616 + }
1.1617 +
1.1618 +/**
1.1619 +* MardGetMaxGainL
1.1620 +* @param aMaxGain
1.1621 +*
1.1622 +*/
1.1623 +void CMMFAudioController::MardGetMaxGainL(TInt& aMaxGain)
1.1624 + {
1.1625 + // [ assert the invariant ]
1.1626 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxGain));
1.1627 +
1.1628 + // [ assert the precondition that we have a source ]
1.1629 + if (!iDataSource)
1.1630 + User::Leave(KErrNotReady);
1.1631 +
1.1632 + //[ assert the precondition that iDataSink is an Audio Input]
1.1633 + if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1.1634 + User::Leave(KErrNotSupported);
1.1635 +
1.1636 + MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1.1637 + aMaxGain = audioInput->SoundDevice().MaxGain();
1.1638 +
1.1639 + //[ assert the invariant ]
1.1640 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxGain));
1.1641 +
1.1642 + }
1.1643 +
1.1644 +/**
1.1645 +* MardGetGainL
1.1646 +* @param aGain
1.1647 +*
1.1648 +*/
1.1649 +void CMMFAudioController::MardGetGainL(TInt& aGain)
1.1650 + {
1.1651 + //[ assert the invariant ]
1.1652 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetGain));
1.1653 +
1.1654 + // [ assert the precondition that we have a sink ]
1.1655 + if (!iDataSource)
1.1656 + User::Leave(KErrNotReady);
1.1657 +
1.1658 + // [ assert the precondition that we have an audio input sink]
1.1659 + if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1.1660 + User::Leave(KErrNotSupported);
1.1661 +
1.1662 + MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1.1663 + aGain = audioInput->SoundDevice().Gain();
1.1664 +
1.1665 + //[ assert the invariant ]
1.1666 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetGain));
1.1667 + }
1.1668 +
1.1669 +
1.1670 +/**
1.1671 + *
1.1672 + * MardSetBalanceL
1.1673 + * @param aBalance
1.1674 + */
1.1675 +void CMMFAudioController::MardSetBalanceL(TInt aBalance)
1.1676 + {
1.1677 + // [ assert the invaraiant ]
1.1678 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetGain));
1.1679 +
1.1680 + // [ precondition is that we have a data source ]
1.1681 + if (!iDataSource)
1.1682 + {
1.1683 + User::Leave(KErrNotReady);
1.1684 + }
1.1685 +
1.1686 + // [ precondition is that the balance is in range ]
1.1687 + // Make sure aBalance is in the range -100 <-> 100
1.1688 + if (aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight)
1.1689 + User::Leave(KErrArgument);
1.1690 +
1.1691 + // [ precondition is that the data sink is an audio output]
1.1692 + if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1.1693 + User::Leave(KErrNotSupported);
1.1694 +
1.1695 +
1.1696 + //[ get the audio output ]
1.1697 + MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1.1698 +
1.1699 + // [ separate out left and right balance ]
1.1700 + TInt left = 0;
1.1701 + TInt right = 0;
1.1702 + CalculateLeftRightBalance( left, right, aBalance );
1.1703 +
1.1704 + //[ set the balance ]
1.1705 + audioInput->SoundDevice().SetRecordBalanceL(left, right);
1.1706 +
1.1707 + // [assert the post condition that the balance is set correctly]
1.1708 + TInt rightBalance = 0;
1.1709 + TInt leftBalance = 0;
1.1710 + audioInput->SoundDevice().GetRecordBalanceL(leftBalance, rightBalance);
1.1711 +
1.1712 + //[ assert post condition holds]
1.1713 + TBool postCondition = (( rightBalance == right) && ( leftBalance == left));
1.1714 + __ASSERT_ALWAYS( postCondition, Panic( EPostConditionViolation ) );
1.1715 +
1.1716 + //[ assert the invariant ]
1.1717 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGainSet));
1.1718 +
1.1719 + }
1.1720 +
1.1721 +/**
1.1722 +*
1.1723 +* MardGetBalanceL
1.1724 +* @param aBalance
1.1725 +*
1.1726 +*/
1.1727 +void CMMFAudioController::MardGetBalanceL(TInt& aBalance)
1.1728 + {
1.1729 + //[ assert the invariant ]
1.1730 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetBalance));
1.1731 +
1.1732 + // [ precondition is that we have a data source ]
1.1733 + if (!iDataSource)
1.1734 + {
1.1735 + User::Leave(KErrNotReady);
1.1736 + }
1.1737 +
1.1738 + // [ iDataSink is an Audio Output ]
1.1739 + if (iDataSource->DataSourceType() != KUidMmfAudioInput)
1.1740 + User::Leave(KErrNotSupported);
1.1741 +
1.1742 + // [ get the play balance ]
1.1743 + MMMFAudioInput* audioInput = STATIC_CAST(MMMFAudioInput*, iDataSource);
1.1744 + TInt left = 50; // arbitrary values
1.1745 + TInt right = 50;
1.1746 + audioInput->SoundDevice().GetRecordBalanceL(left, right);
1.1747 + CalculateBalance( aBalance, left, right );
1.1748 +
1.1749 + //[ assert the invariant ]
1.1750 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetBalance));
1.1751 +
1.1752 + }
1.1753 +
1.1754 +/**
1.1755 +* MapcSetPlaybackWindowL
1.1756 +* @param aStart
1.1757 +* @param aEnd
1.1758 +*
1.1759 +*/
1.1760 +void CMMFAudioController::MapcSetPlaybackWindowL(const TTimeIntervalMicroSeconds& aStart, const TTimeIntervalMicroSeconds& aEnd)
1.1761 + {
1.1762 + iDataPath->SetPlayWindowL(aStart, aEnd);
1.1763 + }
1.1764 +
1.1765 +/**
1.1766 +* MapcDeletePlaybackWindowL
1.1767 +*/
1.1768 +void CMMFAudioController::MapcDeletePlaybackWindowL()
1.1769 + {
1.1770 + iDataPath->ClearPlayWindowL();
1.1771 + }
1.1772 +
1.1773 +
1.1774 +/**
1.1775 +* MapcSetRepeatsL
1.1776 +* @param aRepeatNumberOfTimes
1.1777 +* @param aTrailingSilence
1.1778 +*
1.1779 +*/
1.1780 +
1.1781 +TInt CMMFAudioController::MapcSetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence)
1.1782 + {
1.1783 + TInt err = KErrNone;
1.1784 + if (!iDataSink)
1.1785 + {
1.1786 + err = KErrNotReady;
1.1787 + }
1.1788 + else if (iDataSink->DataSinkType() != KUidMmfAudioOutput)
1.1789 + {
1.1790 + err = KErrNotSupported;
1.1791 + }
1.1792 + else
1.1793 + {
1.1794 + MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
1.1795 + if(audioOutput->SoundDevice().QueryIgnoresUnderflow())
1.1796 + {
1.1797 + iDataPath->SetRepeats(aRepeatNumberOfTimes,aTrailingSilence);
1.1798 + iDataPath->SetDrmProperties(iDataSource, &iDisableAutoIntent);
1.1799 + }
1.1800 + else
1.1801 + {
1.1802 + err = KErrNotSupported;
1.1803 + }
1.1804 + }
1.1805 + return err;
1.1806 + }
1.1807 +
1.1808 +
1.1809 +/**
1.1810 +* MapcGetLoadingProgressL
1.1811 +*/
1.1812 +void CMMFAudioController::MapcGetLoadingProgressL(TInt& /*aPercentageComplete*/)
1.1813 + {
1.1814 + User::Leave(KErrNotSupported);
1.1815 + }
1.1816 +
1.1817 +
1.1818 +/**
1.1819 +* MarcGetRecordTimeAvailableL
1.1820 +* @param aTime
1.1821 +*
1.1822 +*/
1.1823 +void CMMFAudioController::MarcGetRecordTimeAvailableL(TTimeIntervalMicroSeconds& aTime)
1.1824 + {
1.1825 + //[ assert the invariant ]
1.1826 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetRecordTimeAvailable));
1.1827 +
1.1828 + //[ assert the precondition ( in a friendly way for this api
1.1829 + // that we minimally have a data sink ]
1.1830 + if( !iDataSink )
1.1831 + User::Leave( KErrNotReady );
1.1832 +
1.1833 + // Use the FormatEncode to get the bytes per second and the sink (clip) to get the bytes available
1.1834 + // return the calculated value.
1.1835 + if ((iDataSink->DataSinkType() != KUidMmfFileSink) && (iDataSink->DataSinkType() != KUidMmfDescriptorSink))
1.1836 + User::Leave(KErrNotSupported) ;
1.1837 +
1.1838 + // [ max file size ]
1.1839 + //[ pre condition is that we have a sink ]
1.1840 +
1.1841 + // In order to get the record time available we need to take into consideration
1.1842 + // that there may be a max file size ]
1.1843 + TInt64 bytesFree = STATIC_CAST(CMMFClip*, iDataSink)->BytesFree() ;
1.1844 + TInt64 bytesPerSecond = TInt64(0);
1.1845 + //[ set default time available ]
1.1846 + aTime = TTimeIntervalMicroSeconds( 0 ) ; // just return zero
1.1847 +
1.1848 + if( iSinkFormat )
1.1849 + {
1.1850 + TInt maxFileSize = STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->MaximumClipSize();
1.1851 + //[ if maxFileSize > 0 we need to limit the bytes free to this value - size ]
1.1852 + if( maxFileSize > 0 )
1.1853 + {
1.1854 + // [ strangely the size of data written is a TInt ]
1.1855 + TInt fileSize = STATIC_CAST(CMMFClip*, iDataSink)->Size();
1.1856 + bytesFree = maxFileSize - fileSize;
1.1857 + // [ note it can occur that the fileSize id greater than the MaxFileSize
1.1858 + // due to someone setting the max file size on an existing file ]
1.1859 + if( bytesFree < 0 ) bytesFree = 0;
1.1860 + __ASSERT_DEBUG( ( bytesFree <= maxFileSize), Panic( ENoMemoryToRecord) );
1.1861 + }
1.1862 + bytesPerSecond = STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->BytesPerSecond() ;
1.1863 + }
1.1864 +
1.1865 + //[ now lets perform the calculation of time available ]
1.1866 + if ( bytesPerSecond != TInt64(0) )
1.1867 + {
1.1868 + aTime = TTimeIntervalMicroSeconds( bytesFree * KOneSecondInMicroSeconds / bytesPerSecond ) ;
1.1869 + }
1.1870 +
1.1871 + //[ assert the invariant ]
1.1872 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetRecordTimeAvailable));
1.1873 + }
1.1874 +
1.1875 +/**
1.1876 +* MarcSetMaxDurationL
1.1877 +* @param aMaxDuration
1.1878 +*/
1.1879 +void CMMFAudioController::MarcSetMaxDurationL(const TTimeIntervalMicroSeconds& )
1.1880 + {
1.1881 + //[ this method is deprecated and no longer supported ]
1.1882 + User::Leave(KErrNotSupported);
1.1883 + }
1.1884 +
1.1885 +/**
1.1886 +* MarcSetMaxFileSizeL
1.1887 +* @param aFileSize
1.1888 +* @precondition
1.1889 +* The argument aFileSize must be greater than -1
1.1890 +* zero is used as a sentinel value which means that the file
1.1891 +* can grow without limit
1.1892 +*/
1.1893 +void CMMFAudioController::MarcSetMaxFileSizeL(TInt aFileSize )
1.1894 + {
1.1895 + //[ assert the invariant ]
1.1896 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetMaxFileSize));
1.1897 +
1.1898 + //[ assert the state is not playing since this opens open
1.1899 + // nefarious posibilities
1.1900 + if(State() == EPlaying )
1.1901 + User::Leave( KErrNotReady );
1.1902 +
1.1903 + //[ assert we have a sink format ]
1.1904 + if( !iSinkFormat )
1.1905 + User::Leave( KErrNotReady );
1.1906 +
1.1907 + //[ assert file size > -2, as a basic sanity filter
1.1908 + // 0 is the sentinel value which allows a file to grow
1.1909 + // as needed.]
1.1910 + // [We use -1 to reset the value set earlier.]
1.1911 + if( aFileSize < -1 )
1.1912 + {
1.1913 + User::Leave( KErrArgument );
1.1914 + }
1.1915 +
1.1916 + //[ pre condition is that we have a sink ]
1.1917 + STATIC_CAST(CMMFFormatEncode*, iSinkFormat)->SetMaximumClipSizeL( aFileSize );
1.1918 +
1.1919 + // [ assert the post condition ]
1.1920 + // [since we have no means of querying the value
1.1921 + // we have to assume all went well for now or we left]
1.1922 +
1.1923 + //[ assert the invariant ]
1.1924 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetMaxFileSize));
1.1925 + }
1.1926 +
1.1927 +/**
1.1928 +* MarcCropL
1.1929 +* @param aToEnd
1.1930 +*/
1.1931 +void CMMFAudioController::MarcCropL(TBool aToEnd)
1.1932 + {
1.1933 + //[ assert the invariant ]
1.1934 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToCrop));
1.1935 +
1.1936 + //[ precondition there is a sink format]
1.1937 + if (!iSinkFormat)
1.1938 + User::Leave(KErrNotSupported);
1.1939 +
1.1940 + iSinkFormat->CropL( PositionL(), aToEnd );
1.1941 +
1.1942 + //[ assert the invariant ]
1.1943 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterCrop));
1.1944 + }
1.1945 +
1.1946 +/**
1.1947 +* MarcAddMetaDataEntryL
1.1948 +* @param aNewEntry
1.1949 +*/
1.1950 +void CMMFAudioController::MarcAddMetaDataEntryL(const CMMFMetaDataEntry& aNewEntry )
1.1951 + {
1.1952 + //[ assert the invariant ]
1.1953 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToAddMetaDataEntry));
1.1954 +
1.1955 + //[ precondition the format exists ]
1.1956 + if( !iSinkFormat )
1.1957 + User::Leave(KErrNotSupported);
1.1958 +
1.1959 + //[ Add the meta data entry ]
1.1960 + iSinkFormat->AddMetaDataEntryL( aNewEntry );
1.1961 +
1.1962 + //[ assert the invariant ]
1.1963 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterAddMetaDataEntry));
1.1964 +
1.1965 + }
1.1966 +
1.1967 +/**
1.1968 +* MarcRemoveMetaDataEntryL
1.1969 +* @param aIndex
1.1970 +*/
1.1971 +void CMMFAudioController::MarcRemoveMetaDataEntryL(TInt aIndex)
1.1972 + {
1.1973 + //[ assert the invariant ]
1.1974 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToRemoveMetaDataEntry));
1.1975 +
1.1976 + //[ precondition that we are in the primed state ]
1.1977 + if( State() != EPrimed)
1.1978 + User::Leave(KErrNotReady);
1.1979 +
1.1980 + //[ precondition the format exists ]
1.1981 + if( !iSinkFormat )
1.1982 + User::Leave(KErrNotSupported);
1.1983 +
1.1984 + //[ remove the meta data entry ]
1.1985 + iSinkFormat->RemoveMetaDataEntry( aIndex );
1.1986 +
1.1987 + //[ assert the invariant ]
1.1988 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterRemoveMetaDataEntry));
1.1989 +
1.1990 + }
1.1991 +
1.1992 +/**
1.1993 +* MarcReplaceMetaDataEntryL
1.1994 +* @param aIndex
1.1995 +* @param aNewEntry
1.1996 +*/
1.1997 +void CMMFAudioController::MarcReplaceMetaDataEntryL(TInt aIndex, const CMMFMetaDataEntry& aNewEntry)
1.1998 + {
1.1999 + //[ assert the invariant ]
1.2000 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToReplaceMetaDataEntry));
1.2001 +
1.2002 + //[ precondition that we are in the primed state ]
1.2003 + if( State() != EPrimed)
1.2004 + User::Leave(KErrNotReady);
1.2005 +
1.2006 + //[ precondition the format exists ]
1.2007 + if( !iSinkFormat )
1.2008 + User::Leave(KErrNotSupported);
1.2009 +
1.2010 + //[ replace meta data entry ]
1.2011 + iSinkFormat->ReplaceMetaDataEntryL( aIndex, aNewEntry );
1.2012 +
1.2013 + //[ assert the invariant ]
1.2014 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterReplaceMetaDataEntry));
1.2015 +
1.2016 + }
1.2017 +
1.2018 +/**
1.2019 +* MacSetSourceSampleRateL
1.2020 +* @param aSampleRate
1.2021 +*/
1.2022 +void CMMFAudioController::MacSetSourceSampleRateL(TUint aSampleRate)
1.2023 + {
1.2024 + // [ assert the invariant ]
1.2025 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceSampleRate));
1.2026 +
1.2027 + // [ assert the precondition we are stopped ]
1.2028 + if( State() != EStopped )
1.2029 + User::Leave(KErrNotReady);
1.2030 +
1.2031 +
1.2032 + if (iSourceFormat)
1.2033 + {//only applicable to formats
1.2034 + // don't throw an error if the clip already exists with a different sample rate
1.2035 + TInt error = iSourceFormat->SetSampleRate(aSampleRate);
1.2036 + if (error != KErrNone && error != KErrAlreadyExists)
1.2037 + User::Leave(error);
1.2038 + }
1.2039 + else
1.2040 + {//during recording, sample rate cannot be set directly on the datasource. It is set via NegotiateL
1.2041 + User::Leave(KErrNotSupported);
1.2042 + }
1.2043 +
1.2044 + // [assert the post condition ]
1.2045 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceSampleRate));
1.2046 +
1.2047 + }
1.2048 +
1.2049 +/**
1.2050 +* MacSetSourceNumChannelsL
1.2051 +* @param aNumChannels
1.2052 +*/
1.2053 +void CMMFAudioController::MacSetSourceNumChannelsL(TUint aNumChannels)
1.2054 + {
1.2055 + // [ assert the invariant ]
1.2056 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceNumChannels));
1.2057 +
1.2058 + // [assert the precondition that we are stopped ]
1.2059 + if( State() != EStopped )
1.2060 + User::Leave(KErrNotReady);
1.2061 +
1.2062 + if (iSourceFormat)
1.2063 + {//only applicable to formats
1.2064 + // don't throw an error if the clip already exists with a different number of channels
1.2065 + TInt error = iSourceFormat->SetNumChannels(aNumChannels);
1.2066 + if (error != KErrNone && error != KErrAlreadyExists)
1.2067 + User::Leave(error);
1.2068 + }
1.2069 + else
1.2070 + {//during recording, channels cannot be set directly on the datasource. It is set via NegotiateL
1.2071 + User::Leave(KErrNotSupported);
1.2072 + }
1.2073 +
1.2074 + // [ assert the invariant ]
1.2075 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceNumChannels));
1.2076 +
1.2077 + }
1.2078 +
1.2079 +/**
1.2080 +* MacSetSourceFormatL
1.2081 +* @param aFormatUid
1.2082 +*
1.2083 +*/
1.2084 +void CMMFAudioController::MacSetSourceFormatL(TUid aFormatUid)
1.2085 + {
1.2086 + //[ assert the invaraint ]
1.2087 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSourceFormat));
1.2088 +
1.2089 + // [ precondition that the controller is stopped ]
1.2090 + if( State() != EStopped )
1.2091 + User::Leave( KErrNotReady );
1.2092 +
1.2093 + //[ precondition that the data source exists]
1.2094 + if (!iDataSource)
1.2095 + User::Leave(KErrNotReady);
1.2096 +
1.2097 + //[ precondition that we need a format ]
1.2098 + if( !SourceFormatRequired( *iDataSource ) )
1.2099 + User::Leave(KErrNotSupported); //cant set source format if source isn't a clip
1.2100 +
1.2101 + //[ if the format exists and the uid of the requested
1.2102 + // format is the same as the existing format then simply
1.2103 + // return otherwise create a new format ]
1.2104 + if( !((iSourceFormat) && ( iSourceFormat->ImplementationUid() == aFormatUid)))
1.2105 + {
1.2106 + // [ delete the old format regardless ]
1.2107 + delete iSourceFormat;
1.2108 + iSourceFormat = NULL;
1.2109 + iSourceFormat = CMMFFormatDecode::NewL(aFormatUid, iDataSource);
1.2110 + }
1.2111 +
1.2112 + //[ assert the invariant ]
1.2113 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceFormat));
1.2114 +
1.2115 + //[ assert the post condition that a source format has been constructed ]
1.2116 + __ASSERT_ALWAYS( (iSourceFormat != NULL), Panic( EPostConditionViolation ));
1.2117 + }
1.2118 +
1.2119 +/**
1.2120 +* MacSetSinkSampleRateL
1.2121 +* @param aSampleRate
1.2122 +*/
1.2123 +void CMMFAudioController::MacSetSinkSampleRateL(TUint aSampleRate)
1.2124 + {
1.2125 + //[ assert the invariant ]
1.2126 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkSampleRate));
1.2127 +
1.2128 + // [ assert the precondition that we are stopped ]
1.2129 + if (State() != EStopped )
1.2130 + User::Leave(KErrNotReady);
1.2131 +
1.2132 + if (iSinkFormat)
1.2133 + {//only applicable to formats
1.2134 + // don't throw an error if the clip already exists with a different sample rate
1.2135 + TInt error = iSinkFormat->SetSampleRate(aSampleRate);
1.2136 + if (error != KErrNone && error != KErrAlreadyExists)
1.2137 + User::Leave(error);
1.2138 + }
1.2139 + else
1.2140 + {//during playing, sample rate cannot be set directly on the datasink. It is set via NegotiateL
1.2141 + User::Leave(KErrNotSupported);
1.2142 + }
1.2143 +
1.2144 + //[ assert the invariant ]
1.2145 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkSampleRate));
1.2146 + }
1.2147 +
1.2148 +/**
1.2149 +* MacSetSinkNumChannelsL
1.2150 +* @param aNumChannels
1.2151 +*
1.2152 +*/
1.2153 +void CMMFAudioController::MacSetSinkNumChannelsL(TUint aNumChannels)
1.2154 + {
1.2155 + //[ assert the invariant ]
1.2156 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkNumChannels));
1.2157 +
1.2158 + // [ assert the precondition that we are stopped ]
1.2159 + if (State() != EStopped )
1.2160 + User::Leave(KErrNotReady);
1.2161 +
1.2162 + if (iSinkFormat)
1.2163 + {//only applicable to formats
1.2164 + // don't throw an error if the clip already exists with a different number of channels
1.2165 + TInt error = iSinkFormat->SetNumChannels(aNumChannels);
1.2166 + if (error != KErrNone && error != KErrAlreadyExists)
1.2167 + User::Leave(error);
1.2168 + }
1.2169 + else
1.2170 + {//during playing, channels cannot be set directly on the datasink. It is set via NegotiateL
1.2171 + User::Leave(KErrNotSupported);
1.2172 + }
1.2173 +
1.2174 + // [assert the invariant ]
1.2175 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkNumChannels));
1.2176 +
1.2177 + }
1.2178 +
1.2179 +/**
1.2180 +* MacSetSinkFormatL
1.2181 +* @param aFormatUid
1.2182 +*
1.2183 +*/
1.2184 +void CMMFAudioController::MacSetSinkFormatL(TUid aFormatUid)
1.2185 + {
1.2186 + //[ assert the invariant ]
1.2187 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkFormat));
1.2188 +
1.2189 + // [ precondition that the controller is stopped ]
1.2190 + if( State() != EStopped )
1.2191 + User::Leave( KErrNotReady );
1.2192 +
1.2193 + //[ precondition that the data sink exists]
1.2194 + if (!iDataSink)
1.2195 + User::Leave(KErrNotReady);
1.2196 +
1.2197 + //[ precondition that we need a format ]
1.2198 + if (!SinkFormatRequired( *iDataSink))
1.2199 + User::Leave(KErrNotSupported);
1.2200 +
1.2201 + //[ if the format exists and the uid of the requested
1.2202 + // format is the same as the existing format then simply
1.2203 + // return ]
1.2204 + if( !((iSinkFormat) && ( iSinkFormat->ImplementationUid() == aFormatUid)))
1.2205 + {
1.2206 + // [ delete the old format regardless ]
1.2207 + delete iSinkFormat;
1.2208 + iSinkFormat = NULL;
1.2209 + iSinkFormat = CMMFFormatEncode::NewL(aFormatUid, iDataSink);
1.2210 + }
1.2211 +
1.2212 + //[ assert the invariant ]
1.2213 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkFormat));
1.2214 +
1.2215 + //[ assert the post condition that a sink format has been constructed ]
1.2216 + __ASSERT_ALWAYS( (iSinkFormat != NULL), Panic( EPostConditionViolation ));
1.2217 + }
1.2218 +
1.2219 +
1.2220 +/**
1.2221 +* MacSetCodecL
1.2222 +* @param aSourceDataType
1.2223 +* @param aSinkDataType
1.2224 +*
1.2225 +*/
1.2226 +void CMMFAudioController::MacSetCodecL(TFourCC aSourceDataType, TFourCC aSinkDataType)
1.2227 + {
1.2228 + //[ assert the invariant ]
1.2229 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetCodec));
1.2230 +
1.2231 + //[ assert the precondition ]
1.2232 + if(State() != EStopped)
1.2233 + User::Leave(KErrNotReady);
1.2234 +
1.2235 + //pre condition that we have a source format or sink format
1.2236 + if (!iSourceFormat && !iSinkFormat)
1.2237 + {
1.2238 + User::Leave(KErrNotSupported);
1.2239 + }
1.2240 + //don't set codec directly -just set source & sink fourCC codes
1.2241 + //[ ]
1.2242 + TInt error(KErrNone);
1.2243 + if ((iSinkFormat)&&(aSinkDataType != KMMFFourCCCodeNULL))
1.2244 + {
1.2245 + error = iSinkFormat->SetSinkDataTypeCode(aSinkDataType,iMediaId);
1.2246 + }
1.2247 + if ((iSourceFormat)&&(!error)&&(aSourceDataType != KMMFFourCCCodeNULL))
1.2248 + {
1.2249 + error = iSourceFormat->SetSourceDataTypeCode(aSourceDataType,iMediaId);
1.2250 + }
1.2251 +
1.2252 + //[ leave if we are not ready or there was an error ]
1.2253 + User::LeaveIfError(error);
1.2254 +
1.2255 + //[ assert the invariant ]
1.2256 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterSetCodec));
1.2257 + }
1.2258 +
1.2259 +/**
1.2260 +* MacSetSourceBitRateL
1.2261 +* @param "TUint"
1.2262 +* Sets the source bit rate
1.2263 +*
1.2264 +*/
1.2265 +void CMMFAudioController::MacSetSourceBitRateL(TUint aBitRate)
1.2266 + {
1.2267 + //[ assert the invariant ]
1.2268 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToSetSourceBitRate));
1.2269 +
1.2270 + //[ assert the precondition ]
1.2271 + if(State() != EStopped)
1.2272 + User::Leave(KErrNotReady);
1.2273 +
1.2274 + //[ pre condition that we have a source format]
1.2275 + if (!iSourceFormat)
1.2276 + User::Leave(KErrNotSupported);
1.2277 +
1.2278 + //only applicable to formats
1.2279 + User::LeaveIfError(iSourceFormat->SetBitRate(aBitRate));
1.2280 +
1.2281 + //[ assert the set bit rate is the bit rate ]
1.2282 + __ASSERT_ALWAYS( (aBitRate == iSourceFormat->BitRate()), Panic( EPostConditionViolation ));
1.2283 +
1.2284 + //[ assert the invariant ]
1.2285 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSourceBitRate));
1.2286 + }
1.2287 +
1.2288 +
1.2289 +/**
1.2290 +*
1.2291 +* MacSetSourceDataTypeL
1.2292 +* @param "TFourCC"
1.2293 +*
1.2294 +*/
1.2295 +void CMMFAudioController::MacSetSourceDataTypeL(TFourCC aDataType)
1.2296 + {
1.2297 + //pre condition we have a source format
1.2298 + if (!iSourceFormat)
1.2299 + {
1.2300 + User::Leave(KErrNotSupported);
1.2301 + }
1.2302 +
1.2303 + MacSetCodecL(aDataType, KMMFFourCCCodeNULL);
1.2304 + }
1.2305 +
1.2306 +/**
1.2307 +*
1.2308 +* MacSetSinkBitRateL
1.2309 +* @param "TUint"
1.2310 +*
1.2311 +*/
1.2312 +void CMMFAudioController::MacSetSinkBitRateL(TUint aRate)
1.2313 + {
1.2314 + //[ assert the invariant ]
1.2315 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToSetSinkBitRate));
1.2316 +
1.2317 + // [ assert we are stopped ]
1.2318 + if( State() != EStopped)
1.2319 + User::Leave( KErrNotReady );
1.2320 +
1.2321 + //[ pre condition we have a sink format ]
1.2322 + if (!iSinkFormat)
1.2323 + User::Leave(KErrNotSupported);
1.2324 +
1.2325 + //only applicable to formats
1.2326 + User::LeaveIfError(iSinkFormat->SetBitRate(aRate));
1.2327 +
1.2328 + //[ assert the set bit rate is the bit rate ]
1.2329 + __ASSERT_ALWAYS( (aRate == iSinkFormat->BitRate()), Panic( ESetRateIsNotSameAsBitRate));
1.2330 +
1.2331 + //[ assert the invariant ]
1.2332 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterSetSinkBitRate));
1.2333 + }
1.2334 +
1.2335 +/**
1.2336 +*
1.2337 +* MacSetSinkDataTypeL
1.2338 +* @param "TFourCC"
1.2339 +*
1.2340 +*/
1.2341 +void CMMFAudioController::MacSetSinkDataTypeL(TFourCC aDataType)
1.2342 + {
1.2343 + //precondition is that we have a sink format
1.2344 + if (!iSinkFormat)
1.2345 + {
1.2346 + User::Leave(KErrNotSupported);
1.2347 + }
1.2348 +
1.2349 + MacSetCodecL(KMMFFourCCCodeNULL, aDataType);
1.2350 + }
1.2351 +
1.2352 +/**
1.2353 +*
1.2354 +* MacGetSourceSampleRateL
1.2355 +* @param "TUint"
1.2356 +*
1.2357 +*/
1.2358 +void CMMFAudioController::MacGetSourceSampleRateL(TUint& aRate)
1.2359 + {
1.2360 + //[ assert the invariant ]
1.2361 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceSampleRate));
1.2362 +
1.2363 + //precondition is that we have a source format
1.2364 + if (!iSourceFormat)
1.2365 + {
1.2366 + User::Leave(KErrNotSupported);
1.2367 + }
1.2368 +
1.2369 + aRate = iSourceFormat->SampleRate();
1.2370 +
1.2371 + //[ assert the invariant ]
1.2372 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceSampleRate));
1.2373 + }
1.2374 +
1.2375 +/**
1.2376 +*
1.2377 +* MacGetSourceBitRateL
1.2378 +* @param "TUint"
1.2379 +*
1.2380 +*/
1.2381 +void CMMFAudioController::MacGetSourceBitRateL(TUint& aRate)
1.2382 + {
1.2383 + //[ assert the invariant ]
1.2384 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceBitRate));
1.2385 +
1.2386 + // Can only query formats for bit rate - devsound doesn't do bit rates.
1.2387 + if (!iSourceFormat)
1.2388 + User::Leave(KErrNotSupported);
1.2389 +
1.2390 + aRate = iSourceFormat->BitRate();
1.2391 +
1.2392 + //[ assert the invariant ]
1.2393 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceBitRate));
1.2394 +
1.2395 + }
1.2396 +
1.2397 +/**
1.2398 +*
1.2399 +* MacGetSourceNumChannelsL
1.2400 +* @param "TUint&"
1.2401 +*
1.2402 +*/
1.2403 +void CMMFAudioController::MacGetSourceNumChannelsL(TUint& aNumChannels)
1.2404 + {
1.2405 + //[ assert the invariant ]
1.2406 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceNumChannels));
1.2407 +
1.2408 + //precondition is that we have a source format
1.2409 + if (!iSourceFormat)
1.2410 + {
1.2411 + User::Leave(KErrNotSupported);
1.2412 + }
1.2413 +
1.2414 + aNumChannels = iSourceFormat->NumChannels();
1.2415 +
1.2416 + //[ assert the invariant ]
1.2417 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceNumChannels));
1.2418 +
1.2419 + }
1.2420 +
1.2421 +/**
1.2422 +*
1.2423 +* MacGetSourceFormatL
1.2424 +* @param "TUid"
1.2425 +*/
1.2426 +void CMMFAudioController::MacGetSourceFormatL(TUid& aFormat)
1.2427 + {
1.2428 + //[ assert the invariant ]
1.2429 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateToGetSourceFormat));
1.2430 +
1.2431 + //[ precondition we have a format ]
1.2432 + if (!iSourceFormat)
1.2433 + User::Leave(KErrNotSupported);
1.2434 +
1.2435 + // [ get the source format uid ]
1.2436 + aFormat = iSourceFormat->ImplementationUid();
1.2437 +
1.2438 + //[ assert the invariant ]
1.2439 + __ASSERT_ALWAYS( Invariant(), Panic( EBadStateAfterGetSourceFormat));
1.2440 +
1.2441 + }
1.2442 +
1.2443 +/**
1.2444 +*
1.2445 +* MacGetSourceDataTypeL
1.2446 +* @param "TFourCC&"
1.2447 +*
1.2448 +*/
1.2449 +void CMMFAudioController::MacGetSourceDataTypeL(TFourCC& aDataType)
1.2450 + {
1.2451 + //precondition is that we have a source format
1.2452 + if (!iSourceFormat)
1.2453 + {
1.2454 + User::Leave(KErrNotSupported);
1.2455 + }
1.2456 +
1.2457 + aDataType = iSourceFormat->SourceDataTypeCode(TMediaId(KUidMediaTypeAudio));
1.2458 + }
1.2459 +
1.2460 +/**
1.2461 +*
1.2462 +* MacGetSinkSampleRateL
1.2463 +* @param "TUint&"
1.2464 +*
1.2465 +*/
1.2466 +
1.2467 +void CMMFAudioController::MacGetSinkSampleRateL(TUint& aRate)
1.2468 + {
1.2469 + //precondition is that we have a sink format
1.2470 + if (!iSinkFormat)
1.2471 + {
1.2472 + User::Leave(KErrNotSupported);
1.2473 + }
1.2474 +
1.2475 + aRate = iSinkFormat->SampleRate();
1.2476 + }
1.2477 +
1.2478 +/**
1.2479 +*
1.2480 +* MacGetSinkBitRateL
1.2481 +* @param "TUint&"
1.2482 +*
1.2483 +*/
1.2484 +void CMMFAudioController::MacGetSinkBitRateL(TUint& aRate)
1.2485 + {
1.2486 + if (iSinkFormat)
1.2487 + aRate = iSinkFormat->BitRate();
1.2488 + else
1.2489 + User::Leave(KErrNotSupported);
1.2490 + }
1.2491 +
1.2492 +/**
1.2493 +*
1.2494 +* MacGetSinkNumChannelsL
1.2495 +* @param "TUint&"
1.2496 +*
1.2497 +*/
1.2498 +void CMMFAudioController::MacGetSinkNumChannelsL(TUint& aNumChannels)
1.2499 + {
1.2500 + //precondition is that we have a sink format
1.2501 + if (!iSinkFormat)
1.2502 + {
1.2503 + User::Leave(KErrNotSupported);
1.2504 + }
1.2505 +
1.2506 + aNumChannels = iSinkFormat->NumChannels();
1.2507 + }
1.2508 +
1.2509 +/**
1.2510 +*
1.2511 +* MacGetSinkFormatL
1.2512 +* @param "TUid&"
1.2513 +*
1.2514 +*/
1.2515 +void CMMFAudioController::MacGetSinkFormatL(TUid& aFormat)
1.2516 + {
1.2517 + if (iSinkFormat)
1.2518 + aFormat = iSinkFormat->ImplementationUid();
1.2519 + else
1.2520 + User::Leave(KErrNotSupported);
1.2521 + }
1.2522 +
1.2523 +/**
1.2524 +*
1.2525 +* MacGetSinkDataTypeL
1.2526 +* @param "TFourCC&"
1.2527 +*
1.2528 +*/
1.2529 +void CMMFAudioController::MacGetSinkDataTypeL(TFourCC& aDataType)
1.2530 + {
1.2531 + //precondition is that we have a sink format
1.2532 + if (!iSinkFormat)
1.2533 + {
1.2534 + User::Leave(KErrNotSupported);
1.2535 + }
1.2536 +
1.2537 + aDataType = iSinkFormat->SinkDataTypeCode(TMediaId(KUidMediaTypeAudio));
1.2538 + }
1.2539 +
1.2540 +/**
1.2541 +*
1.2542 +* MacGetSupportedSourceSampleRatesL
1.2543 +* @param "RArray<TUint>&"
1.2544 +*
1.2545 +*/
1.2546 +void CMMFAudioController::MacGetSupportedSourceSampleRatesL(RArray<TUint>& aSupportedRates)
1.2547 + {
1.2548 + //precondition is that we have a source format
1.2549 + if (!iSourceFormat)
1.2550 + {
1.2551 + User::Leave(KErrNotSupported);
1.2552 + }
1.2553 +
1.2554 + aSupportedRates.Reset();
1.2555 + iSourceFormat->GetSupportedSampleRatesL(aSupportedRates);
1.2556 + }
1.2557 +
1.2558 +/**
1.2559 +*
1.2560 +* MacGetSupportedSourceBitRatesL
1.2561 +* @param "RArray<TUint>&"
1.2562 +*
1.2563 +*/
1.2564 +void CMMFAudioController::MacGetSupportedSourceBitRatesL(RArray<TUint>& aSupportedRates)
1.2565 + {
1.2566 + aSupportedRates.Reset();
1.2567 + if (iSourceFormat)
1.2568 + iSourceFormat->GetSupportedBitRatesL(aSupportedRates);
1.2569 + else
1.2570 + User::Leave(KErrNotSupported);
1.2571 + }
1.2572 +
1.2573 +/***
1.2574 +*
1.2575 +* MacGetSupportedSourceNumChannelsL
1.2576 +* @param "RArray<TUint>&"
1.2577 +*
1.2578 +*/
1.2579 +void CMMFAudioController::MacGetSupportedSourceNumChannelsL(RArray<TUint>& aSupportedChannels)
1.2580 + {
1.2581 + //precondition is that we have a source format
1.2582 + if (!iSourceFormat)
1.2583 + {
1.2584 + User::Leave(KErrNotSupported);
1.2585 + }
1.2586 +
1.2587 + aSupportedChannels.Reset();
1.2588 + iSourceFormat->GetSupportedNumChannelsL(aSupportedChannels);
1.2589 + }
1.2590 +
1.2591 +/***
1.2592 +*
1.2593 +* MacGetSupportedSourceDataTypesL
1.2594 +* @param "RArray<TFourCC>&"
1.2595 +*
1.2596 +*/
1.2597 +void CMMFAudioController::MacGetSupportedSourceDataTypesL(RArray<TFourCC>& aSupportedDataTypes)
1.2598 + {
1.2599 + //precondition is that we have a source format
1.2600 + if (!iSourceFormat)
1.2601 + {
1.2602 + User::Leave(KErrNotSupported);
1.2603 + }
1.2604 +
1.2605 + aSupportedDataTypes.Reset();
1.2606 + iSourceFormat->GetSupportedDataTypesL(TMediaId(KUidMediaTypeAudio), aSupportedDataTypes);
1.2607 + }
1.2608 +
1.2609 +/***
1.2610 +*
1.2611 +* MacGetSupportedSinkSampleRatesL
1.2612 +* @param "RArray<TUint>& "
1.2613 +*
1.2614 +*/
1.2615 +void CMMFAudioController::MacGetSupportedSinkSampleRatesL(RArray<TUint>& aSupportedRates)
1.2616 + {
1.2617 + //precondition is that we have a sink format
1.2618 + if (!iSinkFormat)
1.2619 + {
1.2620 + User::Leave(KErrNotSupported);
1.2621 + }
1.2622 +
1.2623 + aSupportedRates.Reset();
1.2624 + iSinkFormat->GetSupportedSampleRatesL(aSupportedRates);
1.2625 + }
1.2626 +
1.2627 +/***
1.2628 +*
1.2629 +* MacGetSupportedSinkBitRatesL
1.2630 +* @param RArray<TUint>&
1.2631 +*
1.2632 +*/
1.2633 +void CMMFAudioController::MacGetSupportedSinkBitRatesL(RArray<TUint>& aSupportedRates)
1.2634 + {
1.2635 + if (iSinkFormat)
1.2636 + iSinkFormat->GetSupportedBitRatesL(aSupportedRates);
1.2637 + else
1.2638 + User::Leave(KErrNotSupported);
1.2639 + }
1.2640 +
1.2641 +/***
1.2642 +*
1.2643 +* MacGetSupportedSinkNumChannelsL
1.2644 +* @param RArray<TUint>&
1.2645 +*
1.2646 +*/
1.2647 +void CMMFAudioController::MacGetSupportedSinkNumChannelsL(RArray<TUint>& aSupportedChannels)
1.2648 + {
1.2649 + //precondition is that we have a sink format
1.2650 + if (!iSinkFormat)
1.2651 + {
1.2652 + User::Leave(KErrNotSupported);
1.2653 + }
1.2654 +
1.2655 + aSupportedChannels.Reset();
1.2656 + iSinkFormat->GetSupportedNumChannelsL(aSupportedChannels);
1.2657 + }
1.2658 +
1.2659 +/***
1.2660 +*
1.2661 +* MacGetSupportedSinkDataTypesL
1.2662 +* @param "RArray<TFourCC>&"
1.2663 +*/
1.2664 +void CMMFAudioController::MacGetSupportedSinkDataTypesL(RArray<TFourCC>& aSupportedDataTypes)
1.2665 + {
1.2666 + //precondition is that we have a sink format
1.2667 + if (!iSinkFormat)
1.2668 + {
1.2669 + User::Leave(KErrNotSupported);
1.2670 + }
1.2671 +
1.2672 + aSupportedDataTypes.Reset();
1.2673 + iSinkFormat->GetSupportedDataTypesL(TMediaId(KUidMediaTypeAudio), aSupportedDataTypes);
1.2674 + }
1.2675 +
1.2676 +/**
1.2677 +*
1.2678 +* ConvertFromDevSoundCapsToSampleRatesL
1.2679 +* @param "const TMMFCapabilities& "
1.2680 +* @param "RArray<TUint>&"
1.2681 +*
1.2682 +*/
1.2683 +void CMMFAudioController::ConvertFromDevSoundCapsToSampleRatesL(const TMMFCapabilities& aDevSoundCaps, RArray<TUint>& aSampleRates)
1.2684 + {
1.2685 + if (aDevSoundCaps.iRate & EMMFSampleRate8000Hz)
1.2686 + User::LeaveIfError(aSampleRates.Append(KSampleRate8000Hz));
1.2687 + if (aDevSoundCaps.iRate & EMMFSampleRate11025Hz)
1.2688 + User::LeaveIfError(aSampleRates.Append(KSampleRate11025Hz));
1.2689 + if (aDevSoundCaps.iRate & EMMFSampleRate12000Hz)
1.2690 + User::LeaveIfError(aSampleRates.Append(KSampleRate12000Hz));
1.2691 + if (aDevSoundCaps.iRate & EMMFSampleRate16000Hz)
1.2692 + User::LeaveIfError(aSampleRates.Append(KSampleRate16000Hz));
1.2693 + if (aDevSoundCaps.iRate & EMMFSampleRate22050Hz)
1.2694 + User::LeaveIfError(aSampleRates.Append(KSampleRate22050Hz));
1.2695 + if (aDevSoundCaps.iRate & EMMFSampleRate24000Hz)
1.2696 + User::LeaveIfError(aSampleRates.Append(KSampleRate24000Hz));
1.2697 + if (aDevSoundCaps.iRate & EMMFSampleRate32000Hz)
1.2698 + User::LeaveIfError(aSampleRates.Append(KSampleRate32000Hz));
1.2699 + if (aDevSoundCaps.iRate & EMMFSampleRate44100Hz)
1.2700 + User::LeaveIfError(aSampleRates.Append(KSampleRate44100Hz));
1.2701 + if (aDevSoundCaps.iRate & EMMFSampleRate48000Hz)
1.2702 + User::LeaveIfError(aSampleRates.Append(KSampleRate48000Hz));
1.2703 + if (aDevSoundCaps.iRate & EMMFSampleRate64000Hz)
1.2704 + User::LeaveIfError(aSampleRates.Append(KSampleRate64000Hz));
1.2705 + if (aDevSoundCaps.iRate & EMMFSampleRate88200Hz)
1.2706 + User::LeaveIfError(aSampleRates.Append(KSampleRate88200Hz));
1.2707 + if (aDevSoundCaps.iRate & EMMFSampleRate96000Hz)
1.2708 + User::LeaveIfError(aSampleRates.Append(KSampleRate96000Hz));
1.2709 + }
1.2710 +
1.2711 +/**
1.2712 +*
1.2713 +* ConvertFromDevSoundCapsToNumChannelsL
1.2714 +* @param "const TMMFCapabilities&"
1.2715 +* @param "RArray<TUint>&"
1.2716 +*
1.2717 +*/
1.2718 +void CMMFAudioController::ConvertFromDevSoundCapsToNumChannelsL(const TMMFCapabilities& aDevSoundCaps, RArray<TUint>& aNumChannels)
1.2719 + {
1.2720 + if (aDevSoundCaps.iChannels & EMMFMono)
1.2721 + User::LeaveIfError(aNumChannels.Append(KNumChannelsMono));
1.2722 + if (aDevSoundCaps.iChannels & EMMFStereo)
1.2723 + User::LeaveIfError(aNumChannels.Append(KNumChannelsStereo));
1.2724 + }
1.2725 +
1.2726 +/**
1.2727 +*
1.2728 +* ConvertFromDevSoundCapsToDataTypesL
1.2729 +* @param "const TMMFCapabilities&"
1.2730 +* @param "TMMFCapabilities& aDevSoundCaps, RArray<TFourCC>&"
1.2731 +*
1.2732 +*/
1.2733 +void CMMFAudioController::ConvertFromDevSoundCapsToDataTypesL(const TMMFCapabilities& aDevSoundCaps, RArray<TFourCC>& aDataTypes)
1.2734 + {
1.2735 + if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitPCM)
1.2736 + User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM8));
1.2737 + if (aDevSoundCaps.iEncoding & EMMFSoundEncoding16BitPCM)
1.2738 + User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM16));
1.2739 + if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitALaw)
1.2740 + User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeALAW));
1.2741 + if (aDevSoundCaps.iEncoding & EMMFSoundEncoding8BitMuLaw)
1.2742 + User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeMuLAW));
1.2743 + }
1.2744 +
1.2745 +/**
1.2746 +*
1.2747 +* ConvertFromSampleRateToDevSoundCapsL
1.2748 +* @param "TUint"
1.2749 +* @param "TMMFCapabilities&"
1.2750 +*
1.2751 +*/
1.2752 +void CMMFAudioController::ConvertFromSampleRateToDevSoundCapsL(TUint aSampleRate, TMMFCapabilities& aDevSoundCaps)
1.2753 + {
1.2754 + if (aSampleRate == KSampleRate8000Hz)
1.2755 + aDevSoundCaps.iRate = EMMFSampleRate8000Hz;
1.2756 + else if (aSampleRate == KSampleRate11025Hz)
1.2757 + aDevSoundCaps.iRate = EMMFSampleRate11025Hz;
1.2758 + else if (aSampleRate == KSampleRate12000Hz)
1.2759 + aDevSoundCaps.iRate = EMMFSampleRate12000Hz;
1.2760 + else if (aSampleRate == KSampleRate16000Hz)
1.2761 + aDevSoundCaps.iRate = EMMFSampleRate16000Hz;
1.2762 + else if (aSampleRate == KSampleRate22050Hz)
1.2763 + aDevSoundCaps.iRate = EMMFSampleRate22050Hz;
1.2764 + else if (aSampleRate == KSampleRate24000Hz)
1.2765 + aDevSoundCaps.iRate = EMMFSampleRate24000Hz;
1.2766 + else if (aSampleRate == KSampleRate32000Hz)
1.2767 + aDevSoundCaps.iRate = EMMFSampleRate32000Hz;
1.2768 + else if (aSampleRate == KSampleRate44100Hz)
1.2769 + aDevSoundCaps.iRate = EMMFSampleRate44100Hz;
1.2770 + else if (aSampleRate == KSampleRate48000Hz)
1.2771 + aDevSoundCaps.iRate = EMMFSampleRate48000Hz;
1.2772 + else if (aSampleRate == KSampleRate64000Hz)
1.2773 + aDevSoundCaps.iRate = EMMFSampleRate64000Hz;
1.2774 + else if (aSampleRate == KSampleRate88200Hz)
1.2775 + aDevSoundCaps.iRate = EMMFSampleRate88200Hz;
1.2776 + else if (aSampleRate == KSampleRate96000Hz)
1.2777 + aDevSoundCaps.iRate = EMMFSampleRate96000Hz;
1.2778 + else
1.2779 + User::Leave(KErrNotSupported);
1.2780 + }
1.2781 +
1.2782 +/**
1.2783 +*
1.2784 +* ConvertFromNumChannelsToDevSoundCapsL
1.2785 +* @param "TUint"
1.2786 +* @param "TMMFCapabilities&"
1.2787 +*
1.2788 +*/
1.2789 +void CMMFAudioController::ConvertFromNumChannelsToDevSoundCapsL(TUint aNumChannels, TMMFCapabilities& aDevSoundCaps)
1.2790 + {
1.2791 + if (aNumChannels == KNumChannelsMono)
1.2792 + aDevSoundCaps.iChannels = EMMFMono;
1.2793 + else if (aNumChannels == KNumChannelsStereo)
1.2794 + aDevSoundCaps.iChannels = EMMFStereo;
1.2795 + else
1.2796 + User::Leave(KErrNotSupported);
1.2797 + }
1.2798 +
1.2799 +/**
1.2800 +*
1.2801 +* ConvertFromDataTypeToDevSoundCapsL
1.2802 +* @param "TFourCC"
1.2803 +* @param "TMMFCapabilities&"
1.2804 +*
1.2805 +*/
1.2806 +void CMMFAudioController::ConvertFromDataTypeToDevSoundCapsL(TFourCC aDataType, TMMFCapabilities& aDevSoundCaps)
1.2807 + {
1.2808 + if (aDataType == KMMFFourCCCodePCM8)
1.2809 + aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitPCM;
1.2810 + else if (aDataType == KMMFFourCCCodePCM16)
1.2811 + aDevSoundCaps.iEncoding = EMMFSoundEncoding16BitPCM;
1.2812 + else if (aDataType == KMMFFourCCCodeALAW)
1.2813 + aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitALaw;
1.2814 + else if (aDataType == KMMFFourCCCodeMuLAW)
1.2815 + aDevSoundCaps.iEncoding = EMMFSoundEncoding8BitMuLaw;
1.2816 + else
1.2817 + User::Leave(KErrNotSupported);
1.2818 + }
1.2819 +
1.2820 +/**
1.2821 +* IsValidStateTransition
1.2822 +* The function validates a state transition from iState to aState
1.2823 +* and returns ETrue if the transition is allowed.
1.2824 +* @internalTechnology
1.2825 +* @param TControllerState
1.2826 +* @returns "TBool"
1.2827 +*/
1.2828 +TBool CMMFAudioController::IsValidStateTransition( TControllerState aState ) const
1.2829 + {
1.2830 + TBool result = ETrue ;
1.2831 + //[ assert the precondition that aState is a valid State ]
1.2832 + __ASSERT_ALWAYS( IsValidState(aState), Panic( EBadArgument ) );
1.2833 + //[ assert the invariant that iState is a valid State ]
1.2834 + __ASSERT_ALWAYS( Invariant(), Panic( EInvalidState ));
1.2835 +
1.2836 + // [ check the valid state transitions ]
1.2837 + // the only invalid transition is
1.2838 + // stopped to playing
1.2839 + if( ( iState == EStopped ) && ( aState == EPlaying ))
1.2840 + {
1.2841 + result = EFalse ;
1.2842 + }
1.2843 +
1.2844 + //[ assert the invariant that iState is a valid State ]
1.2845 + __ASSERT_ALWAYS( Invariant(), Panic( EInvalidState ));
1.2846 +
1.2847 + return result ;
1.2848 + }
1.2849 +
1.2850 +/*
1.2851 +* Invariant
1.2852 +* @internalTechnology
1.2853 +* @returns "TBool"
1.2854 +* This function returns whether the invariant is valid
1.2855 +*/
1.2856 +TBool CMMFAudioController::Invariant() const
1.2857 + {
1.2858 + //[ The invariant is for now defined
1.2859 + // as simply being in the correct state and
1.2860 + // having iDataPath defined ]
1.2861 + return ( iDataPath )&& IsValidState( iState);
1.2862 + }
1.2863 +
1.2864 +/*
1.2865 +* SetState
1.2866 +* This function sets the state of the controller.
1.2867 +* @internalTechnology
1.2868 +* @returns "TBool"
1.2869 +*/
1.2870 +TBool CMMFAudioController::SetState(TControllerState aState)
1.2871 + {
1.2872 + TBool result = ETrue;
1.2873 + //[ assert the precondition that the state is a valid state ]
1.2874 + __ASSERT_ALWAYS( IsValidState( aState), Panic( EBadArgument ) );
1.2875 + //[ assert the invariant the current state is valid ]
1.2876 + __ASSERT_ALWAYS( Invariant(), Panic( EBadState ) );
1.2877 + //[ only allow valid state transitions ]
1.2878 + if( IsValidStateTransition( aState ) )
1.2879 + {
1.2880 + //[ valid state transition set the state]
1.2881 + iState = aState ;
1.2882 + }
1.2883 + else
1.2884 + {
1.2885 + //[ invalid state transition return EFalse ]
1.2886 + result = EFalse;
1.2887 + }
1.2888 + // [ assert the invariant on the state ]
1.2889 + __ASSERT_ALWAYS( Invariant(), Panic( EBadState ));
1.2890 +
1.2891 + return result ;
1.2892 + }
1.2893 +
1.2894 +/*
1.2895 +* IsValidState
1.2896 +* checks whether a state is a valid
1.2897 +* @internalTechnology
1.2898 +* @returns "TBool"
1.2899 +* @param TControllerState
1.2900 +*/
1.2901 +TBool CMMFAudioController::IsValidState( TControllerState aState ) const
1.2902 + {
1.2903 + TBool result = EFalse;
1.2904 + if(( aState >= EStopped ) && ( aState <= EPlaying ))
1.2905 + {
1.2906 + result = ETrue;
1.2907 + }
1.2908 + return result;
1.2909 + }
1.2910 +
1.2911 +/**
1.2912 +* State
1.2913 +* The function State returns the current state of the audio controller
1.2914 +* @internalTechnology
1.2915 +* @returns "TControllerState"
1.2916 +*/
1.2917 +CMMFAudioController::TControllerState CMMFAudioController::State() const
1.2918 + {
1.2919 + __ASSERT_ALWAYS( Invariant(), Panic( EBadState ) );
1.2920 + return iState;
1.2921 + }
1.2922 +
1.2923 +/**
1.2924 +*
1.2925 +* SinkFormatRequired
1.2926 +*
1.2927 +*/
1.2928 +TBool CMMFAudioController::SinkFormatRequired( MDataSink& aDataSink ) const
1.2929 + {
1.2930 + return (aDataSink.DataSinkType()==KUidMmfFileSink ||
1.2931 + aDataSink.DataSinkType()==KUidMmfDescriptorSink);
1.2932 + }
1.2933 +
1.2934 +/**
1.2935 +*
1.2936 +* SourceFormatRequired
1.2937 +*
1.2938 +*/
1.2939 +
1.2940 +TBool CMMFAudioController::SourceFormatRequired(MDataSource& aDataSource) const
1.2941 + {
1.2942 + return (aDataSource.DataSourceType()==KUidMmfFileSource ||
1.2943 + aDataSource.DataSourceType()==KUidMmfDescriptorSource);
1.2944 + }
1.2945 +
1.2946 +TInt CMMFAudioController::MdcEvaluateIntent(ContentAccess::TIntent aIntent)
1.2947 + {
1.2948 + if (iDataSource->DataSourceType()==KUidMmfFileSource)
1.2949 + {
1.2950 + CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
1.2951 + TInt err = file->EvaluateIntent(aIntent);
1.2952 + return err;
1.2953 + }
1.2954 + else
1.2955 + {
1.2956 + // Evaluating intent will always succeed on sinks that
1.2957 + // don't support DRM
1.2958 + return KErrNone;
1.2959 + }
1.2960 +
1.2961 + }
1.2962 +
1.2963 +TInt CMMFAudioController::MdcExecuteIntent(ContentAccess::TIntent aIntent)
1.2964 + {
1.2965 + if (iDataSource->DataSourceType()==KUidMmfFileSource)
1.2966 + {
1.2967 + CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
1.2968 + TInt err = file->ExecuteIntent(aIntent);
1.2969 + return err;
1.2970 + }
1.2971 + else
1.2972 + {
1.2973 + // Executing intent will always succeed on sinks that
1.2974 + // don't support DRM
1.2975 + return KErrNone;
1.2976 + }
1.2977 + }
1.2978 +
1.2979 +TInt CMMFAudioController::MdcDisableAutomaticIntent(TBool aDisableAutoIntent)
1.2980 + {
1.2981 + iDisableAutoIntent = aDisableAutoIntent;
1.2982 + return KErrNone;
1.2983 + }
1.2984 +
1.2985 +
1.2986 +TInt CMMFAudioController::MdcSetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
1.2987 + {
1.2988 + if (iDataSource->DataSourceType()==KUidMmfFileSource)
1.2989 + {
1.2990 + CMMFFile* file = static_cast<CMMFFile*>(iDataSource);
1.2991 + TInt err = file->SetAgentProperty(aProperty, aValue);
1.2992 + return err;
1.2993 + }
1.2994 + else
1.2995 + {
1.2996 + return KErrNone;
1.2997 + }
1.2998 + }
1.2999 +
1.3000 +void CMMFAudioController::MarnRegisterAsClientL(TUid aEventType,const TDesC8& aNotificationRegistrationData)
1.3001 + {
1.3002 + //[ assert the invariant ]
1.3003 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToRegisterAsClient));
1.3004 + //[ precondition that we have a sink]
1.3005 + if (!iDataSink)
1.3006 + {
1.3007 + User::Leave(KErrNotReady);
1.3008 + }
1.3009 + //[register the notification ]
1.3010 + MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
1.3011 + TInt err = audioOutput->SoundDevice().RegisterAsClient(aEventType, aNotificationRegistrationData);
1.3012 + User::LeaveIfError(err);
1.3013 + iRegisterARN = ETrue;
1.3014 + //[ assert the invariant ]
1.3015 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterRegisterAsClient));
1.3016 + }
1.3017 +
1.3018 +void CMMFAudioController::MarnCancelRegisterAsClientL(TUid aEventType)
1.3019 + {
1.3020 + //[ assert the invariant ]
1.3021 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToCancelRegisterAsClient));
1.3022 + //[ precondition that we have a sink]
1.3023 + if (!iDataSink)
1.3024 + {
1.3025 + User::Leave(KErrNotReady);
1.3026 + }
1.3027 + //[cancel the notification ]
1.3028 + MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
1.3029 + TInt err = audioOutput->SoundDevice().CancelRegisterAsClient(aEventType);
1.3030 + User::LeaveIfError(err);
1.3031 + iRegisterARN = EFalse;
1.3032 + //[ assert the invariant ]
1.3033 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterCancelRegisterAsClient));
1.3034 + }
1.3035 +
1.3036 +void CMMFAudioController::MarnGetResourceNotificationDataL(TUid aEventType,TDes8& aNotificationData)
1.3037 + {
1.3038 + //[ assert the invariant ]
1.3039 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToGetResourceNotificationData));
1.3040 + //[ precondition that we have a sink]
1.3041 + if (!iDataSink)
1.3042 + {
1.3043 + User::Leave(KErrNotReady);
1.3044 + }
1.3045 + //[get the notification data]
1.3046 + MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
1.3047 + TMMFTimeIntervalMicroSecondsPckg pckg;
1.3048 + TInt err = audioOutput->SoundDevice().GetResourceNotificationData(aEventType, pckg);
1.3049 + User::LeaveIfError(err);
1.3050 +
1.3051 + // aNotificationData is a package buffer returned as TMMFTimeIntervalMicroSecondsPckg,
1.3052 + // but the contents should be converted to an integer and interpreted as the
1.3053 + // data returned is samples played, but not as a microsecond value.
1.3054 + // As the client expects a position (in microseconds from the beginning
1.3055 + // of the clip) we need to convert the data depending on the sample rate
1.3056 + // Potential issue if using the number of samples played with VBR sampling.
1.3057 + RArray<TUint> array;
1.3058 + CleanupClosePushL(array);
1.3059 + ConvertFromDevSoundCapsToSampleRatesL(audioOutput->SoundDevice().Config(), array);
1.3060 + // Should only ever have 1 entry in the array
1.3061 + ASSERT(array.Count() == 1);
1.3062 + TUint rate = array[0];
1.3063 + if (rate)
1.3064 + {
1.3065 + // Convert the given number of samples using the sample rate
1.3066 + const TInt KMicroSecsInOneSec = 1000000;
1.3067 + TTimeIntervalMicroSeconds value = pckg();
1.3068 + value = TTimeIntervalMicroSeconds(value.Int64() * KMicroSecsInOneSec / rate);
1.3069 + pckg() = value;
1.3070 + }
1.3071 + else
1.3072 + {
1.3073 + User::Leave(KErrArgument);
1.3074 + }
1.3075 + aNotificationData = pckg;
1.3076 + CleanupStack::PopAndDestroy();//array
1.3077 +
1.3078 + //[ assert the invariant ]
1.3079 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterGetResourceNotificationData));
1.3080 + }
1.3081 +
1.3082 +void CMMFAudioController::MarnWillResumePlayL()
1.3083 + {
1.3084 + //[ assert the invariant ]
1.3085 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateToResumePlay));
1.3086 + //[ precondition that we have a sink]
1.3087 + if (!iDataSink)
1.3088 + {
1.3089 + User::Leave(KErrNotReady);
1.3090 + }
1.3091 + //[wait for the client to resume ]
1.3092 + MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(iDataSink);
1.3093 + TInt err = audioOutput->SoundDevice().WillResumePlay();
1.3094 + User::LeaveIfError(err);
1.3095 + //[ assert the invariant ]
1.3096 + __ASSERT_ALWAYS( Invariant(), Panic(EBadStateAfterResumePlay));
1.3097 + }