mmlibs/mmfw/src/Client/Video/mmfclientvideoplayerbody.cpp
changeset 0 40261b775718
child 7 94dbab0a2133
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmlibs/mmfw/src/Client/Video/mmfclientvideoplayerbody.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,2102 @@
+// 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/mmfstandardcustomcommands.h>  
+#include <mmf/common/mmfdrmcustomcommands.h>  
+#include <mmf/common/mmfvideo.h>
+#include <mmf/server/mmfdes.h>
+#include <mmf/server/mmffile.h>
+#include "mmfvideocallback.h"
+#include "VideoPlayerBody.h"
+#include "mmfclientvideocommon.h"
+#include "mmfclientutility.h"
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <mmf/common/mmfvideoenums.h>
+#endif
+
+#ifdef SYMBIAN_BUILD_GCE
+#include <videoplayer2.h>
+#include <surfaceeventhandler.h>
+#endif
+
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+#include <mmf/common/mmfpaniccodes.h>
+#include "mmfsubtitleutility.h"
+#endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+
+using namespace ContentAccess;
+
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+
+#ifdef _DEBUG
+void VPUDebugPanicOrLeaveL(TInt aVPUPanicCode, TInt aLeaveCode)
+	{
+	_LIT(KMMFVideoPlayerUtilityPanicCategory, "MMFVideoPlayUtil");
+	User::Panic(KMMFVideoPlayerUtilityPanicCategory, aVPUPanicCode);
+	User::Leave(aLeaveCode); // added for leavescan
+	}
+
+#else
+void VPUDebugPanicOrLeaveL(TInt /*aVPUPanicCode*/, TInt aLeaveCode)
+	{
+	User::Leave(aLeaveCode);
+	}
+#endif //_DEBUG
+
+#endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+
+CVideoPlayerUtility::CBody* CVideoPlayerUtility::CBody::NewL(CVideoPlayerUtility* aParent,
+															 MVideoPlayerUtilityObserver& aObserver,
+															 TInt aPriority,
+															 TInt aPref,
+															 RWsSession& aWs,
+															 CWsScreenDevice& aScreenDevice,
+															 RWindowBase& aWindow,
+															 const TRect& aScreenRect,
+															 const TRect& aClipRect)
+	{
+	CBody* self = new(ELeave) CBody(aParent, aObserver, aScreenDevice.GetScreenNumber(), aPriority, aPref);
+	CleanupStack::PushL(self);
+	self->ConstructL(aWs, aScreenDevice, aWindow, aScreenRect, aClipRect);
+	CleanupStack::Pop();
+	return self;
+	}
+
+#ifdef SYMBIAN_BUILD_GCE
+CVideoPlayerUtility::CBody* CVideoPlayerUtility::CBody::NewL(CVideoPlayerUtility2* aParent,
+															 MVideoPlayerUtilityObserver& aObserver,
+															 TInt aPriority,
+															 TInt aPref)
+	{
+	CBody* self = new(ELeave) CBody(aParent, aObserver, aPriority, aPref);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+#endif // SYMBIAN_BUILD_GCE
+
+CVideoPlayerUtility::CBody::~CBody()
+	{
+	Close();
+	
+	delete iControllerImplementationInformation;
+	delete iDirectScreenAccess;
+	delete iFindAndOpenController;
+	delete iControllerEventMonitor;
+	delete iFrameCallback;
+	delete iAsyncCallback;
+	delete iMimeType;
+	delete iFrameBitmap;
+	if (iFbsSessionConnected)
+		iFbsSession.Disconnect();
+	}
+
+void CVideoPlayerUtility::CBody::Close()
+	{
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+	DisableSubtitles();
+#endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+
+	if (iAsyncCallback)
+		iAsyncCallback->Cancel();
+	if (iFrameCallback)
+		iFrameCallback->Cancel();
+	if (iFindAndOpenController)
+		iFindAndOpenController->Close();
+	if (iControllerEventMonitor)
+		iControllerEventMonitor->Cancel();
+	if(iControllerImplementationInformation)
+		{
+		delete iControllerImplementationInformation;
+		iControllerImplementationInformation = NULL;
+		}
+
+#ifdef SYMBIAN_BUILD_GCE
+	iActiveDisplays.ResetAndDestroy();
+	iSurfaceId = TSurfaceId::CreateNullId();
+#endif
+
+	iController.Close();	
+	iControllerUid = KNullUid;
+	iControllerOpen = EFalse;
+	iDirectScreenAccessAbort = EFalse;
+	}
+
+CVideoPlayerUtility::CBody::CBody(CVideoPlayerUtility* aParent,
+								  MVideoPlayerUtilityObserver& aObserver,
+								  TInt aScreenNumber,
+								  TInt aPriority,
+								  TInt aPref) : 
+	iVideoControllerCustomCommands(iController),
+	iVideoPlayControllerCustomCommands(iController),
+	iAudioPlayDeviceCustomCommands(iController),
+	iAudioRecordDeviceCustomCommands(iController),
+	iVideoDRMExtCustomCommands(iController),
+	iDRMCustomCommands(iController),
+	iVideoPlayControllerExtCustomCommands(iController),	
+	iNotificationRegistrationCommands(iController),
+#ifdef SYMBIAN_BUILD_GCE
+	iVideoPlaySurfaceSupportCustomCommands(iController),
+#endif
+	iArnEventHolder(KNullUid),
+	iVideoSetInitScreenCustomCommands(iController),
+	iObserver(aObserver),
+	iState(EStopped),
+	iParent(aParent),
+	iScreenNumber(aScreenNumber)
+#ifdef SYMBIAN_BUILD_GCE
+	,iGlobalScaleWidth(100.0f),
+	iGlobalScaleHeight(100.0f),
+	iGlobalHorizPos(EHorizontalAlignCenter),
+	iGlobalVertPos(EVerticalAlignCenter)
+#endif
+	{
+	iPrioritySettings.iPriority = aPriority;
+	iPrioritySettings.iPref = aPref;
+	}
+
+#ifdef SYMBIAN_BUILD_GCE
+CVideoPlayerUtility::CBody::CBody(CVideoPlayerUtility2* aParent,
+				MVideoPlayerUtilityObserver& aObserver,
+				TInt aPriority,
+				TInt aPref) : 
+	iVideoControllerCustomCommands(iController),
+	iVideoPlayControllerCustomCommands(iController),
+	iAudioPlayDeviceCustomCommands(iController),
+	iAudioRecordDeviceCustomCommands(iController),
+	iVideoDRMExtCustomCommands(iController),
+	iDRMCustomCommands(iController),
+	iVideoPlayControllerExtCustomCommands(iController),
+	iNotificationRegistrationCommands(iController),
+	iVideoPlaySurfaceSupportCustomCommands(iController),
+	iArnEventHolder(KNullUid),
+	iVideoSetInitScreenCustomCommands(iController),
+	iObserver(aObserver),
+	iState(EStopped),
+	iParent(aParent),
+	iUsingVPU2(ETrue),
+	iGlobalScaleWidth(100.0f),
+	iGlobalScaleHeight(100.0f),
+	iGlobalHorizPos(EHorizontalAlignCenter),
+	iGlobalVertPos(EVerticalAlignCenter)
+	{
+	iPrioritySettings.iPriority = aPriority;
+	iPrioritySettings.iPref = aPref;
+	}
+
+void CVideoPlayerUtility::CBody::ConstructL()
+	{
+	CommonConstructL();
+	iFindAndOpenController = CMMFFindAndOpenController::NewL(*this);
+	iFindAndOpenController->SetSurfaceMode(iUsingVPU2, &iVideoPlaySurfaceSupportCustomCommands);
+	iFindAndOpenController->Configure(KUidMediaTypeVideo, iPrioritySettings, CMMFPluginSelectionParameters::EAllowOtherMediaIds);
+	iFindAndOpenController->ConfigureController(iController, *iControllerEventMonitor, CMMFFindAndOpenController::EPlayback);
+	}
+
+#endif // SYMBIAN_BUILD_GCE
+
+void CVideoPlayerUtility::CBody::ConstructL(RWsSession& aWs,
+						CWsScreenDevice& aScreenDevice,
+						RWindowBase& aWindow,
+						const TRect& aWindowRect,
+						const TRect& aClipRect)
+	{
+	CommonConstructL();
+	
+	SetDisplayWindowL(aWs, aScreenDevice, aWindow, aWindowRect, aClipRect);
+	iFindAndOpenController = CMMFFindAndOpenController::NewL(*this);
+#ifdef SYMBIAN_BUILD_GCE	
+	iFindAndOpenController->SetSurfaceMode(iUsingVPU2, &iVideoPlaySurfaceSupportCustomCommands);
+	
+	// If we open a controller with surface support we may render to surfaces.  We need to store these
+	// so we can add the display as a surface rendering target.
+
+	iWs = &aWs;
+	iDisplayId = aScreenDevice.GetScreenNumber();
+	iWindow = &aWindow;
+	iWindowRect = aWindowRect;
+	iClipRect = aClipRect;	
+
+#endif
+	iFindAndOpenController->Configure(KUidMediaTypeVideo, iPrioritySettings, CMMFPluginSelectionParameters::EAllowOtherMediaIds);
+	iFindAndOpenController->ConfigureController(iController, *iControllerEventMonitor, CMMFFindAndOpenController::EPlayback);
+	}
+
+void CVideoPlayerUtility::CBody::CommonConstructL()
+	{
+	iControllerEventMonitor = CMMFControllerEventMonitor::NewL(*this, iController);
+	iMimeType = HBufC8::NewL(KMaxMimeTypeLength);
+	iAsyncCallback = new (ELeave) CMMFVideoPlayerCallback(iObserver);
+	iFrameCallback = new (ELeave) CMMFVideoPlayerCallback(iObserver);
+	User::LeaveIfError(iFbsSession.Connect());
+	iFbsSessionConnected = ETrue;
+	}
+
+void CVideoPlayerUtility::CBody::Reset() 
+	{
+	Close();
+	
+	// reset all state variables
+	iEventOpenReceived = EFalse;
+	iCallbackOpenReceived = EFalse;
+	iOpenError = KErrNone;
+#ifdef SYMBIAN_BUILD_GCE
+	iGraphicsSurfaceSupported = EFalse;
+#endif
+	iControllerUid = KNullUid;
+	}
+
+void CVideoPlayerUtility::CBody::SetAndUpdateWindow()
+	{
+	if (iOpenError == KErrNone)	
+		{
+		// Set the display window and update display region if the controller doesn't support graphics surface. 		
+		iOpenError = iVideoPlayControllerCustomCommands.SetDisplayWindow(iWindowRect, iClipRect);
+		}
+
+	if (iOpenError == KErrNone && iDirectScreenAccess && iDirectScreenAccess->DrawingRegion())
+		{
+		iOpenError = iVideoPlayControllerCustomCommands.UpdateDisplayRegion(*iDirectScreenAccess->DrawingRegion());
+		}
+	}
+
+void CVideoPlayerUtility::CBody::MfaocComplete(		
+	TInt& aError, 
+	RMMFController*	/*aController*/,
+	TUid aControllerUid, 
+	TMMFMessageDestination* /*aSourceHandle*/, 
+	TMMFMessageDestination* /*aSinkHandle*/)
+	{
+	iCallbackOpenReceived = ETrue;
+
+	// save the error in iOpenError -
+	// unless HandleEvent(KMMFEventCategoryVideoOpenComplete) 
+	// has reported an error already
+	if (iOpenError == KErrNone)
+		iOpenError = aError;
+	
+	if (iOpenError == KErrNone)
+		{
+#ifdef SYMBIAN_BUILD_GCE
+		// Check if the graphics surfaces is supported
+		TInt err = CheckSurfaceSupported();
+	
+		if (!iGraphicsSurfaceSupported)
+			{
+			if (err != KErrNone && iUsingVPU2)
+				{
+				// Set KErrNotSupported if the controller doesn't support graphics surface and 
+				// the open source is using CVideoPlayerUtility2
+				iOpenError = err;
+				}
+			else
+				{
+				SetAndUpdateWindow();
+				}
+			}
+#else
+		SetAndUpdateWindow();
+#endif // SYMBIAN_BUILD_GCE	
+	
+		// now that the controller is open
+		if (iOpenError == KErrNone)
+			{
+			iControllerOpen = ETrue;
+			iControllerUid = aControllerUid;
+
+#ifdef SYMBIAN_BUILD_GCE		
+			// We are using a controller that supports graphics surfaces but are not in surface mode.  
+			// Call AddDisplay so we can render to surfaces using the CVideoUtility API.
+			if (iGraphicsSurfaceSupported && !iUsingVPU2)
+				{
+				if (iDirectScreenAccess)
+					{
+		 			iDirectScreenAccess->Cancel();
+					}
+				
+		        // When using surfaces for CVPU we use DoAddDisplayWindowL() which requires clip rectangle and video extent
+		        // as arguments. Video extent is not supported by CVPU so aWindowRect is used instead. This function
+		        // assumes these args are relative to the window. However they are relative to the display and must be
+		        // converted.
+		        TRect windowRectRelativeToWindow;
+		        TRect clipRectRelativeToWindow;     
+		        ConvertFromRelativeToDisplayToRelativeToWindow(*iWindow, iWindowRect, iClipRect, windowRectRelativeToWindow, clipRectRelativeToWindow);
+
+				TRAP(iOpenError, DoAddDisplayWindowL(*iWs, iDisplayId, *iWindow, clipRectRelativeToWindow, windowRectRelativeToWindow, NULL));				
+				}
+#endif		
+			}
+		// If an error occurred in any of the above, try for next controller if present
+		// in the selection list.
+		else
+			{
+			if(iFindAndOpenController->ControllerIndex() < (iFindAndOpenController->ControllerCount())-1)
+				{
+				aError = iOpenError;
+				
+				if (iAsyncCallback)
+					{
+					iAsyncCallback->Cancel();
+					}
+		
+				if (iControllerEventMonitor)
+					{
+					iControllerEventMonitor->Cancel();
+					}
+				iOpenError = KErrNone;
+					
+				return;
+				}
+				
+			Close();
+			}
+		}
+
+	if(iOpenError != KErrNone && !iControllerOpen)
+		{
+		if (iFindAndOpenController)	
+			{
+			//if try next controller was called when specific controller uid was 
+			//given, skip the searching and report error.
+			if(!iFindAndOpenController->StopTryLoadController()) 
+				{
+				if( !(aError == KErrNoMemory || aError == KErrCancel ) ) 
+					{
+					if(iFindAndOpenController->ControllerIndex() < (iFindAndOpenController->ControllerCount())-1)
+						{
+						aError = iOpenError;   // Actually tries to load controller
+						iOpenError = KErrNone;
+						return;
+						}
+					}
+				}
+			}
+		}
+	
+	// if we've already received the open complete event
+	// call the client now (otherwise wait for it)
+	if (iEventOpenReceived || iOpenError != KErrNone)
+		{
+		// stop a subsequent HandleEvent(KMMFEventCategoryVideoOpenComplete) 
+		// from issuing another callback to client
+		iCallbackOpenReceived = EFalse;
+		iAsyncCallback->Signal(iOpenError, CMMFVideoPlayerCallback::EOpenCompleteEvent);
+		}
+
+	}
+
+void CVideoPlayerUtility::CBody::OpenFileL(const TDesC& aFileName, TUid aControllerUid)
+	{
+	TMMFileSource filesource(aFileName, KDefaultContentObject, EPlay);
+	OpenFileL(filesource, aControllerUid);
+	}
+	
+void CVideoPlayerUtility::CBody::OpenFileL(const RFile& aFile, TUid aControllerUid)
+	{
+	RFile& file = const_cast<RFile&>(aFile);
+	TMMFileHandleSource filehandlesource(file, KDefaultContentObject, EPlay);
+	OpenFileL(filehandlesource, aControllerUid);
+	}
+
+void CVideoPlayerUtility::CBody::OpenFileL(const TMMSource& aSource, TUid aControllerUid)
+	{
+	// Make sure we are closed
+	Reset();
+
+	iFindAndOpenController->ConfigureSourceSink(
+		aSource,
+		CMMFFindAndOpenController::TSourceSink(KUidMmfAudioOutput));
+
+#ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT
+	iFindAndOpenController->SetInitScreenNumber(iScreenNumber, &iVideoSetInitScreenCustomCommands);
+#endif
+
+	if (aControllerUid != KNullUid) 
+		{
+		iFindAndOpenController->OpenByControllerUid(aControllerUid);
+		}
+	else
+		{
+		iFindAndOpenController->OpenByFileSource(aSource);
+		}
+	}
+	
+//
+// This method launches and initializes plugin controller based on the stream 
+// source header passed in the descriptor buffer.
+//
+void CVideoPlayerUtility::CBody::OpenDesL(const TDesC8& aDescriptor, TUid aControllerUid)
+	{
+	// Make sure we are closed
+	Reset();
+
+	iFindAndOpenController->ConfigureSourceSink(
+		CMMFFindAndOpenController::TSourceSink(KUidMmfDescriptorSource, CMMFFindAndOpenController::GetConfigDescriptor(aDescriptor)), 
+		CMMFFindAndOpenController::TSourceSink(KUidMmfAudioOutput, KNullDesC8));
+	
+#ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT
+	iFindAndOpenController->SetInitScreenNumber(iScreenNumber, &iVideoSetInitScreenCustomCommands);
+#endif
+		
+	if (aControllerUid!=KNullUid)
+		{
+		iFindAndOpenController->OpenByControllerUid(aControllerUid);
+		}
+	else
+		{
+		iFindAndOpenController->OpenByDescriptor(aDescriptor);
+		}
+	}
+	
+void CVideoPlayerUtility::CBody::OpenUrlL(const TDesC& aUrl, TInt aIapId, const TDesC8& aMimeType, TUid aControllerUid)
+	{
+	// Make sure we are closed
+	Reset();
+
+	CBufFlat* urlCfgBuffer = NULL;
+    CMMFFindAndOpenController::GetConfigUrlL(urlCfgBuffer, aUrl, aIapId);
+
+	iFindAndOpenController->ConfigureSourceSink(
+		CMMFFindAndOpenController::TSourceSink(KUidMmfUrlSource, urlCfgBuffer->Ptr(0)), 
+		CMMFFindAndOpenController::TSourceSink(KUidMmfAudioOutput, KNullDesC8));
+	
+#ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT
+	iFindAndOpenController->SetInitScreenNumber(iScreenNumber, &iVideoSetInitScreenCustomCommands);
+#endif
+		
+	if (aControllerUid!=KNullUid)
+		{
+		iFindAndOpenController->OpenByControllerUid(aControllerUid);
+		}
+	else
+		iFindAndOpenController->OpenByUrl(aUrl, aIapId, aMimeType);
+
+	delete urlCfgBuffer;
+	}
+
+void CVideoPlayerUtility::CBody::Play()
+	{
+	TInt err = iController.Prime();
+	if (err == KErrNone)
+		err = iController.Play();
+	if (err != KErrNone)
+	    {
+	    iAsyncCallback->Signal(err,CMMFVideoPlayerCallback::EPlayCompleteEvent);
+	    return;
+	    }
+	iState = EPlaying;
+	//If Audio Resource Notification request is pending - attempt now
+	if(iArnEventHolder != KNullUid)
+		{
+		err = iNotificationRegistrationCommands.RegisterAsClient(iArnEventHolder, iNotificationDataHolder);
+		iArnEventHolder = KNullUid;
+		iNotificationDataHolder = KNullDesC8;
+		if(err != KErrNone)
+			{
+			iAsyncCallback->Signal(err, CMMFVideoPlayerCallback::EPlayCompleteEvent);
+			}
+		}
+	}
+
+void CVideoPlayerUtility::CBody::Play(const TTimeIntervalMicroSeconds& aStartTime, const TTimeIntervalMicroSeconds& aEndTime)
+	{
+	TInt err = iController.Prime();
+	if (err == KErrNone)
+	err = iVideoPlayControllerCustomCommands.Play(aStartTime, aEndTime);
+	if (err != KErrNone)
+	    {
+	    iAsyncCallback->Signal(err, CMMFVideoPlayerCallback::EPlayCompleteEvent);
+	    return;
+	    }
+	iState = EPlaying;
+	//If Audio Resource Notification request is pending - attempt now
+	if(iArnEventHolder != KNullUid)
+		{
+		err = iNotificationRegistrationCommands.RegisterAsClient(iArnEventHolder, iNotificationDataHolder);			
+		iArnEventHolder = KNullUid;
+		iNotificationDataHolder = KNullDesC8;
+		if(err != KErrNone)
+			{
+			iAsyncCallback->Signal(err, CMMFVideoPlayerCallback::EPlayCompleteEvent);
+			}
+		}
+	}
+
+
+TInt CVideoPlayerUtility::CBody::Stop()
+	{
+	TInt err = iController.Stop();
+	iState = EStopped;
+	return err;
+	}
+
+void CVideoPlayerUtility::CBody::PauseL()
+	{
+	User::LeaveIfError(iController.Pause());
+	iState = EPaused;
+	}
+
+void CVideoPlayerUtility::CBody::SetVolumeL(TInt aVolume)
+	{
+	User::LeaveIfError(iAudioPlayDeviceCustomCommands.SetVolume(aVolume));
+	}
+
+void CVideoPlayerUtility::CBody::PrepareDSAL(RWsSession& aWs, CWsScreenDevice& aScreenDevice, RWindowBase& aWindow)
+	{
+	CDirectScreenAccess* old = iDirectScreenAccess;
+	iDirectScreenAccess = CDirectScreenAccess::NewL(aWs,aScreenDevice,aWindow,*this);
+	delete old;
+	iDirectScreenAccess->StartL();
+	}
+
+void CVideoPlayerUtility::CBody::SetDisplayWindowL(RWsSession& aWs, CWsScreenDevice& aScreenDevice,
+							RWindowBase& aWindow, const TRect& aWindowRect,
+							const TRect& aClipRect)
+	{	
+	iWindowRect = aWindowRect;
+	iClipRect = aClipRect;
+	
+#ifdef SYMBIAN_BUILD_GCE
+	// If called from CVideoPlayerUtility2, fail with KErrNotSupport. Otherwise, if the controller supports 
+	// the graphics surfaces, it will render to graphics surfaces. If the controller doesn't support 
+	// the graphics surfaces, it will use direct screen access.
+	if (iUsingVPU2)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	// If the controller does not support GCE or the source has not been opened, start new DSA.
+	if (!iGraphicsSurfaceSupported)
+		{
+		PrepareDSAL(aWs, aScreenDevice, aWindow);
+		}
+
+	if (!iGraphicsSurfaceSupported && iControllerOpen)
+		{
+		// Set display window and update region, if controller is open
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.SetDisplayWindow(iWindowRect,iClipRect));
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.UpdateDisplayRegion(*iDirectScreenAccess->DrawingRegion()));
+		}
+		
+	if (iGraphicsSurfaceSupported && iControllerOpen)
+		{
+		// When the controller supports graphics surfaces, need to stop direct screen access.
+ 		if (iDirectScreenAccess)
+ 			{
+ 			iDirectScreenAccess->Cancel();
+  			AbortNow(RDirectScreenAccess::ETerminateCancel);
+ 			}
+
+		// try to remove the display window first no matter it is active or not.
+		// This method won't leave
+		RemoveDisplayWindow(aWindow);
+		
+		// When using surfaces for CVPU we use DoAddDisplayWindowL() which requires clip rectangle and video extent
+		// as arguments. Video extent is not supported by CVPU so aWindowRect is used instead. This function
+		// assumes these args are relative to the window. However they are relative to the display and must be
+		// converted.
+		TRect windowRectRelativeToWindow;
+		TRect clipRectRelativeToWindow;		
+		ConvertFromRelativeToDisplayToRelativeToWindow(aWindow, aWindowRect, aClipRect, windowRectRelativeToWindow, clipRectRelativeToWindow);
+
+        DoAddDisplayWindowL(aWs, aScreenDevice.GetScreenNumber(), aWindow, clipRectRelativeToWindow, windowRectRelativeToWindow, NULL);
+		}
+#else
+	PrepareDSAL(aWs, aScreenDevice, aWindow);
+	
+	if (iControllerOpen)
+		{
+		// Set display window and update region, if controller is open
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.SetDisplayWindow(iWindowRect,iClipRect));
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.UpdateDisplayRegion(*iDirectScreenAccess->DrawingRegion()));
+		if(iDirectScreenAccessAbort)
+			{
+			User::LeaveIfError(iVideoPlayControllerCustomCommands.DirectScreenAccessEvent(EResumeDSA));
+			iDirectScreenAccessAbort = EFalse;
+			}
+		}
+#endif
+	}
+
+TReal32 CVideoPlayerUtility::CBody::VideoFrameRateL() const
+	{
+	TReal32 framerate = 0;
+	User::LeaveIfError(iVideoControllerCustomCommands.GetFrameRate(framerate));
+	return framerate;
+	}
+
+
+void CVideoPlayerUtility::CBody::VideoFrameSizeL(TSize& aSize) const
+	{
+	User::LeaveIfError(iVideoControllerCustomCommands.GetVideoFrameSize(aSize));
+	}
+
+TInt CVideoPlayerUtility::CBody::Volume() const
+	{
+	TInt vol = 0;
+	iAudioPlayDeviceCustomCommands.GetVolume(vol);
+	return vol;
+	}
+
+
+void CVideoPlayerUtility::CBody::SetBalanceL(TInt aBalance)
+	{
+	User::LeaveIfError(iAudioPlayDeviceCustomCommands.SetBalance(aBalance));
+	}
+
+
+TInt CVideoPlayerUtility::CBody::Balance() const
+	{
+	TInt bal = 0;
+	iAudioPlayDeviceCustomCommands.GetBalance(bal);
+	return bal;
+	}
+
+void CVideoPlayerUtility::CBody::SetRotationL(TVideoRotation aRotation)
+	{
+#ifdef SYMBIAN_BUILD_GCE
+	if (!iGraphicsSurfaceSupported)
+		{
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.SetRotation(aRotation));
+		}
+	else
+		{
+		// Rotation setting is not sent to controller when graphics surfaces are used.
+		// If the surface has been created, perform rotation with the help of graphics surfaces;
+		// otherwise, just store the rotation info.
+
+		TInt count = iActiveDisplays.Count();
+		
+		for (TInt i = 0; i < count; ++i)
+			{
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+			CMediaClientVideoDisplayBody* display = iActiveDisplays[i];
+			RArray<CMediaClientVideoDisplayBody::TWindowData>& windows = display->Windows();
+			TInt windowcount = windows.Count();	
+			for (TInt i = 0; i < windowcount; ++i)
+				{
+				CMediaClientVideoDisplayBody::TWindowData& window = windows[i];		
+				if (window.iRotation != aRotation)
+					{
+					// update config only if setting has actually changed
+					UpdateSurfaceAndSubtitleConfigL(*display, window, window.iClipRect, aRotation, iCropRegion);
+					}
+				}
+#else
+
+			iActiveDisplays[i]->SetRotationL(aRotation, iCropRegion);
+#endif//SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+			}
+
+		iGlobalRotation = aRotation;
+
+		}
+#else 
+	User::LeaveIfError(iVideoPlayControllerCustomCommands.SetRotation(aRotation));
+#endif // SYMBIAN_BUILD_GCE
+	}
+
+TVideoRotation CVideoPlayerUtility::CBody::RotationL() const
+	{
+	TVideoRotation rot = EVideoRotationNone;
+#ifdef SYMBIAN_BUILD_GCE
+	if (!iGraphicsSurfaceSupported)
+		{		
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.GetRotation(rot));		
+		}
+	else 
+		{
+		// Rotation setting is not retrieved from controller when graphics surfaces are used.
+		rot = iGlobalRotation;
+		}
+#else
+	User::LeaveIfError(iVideoPlayControllerCustomCommands.GetRotation(rot));
+#endif // SYMBIAN_BUILD_GCE
+	return rot;
+	}
+
+void CVideoPlayerUtility::CBody::SetScaleFactorL(TReal32 aWidthPercentage, TReal32 aHeightPercentage, TBool aAntiAliasFiltering)
+	{
+#ifdef SYMBIAN_BUILD_GCE
+	if (!iGraphicsSurfaceSupported)
+		{
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.SetScaleFactor(aWidthPercentage, aHeightPercentage, aAntiAliasFiltering));
+		}
+	else
+		{
+		// Scale factor  setting is not sent to controller when graphics surfaces are used.
+		// If the surface has been created, perform scale factor with the help of graphics surfaces.
+		iAntiAliasFiltering = aAntiAliasFiltering;
+		iGlobalScaleWidth = aWidthPercentage;
+		iGlobalScaleHeight = aHeightPercentage;
+		iGlobalAutoScaleType = EAutoScaleNone;
+
+		TInt count = iActiveDisplays.Count();
+		
+		for (TInt i = 0; i < count; ++i)
+			{
+			iActiveDisplays[i]->SetScaleFactorL(aWidthPercentage, aHeightPercentage, iCropRegion);
+			}
+		}
+#else
+	User::LeaveIfError(iVideoPlayControllerCustomCommands.SetScaleFactor(aWidthPercentage, aHeightPercentage, aAntiAliasFiltering));
+#endif	// SYMBIAN_BUILD_GCE
+	}
+
+void CVideoPlayerUtility::CBody::GetScaleFactorL(TReal32& aWidthPercentage, TReal32& aHeightPercentage, TBool& aAntiAliasFiltering) const
+	{
+#ifdef SYMBIAN_BUILD_GCE
+	if (!iGraphicsSurfaceSupported)
+		{
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.GetScaleFactor(aWidthPercentage, aHeightPercentage, aAntiAliasFiltering));
+		}
+	else
+		{
+		// Scale factor setting is not retrieved from controller when graphics surfaces are used.
+		
+		aWidthPercentage = iGlobalScaleWidth;
+		aHeightPercentage = iGlobalScaleHeight;	
+		
+		aAntiAliasFiltering = iAntiAliasFiltering;
+		}
+#else
+	User::LeaveIfError(iVideoPlayControllerCustomCommands.GetScaleFactor(aWidthPercentage, aHeightPercentage, aAntiAliasFiltering));	
+#endif // SYMBIAN_BUILD_GCE
+	}
+
+void CVideoPlayerUtility::CBody::SetCropRegionL(const TRect& aCropRegion)
+	{
+#ifdef SYMBIAN_BUILD_GCE
+	if (!iGraphicsSurfaceSupported)
+		{
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.SetCropRegion(aCropRegion));
+		}
+	else
+		{
+		// Crop region setting is not sent to controller when graphics surfaces are used.
+		// If the surface has been created, perform crop region with the help of graphics surfaces;
+		// otherwise, just store the crop region info.
+		
+		iCropRegion = aCropRegion;
+		User::LeaveIfError(SetAllBackgroundSurfaces());
+		}
+#else
+	User::LeaveIfError(iVideoPlayControllerCustomCommands.SetCropRegion(aCropRegion));
+#endif // SYMBIAN_BUILD_GCE
+	}
+
+void CVideoPlayerUtility::CBody::GetCropRegionL(TRect& aCropRegion) const
+	{
+#ifdef SYMBIAN_BUILD_GCE
+	if (!iGraphicsSurfaceSupported )
+		{
+		User::LeaveIfError(iVideoPlayControllerCustomCommands.GetCropRegion(aCropRegion));
+		}
+	else
+		{
+		// Crop rectangle setting is not retrieved from controller when graphics surfaces are used.
+		aCropRegion = iCropRegion;
+		}
+#else
+	User::LeaveIfError(iVideoPlayControllerCustomCommands.GetCropRegion(aCropRegion));
+#endif // SYMBIAN_BUILD_GCE
+	}
+
+void CVideoPlayerUtility::CBody::Prepare()
+	{
+	TInt error = iVideoPlayControllerCustomCommands.Prepare();
+	if (error)
+		iObserver.MvpuoPrepareComplete(error);
+	}
+
+const TDesC8& CVideoPlayerUtility::CBody::VideoFormatMimeType() const
+	{
+	TPtr8 des = iMimeType->Des();
+	TInt err = iVideoControllerCustomCommands.GetVideoMimeType(des);
+	if (!err)
+		return *iMimeType;
+	else
+		return KNullDesC8;
+	}
+											 
+void CVideoPlayerUtility::CBody::RegisterForVideoLoadingNotification(MVideoLoadingObserver& aObserver)
+	{
+	iVideoLoadingObserver = &aObserver;
+	}
+
+TInt CVideoPlayerUtility::CBody::NumberOfMetaDataEntriesL() const
+	{
+	TInt num = 0;
+	User::LeaveIfError(iController.GetNumberOfMetaDataEntries(num));
+	return num;
+	}
+
+
+CMMFMetaDataEntry* CVideoPlayerUtility::CBody::MetaDataEntryL(TInt aMetaDataIndex) const
+	{
+	return iController.GetMetaDataEntryL(aMetaDataIndex);
+	}
+
+void CVideoPlayerUtility::CBody::SetPriorityL(TInt aPriority, TInt aPref)
+	{
+	iPrioritySettings.iPref = aPref;
+	iPrioritySettings.iPriority = aPriority;
+
+	TInt err = iController.SetPrioritySettings(iPrioritySettings);
+	if ((err == KErrNone) || (err == KErrNotReady))
+		{
+		iFindAndOpenController->Configure(KUidMediaTypeVideo, iPrioritySettings, CMMFPluginSelectionParameters::EAllowOtherMediaIds);
+		}
+	else
+		{
+		User::Leave(err);
+		}
+	}
+
+void CVideoPlayerUtility::CBody::PriorityL(TInt & aPriority, TMdaPriorityPreference &aPref) const 
+	{
+	aPriority = iPrioritySettings.iPriority;
+	aPref = TMdaPriorityPreference(iPrioritySettings.iPref);
+	}
+
+
+void CVideoPlayerUtility::CBody::SetPositionL(const TTimeIntervalMicroSeconds& aPosition)
+	{
+	User::LeaveIfError(iController.SetPosition(aPosition));
+	}
+
+
+TTimeIntervalMicroSeconds CVideoPlayerUtility::CBody::DurationL() const
+	{
+	TTimeIntervalMicroSeconds duration;
+	User::LeaveIfError(iController.GetDuration(duration));
+	return duration;
+	}
+
+TTimeIntervalMicroSeconds CVideoPlayerUtility::CBody::PositionL() const
+	{
+	TTimeIntervalMicroSeconds position;
+	User::LeaveIfError(iController.GetPosition(position));
+	return position;
+	}
+
+TInt CVideoPlayerUtility::CBody::MaxVolume() const
+	{
+	TInt maxVol = 0;
+	iAudioPlayDeviceCustomCommands.GetMaxVolume(maxVol);
+	return maxVol;
+	}
+
+void CVideoPlayerUtility::CBody::GetFrameL(TDisplayMode aDisplayMode, TBool aUseIntentAPI, TIntent aIntent)
+	{
+	delete iFrameBitmap;
+	iFrameBitmap = NULL;
+	iFrameBitmap = new (ELeave) CFbsBitmap;
+	User::LeaveIfError(iFrameBitmap->Create(TSize(0,0),aDisplayMode));
+
+	iFrameCallback->SetFrame(*iFrameBitmap);
+
+	if (aUseIntentAPI)
+		{
+		iVideoDRMExtCustomCommands.GetFrame(*iFrameBitmap, aIntent, iFrameCallback->ActiveStatus());
+		}
+	else
+		{
+		iVideoPlayControllerCustomCommands.GetFrame(*iFrameBitmap, iFrameCallback->ActiveStatus());
+		}
+	}
+
+MMMFDRMCustomCommand* CVideoPlayerUtility::CBody::GetDRMCustomCommand()
+	{
+	// TODO: check controller supports MMMFDRMCustomCommandImplementor
+	TInt error = iDRMCustomCommands.EvaluateIntent(ContentAccess::EPeek);
+	if (error==KErrNone)
+		{
+		return static_cast<MMMFDRMCustomCommand*>(&iDRMCustomCommands);
+		}
+	else
+		{
+		return NULL;
+		}
+	}
+	
+TInt CVideoPlayerUtility::CBody::VideoBitRateL() const
+	{
+	TInt bitRate;
+	User::LeaveIfError(iVideoControllerCustomCommands.GetVideoBitRate(bitRate));
+	return bitRate;
+	}
+
+TInt CVideoPlayerUtility::CBody::AudioBitRateL() const
+	{
+	TInt bitRate;
+	User::LeaveIfError(iVideoControllerCustomCommands.GetAudioBitRate(bitRate));
+	return bitRate;
+	}
+
+TBool CVideoPlayerUtility::CBody::AudioEnabledL() const
+	{
+	TBool enabled;
+	User::LeaveIfError(iVideoPlayControllerCustomCommands.GetAudioEnabled(enabled));
+	return enabled;
+	}
+	
+	
+void CVideoPlayerUtility::CBody::RefreshFrameL()
+	{
+	User::LeaveIfError(iVideoPlayControllerCustomCommands.RefreshFrame());
+	}
+
+TFourCC CVideoPlayerUtility::CBody::AudioTypeL() const
+	{
+	TFourCC codec;
+	User::LeaveIfError(iVideoControllerCustomCommands.GetAudioCodec(codec));
+	return codec;
+	}
+
+
+void CVideoPlayerUtility::CBody::HandleEvent(const TMMFEvent& aEvent)
+	{
+	if (aEvent.iEventType == KMMFEventCategoryVideoOpenComplete)
+		{
+		// if we haven't had a MfaocComplete() callback yet,
+		// we need to delay the call back to the client
+		// because the source/sink will not have been opened yet.
+		iEventOpenReceived = ETrue;
+		if (iOpenError == KErrNone)
+			iOpenError = aEvent.iErrorCode;
+		if (iCallbackOpenReceived)
+			iObserver.MvpuoOpenComplete(aEvent.iErrorCode);
+		}
+	else if (aEvent.iEventType == KMMFEventCategoryVideoPrepareComplete)
+		{
+		iObserver.MvpuoPrepareComplete(aEvent.iErrorCode);
+		}
+	else if (aEvent.iEventType == KMMFEventCategoryPlaybackComplete)
+		{
+		iObserver.MvpuoPlayComplete(aEvent.iErrorCode);
+		}
+	else if (aEvent.iEventType == KMMFEventCategoryVideoLoadingStarted)
+		{
+		if (iVideoLoadingObserver)
+			iVideoLoadingObserver->MvloLoadingStarted();
+		}
+	else if (aEvent.iEventType == KMMFEventCategoryVideoLoadingComplete)
+		{
+		if (iVideoLoadingObserver)
+			iVideoLoadingObserver->MvloLoadingComplete();
+		}
+	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);	
+			}
+		}
+#ifdef SYMBIAN_BUILD_GCE
+	else if(aEvent.iEventType == KMMFEventCategoryVideoSurfaceCreated)
+		{
+		TInt error = SurfaceCreated();
+			
+		if (error != KErrNone)	
+			{
+			// Send error to the client
+			TMMFEvent generalError(KMMFEventCategoryVideoPlayerGeneralError, error);
+			iObserver.MvpuoEvent(generalError);	
+			}
+		}
+	else if(aEvent.iEventType == KMMFEventCategoryVideoSurfaceParametersChanged)
+		{
+		TInt error = SurfaceParametersChanged();
+				
+		if (error != KErrNone)	
+			{
+			// Send error to the client
+			TMMFEvent generalError(KMMFEventCategoryVideoPlayerGeneralError, error);
+			iObserver.MvpuoEvent(generalError);	
+			}
+		}		
+	else if(aEvent.iEventType == KMMFEventCategoryVideoRemoveSurface)
+		{
+		// Check surface is created
+		TInt error = RemoveSurface(ETrue);
+			
+		if (error != KErrNone)
+			{
+			// Send error to the client
+			TMMFEvent generalError(KMMFEventCategoryVideoPlayerGeneralError, error);
+			iObserver.MvpuoEvent(generalError);	
+			}
+		}
+#endif // SYMBIAN_BUILD_GCE	
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+	else if(aEvent.iEventType == KMMFEventCategoryVideoSubtitleCrpReady)
+		{
+		if (iSubtitleUtility)
+			{
+			// subtitle has not been disabled before event arrive
+			RWindow* window = FindWindowWithWsHandle(iActiveDisplays, aEvent.iErrorCode);
+			if (window)
+				{
+				// window has not been removed before event arrive
+				iSubtitleUtility->HandleCrpReady(*window);
+				}
+			}
+		}
+#endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+	else 
+		// Pass on all unrecognised events to the client
+		iObserver.MvpuoEvent(aEvent);
+	}
+
+#ifdef SYMBIAN_BUILD_GCE
+TInt CVideoPlayerUtility::CBody::SurfaceCreated()
+	{
+	TInt count = iActiveDisplays.Count();
+	TBool replaceSurface = !(iSurfaceId.IsNull());
+	TSurfaceId oldSurfaceId(iSurfaceId);
+	
+	// first remove surface if one already in use
+	if(replaceSurface)
+		{
+		for (TInt i = 0; i < count; i++)
+			{
+			CMediaClientVideoDisplayBody* display = iActiveDisplays[i];
+			display->RemoveSurface(EFalse);
+			}
+		iSurfaceId = TSurfaceId::CreateNullId();
+		}
+	
+	TSurfaceId surfaceId;
+	TRect cropRect;
+	TVideoAspectRatio aspectRatio;
+	
+	TInt error = iVideoPlaySurfaceSupportCustomCommands.GetSurfaceParameters(surfaceId, 
+										cropRect, 
+										aspectRatio);
+	if(error != KErrNone)
+		{
+		if(replaceSurface)
+				{
+				// ignore error
+				iVideoPlaySurfaceSupportCustomCommands.SurfaceRemoved(oldSurfaceId);
+				}
+		return error;
+		}
+	
+	// loop through all displays, if any fail continue and report error later
+	TInt error2;
+	for (TInt i = 0; i < count; ++i)
+		{
+		error2 = iActiveDisplays[i]->SurfaceCreated(surfaceId, cropRect, aspectRatio, iCropRegion);
+		if(error2 != KErrNone)
+			{
+			error = error2;
+			}
+		}
+	
+	// now store surface details
+	iSurfaceId = surfaceId;
+	iSurfaceCropRect = cropRect;
+	iAspectRatio = aspectRatio;
+	
+	// if surface already existed tell video adaptation it is no longer in use. Video adaptation
+	// will remove the surface when it receives this call therefore the following code must be done at the
+	// end of this function.
+	if (replaceSurface)
+        {
+        error2 = iVideoPlaySurfaceSupportCustomCommands.SurfaceRemoved(oldSurfaceId);
+        if (error2 != KErrNone)
+            {
+            error = error2;
+            }
+        }
+    return error;
+	}
+
+TInt CVideoPlayerUtility::CBody::SurfaceParametersChanged()
+	{
+	if (iSurfaceId.IsNull())
+		{
+		return KErrNotSupported;
+		}
+	
+	TSurfaceId surfaceId;
+	TRect cropRect;
+	TVideoAspectRatio aspectRatio;
+	
+	TInt error = iVideoPlaySurfaceSupportCustomCommands.GetSurfaceParameters(surfaceId, 
+										cropRect, 
+										aspectRatio);
+	if (error != KErrNone)
+		{
+		return error;
+		}
+	
+	if (iSurfaceId != surfaceId)
+		{
+		return KErrInUse;
+		}
+
+	TInt count = iActiveDisplays.Count();
+	TInt error2 = KErrNone;
+	for (TInt i = 0; i < count; ++i)
+		{
+		// ignore error and continue to set parameters
+		iActiveDisplays[i]->SurfaceParametersChanged(surfaceId, cropRect, aspectRatio);
+		
+		// save the error for the first failure and attempt to redraw remaining displays
+		error2 = iActiveDisplays[i]->RedrawWindows(iCropRegion);
+		if ((error2 != KErrNone) && (error == KErrNone))
+			{
+			error = error2;
+			}
+		}
+	return error;
+	}
+		
+TInt CVideoPlayerUtility::CBody::SetAllBackgroundSurfaces()
+	{
+	TInt count = iActiveDisplays.Count();
+	TInt err = KErrNone;
+	
+	for (TInt i = 0; i < count; ++i)
+		{
+		CMediaClientVideoDisplayBody* display = iActiveDisplays[i];
+		err = display->RedrawWindows(iCropRegion);
+			
+		if (err != KErrNone)
+			{
+			break;
+			}
+		}
+	return err;
+	}
+
+TInt CVideoPlayerUtility::CBody::RemoveSurface(TBool aControllerEvent)
+	{
+	if (iSurfaceId.IsNull())
+		{
+		return KErrNotFound;
+		}
+	
+	TInt count = iActiveDisplays.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		iActiveDisplays[i]->RemoveSurface(aControllerEvent);
+		}
+	
+	TInt error = iVideoPlaySurfaceSupportCustomCommands.SurfaceRemoved(iSurfaceId);
+
+	iSurfaceId = TSurfaceId::CreateNullId();
+	
+	return error;
+	}
+	
+#endif // SYMBIAN_BUILD_GCE
+
+void CVideoPlayerUtility::CBody::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/)
+	{
+	if (iControllerOpen)
+		{
+		iVideoPlayControllerCustomCommands.DirectScreenAccessEvent(EAbortDSA);
+		iDirectScreenAccessAbort = ETrue;
+		}
+	}
+
+void CVideoPlayerUtility::CBody::Restart(RDirectScreenAccess::TTerminationReasons /*aReason*/) 
+	{
+	__ASSERT_ALWAYS(iDirectScreenAccess, User::Panic(_L("iDirectScreenAccess is NULL"), KErrArgument)); // should always be valid if we have a callback from it
+	TRAPD( err, iDirectScreenAccess->StartL());
+
+	if (iControllerOpen)
+		{
+		if (err == KErrNone)
+			{
+			iVideoPlayControllerCustomCommands.UpdateDisplayRegion(*iDirectScreenAccess->DrawingRegion());
+			iVideoPlayControllerCustomCommands.DirectScreenAccessEvent(EResumeDSA);
+			}
+		}
+	}
+
+TInt CVideoPlayerUtility::CBody::CustomCommandSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TDes8& aDataFrom)
+	{
+	return iController.CustomCommandSync(aDestination, aFunction, aDataTo1, aDataTo2, aDataFrom);
+	}
+	
+TInt CVideoPlayerUtility::CBody::CustomCommandSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2)
+	{
+	return iController.CustomCommandSync(aDestination, aFunction, aDataTo1, aDataTo2);
+	}
+	
+void CVideoPlayerUtility::CBody::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 CVideoPlayerUtility::CBody::CustomCommandAsync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TRequestStatus& aStatus)
+	{
+	iController.CustomCommandAsync(aDestination, aFunction, aDataTo1, aDataTo2, aStatus);
+	}
+	
+void CVideoPlayerUtility::CBody::SetVideoFrameRateL(TReal32 aFramesPerSecond)
+	{
+	User::LeaveIfError(iVideoControllerCustomCommands.SetFrameRate(aFramesPerSecond));
+	}
+
+const CMMFControllerImplementationInformation& CVideoPlayerUtility::CBody::ControllerImplementationInformationL()
+	{
+	if (!iControllerImplementationInformation)
+		{
+		if (iControllerUid==KNullUid)
+			User::Leave(KErrNotReady);
+		iControllerImplementationInformation = CMMFControllerImplementationInformation::NewL(iControllerUid);
+		}
+	return *iControllerImplementationInformation;
+	}
+	
+void CVideoPlayerUtility::CBody::GetVideoLoadingProgressL(TInt& aPercentageProgress)
+	{
+	User::LeaveIfError(iVideoPlayControllerCustomCommands.GetLoadingProgress(aPercentageProgress));
+	}
+
+void CVideoPlayerUtility::CBody::StopDirectScreenAccessL()
+	{
+#ifdef SYMBIAN_BUILD_GCE
+	if (iUsingVPU2)
+		{
+		User::Leave(KErrNotSupported);
+		}
+
+	if (!iGraphicsSurfaceSupported)
+		{
+		__ASSERT_ALWAYS(iDirectScreenAccess, User::Panic(_L("iDirectScreenAccess is NULL"), KErrArgument));
+		iDirectScreenAccess->Cancel();
+		AbortNow(RDirectScreenAccess::ETerminateCancel);
+		}
+#else
+	__ASSERT_ALWAYS(iDirectScreenAccess, User::Panic(_L("iDirectScreenAccess is NULL"), KErrArgument));
+	iDirectScreenAccess->Cancel();
+	AbortNow(RDirectScreenAccess::ETerminateCancel);
+#endif // SYMBIAN_BUILD_GCE
+	}
+	
+void CVideoPlayerUtility::CBody::StartDirectScreenAccessL()
+	{
+#ifdef SYMBIAN_BUILD_GCE
+	if (iUsingVPU2)
+		{
+		User::Leave(KErrNotSupported);
+		}
+
+	if (!iGraphicsSurfaceSupported)
+		{
+		// ETerminateCancel is a dummy value that is ignored by Restart()
+		Restart(RDirectScreenAccess::ETerminateCancel);
+		}
+#else
+	// ETerminateCancel is a dummy value that is ignored by Restart()
+	Restart(RDirectScreenAccess::ETerminateCancel);
+#endif  // SYMBIAN_BUILD_GCE
+	}
+
+//registers for notification when audio resource is available.
+TInt CVideoPlayerUtility::CBody::RegisterAudioResourceNotification( MMMFAudioResourceNotificationCallback& aCallback, 
+																	TUid aNotificationEventUid, 
+																	const TDesC8& aNotificationRegistrationData)
+	{
+	//if not valid notification event id, return;
+	if(aNotificationEventUid != KMMFEventCategoryAudioResourceAvailable)
+		{
+		return KErrNotSupported;
+		}
+		
+	iAudioResourceNotificationCallBack = &aCallback;
+	TInt err = iNotificationRegistrationCommands.RegisterAsClient(aNotificationEventUid, aNotificationRegistrationData);
+	if(err == KErrNotReady)
+		{
+		//save the request - so that registration can be attempted on play
+		iArnEventHolder = 	aNotificationEventUid;
+		iNotificationDataHolder = aNotificationRegistrationData;
+		return KErrNone;
+		}
+	iArnEventHolder = KNullUid;
+	iNotificationDataHolder = KNullDesC8;
+	return err;
+	}
+
+//Cancels the registration for audio resource notification.
+TInt CVideoPlayerUtility::CBody::CancelRegisterAudioResourceNotification(TUid aNotificationEventId)
+	{
+	//if not valid notification event id, return;
+	if(aNotificationEventId != KMMFEventCategoryAudioResourceAvailable)
+		{
+		return KErrNotSupported;
+		}
+	TInt err = iNotificationRegistrationCommands.CancelRegisterAsClient(aNotificationEventId);
+	if(err == KErrNotReady)
+		{
+		if(iArnEventHolder == KNullUid)	
+			{
+			return KErrCancel;
+			}
+		//iArnEventHolder has data to re-attempt registration ;
+		//but reattempt is not made(which is done in play);hence return KErrNone
+		iArnEventHolder = KNullUid;
+		iNotificationDataHolder = KNullDesC8;
+		return KErrNone;
+		}
+	return err;
+	}
+
+//Waits for the client to resume the play even after the default timer expires.
+TInt CVideoPlayerUtility::CBody::WillResumePlay()
+	{
+	return iNotificationRegistrationCommands.WillResumePlay();
+	}
+
+// This method will fail with KErrNotSupported when using CVideoPlayerUtility2, otherwise
+// set the screen number.
+TInt CVideoPlayerUtility::CBody::SetInitScreenNumber(TInt aScreenNumber)
+	{
+#ifdef SYMBIAN_BUILD_GCE
+	// If the method is called from CVideoPlayerUtility2, return KErrNotSupport
+	if (iUsingVPU2)
+		{
+		return KErrNotSupported;
+		}
+#endif
+		
+#ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT
+	iScreenNumber = aScreenNumber;
+	return KErrNone;
+#else
+	aScreenNumber = aScreenNumber;//added to remove the warning
+	return KErrNotSupported;
+#endif
+	}
+
+#ifdef SYMBIAN_BUILD_GCE
+//-------------------------------------------------------------------------------
+
+void CVideoPlayerUtility::CBody::AddDisplayWindowL(RWsSession& aWs, CWsScreenDevice& aScreenDevice, 
+							RWindow& aWindow, const TRect& aVideoExtent, 
+							const TRect& aWindowClipRect)
+	{
+	// set window and get display ID for the window
+	TRect windowRect = TRect(aWindow.Size()); 
+	
+	// Check the rectangle is contained completely within the window
+	if (!RectContains(windowRect, aWindowClipRect))
+		{
+		// NOTE: TRect::Contains() is not used for comparison here as point located on the right hand 
+		//       side or bottom is considered to be outside the rectangle, which is not the desirable 
+		//       behaviour in this case
+		User::Leave(KErrArgument);
+		}
+		
+	DoAddDisplayWindowL(aWs, aScreenDevice.GetScreenNumber(), aWindow, aWindowClipRect, aVideoExtent, &aWindow);
+	}
+	
+void CVideoPlayerUtility::CBody::AddDisplayWindowL(RWsSession& aWs, CWsScreenDevice& aScreenDevice, RWindow& aWindow)
+	{
+	DoAddDisplayWindowL(aWs, aScreenDevice.GetScreenNumber(), aWindow, TRect(aWindow.Size()), TRect(aWindow.Size()), &aWindow);
+	}
+
+void CVideoPlayerUtility::CBody::DoAddDisplayWindowL(RWsSession& aWs, TInt aDisplayId, RWindowBase& aWindow,
+								const TRect& aClipRect, const TRect& aVideoExtent, RWindow* aWindow2)
+	{
+	iWs = &aWs;
+
+	// check opening the source is complete and the client has been recieved an MvpuoOpenComplete() callback
+	if (!iControllerOpen)
+		{
+		User::Leave(KErrNotReady);
+		}
+
+	// make sure window isn't already added on another display
+	TRAPD(err, CMediaClientVideoDisplayBody::FindDisplayWithWindowL(iActiveDisplays, aWindow));
+	if (err != KErrNotFound)
+		{
+		// If err is something else but KErrNone leave
+		User::LeaveIfError(err);
+		// Window is already in use
+		User::Leave(KErrInUse);
+		}
+
+	TInt pos = iActiveDisplays.FindInOrder(aDisplayId, CMediaClientVideoDisplayBody::CompareByDisplay);
+	CMediaClientVideoDisplayBody* display = NULL;
+
+	if (pos == KErrNotFound)
+		{
+		if(iSurfaceId.IsNull())
+			{
+			display = CMediaClientVideoDisplayBody::NewL(aDisplayId);
+			}
+		else
+			{
+			display = CMediaClientVideoDisplayBody::NewL(aDisplayId, iSurfaceId, iSurfaceCropRect, iAspectRatio);
+			}
+		CleanupStack::PushL(display);
+		iActiveDisplays.InsertInOrderL(display, CMediaClientVideoDisplayBody::Compare);
+		CleanupStack::Pop(display);
+		}
+	else 
+		{
+		User::LeaveIfError(pos);
+		display = iActiveDisplays[pos];
+		}
+
+	display->AddDisplayWindowL(&aWindow, aClipRect, iCropRegion, aVideoExtent, iGlobalScaleWidth, iGlobalScaleHeight,
+								iGlobalRotation, iGlobalAutoScaleType, iGlobalHorizPos, iGlobalVertPos, aWindow2);
+
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+	if (iSubtitleUtility)
+		{
+		// subtitles were enabled already, so enable subtitles on this window
+		TMMFSubtitleWindowConfig config;
+		config.iWindowId = aWindow.WsHandle();
+		config.iWindowClipRect = aClipRect;
+		config.iDisplayMode = aWindow.DisplayMode();
+		config.iRotation = iGlobalRotation;
+		iSubtitleUtility->AddSubtitleConfig(config); // ignore error from add subtitle config because the window can still display video properly
+		}
+#endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+	}
+
+void CVideoPlayerUtility::CBody::RemoveDisplayWindow(RWindowBase& aWindow)
+	{
+	CMediaClientVideoDisplayBody* display = NULL;
+	TRAPD(err, display = CMediaClientVideoDisplayBody::FindDisplayWithWindowL(iActiveDisplays, aWindow));
+	
+	if (err == KErrNone)
+		{		
+		display->RemoveDisplayWindow(aWindow);
+	
+		if (!display->IsUsed())
+
+			{
+			TInt pos = iActiveDisplays.Find(display);
+			iActiveDisplays.Remove(pos);
+			delete display;
+			}
+
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+		if (iSubtitleUtility)
+			{
+			// subtitles are enabled, so remove window config, ignore error
+			iSubtitleUtility->RemoveSubtitleConfig(aWindow.WsHandle());
+			}
+#endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+		}	
+	}
+
+void CVideoPlayerUtility::CBody::AddDisplayL(TInt aDisplay, MMMFSurfaceEventHandler& aEventHandler)
+	{
+	if (!iControllerOpen)
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	TInt err = iActiveDisplays.FindInOrder(aDisplay, CMediaClientVideoDisplayBody::CompareByDisplay);
+	
+	if (err == KErrNotFound)
+		{
+		CMediaClientVideoDisplayBody* display;
+		if(iSurfaceId.IsNull())
+			{
+			display = CMediaClientVideoDisplayBody::NewL(aDisplay);
+			}
+		else
+			{
+			display = CMediaClientVideoDisplayBody::NewL(aDisplay, iSurfaceId, iSurfaceCropRect, iAspectRatio);
+			}
+		CleanupStack::PushL(display);
+		iActiveDisplays.InsertInOrderL(display, CMediaClientVideoDisplayBody::Compare);
+		CleanupStack::Pop(display);
+		display->AddDisplayL(aEventHandler);
+		}
+	else
+		{
+		User::LeaveIfError(err);
+		iActiveDisplays[err]->AddDisplayL(aEventHandler);
+		}
+	}
+
+void CVideoPlayerUtility::CBody::RemoveDisplay(TInt aDisplay)
+	{
+	TInt pos = iActiveDisplays.FindInOrder(aDisplay, CMediaClientVideoDisplayBody::CompareByDisplay);
+	
+	if (pos >= KErrNone)
+		{
+		CMediaClientVideoDisplayBody* disp = iActiveDisplays[pos];
+		disp->RemoveDisplay();
+		
+		if (!disp->HasWindows())
+			{
+			iActiveDisplays.Remove(pos);
+			delete disp;
+			}
+		}
+	}
+
+void CVideoPlayerUtility::CBody::ConvertFromRelativeToDisplayToRelativeToWindow(
+            const RWindowBase& aWindow,
+            const TRect& aFromWindowRect,
+            const TRect& aFromClipRect,
+            TRect& aToWindowRect,
+            TRect& aToClipRect)
+    {
+    TPoint windowOrigin = aWindow.AbsPosition();
+    
+    // window rect
+    aToWindowRect.iTl.iX = aFromWindowRect.iTl.iX - windowOrigin.iX;
+    aToWindowRect.iTl.iY = aFromWindowRect.iTl.iY - windowOrigin.iY;
+    aToWindowRect.iBr.iX = aFromWindowRect.iBr.iX - windowOrigin.iX;
+    aToWindowRect.iBr.iY = aFromWindowRect.iBr.iY - windowOrigin.iY;
+    
+    // clip rect
+    aToClipRect.iTl.iX = aFromClipRect.iTl.iX - windowOrigin.iX;
+    aToClipRect.iTl.iY = aFromClipRect.iTl.iY - windowOrigin.iY;
+    aToClipRect.iBr.iX = aFromClipRect.iBr.iX - windowOrigin.iX;
+    aToClipRect.iBr.iY = aFromClipRect.iBr.iY - windowOrigin.iY;
+    }
+
+void CVideoPlayerUtility::CBody::SetVideoExtentL(const RWindowBase& aWindow, const TRect& aVideoExtent)
+	{
+	// check opening the source is complete and the client has been recieved an MvpuoOpenComplete() callback
+	if (!iControllerOpen)
+		{
+		User::Leave(KErrNotReady);
+		}
+		
+	CMediaClientVideoDisplayBody* display = CMediaClientVideoDisplayBody::FindDisplayWithWindowL(iActiveDisplays, aWindow);
+	display->SetVideoExtentL(aWindow, aVideoExtent, iCropRegion);
+	}
+
+void CVideoPlayerUtility::CBody::SetWindowClipRectL(const RWindowBase& aWindow, const TRect& aWindowClipRect)
+	{
+    // check opening the source is complete and the client has been recieved an MvpuoOpenComplete() callback
+	if (!iControllerOpen)
+		{
+		User::Leave(KErrNotReady);
+		}
+
+	TRect winRect(aWindow.Size());
+
+	if (!RectContains(winRect, aWindowClipRect))
+		{
+		User::Leave(KErrArgument);
+		}
+		
+	CMediaClientVideoDisplayBody* display = CMediaClientVideoDisplayBody::FindDisplayWithWindowL(iActiveDisplays, aWindow);
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+	RArray<CMediaClientVideoDisplayBody::TWindowData>& windows = display->Windows();
+	TInt pos = windows.Find(aWindow.WsHandle(), CMediaClientVideoDisplayBody::TWindowData::CompareByWsHandle);
+	User::LeaveIfError(pos);
+	
+	CMediaClientVideoDisplayBody::TWindowData& currentWin = windows[pos];
+	if (currentWin.iClipRect != aWindowClipRect)
+		{
+		// update config only if setting has actually changed
+		UpdateSurfaceAndSubtitleConfigL(*display, currentWin, aWindowClipRect, currentWin.iRotation, iCropRegion);
+		}
+#else
+	display->SetWindowClipRectL(aWindow, aWindowClipRect, iCropRegion);
+#endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+	}
+
+// Check if the controller supports the graphics surface. Has to be called after resource opened.
+TInt CVideoPlayerUtility::CBody::CheckSurfaceSupported()
+	{
+	TInt err = iFindAndOpenController->SurfaceSupported();
+		
+	if (err == KErrNone)
+		{
+		iGraphicsSurfaceSupported = ETrue;
+		}
+	else 
+		{
+		iGraphicsSurfaceSupported = EFalse;
+		}
+		
+	return err;
+	}
+
+TBool CVideoPlayerUtility::CBody::RectContains(const TRect& aLeft, const TRect& aRight)
+	{
+	return !(aLeft.iTl.iX > aRight.iTl.iX || 
+			aLeft.iTl.iY > aRight.iTl.iY ||
+	    	aLeft.iBr.iX < aRight.iBr.iX || 
+	    	aLeft.iBr.iY < aRight.iBr.iY);
+	}
+	
+	
+void CVideoPlayerUtility::CBody::SetAutoScaleL(const RWindowBase& aWindow, TAutoScaleType aScaleType)
+	{
+	SetAutoScaleL(aWindow, aScaleType, EHorizontalAlignCenter, EVerticalAlignCenter);
+	}
+	
+void CVideoPlayerUtility::CBody::SetAutoScaleL(const RWindowBase& aWindow, TAutoScaleType aScaleType, TInt aHorizPos, TInt aVertPos)
+	{
+	if (!iControllerOpen)
+		{
+		User::Leave(KErrNotReady);
+		}
+		
+	CMediaClientVideoDisplayBody* display = CMediaClientVideoDisplayBody::FindDisplayWithWindowL(iActiveDisplays, aWindow);
+	display->SetAutoScaleL(aWindow, aScaleType, aHorizPos, aVertPos, iCropRegion);
+	}
+
+void CVideoPlayerUtility::CBody::SetRotationL(const RWindowBase& aWindow, TVideoRotation aRotation)
+	{
+	if (!iControllerOpen)
+		{
+		User::Leave(KErrNotReady);
+		}
+
+	CMediaClientVideoDisplayBody* display = CMediaClientVideoDisplayBody::FindDisplayWithWindowL(iActiveDisplays, aWindow);
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+	RArray<CMediaClientVideoDisplayBody::TWindowData>& windows = display->Windows();
+	TInt pos = windows.Find(aWindow.WsHandle(), CMediaClientVideoDisplayBody::TWindowData::CompareByWsHandle);
+	User::LeaveIfError(pos);
+	
+	CMediaClientVideoDisplayBody::TWindowData& currentWin = windows[pos];
+	if (currentWin.iRotation != aRotation)
+		{
+		UpdateSurfaceAndSubtitleConfigL(*display, currentWin, currentWin.iClipRect, aRotation, iCropRegion);
+		}
+#else
+	display->SetRotationL(aWindow, aRotation, iCropRegion);
+#endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+	}
+	
+TVideoRotation CVideoPlayerUtility::CBody::RotationL(const RWindowBase& aWindow) const
+	{
+	if (!iControllerOpen)
+		{
+		User::Leave(KErrNotReady);
+		}
+	CMediaClientVideoDisplayBody* display = CMediaClientVideoDisplayBody::FindDisplayWithWindowL(iActiveDisplays, aWindow);
+	return display->RotationL(aWindow);
+	}
+	
+void CVideoPlayerUtility::CBody::SetScaleFactorL(const RWindowBase& aWindow, TReal32 aWidthPercentage, TReal32 aHeightPercentage)
+	{
+	if (!iControllerOpen)
+		{
+		User::Leave(KErrNotReady);
+		
+		}
+	CMediaClientVideoDisplayBody* display = CMediaClientVideoDisplayBody::FindDisplayWithWindowL(iActiveDisplays, aWindow);
+	display->SetScaleFactorL(aWindow, aWidthPercentage, aHeightPercentage, iCropRegion);
+	}
+	
+void CVideoPlayerUtility::CBody::GetScaleFactorL(const RWindowBase& aWindow, TReal32& aWidthPercentage, TReal32& aHeightPercentage) const
+	{
+	if (!iControllerOpen)
+		{
+		User::Leave(KErrNotReady);
+		
+		}
+	CMediaClientVideoDisplayBody* display = CMediaClientVideoDisplayBody::FindDisplayWithWindowL(iActiveDisplays, aWindow);
+	display->GetScaleFactorL(aWindow, aWidthPercentage, aHeightPercentage);
+	}
+
+void CVideoPlayerUtility::CBody::SetExternalDisplaySwitchingL(TInt aDisplay, TBool aControl)
+    {
+    TInt pos = iActiveDisplays.FindInOrder(aDisplay, CMediaClientVideoDisplayBody::CompareByDisplay);
+    
+    User::LeaveIfError(pos);
+    
+    iActiveDisplays[pos]->SetExternalDisplaySwitchingL(aControl);
+    }
+
+#endif // SYMBIAN_BUILD_GCE
+
+void CVideoPlayerUtility::CBody::SetPlayVelocityL(TInt aVelocity)
+	{
+	// Leave if Open is not yet called on controller.
+	if(!iEventOpenReceived)
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	User::LeaveIfError(iVideoPlayControllerExtCustomCommands.SetPlayVelocity(aVelocity));	
+	}
+
+const TInt KDefaultPlayVelocity = 100;
+
+TInt CVideoPlayerUtility::CBody::PlayVelocityL() const
+	{
+	TInt velocity;
+	TInt error;
+
+	// Leave if Open is not yet called.
+	if( !iEventOpenReceived )
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	error = iVideoPlayControllerExtCustomCommands.PlayVelocity(velocity);
+	/* if customcommand is not implemented by controller pluggin return default value(100) */
+	if (KErrNotSupported == error)
+		{
+		velocity = KDefaultPlayVelocity;
+		}
+	else
+		{
+		User::LeaveIfError(	error );	
+		}
+	return velocity;
+	}
+void CVideoPlayerUtility::CBody::StepFrameL(TInt aStep)
+	{
+	//Leave if not in paused state. This functionality is supported only in paused state.
+	if( (!iEventOpenReceived ) || ( EPaused != iState ) )
+		{
+		User::Leave(KErrNotReady);
+		}
+
+	User::LeaveIfError(iVideoPlayControllerExtCustomCommands.StepFrame(aStep));
+	}
+void CVideoPlayerUtility::CBody::GetPlayRateCapabilitiesL(TVideoPlayRateCapabilities& aCapabilities) const
+	{
+	TInt error;
+
+	// Leave if Open is not yet called on controller.
+	if( !iEventOpenReceived )
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	error = iVideoPlayControllerExtCustomCommands.GetPlayRateCapabilities(aCapabilities);
+	/* if customcommand is not implemented by controller pluggin return not supported */
+	if (KErrNotSupported == error)
+		{
+		aCapabilities.iPlayBackward = EFalse;
+		aCapabilities.iPlayForward = EFalse;
+		aCapabilities.iStepBackward = EFalse;
+		aCapabilities.iStepForward = EFalse;
+		}
+	else
+		{
+		User::LeaveIfError(error);
+		}	
+	}
+void CVideoPlayerUtility::CBody::SetVideoEnabledL(TBool aVideoEnabled)
+	{
+	// Leave if Open is not yet called or not in stopped state.
+	if( (!iEventOpenReceived ) || ( EStopped != iState ) )
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	User::LeaveIfError(iVideoPlayControllerExtCustomCommands.SetVideoEnabled(aVideoEnabled));
+	}
+TBool CVideoPlayerUtility::CBody::VideoEnabledL() const
+	{
+	TBool videoEnabled;
+	TInt error;
+
+	// Leave if Open is not yet called.
+	if( !iEventOpenReceived )
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	error = iVideoPlayControllerExtCustomCommands.VideoEnabled(videoEnabled);
+	/* if customcommand is not implemented by controller pluggin return default value ETrue */
+	if (KErrNotSupported == error)
+		{
+		videoEnabled = ETrue;
+		}
+	else
+		{
+		User::LeaveIfError(error);
+		}	
+	return videoEnabled;
+	}
+void CVideoPlayerUtility::CBody::SetAudioEnabledL(TBool aAudioEnabled)
+	{
+	// Leave if Open is not yet called or not in stopped state.
+	if( (!iEventOpenReceived ) || ( EStopped != iState ) )
+		{
+		User::Leave(KErrNotReady);
+		}
+	
+	User::LeaveIfError(iVideoPlayControllerExtCustomCommands.SetAudioEnabled(aAudioEnabled));
+	}
+void CVideoPlayerUtility::CBody::SetAutoScaleL(TAutoScaleType aScaleType)
+	{
+	SetAutoScaleL(aScaleType, EHorizontalAlignCenter, EVerticalAlignCenter);
+	}
+void CVideoPlayerUtility::CBody::SetAutoScaleL(TAutoScaleType aScaleType, TInt aHorizPos, TInt aVertPos)
+	{
+	// Leave if Open is not yet called.
+	if(!iEventOpenReceived )
+		{
+		User::Leave(KErrNotReady);
+		}	
+
+#ifdef SYMBIAN_BUILD_GCE
+	if (!iGraphicsSurfaceSupported)
+		{
+		User::LeaveIfError(iVideoPlayControllerExtCustomCommands.SetAutoScale(aScaleType, aHorizPos, aVertPos));
+		}
+	else
+		{
+		// Auto scale setting is not sent to controller when graphics surfaces are used.
+		// If the surface has been created, perform auto scale with the help of graphics surfaces;
+		// otherwise, just store the auto scale info.
+		iGlobalAutoScaleType = aScaleType;
+		iGlobalHorizPos = aHorizPos;
+		iGlobalVertPos = aVertPos;
+		
+		TInt count = iActiveDisplays.Count();
+		
+		for (TInt i = 0; i < count; ++i)
+			{
+			iActiveDisplays[i]->SetAutoScaleL(aScaleType, aHorizPos, aVertPos, iCropRegion);
+			}
+		}
+#else
+	User::LeaveIfError(iVideoPlayControllerExtCustomCommands.SetAutoScale(aScaleType, aHorizPos, aVertPos));
+#endif // SYMBIAN_BUILD_GCE
+	}
+
+#ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+TBool CVideoPlayerUtility::CBody::SubtitlesAvailable()
+	{
+	if (!iControllerOpen)
+		{
+		return EFalse;
+		}
+
+	return CMMFSubtitleUtility::SubtitlesAvailable(iController);
+	}
+
+void CVideoPlayerUtility::CBody::EnableSubtitlesL()
+	{
+	// Check if video file and controller is opened
+	__ASSERT_ALWAYS(iControllerOpen, VPUDebugPanicOrLeaveL(EMMFVideoPlayerUtilityFileNotOpened, KErrNotReady));
+	// Check if subtitles are already enabled
+	__ASSERT_ALWAYS(!iSubtitleUtility, User::Leave(KErrInUse));
+	// Check if display window is added
+	TBool windowsAdded = EFalse;
+	for (TInt i = iActiveDisplays.Count()-1; (i >= 0 && windowsAdded == EFalse); --i)
+		{
+		CMediaClientVideoDisplayBody* display = iActiveDisplays[i];
+		windowsAdded = display->HasWindows();
+		}
+	__ASSERT_ALWAYS(windowsAdded, VPUDebugPanicOrLeaveL(EMMFVideoPlayerUtilityNoWindowAdded, KErrNotReady));
+
+
+	iSubtitleUtility = CMMFSubtitleUtility::NewL(iController, *iWs);
+	TInt err = iSubtitleUtility->EnableSubtitles();
+	if (KErrNone != err)
+		{
+		delete iSubtitleUtility;
+		iSubtitleUtility = NULL;
+		if (KErrNotSupported == err || KErrNotFound == err)
+			{
+			// controller does not support subtitles or subtitle source not found,
+			// panic client because they should have called SubtitlesAvailable first
+			VPUDebugPanicOrLeaveL(EMMFVideoPlayerUtilitySubtitleNotSupported, err);
+			}
+		
+		// leave in release mode or any other error
+		User::Leave(err);
+		}
+
+	TBool subtitleEnabled = EFalse;
+	TInt count = iActiveDisplays.Count();
+	
+	// add the windows in the orders that they were added
+	for (TInt i = 0; i < count; ++i)
+		{
+		CMediaClientVideoDisplayBody* display = iActiveDisplays[i];
+		err = EnableSubtitles(*display);
+		
+		if (KErrNone == err)
+			{
+			subtitleEnabled = ETrue;
+			}
+		}
+
+	// no subtitle window was enabled successfully, enable subtitle failed
+	if (!subtitleEnabled)
+		{
+		DisableSubtitles();	// disable subtitle on controller side
+		User::Leave(err); // Leave with error returned by last EnableSubtitles call
+		}
+	}
+
+void CVideoPlayerUtility::CBody::DisableSubtitles()
+	{
+	if (iSubtitleUtility)
+		{
+		iSubtitleUtility->DisableSubtitles();
+		
+		delete iSubtitleUtility;
+		iSubtitleUtility = NULL;
+		}
+	}
+
+TArray<TLanguage> CVideoPlayerUtility::CBody::SupportedSubtitleLanguagesL()
+	{
+	// Check if subtitles have been enabled
+	__ASSERT_ALWAYS(iSubtitleUtility, VPUDebugPanicOrLeaveL(EMMFVideoPlayerUtilitySubtitleNotEnabled, KErrNotReady));
+
+	return iSubtitleUtility->SupportedSubtitleLanguagesL();
+	}
+
+TLanguage CVideoPlayerUtility::CBody::SubtitleLanguageL()
+	{
+	// Check if subtitles have been enabled
+	__ASSERT_ALWAYS(iSubtitleUtility, VPUDebugPanicOrLeaveL(EMMFVideoPlayerUtilitySubtitleNotEnabled, KErrNotReady));
+
+	return iSubtitleUtility->SubtitleLanguage();
+	}
+
+void CVideoPlayerUtility::CBody::SetSubtitleLanguageL(TLanguage aLanguage)
+	{
+	// Check if subtitles have been enabled
+	__ASSERT_ALWAYS(iSubtitleUtility, VPUDebugPanicOrLeaveL(EMMFVideoPlayerUtilitySubtitleNotEnabled, KErrNotReady));
+
+	TInt err = iSubtitleUtility->SetSubtitleLanguage(aLanguage);
+	if (KErrNotSupported == err)
+		{
+		// panic on debug because client should call SupportedSubtitleLanguagesL() first
+		VPUDebugPanicOrLeaveL(EMMFVideoPlayerUtilitySubtitleLanguageNotSupported, KErrNotSupported);
+		}
+	User::LeaveIfError(err);
+	}
+
+void CVideoPlayerUtility::CBody::RedrawSubtitle(RWindow& aWindow, const TRect &aRect)
+	{
+	if (iSubtitleUtility)
+		{
+		// subtitle is enabled
+		RWindow* window = FindWindowWithWsHandle(iActiveDisplays, aWindow.WsHandle());
+		if (window) // check that window was added for video playback
+			{
+			iSubtitleUtility->RedrawSubtitle(aWindow, aRect);
+			}
+		}
+	// else ignore the redraw request
+	}
+
+RWindow* CVideoPlayerUtility::CBody::FindWindowWithWsHandle(const RPointerArray<CMediaClientVideoDisplayBody>& aDisplays, TInt aWsHandle)
+	{
+	TInt count = aDisplays.Count();
+	
+	for (TInt i = 0; i < count; ++i)
+		{
+		CMediaClientVideoDisplayBody* display = aDisplays[i];
+		RArray<CMediaClientVideoDisplayBody::TWindowData>& windows = display->Windows();
+		TInt pos = windows.Find(aWsHandle, CMediaClientVideoDisplayBody::TWindowData::CompareByWsHandle);
+		if (pos >= 0)
+			{
+			return windows[pos].iWindow2;
+			}
+		}
+		
+	return NULL;
+	}
+
+// Update the supplied window with the new clip rect and rotation
+// If updating of surface failed, this function leave after restoring the original aWindowData
+void CVideoPlayerUtility::CBody::UpdateSurfaceAndSubtitleConfigL(CMediaClientVideoDisplayBody& aDisplay,CMediaClientVideoDisplayBody::TWindowData& aWindowData, const TRect& aClipRect, TVideoRotation aRotation, const TRect& aCropRegion)
+	{
+	TRect oldClipRect = aWindowData.iClipRect;
+	TVideoRotation oldRotation = aWindowData.iRotation;
+	
+	aWindowData.iClipRect = aClipRect;
+	aWindowData.iRotation = aRotation;
+	
+	if (aDisplay.IsSurfaceCreated())
+		{
+		TInt err = aDisplay.SetBackgroundSurface(aWindowData, aCropRegion);
+		if (KErrNone != err)
+			{
+			aWindowData.iClipRect = oldClipRect;
+			aWindowData.iRotation = oldRotation;
+			User::Leave(err);
+			}
+		}
+	
+	// Set background was successful or surface was not created, so 
+	// update subtitle config if subtitles are enabled
+	if (iSubtitleUtility)
+		{
+		TMMFSubtitleWindowConfig config;
+		GetSubtitleConfigFromWindowData(aWindowData, config);
+
+		iSubtitleUtility->UpdateSubtitleConfig(config);
+		}
+	}
+
+void CVideoPlayerUtility::CBody::GetSubtitleConfigFromWindowData(CMediaClientVideoDisplayBody::TWindowData& aWindowData, TMMFSubtitleWindowConfig& aConfig)
+	{
+	aConfig.iWindowId = aWindowData.iWindow->WsHandle();
+	aConfig.iWindowClipRect = aWindowData.iClipRect;
+	aConfig.iDisplayMode = aWindowData.iWindow->DisplayMode();
+	aConfig.iRotation = aWindowData.iRotation;
+	
+	}
+TInt CVideoPlayerUtility::CBody::EnableSubtitles(CMediaClientVideoDisplayBody& aDisplay)
+	{
+	TBool windowAdded = EFalse;
+	RArray<CMediaClientVideoDisplayBody::TWindowData> windows = aDisplay.Windows();
+	
+ 	TInt count = windows.Count();
+	TInt err = KErrNone;	
+	// add the windows in the orders that they are added
+	for (TInt i = 0; i < count; ++i)
+		{
+		err = AddSubtitleConfig(windows[i]);
+		if (KErrNone == err)
+			{
+			windowAdded = ETrue;
+			}
+		}
+
+	// Return the error code returned by the last AddSubtitleConfig call.
+	if (!windowAdded)
+		{
+		return err;
+		}
+	
+	return KErrNone;
+	}
+
+TInt CVideoPlayerUtility::CBody::AddSubtitleConfig(CMediaClientVideoDisplayBody::TWindowData& aWindowData)
+	{
+	ASSERT(iSubtitleUtility);
+	TMMFSubtitleWindowConfig config;
+	GetSubtitleConfigFromWindowData(aWindowData, config);
+	
+	return iSubtitleUtility->AddSubtitleConfig(config);
+	}
+#endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
+