Original source files from sf/os/mm/mmlibs/mmfw, to be reworked for stem_MediaClientAudio.dll
authorWilliam Roberts <williamr@symbian.org>
Wed, 20 Oct 2010 13:05:58 +0100
changeset 125 657f02e590f1
parent 124 320024dcf7b6
child 126 faed561c44ed
Original source files from sf/os/mm/mmlibs/mmfw, to be reworked for stem_MediaClientAudio.dll
breakdeps/mmfclientaudioplayer.cpp
breakdeps/mmfclientaudioplayer.h
breakdeps/mmfclienttoneplayer.cpp
breakdeps/mmfclienttoneplayer.h
breakdeps/mmfclientutility.cpp
breakdeps/mmfclientutility.h
--- /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 <bautils.h>
+#include <utf.h>
+#include <mmf/common/mmfpaniccodes.h>
+#include "mmfclientaudioplayer.h"
+#include "mmfclientutility.h"
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <mmf/common/mmfdurationinfocustomcommandsimpl.h>
+#include <mmf/common/mmfdurationinfocustomcommandsenums.h>
+#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<RFile&>(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<RFile&>(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<const TMMFileHandleSource&>(aSource).Handle();
+		iFindAndOpenController->ConfigureSourceSink(
+			TMMFileHandleSource(fileHandle, aSource.UniqueId(), aSource.Intent(), aSource.IsUIEnabled()),
+			CMMFFindAndOpenController::TSourceSink(KUidMmfAudioOutput));
+
+		}
+	if (aSource.SourceType()==KUidMMFileSource)
+		{
+		const TDesC& fileName = static_cast<const TMMFileSource&>(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<TMMFDurationInfo> 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<TMMFAudioConfig::KNotificationDataBufferSize> 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<MMMFDRMCustomCommand*>(&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
+	}
--- /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 <e32std.h>
+#include <e32base.h>
+#include <mdaaudiosampleplayer.h>
+#include <mmf/common/mmfcontroller.h>
+#include <mmf/server/mmffile.h>
+#include <mmf/server/mmfdes.h>
+#include <mmfcontrollerimplementationuids.hrh>
+#include <mmf/common/mmfstandardcustomcommands.h>
+#include <mmf/common/mmfdrmcustomcommands.h>
+#include "mmfclientutility.h"
+#include <mmf/common/mmfdurationinfocustomcommands.h>
+
+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<TUid> 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
--- /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 <mmf/common/mmfpaniccodes.h>
+
+#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;
+	}
--- /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 <e32std.h>
+#include <e32base.h>
+#include <mdaaudiotoneplayer.h>
+#include <mmf/server/sounddevice.h>
+#include <caf/data.h>
+#include <caf/content.h>
+//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
--- /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 <e32std.h>
+#include <f32file.h>
+#include <bautils.h>
+#include <mmf/server/mmfdrmpluginserverproxy.h>
+#include <caf/content.h>
+#include <caf/data.h>
+using namespace ContentAccess;
+
+#include "mmfclientutility.h"
+#include <mmf/common/mmfpaniccodes.h>
+
+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<const TMMFileSource&>(aSource);
+			iData = CData::NewL(TVirtualPathPtr(fileSource.Name(), fileSource.UniqueId()),
+								EContentShareReadWrite);
+			}
+
+		if (aSource.SourceType()==KUidMMFileHandleSource)
+			{
+			const TMMFileHandleSource& fileHandleSource = static_cast<const TMMFileHandleSource&>(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<ContentAccess::TIntent> intentPckg(aSource.Intent());
+		stream.WriteL(intentPckg);
+		stream.CommitL();
+	
+		CleanupStack::PopAndDestroy(&stream);
+		if (aSource.SourceType()==KUidMMFileSource)
+			{
+			const TMMFileSource& fileSource = static_cast<const TMMFileSource&>(aSource);
+			iDrmPluginServer->OpenDataContentL(fileSource.Name(), dataBuffer->Ptr(0));
+			}
+		if (aSource.SourceType()==KUidMMFileHandleSource)
+			{
+			const TMMFileHandleSource& fileHandleSource = static_cast<const TMMFileHandleSource&>(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<const TMMFileSource&>(aSource);
+		iFileName = fileSource.Name();
+		iUseFileHandle = EFalse;
+		}
+
+	if (aSource.SourceType()==KUidMMFileHandleSource)
+		{
+		const TMMFileHandleSource& fileHandleSource = static_cast<const TMMFileHandleSource&>(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<TUint8*> (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<const CMMFileSourceSink*>(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<const CMMFileSourceSink*>(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<TUid> mediaIds;
+	CleanupClosePushL(mediaIds);
+	User::LeaveIfError(mediaIds.Append(iMediaId));
+
+	cSelect->SetMediaIdsL(mediaIds, iMediaIdMatchType);
+
+	if (mode == EPlayback)
+		{
+		ASSERT(fileInfo!=NULL);
+		TBuf8<KMaxMimeLength> 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<TUid> 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<TUid> 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<TUid> 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<RFile*> 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<const TMMFileSource&>(aSource);
+		iFileName = fileSource.Name().AllocL();
+		
+		DoCreateFileSourceConfigDataL();
+		}
+	else if (aSource.SourceType() == KUidMMFileHandleSource)
+		{
+		const TMMFileHandleSource& fileHandleSource = static_cast<const TMMFileHandleSource&>(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;
+	}
+
+
--- /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 <mda/common/audio.h>
+#include <mda/common/gsmaudio.h>
+#include <mda/client/utility.h>
+#include <mmf/common/mmffourcc.h>
+#include <mmfformatimplementationuids.hrh>
+#include "mmf/common/mmfcontrollerpluginresolver.h"
+#include <mmf/server/mmffile.h>
+#include <mmf/server/mmfdes.h>
+#include "mmf/common/mmfcontroller.h"
+
+#include <f32file.h>
+#include <caf/content.h>
+#include <caf/data.h>
+#include <mmf/common/mmfstandardcustomcommands.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <mmf/common/mmfstandardcustomcommandsenums.h>
+#include <mmf/common/mmfstandardcustomcommandsimpl.h>
+#endif
+#ifdef SYMBIAN_BUILD_GCE
+#include <mmf/common/mmfvideosurfacecustomcommands.h>
+#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__