breakdeps/mmfclientutility.cpp
changeset 125 657f02e590f1
--- /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;
+	}
+
+