# HG changeset patch # User William Roberts # Date 1287576358 -3600 # Node ID 657f02e590f17d13ceebf1eddca8dee7e521a096 # Parent 320024dcf7b6b089f3ccdbb721811ec3ab1bd81d Original source files from sf/os/mm/mmlibs/mmfw, to be reworked for stem_MediaClientAudio.dll diff -r 320024dcf7b6 -r 657f02e590f1 breakdeps/mmfclientaudioplayer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/mmfclientaudioplayer.cpp Wed Oct 20 13:05:58 2010 +0100 @@ -0,0 +1,2127 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include +#include "mmfclientaudioplayer.h" +#include "mmfclientutility.h" +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include +#endif + +using namespace ContentAccess; + +// declared in the recorder module +void Panic(TInt aPanicCode); + +/** +Constructs and initialises a new instance of the audio player utility. + +The function leaves if the audio player utility object cannot be created. + +No callback notification is made upon completion of NewL(). + +@param aCallback + The audio player observer interface. +@param aPriority + The Priority Value - this client's relative priority. This is a value between EMdaPriorityMin and + EMdaPriorityMax and represents a relative priority. A higher value indicates a more important request. +@param aPref + The Priority Preference - an additional audio policy parameter. The suggested default is + EMdaPriorityPreferenceNone. Further values are given by TMdaPriorityPreference, and additional + values may be supported by given phones and/or platforms, but should not be depended upon by + portable code. + +@return A pointer to the new audio player utility object. + +Note: The Priority Value and Priority Preference are used primarily when deciding what to do when +several audio clients attempt to play or record simultaneously. In addition to the Priority Value and Preference, +the adaptation may consider other parameters such as the SecureId and Capabilities of the client process. +Whatever, the decision as to what to do in such situations is up to the audio adaptation, and may +vary between different phones. Portable applications are advised not to assume any specific behaviour. +*/ +EXPORT_C CMdaAudioPlayerUtility* CMdaAudioPlayerUtility::NewL(MMdaAudioPlayerCallback& aCallback, + TInt aPriority, + TInt aPref) + { + CMdaAudioPlayerUtility* self = new(ELeave) CMdaAudioPlayerUtility(); + CleanupStack::PushL(self); + self->iProperties = CMMFMdaAudioPlayerUtility::NewL(aCallback, aPriority, aPref); + CleanupStack::Pop(self); + return self; + } + +/** +Constructs and initialises a new instance of the audio player utility for playing sampled audio data +from a file. The audio data must be in a supported format (e.g. WAV and AU). + +The function leaves if the audio player utility object cannot be created. + +When initialisation of the audio player utility is complete, successfully or otherwise, the callback +function MMdaAudioPlayerCallback::MapcInitComplete() is called. + +@param aFileName + The full path name of the file containing the audio data. +@param aCallback + The audio player observer interface. +@param aPriority + The Priority Value - this client's relative priority. This is a value between EMdaPriorityMin and + EMdaPriorityMax and represents a relative priority. A higher value indicates a more important request. +@param aPref + The Priority Preference - an additional audio policy parameter. The suggested default is + EMdaPriorityPreferenceNone. Further values are given by TMdaPriorityPreference, and additional + values may be supported by given phones and/or platforms, but should not be depended upon by + portable code. +@param aServer + Not used in 7.0s. This parameter is provided for binary compatibility with previous versions. + +@return A pointer to the new audio player utility object. + +Note: The Priority Value and Priority Preference are used primarily when deciding what to do when +several audio clients attempt to play or record simultaneously. In addition to the Priority Value and Preference, +the adaptation may consider other parameters such as the SecureId and Capabilities of the client process. +Whatever, the decision as to what to do in such situations is up to the audio adaptation, and may +vary between different phones. Portable applications are advised not to assume any specific behaviour. +*/ +EXPORT_C CMdaAudioPlayerUtility* CMdaAudioPlayerUtility::NewFilePlayerL(const TDesC& aFileName, + MMdaAudioPlayerCallback& aCallback, + TInt aPriority, + TInt aPref, + CMdaServer* /*aServer*/) + { + CMdaAudioPlayerUtility* self = new(ELeave) CMdaAudioPlayerUtility(); + CleanupStack::PushL(self); + self->iProperties = CMMFMdaAudioPlayerUtility::NewFilePlayerL(aFileName, aCallback, aPriority, aPref); + CleanupStack::Pop(self); + return self; + } + +/** +Constructs and initialises a new instance of the audio player utility for playing sampled audio data +from a descriptor. + +The audio data must be in a supported format (e.g. WAV and AU). + +The function leaves if the audio player utility object cannot be created. When initialisation of the +audio player utility is complete, successfully or otherwise, the callback function +MMdaAudioPlayerCallback::MapcInitComplete() is called. + +@param aData + A descriptor containing the audio data. This descriptor must remain in existence for the + lifetime of this audio player utility object. +@param aCallback + The audio player observer interface. +@param aPriority + The Priority Value - this client's relative priority. This is a value between EMdaPriorityMin and + EMdaPriorityMax and represents a relative priority. A higher value indicates a more important request. +@param aPref + The Priority Preference - an additional audio policy parameter. The suggested default is + EMdaPriorityPreferenceNone. Further values are given by TMdaPriorityPreference, and additional + values may be supported by given phones and/or platforms, but should not be depended upon by + portable code. +@param aServer + Not used in 7.0s. This parameter is provided for binary compatibility with previous versions. + +@return A pointer to the new audio player utility object. + +Note: The Priority Value and Priority Preference are used primarily when deciding what to do when +several audio clients attempt to play or record simultaneously. In addition to the Priority Value and Preference, +the adaptation may consider other parameters such as the SecureId and Capabilities of the client process. +Whatever, the decision as to what to do in such situations is up to the audio adaptation, and may +vary between different phones. Portable applications are advised not to assume any specific behaviour. +*/ +EXPORT_C CMdaAudioPlayerUtility* CMdaAudioPlayerUtility::NewDesPlayerL(const TDesC8& aData, MMdaAudioPlayerCallback& aCallback, TInt aPriority, TInt aPref, CMdaServer* /*aServer*/) + { + CMdaAudioPlayerUtility* self = new(ELeave) CMdaAudioPlayerUtility(); + CleanupStack::PushL(self); + self->iProperties = CMMFMdaAudioPlayerUtility::NewDesPlayerL(aData, aCallback, aPriority, aPref); + CleanupStack::Pop(self); + return self; + } + +/** +Constructs and initialises a new instance of the audio player utility for playing sampled audio data +from a read only descriptor. + +The audio data must be in a supported format (e.g. WAV and AU). + +The function leaves if the audio player utility object cannot be created. When initialisation of +the audio player utility is complete, successfully or otherwise, the callback function +MMdaAudioPlayerCallback::MapcInitComplete() is called. + +@param aData + A read only descriptor containing the audio data. This descriptor must remain in existence + for the lifetime of this audio player utility object. +@param aCallback + The audio player observer interface. +@param aPriority + The Priority Value - this client's relative priority. This is a value between EMdaPriorityMin and + EMdaPriorityMax and represents a relative priority. A higher value indicates a more important request. +@param aPref + The Priority Preference - an additional audio policy parameter. The suggested default is + EMdaPriorityPreferenceNone. Further values are given by TMdaPriorityPreference, and additional + values may be supported by given phones and/or platforms, but should not be depended upon by + portable code. +@param aServer + Not used in 7.0s. This parameter is provided for binary compatibility with previous versions. + +@return A pointer to a new audio player utility. + +Note: The Priority Value and Priority Preference are used primarily when deciding what to do when +several audio clients attempt to play or record simultaneously. In addition to the Priority Value and Preference, +the adaptation may consider other parameters such as the SecureId and Capabilities of the client process. +Whatever, the decision as to what to do in such situations is up to the audio adaptation, and may +vary between different phones. Portable applications are advised not to assume any specific behaviour. +*/ +EXPORT_C CMdaAudioPlayerUtility* CMdaAudioPlayerUtility::NewDesPlayerReadOnlyL(const TDesC8& aData, MMdaAudioPlayerCallback& aCallback, TInt aPriority, TInt aPref, CMdaServer* /*aServer*/) + { + CMdaAudioPlayerUtility* self = new(ELeave) CMdaAudioPlayerUtility(); + CleanupStack::PushL(self); + self->iProperties = CMMFMdaAudioPlayerUtility::NewDesPlayerReadOnlyL(aData, aCallback, aPriority, aPref); + CleanupStack::Pop(self); + return self; + } + +CMdaAudioPlayerUtility::CMdaAudioPlayerUtility() + { + } + +/** +Destructor. + +Frees all resources owned by the object prior to its destruction. +*/ +CMdaAudioPlayerUtility::~CMdaAudioPlayerUtility() + { + delete iProperties; + } + +/** +Ensures that any subsequent calls to OpenXYZ() will create controllers that +share a heap. + +The default behaviour is that for each player utility a controller with its own heap +is created. Each heap uses a chunk, so using this function avoids situations where +the number of chunks per process is limited. +The default behaviour is generally to be preferred, and should give lower overall +memory usage. However, if many controllers are to be created for a particular thread, +then this function should be used to prevent running out of heaps or chunks. + +@since 9.1 +*/ +EXPORT_C void CMdaAudioPlayerUtility::UseSharedHeap() + { + ASSERT(iProperties); + iProperties->UseSharedHeap(); + } + +// 5.0 functions + +/** +Begins playback of audio sample data at the current playback position using the current volume, +gain and priority settings. + +When playing of the audio sample is complete, successfully or +otherwise, the callback function +MMdaAudioPlayerCallback::MapcPlayComplete() is +called. + +If this function is called whilst already playing then +MMdaAudioPlayerCallback::MapcPlayComplete will return with the +error code KErrNotReady. + +@since 5.0 +*/ +void CMdaAudioPlayerUtility::Play() + { + ASSERT(iProperties); + iProperties->Play(); + } + +/** +Stops playback of the audio sample as soon as possible. + +If the audio sample is playing, playback is stopped as soon as +possible. If playback is already complete, nothing further happens as +a result of calling this function. The callback function +MMdaAudioPlayerCallback::MapcPlayComplete() is not +called. + +@since 5.0 +*/ +void CMdaAudioPlayerUtility::Stop() + { + ASSERT(iProperties); + iProperties->Stop(); + } + + +/** +Changes the current playback volume to a specified value. + +The volume can be changed before or during playback and is effective +immediately. The volume can be set to any value between zero (mute) and +the maximum permissible volume (determined using MaxVolume()). + +@param aVolume + The volume setting. This can be any value from zero to + the value returned by a call to + CMdaAudioPlayerUtility::MaxVolume(). + Setting a zero value mutes the sound. Setting the maximum + value results in the loudest possible sound. Values less + than zero would be set to zero and the values greater than + the maximum permitted volume would be set to the maximum volume. +@return An error code indicating if the function call was successful. KErrNone on success, + otherwise another of the system-wide error codes. +@panic EMMFMediaClientBadArgument is raised when the audio player utility is not initialised. + +@since 5.0 +*/ +TInt CMdaAudioPlayerUtility::SetVolume(TInt aVolume) + { + ASSERT(iProperties); + return iProperties->SetVolume(aVolume); + } + +/** +Sets the number of times the audio sample is to be repeated during the +playback operation. + +A period of silence can follow each playing of the sample. The audio +sample can be repeated indefinitely. + +@param aRepeatNumberOfTimes + The number of times the audio sample, together with + the trailing silence, is to be repeated. If this is + set to KMdaRepeatForever, then the audio + sample, together with the trailing silence, is + repeated indefinitely or until Stop() is + called. If this is set to zero, then the audio sample + is not repeated. +@param aTrailingSilence + The time interval of the trailing silence in microseconds. + +@since 5.0 +*/ +void CMdaAudioPlayerUtility::SetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence) + { + ASSERT(iProperties); + iProperties->SetRepeats(aRepeatNumberOfTimes, aTrailingSilence); + } + +/** +Defines the period over which the volume level is to rise smoothly +from nothing to the normal volume level. + +@param aRampDuration + The period over which the volume is to rise. A zero + value causes the audio sample to be played at the + normal level for the full duration of the playback. A + value which is longer than the duration of the audio + sample means that the sample never reaches its normal + volume level. + +@since 5.0 +*/ +void CMdaAudioPlayerUtility::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration) + { + ASSERT(iProperties); + iProperties->SetVolumeRamp(aRampDuration); + } + +/** +Returns the duration of the audio sample in microseconds. + +@return The duration of the sample in microseconds. + +@since 5.0 +*/ +const TTimeIntervalMicroSeconds& CMdaAudioPlayerUtility::Duration() + { + ASSERT(iProperties); + return iProperties->Duration(); + } + +/** +Returns the duration of the audio sample in microseconds, and the duration state. + +@param aDuration + The duration of the sample in microseconds. +@return The duration state + +@since 9.1 +*/ +EXPORT_C TMMFDurationInfo CMdaAudioPlayerUtility::Duration(TTimeIntervalMicroSeconds& aDuration) +{ + ASSERT(iProperties); + return iProperties->Duration(aDuration); +} + +/** +Returns an integer representing the maximum volume. + +This is the maximum value which can be passed to +CMdaAudioPlayerUtility::SetVolume(). This value is platform +independent, but is always greater than or equal to one. + +@return The maximum volume setting. +@panic EMMFMediaClientPanicServerCommunicationProblem is raised when the audio player utility is not initialised. + +@since 5.0 +*/ +TInt CMdaAudioPlayerUtility::MaxVolume() + { + ASSERT(iProperties); + return iProperties->MaxVolume(); + } + +// 7.0s functions + +/** +Opens an audio clip from a file. + +The audio data must be in a supported format (for example, WAV or AU). + +This function leaves with KErrNotReady if there is a previous open statement awaiting notification of completion. + +@param aFileName + The file to open. +@leave KErrNotReady + If a previous open statement is awaiting notification of completion. + opening the file +@since 7.0s +*/ +EXPORT_C void CMdaAudioPlayerUtility::OpenFileL(const TDesC& aFileName) + { + ASSERT(iProperties); + iProperties->OpenFileL(aFileName); + } + +/** +Opens an audio clip from a file. + +The audio data must be in a supported format (for example, WAV or AU). + +This function leaves with KErrNotReady if there is a previous open statement awaiting notification of completion. + +Note: it is generally advisable that the RFile is shared through the call RFs::ShareProtected(). +This allows the adaptation to pass it to another process, if that is required. This is particularly +true of playing DRM encrypted files. + +@param aFile + The open shared session file handle to use +@leave KErrBadHandle + If the file handle is not shared through the call RFs::ShareProtected(), and the adaptation needs it to be. +@leave KErrNotReady + If a previous open statement is awaiting notification of completion. + opening the file +*/ +EXPORT_C void CMdaAudioPlayerUtility::OpenFileL(const RFile& aFile) + { + ASSERT(iProperties); + RFile& file = const_cast(aFile); + TMMFileHandleSource tfs(file, KDefaultContentObject, EPlay); + iProperties->OpenFileL(tfs); + } + +/** +Opens an audio clip from a file. + +The audio data must be in a supported format (for example, WAV or AU). + +This function leaves with KErrNotReady if there is a previous open statement awaiting notification of completion. + +@param aSource + The file to open or an open file handle to use +@leave KErrNotReady + If a previous open statement is awaiting notification of completion. + opening the file +*/ +EXPORT_C void CMdaAudioPlayerUtility::OpenFileL(const TMMSource& aSource) + { + ASSERT(iProperties); + iProperties->OpenFileL(aSource); + } + +/** +Opens an audio clip from a descriptor. + +The audio data must be in a supported format (for example, WAV or AU). + +@param aDescriptor + A descriptor containing the audio clip. +@leave KErrInUse + If a previous open statement is awaiting notification of completion. + +@since 7.0s +*/ +EXPORT_C void CMdaAudioPlayerUtility::OpenDesL(const TDesC8& aDescriptor) + { + ASSERT(iProperties); + iProperties->OpenDesL(aDescriptor); + } + +/** +Opens an audio clip from a URL. + +The audio data must be in a supported format (for example, WAV or AU). + +@param aUrl + The URL to open. +@param aIapId + Internet access point(IAP) ID to use. KUseDefaultIap selects the default IAP. +@param aMimeType + MIME type of the URL source. + +@leave KErrInUse + If a previous open statement is awaiting notification of completion. + +@since 7.0s +*/ +EXPORT_C void CMdaAudioPlayerUtility::OpenUrlL(const TDesC& aUrl, const TInt aIapId /*=KUseDefaultIap*/, const TDesC8& aMimeType /*=KNullDesC8*/) + { + ASSERT(iProperties); + iProperties->OpenUrlL(aUrl, aIapId, aMimeType); + } + +/** +Pauses the playback of the audio clip. + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::Pause() + { + ASSERT(iProperties); + return iProperties->Pause(); + } + +/** +Closes the current audio clip (allowing another clip to be opened). + +@since 7.0s +*/ +EXPORT_C void CMdaAudioPlayerUtility::Close() + { + ASSERT(iProperties); + iProperties->Close(); + } + +/** +Returns the current playback position in microseconds from the start of the clip. + +@param aPosition + The current time position in microseconds from the start of the clip to the current + play position. + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::GetPosition(TTimeIntervalMicroSeconds& aPosition) + { + ASSERT(iProperties); + return iProperties->GetPosition(aPosition); + } + +/** +Sets the current playback position in microseconds from the start of the clip. + +@param aPosition + The position to move to in microseconds from the start of the clip. + +@since 7.0s +*/ +EXPORT_C void CMdaAudioPlayerUtility::SetPosition(const TTimeIntervalMicroSeconds& aPosition) + { + ASSERT(iProperties); + iProperties->SetPosition(aPosition); + } + +/** +Sets the priority for playback. This is used to arbitrate between multiple +objects trying to access a single sound device. + +@param aPriority + The Priority Value. +@param aPref + The Priority Preference. + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. + +@since 7.0s + +@see CMdaAudioPlayerUtility::NewL() + +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::SetPriority(TInt aPriority, TInt aPref) + { + ASSERT(iProperties); + return iProperties->SetPriority(aPriority, aPref); + } + +/** +Returns the current playback volume. + +@param aVolume + A value between 0 and the maximum volume settings returned by MaxVolume(). + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::GetVolume(TInt& aVolume) + { + ASSERT(iProperties); + return iProperties->GetVolume(aVolume); + } + +/** +Returns the number of meta data entries in the current audio clip. + +@param aNumEntries + The number of meta data entries in the header of the current clip. + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::GetNumberOfMetaDataEntries(TInt& aNumEntries) + { + ASSERT(iProperties); + return iProperties->GetNumberOfMetaDataEntries(aNumEntries); + } + +/** +Returns the requested meta data entry. + +@param aMetaDataIndex + The index number of the meta data to retrieve. + +@return The requested meta data entry. +@leave KErrNotFound + The meta data entry does not exist. +@leave KErrNotImplemented + The controller does not support meta data information for this format. + +@since 7.0s +*/ +EXPORT_C CMMFMetaDataEntry* CMdaAudioPlayerUtility::GetMetaDataEntryL(TInt aMetaDataIndex) + { + ASSERT(iProperties); + return iProperties->GetMetaDataEntryL(aMetaDataIndex); + } + +/** +Defines a window on the audio sample data. + +The window is defined in terms of a start and end position. +When the current playback position reaches the window end position, or Stop() is called, the +current playback position is set to the window start position and playback stops. + +The current playback position is not affected by a call to SetPlayWindow() unless it is outside +the new playback window, in which case it is set to the window start or end position depending +on which one is closer. + +The window persists until ClearPlayWindow() is called. +Loading new audio sample data without adjusting or clearing the window will result in +playback errors if the window is outside the new data. + +@param aStart + The position defining the start of the window, measured in microseconds. If this value is less + than zero, it is set to zero. If this value is greater than aEnd, then it is swapped with aEnd. +@param aEnd + The position defining the end of the window, measured in microseconds. If this value is greater + than the value returned by Duration(), it is set to the value of Duration(). If this value is + less than aStart, then it is swapped with aStart. + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::SetPlayWindow(const TTimeIntervalMicroSeconds& aStart, + const TTimeIntervalMicroSeconds& aEnd) + { + ASSERT(iProperties); + return iProperties->SetPlayWindow(aStart, aEnd); + } + +/** +Clears the current playback window. + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::ClearPlayWindow() + { + ASSERT(iProperties); + return iProperties->ClearPlayWindow(); + } + +/** +Sets the current playback balance. + +@param aBalance + A value between KMMFBalanceMaxLeft + and KMMFBalanceMaxRight. The default value is + KMMFBalanceCenter. + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::SetBalance(TInt aBalance /*= KMMFBalanceCenter*/) + { + ASSERT(iProperties); + return iProperties->SetBalance(aBalance); + } + +/** + * Returns The current playback balance. This function may not return the same value + * as passed to SetBalance depending on the internal implementation in + * the underlying components. + * + * @param aBalance + * A value between KMMFBalanceMaxLeft + * and KMMFBalanceMaxRight. + * + * @return An error code indicating if the function call was successful. KErrNone on success, otherwise + * another of the system-wide error codes. + * + * @since 7.0s + */ +EXPORT_C TInt CMdaAudioPlayerUtility::GetBalance(TInt& aBalance) + { + ASSERT(iProperties); + return iProperties->GetBalance(aBalance); + } + +/** +Returns the controller implementation information associated with the current controller. + +@return The controller implementation structure + +@since 7.0s +*/ +EXPORT_C const CMMFControllerImplementationInformation& CMdaAudioPlayerUtility::ControllerImplementationInformationL() + { + ASSERT(iProperties); + return iProperties->ControllerImplementationInformationL(); + } + +/** +Registers callback object to receive notifications of audio loading/rebuffering. + +@param aCallback + The object to receive audio loading notifications. + +@since 7.0s +*/ +EXPORT_C void CMdaAudioPlayerUtility::RegisterForAudioLoadingNotification(MAudioLoadingObserver& aCallback) + { + ASSERT(iProperties); + iProperties->RegisterForAudioLoadingNotification(aCallback); + } + +/** +Returns the current progress of audio loading. + +@param aPercentageProgress + The percentage of the audio clip loaded. + +@since 7.0s +*/ +EXPORT_C void CMdaAudioPlayerUtility::GetAudioLoadingProgressL(TInt& aPercentageProgress) + { + ASSERT(iProperties); + iProperties->GetAudioLoadingProgressL(aPercentageProgress); + } + +/** +Sends a synchronous custom command to the controller. + +@param aDestination + The destination of the message, consisting of the UID of + the interface of this message. +@param aFunction + The function number to indicate which function is to be called + on the interface defined in the aDestination parameter. +@param aDataTo1 + A reference to the first chunk of data to be copied to the controller + framework. The exact contents of the data are dependent on the + interface being called. Can be KNullDesC8. +@param aDataTo2 + A reference to the second chunk of data to be copied to the controller + framework. The exact contents of the data are dependent on the + interface being called. Can be KNullDesC8. +@param aDataFrom + A reference to an area of memory to which the controller framework will + write any data to be passed back to the client. Can't be KNullDesC8. + +@return The result of the request. Exact range of values is dependent on the interface. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::CustomCommandSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TDes8& aDataFrom) + { + ASSERT(iProperties); + return iProperties->CustomCommandSync(aDestination, aFunction, aDataTo1, aDataTo2, aDataFrom); + } + +/** +Sends a synchronous custom command to the controller. + +@param aDestination + The destination of the message, consisting of the UID of + the interface of this message. +@param aFunction + The function number to indicate which function is to be called + on the interface defined in the aDestination parameter. +@param aDataTo1 + A reference to the first chunk of data to be copied to the controller + framework. The exact contents of the data are dependent on the + interface being called. Can be KNullDesC8. +@param aDataTo2 + A reference to the second chunk of data to be copied to the controller + framework. The exact contents of the data are dependent on the + interface being called. Can be KNullDesC8. + +@return The result of the request. Exact range of values is dependent on the interface. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::CustomCommandSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2) + { + ASSERT(iProperties); + return iProperties->CustomCommandSync(aDestination, aFunction, aDataTo1, aDataTo2); + } + +/** +Sends an asynchronous custom command to the controller. + +Note: +This method will return immediately. The RunL of the active object owning the +aStatus parameter will be called when the command is completed by the +controller framework. + +@param aDestination + The destination of the message, consisting of the uid of + the interface of this message. +@param aFunction + The function number to indicate which function is to be called + on the interface defined in the aDestination parameter. +@param aDataTo1 + A reference to the first chunk of data to be copied to the controller + framework. The exact contents of the data are dependent on the + interface being called. Can be KNullDesC8. +@param aDataTo2 + A reference to the second chunk of data to be copied to the controller + framework. The exact contents of the data are dependent on the + interface being called. Can be KNullDesC8. +@param aDataFrom + A reference to an area of memory to which the controller framework will + write any data to be passed back to the client. Can't be KNullDesC8." +@param aStatus + The TRequestStatus of an active object. This will contain the + result of the request on completion. The exact range of + result values is dependent on the interface. + +@since 7.0s +*/ +EXPORT_C void CMdaAudioPlayerUtility::CustomCommandAsync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TDes8& aDataFrom, TRequestStatus& aStatus) + { + ASSERT(iProperties); + iProperties->CustomCommandAsync(aDestination, aFunction, aDataTo1, aDataTo2, aDataFrom, aStatus); + } + +/** +Sends an asynchronous custom command to the controller. + +Note: +This method will return immediately. The RunL of the active object owning the +aStatus parameter will be called when the command is completed by the +controller framework. + +@param aDestination + The destination of the message, consisting of the uid of + the interface of this message. +@param aFunction + The function number to indicate which function is to be called + on the interface defined in the aDestination parameter. +@param aDataTo1 + A reference to the first chunk of data to be copied to the controller + framework. The exact contents of the data are dependent on the + interface being called. Can be KNullDesC8. +@param aDataTo2 + A reference to the second chunk of data to be copied to the controller + framework. The exact contents of the data are dependent on the + interface being called. Can be KNullDesC8. +@param aStatus + The TRequestStatus of an active object. This will contain the + result of the request on completion. The exact range of + result values is dependent on the interface. + +@since 7.0s +*/ +EXPORT_C void CMdaAudioPlayerUtility::CustomCommandAsync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TRequestStatus& aStatus) + { + ASSERT(iProperties); + iProperties->CustomCommandAsync(aDestination, aFunction, aDataTo1, aDataTo2, aStatus); + } + +/** +Returns the bit rate of the audio clip. + +@param aBitRate + The bit rate of the audio clip + +@return An error code indicating if the function call was successful. KErrNone on success, + otherwise another of the system-wide error codes. + +@since 7.0s +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::GetBitRate(TUint& aBitRate) + { + ASSERT(iProperties); + return iProperties->GetBitRate(aBitRate); + } + +/** +Gets a controller's DRM custom command implementation. + +@return A pointer to a controller's DRM custom command implementation, or NULL if the +controller does not support it. +*/ +EXPORT_C MMMFDRMCustomCommand* CMdaAudioPlayerUtility::GetDRMCustomCommand() + { + ASSERT(iProperties); + return iProperties->GetDRMCustomCommand(); + } + +/** +Registers the Event for Notification when resource is avaliable. + +@param aCallback + The audio outputstream observer interface.. + +@param aNotificationEventUid + The Event for which the client is registered. + +@param aNotificationRegistrationData + Notification registration specific data. + +@return An error code indicating if the registration was successful. KErrNone on success, + otherwise another of the system-wide error codes. +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::RegisterAudioResourceNotification(MMMFAudioResourceNotificationCallback& aCallback,TUid aNotificationEventUid,const TDesC8& aNotificationRegistrationData) + { + ASSERT(iProperties); + return iProperties->RegisterAudioResourceNotification(aCallback,aNotificationEventUid,aNotificationRegistrationData); + } + +/** +Cancels the registered notification event. + +@param aNotificationEventUid + The Event to notify the client. + +@return An error code indicating if the registration was successful. KErrNone on success, + otherwise another of the system-wide error codes. +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::CancelRegisterAudioResourceNotification(TUid aNotificationEventUid) + { + ASSERT(iProperties); + return iProperties->CancelRegisterAudioResourceNotification(aNotificationEventUid); + } + +/** +Waits for the client to resume the play even after the default timer expires. + +@return An error code indicating if the registration was successful. KErrNone on success, + otherwise another of the system-wide error codes. +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::WillResumePlay() + { + ASSERT(iProperties); + return iProperties->WillResumePlay(); + } + + +/** +Set the priority of the controller's sub thread. + +This can be used to increase the responsiveness of the audio plugin to minimise +any lag in processing. This function should be used with care as it may have knock-on +effects elsewhere in the system. + +@param aPriority + The TThreadPriority that the thread should run under. The default is EPriorityNormal. +@return TInt + A standard error code: KErrNone if successful, KErrNotReady if the thread does not have a + valid handle. +*/ +EXPORT_C TInt CMdaAudioPlayerUtility::SetThreadPriority(const TThreadPriority& aPriority) const + { + ASSERT(iProperties); + return iProperties->SetThreadPriority(aPriority); + } + + + + +CMMFMdaAudioPlayerUtility* CMMFMdaAudioPlayerUtility::NewL(MMdaAudioPlayerCallback& aCallback, + TInt aPriority, + TInt aPref) + { + CMMFMdaAudioPlayerUtility* self = new(ELeave) CMMFMdaAudioPlayerUtility(aCallback, aPriority, aPref); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CMMFMdaAudioPlayerUtility* CMMFMdaAudioPlayerUtility::NewFilePlayerL(const TDesC& aFileName, + MMdaAudioPlayerCallback& aCallback, + TInt aPriority, + TInt aPref, + CMdaServer* /*aServer*/) + { + CMMFMdaAudioPlayerUtility* self = new(ELeave) CMMFMdaAudioPlayerUtility(aCallback, aPriority, aPref); + CleanupStack::PushL(self); + self->ConstructL(); + TMMFileSource filesource(aFileName, KDefaultContentObject, EPlay); + self->OpenFileL(filesource); + CleanupStack::Pop(self); + return self; + } + +CMMFMdaAudioPlayerUtility* CMMFMdaAudioPlayerUtility::NewDesPlayerL(const TDesC8& aData, MMdaAudioPlayerCallback& aCallback, TInt aPriority, TInt aPref, CMdaServer* /*aServer*/) + { + CMMFMdaAudioPlayerUtility* self = new(ELeave) CMMFMdaAudioPlayerUtility(aCallback, aPriority, aPref); + CleanupStack::PushL(self); + self->ConstructL(); + self->OpenDesL(aData); + CleanupStack::Pop(self); + return self; + } + +CMMFMdaAudioPlayerUtility* CMMFMdaAudioPlayerUtility::NewDesPlayerReadOnlyL(const TDesC8& aData, MMdaAudioPlayerCallback& aCallback, TInt aPriority, TInt aPref, CMdaServer* /*aServer*/) + { + CMMFMdaAudioPlayerUtility* self = new(ELeave) CMMFMdaAudioPlayerUtility(aCallback, aPriority, aPref); + CleanupStack::PushL(self); + self->ConstructL(); + self->OpenDesL(aData); + CleanupStack::Pop(self); + return self; + } + +void CMMFMdaAudioPlayerUtility::UseSharedHeap() + { + iFindAndOpenController->UseSharedHeap(); + } + +// CMMFMdaAudioPlayerUtility +CMMFMdaAudioPlayerUtility::~CMMFMdaAudioPlayerUtility() + { + + delete iControllerImplementationInformation; + delete iAsyncCallBack; + delete iRepeatTrailingSilenceTimer; + delete iFindAndOpenController; + delete iControllerEventMonitor; + iMediaIds.Close(); + iController.Close(); + } + +CMMFMdaAudioPlayerUtility::CMMFMdaAudioPlayerUtility(MMdaAudioPlayerCallback& aCallback, TInt aPriority, TInt aPref) : + iCallback(aCallback), + iAudioPlayDeviceCommands(iController), + iAudioPlayControllerCommands(iController), + iNotificationRegistrationCommands(iController), + iDRMCustomCommands(iController), + iAudioPlayControllerSetRepeatsCommands(iController) + { + iState = EStopped; + iPrioritySettings.iPriority = aPriority; + iPrioritySettings.iPref = aPref; + iPlayStart = TTimeIntervalMicroSeconds(0); + iPlayEnd = TTimeIntervalMicroSeconds(0); + iPlayWindowSet = ENone; + iEventHolder = KNullUid; + } + +void CMMFMdaAudioPlayerUtility::ConstructL() + { + iControllerEventMonitor = CMMFControllerEventMonitor::NewL(*this, iController); + iRepeatTrailingSilenceTimer = CRepeatTrailingSilenceTimer::NewL(*this); + iAsyncCallBack = CMMFMdaAudioPlayerCallBack::NewL(iCallback); + User::LeaveIfError(iMediaIds.Append(KUidMediaTypeAudio)); + iFindAndOpenController = CMMFFindAndOpenController::NewL(*this); + iFindAndOpenController->Configure(iMediaIds[0], iPrioritySettings); + iFindAndOpenController->ConfigureController(iController, *iControllerEventMonitor, CMMFFindAndOpenController::EPlayback); + } + +void CMMFMdaAudioPlayerUtility::MfaocComplete( + TInt& aError, + RMMFController* /*aController*/, + TUid aControllerUid, + TMMFMessageDestination* /*aSourceHandle*/, + TMMFMessageDestination* /*aSinkHandle*/) + { + if (aError == KErrNone) + { + iControllerUid = aControllerUid; + + // Get the clip duration + iDuration = TTimeIntervalMicroSeconds(0); + aError = iController.GetDuration(iDuration); + + // If an error occurred during GetDuration, may try for next controller, if present. + if (aError != KErrNone) + { + iControllerEventMonitor->Cancel(); + + if (iFindAndOpenController) + { + if(iFindAndOpenController-> ControllerIndex() < (iFindAndOpenController->ControllerCount())-1) + { + return; //actually tries to load next controllers, if there are other controllers selected in the controller list + } + } + + iController.Close(); // otherwise close the controller + } + + if (iFindAndOpenController) + { + iFindAndOpenController->Close(); + } + } + + iAsyncCallBack->InitComplete(aError, iDuration); + } + +/** + Open an audio clip from a file + @param "const TFileSource& aFileSource" "the file to open" + @leave "" "Leaves on an error opening the file + @since version 5.0 +*/ +void CMMFMdaAudioPlayerUtility::OpenFileL(const TDesC& aFileName) + { + TMMFileSource filesource(aFileName, KDefaultContentObject, EPlay); + OpenFileL(filesource); + } + +/** + Open an audio clip from a file + @param "const RFile& aFile" "the shared session file handle to open" + @leave "" "KErrBadHandle if the file handle is not shared through the call RFs::ShareProtected(), and the underlying CAF layer needs it to be. + @leave "" "Leaves on an error opening the file + @since version 5.0 +*/ +void CMMFMdaAudioPlayerUtility::OpenFileL(const RFile& aFile) + { + RFile& file = const_cast(aFile); + TMMFileHandleSource filesource(file, KDefaultContentObject, EPlay); + OpenFileL(filesource); + } + +void CMMFMdaAudioPlayerUtility::OpenFileL(const TMMSource& aSource) + { + // If iAsyncCallBack is already active, we're still in the process of notifying the client + // that a previous request to Open...(...) has completed. + if (iAsyncCallBack->IsActive()) + User::Leave(KErrNotReady); + + if (aSource.SourceType()==KUidMMFileHandleSource) + { + RFile& fileHandle = static_cast(aSource).Handle(); + iFindAndOpenController->ConfigureSourceSink( + TMMFileHandleSource(fileHandle, aSource.UniqueId(), aSource.Intent(), aSource.IsUIEnabled()), + CMMFFindAndOpenController::TSourceSink(KUidMmfAudioOutput)); + + } + if (aSource.SourceType()==KUidMMFileSource) + { + const TDesC& fileName = static_cast(aSource).Name(); + iFindAndOpenController->ConfigureSourceSink( + TMMFileSource(fileName, aSource.UniqueId(), aSource.Intent(), aSource.IsUIEnabled()), + CMMFFindAndOpenController::TSourceSink(KUidMmfAudioOutput)); + } + + iFindAndOpenController->OpenByFileSource(aSource); + } + +/** + Open an audio clip from a descriptor + @param "const TDesC8& aDescriptor" "the descriptor containing the clip" + @leave "" "Leaves on an error opening the descriptor" + @since version 5.0 +*/ +void CMMFMdaAudioPlayerUtility::OpenDesL(const TDesC8& aDescriptor) + { + // If iAsyncCallBack is already active, we're still in the process of notifying the client + // that a previous request to Open...(...) has completed. + if (iAsyncCallBack->IsActive()) + User::Leave(KErrInUse); + + iFindAndOpenController->ConfigureSourceSink( + CMMFFindAndOpenController::TSourceSink(KUidMmfDescriptorSource, + CMMFFindAndOpenController::GetConfigDescriptor(aDescriptor)), + CMMFFindAndOpenController::TSourceSink(KUidMmfAudioOutput)); + iFindAndOpenController->OpenByDescriptor(aDescriptor); + } + +/** + Open an audio clip from a Url + @param "const TDesC& aUrl" "the url reference to the clip" + @leave "" "Leaves on an error opening the url" + @since version 7.0s +*/ +void CMMFMdaAudioPlayerUtility::OpenUrlL(const TDesC& aUrl, const TInt aIapId, const TDesC8& aMimeType) + { + // If iAsyncCallBack is already active, we're still in the process of notifying the client + // that a previous request to Open...(...) has completed. + if (iAsyncCallBack->IsActive()) + User::Leave(KErrInUse); + + CBufFlat* urlCfgBuffer = NULL; + CMMFFindAndOpenController::GetConfigUrlL(urlCfgBuffer, aUrl, aIapId); + + iFindAndOpenController->ConfigureSourceSink( + CMMFFindAndOpenController::TSourceSink(KUidMmfUrlSource, urlCfgBuffer->Ptr(0)), + CMMFFindAndOpenController::TSourceSink(KUidMmfAudioOutput)); + iFindAndOpenController->OpenByUrl(aUrl, aIapId, aMimeType); + delete urlCfgBuffer; + } + +/** +Begins playback of the initialised audio sample at the current volume +and priority levels. + +When playing of the audio sample is complete, successfully or +otherwise, the callback function +MMdaAudioPlayerCallback::MapcPlayComplete() is +called. + +If this function is called whilst already playing then +MMdaAudioPlayerCallback::MapcPlayComplete will return with the +error code KErrNotReady. + +@since 5.0 +*/ +void CMMFMdaAudioPlayerUtility::Play() + { + // if we're already playing, call the client's callback with KErrNotReady. + // This is what the controller would do if we allowed the Play() + // to propagate down. Need to do it here too (for consistency) + // in case we're in a trailing silence period. + if (iState == EPlaying) + { + iAsyncCallBack->PlayComplete(KErrNotReady); + return; + } + + // cancel the repeat timer in case the client has called Play() + // without waiting for the previous play to complete + iRepeatTrailingSilenceTimer->Cancel(); + // Reset played count + if(iState != EPaused) + { + iNumberOfTimesPlayed = 0; + if(iNumberOfTimesToRepeat>0 || iNumberOfTimesToRepeat == KMdaRepeatForever) + { + TInt err = iAudioPlayControllerSetRepeatsCommands.SetRepeats(iNumberOfTimesToRepeat, iTrailingSilence); + if(err==KErrNone) + { + iNumberOfTimesToRepeat = 0; + iTrailingSilence = 0; + } + //Controller not supporting setrepeats custom command is not a real error + //we revert back to playerutility's loop play implementation in that case + } + } + + DoPlay(); + } + +void CMMFMdaAudioPlayerUtility::DoPlay() + { +#if defined(__AUDIO_PROFILING) + RDebug::ProfileStart(4); +#endif // defined(__AUDIO_PROFILING) + TInt err = KErrNone; + if (iState != EPaused || iRepeatCancelled) + { + err = iController.Prime(); + iRepeatCancelled = EFalse; + +#if defined(__AUDIO_PROFILING) + RDebug::ProfileEnd(4); +#endif // defined(__AUDIO_PROFILING) + + // make sure we don't set the position outside the play window - + // but allow it to remain unchanged if it's within the window + if (iPlayWindowSet == ESet && + (iPosition < iPlayStart || iPosition >= iPlayEnd)) + iPosition = iPlayStart; + + if (err==KErrNone) + err = iController.SetPosition(iPosition); + } + + if (err==KErrNone) + { + if (iPlayWindowSet == ESet) + err = iAudioPlayControllerCommands.SetPlaybackWindow(iPlayStart, iPlayEnd); + else if (iPlayWindowSet == EClear) + { + err = iAudioPlayControllerCommands.DeletePlaybackWindow(); + iPlayWindowSet = ENone; // assume window will stay cleared + } + } + + if (err==KErrNone) + { +#if defined(__AUDIO_PROFILING) + RDebug::ProfileStart(5); +#endif // defined(__AUDIO_PROFILING) + + err = iController.Play(); + +#if defined(__AUDIO_PROFILING) + RDebug::ProfileEnd(5); +#endif // defined(__AUDIO_PROFILING) + } + + if (err!=KErrNone) + iAsyncCallBack->PlayComplete(err); + else + iState = EPlaying; + + if(iEventHolder != KNullUid) + { + err = iNotificationRegistrationCommands.RegisterAsClient(iEventHolder,iNotificationDataHolder); + iEventHolder = KNullUid; + iNotificationDataHolder = KNullDesC8; + if(err == KErrNotSupported) + { + return; + } + if(err != KErrNone) + { + iController.Stop(); + iAsyncCallBack->PlayComplete(err); + } + } + } + +/** +Stops playback of the audio sample as soon as possible. + +If the audio sample is playing, playback is stopped as soon as +possible. If playback is already complete, nothing further happens as +a result of calling this function. The callback function +MMdaAudioPlayerCallback::MapcPlayComplete() is not +called. + +@since 5.0 +*/ +void CMMFMdaAudioPlayerUtility::Stop() + { + + if (iState==EStopped) + { + // resetting the position to the start. + //if any position change in stoped state + iPosition = iPlayStart; + return; + } + + if (iState==EPlaying || iState==EPaused) + { + // cancel the repeat timer in case the client has called Stop() + // during the trailing silence period + iRepeatTrailingSilenceTimer->Cancel(); + + iController.Stop(); + iPosition = iPlayStart; + iState = EStopped; + } + + } + +/** + * + * Pauses playback of the audio clip + * @return One of the system-wide error codes + * @since 7.0s + */ +TInt CMMFMdaAudioPlayerUtility::Pause() + { + TInt err = KErrNone; + if(iRepeatTrailingSilenceTimer->IsActive()) + { + iRepeatTrailingSilenceTimer->Cancel(); + iRepeatCancelled = ETrue; + iState = EPaused; + return KErrNone; + } + if (iState==EPlaying) + { + err = iController.Pause(); + if (!err || err==KErrNotReady) + err = iController.GetPosition(iPosition); + iState = EPaused; + } + return err; + } + +/** + * + * Closes the current audio clip (allowing another clip to be opened) + * + * @since 7.0s + */ +void CMMFMdaAudioPlayerUtility::Close() + { + // Reset the audio player state. + Stop(); + iControllerEventMonitor->Cancel(); + iController.Close(); + if (iFindAndOpenController) + iFindAndOpenController->Close(); + if(iControllerImplementationInformation) + { + delete iControllerImplementationInformation; + iControllerImplementationInformation = NULL; + } + iControllerUid = KNullUid; + } + + +/** +Changes the current playback volume to a specified value. + +The volume can be changed before or during playback and is effective +immediately. + +@param aVolume + The volume setting. This can be any value from zero to + the value returned by a call to + CMdaAudioPlayerUtility::MaxVolume(). + Setting a zero value mutes the sound. Setting the + maximum value results in the loudest possible sound. +@return An error code indicating if the function call was successful. KErrNone on success, + otherwise another of the system-wide error codes. +@panic EMMFMediaClientBadArgument is raised when the audio player utility is not initialised. + +@since 5.0 +*/ +TInt CMMFMdaAudioPlayerUtility::SetVolume(TInt aVolume) + { + TInt err = iAudioPlayDeviceCommands.SetVolume(aVolume); + if (err == KErrArgument) + { + TInt maxVolume = MaxVolume(); + if (aVolume < 0) + { + aVolume = 0; + } + else if (aVolume > maxVolume) + { + aVolume = maxVolume; + } + err = iAudioPlayDeviceCommands.SetVolume(aVolume); + } + + return err; + } + +/** +Sets the number of times the audio sample is to be repeated during the +playback operation. + +A period of silence can follow each playing of the sample. The audio +sample can be repeated indefinitely. + +@param aRepeatNumberOfTimes + The number of times the audio sample, together with + the trailing silence, is to be repeated. If this is + set to KMdaRepeatForever, then the audio + sample, together with the trailing silence, is + repeated indefinitely or until Stop() is + called. If this is set to zero, then the audio sample + is not repeated. The behaviour is undefined for + negative values (other than KMdaRepeatForever). +@param aTrailingSilence + The time interval of the training silence. + Negative values will produce a panic USER 87. +@since 5.0 +*/ +void CMMFMdaAudioPlayerUtility::SetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence) + { + TInt err = iAudioPlayControllerSetRepeatsCommands.SetRepeats(aRepeatNumberOfTimes, aTrailingSilence); + + if(err!=KErrNone) + { + iNumberOfTimesToRepeat = aRepeatNumberOfTimes; + iTrailingSilence = aTrailingSilence; + } + } + +/** +Defines the period over which the volume level is to rise smoothly +from nothing to the normal volume level. + +@param aRampDuration + The period over which the volume is to rise. A zero + value causes the audio sample to be played at the + normal level for the full duration of the playback. A + value which is longer than the duration of the audio + sample means that the sample never reaches its normal + volume level. + +@since 5.0 +*/ +void CMMFMdaAudioPlayerUtility::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration) + { + iAudioPlayDeviceCommands.SetVolumeRamp(aRampDuration); + } + +TInt CMMFMdaAudioPlayerUtility::SetPriority(TInt aPriority, TInt aPref) + { + iPrioritySettings.iPref = aPref; + iPrioritySettings.iPriority = aPriority; + iFindAndOpenController->Configure(iMediaIds[0], iPrioritySettings); + + return iController.SetPrioritySettings(iPrioritySettings); + } + +/** +Returns the duration of the audio sample. + +@return The duration in microseconds. + +@since 5.0 +*/ +const TTimeIntervalMicroSeconds& CMMFMdaAudioPlayerUtility::Duration() + { + TInt err = iController.GetDuration(iDuration); + if (err) + { + iDuration = 0; + } + return iDuration; + } + +/** +Returns the duration of the audio sample in microseconds, and the duration state. + +@param aDuration + The duration of the sample in microseconds. +@return The duration state + +@since 9.1 +*/ +TMMFDurationInfo CMMFMdaAudioPlayerUtility::Duration(TTimeIntervalMicroSeconds& aDuration) +{ + TPckgBuf pckg; + TMMFDurationInfo result = EMMFDurationInfoValid; + + TMMFMessageDestinationPckg iDestinationPckg(TMMFMessageDestination(KUidInterfaceMMFDurationInfoControl, KMMFObjectHandleController)); + + TInt err = iController.CustomCommandSync(iDestinationPckg, + EMMFGetDurationInfo, + KNullDesC8, + KNullDesC8, + pckg ); + + switch ( err ) + { + case KErrNone: + result = pckg(); + break; + + case KErrNotSupported: + // Custom command not implemented return EMMFDurationInfoValid as the default value + break; + + default: + // Unknown error + result = EMMFDurationInfoUnknown; + break; + } + + // Get the duration information to return in aDuration + // This is the intended behaviour regardless of what value err has + aDuration = Duration(); + return result; +} + +/** +Returns an integer representing the maximum volume. + +This is the maximum value which can be passed to +CMdaAudioPlayerUtility::SetVolume(). + +@return The maximum volume. This value is platform dependent but is always greater than or equal + to one. +@panic EMMFMediaClientPanicServerCommunicationProblem is raised when the audio player utility is not initialised. + +@since 5.0 +*/ +TInt CMMFMdaAudioPlayerUtility::MaxVolume() + { + TInt maxVolume = 0; +#ifdef _DEBUG + TInt error = +#endif + iAudioPlayDeviceCommands.GetMaxVolume(maxVolume); + __ASSERT_DEBUG(error==KErrNone, Panic(EMMFMediaClientPanicServerCommunicationProblem)); + return maxVolume; + } + +void CMMFMdaAudioPlayerUtility::HandleEvent(const TMMFEvent& aEvent) + { + // handle loading started/complete messages first, as the later code does not explicitly check the event type + if (aEvent.iEventType == KMMFEventCategoryAudioLoadingStarted) + { + if (iLoadingObserver) + { + iLoadingObserver->MaloLoadingStarted(); + } + } + else if (aEvent.iEventType == KMMFEventCategoryAudioLoadingComplete) + { + if (iLoadingObserver) + { + iLoadingObserver->MaloLoadingComplete(); + } + } + else if (aEvent.iEventType == KMMFEventCategoryAudioResourceAvailable) + { + if (iAudioResourceNotificationCallBack != NULL) + { + TBuf8 notificationData; + if (KErrNone != iNotificationRegistrationCommands.GetResourceNotificationData(aEvent.iEventType, notificationData)) + { + notificationData.SetLength(0); + } + iAudioResourceNotificationCallBack->MarncResourceAvailable(aEvent.iEventType, notificationData); + } + } + else if (aEvent.iEventType == KMMFEventCategoryPlaybackComplete) + { + TInt oldState = iState; + //DevCR KEVN-7T5EHA: In case of pre-emption, we need to get the position from Controller, if that fails we reset the position to keep the original behaviour. + if(aEvent.iErrorCode == KErrInUse ||aEvent.iErrorCode == KErrDied ||aEvent.iErrorCode == KErrAccessDenied ) + { + TInt err= iController.GetPosition(iPosition); + if(err != KErrNone) + { + iPosition = iPlayStart; + } + } + else + { + iPosition = iPlayStart; + } + if (aEvent.iErrorCode == KErrNone) + { + //If we weren't playing, ignore the event. + if (oldState == EPlaying) + { + //we finished playing the clip so repeat if required + iNumberOfTimesPlayed++; + if ((iNumberOfTimesPlayed > iNumberOfTimesToRepeat) && (iNumberOfTimesToRepeat != KMdaRepeatForever)) + { + //we've repeated enough times now + iNumberOfTimesPlayed = 0; + iState = EStopped; + iCallback.MapcPlayComplete(KErrNone); + } + else + { + // We need to play silence, then repeat the clip + iTrailingSilenceLeftToPlay = iTrailingSilence; + PlaySilence(); + } + } + } + else + { //aEvent.iErrorCode != KErrNone + //if we weren't playing, don't advise Client. + iState = EStopped; + if (oldState == EPlaying) + { + iCallback.MapcPlayComplete(aEvent.iErrorCode); + } + } + } + else if(aEvent.iEventType == KMMFErrorCategoryControllerGeneralError) + { + TInt oldState = iState; + iPosition = iPlayStart; + iState = EStopped; + if (oldState == EPlaying) + { + iCallback.MapcPlayComplete(aEvent.iErrorCode); + } + } + // else we have an unexpected event that cannot be dealt with by the client. + // We will simply ignore this. + } + +void CMMFMdaAudioPlayerUtility::PlaySilence() + { + // iRepeatTrailingSilenceTimer->After() takes a TTimeIntervalMicroSeconds32 + // so for longer periods of silence call it repeatedly with KMaxTInt lengths + TTimeIntervalMicroSeconds32 silence; + if (iTrailingSilenceLeftToPlay.Int64() > KMaxTInt) + { + silence = KMaxTInt; + iTrailingSilenceLeftToPlay = iTrailingSilenceLeftToPlay.Int64() - KMaxTInt; + } + else + { + silence = I64INT(iTrailingSilenceLeftToPlay.Int64()); + iTrailingSilenceLeftToPlay = 0; + } + iRepeatTrailingSilenceTimer->After(silence); + } + +void CMMFMdaAudioPlayerUtility::RepeatTrailingSilenceTimerComplete() + { + if (iTrailingSilenceLeftToPlay.Int64() > 0) + { + PlaySilence(); + } + else + { + // reset the position for subsequent plays + iPosition = iPlayStart; + DoPlay(); + } + } + +/** + * + * Returns the current playback position in microseconds + * + * @param "TTimeIntervalMicroSeconds& aPosition" + * The current time position in microseconds from the start of the file + * @return "TInt" One of the global error codes + * + * @since 7.0s + */ +TInt CMMFMdaAudioPlayerUtility::GetPosition(TTimeIntervalMicroSeconds& aPosition) + { + TInt error = KErrNone; + if (iState==EPlaying) + error = iController.GetPosition(iPosition); + aPosition = iPosition; + return error; + } + +/** + * + * Set the current playback position in microseconds from the start of the file + * + * @param "TTimeIntervalMicroSeconds& aPosition" + * The position to move to in microseconds from the start of the file. + * If aPosition is negative, the position is set to the start of the file. + * If aPosition is greater than the file duration, the position is set to the + * end of the file. + * + * @since 7.0s + */ +void CMMFMdaAudioPlayerUtility::SetPosition(const TTimeIntervalMicroSeconds& aPosition) + { + // Clip the position if aPosition is greater than the duration + // or if aPosition is negative. + const TTimeIntervalMicroSeconds maxPosition(Duration()); + const TTimeIntervalMicroSeconds minPosition(0); + + if (aPosition > maxPosition) + iPosition = maxPosition; + else if (aPosition < minPosition) + iPosition = minPosition; + else + iPosition = aPosition; + + if (iState==EPlaying || iState==EPaused) + { + iController.SetPosition(iPosition); + } +// else if (iState == EPaused) +// { +// Stop(); // We call stop so that DevSound's internal buffers are reset +// } + } + +/** +Returns the current playback volume + +@param aVolume + A volume value between 0 and the value returned by MaxVolume(). + +@return One of the global error codes. + +@since 7.0s +*/ +TInt CMMFMdaAudioPlayerUtility::GetVolume(TInt& aVolume) + { + TInt error = iAudioPlayDeviceCommands.GetVolume(aVolume); + return error; + } + +/** + * + * Returns the number of meta data entries in the current clip + * + * @param "TInt& aNumEntries" + * The number of meta data entries in the header of the current clip + * @return "TInt" One of the global error codes + * + * @since 7.0s + */ +TInt CMMFMdaAudioPlayerUtility::GetNumberOfMetaDataEntries(TInt& aNumEntries) + { + TInt error = iController.GetNumberOfMetaDataEntries(aNumEntries); + return error; + } + +/** + * + * Returns the requested meta data entry + * + * @param "TInt aMetaDataIndex" + * The index number of the meta data to retrieve + * @return "CMMFMetaDataEntry*" The meta data entry to return + * @leave Leaves with KErrNotFound if the meta data entry does not exist or + * KErrNotImplemented if the controller does not support meta data + * information for this format. Other errors indicate more general system + * failure. + * + * @since 7.0s + */ +CMMFMetaDataEntry* CMMFMdaAudioPlayerUtility::GetMetaDataEntryL(TInt aMetaDataIndex) + { + return iController.GetMetaDataEntryL(aMetaDataIndex); + } + +/** + * + * Set the current playback window + * + * @param "const TTimeIntervalMicroSeconds& aStart" + * Start time of playback window relative to start of file + * @param "const TTimeIntervalMicroSeconds& aEnd" + * End time of playback window relative to start of file + * + * @return "TInt" One of the global error codes + * + * @since 7.0s + */ +TInt CMMFMdaAudioPlayerUtility::SetPlayWindow(const TTimeIntervalMicroSeconds& aPlayStart, + const TTimeIntervalMicroSeconds& aPlayEnd) + { + TInt error = KErrNone; + + if (aPlayStart >= TTimeIntervalMicroSeconds(0) && + aPlayStart < iDuration && + aPlayStart < aPlayEnd && + aPlayEnd <= iDuration ) + { + iPlayStart = aPlayStart; + iPlayEnd = aPlayEnd; + iPlayWindowSet = ESet; + + if (iState==EPlaying) + error = iAudioPlayControllerCommands.SetPlaybackWindow(aPlayStart, aPlayEnd); + } + else + error = KErrArgument; + + return error; + } + +/** + * + * Clear the current playback window + * + * @return "TInt" One of the global error codes + * + * @since 7.0s + */ +TInt CMMFMdaAudioPlayerUtility::ClearPlayWindow() + { + // clear play window start - very important because this is assigned + // to iPosition when we stop & is used to set the position on the next Play() + iPosition = iPlayStart = iPlayEnd = TTimeIntervalMicroSeconds(0); + + iPlayWindowSet = EClear; + TInt err = KErrNone; + if (iState==EPlaying) + err = iAudioPlayControllerCommands.DeletePlaybackWindow(); + return err; + } + +/** +Sets the current playback balance + +@param aBalance + A value between KMMFBalanceMaxLeft and KMMFBalanceMaxRight. The default value is + KMMFBalanceCenter. + +@return One of the global error codes. + +@since 7.0s +*/ +TInt CMMFMdaAudioPlayerUtility::SetBalance(TInt aBalance) + { + TInt err = iAudioPlayDeviceCommands.SetBalance(aBalance); + return err; + } + +/** +Returns the bit rate of the audio clip. + +@param aBitRate + Bit rate of the audio clip. + +@return One of the global error codes. + +@since 7.0s +*/ +TInt CMMFMdaAudioPlayerUtility::GetBitRate(TUint& aBitRate) + { + RMMFAudioControllerCustomCommands controller(iController); + TInt err = controller.GetSourceBitRate(aBitRate); + return err; + } + +const CMMFControllerImplementationInformation& CMMFMdaAudioPlayerUtility::ControllerImplementationInformationL() + { + if (!iControllerImplementationInformation) + { + if (iControllerUid==KNullUid) + User::Leave(KErrNotReady); + iControllerImplementationInformation = CMMFControllerImplementationInformation::NewL(iControllerUid); + } + return *iControllerImplementationInformation; + } + +void CMMFMdaAudioPlayerUtility::GetAudioLoadingProgressL(TInt& aPercentageProgress) + { + User::LeaveIfError(iAudioPlayControllerCommands.GetLoadingProgress(aPercentageProgress)); + } + +TInt CMMFMdaAudioPlayerUtility::CustomCommandSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TDes8& aDataFrom) + { + return iController.CustomCommandSync(aDestination, aFunction, aDataTo1, aDataTo2, aDataFrom); + } + +TInt CMMFMdaAudioPlayerUtility::CustomCommandSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2) + { + return iController.CustomCommandSync(aDestination, aFunction, aDataTo1, aDataTo2); + } + +void CMMFMdaAudioPlayerUtility::CustomCommandAsync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TDes8& aDataFrom, TRequestStatus& aStatus) + { + iController.CustomCommandAsync(aDestination, aFunction, aDataTo1, aDataTo2, aDataFrom, aStatus); + } + +void CMMFMdaAudioPlayerUtility::CustomCommandAsync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TRequestStatus& aStatus) + { + iController.CustomCommandAsync(aDestination, aFunction, aDataTo1, aDataTo2, aStatus); + } + +/** +Returns the current playback balance + +@param aBalance + A value between KMMFBalanceMaxLeft and KMMFBalanceMaxRight + +@return One of the global error codes. + +@since 7.0s +*/ +TInt CMMFMdaAudioPlayerUtility::GetBalance(TInt& aBalance) + { + TInt err = iAudioPlayDeviceCommands.GetBalance(aBalance); + return err; + } + +MMMFDRMCustomCommand* CMMFMdaAudioPlayerUtility::GetDRMCustomCommand() + { + // TODO: check controller supports MMMFDRMCustomCommandImplementor + if (iDRMCustomCommands.IsSupported()) + { + return static_cast(&iDRMCustomCommands); + } + else + { + return NULL; + } + } + +void CMMFMdaAudioPlayerUtility::RegisterForAudioLoadingNotification(MAudioLoadingObserver& aLoadingObserver) + { + iLoadingObserver = &aLoadingObserver; + } + +TInt CMMFMdaAudioPlayerUtility::RegisterAudioResourceNotification(MMMFAudioResourceNotificationCallback& aCallback, + TUid aNotificationEventUid, + const TDesC8& aNotificationRegistrationData) + { + iAudioResourceNotificationCallBack = &aCallback; + TInt err = iNotificationRegistrationCommands.RegisterAsClient(aNotificationEventUid, aNotificationRegistrationData); + if(err == KErrNotReady) + { + iEventHolder = aNotificationEventUid; + iNotificationDataHolder = aNotificationRegistrationData; + return KErrNone; + } + iNotificationDataHolder = KNullDesC8; + iEventHolder = KNullUid; + return err; + } + +TInt CMMFMdaAudioPlayerUtility::CancelRegisterAudioResourceNotification(TUid aNotificationEventId) + { + TInt err = iNotificationRegistrationCommands.CancelRegisterAsClient(aNotificationEventId); + if(err == KErrNotReady) + { + if(aNotificationEventId != KMMFEventCategoryAudioResourceAvailable) + { + return KErrNotSupported; + } + if(iEventHolder == KNullUid) + { + return KErrCancel; + } + iEventHolder = KNullUid; + iNotificationDataHolder = KNullDesC8; + return KErrNone; + } + return err; + } + +TInt CMMFMdaAudioPlayerUtility::WillResumePlay() + { + return iNotificationRegistrationCommands.WillResumePlay(); + } + +TInt CMMFMdaAudioPlayerUtility::SetThreadPriority(const TThreadPriority& aThreadPriority) const + { + return iController.SetThreadPriority(aThreadPriority); + } + +CRepeatTrailingSilenceTimer* CRepeatTrailingSilenceTimer::NewL(MRepeatTrailingSilenceTimerObs& aObs) + { + CRepeatTrailingSilenceTimer* s = new(ELeave) CRepeatTrailingSilenceTimer(aObs); + CleanupStack::PushL(s); + s->ConstructL(); + CleanupStack::Pop(); + return s; + } + +void CRepeatTrailingSilenceTimer::RunL() + { + iObs.RepeatTrailingSilenceTimerComplete(); + } + +CRepeatTrailingSilenceTimer::CRepeatTrailingSilenceTimer(MRepeatTrailingSilenceTimerObs& aObs) : + CTimer(EPriorityHigh), + iObs(aObs) + { + CActiveScheduler::Add(this); + } + + + +CMMFMdaAudioPlayerCallBack* CMMFMdaAudioPlayerCallBack::NewL(MMdaAudioPlayerCallback& aCallback) + { + return new(ELeave) CMMFMdaAudioPlayerCallBack(aCallback); + } + +CMMFMdaAudioPlayerCallBack::CMMFMdaAudioPlayerCallBack(MMdaAudioPlayerCallback& aCallback) : + CActive(CActive::EPriorityHigh), iCallback(aCallback) + { + CActiveScheduler::Add(this); + } + +CMMFMdaAudioPlayerCallBack::~CMMFMdaAudioPlayerCallBack() + { + Cancel(); + } + +void CMMFMdaAudioPlayerCallBack::InitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration) + { + iError = aError; + iDuration = aDuration; + iState = ECallbackInitComplete; + if (!IsActive()) + { + TRequestStatus* s = &iStatus; + SetActive(); + User::RequestComplete(s, KErrNone); + } + } + +void CMMFMdaAudioPlayerCallBack::PlayComplete(TInt aError) + { + iError = aError; + iState = ECallbackPlayComplete; + if (!IsActive()) + { + TRequestStatus* s = &iStatus; + SetActive(); + User::RequestComplete(s, KErrNone); + } + } + +void CMMFMdaAudioPlayerCallBack::RunL() + { + switch (iState) + { + case ECallbackInitComplete: + iCallback.MapcInitComplete(iError, iDuration); + break; + case ECallbackPlayComplete: + iCallback.MapcPlayComplete(iError); + break; + } + } + +void CMMFMdaAudioPlayerCallBack::DoCancel() + { + // Nothing to cancel + } diff -r 320024dcf7b6 -r 657f02e590f1 breakdeps/mmfclientaudioplayer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/mmfclientaudioplayer.h Wed Oct 20 13:05:58 2010 +0100 @@ -0,0 +1,261 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + + +#ifndef MMFCLIENTAUDIOPLAY_H +#define MMFCLIENTAUDIOPLAY_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mmfclientutility.h" +#include + +static const TUid KUidMmfAudioController = {KMmfUidControllerAudio}; + +/** +Mixin class to allow notification that the timed silence has finished. +*/ +class MRepeatTrailingSilenceTimerObs + { +public: + virtual void RepeatTrailingSilenceTimerComplete() = 0; + }; + +/** +CTimer-based active object that waits the requested time before notifying its observer. +*/ +class CRepeatTrailingSilenceTimer : public CTimer + { +public: + static CRepeatTrailingSilenceTimer* NewL(MRepeatTrailingSilenceTimerObs& aObs); + void RunL(); +private: + CRepeatTrailingSilenceTimer(MRepeatTrailingSilenceTimerObs& aObs); +private: + MRepeatTrailingSilenceTimerObs& iObs; + }; + +/** +Active object utility class to allow the callback to be called asynchronously. +This should help prevent re-entrant code in clients of the mediaframework. +*/ +class CMMFMdaAudioPlayerCallBack : public CActive + { +public: + enum TCallbackState { + ECallbackInitComplete, + ECallbackPlayComplete + }; + + +public: + static CMMFMdaAudioPlayerCallBack* NewL(MMdaAudioPlayerCallback& aCallback); + ~CMMFMdaAudioPlayerCallBack(); + void InitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration); + void PlayComplete(TInt aError); +private: + CMMFMdaAudioPlayerCallBack(MMdaAudioPlayerCallback& aCallback); + void RunL(); + void DoCancel(); +private: + MMdaAudioPlayerCallback& iCallback; + TInt iError; + TTimeIntervalMicroSeconds iDuration; + TCallbackState iState; + }; + +/** +Concrete implementation of the CMdaAudioPlayerUtility API. +@see CMdaAudioPlayerUtility +*/ +class CMMFMdaAudioPlayerUtility; +NONSHARABLE_CLASS( CMMFMdaAudioPlayerUtility ): public CBase, + public MMMFControllerEventMonitorObserver, + public MRepeatTrailingSilenceTimerObs, + public MMMFFindAndOpenControllerObserver + { +friend class CMdaAudioPlayerUtility; +// friends for Unit testing only +friend class CTestStepUnitMMFAudClient; + +public: + enum TMMFAudioPlayerState + { + EStopped, + EOpening, + EPaused, + EPlaying + }; +public: + static CMMFMdaAudioPlayerUtility* NewFilePlayerL(const TDesC& aFileName, + MMdaAudioPlayerCallback& aCallback, + TInt aPriority = EMdaPriorityNormal, + TInt aPref = EMdaPriorityPreferenceTimeAndQuality, + CMdaServer* aServer = NULL); + static CMMFMdaAudioPlayerUtility* NewDesPlayerL(const TDesC8& aData, + MMdaAudioPlayerCallback& aCallback, + TInt aPriority = EMdaPriorityNormal, + TInt aPref = EMdaPriorityPreferenceTimeAndQuality, + CMdaServer* aServer = NULL); + static CMMFMdaAudioPlayerUtility* NewDesPlayerReadOnlyL(const TDesC8& aData, + MMdaAudioPlayerCallback& aCallback, + TInt aPriority = EMdaPriorityNormal, + TInt aPref = EMdaPriorityPreferenceTimeAndQuality, + CMdaServer* aServer = NULL); + + static CMMFMdaAudioPlayerUtility* NewL(MMdaAudioPlayerCallback& aCallback, + TInt aPriority = EMdaPriorityNormal, + TInt aPref = EMdaPriorityPreferenceTimeAndQuality); + +/** + Destructor +*/ + ~CMMFMdaAudioPlayerUtility(); + + void UseSharedHeap(); + + void OpenFileL(const TDesC& aFileName); + void OpenFileL(const RFile& aFile); + void OpenFileL(const TMMSource& aSource); + + void OpenDesL(const TDesC8& aDescriptor); + void OpenUrlL(const TDesC& aUrl, TInt aIapId=KUseDefaultIap, const TDesC8& aMimeType = KNullDesC8); + void Play(); + void Stop(); + TInt SetVolume(TInt aVolume); + void SetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence); + void SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration); + const TTimeIntervalMicroSeconds& Duration(); + TInt MaxVolume(); + + // API Additions since version 7.0 + TInt Pause(); + void Close(); + TInt GetPosition(TTimeIntervalMicroSeconds& aPosition); + void SetPosition(const TTimeIntervalMicroSeconds& aPosition); + + TInt SetPriority(TInt aPriority, TInt aPref); + TInt GetVolume(TInt& aVolume); + TInt GetNumberOfMetaDataEntries(TInt& aNumEntries); + CMMFMetaDataEntry* GetMetaDataEntryL(TInt aMetaDataIndex); + TInt SetPlayWindow(const TTimeIntervalMicroSeconds& aStart, + const TTimeIntervalMicroSeconds& aEnd); + TInt ClearPlayWindow(); + TInt SetBalance(TInt aBalance = KMMFBalanceCenter); + TInt GetBalance(TInt& aBalance); + TInt GetBitRate(TUint& aBitRate); + + void RegisterForAudioLoadingNotification(MAudioLoadingObserver& aCallback); + void GetAudioLoadingProgressL(TInt& aPercentageProgress); + const CMMFControllerImplementationInformation& ControllerImplementationInformationL(); + + TInt RegisterAudioResourceNotification(MMMFAudioResourceNotificationCallback& aCallback,TUid aNotificationEventUid,const TDesC8& aNotificationRegistrationData = KNullDesC8); + TInt CancelRegisterAudioResourceNotification(TUid aNotificationEventId); + TInt WillResumePlay(); + TInt CustomCommandSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TDes8& aDataFrom); + TInt CustomCommandSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2); + void CustomCommandAsync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TDes8& aDataFrom, TRequestStatus& aStatus); + void CustomCommandAsync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TRequestStatus& aStatus); + + MMMFDRMCustomCommand* GetDRMCustomCommand(); + + TInt SetThreadPriority(const TThreadPriority& aThreadPriority) const; + + TMMFDurationInfo Duration(TTimeIntervalMicroSeconds& aDuration); + + // from MMMFControllerEventMonitorObserver + virtual void HandleEvent(const TMMFEvent& aEvent); + // from MRepeatTrailingSilenceTimerObs + virtual void RepeatTrailingSilenceTimerComplete(); + + // from MMMFFindAndOpenControllerObserver + virtual void MfaocComplete( + TInt& aError, + RMMFController* aController, + TUid aControllerUid, + TMMFMessageDestination* aSourceHandle, + TMMFMessageDestination* aSinkHandle); + +protected: + CMMFMdaAudioPlayerUtility(MMdaAudioPlayerCallback& aCallback, TInt aPriority, TInt aPref); + void ConstructL(); + void DoPlay(); + +private: + void PlaySilence(); + +private: + // last play window command + enum TPlayWindowCommand + { + ENone, + ESet, + EClear + }; + + MMdaAudioPlayerCallback& iCallback; + CMMFMdaAudioPlayerCallBack* iAsyncCallBack; + MAudioLoadingObserver* iLoadingObserver; + MMMFAudioResourceNotificationCallback* iAudioResourceNotificationCallBack; + RMMFController iController; + CMMFControllerEventMonitor* iControllerEventMonitor; + TMMFAudioPlayerState iState; + TTimeIntervalMicroSeconds iDuration; // Needed because of api "Duration()" that returns a reference + TMMFPrioritySettings iPrioritySettings; + + TInt iNumberOfTimesPlayed; + TInt iNumberOfTimesToRepeat; + TTimeIntervalMicroSeconds iTrailingSilence; + TTimeIntervalMicroSeconds iTrailingSilenceLeftToPlay; + CRepeatTrailingSilenceTimer* iRepeatTrailingSilenceTimer; + + // Source and sink handle info + TMMFMessageDestination iSourceHandle; + TMMFMessageDestination iSinkHandle; + + // Custom command handlers + RMMFAudioPlayDeviceCustomCommands iAudioPlayDeviceCommands; + RMMFAudioPlayControllerCustomCommands iAudioPlayControllerCommands; + RMMFResourceNotificationCustomCommands iNotificationRegistrationCommands; + RMMFDRMCustomCommands iDRMCustomCommands; + RMMFAudioPlayControllerSetRepeatsCustomCommands iAudioPlayControllerSetRepeatsCommands; + + // Current playback time so we can resume from where we were stopped + TTimeIntervalMicroSeconds iPosition; + + // Play window start and end times and whether it has been set + TTimeIntervalMicroSeconds iPlayStart; + TTimeIntervalMicroSeconds iPlayEnd; + TPlayWindowCommand iPlayWindowSet; + RArray iMediaIds; + + CMMFControllerImplementationInformation* iControllerImplementationInformation; + TUid iControllerUid; + + // utility class to find and open a suitable controller asynchronously + CMMFFindAndOpenController* iFindAndOpenController; + TUid iEventHolder; + TBuf8<256> iNotificationDataHolder; + TBool iRepeatCancelled; + }; + +#endif diff -r 320024dcf7b6 -r 657f02e590f1 breakdeps/mmfclienttoneplayer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/mmfclienttoneplayer.cpp Wed Oct 20 13:05:58 2010 +0100 @@ -0,0 +1,1442 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include + +#include "mmfclienttoneplayer.h" +using namespace ContentAccess; +enum TMmfMdaAudioToneUtility + { + EBadArgument, + EPostConditionViolation, + EPlayStartedCalledWithError + }; + +// declared in the recorder module +void Panic(TInt aPanicCode); + +/** +Creates a new instance of the tone player utility. +The default volume is set to MaxVolume() / 2. + +@param aObserver + A class to receive notifications from the tone player. +@param aServer + This parameter is no longer used and should be NULL. + +@return A pointer to the new audio tone player utility object. + +@since 5.0 +*/ +EXPORT_C CMdaAudioToneUtility* CMdaAudioToneUtility::NewL(MMdaAudioToneObserver& aObserver, CMdaServer* aServer /*= NULL*/) + { + return CMdaAudioToneUtility::NewL(aObserver, aServer, EMdaPriorityNormal, EMdaPriorityPreferenceTimeAndQuality); + } + +/** +Creates a new instance of the tone player utility. +The default volume is set to MaxVolume() / 2. + +@param aObserver + A class to receive notifications from the tone player +@param aServer + This parameter is no longer used and should be NULL +@param aPriority + The Priority Value - this client's relative priority. This is a value between EMdaPriorityMin and + EMdaPriorityMax and represents a relative priority. A higher value indicates a more important request. +@param aPref + The Priority Preference - an additional audio policy parameter. The suggested default is + EMdaPriorityPreferenceNone. Further values are given by TMdaPriorityPreference, and additional + values may be supported by given phones and/or platforms, but should not be depended upon by + portable code. + +@return A pointer to the new audio tone player utility object. + +@since 5.0 + +Note: The Priority Value and Priority Preference are used primarily when deciding what to do when +several audio clients attempt to play or record simultaneously. In addition to the Priority Value and Preference, +the adaptation may consider other parameters such as the SecureId and Capabilities of the client process. +Whatever, the decision as to what to do in such situations is up to the audio adaptation, and may +vary between different phones. Portable applications are advised not to assume any specific behaviour. +*/ +EXPORT_C CMdaAudioToneUtility* CMdaAudioToneUtility::NewL(MMdaAudioToneObserver& aObserver, CMdaServer* /*aServer = NULL*/, + TInt aPriority /*= EMdaPriorityNormal*/, + TInt aPref /*= EMdaPriorityPreferenceTimeAndQuality*/) + { + CMdaAudioToneUtility* self = new(ELeave) CMdaAudioToneUtility(); + CleanupStack::PushL(self); + self->iProperties = CMMFMdaAudioToneUtility::NewL(aObserver, NULL, aPriority, aPref); + CleanupStack::Pop(); //self + return self; + } + +/** +Destructor. Frees any resources held by the tone player + +@since 5.0 +*/ +CMdaAudioToneUtility::~CMdaAudioToneUtility() + { + delete iProperties; + } + +/** +Returns the current state of the audio tone utility. + +@return The state of the audio tone utility. + +@since 5.0 +*/ +TMdaAudioToneUtilityState CMdaAudioToneUtility::State() + { + ASSERT(iProperties); + return iProperties->State(); + } + +/** +Returns the maximum volume supported by the device. This is the maximum value which can be +passed to CMdaAudioToneUtility::SetVolume(). + +@return The maximum volume. This value is platform dependent but is always greater than or equal to one. + +@since 5.0 +*/ +TInt CMdaAudioToneUtility::MaxVolume() + { + ASSERT(iProperties); + return iProperties->MaxVolume(); + } + +/** +Returns an integer representing the current volume of the audio device. + +@return The current volume. + +@since 5.0 +*/ +TInt CMdaAudioToneUtility::Volume() + { + ASSERT(iProperties); + return iProperties->Volume(); + } + +/** +Changes the volume of the audio device. + +The volume can be changed before or during play and is effective +immediately. + +@param aVolume + The volume setting. This can be any value from zero to + the value returned by a call to + CMdaAudioToneUtility::MaxVolume(). + Setting a zero value mutes the sound. Setting the + maximum value results in the loudest possible sound. + +@since 5.0 +*/ +void CMdaAudioToneUtility::SetVolume(TInt aVolume) + { + ASSERT(iProperties); + iProperties->SetVolume(aVolume); + } + +/** +Changes the clients priority. + +@param aPriority + The Priority Value. +@param aPref + The Priority Preference. + +@see CMdaAudioToneUtility::NewL() + +@since 5.0 + +*/ +void CMdaAudioToneUtility::SetPriority(TInt aPriority, TInt aPref) + { + ASSERT(iProperties); + iProperties->SetPriority(aPriority, aPref); + } + +/** +Changes the duration of DTMF tones, the gaps between DTMF tones and the +pauses. + +@param aToneLength + The duration of the DTMF tone in microseconds. +@param aToneOffLength + The gap between DTFM tones in microseconds. +@param aPauseLength + Pauses in microseconds +*/ +void CMdaAudioToneUtility::SetDTMFLengths(TTimeIntervalMicroSeconds32 aToneLength, + TTimeIntervalMicroSeconds32 aToneOffLength, + TTimeIntervalMicroSeconds32 aPauseLength) + { + ASSERT(iProperties); + iProperties->SetDTMFLengths(aToneLength, aToneOffLength, aPauseLength); + } + +/** +Sets the number of times the tone sequence is to be repeated during +the play operation. + +A period of silence can follow each playing of the tone sequence. The +tone sequence can be repeated indefinitely. + +@param aRepeatNumberOfTimes + The number of times the tone sequence, together with + the trailing silence, is to be repeated. If this is + set to KMdaRepeatForever, then the tone + sequence, together with the trailing silence, is + repeated indefinitely. The behaviour is undefined for values other than + KMdaRepeatForever, zero and positive. +@param aTrailingSilence + The time interval of the training silence. The behaviour is undefined + for values other than zero and positive. + +@since 5.0 +*/ +void CMdaAudioToneUtility::SetRepeats(TInt aRepeatNumberOfTimes, + const TTimeIntervalMicroSeconds& aTrailingSilence) + { + ASSERT(iProperties); + iProperties->SetRepeats(aRepeatNumberOfTimes, aTrailingSilence); + } + +/** +Defines the period over which the volume level is to rise smoothly +from nothing to the normal volume level. + +@param aRampDuration + The period over which the volume is to rise. A zero + value causes the tone to be played at the normal level + for the full duration of the playback. A value which + is longer than the duration of the tone sequence means + that the tone never reaches its normal volume level. + +@since 5.0 +*/ +void CMdaAudioToneUtility::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration) + { + ASSERT(iProperties); + iProperties->SetVolumeRamp(aRampDuration); + } + +/** +Returns the number of available pre-defined tone sequences. + +@return The number of tone sequences. This value is implementation + dependent but is always greater than or equal to zero. + +@since 5.0 +*/ +TInt CMdaAudioToneUtility::FixedSequenceCount() + { + ASSERT(iProperties); + return iProperties->FixedSequenceCount(); + } + +/** +Returns the name assigned to a specific pre-defined tone sequence. + +@param aSequenceNumber + The index identifying the specific pre-defined tone sequence. + Index values are relative to zero. This can be any value from + zero to the value returned by a call to FixedSequenceCount() - 1. + The function raises a panic if sequence number is not within this + range. + +@see CMMFDevSound::FixedSequenceName(TInt aSequenceNumber) +@see FixedSequenceCount() + +@return The name assigned to the tone sequence. + +@since 5.0 +*/ +const TDesC& CMdaAudioToneUtility::FixedSequenceName(TInt aSequenceNumber) + { + ASSERT(iProperties); + return iProperties->FixedSequenceName(aSequenceNumber); + } + +/** +Configures the audio tone player utility to play a single tone. + +This function is asynchronous. On completion, the observer callback +function MMdaAudioToneObserver::MatoPrepareComplete() is +called, indicating the success or failure of the configuration +operation.The configuration operation can be cancelled by calling +CMdaAudioToneUtility::CancelPrepare(). The configuration +operation cannot be started if a play operation is in progress. + +@param aFrequency + The frequency (pitch) of the tone in Hz. +@param aDuration + The duration of the tone in microseconds. +@since 5.0 +*/ +void CMdaAudioToneUtility::PrepareToPlayTone(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration) + { + ASSERT(iProperties); + iProperties->PrepareToPlayTone(aFrequency, aDuration); + } + +/** +Configures the audio tone player utility to play a dual tone. +The generated tone consists of two sine waves of different +frequencies summed together. + +This function is asynchronous. On completion, the observer callback +function MMdaAudioToneObserver::MatoPrepareComplete() is +called, indicating the success or failure of the configuration +operation. The configuration operation can be cancelled by calling +CMdaAudioToneUtility::CancelPrepare(). The configuration +operation cannot be started if a play operation is in progress. + +@param aFrequencyOne + The first frequency (pitch) of the tone. +@param aFrequencyTwo + The second frequency (pitch) of the tone. +@param aDuration + The duration of the tone in microseconds. + +@since 7.0sy +*/ +EXPORT_C void CMdaAudioToneUtility::PrepareToPlayDualTone(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration) + { + ASSERT(iProperties); + iProperties->PrepareToPlayDualTone(aFrequencyOne, aFrequencyTwo, aDuration); + } + +/** +Configures the audio tone utility player to play a DTMF (Dual-Tone +Multi-Frequency) string. + +This function is asynchronous. On completion, the observer callback +function MMdaAudioToneObserver::MatoPrepareComplete() is +called, indicating the success or failure of the configuration +operation. The configuration operation can be cancelled by calling +CMdaAudioToneUtility::CancelPrepare(). The configuration +operation cannot be started if a play operation is in progress. + +@param aDTMF + A descriptor containing the DTMF string. + +@since 5.0 +*/ +void CMdaAudioToneUtility::PrepareToPlayDTMFString(const TDesC& aDTMF) + { + ASSERT(iProperties); + iProperties->PrepareToPlayDTMFString(aDTMF); + } + +/** +Configures the audio tone player utility to play a tone sequence +contained in a descriptor. + +This function is asynchronous. On completion, the observer callback +function MMdaAudioToneObserver::MatoPrepareComplete() is +called, indicating the success or failure of the configuration +operation. The configuration operation can be cancelled by calling +CMdaAudioToneUtility::CancelPrepare(). The configuration +operation cannot be started if a play operation is in progress. + +@param aSequence + The descriptor containing the tone sequence. The + format of the data is unspecified but is expected to + be platform dependent. A device might support more + than one form of sequence data. + +@since 5.0 +*/ +void CMdaAudioToneUtility::PrepareToPlayDesSequence(const TDesC8& aSequence) + { + ASSERT(iProperties); + iProperties->PrepareToPlayDesSequence(aSequence); + } + +/** +Configures the audio tone player utility to play a tone sequence +contained in a file. + +This function is asynchronous. On completion, the observer callback +function MMdaAudioToneObserver::MatoPrepareComplete() is +called, indicating the success or failure of the configuration +operation. The configuration operation can be cancelled by calling +CMdaAudioToneUtility::CancelPrepare(). The configuration +operation cannot be started if a play operation is in progress. + +@param aFileName + The full path name of the file containing the tone + sequence. The format of the data is unspecified but is + expected to be platform dependent. A device might + support more than one form of sequence data. + +@since 5.0 +*/ +void CMdaAudioToneUtility::PrepareToPlayFileSequence(const TDesC& aFileName) + { + ASSERT(iProperties); + iProperties->PrepareToPlayFileSequence(aFileName); + } + +/** +Configures the audio tone player utility to play a tone sequence +contained in a file. + +This function is asynchronous. On completion, the observer callback +function MMdaAudioToneObserver::MatoPrepareComplete() is +called, indicating the success or failure of the configuration +operation. The configuration operation can be cancelled by calling +CMdaAudioToneUtility::CancelPrepare(). The configuration +operation cannot be started if a play operation is in progress. + +@param aFile + A handle to an open file containing the tone + sequence. The format of the data is unspecified but is + expected to be platform dependent. A device might + support more than one form of sequence data. + +@since 5.0 +*/ +EXPORT_C void CMdaAudioToneUtility::PrepareToPlayFileSequence(RFile& aFile) + { + ASSERT(iProperties); + iProperties->PrepareToPlayFileSequence(aFile); + } + + +/** +Configures the audio tone player utility to play the specified +pre-defined tone sequence. + +This function is asynchronous. On completion, the observer callback +function MMdaAudioToneObserver::MatoPrepareComplete() is +called, indicating the success or failure of the configuration +operation. The configuration operation can be cancelled by calling +CMdaAudioToneUtility::CancelPrepare(). The configuration +operation cannot be started if a play operation is in progress. + +@param aSequenceNumber + An index into the set of pre-defined tone sequences. + This can be any value from zero to the value returned by a + call to FixedSequenceCount() - 1. + If the sequence number is not within this range, a panic will be + raised when Play() is called later. + +@see FixedSequenceCount() +@see CMMFDevSound::PlayFixedSequenceL(TInt aSequenceNumber) + +@since 5.0 +*/ +void CMdaAudioToneUtility::PrepareToPlayFixedSequence(TInt aSequenceNumber) + { + ASSERT(iProperties); + iProperties->PrepareToPlayFixedSequence(aSequenceNumber); + } + +/** +Cancels the configuration operation. + +The observer callback function +MMdaAudioToneObserver::MatoPrepareComplete() is not +called. + +@since 5.0 +*/ +void CMdaAudioToneUtility::CancelPrepare() + { + ASSERT(iProperties); + iProperties->CancelPrepare(); + } + +/** +Plays the tone. + +The tone played depends on the current configuration.This function is +asynchronous. On completion, the observer callback function +MMdaAudioToneObserver::MatoPlayComplete() is called, +indicating the success or failure of the play operation.The play +operation can be cancelled by +calling CMdaAudioToneUtility::CancelPlay(). + +@since 5.0 +*/ +void CMdaAudioToneUtility::Play() + { + ASSERT(iProperties); + iProperties->Play(); + } + +EXPORT_C TInt CMdaAudioToneUtility::Pause() + { + ASSERT(iProperties); + return iProperties->Pause(); + } + +EXPORT_C TInt CMdaAudioToneUtility::Resume() + { + ASSERT(iProperties); + return iProperties->Resume(); + } + +/** +Cancels the tone playing operation. + +The observer callback +function MMdaAudioToneObserver::MatoPlayComplete() is not +called. + +@since 5.0 +*/ +void CMdaAudioToneUtility::CancelPlay() + { + ASSERT(iProperties); + iProperties->CancelPlay(); + } + +/** +Sets the stereo balance for playback. + +@param aBalance + The balance. Should be between KMMFBalanceMaxLeft and KMMFBalanceMaxRight. + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. + +@since 7.0s +*/ +EXPORT_C void CMdaAudioToneUtility::SetBalanceL(TInt aBalance /*=KMMFBalanceCenter*/) + { + ASSERT(iProperties); + iProperties->SetBalanceL(aBalance); + } + +/** + * Returns The current playback balance.This function may not return the same value + * as passed to SetBalanceL depending on the internal implementation in + * the underlying components. + * + * @return The balance. Should be between KMMFBalanceMaxLeft and KMMFBalanceMaxRight. + * + * @since 7.0s + */ +EXPORT_C TInt CMdaAudioToneUtility::GetBalanceL() + { + ASSERT(iProperties); + return iProperties->GetBalanceL(); + } + +/** +Retrieves a custom interface to the underlying device. + +@param aInterfaceId + The interface UID, defined with the custom interface. + +@return A pointer to the interface implementation, or NULL if the device does not + implement the interface requested. The return value must be cast to the + correct type by the user. +*/ +EXPORT_C TAny* CMdaAudioToneUtility::CustomInterface(TUid aInterfaceId) + { + ASSERT(iProperties); + return iProperties->CustomInterface(aInterfaceId); + } + +EXPORT_C void CMdaAudioToneUtility::RegisterPlayStartCallback(MMdaAudioTonePlayStartObserver& aObserver) + { + ASSERT(iProperties); + iProperties->RegisterPlayStartCallback(aObserver); + } + + + +CMMFMdaAudioToneUtility* CMMFMdaAudioToneUtility::NewL(MMdaAudioToneObserver& aObserver, CMdaServer* /*aServer = NULL*/, + TInt aPriority /*= EMdaPriorityNormal*/, + TInt aPref /*= EMdaPriorityPreferenceTimeAndQuality*/) + + { + CMMFMdaAudioToneUtility* self = new(ELeave) CMMFMdaAudioToneUtility(aObserver, aPriority, aPref); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + + +CMMFMdaAudioToneUtility::CMMFMdaAudioToneUtility(MMdaAudioToneObserver& aCallback, TInt aPriority, TInt aPref) : + iCallback(aCallback) + { + iPrioritySettings.iPref = aPref; + iPrioritySettings.iPriority = aPriority; + iState = EMdaAudioToneUtilityNotReady; + iInitialized = EFalse; + iPlayCalled = EFalse; + +#ifdef _DEBUG + iPlayCalledBeforeInitialized = EFalse; +#endif + } + +void CMMFMdaAudioToneUtility::ConstructL() + { + iAsyncCallback = CMMFMdaAudioToneObserverCallback::NewL(*this, *this); + + iDevSound = CMMFDevSound::NewL(); + iDevSound->InitializeL(*this,EMMFStateTonePlaying); + + // In some implementations InitializeComplete() returns in the InitializeL() context, + // check the error + User::LeaveIfError(iInitializeState); + + iDevSound->SetPrioritySettings(iPrioritySettings); + SetVolume(MaxVolume()/2 ); // set the volume to an intermediate value + } + +CMMFMdaAudioToneUtility::~CMMFMdaAudioToneUtility() + { + delete iDevSound; + delete iAsyncCallback; + delete iToneConfig; + } + + + +void CMMFMdaAudioToneUtility::InitializeComplete(TInt aError) + { +#ifdef _DEBUG + __ASSERT_ALWAYS(!iPlayCalledBeforeInitialized, User::Panic(_L("PlayInitialized called before InitializeComplete"), 0)); +#endif + iInitialized = ETrue; + + if (iPlayCalled) + { + // Play() is called before InitializeComplete() + if (aError == KErrNone) + { + PlayAfterInitialized(); + } + else + { + // InitializeComplete() with error other than KErrNone + iState = EMdaAudioToneUtilityNotReady; + iAsyncCallback->MatoPlayComplete(aError); + } + iPlayCalled = EFalse; + } + iInitializeState = aError; + } + +void CMMFMdaAudioToneUtility::ToneFinished(TInt aError) + { + if (aError != KErrCancel) + { + if (aError == KErrUnderflow) + { + aError = KErrNone; + } + + iAsyncCallback->MatoPlayComplete(aError); + } + // else don't want to callback after a cancel + } + + +TMdaAudioToneUtilityState CMMFMdaAudioToneUtility::State() + { + return iState; + } + +TInt CMMFMdaAudioToneUtility::MaxVolume() + { + return iDevSound->MaxVolume(); + } + +TInt CMMFMdaAudioToneUtility::Volume() + { + return iDevSound->Volume(); + } + +void CMMFMdaAudioToneUtility::SetVolume(TInt aVolume) + { + iDevSound->SetVolume(aVolume); + } + +void CMMFMdaAudioToneUtility::SetPriority(TInt aPriority, TInt aPref) + { + iPrioritySettings.iPref = aPref; + iPrioritySettings.iPriority = aPriority; + iDevSound->SetPrioritySettings(iPrioritySettings); + } + +void CMMFMdaAudioToneUtility::SetDTMFLengths(TTimeIntervalMicroSeconds32 aToneLength, + TTimeIntervalMicroSeconds32 aToneOffLength, + TTimeIntervalMicroSeconds32 aPauseLength) + { + iDevSound->SetDTMFLengths(aToneLength, aToneOffLength, aPauseLength); + } + +void CMMFMdaAudioToneUtility::SetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence) + { + iDevSound->SetToneRepeats(aRepeatNumberOfTimes, aTrailingSilence); + } + +void CMMFMdaAudioToneUtility::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration) + { + iDevSound->SetVolumeRamp(aRampDuration); + } + +TInt CMMFMdaAudioToneUtility::FixedSequenceCount() + { + return iDevSound->FixedSequenceCount(); + } + +const TDesC& CMMFMdaAudioToneUtility::FixedSequenceName(TInt aSequenceNumber) + { + return iDevSound->FixedSequenceName(aSequenceNumber); + } + +/** +* CalculateBalance +* @param aBalance +* @param aLeft +* @param aRight +* +* follows a simple straight line transformation +* y = m x + c +* m = (KMMFBalanceMaxLeft-KMMFBalanceMaxRight)/ 100 +* c = KMMFBalanceMaxRight +* by substitution +* when aLeft = 0 +* KMMFBalanceMaxRight = m * 0 + c +* c = KMMFBalanceMaxRight +* when aLeft = 100 +* KMMFBalanceMaxLeft = m * 100 + KMMFBalanceMaxRight +* m = ( KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) /100 +*/ +void CMMFMdaAudioToneUtility::CalculateBalance( TInt& aBalance, TInt aLeft, TInt aRight ) const + { + //[ assert pre conditions ] + __ASSERT_ALWAYS( (( aLeft + aRight ) == 100 ), Panic( EBadArgument )); + __ASSERT_ALWAYS( (( 0 <= aLeft) && ( 100 >= aLeft)), Panic( EBadArgument) ); + __ASSERT_ALWAYS( (( 0 <= aRight) && ( 100 >= aRight)), Panic( EBadArgument) ); + + aBalance = (aLeft * (KMMFBalanceMaxLeft-KMMFBalanceMaxRight))/100 + KMMFBalanceMaxRight; + + //[ assert post condition that aBalance is within limits ] + __ASSERT_ALWAYS( !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight), Panic(EBadArgument)); + + } + + +/** +* CalculateLeftRightBalance +* @param aLeft +* @param aRight +* @param aBalance +* Preconditions: +* !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight) +* y = m x + c +* aLeft = m ( aBalance ) + c +* when aBalance = KMMFBalanceMaxLeft aLeft = 100 +* when aBalance = KMMFBalanceMaxRight aLeft = 0 +* 100 = m( KMMFBalanceMaxLeft ) + c +* 0 = m( KMMFBalanceMaxRight ) + c +* c = -(KMMFBalanceMaxRight) m +* 100 = m(KMMFBalanceMaxLeft ) - m(KMMFBalanceMaxRight) +* m = 100/(KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) +* c = -(KMMFBalanceMaxRight) * 100 /(KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) +* aLeft = ( aBalance - KMMFBalanceMaxRight ) * 100 /( KMMFBalanceMaxLeft - KMMFBalanceMaxRight ) +*/ +void CMMFMdaAudioToneUtility::CalculateLeftRightBalance( TInt& aLeft, TInt& aRight, TInt aBalance ) const + { + // [ assert precondition that aBalance is within limits ] + __ASSERT_ALWAYS( !(aBalance < KMMFBalanceMaxLeft || aBalance > KMMFBalanceMaxRight), Panic(EBadArgument)); + + //[ Now separate percentage balances out from aBalance ] + aLeft = (100 * (aBalance-KMMFBalanceMaxRight)) / (KMMFBalanceMaxLeft-KMMFBalanceMaxRight); + aRight = 100 - aLeft; + + //[ assert post condition that left and right are within range ] + __ASSERT_ALWAYS( ( (aLeft <= 100) && (aLeft >= 0) ), Panic(EPostConditionViolation)); + __ASSERT_ALWAYS( ( (aRight <= 100) && (aRight >= 0) ), Panic(EPostConditionViolation)); + } + + +void CMMFMdaAudioToneUtility::SetBalanceL(TInt aBalance) + { + TInt left; + TInt right; + CalculateLeftRightBalance(left,right,aBalance); + iDevSound->SetPlayBalanceL(left,right); + } + +TInt CMMFMdaAudioToneUtility::GetBalanceL() + { + TInt left; + TInt right; + TInt balance; + iDevSound->GetPlayBalanceL(left, right); + CalculateBalance(balance,left,right); + return balance; + } + +void CMMFMdaAudioToneUtility::PrepareToPlayTone(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration) + { + delete iToneConfig; + iToneConfig = NULL; + TRAPD(error, iToneConfig = CMMFSimpleToneConfig::NewL(aFrequency, aDuration)); + iAsyncCallback->MatoPrepareComplete(error); + } + +void CMMFMdaAudioToneUtility::PrepareToPlayDualTone(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration) + { + delete iToneConfig; + iToneConfig = NULL; + TRAPD(error, iToneConfig = CMMFDualToneConfig::NewL(aFrequencyOne, aFrequencyTwo, aDuration)); + iAsyncCallback->MatoPrepareComplete(error); + } + +void CMMFMdaAudioToneUtility::PrepareToPlayDTMFString(const TDesC& aDTMF) + { + delete iToneConfig; + iToneConfig = NULL; + TRAPD(error, iToneConfig = CMMFDTMFStringToneConfig::NewL(aDTMF)); + iAsyncCallback->MatoPrepareComplete(error); + } + +void CMMFMdaAudioToneUtility::PrepareToPlayDesSequence(const TDesC8& aSequence) + { + delete iToneConfig; + iToneConfig = NULL; + TRAPD(error, iToneConfig = CMMFDesSeqToneConfig::NewL(aSequence)); + iAsyncCallback->MatoPrepareComplete(error); + } + +void CMMFMdaAudioToneUtility::PrepareToPlayFileSequence(const TDesC& aFileName) + { + delete iToneConfig; + iToneConfig = NULL; + TRAPD(error, iToneConfig = CMMFFileSeqToneConfig::NewL(aFileName)); + iAsyncCallback->MatoPrepareComplete(error); + } + +void CMMFMdaAudioToneUtility::PrepareToPlayFileSequence(RFile& aFileName) + { + delete iToneConfig; + iToneConfig = NULL; + TRAPD(error, iToneConfig = CMMFFileSeqToneConfig::NewL(aFileName)); + iAsyncCallback->MatoPrepareComplete(error); + } + + + + +void CMMFMdaAudioToneUtility::PrepareToPlayFixedSequence(TInt aSequenceNumber) + { + delete iToneConfig; + iToneConfig = NULL; + TRAPD(error, iToneConfig = CMMFFixedSeqToneConfig::NewL(aSequenceNumber)); + iSequenceNumber = aSequenceNumber; + iAsyncCallback->MatoPrepareComplete(error); + } + +void CMMFMdaAudioToneUtility::CancelPrepare() + { + // FIXME - do we need to cancel the callback? What if the callback is actually calling back another error? Probably best not to cancel... + delete iToneConfig; + iToneConfig = NULL; + + if (iState == EMdaAudioToneUtilityPrepared) + { + iState = EMdaAudioToneUtilityNotReady; + } + // Cancel the AO + iAsyncCallback->Cancel(); + } + +TInt CMMFMdaAudioToneUtility::Pause() + { + // Handle scenario when Pause is called before playback has started + if (iState != EMdaAudioToneUtilityPlaying || (iState == EMdaAudioToneUtilityPlaying && !iInitialized)) + { + return KErrNotReady; + } + + else if(! iDevSound->IsResumeSupported() || iToneConfig->Type() != CMMFToneConfig::EMmfToneTypeFileSeq) + { + return KErrNotSupported; + } + + iDevSound->Pause(); + iState = EMdaAudioToneUtilityPaused; + return KErrNone; + } + +TInt CMMFMdaAudioToneUtility::Resume() + { + TInt err = KErrNone; + if (iState != EMdaAudioToneUtilityPaused) + { + err = KErrNotReady; + } + + else if( iDevSound->IsResumeSupported() == EFalse || iToneConfig->Type() != CMMFToneConfig::EMmfToneTypeFileSeq) + { + err = KErrNotSupported; + } + + if(err == KErrNone) + { + err = iDevSound->Resume(); + if(err == KErrNone) + { + iState = EMdaAudioToneUtilityPlaying; + } + } + return err; + } + +void CMMFMdaAudioToneUtility::Play() + { + TInt error = KErrNone; + + if ((iState == EMdaAudioToneUtilityPlaying) || (iState == EMdaAudioToneUtilityPaused) || iPlayCalled) + { + error = KErrInUse; + } + + if (!error) + { + if (!iToneConfig) + { + TRAP(error, iToneConfig = CMMFFixedSeqToneConfig::NewL(iSequenceNumber)); + } + } + // If there was an error, notify the client now. Otherwise, client will be notified when + // play has finished. + if (error) + { + iState = EMdaAudioToneUtilityNotReady; + iAsyncCallback->MatoPlayComplete(error); + } + + if (!error) + { + iState = EMdaAudioToneUtilityPlaying; + + if (iInitialized) + { + // Play() is called after InitializeComplete() + if (iInitializeState) + { + // InitializeComplete() with error other than KErrNone + iState = EMdaAudioToneUtilityNotReady; + iAsyncCallback->MatoPlayComplete(iInitializeState); + } + else + { + PlayAfterInitialized(); + } + } + else + { + // Play() is called before InitializeComplete() + iPlayCalled = ETrue; + } + } + } + +void CMMFMdaAudioToneUtility::PlayAfterInitialized() + { +#ifdef _DEBUG + if (iInitialized == EFalse) + { + iPlayCalledBeforeInitialized = ETrue; + } +#endif + + TInt error = KErrNone; + switch (iToneConfig->Type()) + { + case CMMFToneConfig::EMmfToneTypeSimple: + { + CMMFSimpleToneConfig* c = STATIC_CAST(CMMFSimpleToneConfig*, iToneConfig); + TRAP(error, iDevSound->PlayToneL(c->Frequency(), c->Duration())); + break; + } + case CMMFToneConfig::EMmfToneTypeDual: + { + CMMFDualToneConfig* c = STATIC_CAST(CMMFDualToneConfig*, iToneConfig); + TRAP(error, iDevSound->PlayDualToneL(c->FrequencyOne(), c->FrequencyTwo(), c->Duration())); + break; + } + case CMMFToneConfig::EMmfToneTypeDTMF: + { + CMMFDTMFStringToneConfig* c = STATIC_CAST(CMMFDTMFStringToneConfig*, iToneConfig); + TRAP(error, iDevSound->PlayDTMFStringL(c->DTMF())); + break; + } + case CMMFToneConfig::EMmfToneTypeDesSeq: + { + CMMFDesSeqToneConfig* c = STATIC_CAST(CMMFDesSeqToneConfig*, iToneConfig); + TRAP(error, iDevSound->PlayToneSequenceL(c->DesSeq())); + break; + } + case CMMFToneConfig::EMmfToneTypeFileSeq: + { + CMMFFileSeqToneConfig* c = STATIC_CAST(CMMFFileSeqToneConfig*, iToneConfig); + + // check we have rights to play + TRAP(error, c->ExecuteIntentL()); + + // if we have rights then go ahead and play + if (error == KErrNone) + { + TRAP(error, iDevSound->PlayToneSequenceL(c->FileSeq())); + } + + break; + } + case CMMFToneConfig::EMmfToneTypeFixedSeq: + { + CMMFFixedSeqToneConfig* c = STATIC_CAST(CMMFFixedSeqToneConfig*, iToneConfig); + TRAP(error, iDevSound->PlayFixedSequenceL(c->SequenceNumber())); + break; + } + default: + { + User::Panic(KMMFMdaAudioToneUtilityPanicCategory, EMMFMdaAudioToneUtilityBadToneConfig); + break; + } + } + + // If there was an error, notify the client now. Otherwise, client will be notified when + // play has finished. + if (error) + { + iState = EMdaAudioToneUtilityNotReady; + iAsyncCallback->MatoPlayComplete(error); + } + else + { + if(iPlayStartObserver) + { + iAsyncCallback->MatoPlayStarted(KErrNone); + } + } + } + +void CMMFMdaAudioToneUtility::CancelPlay() + { + iDevSound->Stop(); + + if(iState == EMdaAudioToneUtilityPlaying || iState == EMdaAudioToneUtilityPaused) + { + iState = EMdaAudioToneUtilityPrepared; + } + // Cancel the AO + iAsyncCallback->Cancel(); + iPlayCalled = EFalse; + } + + +void CMMFMdaAudioToneUtility::SendEventToClient(const TMMFEvent& /*aEvent*/) + { + if(iState == EMdaAudioToneUtilityPlaying) + { + iState = EMdaAudioToneUtilityPrepared; + } + + iAsyncCallback->MatoPlayComplete(KErrInUse); + } + + +void CMMFMdaAudioToneUtility::RegisterPlayStartCallback(MMdaAudioTonePlayStartObserver& aObserver) + { + iPlayStartObserver = &aObserver; + } + +void CMMFMdaAudioToneUtility::MatoPrepareComplete(TInt aError) + { + if (!aError) + { + iState = EMdaAudioToneUtilityPrepared; + } + else + { + iState = EMdaAudioToneUtilityNotReady; + } + + iCallback.MatoPrepareComplete(aError); + } + +void CMMFMdaAudioToneUtility::MatoPlayComplete(TInt aError) + { + iState = EMdaAudioToneUtilityPrepared; + iCallback.MatoPlayComplete(aError); + } + +void CMMFMdaAudioToneUtility::MatoPlayStarted(TInt aError) + { + __ASSERT_DEBUG(aError==KErrNone, Panic(EPlayStartedCalledWithError)); + + // Not always there is an observer registered + if(iPlayStartObserver) + { + iPlayStartObserver->MatoPlayStarted(aError); + } + } + +// CustomInferface - just pass on to DevSound. +TAny* CMMFMdaAudioToneUtility::CustomInterface(TUid aInterfaceId) + { + return iDevSound->CustomInterface(aInterfaceId); + } + + +CMMFMdaAudioToneObserverCallback* CMMFMdaAudioToneObserverCallback::NewL(MMdaAudioToneObserver& aCallback, MMdaAudioTonePlayStartObserver& aPlayStartCallback) + { + return new(ELeave) CMMFMdaAudioToneObserverCallback(aCallback, aPlayStartCallback); + } + +CMMFMdaAudioToneObserverCallback::CMMFMdaAudioToneObserverCallback(MMdaAudioToneObserver& aCallback, MMdaAudioTonePlayStartObserver& aPlayStartCallback) : + CActive(CActive::EPriorityHigh), + iCallback(aCallback), + iPlayStartCallback(aPlayStartCallback) + { + CActiveScheduler::Add(this); + } + +CMMFMdaAudioToneObserverCallback::~CMMFMdaAudioToneObserverCallback() + { + Cancel(); + } + +void CMMFMdaAudioToneObserverCallback::MatoPrepareComplete(TInt aError) + { + iAction = EPrepareComplete; + iErrorCode = aError; + + TRequestStatus* s = &iStatus; + SetActive(); + User::RequestComplete(s, KErrNone); + } + +void CMMFMdaAudioToneObserverCallback::MatoPlayComplete(TInt aError) + { + if(!IsActive()) + { + iAction = EPlayComplete; + iErrorCode = aError; + + TRequestStatus* s = &iStatus; + SetActive(); + User::RequestComplete(s, KErrNone); + } + } + +void CMMFMdaAudioToneObserverCallback::MatoPlayStarted(TInt aError) + { + iAction = EPlayStarted; + iErrorCode = aError; + + TRequestStatus* s = &iStatus; + SetActive(); + User::RequestComplete(s, KErrNone); + } + +void CMMFMdaAudioToneObserverCallback::RunL() + { + switch (iAction) + { + case EPrepareComplete: + { + iCallback.MatoPrepareComplete(iErrorCode); + break; + } + case EPlayComplete: + { + iCallback.MatoPlayComplete(iErrorCode); + break; + } + case EPlayStarted: + iPlayStartCallback.MatoPlayStarted(iErrorCode); + break; + } + } + +void CMMFMdaAudioToneObserverCallback::DoCancel() + { + //nothing to cancel + } + + + + + + +// Tone config classes + +// Simple Tone +CMMFToneConfig* CMMFSimpleToneConfig::NewL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration) + { + return STATIC_CAST(CMMFToneConfig*, new(ELeave) CMMFSimpleToneConfig(aFrequency, aDuration)); + } + +CMMFSimpleToneConfig::CMMFSimpleToneConfig(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration) : + CMMFToneConfig(CMMFToneConfig::EMmfToneTypeSimple), + iFrequency(aFrequency), + iDuration(aDuration) + { + } + +CMMFSimpleToneConfig::~CMMFSimpleToneConfig() + { + } + +TInt CMMFSimpleToneConfig::Frequency() + { + return iFrequency; + } + +const TTimeIntervalMicroSeconds& CMMFSimpleToneConfig::Duration() + { + return iDuration; + } + + +// Dual Tone +CMMFToneConfig* CMMFDualToneConfig::NewL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration) + { + return STATIC_CAST(CMMFToneConfig*, new(ELeave) CMMFDualToneConfig(aFrequencyOne, aFrequencyTwo, aDuration)); + } + +CMMFDualToneConfig::CMMFDualToneConfig(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration) : + CMMFToneConfig(CMMFToneConfig::EMmfToneTypeDual), + iFrequencyOne(aFrequencyOne), + iFrequencyTwo(aFrequencyTwo), + iDuration(aDuration) + { + } + +CMMFDualToneConfig::~CMMFDualToneConfig() + { + } + +TInt CMMFDualToneConfig::FrequencyOne() + { + return iFrequencyOne; + } + +TInt CMMFDualToneConfig::FrequencyTwo() + { + return iFrequencyTwo; + } + +const TTimeIntervalMicroSeconds& CMMFDualToneConfig::Duration() + { + return iDuration; + } + + +CMMFToneConfig* CMMFDTMFStringToneConfig::NewL(const TDesC& aDTMF) + { + CMMFDTMFStringToneConfig* s = new(ELeave) CMMFDTMFStringToneConfig; + CleanupStack::PushL(s); + s->ConstructL(aDTMF); + CleanupStack::Pop(); + return STATIC_CAST(CMMFToneConfig*, s); + } + +CMMFDTMFStringToneConfig::CMMFDTMFStringToneConfig() : + CMMFToneConfig(CMMFToneConfig::EMmfToneTypeDTMF) + { + } + +LOCAL_C void validateDTMFL(const TDesC& aDTMF) +// +// Validate that the supplied DTMf string contains only playable characters +// + { + TInt stringLength = aDTMF.Length(); + TChar ch; + for (TInt index = 0; index < stringLength ; index++) + { + ch = aDTMF[index]; + if (!ch.IsDigit() && !ch.IsHexDigit() && !ch.IsSpace() && + (ch != '*') && (ch != '#') && (ch != ',')) + { + User::Leave(KErrArgument); // Bad DTMF string + } + } + } + +void CMMFDTMFStringToneConfig::ConstructL(const TDesC& aDTMF) + { + validateDTMFL(aDTMF); + iDTMF = aDTMF.AllocL(); + } + +CMMFDTMFStringToneConfig::~CMMFDTMFStringToneConfig() + { + delete iDTMF; + } + +const TDesC& CMMFDTMFStringToneConfig::DTMF() + { + return *iDTMF; + } + + +CMMFToneConfig* CMMFDesSeqToneConfig::NewL(const TDesC8& aDesSeq) + { + CMMFDesSeqToneConfig* s = new(ELeave) CMMFDesSeqToneConfig; + CleanupStack::PushL(s); + s->ConstructL(aDesSeq); + CleanupStack::Pop(); + return STATIC_CAST(CMMFToneConfig*, s); + } + +CMMFDesSeqToneConfig::CMMFDesSeqToneConfig() : + CMMFToneConfig(CMMFToneConfig::EMmfToneTypeDesSeq) + { + } + +void CMMFDesSeqToneConfig::ConstructL(const TDesC8& aDesSeq) + { + iDesSeq = aDesSeq.AllocL(); + } + +CMMFDesSeqToneConfig::~CMMFDesSeqToneConfig() + { + delete iDesSeq; + } + +const TDesC8& CMMFDesSeqToneConfig::DesSeq() + { + return *iDesSeq; + } + + +CMMFToneConfig* CMMFFileSeqToneConfig::NewL(const TDesC& aFileSeq) + { + CMMFFileSeqToneConfig* s = new(ELeave) CMMFFileSeqToneConfig; + CleanupStack::PushL(s); + s->ConstructL(aFileSeq); + CleanupStack::Pop(); + return STATIC_CAST(CMMFToneConfig*, s); + } + +CMMFFileSeqToneConfig::CMMFFileSeqToneConfig() : + CMMFToneConfig(CMMFToneConfig::EMmfToneTypeFileSeq) + { + } + +void CMMFFileSeqToneConfig::ConstructL(const TDesC& aFileSeq) + { + // get access to DRM content through filename + iCAFContent = CContent::NewL(aFileSeq); + + // open the CAF source with play intent + iCAFData = iCAFContent->OpenContentL(ContentAccess::EPlay, KDefaultContentObject); + + // read into a descriptor + TInt dataSize = 0; + iCAFData->DataSizeL(dataSize); + + iDesSeq = HBufC8::NewL(dataSize); + TPtr8 desSeqPtr = iDesSeq->Des(); + iCAFData->Read(desSeqPtr); + } + + + +CMMFToneConfig* CMMFFileSeqToneConfig::NewL(RFile& aFile) + { + CMMFFileSeqToneConfig* s = new(ELeave) CMMFFileSeqToneConfig; + CleanupStack::PushL(s); + s->ConstructL(aFile); + CleanupStack::Pop(); + return STATIC_CAST(CMMFToneConfig*, s); + } + + +void CMMFFileSeqToneConfig::ConstructL(RFile& aFile) + { + // get DRM access to file handle + iCAFContent = CContent::NewL(aFile); + + // open the CAF source with play intent + iCAFData = iCAFContent->OpenContentL(ContentAccess::EPlay, KDefaultContentObject); + + // read into a descriptor + TInt dataSize = 0; + iCAFData->DataSizeL(dataSize); + + iDesSeq = HBufC8::NewL(dataSize); + TPtr8 desSeqPtr = iDesSeq->Des(); + iCAFData->Read(desSeqPtr); + } + + +CMMFFileSeqToneConfig::~CMMFFileSeqToneConfig() + { + delete iCAFData; + iCAFData = NULL; + + delete iCAFContent; + iCAFContent = NULL; + + delete iDesSeq; + } + +const TDesC8& CMMFFileSeqToneConfig::FileSeq() + { + return *iDesSeq; + } + +void CMMFFileSeqToneConfig::ExecuteIntentL() + { + if (iCAFData) + { + User::LeaveIfError(iCAFData->ExecuteIntent(ContentAccess::EPlay)); + } + } + +CMMFToneConfig* CMMFFixedSeqToneConfig::NewL(TInt aSeqNo) + { + return STATIC_CAST(CMMFToneConfig*, new(ELeave) CMMFFixedSeqToneConfig(aSeqNo)); + } + +CMMFFixedSeqToneConfig::CMMFFixedSeqToneConfig(TInt aSeqNo) : + CMMFToneConfig(CMMFToneConfig::EMmfToneTypeFixedSeq), + iSequenceNumber(aSeqNo) + { + } + +CMMFFixedSeqToneConfig::~CMMFFixedSeqToneConfig() + { + } + +TInt CMMFFixedSeqToneConfig::SequenceNumber() + { + return iSequenceNumber; + } diff -r 320024dcf7b6 -r 657f02e590f1 breakdeps/mmfclienttoneplayer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/mmfclienttoneplayer.h Wed Oct 20 13:05:58 2010 +0100 @@ -0,0 +1,284 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + + +#ifndef __MMFCLIENTTONEPLAY_H__ +#define __MMFCLIENTTONEPLAY_H__ + + +#include +#include +#include +#include +#include +#include +//Panic category and codes +_LIT(KMMFMdaAudioToneUtilityPanicCategory, "MMFMdaAudioToneUtility"); +enum TMMFMdaAudioToneUtilityPanicCodes + { + EMMFMdaAudioToneUtilityAlreadyPrepared, + EMMFMdaAudioToneUtilityBadToneConfig, + EMMFMdaAudioToneUtilityBadMixinCall + }; + +/** +Active object utility class to allow the callback to be called asynchronously. +This should help prevent re-entrant code in clients of the mediaframework. +*/ +class CMMFMdaAudioToneObserverCallback : public CActive, public MMdaAudioToneObserver, public MMdaAudioTonePlayStartObserver + { +public: + static CMMFMdaAudioToneObserverCallback* NewL(MMdaAudioToneObserver& aCallback, MMdaAudioTonePlayStartObserver& aPlayStartCallback); + ~CMMFMdaAudioToneObserverCallback(); +// From MMdaAudioToneObserver + virtual void MatoPrepareComplete(TInt aError); + virtual void MatoPlayComplete(TInt aError); +// From MMdaAudioTonePlayStartObserver + virtual void MatoPlayStarted(TInt aError); +private: + CMMFMdaAudioToneObserverCallback(MMdaAudioToneObserver& aCallback, MMdaAudioTonePlayStartObserver& aPlayStartCallback); + void RunL(); + void DoCancel(); +private: + enum TMMFAudioToneObserverCallbackAction {EPrepareComplete, EPlayComplete, EPlayStarted}; + MMdaAudioToneObserver& iCallback; + MMdaAudioTonePlayStartObserver& iPlayStartCallback; + TMMFAudioToneObserverCallbackAction iAction; + TInt iErrorCode; + }; + +class CMMFToneConfig; + +/** +Concrete implementation of the CMdaAudioToneUtility API. +@see CMdaAudioToneUtility +*/ +class CMMFMdaAudioToneUtility; +NONSHARABLE_CLASS( CMMFMdaAudioToneUtility ): public CBase, + public MMdaAudioToneObserver, + public MDevSoundObserver, + public MMdaAudioTonePlayStartObserver + { +friend class CMdaAudioToneUtility; +// only for testing purposes +friend class CTestStepUnitMMFAudClient; + +public: + static CMMFMdaAudioToneUtility* NewL(MMdaAudioToneObserver& aObserver, CMdaServer* aServer = NULL, + TInt aPriority = EMdaPriorityNormal, + TInt aPref = EMdaPriorityPreferenceTimeAndQuality); + + ~CMMFMdaAudioToneUtility(); + + TMdaAudioToneUtilityState State(); + TInt MaxVolume(); + TInt Volume(); + void SetVolume(TInt aVolume); + void SetPriority(TInt aPriority, TInt aPref); + void SetDTMFLengths(TTimeIntervalMicroSeconds32 aToneLength, + TTimeIntervalMicroSeconds32 aToneOffLength, + TTimeIntervalMicroSeconds32 aPauseLength); + void SetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence); + void SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration); + TInt FixedSequenceCount(); + const TDesC& FixedSequenceName(TInt aSequenceNumber); + void PrepareToPlayTone(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration); + void PrepareToPlayDualTone(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration); + void PrepareToPlayDTMFString(const TDesC& aDTMF); + void PrepareToPlayDesSequence(const TDesC8& aSequence); + void PrepareToPlayFileSequence(const TDesC& aFileName); + void PrepareToPlayFileSequence(RFile& aFile); + void PrepareToPlayFixedSequence(TInt aSequenceNumber); + void CancelPrepare(); + void Play(); + void CancelPlay(); + TInt Pause(); + TInt Resume(); + + void SetBalanceL(TInt aBalance=KMMFBalanceCenter); + TInt GetBalanceL(); +// From MMdaAudioToneObserver + void MatoPrepareComplete(TInt aError); + void MatoPlayComplete(TInt aError); + +// From DevSoundObserver + void InitializeComplete(TInt aError); + void ToneFinished(TInt aError); + void BufferToBeFilled(CMMFBuffer* /*aBuffer*/) {User::Panic(KMMFMdaAudioToneUtilityPanicCategory,EMMFMdaAudioToneUtilityBadMixinCall);} + void PlayError(TInt /*aError*/) {User::Panic(KMMFMdaAudioToneUtilityPanicCategory,EMMFMdaAudioToneUtilityBadMixinCall);} + void BufferToBeEmptied(CMMFBuffer* /*aBuffer*/) {User::Panic(KMMFMdaAudioToneUtilityPanicCategory,EMMFMdaAudioToneUtilityBadMixinCall);} + void RecordError(TInt /*aError*/) {User::Panic(KMMFMdaAudioToneUtilityPanicCategory,EMMFMdaAudioToneUtilityBadMixinCall);} + void ConvertError(TInt /*aError*/) {User::Panic(KMMFMdaAudioToneUtilityPanicCategory,EMMFMdaAudioToneUtilityBadMixinCall);} + void DeviceMessage(TUid /*aMessageId*/, const TDesC8& /*aMsg*/) {User::Panic(KMMFMdaAudioToneUtilityPanicCategory,EMMFMdaAudioToneUtilityBadMixinCall);} + void SendEventToClient(const TMMFEvent& /*aEvent*/); + + TAny* CustomInterface(TUid aInterfaceId); + + void PlayAfterInitialized(); + + void RegisterPlayStartCallback(MMdaAudioTonePlayStartObserver& aObserver); + +// From MMdaAudioTonePlayStartObserver + void MatoPlayStarted(TInt aError); + +protected: + CMMFMdaAudioToneUtility(MMdaAudioToneObserver& aCallback, TInt aPriority, TInt aPref); + void ConstructL(); +private: + // functions to convert between MediaServer Balance and SoundDev balance + void CalculateBalance( TInt& aBalance, TInt aLeft, TInt aRight ) const; + void CalculateLeftRightBalance( TInt& aLeft, TInt& aRight, TInt aBalance ) const; + +private: + CMMFDevSound* iDevSound; + MMdaAudioToneObserver& iCallback; + CMMFMdaAudioToneObserverCallback* iAsyncCallback; + + CMMFToneConfig* iToneConfig; + // Devsound doesn't take copies of descriptors we pass to it, so we + // need to cache the config info until it has finished playing. + CMMFToneConfig* iPlayingToneConfig; //unused remove when BC break allowed + + TMdaAudioToneUtilityState iState; + + TMMFPrioritySettings iPrioritySettings; + + TInt iInitializeState; + + TInt iSequenceNumber; + TBool iPlayCalled; + + TBool iInitialized; + + MMdaAudioTonePlayStartObserver* iPlayStartObserver; + +#ifdef _DEBUG + TBool iPlayCalledBeforeInitialized; +#endif + }; + + +// Tone configurations +class CMMFToneConfig : public CBase + { +public: + enum TMMFToneType + { + EMmfToneTypeSimple, + EMmfToneTypeDTMF, + EMmfToneTypeDesSeq, + EMmfToneTypeFileSeq, + EMmfToneTypeFixedSeq, + EMmfToneTypeDual, + }; + virtual ~CMMFToneConfig() {} + TMMFToneType Type() {return iType;} +protected: + CMMFToneConfig(TMMFToneType aType) : iType(aType) {} +private: + TMMFToneType iType; + }; + +class CMMFSimpleToneConfig : public CMMFToneConfig + { +public: + static CMMFToneConfig* NewL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration); + virtual ~CMMFSimpleToneConfig(); + TInt Frequency(); + const TTimeIntervalMicroSeconds& Duration(); +protected: + CMMFSimpleToneConfig(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration); +private: + TInt iFrequency; + TTimeIntervalMicroSeconds iDuration; + }; + +class CMMFDualToneConfig : public CMMFToneConfig + { +public: + static CMMFToneConfig* NewL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration); + virtual ~CMMFDualToneConfig(); + TInt FrequencyOne(); + TInt FrequencyTwo(); + const TTimeIntervalMicroSeconds& Duration(); +protected: + CMMFDualToneConfig(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration); +private: + TInt iFrequencyOne; + TInt iFrequencyTwo; + TTimeIntervalMicroSeconds iDuration; + }; + +class CMMFDTMFStringToneConfig : public CMMFToneConfig + { +public: + static CMMFToneConfig* NewL(const TDesC& aDTMF); + static CMMFToneConfig* NewL(RFile& aFile); + virtual ~CMMFDTMFStringToneConfig(); + const TDesC& DTMF(); +protected: + CMMFDTMFStringToneConfig(); + void ConstructL(const TDesC& aDTMF); +private: + HBufC* iDTMF; + }; + +class CMMFDesSeqToneConfig : public CMMFToneConfig + { +public: + static CMMFToneConfig* NewL(const TDesC8& aDesSeq); + virtual ~CMMFDesSeqToneConfig(); + const TDesC8& DesSeq(); +protected: + CMMFDesSeqToneConfig(); + void ConstructL(const TDesC8& aDesSeq); +private: + HBufC8* iDesSeq; + }; + + +class CMMFFileSeqToneConfig : public CMMFToneConfig + { +public: + static CMMFToneConfig* NewL(const TDesC& aFileSeq); + static CMMFToneConfig* NewL(RFile& aFile); + virtual ~CMMFFileSeqToneConfig(); + const TDesC8& FileSeq(); + + // CAF support for Tone Utility + void ExecuteIntentL(); +protected: + CMMFFileSeqToneConfig(); + void ConstructL(const TDesC& aFileSeq); + void ConstructL(RFile& aFile); +private: + ContentAccess::CContent* iCAFContent; + ContentAccess::CData* iCAFData; + HBufC8* iDesSeq; + }; + +class CMMFFixedSeqToneConfig : public CMMFToneConfig + { +public: + static CMMFToneConfig* NewL(TInt aSeqNo); + virtual ~CMMFFixedSeqToneConfig(); + TInt SequenceNumber(); +protected: + CMMFFixedSeqToneConfig(TInt aSeqNo); +private: + TInt iSequenceNumber; + }; + +#endif diff -r 320024dcf7b6 -r 657f02e590f1 breakdeps/mmfclientutility.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/mmfclientutility.cpp Wed Oct 20 13:05:58 2010 +0100 @@ -0,0 +1,2531 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Audio, MIDI and Video client utility functions. +// +// + +#include +#include +#include +#include +#include +#include +using namespace ContentAccess; + +#include "mmfclientutility.h" +#include + +const TInt KMaxMimeLength = 256; +const TInt KMaxHeaderSize = 256; +const TInt KExpandSize = 100; + +#ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT + const TInt KDefaultScreenNo = 0; +#endif + +void CUPanic(TInt aCUPanicCode) + { + _LIT(KMMFMediaClientUtilityPaanicCategory, "MMFClientUtility"); + User::Panic(KMMFMediaClientUtilityPaanicCategory, aCUPanicCode); + } + +/** + * @internalComponent + */ +EXPORT_C TUid CMMFClientUtility::ConvertMdaFormatUidToECOMWrite(TUid aMdaFormatUid) + { + TUid ECOMUid = KNullUid; + if (aMdaFormatUid == KUidMdaClipFormatWav) + ECOMUid = TUid::Uid(KMmfUidFormatWAVWrite); + else if (aMdaFormatUid == KUidMdaClipFormatAu) + ECOMUid = TUid::Uid(KMmfUidFormatAUWrite); + else if (aMdaFormatUid == KUidMdaClipFormatRawAudio) + ECOMUid = TUid::Uid(KMmfUidFormatRAWWrite); + else if (aMdaFormatUid == KUidMdaClipFormatRawAmr) + ECOMUid = TUid::Uid(KAdvancedUidFormatAMRWrite); + + return ECOMUid; + } + +/** + * @internalComponent + */ +EXPORT_C TUid CMMFClientUtility::ConvertMdaFormatUidToECOMRead(TUid aMdaFormatUid) + { + TUid ECOMUid = KNullUid; + if (aMdaFormatUid == KUidMdaClipFormatWav) + ECOMUid = TUid::Uid(KMmfUidFormatWAVRead); + else if (aMdaFormatUid == KUidMdaClipFormatAu) + ECOMUid = TUid::Uid(KMmfUidFormatAURead); + else if (aMdaFormatUid == KUidMdaClipFormatRawAudio) + ECOMUid = TUid::Uid(KMmfUidFormatRAWRead); + else if (aMdaFormatUid == KUidMdaClipFormatRawAmr) + ECOMUid = TUid::Uid(KAdvancedUidFormatAMRRead); + + return ECOMUid; + } + +/** + * @internalComponent + */ +EXPORT_C TInt CMMFClientUtility::GetFileHeaderData(const TDesC& aFileName, TDes8& aHeaderData, TInt aMaxLength) + { + RFs fsSession; + RFile file; + TInt error = KErrNone; + + if ((error = fsSession.Connect()) == KErrNone) + { + if ((error = file.Open(fsSession, aFileName, EFileShareReadersOrWriters)) == KErrNone) + { + TInt size = 0; + + if ((error = file.Size(size)) == KErrNone) + { + if (size > 0) + { + if (size > aMaxLength) + size = aMaxLength; + + error = file.Read(aHeaderData, size); + } + } + file.Close(); + } + fsSession.Close(); + } + + return error; + } + +/** + * @internalComponent + */ +EXPORT_C TFourCC CMMFClientUtility::ConvertMdaCodecToFourCC(TMdaPackage& aCodec) + { + TFourCC dataType = KMMFFourCCCodeNULL; + switch (aCodec.Uid().iUid) + { + case KUidMdaWavPcmCodecDefine: + { + TMdaPcmWavCodec* pcmWavCodec = (TMdaPcmWavCodec*)&aCodec; + if (pcmWavCodec->iBits == TMdaPcmWavCodec::E8BitPcm) + dataType = KMMFFourCCCodePCMU8; //8 bit PCM + else + dataType = KMMFFourCCCodePCM16; //16 bit PCM + break; + } + case KUidMdaAu8PcmCodecDefine: + dataType = KMMFFourCCCodePCM8; + break; + case KUidMdaAuCodecDefine: + case KUidMdaAu16PcmCodecDefine: + dataType = KMMFFourCCCodePCM16B; + break; + + case KUidMdaAuMulawCodecDefine: + case KUidMdaWavMulawCodecDefine: + case KUidMdaRawAudioMulawCodecDefine: //uLAW + dataType = KMMFFourCCCodeMuLAW; + break; + case KUidMdaAuAlawCodecDefine: + case KUidMdaWavAlawCodecDefine: + case KUidMdaRawAudioAlawCodecDefine: //ALAW + dataType = KMMFFourCCCodeALAW; + break; + case KUidMdaRawAudioS8PcmCodecDefine: // P8 + dataType = KMMFFourCCCodePCM8; + break; + case KUidMdaRawAudioU8PcmCodecDefine: // PU8 + dataType = KMMFFourCCCodePCMU8; + break; + case KUidMdaRawAudioSL16PcmCodecDefine: // P16 + dataType = KMMFFourCCCodePCM16; + break; + case KUidMdaRawAudioSB16PcmCodecDefine: //P16B + dataType = KMMFFourCCCodePCM16B; + break; + case KUidMdaRawAudioUL16PcmCodecDefine: //PU16 + dataType = KMMFFourCCCodePCMU16; + break; + case KUidMdaRawAudioUB16PcmCodecDefine: //PU6B + dataType = KMMFFourCCCodePCMU16B; + break; + case KUidMdaGsmWavCodecDefine: //GSM6 + dataType = KMMFFourCCCodeGSM610; + break; + case KUidMdaWavImaAdpcmCodecDefine: + dataType = KMMFFourCCCodeIMAD; + break; + case KUidMdaRawAmrCodecDefine: + dataType = KMMFFourCCCodeAMR; + break; + default: // Not a Uid we recognise + dataType = KMMFFourCCCodeNULL; + break; + } + return dataType; + } + + +CMMFUtilityFileInfo* CMMFUtilityFileInfo::NewL(TMMSource& aSource, TBool aSecureDRMMode) + { + CMMFUtilityFileInfo* self = CMMFUtilityFileInfo::NewLC(aSource, aSecureDRMMode); + CleanupStack::Pop(self); + return self; + } + + +CMMFUtilityFileInfo* CMMFUtilityFileInfo::NewLC(TMMSource& aSource, TBool aSecureDRMMode) + { + CMMFUtilityFileInfo* self = new (ELeave) CMMFUtilityFileInfo; + CleanupStack::PushL(self); + self->ConstructL(aSource, aSecureDRMMode); + return self; + } + + +void CMMFUtilityFileInfo::ConstructL(const TMMSource& aSource, TBool aSecureDRMMode) + { + if (!aSecureDRMMode) + { + if (aSource.SourceType()==KUidMMFileSource) + { + const TMMFileSource& fileSource = static_cast(aSource); + iData = CData::NewL(TVirtualPathPtr(fileSource.Name(), fileSource.UniqueId()), + EContentShareReadWrite); + } + + if (aSource.SourceType()==KUidMMFileHandleSource) + { + const TMMFileHandleSource& fileHandleSource = static_cast(aSource); + iData = CData::NewL(fileHandleSource.Handle(), fileHandleSource.UniqueId()); + } + + TInt err = iData->SetProperty(EAgentPropertyAgentUI, aSource.IsUIEnabled()); + if (err != KErrNone && err != KErrCANotSupported) + { + // KErrCANotSupported isn't a problem for us so eat the error code. + User::Leave(err); + } + + err = iData->EvaluateIntent(aSource.Intent()); + User::LeaveIfError(err); + } + else + { + // Use RMMFDRMPluginServerProxy as medium + iDrmPluginServer = new (ELeave) RMMFDRMPluginServerProxy; + User::LeaveIfError(iDrmPluginServer->Open()); + + CBufFlat* dataBuffer = CBufFlat::NewL(KExpandSize); + CleanupStack::PushL(dataBuffer); + RBufWriteStream stream; + stream.Open(*dataBuffer); + CleanupClosePushL(stream); + + stream.WriteInt32L(aSource.UniqueId().Length()); + stream.WriteL(aSource.UniqueId()); + stream.WriteInt32L(aSource.IsUIEnabled()); + TPckgBuf intentPckg(aSource.Intent()); + stream.WriteL(intentPckg); + stream.CommitL(); + + CleanupStack::PopAndDestroy(&stream); + if (aSource.SourceType()==KUidMMFileSource) + { + const TMMFileSource& fileSource = static_cast(aSource); + iDrmPluginServer->OpenDataContentL(fileSource.Name(), dataBuffer->Ptr(0)); + } + if (aSource.SourceType()==KUidMMFileHandleSource) + { + const TMMFileHandleSource& fileHandleSource = static_cast(aSource); + iDrmPluginServer->OpenDataContentL(fileHandleSource.Handle(), dataBuffer->Ptr(0)); + } + CleanupStack::PopAndDestroy(dataBuffer); + } + } + +TInt CMMFUtilityFileInfo::EvaluateIntent(TIntent aIntent) + { + if (iData) + { + return iData->EvaluateIntent(aIntent); + } + else + { + ASSERT(iDrmPluginServer); + return iDrmPluginServer->EvaluateDataContentIntent(aIntent); + } + } +/** + * @internalComponent + */ +TBool CMMFUtilityFileInfo::GetFileMimeTypeL(TDes8& aMimeType) + { + if (iData) + { + return iData->GetMimeTypeL(aMimeType); + } + else + { + ASSERT(iDrmPluginServer); + return iDrmPluginServer->GetDataContentMimeTypeL(aMimeType); + } + } + +/** + * @internalComponent + */ +void CMMFUtilityFileInfo::GetFileHeaderDataL(TDes8& aHeaderData, TInt aMaxLength) + { + if (iData) + { + TInt size = 0; + iData->DataSizeL(size); + if (size > 0) + { + if (size > aMaxLength) + size = aMaxLength; + TInt pos = 0; + User::LeaveIfError(iData->Seek(ESeekStart, pos)); + User::LeaveIfError(iData->Read(aHeaderData, size)); + } + } + else + { + ASSERT(iDrmPluginServer); + iDrmPluginServer->GetDataContentFileHeaderL(aHeaderData, aMaxLength); + } + } + +/** + * @internalComponent + */ +EXPORT_C HBufC8* CMMFClientUtility::GetFileExtensionL(const TDesC& aFileName) + { + TParse fileName; + fileName.Set(aFileName,NULL,NULL); + HBufC8* fileSuffix = NULL; + if(fileName.ExtPresent()) + { + TPtrC fileSuffixPtr(fileName.Ext()); + fileSuffix = HBufC8::NewL(fileSuffixPtr.Length()); + fileSuffix->Des().Copy(fileSuffixPtr); + } + else + { + fileSuffix = KNullDesC8().AllocL(); + } + return fileSuffix; + } + + +/** + * @internalComponent + */ +CMMFUtilityFileInfo::~CMMFUtilityFileInfo() + { + if (iData) + { + delete iData; + } + if (iDrmPluginServer) + { + iDrmPluginServer->Close(); + delete iDrmPluginServer; + } + } + +/* + * @internalComponent + * + * Returns an integer rating indicating how well the supplied format matches + * the header data and file extension supplied. + * 3 brownie points awarded for data & suffix match. + * 2 brownie points awarded for data match alone. + * 1 brownie point awarded for suffix match alone. + */ +TInt CMMFClientUtility::GetBestMatchL(const CMMFFormatImplementationInformation* format, const TDesC8& aHeaderData, const TDesC8& aFileExtension) + { + TInt browniePoints = 0; + + if (aHeaderData.Length() > 0) // Non empty file + { + if (aFileExtension.Length() > 0) // With a file extension + { + if (format->SupportsHeaderDataL(aHeaderData) && + format->SupportsFileExtension(aFileExtension)) + { + browniePoints = 3; + } + else if (format->SupportsHeaderDataL(aHeaderData)) + { + browniePoints = 2; + } + else + { + // See if this format has any 'empty' match data or no match data, indicating + // that this format will match extension alone even if data present. + // (A format may have more than one match data string.) + const CDesC8Array& supportedHeaderData = format->SupportedHeaderData(); + + if (supportedHeaderData.Count() == 0) + { + // No header data indicated. + if (format->SupportsFileExtension(aFileExtension)) + { + browniePoints = 1; + } + } + else + { + for (register TInt i = 0; i < supportedHeaderData.Count(); i++) + { + if ((supportedHeaderData[i].Length() == 0) && + format->SupportsFileExtension(aFileExtension)) + { + browniePoints = 1; + } + } + } + } + } + else + { + // No file suffix, so must match header data alone. + if (format->SupportsHeaderDataL(aHeaderData)) + { + browniePoints = 2; + } + } + } + else // Empty File + { + // We have no choice but to match extension, if there is one. + if ((aFileExtension.Length() > 0) && format->SupportsFileExtension(aFileExtension)) + { + browniePoints = 1; + } + } + + return browniePoints; +} + +/** + * @internalComponent + * + * This function parses all the play & record formats in the given list of controllers, + * looking for controllers & formats that best match the requirements. + * Play controllers will be returned before record controllers, and + * in cases of equal priority between formats, ECom order will be maintained. + * + * @param "aControllers" + * A reference to a user supplied list of controllers retrieved from ECom. + * This list may be have been filtered for audio/video/play/record. + * @param "aHeaderDataPlayback" + * A descriptor reference containing the file's header data. + * for matching against a controller's play formats. May be KNullDesC8 + * @param "aFileExtensionPlayback" + * A descriptor reference containing the filename's extension. + * for matching against a controller's play formats. May be KNullDesC8 + * @param "aHeaderDataRecord" + * A descriptor reference containing the file's header data. + * for matching against a controller's record formats. May be KNullDesC8 + * @param "aFileExtensionRecord" + * A descriptor reference containing the filename's extension. + * for matching against a controller's record formats. May be KNullDesC8 + * @param "aPrioritisedControllers" + * A reference to a user supplied list through which the list of + * prioritised controllers will be returned. + * @since 7.0s + */ +void CMMFClientUtility::PrioritiseControllersL( + const RMMFControllerImplInfoArray& aControllers, + const TDesC8& aHeaderDataPlayback, + const TDesC8& aFileExtensionPlayback, + const TDesC8& aHeaderDataRecord, + const TDesC8& aFileExtensionRecord, + RMMFControllerImplInfoArray& prioritisedControllers) + { + RMMFControllerImplInfoArray fullMatchControllers; // data AND suffix + CleanupClosePushL(fullMatchControllers); + RMMFControllerImplInfoArray partMatchControllers; // data OR suffix + CleanupClosePushL(partMatchControllers); + + TBool checkingPlaybackFormats = EFalse; + TBool checkingRecordFormats = EFalse; + + if (aHeaderDataPlayback != KNullDesC8 || aFileExtensionPlayback != KNullDesC8) + checkingPlaybackFormats = ETrue; + if (aHeaderDataRecord != KNullDesC8 || aFileExtensionRecord != KNullDesC8) + checkingRecordFormats = ETrue; + + // Examine each format for each controller. We only want to know at this stage + // if the controller has suitable formats, so as soon as we know it has, we can + // add it to out list, ranked by how well it matched. + for (register TInt i = 0; i < aControllers.Count(); i++) + { + const CMMFControllerImplementationInformation* controller = aControllers[i]; + TInt savedBrowniePointsPlayback = 0; + TInt savedBrowniePointsRecord = 0; + + if (checkingPlaybackFormats) + { + for (register TInt p = 0; p < controller->PlayFormats().Count(); p++) + { + const CMMFFormatImplementationInformation* format = controller->PlayFormats()[p]; + + TInt browniePoints = GetBestMatchL(format, aHeaderDataPlayback, aFileExtensionPlayback); + + if (browniePoints >= savedBrowniePointsPlayback) + savedBrowniePointsPlayback = browniePoints; + } + } + + if (checkingRecordFormats) + { + for (register TInt r = 0; r < controller->RecordFormats().Count(); r++) + { + const CMMFFormatImplementationInformation* format = controller->RecordFormats()[r]; + + TInt browniePoints = GetBestMatchL(format, aHeaderDataRecord, aFileExtensionRecord); + + if (browniePoints >= savedBrowniePointsRecord) + savedBrowniePointsRecord = browniePoints; + } + } + + TInt savedBrowniePoints = 0; + // if we're checking both playback & record formats + // make sure we've found both + if (checkingPlaybackFormats && checkingRecordFormats) + { + savedBrowniePoints = Min(savedBrowniePointsPlayback, savedBrowniePointsRecord); + } + else if (checkingPlaybackFormats) + { + savedBrowniePoints = savedBrowniePointsPlayback; + } + else if (checkingRecordFormats) + { + savedBrowniePoints = savedBrowniePointsRecord; + } + + // Checked all formats for this controller, now count our brownie points. + switch (savedBrowniePoints) + { + case 3: + User::LeaveIfError(fullMatchControllers.Append(controller)); + break; + case 2: + User::LeaveIfError(partMatchControllers.Insert(controller, 0)); + break; + case 1: + User::LeaveIfError(partMatchControllers.Append(controller)); + break; + default: + break; + } + } + + // The better the controller matches, the earlier it will be in the final list. + for (register TInt x = 0; x < fullMatchControllers.Count(); x++) + { + if (prioritisedControllers.Find(fullMatchControllers[x]) == KErrNotFound) + { + User::LeaveIfError(prioritisedControllers.Append(fullMatchControllers[x])); + } + } + + for (register TInt y = 0; y < partMatchControllers.Count(); y++) + { + if (prioritisedControllers.Find(partMatchControllers[y]) == KErrNotFound) + { + User::LeaveIfError(prioritisedControllers.Append(partMatchControllers[y])); + } + } + + CleanupStack::PopAndDestroy(2, &fullMatchControllers); // fullMatchControllers, partMatchControllers + } + +/** + * @internalComponent + */ +EXPORT_C CMMFMdaObjectStateChangeObserverCallback* CMMFMdaObjectStateChangeObserverCallback::NewL(MMdaObjectStateChangeObserver& aCallback) + { + return new(ELeave) CMMFMdaObjectStateChangeObserverCallback(aCallback); + } + +/** + * @internalComponent + */ +CMMFMdaObjectStateChangeObserverCallback::~CMMFMdaObjectStateChangeObserverCallback() + { + Cancel(); + } + +/** + * @internalComponent + */ +EXPORT_C void CMMFMdaObjectStateChangeObserverCallback::CallBack(CBase* aObject, TInt aPreviousState, TInt aCurrentState, TInt aErrorCode) + { + iObject = aObject; + iPreviousState = aPreviousState; + iCurrentState = aCurrentState; + iErrorCode = aErrorCode; + if (!IsActive()) + { + TRequestStatus* s = &iStatus; + SetActive(); + User::RequestComplete(s, KErrNone); + } + } + +CMMFMdaObjectStateChangeObserverCallback::CMMFMdaObjectStateChangeObserverCallback(MMdaObjectStateChangeObserver& aCallback) : + CActive(CActive::EPriorityHigh), + iCallback(aCallback) + { + CActiveScheduler::Add(this); + } + +void CMMFMdaObjectStateChangeObserverCallback::RunL() + { + iCallback.MoscoStateChangeEvent(iObject, iPreviousState, iCurrentState, iErrorCode); + } + +void CMMFMdaObjectStateChangeObserverCallback::DoCancel() + { + //nothing to cancel + } + + +//**************************************** +// CMMFFindAndOpenController +//**************************************** + +/** + * Factory function to create a CMMFFindAndOpenController class + * + * @internalComponent + */ +EXPORT_C CMMFFindAndOpenController* CMMFFindAndOpenController::NewL(MMMFFindAndOpenControllerObserver& aObserver) + { + CMMFFindAndOpenController* self = new(ELeave) CMMFFindAndOpenController(aObserver); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CMMFFindAndOpenController::~CMMFFindAndOpenController() + { + Cancel(); + + // delete temporary variables + Close(); + + // this should cancel the AO + delete iAddDataSourceSinkAsync; + + delete iPrimaryConfig; + delete iSecondaryConfig; + } + +/** + * Function to free up memory after a successful open has completed + * Useful to allow a alloc testing to work. + * Must not be called if ReOpen() is to be called + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::Close() + { + + Cancel(); + + if(iAddDataSourceSinkAsync) + { + iAddDataSourceSinkAsync->Cancel(); + } + + if (iPrimaryConfig) + iPrimaryConfig->Close(); + if (iSecondaryConfig) + iSecondaryConfig->Close(); + + iPrioritisedControllers.Close(); + iControllers.ResetAndDestroy(); + iControllers.Close(); + + iFileName.SetLength(0); + iFileNameSecondary.SetLength(0); + + delete iUrl; + iUrl = NULL; + + delete iMimeType; + iMimeType = NULL; + + delete iUniqueId; + iUniqueId = NULL; + + if (iOwnFileHandle) + { + iFileHandle.Close(); + iOwnFileHandle = EFalse; + } + } +/** + * Function to free up memory of which is not required in ReOpen() + * after a successful open has completed + * Useful to allow a alloc testing to work. + * + * @internalComponent + */ + +EXPORT_C void CMMFFindAndOpenController::CloseConfig() + { + Cancel(); + if(iAddDataSourceSinkAsync) + { + iAddDataSourceSinkAsync->Cancel(); + } + + if (iSecondaryConfig) + { + iSecondaryConfig->Close(); + } + + iPrioritisedControllers.Close(); + iControllers.ResetAndDestroy(); + iControllers.Close(); + + iFileName.SetLength(0); + iFileNameSecondary.SetLength(0); + + delete iUrl; + iUrl = NULL; + + delete iMimeType; + iMimeType = NULL; + + delete iUniqueId; + iUniqueId = NULL; + + if (iOwnFileHandle) + { + iFileHandle.Close(); + iOwnFileHandle = EFalse; + } + } + +CMMFFindAndOpenController::CMMFFindAndOpenController(MMMFFindAndOpenControllerObserver& aObserver) : + CActive(EPriorityStandard), + iObserver(aObserver), + iDescriptor(NULL, 0) + { + CActiveScheduler::Add(this); + } + +void CMMFFindAndOpenController::ConstructL() + { + iAddDataSourceSinkAsync = CMMFAddDataSourceSinkAsync::NewL(*this); + iPrimaryConfig = new (ELeave) CConfig(); + iSecondaryConfig = new (ELeave) CConfig; + iCurrentConfig = iPrimaryConfig; + + RProcess thisProcess; + iHasDrmCapability = thisProcess.HasCapability(ECapabilityDRM, KSuppressPlatSecDiagnostic); + thisProcess.Close(); + } + +void CMMFFindAndOpenController::RunL() + { + Process(); + } + +void CMMFFindAndOpenController::DoCancel() + { + iAddDataSourceSinkAsync->Cancel(); + } + +/** + * Defines the media ID & priority to be used when opening a controller + * Normally called once only after class has been constructed + * + * @param aMediaId + * the media ID to use when searching for a controller + * e.g. KUidMediaTypeAudio + * @param aPrioritySettings + * the priority settings to use when opening a controller + * @param aMediaIdMatchType + * Defines the type of media id match to be performed on the plugins + * returned from the ECOM registry. + * @leave can leave with KErrNoMemory + + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::Configure( + TUid aMediaId, + TMMFPrioritySettings aPrioritySettings, + CMMFPluginSelectionParameters::TMediaIdMatchType aMediaIdMatchType) + { + iPrioritySettings = aPrioritySettings; + + iMediaIdMatchType = aMediaIdMatchType; + + iMediaId = aMediaId; + } + +void CMMFFindAndOpenController::ConfigureController( + CConfig& config, + RMMFController& aController, + CMMFControllerEventMonitor& aEventMonitor, + TControllerMode aControllerMode) + { + config.iController = &aController; + config.iEventMonitor = &aEventMonitor; + config.iControllerMode = aControllerMode; + } + +/** + * Configures the primary controller + * + * @param aController + * a reference to the client controller object to use + * @param aEventMonitor + * a reference to an event monitor object for receiving + * events from the controller + * @param aControllerMode + * indicates whether this controller is to be used for recording + * or playback + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::ConfigureController( + RMMFController& aController, + CMMFControllerEventMonitor& aEventMonitor, + TControllerMode aControllerMode) + { + ConfigureController( + *iPrimaryConfig, + aController, + aEventMonitor, + aControllerMode); + } + +/** + * Configures the secondary controller + * + * This is only needed for the audio recorder utility which opens + * one controller for playback and another for recording + * + * @param aController + * a reference to the client controller object to use + * @param aEventMonitor + * a reference to an event monitor object for receiving + * events from the controller + * @param aControllerMode + * indicates whether this controller is to be used for recording + * or playback or converting + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::ConfigureSecondaryController( + RMMFController& aController, + CMMFControllerEventMonitor& aEventMonitor, + TControllerMode aControllerMode) + { + ConfigureController( + *iSecondaryConfig, + aController, + aEventMonitor, + aControllerMode); + } + +/** + * Makes any controllers that are opened subsequently share a single heap. + * + * The default behaviour is that each controller is created with its own heap. + * Each heap uses a chunk, so using this function avoids situations where the number + * of chunks per process is limited. + * The default behaviour is generally to be preferred, and should give lower overall + * memory usage. However, if many controllers are to be created for a particular thread, + * then this function should be used to prevent running out of heaps or chunks. + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::UseSharedHeap() + { + iUseSharedHeap = ETrue; + } + +void CMMFFindAndOpenController::Init() + { + // This should be called prior to opening, so reset the error + iError = KErrNone; + iSourceSinkConfigured = EFalse; + iControllerCount = 0; + } + +void CMMFFindAndOpenController::ConfigureSourceSink( + CConfig& config, + TSourceSink aSource, + TSourceSink aSink) + { + TInt err; + TRAP(err, config.iSource = CreateSourceSinkL(aSource)); + if (err != KErrNone) + { + iError = err; + return; + } + + TRAP(err, config.iSink = CreateSourceSinkL(aSink)); + if (err != KErrNone) + { + iError = err; + return; + } + } + + +void CMMFFindAndOpenController::ConfigureSourceSink( + CConfig& config, + const TMMSource& aSource, + TSourceSink aSink) + { + TInt err; + TRAP(err, config.iSource = CreateSourceSinkL(aSource)); + if (err != KErrNone) + { + iError = err; + return; + } + + TRAP(err, config.iSink = CreateSourceSinkL(aSink)); + if (err != KErrNone) + { + iError = err; + return; + } + } + + + +/** + * Configure the primary controller's source and sink + * The descriptors passed to this function are copied so they do not need to be persistent. + * To simplify the API, any errors that occur are reported back asynchronously following + * a subsequent call to OpenByXXX() + * + * @param aSourceUid + * the UID of the data source + * @param aSourceData + * a reference to a descriptor used to configure the source + * @param aSinkUid + * the UID of the data sink + * @param aSinkData + * a reference to a descriptor used to configure the sink + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::ConfigureSourceSink( + TSourceSink aSource, + TSourceSink aSink) + { + + CConfig* config = NULL; + + Init(); + config = iPrimaryConfig; + + + // must have already called ConfigureController() + __ASSERT_ALWAYS(config->iController != NULL, CUPanic(EMMFMediaClientUtilityBadState)); + + ConfigureSourceSink( + *config, + aSource, + aSink); + iCurrentConfig = config; + + iSourceSinkConfigured = ETrue; + } + + +/** + * Configure the primary controller's source and sink + * The descriptors passed to this function are copied so they do not need to be persistent. + * To simplify the API, any errors that occur are reported back asynchronously following + * a subsequent call to OpenByXXX() + * + * @param aSourceUid + * the UID of the data source + * @param aSourceData + * a reference to a descriptor used to configure the source + * @param aSinkUid + * the UID of the data sink + * @param aSinkData + * a reference to a descriptor used to configure the sink + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::ConfigureSecondarySourceSink( + TSourceSink aSource, + TSourceSink aSink) + { + if (iError != KErrNone) + { + // if there was an error configuring the primary source/sink, do not try the secondary one + // Don't return the error, since the stored error will be returned by the OpenBy... method + return; + } + + CConfig* config = NULL; + + config = iSecondaryConfig; + + // must have already configured the primary controller + __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); + config = iSecondaryConfig; + + // must have already called ConfigureController() + __ASSERT_ALWAYS(config->iController != NULL, CUPanic(EMMFMediaClientUtilityBadState)); + + ConfigureSourceSink( + *config, + aSource, + aSink); + iCurrentConfig = config; + + iSourceSinkConfigured = ETrue; + } + + + +EXPORT_C void CMMFFindAndOpenController::ConfigureSourceSink( + const TMMSource& aSource, + TSourceSink aSink) + { + Init(); + CConfig* config = iPrimaryConfig; + + // must have already called ConfigureController() + __ASSERT_ALWAYS(config->iController != NULL, CUPanic(EMMFMediaClientUtilityBadState)); + + ConfigureSourceSink( + *config, + aSource, + aSink); + iCurrentConfig = config; + + iSourceSinkConfigured = ETrue; + } + + + +/** + * Opens a controller using the supplied controller UID + * and adds the source & sink + * Completion is indicated asynchonously by a call to MfaocComplete() + * + * @param aControllerUid + * the UID of the primary controller + * @param aControllerUid + * the UID of the secondary controller + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::OpenByControllerUid( + TUid aControllerUid, + TUid aSecondaryControllerUid) + { + // must have already called ConfigureSourceSink() + __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); + + // Have there been any errors so far ? + if (iError != KErrNone) + { + SchedSendError(); + return; + } + + if (iCurrentConfig == iPrimaryConfig) + { + // only do this for the playback controller + TRAP(iError, iCurrentConfig->iSource->EvaluateIntentL()) + + if (iError != KErrNone && + !(iCurrentConfig->iControllerMode == EPlayback && iError == KErrPermissionDenied && !iHasDrmCapability)) + { + // KErrPermissionDenied error and no DRM capability are not problems in Playback mode + // proper action will be performed when controller is loaded + SchedSendError(); + return; + } + } + + iPrimaryConfig->iControllerUid = aControllerUid; + if (iCurrentConfig == iSecondaryConfig) + { + if (aSecondaryControllerUid == KNullUid) + iSecondaryConfig->iControllerUid = aControllerUid; + else + iSecondaryConfig->iControllerUid = aSecondaryControllerUid; + } + + iMode = EOpenByControllerUid; + iControllerImplInfo = NULL; + iState = EOpenController; + KickState(); + } + +/** + * Opens a controller using the supplied file name + * and adds the source & sink + * A copy is made of the filename or file handle so that it need not be persistent + * Completion is indicated asynchonously by a call to MfaocComplete() + * + * @param aSource + * a reference to a TFileSource object to be used when searching + * for a controller + * @param aFileNameSecondary + * a reference to the seconday filename to be used when searching + * for a controller. This need only be supplied when converting + * between two files. + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::OpenByFileSource(const TMMSource& aSource, const TDesC& aFileNameSecondary) + { + // must have already called ConfigureSourceSink() + __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); + + TInt err; + // Have there been any errors so far ? + if (iError != KErrNone) + { + SchedSendError(); + return; + } + + if (iOwnFileHandle) + { + // in case of error + iFileHandle.Close(); + iOwnFileHandle = EFalse; + } + + iEnableUi = aSource.IsUIEnabled(); + if (aSource.SourceType()==KUidMMFileSource) + { + const TMMFileSource& fileSource = static_cast(aSource); + iFileName = fileSource.Name(); + iUseFileHandle = EFalse; + } + + if (aSource.SourceType()==KUidMMFileHandleSource) + { + const TMMFileHandleSource& fileHandleSource = static_cast(aSource); + ASSERT(iFileHandle.SubSessionHandle()==0); // closed just above + err = iFileHandle.Duplicate(fileHandleSource.Handle()); + if (err != KErrNone) + { + SchedSendError(err); + return; + } + iFileHandle.Name(iFileName); //ignore error return since we'll just do without the filename if not available + iUseFileHandle = ETrue; + iOwnFileHandle = ETrue; // because we dup'd it + } + + TRAP(err, iUniqueId = aSource.UniqueId().AllocL()); + iIntent = aSource.Intent(); + if (err != KErrNone) + { + SchedSendError(err); + return; + } + + + // take a copy of the secondary file name + iFileNameSecondary = aFileNameSecondary; + + iMode = EOpenByFileName; + iState = EBuildControllerList; + KickState(); + } + +/** + * Opens a controller using the supplied format UID + * and adds the source & sink + * Completion is indicated asynchonously by a call to MfaocComplete() + * + * @param aFormatUid + * the UID of a format that must be supported by the controller + * @param aFormatUidSecondary + * the UID of a secondary format that must be supported by the controller + * This need only be supplied when converting between two differnet formats. + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::OpenByFormatUid(TUid aFormatUid, TUid aFormatUidSecondary) + { + // must have already called ConfigureSourceSink() + __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); + + // Have there been any errors so far ? + if (iError != KErrNone) + { + SchedSendError(); + return; + } + + iFormatUid = aFormatUid; + iFormatUidSecondary = aFormatUidSecondary; + + iMode = EOpenByFormatUid; + iState = EBuildControllerList; + KickState(); + } + +/** + * Opens a controller using the supplied descriptor + * and adds the source & sink + * Completion is indicated asynchonously by a call to MfaocComplete() + * + * @param aDescriptor + * a reference to the descriptor to be used when searching + * for a controller + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::OpenByDescriptor(const TDesC8& aDescriptor) + { + // must have already called ConfigureSourceSink() + __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); + + // Have there been any errors so far ? + if (iError != KErrNone) + { + SchedSendError(); + return; + } + + // take a copy of the descriptor + TUint8* desBufferPtr = const_cast (aDescriptor.Ptr()); + iDescriptor.Set( desBufferPtr,aDescriptor.Length(),aDescriptor.Length()); + + iMode = EOpenByDescriptor; + iState = EBuildControllerList; + KickState(); + } + +/** + * Opens a controller using the supplied URL + * and adds the source & sink + * Completion is indicated asynchonously by a call to MfaocComplete() + * + * @param aUrl + * a reference to the URL to be used when searching for a controller + * @param aIapId + * the IAP ID to be used when searching for a controller + * @param aMimeType + * the MIME type of the data to be used when searching for a controller + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::OpenByUrl(const TDesC& aUrl, TInt aIapId, const TDesC8& aMimeType) + { + // must have already called ConfigureSourceSink() + __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); + + // Have there been any errors so far ? + if (iError != KErrNone) + { + SchedSendError(); + return; + } + + // take a copy of the Url + delete iUrl; + iUrl = NULL; + iUrl = aUrl.Alloc(); + if (iUrl == NULL) + { + SchedSendError(KErrNoMemory); + return; + } + + // take a copy of the IapId + iIapId = aIapId; + + // take a copy of the mime type + delete iMimeType; + iMimeType = NULL; + iMimeType = aMimeType.Alloc(); + if (iMimeType == NULL) + { + SchedSendError(KErrNoMemory); + return; + } + + iMode = EOpenByUrl; + iState = EBuildControllerList; + KickState(); + } + +/** + * Static function to return a TMMFFileConfig object + * suitable for passing to ConfigureSourceSink() + * + * @param aFileName + * the filename to use + * + * @internalComponent + */ +EXPORT_C TMMFFileConfig CMMFFindAndOpenController::GetConfigFile(const TDesC& aFileName) + { + TMMFFileConfig sourceSinkData; + sourceSinkData().iPath = aFileName; + return sourceSinkData; + } + +/** + * Static function to return a TMMFDescriptorConfig object + * suitable for passing to ConfigureSourceSink() + * + * @param aFileName + * the filename to use + * + * @internalComponent + */ +EXPORT_C TMMFDescriptorConfig CMMFFindAndOpenController::GetConfigDescriptor(const TDesC8& aDescriptor) + { + TMMFDescriptorConfig sourceSinkData; + sourceSinkData().iDes = (TAny*)&aDescriptor; + sourceSinkData().iDesThreadId = RThread().Id(); + return sourceSinkData; + } + +/** + * Static function to create a CBufFlat object + * suitable for passing to ConfigureSourceSink() + * + * @param aUrlCfgBuffer + * the reference to a caller-supplied pointer used to create + * a CBufFlat object. The caller is responsible for deletion. + * @param aUrl + * a reference to the URL to be used + * @param aIapId + * the IAP ID to be used + * @return can return KErrNone or KErrNoMemory + * + * @internalComponent + */ + +EXPORT_C void CMMFFindAndOpenController::GetConfigUrlL(CBufFlat*& aUrlCfgBuffer, const TDesC& aUrl, TInt aIapId) + { + delete aUrlCfgBuffer; + aUrlCfgBuffer = NULL; + + CMMFUrlParams* urlCfg = CMMFUrlParams::NewL(aUrl,aIapId); + CleanupStack::PushL(urlCfg); + aUrlCfgBuffer = urlCfg->ExternalizeToCBufFlatLC(); + CleanupStack::Pop(aUrlCfgBuffer); + CleanupStack::PopAndDestroy(urlCfg); + } +/** + * ReOpens the previously opened primary controller + * + * @internalComponent + */ +EXPORT_C void CMMFFindAndOpenController::ReOpen() + { + // should already have a valid controller uid so just open it + iControllerImplInfo = NULL; + iState = EOpenController; + KickState(); + } + +void CMMFFindAndOpenController::OpenPrimaryController(void) + { + iCurrentConfig = iPrimaryConfig; + switch(iMode) + { + case EOpenByFileName: + case EOpenByFormatUid: + case EOpenByDescriptor: + case EOpenByUrl: + iState = EBuildControllerList; + break; + case EOpenByControllerUid: + iControllerImplInfo = NULL; + iState = EOpenController; + break; + } + KickState(); + } + +void CMMFFindAndOpenController::KickState() + { + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + SetActive(); + } + +void CMMFFindAndOpenController::CloseController() + { + if (iCurrentConfig->iEventMonitor) + iCurrentConfig->iEventMonitor->Cancel(); + iCurrentConfig->iController->Close(); + } + +void CMMFFindAndOpenController::Process() + { + switch(iState) + { + case EBuildControllerList: + switch(iMode) + { + case EOpenByFileName: + TRAP(iError, BuildControllerListFileNameL()); + break; + case EOpenByDescriptor: + TRAP(iError, BuildControllerListDescriptorL()); + break; + case EOpenByUrl: + TRAP(iError, BuildControllerListUrlL()); + break; + case EOpenByFormatUid: + TRAP(iError, BuildControllerListFormatL()); + break; + default: + CUPanic(EMMFMediaClientUtilityBadState); + } + + if (iError != KErrNone) + { + iState = EIdle; + SendError(); + break; + } + + // try the first controller + iControllerIndex = -1; + TryNextController(); + break; + + case EOpenController: + { + // Make sure any existing controller is closed. + CloseController(); + + TBool isSecureDrmProcess = EFalse;// need to keep it false as UseSecureDRMProcess may return error + // Loading controller in new threading model is enabled only in playback mode + TUid sourceUid = iCurrentConfig->iSource->SourceSinkUid(); + TBool localPlaybackMode = iCurrentConfig->iControllerMode == EPlayback && + (sourceUid == KUidMmfFileSource || sourceUid == KUidMmfDescriptorSource); + if(localPlaybackMode) + { + TRAPD(err,UseSecureDRMProcessL(isSecureDrmProcess)); + if(err == KErrPermissionDenied) + { + isSecureDrmProcess = ETrue; + } + else if(err != KErrNone) + { + iError = err; + SendError(err); + return; + } + } + // Open the controller + if (iControllerImplInfo) + { + if(isSecureDrmProcess && localPlaybackMode) + { + iError = iCurrentConfig->iController->OpenInSecureDRMProcess(*iControllerImplInfo, iPrioritySettings, iUseSharedHeap); + iUsingSecureDrmProcess = ETrue; + } + else + { + iError = iCurrentConfig->iController->Open(*iControllerImplInfo, iPrioritySettings, iUseSharedHeap); + iUsingSecureDrmProcess = EFalse;; + } + } + else + { + if(isSecureDrmProcess && localPlaybackMode) + { + iError = iCurrentConfig->iController->OpenInSecureDRMProcess(iCurrentConfig->iControllerUid, iPrioritySettings, iUseSharedHeap); + iUsingSecureDrmProcess = ETrue; + + } + else + { + iError = iCurrentConfig->iController->Open(iCurrentConfig->iControllerUid, iPrioritySettings, iUseSharedHeap); + iUsingSecureDrmProcess = EFalse; + } + } + //in case of error, including KErrNomemory try next controller + if (iError) + { + TryNextController(); + } + else + { + #ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT + #ifndef SYMBIAN_BUILD_GCE + if(iCurrentConfig->iControllerMode == EPlayback && iMediaId == KUidMediaTypeVideo) + { + iError = iVideoSetInitScreenCustomCommands->SetInitScreenNumber(iScreenNumber); + if(iError) + { + if (iError == KErrNotSupported && iScreenNumber == KDefaultScreenNo) + { + iError = KErrNone; + } + else + { + iState = EIdle; + SendError(); + break; + } + } + } + #endif // SYMBIAN_BUILD_GCE + #endif // SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT + iCurrentConfig->iEventMonitor->Start(); + + if (iCurrentConfig == iSecondaryConfig) + { + iState = EAddSource; + KickState(); + } + else + { + iState = EAddSink; + KickState(); + } + } + } + break; + + case EAddSource: + { + iState = EWaitingForSource; + const CMMSourceSink* source = iCurrentConfig->iSource; + // CMMSourceSink has the ability to transform the data it stored into a data stream + // which can be passed to CMMFAddDataSourceSinkAsync for further processing. + // CMMFileSourceSink, which is a specialized CMMSourceSink, stores info about a file + // source/sink. The info about the file can be a file path or a file handle. + // When it holds a file handle and turns info into data stream, the file handle is + // stored as a pointer in the stream. However, at this point, it cannot guarantee that + // the streamed info is always extracted within the same process. If the pointer is + // dereferenced in other process, a panic will raise in the system. Therefore, a file + // handle, rather than pointer, is used when necessary. + if (iUsingSecureDrmProcess && source->CarryingFileHandle()) + { + iAddDataSourceSinkAsync->AddFileHandleDataSource(*iCurrentConfig->iController, + static_cast(source)->FileHandle(), + source->SourceSinkData()); + } + else + { + iAddDataSourceSinkAsync->AddDataSource(*iCurrentConfig->iController, + source->SourceSinkUid(), + source->SourceSinkData()); + } + } + break; + + case EAddSink: + { + iState = EWaitingForSink; + const CMMSourceSink* sink = iCurrentConfig->iSink; + // CMMSourceSink has the ability to transform the data it stored into a data stream + // which can be passed to CMMFAddDataSourceSinkAsync for further processing. + // CMMFileSourceSink, which is a specialized CMMSourceSink, stores info about a file + // source/sink. The info about the file can be a file path or a file handle. + // When it holds a file handle and turns info into data stream, the file handle is + // stored as a pointer in the stream. However, at this point, it cannot guarantee that + // the streamed info is always extracted within the same process. If the pointer is + // dereferenced in other process, a panic will raise in the system. Therefore, a file + // handle, rather than pointer, is used when necessary. + const TDesC8& sinkData = sink->SourceSinkData(); + if (iUsingSecureDrmProcess && sink->CarryingFileHandle()) + { + iAddDataSourceSinkAsync->AddFileHandleDataSink(*iCurrentConfig->iController, + static_cast(sink)->FileHandle(), + sinkData); + } + else + { + iAddDataSourceSinkAsync->AddDataSink(*iCurrentConfig->iController, + sink->SourceSinkUid(), + sinkData); + } + } + break; + + case EWaitingForSource: + break; + + case EWaitingForSink: + break; + + case ESendError: + SendError(); + iState = EIdle; + break; + + case EIdle: + default: + break; + } + } + +void CMMFFindAndOpenController::TryNextController() + { + // If an error occurred close the controller. + if (iError != KErrNone) + { + CloseController(); + } + + iStopTryLoadController = EFalse; + + if (iMode == EOpenByControllerUid || ++iControllerIndex >= iControllerCount) + { + //Raise a flag to stop trying to load the controllers + iStopTryLoadController = ETrue; + + // KErrNotSupported is the default error, but will only be used if no other error + // has been discovered (the first error found is used by default) + // However, KErrBadHandle seems to mean that we tried to use the DRM server without + // RFs::ShareProtected() having been called, so force usage of KErrNotSupported so + // client does not see changed + TBool forceErrorUse = EFalse; + if (iError==KErrBadHandle) + { + forceErrorUse = ETrue; + } + SendError(KErrNotSupported, forceErrorUse); + + return; + } + + if (iMode == EOpenByFileName || iMode == EOpenByFormatUid) + { + iControllerImplInfo = iPrioritisedControllers[iControllerIndex]; + } + else //if (iMode == EOpenByDescriptor || iMode == EOpenByUrl) + { + iControllerImplInfo = iControllers[iControllerIndex]; + } + + iCurrentConfig->iControllerUid = iControllerImplInfo->Uid(); + iState = EOpenController; + KickState(); + } + +void CMMFFindAndOpenController::MadssaoAddDataSourceSinkAsyncComplete(TInt aError, const TMMFMessageDestination& aHandle) + { + iError = aError; + + // take the first available exit if we're out of memory + // or we've been cancelled + if (iError == KErrNoMemory || iError == KErrCancel) + { + SendError(); + return; + } + + // failed to add source or sink - try the next controller + if (aError != KErrNone) + { + TryNextController(); + return; + } + + if (iState == EWaitingForSource) + { + #ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT + #ifdef SYMBIAN_BUILD_GCE + // If surfaces are required try to use them. If this fails then fall back to using + // direct screen access. + if(iCurrentConfig->iControllerMode == EPlayback && iMediaId == KUidMediaTypeVideo) + { + // UseSurfaces call has to be done after adding data sink and adding data source. + iSurfaceSupported = iVideoPlaySurfaceSupportCustomCommands->UseSurfaces(); + + if (iSurfaceSupported == KErrNotSupported) + { + if (iUseVPU2) + { + if (ControllerIndex() < ControllerCount() - 1) + { + // Until end of the list of controllers, + // try the next one for surface support + TryNextController(); // this will also kick-state + return; + } + else + { + iError = iSurfaceSupported; + } + } + else + { + // No surface enabled controller found + // not required to do only surface, + // use the last one that matched. + iError = iVideoSetInitScreenCustomCommands->SetInitScreenNumber(iScreenNumber); + if (iError == KErrNotSupported && iScreenNumber == KDefaultScreenNo) + { + iError = KErrNone; + } + } + } + else + { + iError = iSurfaceSupported; + } + } + #endif // SYMBIAN_BUILD_GCE + #endif // SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT + + iSourceHandle = aHandle; + if (iCurrentConfig == iSecondaryConfig) + { + iState = EAddSink; + } + else // completed ok ! + { + iState = EIdle; + SendError(KErrNone, ETrue); + return; + } + } + else if (iState == EWaitingForSink) + { + iSinkHandle = aHandle; + if (iCurrentConfig == iSecondaryConfig) // completed ok ! + { + iState = EIdle; + iError = KErrNone; + SendError(); + return; + } + else + { + iState = EAddSource; + } + } + + KickState(); + } + +void CMMFFindAndOpenController::SendError(TInt aError, TBool aOverrideError) + { + if (iError == KErrNone || aOverrideError) + { + iError = aError; + } + + iObserver.MfaocComplete(iError, iCurrentConfig->iController, iCurrentConfig->iControllerUid, &iSourceHandle, &iSinkHandle); + + // if we've just attempted to open the Secondary controller, + // try to open the Primary controller + if (iCurrentConfig == iSecondaryConfig) + { + if (iError == KErrNone) + OpenPrimaryController(); + } + + // if we failed to open, may as well free up some memory + // if open succeeded we need to preserve state in case of a re-open + if (iError != KErrNone) + { + if(iControllerIndex >= iControllerCount-1) + { + Close(); + } + else //if there are other controllers selected in the controller list, try them + { + Cancel(); + if(iAddDataSourceSinkAsync) + { + iAddDataSourceSinkAsync->Cancel(); + } + + TryNextController(); + } + } + } + +void CMMFFindAndOpenController::SchedSendError(TInt aError) + { + if (aError != KErrNone) + iError = aError; + iState = ESendError; + KickState(); + } + +void CMMFFindAndOpenController::BuildControllerListFileNameL() + { + // Retrieve a list of possible controllers from ECOM + // If we don't have a match, leave with unsupported + + iControllers.ResetAndDestroy(); + iPrioritisedControllers.Reset(); + + TControllerMode mode = iCurrentConfig->iControllerMode; + + // if we're playing, try to get the MIME type from the Content Access + // Framework (CAF) & use that to select a controller - if that fails, + // try to select a controller based on the header data/file extension + + CMMFUtilityFileInfo* fileInfo = NULL; + + TInt error; + + //If the current CMMSourceSink is a CMMFileSourceSink + // Using the previous version we'd get KErrCANoPermission when calling EvaluateIntent in the + // CMMFUtilityFileInfo ConstructL as the intent == EUnknown, so now pass the intent as a parameter + // to TMMFileHandleSource and.... + TBool isSecureDrmProcess = EFalse; + //need to do this only in local playback mode + //UseSecureDRMProcess() function in called only in case of local play / record + // so we'll just chk for playback mode + if(mode == EPlayback) + { + TRAP(error, UseSecureDRMProcessL(isSecureDrmProcess)); + if(error == KErrPermissionDenied) + { + isSecureDrmProcess = ETrue; + } + else + { + User::LeaveIfError(error); + } + } + TRAP(error, fileInfo = CreateFileInfoL(isSecureDrmProcess)); + + if (fileInfo != NULL) + { + CleanupDeletePushL(fileInfo); + } + + if (error != KErrNone) + { + // if playback mode, leave for any error + // if record mode, allow KErrNotFound + if (mode == EPlayback || (mode != EPlayback && error != KErrNotFound)) + { + User::Leave(error); + } + } + + CMMFControllerPluginSelectionParameters* cSelect = NULL; + if (isSecureDrmProcess) + { + cSelect = CMMFControllerSecureDrmPluginSelectionParameters::NewLC(); + } + else + { + cSelect = CMMFControllerPluginSelectionParameters::NewLC(); + } + RArray mediaIds; + CleanupClosePushL(mediaIds); + User::LeaveIfError(mediaIds.Append(iMediaId)); + + cSelect->SetMediaIdsL(mediaIds, iMediaIdMatchType); + + if (mode == EPlayback) + { + ASSERT(fileInfo!=NULL); + TBuf8 mimeType; + TBool mimeTypeKnown = fileInfo->GetFileMimeTypeL(mimeType); + if (mimeTypeKnown) + { + CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); + fSelect->SetMatchToMimeTypeL(mimeType); + cSelect->SetRequiredPlayFormatSupportL(*fSelect); + cSelect->ListImplementationsL(iControllers); + CleanupStack::PopAndDestroy(fSelect); + } + + + // copy to the iPrioritisedControllers array - this is a NOOP if the + // MIME type is not known since iControllers will be empty + ASSERT(mimeTypeKnown || iControllers.Count() == 0); + for (TInt controllerIndex=0; controllerIndex < iControllers.Count(); controllerIndex++) + User::LeaveIfError(iPrioritisedControllers.Append(iControllers[controllerIndex])); + + iControllerCount = iPrioritisedControllers.Count(); + if (iControllerCount > 0) + { + // Clean up + // cSelect, mediaIds, + CleanupStack::PopAndDestroy(2, cSelect); + if (fileInfo != NULL) + { + CleanupStack::PopAndDestroy(fileInfo); + } + return; + } + } + + // Retrieve header data first. If file doesn't exist, its ok. + HBufC8* headerData = HBufC8::NewLC(KMaxHeaderSize); + TPtr8 headerDataPtr = headerData->Des(); + if (fileInfo) + { + fileInfo->GetFileHeaderDataL(headerDataPtr, KMaxHeaderSize); + } + + // Get the filename's suffix + HBufC8* fileSuffix = CMMFClientUtility::GetFileExtensionL(iFileName); + + CleanupStack::PushL(fileSuffix); + TPtr8 fileSuffixPtr = fileSuffix->Des(); + + // Get the secondary filename's header data (for convert) + HBufC8* headerDataSecondary = HBufC8::NewLC(KMaxHeaderSize); + TPtr8 headerDataPtrSecondary = headerDataSecondary->Des(); + if (iFileNameSecondary.Length() > 0 && fileInfo) + { + fileInfo->GetFileHeaderDataL(headerDataPtrSecondary, KMaxHeaderSize); + } + + // Get the secondary filename's suffix + HBufC8* fileSuffixSecondary = CMMFClientUtility::GetFileExtensionL(iFileNameSecondary); + CleanupStack::PushL(fileSuffixSecondary); + TPtr8 fileSuffixPtrSecondary = fileSuffixSecondary->Des(); + + + CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); + + if (mode == EPlayback || mode == EConvert) + cSelect->SetRequiredPlayFormatSupportL(*fSelect); + if (mode == ERecord || mode == EConvert) + cSelect->SetRequiredRecordFormatSupportL(*fSelect); + + cSelect->ListImplementationsL(iControllers); + + if (iControllers.Count()==0) + User::Leave(KErrNotSupported); + + if (mode == ERecord) + { + CMMFClientUtility::PrioritiseControllersL( + iControllers, + headerDataPtrSecondary, + fileSuffixPtrSecondary, + headerDataPtr, + fileSuffixPtr, + iPrioritisedControllers); + } + else + { + CMMFClientUtility::PrioritiseControllersL( + iControllers, + headerDataPtr, + fileSuffixPtr, + headerDataPtrSecondary, + fileSuffixPtrSecondary, + iPrioritisedControllers); + } + + iControllerCount = iPrioritisedControllers.Count(); + if (iControllerCount == 0) + User::Leave(KErrNotSupported); + + // Clean up + // cSelect, mediaIds, + // headerData, fileSuffix, headerDataSecondary, fileSuffixSecondary, + // fSelect + CleanupStack::PopAndDestroy(7, cSelect); + if (fileInfo != NULL) + { + CleanupStack::PopAndDestroy(fileInfo); + } + } + +void CMMFFindAndOpenController::BuildControllerListDescriptorL() + { + // Retrieve a list of possible controllers from ECOM + // If we don't have a match, leave with unsupported + + iControllers.ResetAndDestroy(); + + CMMFControllerPluginSelectionParameters* cSelect = CMMFControllerPluginSelectionParameters::NewLC(); + CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); + + + RArray mediaIds; + CleanupClosePushL(mediaIds); + User::LeaveIfError(mediaIds.Append(iMediaId)); + + cSelect->SetMediaIdsL(mediaIds, iMediaIdMatchType); + + TPtrC8 header = iDescriptor.Left(KMaxHeaderSize); + fSelect->SetMatchToHeaderDataL(header); + + + TControllerMode mode = iCurrentConfig->iControllerMode; + if (mode == EPlayback || mode == EConvert) + cSelect->SetRequiredPlayFormatSupportL(*fSelect); + if (mode == ERecord || mode == EConvert) + cSelect->SetRequiredRecordFormatSupportL(*fSelect); + + cSelect->ListImplementationsL(iControllers); + + iControllerCount = iControllers.Count(); + if (iControllerCount == 0) + User::Leave(KErrNotSupported); + + // Clean up + // cSelect, fSelect, mediaIds + CleanupStack::PopAndDestroy(3, cSelect); + } + +void CMMFFindAndOpenController::BuildControllerListUrlL() + { + // Retrieve a list of possible controllers from ECOM + // If we don't have a match, leave with unsupported + + iControllers.ResetAndDestroy(); + + CMMFControllerPluginSelectionParameters* cSelect = CMMFControllerPluginSelectionParameters::NewLC(); + CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); + + RArray mediaIds; + CleanupClosePushL(mediaIds); + User::LeaveIfError(mediaIds.Append(iMediaId)); + + cSelect->SetMediaIdsL(mediaIds, iMediaIdMatchType); + + + if (*iMimeType != KNullDesC8) + { + fSelect->SetMatchToMimeTypeL(*iMimeType);//We match to mime type + } + else + { + fSelect->SetMatchToUriSupportL(*iUrl); + } + + TControllerMode mode = iCurrentConfig->iControllerMode; + if (mode == EPlayback || mode == EConvert) + cSelect->SetRequiredPlayFormatSupportL(*fSelect); + if (mode == ERecord || mode == EConvert) + cSelect->SetRequiredRecordFormatSupportL(*fSelect); + + cSelect->ListImplementationsL(iControllers); + + iControllerCount = iControllers.Count(); + if (iControllerCount == 0) + User::Leave(KErrNotSupported); + + // Clean up + // cSelect, fSelect, mediaIds + CleanupStack::PopAndDestroy(3, cSelect); + } + +void CMMFFindAndOpenController::BuildControllerListFormatL() + { + // Retrieve a list of possible controllers from ECOM + // If we don't have a match, leave with unsupported + + iControllers.ResetAndDestroy(); + iPrioritisedControllers.Reset(); + + CMMFControllerPluginSelectionParameters* cSelect = CMMFControllerPluginSelectionParameters::NewLC(); + + // Select the media IDs to allow + RArray mediaIds; + CleanupClosePushL(mediaIds); + User::LeaveIfError(mediaIds.Append(iMediaId)); + + cSelect->SetMediaIdsL(mediaIds, iMediaIdMatchType); + + CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); + + TControllerMode mode = iCurrentConfig->iControllerMode; + if (mode == EPlayback || mode == EConvert) + cSelect->SetRequiredPlayFormatSupportL(*fSelect); + if (mode == ERecord || mode == EConvert) + cSelect->SetRequiredRecordFormatSupportL(*fSelect); + + //Obtain a list of the controllers + cSelect->ListImplementationsL(iControllers); + + CleanupStack::PopAndDestroy(3, cSelect); // cSelect, mediaIds, fSelect + + iControllerCount = iControllers.Count(); + if (iControllerCount == 0) + User::Leave(KErrNotSupported); + + TUid formatUidPrimary; + TUid formatUidSecondary; + if (mode == ERecord) + { + formatUidSecondary = iFormatUid; + formatUidPrimary = iFormatUidSecondary; + } + else + { + formatUidPrimary = iFormatUid; + formatUidSecondary = iFormatUidSecondary; + } + + for (TInt controllerIndex=0; controllerIndex < iControllers.Count(); controllerIndex++) + { + const RMMFFormatImplInfoArray& recFormatInfo = iControllers[controllerIndex]->RecordFormats(); + const RMMFFormatImplInfoArray& playFormatInfo = iControllers[controllerIndex]->PlayFormats(); + + TBool playFormatMatched = EFalse; + TBool recordFormatMatched = EFalse; + + if (formatUidPrimary == KNullUid) + { + playFormatMatched = ETrue; + } + else + { + for(TInt playFormatIndex =0; playFormatIndex < playFormatInfo.Count(); playFormatIndex++) + { + if(playFormatInfo[playFormatIndex]->Uid() == formatUidPrimary) + { + playFormatMatched = ETrue; + break; + } + } + } + + if (formatUidSecondary == KNullUid) + { + recordFormatMatched = ETrue; + } + else + { + for (TInt recFormatIndex =0; recFormatIndex < recFormatInfo.Count(); recFormatIndex++) + { + if (recFormatInfo[recFormatIndex]->Uid() == formatUidSecondary) + { + recordFormatMatched = ETrue; + break; + } + } + } + + if (playFormatMatched && recordFormatMatched) + User::LeaveIfError(iPrioritisedControllers.Append(iControllers[controllerIndex])); + } + + iControllerCount = iPrioritisedControllers.Count(); + if (iControllerCount == 0) + User::Leave(KErrNotSupported); + } + +CMMSourceSink* CMMFFindAndOpenController::CreateSourceSinkL(const TSourceSink& aParams) + { + if (aParams.iUseFileHandle) + { + return CMMFileSourceSink::NewL(aParams.iUid, aParams.iFileHandle); + } + return CMMSourceSink::NewL(aParams.iUid, aParams.iConfigData); + } + + +CMMSourceSink* CMMFFindAndOpenController::CreateSourceSinkL(const TMMSource& aSource) + { + if (!(aSource.SourceType()==KUidMMFileSource || + aSource.SourceType()==KUidMMFileHandleSource)) + User::Leave(KErrNotSupported); + + return CMMFileSourceSink::NewL(KUidMmfFileSource, aSource); + } + +CMMFUtilityFileInfo* CMMFFindAndOpenController::CreateFileInfoL(TBool aSecureDRMMode) + { + CMMFUtilityFileInfo* fileInfo = NULL; + if (iUseFileHandle) + { + if (iUniqueId != NULL) + { + TMMFileHandleSource fileHandleSource(iFileHandle, (*iUniqueId), iIntent,iEnableUi); + fileInfo = CMMFUtilityFileInfo::NewL(fileHandleSource, aSecureDRMMode); + } + else + { + TMMFileHandleSource fileHandleSource(iFileHandle); + fileInfo = CMMFUtilityFileInfo::NewL(fileHandleSource, aSecureDRMMode); + } + } + else + { + if (iUniqueId != NULL) + { + TMMFileSource fileSource(iFileName, (*iUniqueId), iIntent,iEnableUi); + fileInfo = CMMFUtilityFileInfo::NewL(fileSource, aSecureDRMMode); + } + else + { + TMMFileSource fileSource(iFileName); + fileInfo = CMMFUtilityFileInfo::NewL(fileSource, aSecureDRMMode); + } + } + return fileInfo; + } + +EXPORT_C CMMFFindAndOpenController::TSourceSink::TSourceSink(TUid aUid, const TDesC8& aConfigData) + : iConfigData(aConfigData) + { + iUid = aUid; + + iUseFileHandle = EFalse; + } + +EXPORT_C CMMFFindAndOpenController::TSourceSink::TSourceSink(TUid aUid, const RFile& aFile) + : iConfigData(KNullDesC8) + { + iUid = aUid; + + iFileHandle = aFile; + iUseFileHandle = ETrue; + } + +EXPORT_C void CMMFFindAndOpenController::SetInitScreenNumber(TInt aScreenNumber, RMMFVideoSetInitScreenCustomCommands* aVideoSetInitScreenCustomCommands) + { + iScreenNumber = aScreenNumber; + iVideoSetInitScreenCustomCommands = aVideoSetInitScreenCustomCommands; + } + +CMMFFindAndOpenController::CConfig::CConfig() + { + } + +void CMMFFindAndOpenController::CConfig::Close() + { + delete iSource; + iSource = NULL; + delete iSink; + iSink = NULL; + } +CMMFFindAndOpenController::CConfig::~CConfig() + { + Close(); + } + +void CMMFFindAndOpenController::UseSecureDRMProcessL(TBool& aIsSecureDrmProcess) + { + if(iHasDrmCapability)//if client has DRM capability, we never use Secure DRM Process + { + aIsSecureDrmProcess = EFalse; + return; + } + TBool isDataProtected = EFalse; + ContentAccess::CContent* content = NULL; + TControllerMode mode = iCurrentConfig->iControllerMode; + + //setting aUseSecureDrmProcess to false(default value) + aIsSecureDrmProcess = EFalse; + + //need to proceed only in case of local playback mode + TUid sourceUid = iCurrentConfig->iSource->SourceSinkUid(); + TBool localPlaybackMode = ( mode == EPlayback && + (sourceUid == KUidMmfFileSource || sourceUid == KUidMmfDescriptorSource) ); + if(!localPlaybackMode) + { + return; + } + + if (iUseFileHandle && iOwnFileHandle) + { + content = ContentAccess::CContent::NewLC(iFileHandle); + } + else if(iFileName.Length()) //need to check if file name exist + { + content = ContentAccess::CContent::NewLC(iFileName); + } + else + {//in case of descriptor source content object will not be created + return; + } + TInt value = 0; + TInt error = KErrNone; + if(iUniqueId != NULL) + { + error = content->GetAttribute(EIsProtected, value, *iUniqueId ); + } + else + { + error = content->GetAttribute(EIsProtected, value); + } + if( (error == KErrNone && value) || error == KErrPermissionDenied ) + {//2nd condition can be true if GetAttribute checks for DRM cap and return error if not found + isDataProtected = ETrue; + } + else if( error != KErrNone && error != KErrPermissionDenied) + {//leaving as GetAttribute of CAF caused an error. + User::Leave(error); + } + + CleanupStack::PopAndDestroy(content); + if(isDataProtected && !iHasDrmCapability && mode == EPlayback) + {//only when the Data is protected and client does not have the DRM capability, we need secure DRM process + aIsSecureDrmProcess = ETrue; + } + } + +EXPORT_C CMMSourceSink* CMMSourceSink::NewLC(TUid aUid, const TDesC8& aDescriptor) + { + CMMSourceSink* self = new (ELeave) CMMSourceSink(aUid); + CleanupStack::PushL(self); + self->ConstructL(aDescriptor); + return self; + } + +EXPORT_C CMMSourceSink* CMMSourceSink::NewL(TUid aUid, const TDesC8& aDescriptor) + { + CMMSourceSink* sourcesink = CMMSourceSink::NewLC(aUid, aDescriptor); + CleanupStack::Pop(sourcesink); + return sourcesink; + } + +CMMSourceSink::CMMSourceSink(TUid aUid) + : iUid(aUid) + { + } + +CMMSourceSink::~CMMSourceSink() + { + delete iBuf; + } + +void CMMSourceSink::ConstructL(const TDesC8& aDescriptor) + { + iBuf = aDescriptor.AllocL(); + } + +TUid CMMSourceSink::SourceSinkUid() const + { + return iUid; + } + +const TDesC8& CMMSourceSink::SourceSinkData() const + { + return *iBuf; + } + +TBool CMMSourceSink::CarryingFileHandle() const + { + return EFalse; + } + +EXPORT_C CMMFileSourceSink* CMMFileSourceSink::NewLC(TUid aUid, const RFile& aFile) + { + CMMFileSourceSink* self = new (ELeave) CMMFileSourceSink(aUid); + CleanupStack::PushL(self); + self->ConstructL(aFile); + return self; + } + +EXPORT_C CMMFileSourceSink* CMMFileSourceSink::NewL(TUid aUid, const RFile& aFile) + { + CMMFileSourceSink* sourcesink = CMMFileSourceSink::NewLC(aUid, aFile); + CleanupStack::Pop(sourcesink); + return sourcesink; + } + +CMMFileSourceSink::CMMFileSourceSink(TUid aUid) + : CMMSourceSink(aUid) + { + } + +void CMMFileSourceSink::ConstructL(const RFile& aFile) + { + User::LeaveIfError(iHandle.Duplicate(aFile)); + iUsingFileHandle = ETrue; + iFileName = HBufC::NewMaxL(KMaxFileName); + TPtr fileNamePtr = iFileName->Des(); + iHandle.Name(fileNamePtr); + DoCreateFileHandleSourceConfigDataL(); + } + +void CMMFileSourceSink::DoCreateFileHandleSourceConfigDataL() + { + CBufFlat* buf = CBufFlat::NewL(KExpandSize); + CleanupStack::PushL(buf); + RBufWriteStream stream; + stream.Open(*buf); + CleanupClosePushL(stream); + + TPckgBuf fileptr(&iHandle); + stream.WriteInt32L(KMMFileHandleSourceUid.iUid); + stream.WriteL(fileptr); + + TInt length = 0; + if (iUniqueId != NULL) + length = iUniqueId->Length(); + stream.WriteInt32L(length); + if (length>0) + stream.WriteL(*iUniqueId); + + stream.WriteInt32L(iEnableUI); + + stream.CommitL(); + CleanupStack::PopAndDestroy(&stream); + iSourceSinkData = buf->Ptr(0).AllocL(); + + CleanupStack::PopAndDestroy(buf); + } + +const TDesC8& CMMFileSourceSink::SourceSinkData() const + { + ASSERT(iSourceSinkData); + return *iSourceSinkData; + } + +CMMFileSourceSink::~CMMFileSourceSink() + { + iHandle.Close(); // delete whatever + delete iFileName; + delete iSourceSinkData; + delete iUniqueId; + } + +EXPORT_C CMMFileSourceSink* CMMFileSourceSink::NewLC(TUid aUid, const TMMSource& aSource) + { + CMMFileSourceSink* self = new (ELeave) CMMFileSourceSink(aUid); + CleanupStack::PushL(self); + self->ConstructL(aSource); + return self; + } + +EXPORT_C CMMFileSourceSink* CMMFileSourceSink::NewL(TUid aUid, const TMMSource& aSource) + { + CMMFileSourceSink* sourcesink = CMMFileSourceSink::NewLC(aUid, aSource); + CleanupStack::Pop(sourcesink); + return sourcesink; + } + +void CMMFileSourceSink::ConstructL(const TMMSource& aSource) + { + iUniqueId = aSource.UniqueId().AllocL(); + iIntent = aSource.Intent(); + iEnableUI = aSource.IsUIEnabled(); + + if (aSource.SourceType() == KUidMMFileSource) + { + const TMMFileSource& fileSource = static_cast(aSource); + iFileName = fileSource.Name().AllocL(); + + DoCreateFileSourceConfigDataL(); + } + else if (aSource.SourceType() == KUidMMFileHandleSource) + { + const TMMFileHandleSource& fileHandleSource = static_cast(aSource); + iHandle.Close(); // in case already open + User::LeaveIfError(iHandle.Duplicate(fileHandleSource.Handle())); + iUsingFileHandle = ETrue; + iFileName = HBufC::NewMaxL(KMaxFileName); + TPtr fileNamePtr = iFileName->Des(); + iHandle.Name(fileNamePtr); + + DoCreateFileHandleSourceConfigDataL(); + } + else + { + User::Leave(KErrNotSupported); + } + } + +void CMMSourceSink::EvaluateIntentL() + { + } + +void CMMFileSourceSink::EvaluateIntentL() + { + if (iUsingFileHandle) + { + ContentAccess::CContent* Content = ContentAccess::CContent::NewLC(iHandle); + Content->OpenContentLC(iIntent, *iUniqueId); + CleanupStack::PopAndDestroy(2, Content); + } + else + { + ContentAccess::CContent* Content = ContentAccess::CContent::NewLC(*iFileName); + Content->OpenContentLC(iIntent, *iUniqueId); + CleanupStack::PopAndDestroy(2, Content); + } + } + + + +EXPORT_C void CMMFileSourceSink::EvaluateIntentL(ContentAccess::TIntent aIntent) + { + if (iUsingFileHandle) + { + ContentAccess::CContent* Content = ContentAccess::CContent::NewLC(iHandle); + Content->OpenContentLC(aIntent, *iUniqueId); + CleanupStack::PopAndDestroy(2, Content); + } + else + { + ContentAccess::CContent* Content = ContentAccess::CContent::NewLC(*iFileName); + Content->OpenContentLC(aIntent, *iUniqueId); + CleanupStack::PopAndDestroy(2, Content); + } + } + +void CMMFileSourceSink::DoCreateFileSourceConfigDataL() + { + CBufFlat* buf = CBufFlat::NewL(KExpandSize); + CleanupStack::PushL(buf); + RBufWriteStream stream; + stream.Open(*buf); + CleanupClosePushL(stream); + + stream.WriteInt32L(KMMFileSourceUid.iUid); + stream.WriteInt32L(iFileName->Length()); + stream.WriteL(*iFileName); + TInt length = 0; + if (iUniqueId != NULL) + length = iUniqueId->Length(); + stream.WriteInt32L(length); + if (length>0) + stream.WriteL(*iUniqueId); + + stream.WriteInt32L(iEnableUI); + + stream.CommitL(); + CleanupStack::PopAndDestroy(&stream); + iSourceSinkData = buf->Ptr(0).AllocL(); + + CleanupStack::PopAndDestroy(buf); + } + +TBool CMMFileSourceSink::CarryingFileHandle() const + { + return iUsingFileHandle; + } + + diff -r 320024dcf7b6 -r 657f02e590f1 breakdeps/mmfclientutility.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/mmfclientutility.h Wed Oct 20 13:05:58 2010 +0100 @@ -0,0 +1,510 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Client utility functions +// +// + +#ifndef __MMF_CLIENT_UTILITY_H__ +#define __MMF_CLIENT_UTILITY_H__ + +#include +#include +#include +#include +#include +#include "mmf/common/mmfcontrollerpluginresolver.h" +#include +#include +#include "mmf/common/mmfcontroller.h" + +#include +#include +#include +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include +#endif +#ifdef SYMBIAN_BUILD_GCE +#include +#endif + +class CMMSourceSink; // declared here. + +NONSHARABLE_CLASS( CMMSourceSink ): public CBase + { +public: + IMPORT_C static CMMSourceSink* NewL(TUid aUid, const TDesC8& aDescriptor); + IMPORT_C static CMMSourceSink* NewLC(TUid aUid, const TDesC8& aDescriptor); + + virtual ~CMMSourceSink(); + virtual TUid SourceSinkUid() const; + virtual const TDesC8& SourceSinkData() const; + + virtual TBool CarryingFileHandle() const; + + virtual void EvaluateIntentL(); +protected: + CMMSourceSink(TUid aUid); + + +private: + void ConstructL(const TDesC8& aDescriptor); + + const TUid iUid; + HBufC8* iBuf; + }; + + + + +class CMMFileSourceSink; // declared here. + +NONSHARABLE_CLASS( CMMFileSourceSink ): public CMMSourceSink + { +public: + IMPORT_C static CMMFileSourceSink* NewL(TUid aUid, const RFile& aFile); + IMPORT_C static CMMFileSourceSink* NewLC(TUid aUid, const RFile& aFile); + + IMPORT_C static CMMFileSourceSink* NewL(TUid aUid, const TMMSource& aMMSource); + IMPORT_C static CMMFileSourceSink* NewLC(TUid aUid, const TMMSource& aMMSource); + + const TDesC& UniqueId() const {return *iUniqueId;} + + virtual ~CMMFileSourceSink(); + + const TDesC& FileName() const {return *iFileName;} + const TDesC8& SourceSinkData() const; + + IMPORT_C void EvaluateIntentL(ContentAccess::TIntent aIntent); + virtual void EvaluateIntentL(); + + TBool CarryingFileHandle() const; + + TBool UsingFileHandle() const {return iUsingFileHandle;}; + const RFile& FileHandle() const {return iHandle;}; +protected: + CMMFileSourceSink(TUid aUid); + +private: + void ConstructL(const TMMSource& aSource); + void DoCreateFileSourceConfigDataL(); + void ConstructL(const RFile& aFile); + void DoCreateFileHandleSourceConfigDataL(); + + TBool iUsingFileHandle; + RFile iHandle; + HBufC* iFileName; + HBufC8* iSourceSinkData; + HBufC* iUniqueId; + ContentAccess::TIntent iIntent; + + TBool iEnableUI; + }; + + + +class CMMFMdaObjectStateChangeObserverCallback; // declared here. +/** +Active object utility class to allow the callback to be called asynchronously. +This should help prevent re-entrant code in clients of the mediaframework. +*/ +NONSHARABLE_CLASS( CMMFMdaObjectStateChangeObserverCallback ): public CActive + { +public: + IMPORT_C static CMMFMdaObjectStateChangeObserverCallback* NewL(MMdaObjectStateChangeObserver& aCallback); + virtual ~CMMFMdaObjectStateChangeObserverCallback(); + IMPORT_C void CallBack(CBase* aObject, TInt aPreviousState, TInt aCurrentState, TInt aErrorCode); +private: + CMMFMdaObjectStateChangeObserverCallback(MMdaObjectStateChangeObserver& aCallback); + void RunL(); + void DoCancel(); +private: + MMdaObjectStateChangeObserver& iCallback; + CBase* iObject; + TInt iPreviousState; + TInt iCurrentState; + TInt iErrorCode; + }; + +class CMMFClientUtility; // declared here. + +NONSHARABLE_CLASS( CMMFClientUtility ) + { +public: + IMPORT_C static TUid ConvertMdaFormatUidToECOMWrite(TUid aMdaFormatUid); + IMPORT_C static TUid ConvertMdaFormatUidToECOMRead(TUid aMdaFormatUid); + IMPORT_C static TFourCC ConvertMdaCodecToFourCC(TMdaPackage& aCodec); + IMPORT_C static TInt GetFileHeaderData(const TDesC& aFileName, TDes8& aHeaderData, TInt aMaxLength); + IMPORT_C static HBufC8* GetFileExtensionL(const TDesC& aFileName); + static void PrioritiseControllersL( + const RMMFControllerImplInfoArray& aControllers, + const TDesC8& aHeaderDataPlayback, + const TDesC8& aFileExtensionPlayback, + const TDesC8& aHeaderDataRecord, + const TDesC8& aFileExtensionRecord, + RMMFControllerImplInfoArray& aPrioritisedControllers); + static TInt GetBestMatchL(const CMMFFormatImplementationInformation* format, const TDesC8& aHeaderData, const TDesC8& aFileExtension); + +private: + CMMFClientUtility(); + }; + +class CMMFUtilityFileInfo; // declared here. +class RMMFDRMPluginServerProxy; + +NONSHARABLE_CLASS( CMMFUtilityFileInfo ): public CBase + { +public: + + static CMMFUtilityFileInfo* NewL(TMMSource& aSource, TBool aSecureDRMMode = EFalse); + static CMMFUtilityFileInfo* NewLC(TMMSource& aSource, TBool aSecureDRMMode = EFalse); + + ~CMMFUtilityFileInfo(); + + TBool GetFileMimeTypeL(TDes8& aMimeType); + void GetFileHeaderDataL(TDes8& aHeaderData, TInt aMaxLength); + TInt EvaluateIntent(ContentAccess::TIntent aIntent); + +private: + CMMFUtilityFileInfo(); + + void ConstructL(const TMMSource& aSource, TBool aSecureDRMMode); + +private: + ContentAccess::CData* iData; + RMMFDRMPluginServerProxy* iDrmPluginServer; + }; + +inline CMMFUtilityFileInfo::CMMFUtilityFileInfo() + { + }; + +/** + * Mixin class that the user of the class CMMFFindAndOpenController must derive from. + * @internalComponent + */ +class MMMFFindAndOpenControllerObserver + { +public: + /** + * Callback function to indicate the success or failure + * of an attempt to find and open a suitable controller and + * to add a source and sink. + * @see CMMFFindAndOpenController + * + * @param aError + * Indicates whether a controller has been opened sucessfully + * This is passed by reference, mainly for the audio recorder utility + * which opens two controllers: if the secondary controller (which is + * always opened first) fails to open, then the audio recorder utility + * may choose to set aError = KErrNone in the MfaocComplete() callback + * to indicate to CFindAndOpenControler() that it should continue + * to open the primary controller, even though opening the secondary failed. + * @param aController + * A pointer to the controller that has been opened or has failed to open + * This is mainly for the audio recorder utility to indicate + * which controller (primary or secondary) has been opened. + * @param aControllerUid + * the UID of the controller that has been opened + * @param aSourceHandle + * a pointer to the source handle + * @internalComponent + * a pointer to the sink handle + */ + virtual void MfaocComplete( + TInt& aError, + RMMFController* aController, + TUid aControllerUid = KNullUid, + TMMFMessageDestination* aSourceHandle = NULL, + TMMFMessageDestination* aSinkHandle = NULL) = 0; + }; + + +class CMMFFindAndOpenController; // declared here. +/** + * Utility class used by the MMF client API classes. + * Finds and opens a suitable controller and adds a source and a sink + * asynchronously. Completion is indicated asynchronously + * using the MMMFFindAndOpenControllerObserver mixin class. + * + * @internalComponent + */ +NONSHARABLE_CLASS( CMMFFindAndOpenController ): public CActive, public MMMFAddDataSourceSinkAsyncObserver + { +public: + enum TControllerMode + { + EPlayback, + ERecord, + EConvert + }; + + enum TControllerNumber + { + EPrimaryController, + ESecondaryController + }; + + class TSourceSink + { + public: + IMPORT_C TSourceSink(TUid aUid, const TDesC8& aData = KNullDesC8); + IMPORT_C TSourceSink(TUid aUid, const RFile& aFile); + + TUid iUid; + const TDesC8& iConfigData; + TBool iUseFileHandle; + RFile iFileHandle; + }; + + + + +public: + IMPORT_C static CMMFFindAndOpenController* NewL(MMMFFindAndOpenControllerObserver& aObserver); + virtual ~CMMFFindAndOpenController(); + + // from CActive + virtual void DoCancel(); + virtual void RunL(); + + // from MMMFAddDataSourceSinkAsyncObserver + virtual void MadssaoAddDataSourceSinkAsyncComplete(TInt aError, const TMMFMessageDestination& aHandle); + + IMPORT_C void Configure( + TUid aMediaId, + TMMFPrioritySettings aPrioritySettings, + CMMFPluginSelectionParameters::TMediaIdMatchType aMediaIdMatchType = CMMFPluginSelectionParameters::EAllowOnlySuppliedMediaIds); + + IMPORT_C void ConfigureController(RMMFController& aController, CMMFControllerEventMonitor& aEventMonitor, TControllerMode aControllerMode = EPlayback); + IMPORT_C void ConfigureSecondaryController(RMMFController& aController, CMMFControllerEventMonitor& aEventMonitor, TControllerMode aControllerMode = EPlayback); + + IMPORT_C void UseSharedHeap(); + + IMPORT_C void ConfigureSourceSink( + TSourceSink aSource, + TSourceSink aSink); + IMPORT_C void ConfigureSecondarySourceSink( + TSourceSink aSource, + TSourceSink aSink); + + IMPORT_C void ConfigureSourceSink( + const TMMSource& aSource, + TSourceSink aSink); + + IMPORT_C void OpenByFileSource(const TMMSource& aFileSource, const TDesC& aFileNameSecondary = KNullDesC); + + IMPORT_C void OpenByFormatUid(TUid aFormatUid, TUid aFormatUidSecondary = KNullUid); + IMPORT_C void OpenByDescriptor(const TDesC8& aDescriptor); + IMPORT_C void OpenByUrl(const TDesC& aUrl, TInt aIapId, const TDesC8& aMimeType); + IMPORT_C void OpenByControllerUid(TUid aControllerUid, TUid aSecondaryControllerUid = KNullUid); + IMPORT_C void ReOpen(); + IMPORT_C void Close(); + + IMPORT_C static TMMFFileConfig GetConfigFile(const TDesC& aFileName); + IMPORT_C static TMMFDescriptorConfig GetConfigDescriptor(const TDesC8& aDescriptor); + IMPORT_C void CloseConfig(); + IMPORT_C static void GetConfigUrlL(CBufFlat*& aUrlCfgBuffer, const TDesC& aUrl, TInt aIapId); + + /** made public to check for further selected controllers in the queue */ + inline TInt ControllerIndex() const; + inline TInt ControllerCount() const; + + /** made public to stop checking for further selected controllers in the queue */ + inline TBool StopTryLoadController() const; + IMPORT_C void SetInitScreenNumber(TInt aScreenNumber, RMMFVideoSetInitScreenCustomCommands* aVideoSetInitScreenCustomCommands); +#ifdef SYMBIAN_BUILD_GCE + inline void SetSurfaceMode(TBool aUseSurface, RMMFVideoPlaySurfaceSupportCustomCommands* aVideoPlaySurfaceSupportCustomCommands); + inline TInt SurfaceSupported(); +#endif + +private: + class CConfig: public CBase + { + public: + CConfig(); + ~CConfig(); + void Close(); + public: + RMMFController* iController; // not owned + CMMFControllerEventMonitor* iEventMonitor; // not owned + + /** indicates whether this controller is being used for + playback, recording or converting */ + TControllerMode iControllerMode; + + CMMSourceSink* iSource; + CMMSourceSink* iSink; + TUid iControllerUid; + }; + + CMMFFindAndOpenController(MMMFFindAndOpenControllerObserver& aObserver); + void ConstructL(); + + void Init(); + + void ConfigureSourceSink( + CConfig& config, + TSourceSink aSource, + TSourceSink aSink); + + void ConfigureSourceSink( + CConfig& config, + const TMMSource& aSource, + TSourceSink aSink); + + + void ConfigureController( + CConfig& config, + RMMFController& aController, + CMMFControllerEventMonitor& aEventMonitor, + TControllerMode aControllerMode); + + void CloseController(); + + void OpenPrimaryController(void); + + void KickState(); + void Process(); + void SendError(TInt aError = KErrNone, TBool aForcedError = EFalse); + void SchedSendError(TInt aError = KErrNone); + void BuildControllerListFileNameL(); + void BuildControllerListDescriptorL(); + void BuildControllerListUrlL(); + void BuildControllerListFormatL(); + void TryNextController(); + + CMMSourceSink* CreateSourceSinkL(const TSourceSink& aParams); + CMMSourceSink* CreateSourceSinkL(const TMMSource& aSource); + + CMMFUtilityFileInfo* CreateFileInfoL(TBool aSecureDRMMode = EFalse); + void UseSecureDRMProcessL(TBool& aIsSecureDrmProcess); +private: + /** primary controller details */ + CConfig* iPrimaryConfig; + /** secondary controller details */ + CConfig* iSecondaryConfig; + /** points to either iPrimaryConfig or iSecondaryConfig */ + CConfig* iCurrentConfig; // not owned + + enum TMode + { + EOpenByControllerUid, + EOpenByFileName, + EOpenByDescriptor, + EOpenByUrl, + EOpenByFormatUid + }; + TMode iMode; + + /** indicates what state the state machine is in */ + enum TState + { + EIdle, + EBuildControllerList, + EOpenController, + EAddSource, + EAddSink, + EWaitingForSource, + EWaitingForSink, + ESendError + }; + TState iState; + + MMMFFindAndOpenControllerObserver& iObserver; + CMMFAddDataSourceSinkAsync* iAddDataSourceSinkAsync; + + TInt iControllerIndex; + TInt iControllerCount; + + TFileName iFileNameSecondary; // for converting + + TFileName iFileName; + TBool iUseFileHandle; + TBool iOwnFileHandle; + HBufC* iUniqueId; + RFile iFileHandle; + ContentAccess::TIntent iIntent; + + HBufC* iUrl; + HBufC8* iMimeType; + TPtr8 iDescriptor; + TInt iIapId; + TUid iFormatUid; + TUid iFormatUidSecondary; // for converting + + TUid iMediaId; + TMMFPrioritySettings iPrioritySettings; + CMMFPluginSelectionParameters::TMediaIdMatchType iMediaIdMatchType; + + RMMFControllerImplInfoArray iControllers; + RMMFControllerImplInfoArray iPrioritisedControllers; + + // if this is non-null, then it points to an element in + // either iControllers or iPrioritisedControllers + CMMFControllerImplementationInformation* iControllerImplInfo; // not owned + + TControllerMode iControllerMode; + TBool iSourceSinkConfigured; + TInt iError; + + TMMFMessageDestination iSourceHandle; + TMMFMessageDestination iSinkHandle; + TBool iEnableUi; + + TBool iUseSharedHeap; // should new controllers use shared heaps? + TBool iStopTryLoadController; //stop to try loading the selected conrollers from the list + RMMFVideoSetInitScreenCustomCommands* iVideoSetInitScreenCustomCommands; + TInt iScreenNumber; + TBool iHasDrmCapability; + TBool iUsingSecureDrmProcess; + +#ifdef SYMBIAN_BUILD_GCE + RMMFVideoPlaySurfaceSupportCustomCommands* iVideoPlaySurfaceSupportCustomCommands; + TBool iUseVPU2; + TInt iSurfaceSupported; +#endif + }; + +inline TInt CMMFFindAndOpenController::ControllerIndex() const + { + return iControllerIndex; + } + +inline TInt CMMFFindAndOpenController::ControllerCount() const + { + return iControllerCount; + } + +inline TBool CMMFFindAndOpenController::StopTryLoadController() const + { + return iStopTryLoadController; + } + +#ifdef SYMBIAN_BUILD_GCE +inline void CMMFFindAndOpenController::SetSurfaceMode(TBool aUseVPU2, RMMFVideoPlaySurfaceSupportCustomCommands* aVideoPlaySurfaceSupportCustomCommands) + { + iUseVPU2 = aUseVPU2; + iSurfaceSupported = KErrNone; + iVideoPlaySurfaceSupportCustomCommands = aVideoPlaySurfaceSupportCustomCommands; + } + +inline TInt CMMFFindAndOpenController::SurfaceSupported() + { + return iSurfaceSupported; + } +#endif // SYMBIAN_BUILD_GCE + +#endif // __MMF_CLIENT_UTILITY_H__