mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.cpp
changeset 0 40261b775718
child 7 94dbab0a2133
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,958 @@
+// 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 "mediaclientvideodisplaybody.h"
+#include "mediaclientvideotrace.h"
+#include <surfaceeventhandler.h>
+
+CMediaClientVideoDisplayBody* CMediaClientVideoDisplayBody::NewL(TInt aDisplayId)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::NewL +++"));
+	CMediaClientVideoDisplayBody* self = new (ELeave) CMediaClientVideoDisplayBody(aDisplayId);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::NewL ---"));
+	return self;
+	}
+
+CMediaClientVideoDisplayBody* CMediaClientVideoDisplayBody::NewL(TInt aDisplayId, const TSurfaceId& aSurfaceId,
+		const TRect& aCropRect, TVideoAspectRatio aAspectRatio)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::NewL +++"));
+	if(aSurfaceId.IsNull())
+		{
+		User::Leave(KErrArgument);
+		}
+	CMediaClientVideoDisplayBody* self = new(ELeave) CMediaClientVideoDisplayBody(aDisplayId, aSurfaceId, aCropRect, aAspectRatio);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::NewL ---"));
+	return self;
+	}
+
+void CMediaClientVideoDisplayBody::ConstructL()
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::ConstructL +++"));
+	
+	iExtDisplaySwitchingSupported = CExtDisplayConnectionProviderInterface::ExternalDisplaySupportedL();
+	
+	// Try and enable display switching by default. If this leaves then do so quietly.
+	// Either the client has no scheduler installed or the device does not support external
+	// switching (i.e. no plugin was found) 
+	TRAPD(err, SetExternalDisplaySwitchingL(ETrue));
+	err = err; // remove compile warning
+	DEBUG_PRINT2(_L("CMediaClientVideoDisplayBody::ConstructL SetExternalDisplaySwitchingL returned with %d"), err);
+	
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::ConstructL ---"));
+	}
+
+CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody(TInt aDisplayId, const TSurfaceId& aSurfaceId,
+		const TRect& aCropRect, TVideoAspectRatio aAspectRatio) :
+	iDisplayId(aDisplayId),
+	iSurfaceId(aSurfaceId),
+	iCropRect(aCropRect),
+	iAspectRatio(aAspectRatio)
+	{	
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody ---"));
+	}
+
+CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody(TInt aDisplayId) :
+	iDisplayId(aDisplayId)
+	{	
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody ---"));
+	}
+
+CMediaClientVideoDisplayBody::~CMediaClientVideoDisplayBody()
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::~CMediaClientVideoDisplayBody +++"));
+
+	RemoveBackgroundSurface(ETrue);
+		
+	iWindows.Close();	
+	delete iExtDisplayConnectionProvider;
+	REComSession::FinalClose();
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::~CMediaClientVideoDisplayBody ---"));
+	}
+
+void CMediaClientVideoDisplayBody::AddDisplayL(MMMFSurfaceEventHandler& aEventHandler)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::AddDisplayL +++"));
+	if (iEventHandler != NULL)
+		{
+		User::Leave(KErrInUse);
+		}
+		
+	iEventHandler = &aEventHandler;
+	
+	if (IsSurfaceCreated())
+		{
+		iEventHandler->MmsehSurfaceCreated(iDisplayId, iSurfaceId, iCropRect, iAspectRatio);
+		}
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::AddDisplayL ---"));
+	}
+	
+void CMediaClientVideoDisplayBody::AddDisplayWindowL(const RWindowBase* aWindow, const TRect& aClipRect, const TRect& aCropRegion, const TRect& aVideoExtent, 
+															TReal32 aScaleWidth, TReal32 aScaleHeight, TVideoRotation aRotation, 
+															TAutoScaleType aAutoScaleType, TInt aHorizPos, TInt aVertPos, RWindow* aWindow2)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::AddDisplayWindowL +++"));
+	TInt pos = iWindows.Find(aWindow->WsHandle(), TWindowData::CompareByWsHandle);
+	
+	if (pos != KErrNotFound)
+		{
+		User::Leave(KErrInUse);
+		}
+	
+	TWindowData winData(aWindow, aClipRect, aVideoExtent, aScaleWidth, aScaleHeight, aRotation, aAutoScaleType, aHorizPos, aVertPos, aWindow2);
+	iWindows.AppendL(winData);
+	
+	iCropRegion = aCropRegion;
+	
+	if (IsSurfaceCreated())
+		{
+        if(iExtDisplaySwitchingSupported && iClientRequestedExtDisplaySwitching)
+            {
+            CreateExtDisplayConnProvAndRemoveSurfaceL(EFalse);
+            }
+        
+        if(!iExtDisplayConnected)
+            {
+            User::LeaveIfError(SetBackgroundSurface(winData, aCropRegion));
+            }
+		}
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::AddDisplayWindowL ---"));
+	}
+
+void CMediaClientVideoDisplayBody::RemoveDisplay()
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveDisplay +++"));
+	iEventHandler = NULL;
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveDisplay ---"));
+	}	
+
+TInt CMediaClientVideoDisplayBody::RemoveDisplayWindow(const RWindowBase& aWindow)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveDisplayWindow +++"));
+	TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
+	
+	if (pos >= 0)
+		{
+		if (IsSurfaceCreated())
+			{
+			iWindows[pos].iWindow->RemoveBackgroundSurface(ETrue);
+
+			// Make sure all window rendering has completed before proceeding
+			RWsSession* ws = iWindows[pos].iWindow->Session();
+			if (ws)
+				{
+				ws->Finish();
+				}
+			}
+		iWindows.Remove(pos);
+		
+		if(iWindows.Count() == 0)
+		    {
+		    RemoveExtDisplayConnProv();
+		    }
+		}
+	
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveDisplayWindow ---"));
+	return pos;
+	}
+
+
+TInt CMediaClientVideoDisplayBody::SurfaceCreated(const TSurfaceId& aSurfaceId, const TRect& aCropRect, TVideoAspectRatio aAspectRatio, const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SurfaceCreated +++"));
+	TBool emitEvent = EFalse;
+	if((iSurfaceId != aSurfaceId) && (!aSurfaceId.IsNull()))
+		{
+		emitEvent = ETrue;
+		}
+
+	iSurfaceId = aSurfaceId;
+	iCropRect = aCropRect;
+	iAspectRatio = aAspectRatio;
+	iCropRegion = aCropRegion;
+	
+	if (emitEvent && iEventHandler)
+		{
+		iEventHandler->MmsehSurfaceCreated(iDisplayId, iSurfaceId, iCropRect, iAspectRatio);
+		}
+
+	TInt err = KErrNone;
+    if(iExtDisplaySwitchingSupported && iClientRequestedExtDisplaySwitching)
+        {
+        TRAP(err, CreateExtDisplayConnProvAndRemoveSurfaceL(EFalse));
+        }
+    
+    if(!iExtDisplayConnected)
+        {
+        err = RedrawWindows(aCropRegion);
+        }
+    
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SurfaceCreated ---"));
+	return err;
+	}
+
+void CMediaClientVideoDisplayBody::RemoveBackgroundSurface(TBool aTriggerRedraw)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveBackgroundSurface +++"));
+	if (IsSurfaceCreated())
+		{
+		TInt count = iWindows.Count();
+	
+		RWsSession* ws = NULL;
+		for (TInt i = 0; i < count; ++i)
+			{
+			iWindows[i].iWindow->RemoveBackgroundSurface(aTriggerRedraw);
+			// Make sure all window rendering has completed before proceeding
+			ws = iWindows[i].iWindow->Session();
+			if (ws)
+				{
+				ws->Finish();
+				}
+			}
+		}
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveBackgroundSurface ---"));
+	}
+
+void CMediaClientVideoDisplayBody::RemoveSurface(TBool aControllerEvent)
+    {
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveSurface +++"));
+    if (IsSurfaceCreated())
+        {
+        if(!iExtDisplayConnected)
+            {
+            RemoveBackgroundSurface(ETrue);
+            }
+        
+        if (iEventHandler  && aControllerEvent)
+            {
+            iEventHandler->MmsehRemoveSurface(iSurfaceId);
+            }
+
+        iSurfaceId = TSurfaceId::CreateNullId();
+
+        RemoveExtDisplayConnProv();
+        }
+    
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveSurface ---"));
+    }
+
+TInt CMediaClientVideoDisplayBody::SurfaceParametersChanged(const TSurfaceId& aSurfaceId, const TRect& aCropRect, TVideoAspectRatio aAspectRatio)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SurfaceParametersChanged +++"));
+	if (!IsSurfaceCreated())
+		{
+		return KErrNotSupported;
+		}
+
+	if (iSurfaceId != aSurfaceId)
+		{
+		return KErrInUse;
+		}
+	
+	iCropRect = aCropRect;
+	iAspectRatio = aAspectRatio;
+	
+	if (iEventHandler)
+		{
+		iEventHandler->MmsehSurfaceParametersChanged(iSurfaceId, iCropRect, iAspectRatio);
+		}
+
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SurfaceParametersChanged ---"));
+	return KErrNone;
+	}
+	
+TInt CMediaClientVideoDisplayBody::RedrawWindows(const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RedrawWindows +++"));
+	TInt err = KErrNone;	
+
+	iCropRegion = aCropRegion;
+	
+	if(IsSurfaceCreated())
+		{
+		TInt count = iWindows.Count();
+	
+		for (TInt i = 0; i < count; ++i)
+			{
+			err = SetBackgroundSurface(iWindows[i], aCropRegion);
+		
+			if (err != KErrNone)
+				{
+				break;
+				}
+			}
+		}
+		
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RedrawWindows ---"));
+	return err;
+	}
+
+void CMediaClientVideoDisplayBody::SetAutoScaleL(const RWindowBase& aWindow, TAutoScaleType aScaleType, TInt aHorizPos, TInt aVertPos, const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetAutoScaleL +++"));
+	TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
+	User::LeaveIfError(pos);
+	
+	iWindows[pos].iAutoScaleType = aScaleType;
+	iWindows[pos].iHorizPos = aHorizPos;
+	iWindows[pos].iVertPos = aVertPos;
+	iCropRegion = aCropRegion;
+	
+	if (IsSurfaceCreated() && !iExtDisplayConnected)
+		{
+		User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion));
+		}
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetAutoScaleL ---"));
+	}
+	
+
+void CMediaClientVideoDisplayBody::SetRotationL(const RWindowBase& aWindow, TVideoRotation aRotation, const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetRotationL +++"));
+	TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
+	User::LeaveIfError(pos);
+	
+	iWindows[pos].iRotation = aRotation;
+	iCropRegion = aCropRegion;
+	
+    if (IsSurfaceCreated() && !iExtDisplayConnected)
+		{
+		User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion));
+		}
+	
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetRotationL ---"));
+	}
+
+TVideoRotation CMediaClientVideoDisplayBody::RotationL(const RWindowBase& aWindow)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RotationL +++"));
+	TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
+	User::LeaveIfError(pos);
+	
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RotationL ---"));
+	return iWindows[pos].iRotation;
+	}
+
+void CMediaClientVideoDisplayBody::SetScaleFactorL(const RWindowBase& aWindow, TReal32 aWidthPercentage, TReal32 aHeightPercentage, const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetScaleFactorL +++"));
+	TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
+	User::LeaveIfError(pos);
+	
+	if (aWidthPercentage <= 0.0 || aHeightPercentage <= 0.0)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	
+	iWindows[pos].iScaleWidth = aWidthPercentage;
+	iWindows[pos].iScaleHeight = aHeightPercentage;
+	iWindows[pos].iAutoScaleType = EAutoScaleNone;
+	iCropRegion = aCropRegion;
+	
+    if (IsSurfaceCreated() && !iExtDisplayConnected)
+		{
+		User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion));
+		}
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetScaleFactorL ---"));
+	}
+	
+void CMediaClientVideoDisplayBody::GetScaleFactorL(const RWindowBase& aWindow, TReal32& aWidthPercentage, TReal32& aHeightPercentage)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::GetScaleFactorL +++"));
+	TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
+	User::LeaveIfError(pos);
+	
+	aWidthPercentage = iWindows[pos].iScaleWidth;
+	aHeightPercentage = iWindows[pos].iScaleHeight;
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::GetScaleFactorL ---"));
+	}
+
+void CMediaClientVideoDisplayBody::SetAutoScaleL(TAutoScaleType aScaleType, TInt aHorizPos, TInt aVertPos, const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetAutoScaleL +++"));
+	
+	iCropRegion = aCropRegion;
+	TInt count = iWindows.Count();
+	
+	for (TInt i = 0; i < count; ++i)
+		{
+		iWindows[i].iAutoScaleType = aScaleType;
+		iWindows[i].iHorizPos = aHorizPos;
+		iWindows[i].iVertPos = aVertPos;
+	    if (IsSurfaceCreated() && !iExtDisplayConnected)
+			{
+			User::LeaveIfError(SetBackgroundSurface(iWindows[i], aCropRegion));
+			}
+		}
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetAutoScaleL ---"));
+	}
+
+
+void CMediaClientVideoDisplayBody::SetRotationL(TVideoRotation aRotation, const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetRotationL +++"));
+	iCropRegion = aCropRegion;
+	TInt count = iWindows.Count();
+	
+	for (TInt i = 0; i < count; ++i)
+		{
+		iWindows[i].iRotation = aRotation;
+	    if (IsSurfaceCreated() && !iExtDisplayConnected)
+			{
+			User::LeaveIfError(SetBackgroundSurface(iWindows[i], aCropRegion));
+			}
+		}
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetRotationL ---"));
+	}
+		
+void CMediaClientVideoDisplayBody::SetScaleFactorL(TReal32 aWidthPercentage, TReal32 aHeightPercentage, const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetScaleFactorL +++"));
+	if (aWidthPercentage <= 0.0 || aHeightPercentage <= 0.0)
+		{
+		User::Leave(KErrArgument);
+		}
+	
+	iCropRegion = aCropRegion;
+	TInt count = iWindows.Count();
+	
+	for (TInt i = 0; i < count; ++i)
+		{
+		iWindows[i].iScaleWidth = aWidthPercentage;
+		iWindows[i].iScaleHeight = aHeightPercentage;
+		iWindows[i].iAutoScaleType = EAutoScaleNone;
+	    if (IsSurfaceCreated() && !iExtDisplayConnected)
+			{
+			User::LeaveIfError(SetBackgroundSurface(iWindows[i], aCropRegion));
+			}
+		}
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetScaleFactorL ---"));
+	}
+
+void CMediaClientVideoDisplayBody::SetWindowClipRectL(const RWindowBase& aWindow, const TRect& aWindowClipRect, const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetWindowClipRectL +++"));
+	
+	TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
+	User::LeaveIfError(pos);
+	
+	iWindows[pos].iClipRect = aWindowClipRect;
+	iCropRegion = aCropRegion;
+	
+    if (IsSurfaceCreated() && !iExtDisplayConnected)
+		{
+		User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion));
+		}
+	
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetWindowClipRectL ---"));
+	}
+	
+void CMediaClientVideoDisplayBody::SetVideoExtentL(const RWindowBase& aWindow, const TRect& aVideoExtent, const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetVideoExtentL +++"));
+	TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
+	User::LeaveIfError(pos);
+	
+	iWindows[pos].iVideoExtent = aVideoExtent;
+	iCropRegion = aCropRegion;
+	
+    if (IsSurfaceCreated() && !iExtDisplayConnected)
+		{
+		User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion));
+		}
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetVideoExtentL ---"));
+	}
+	
+TBool CMediaClientVideoDisplayBody::HasWindows() const
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::HasWindows +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::HasWindows ---"));
+	return (iWindows.Count() > 0);
+	}
+	
+TInt CMediaClientVideoDisplayBody::SetBackgroundSurface(TWindowData& aWindowData,  
+									const TRect& aCropRegion)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetBackgroundSurface +++"));
+	
+	// required as this private function is called directly from external friend class
+	iCropRegion = aCropRegion;
+
+    // viewport is the viewable area of surface
+    TRect viewport(iCropRect);
+    if (aCropRegion.Width() > 0 || aCropRegion.Height() > 0)
+        {
+        viewport.Intersection(aCropRegion);
+        }
+    
+    // Viewport is 0 size, don't show any video
+    if (viewport.Width() <= 0 || viewport.Height() <= 0)
+        {
+        return KErrArgument;
+        }
+
+	TRect extent;
+	CalculateExtentAndViewport(aWindowData, extent, viewport);
+	
+	aWindowData.iSurfaceConfig.SetViewport(viewport);
+	aWindowData.iSurfaceConfig.SetExtent(extent);
+	aWindowData.iSurfaceConfig.SetOrientation(ConvertRotation(aWindowData.iRotation));
+	
+	aWindowData.iSurfaceConfig.SetSurfaceId(iSurfaceId);
+	
+	// Get the rectangle that bounds the crop rectangle and the viewport.  This should be
+	// the same as the crop rectangle as long as the viewport does not go outside this area.
+	TRect rect(iCropRect);
+	rect.BoundingRect(viewport);
+	TInt err = KErrNone;
+	
+	// Check if the viewport and extent can be displayed as a background surface. The viewport 
+	// is valid if it is within the crop rectangle and is not empty.  The extent is valid if 
+	// it is not empty. 
+	if (rect == iCropRect && !viewport.IsEmpty() && !extent.IsEmpty())
+		{
+		err = aWindowData.iWindow->SetBackgroundSurface(aWindowData.iSurfaceConfig, ETrue);
+		}
+
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetBackgroundSurface ---"));
+	return err;
+	}
+
+void CMediaClientVideoDisplayBody::CalculateExtentAndViewport(const TWindowData& aWindowData, TRect& aExtent, TRect& aViewport)
+    {
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CalculateExtentAndViewport +++"));
+
+    TRect videoExtent(aWindowData.iVideoExtent);
+    
+    TReal32 inputWidth = 0.0f;
+    TReal32 inputHeight = 0.0f;
+    TReal32 pixelAspectRatio = 0.0f;
+    switch (aWindowData.iRotation)
+        {
+        case EVideoRotationNone:
+        case EVideoRotationClockwise180:
+            inputWidth = static_cast<TReal32>(aViewport.Width());
+            inputHeight = static_cast<TReal32>(aViewport.Height());
+            pixelAspectRatio = static_cast<TReal32>(iAspectRatio.iNumerator) / iAspectRatio.iDenominator;
+            break;
+        case EVideoRotationClockwise90:
+        case EVideoRotationClockwise270:
+            inputWidth = static_cast<TReal32>(aViewport.Height());
+            inputHeight = static_cast<TReal32>(aViewport.Width());
+            pixelAspectRatio = static_cast<TReal32>(iAspectRatio.iDenominator) / iAspectRatio.iNumerator;
+            break;
+        default:
+            // Should never get to default unless there's been some programming error.
+            User::Invariant();
+            break;
+        }
+        
+    TReal32 viewportAspect = pixelAspectRatio * inputWidth / inputHeight;
+    TReal32 vidextAspect = static_cast<TReal32>(videoExtent.Width()) / static_cast<TReal32>(videoExtent.Height());
+    
+    // Set the extent to the display area in the window.  The final height and with is to 
+    // be changed by deltaHeight and deltaWidth respectively.
+    aExtent = videoExtent;
+    
+    TInt deltaHeight = 0;
+    TInt deltaWidth = 0;
+    
+    if (aWindowData.iAutoScaleType == EAutoScaleBestFit)
+        {
+        if (viewportAspect > vidextAspect)
+            {
+            // Shrink height to get the correct aspect ratio
+            deltaHeight = (TInt) (aExtent.Width() / viewportAspect - aExtent.Height());
+            }
+        else
+            {
+            // Shrink width to get the correct aspect ratio
+            deltaWidth = (TInt) (aExtent.Height() * viewportAspect - aExtent.Width());
+            }
+        }
+    else if (aWindowData.iAutoScaleType == EAutoScaleClip)
+        {
+        if (viewportAspect > vidextAspect)
+            {
+            // Expand width to get the correct aspect ratio
+            deltaWidth = (TInt) (aExtent.Height() * viewportAspect - aExtent.Width());
+            }
+        else
+            {
+            // Expand height to get the correct aspect ratio
+            deltaHeight = (TInt) (aExtent.Width() / viewportAspect - aExtent.Height());
+            }
+        }
+    else if (aWindowData.iAutoScaleType == EAutoScaleStretch)
+        {
+        // Don't do anything: the extent is already set to the size of the video extent.
+        }
+    else if (aWindowData.iAutoScaleType == EAutoScaleNone)
+        {
+        // for non-square pixels, reduce one dimension
+        // TBD other option is to enlarge in the other dimension
+        if(pixelAspectRatio > 1)
+            {
+            inputHeight /= pixelAspectRatio;
+            }
+        else if(pixelAspectRatio < 1)
+            {
+            inputWidth *= pixelAspectRatio;
+            }
+        deltaHeight = (TInt) (inputHeight * aWindowData.iScaleHeight * 0.01 - videoExtent.Height());
+        deltaWidth = (TInt) (inputWidth * aWindowData.iScaleWidth * 0.01 - videoExtent.Width());
+        }
+    
+    // Change the width of the extent in the proper directions and propertions.
+    switch (aWindowData.iHorizPos)
+        {
+    case EHorizontalAlignCenter:
+        aExtent.iTl.iX -= deltaWidth / 2;
+        aExtent.iBr.iX += deltaWidth / 2;
+        break;
+    case EHorizontalAlignLeft:
+        aExtent.iBr.iX += deltaWidth;
+        break;
+    case EHorizontalAlignRight:
+        aExtent.iTl.iX -= deltaWidth;
+        break;
+    default:
+        TInt width = aExtent.Width() + deltaWidth;
+        aExtent.iTl.iX += aWindowData.iHorizPos;
+        aExtent.iBr.iX = aExtent.iTl.iX + width;
+        break;
+        }
+    
+    // Change the height of the extent in the proper directions and propertions.
+    switch (aWindowData.iVertPos)
+        {
+    case EVerticalAlignCenter:
+        aExtent.iTl.iY -= deltaHeight / 2;
+        aExtent.iBr.iY += deltaHeight / 2;
+        break;
+    case EVerticalAlignTop:
+        aExtent.iBr.iY += deltaHeight;
+        break;
+    case EVerticalAlignBottom:
+        aExtent.iTl.iY -= deltaHeight;
+        break;
+    default:
+        TInt height = aExtent.Height() + deltaHeight;
+        aExtent.iTl.iY += aWindowData.iVertPos;
+        aExtent.iBr.iY = aExtent.iTl.iY + height;
+        break;
+        }
+        
+    // The video should not be displayed outside the intended video extent or clipping rectangle.  
+    // The extent already has the correct size and position for displaying the entire viewport.  
+    // The viewport is clipped such that the video is not moved/distorted when we take the extent 
+    // to be the intersection of itself and the intended video extent.
+    
+    TRect viewableArea(videoExtent);
+    viewableArea.Intersection(aWindowData.iClipRect);
+    
+    // Number of pixels (in window coordinates) to be clipped on the right, bottom, top and left sides of
+    // the video.
+    TInt dr = Max(0, aExtent.iBr.iX - viewableArea.iBr.iX);
+    TInt db = Max(0, aExtent.iBr.iY - viewableArea.iBr.iY);
+    TInt dt = Max(0, viewableArea.iTl.iY - aExtent.iTl.iY);
+    TInt dl = Max(0, viewableArea.iTl.iX - aExtent.iTl.iX);
+    
+    // Calculate the number of pixels in the video per window pixel in both x and y directions.
+    TReal32 wRatio = 0.0f; 
+    TReal32 hRatio = 0.0f;
+    
+    // Make sure we don't divide by 0
+    if (aExtent.Width() != 0)
+        {
+        wRatio = inputWidth / static_cast<TReal32>(aExtent.Width());
+        }
+    
+    if (aExtent.Height() != 0)
+        {
+        hRatio = inputHeight / static_cast<TReal32>(aExtent.Height());
+        }
+    
+    // Clip the viewport 
+    switch (aWindowData.iRotation)
+        {
+        case EVideoRotationNone:
+            aViewport.iBr.iX -= (TInt) (wRatio * static_cast<TReal32>(dr));
+            aViewport.iBr.iY -= (TInt) (hRatio * static_cast<TReal32>(db));
+            aViewport.iTl.iX += (TInt) (wRatio * static_cast<TReal32>(dl));
+            aViewport.iTl.iY += (TInt) (hRatio * static_cast<TReal32>(dt));
+            break;
+        case EVideoRotationClockwise180:
+            aViewport.iBr.iX -= (TInt) (wRatio * static_cast<TReal32>(dl));
+            aViewport.iBr.iY -= (TInt) (hRatio * static_cast<TReal32>(dt));
+            aViewport.iTl.iX += (TInt) (wRatio * static_cast<TReal32>(dr));
+            aViewport.iTl.iY += (TInt) (hRatio * static_cast<TReal32>(db));
+            break;
+        case EVideoRotationClockwise90:
+            aViewport.iBr.iX -= (TInt) (wRatio * static_cast<TReal32>(db));
+            aViewport.iBr.iY -= (TInt) (hRatio * static_cast<TReal32>(dl));
+            aViewport.iTl.iX += (TInt) (wRatio * static_cast<TReal32>(dt));
+            aViewport.iTl.iY += (TInt) (hRatio * static_cast<TReal32>(dr));
+            break;
+        case EVideoRotationClockwise270:
+            aViewport.iBr.iX -= (TInt) (wRatio * static_cast<TReal32>(dt));
+            aViewport.iBr.iY -= (TInt) (hRatio * static_cast<TReal32>(dr));
+            aViewport.iTl.iX += (TInt) (wRatio * static_cast<TReal32>(db));
+            aViewport.iTl.iY += (TInt) (hRatio * static_cast<TReal32>(dl));
+            break;
+        default:
+            // Should never get to default unless there's been some programming error.
+            User::Invariant();
+            break;
+        }
+    
+    // Clip the extent.
+    aExtent.Intersection(viewableArea);
+    
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CalculateExtentAndViewport ---"));
+    }
+
+TBool CMediaClientVideoDisplayBody::IsUsed() const
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::IsUsed +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::IsUsed ---"));
+	return (iEventHandler != NULL || iWindows.Count() > 0);
+	}
+	
+
+TBool CMediaClientVideoDisplayBody::IsSurfaceCreated() const
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::IsSurfaceCreated +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::IsSurfaceCreated ---"));
+	return !(iSurfaceId.IsNull());
+	}
+		
+TInt CMediaClientVideoDisplayBody::DisplayId() const
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::DisplayId +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::DisplayId ---"));
+	return iDisplayId;
+	}
+	
+TInt CMediaClientVideoDisplayBody::CompareByDisplay(const TInt* aDisplayId, const CMediaClientVideoDisplayBody& aDisplay)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CompareByDisplay +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CompareByDisplay ---"));
+	return (*aDisplayId - aDisplay.DisplayId());
+	}
+		
+TInt CMediaClientVideoDisplayBody::Compare(const CMediaClientVideoDisplayBody& aLeft, const CMediaClientVideoDisplayBody& aRight)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::Compare +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::Compare ---"));
+	return (aLeft.DisplayId() - aRight.DisplayId());
+	}
+	
+CFbsBitGc::TGraphicsOrientation CMediaClientVideoDisplayBody::ConvertRotation(TVideoRotation aRotation)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::ConvertRotation +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::ConvertRotation ---"));
+	switch(aRotation)
+		{
+		case EVideoRotationNone:
+			return CFbsBitGc::EGraphicsOrientationNormal;
+		case EVideoRotationClockwise90:
+			return CFbsBitGc::EGraphicsOrientationRotated270;
+		case EVideoRotationClockwise180:
+			return CFbsBitGc::EGraphicsOrientationRotated180;
+		case EVideoRotationClockwise270:
+			return CFbsBitGc::EGraphicsOrientationRotated90;
+		default:
+			// Should never get to default unless there's been some programming error.
+			User::Invariant();
+			// This is never reached, just to keep the compiler happy
+			return CFbsBitGc::EGraphicsOrientationNormal;
+		}
+	}
+
+CMediaClientVideoDisplayBody* CMediaClientVideoDisplayBody::FindDisplayWithWindowL(const RPointerArray<CMediaClientVideoDisplayBody>& aDisplays, const RWindowBase& aWindow)
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::FindDisplayWithWindowL +++"));
+	TInt count = aDisplays.Count();
+	
+	for (TInt i = 0; i < count; ++i)
+		{
+		CMediaClientVideoDisplayBody* display = aDisplays[i];
+	
+		if (display->iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle) != KErrNotFound)
+			{
+			DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::FindDisplayWithWindowL ---"));
+			return display;	
+			}
+		}
+		
+	User::Leave(KErrNotFound);
+	return NULL;
+	}
+	
+RArray<CMediaClientVideoDisplayBody::TWindowData>& CMediaClientVideoDisplayBody::Windows()
+	{
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::Windows +++"));
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::Windows ---"));
+	return iWindows;	
+	}
+
+void CMediaClientVideoDisplayBody::MedcpcExtDisplayCalculateExtentAndViewportL(TRect& aExtent, TRect& aViewport, TRect& aExternalDisplayRect)
+    {
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::MedcpcExtDisplayCalculateExtentAndViewportL +++"));
+    
+    TWindowData windowData;
+    windowData.iVideoExtent = aExternalDisplayRect;
+    windowData.iRotation = EVideoRotationNone;
+    windowData.iAutoScaleType = EAutoScaleBestFit;
+    windowData.iHorizPos = EHorizontalAlignCenter;
+    windowData.iVertPos = EVerticalAlignCenter;
+    windowData.iClipRect = aExternalDisplayRect;
+    
+    aViewport = iCropRect;
+    // Viewport is 0 size, don't show any video
+    if (aViewport.Width() <= 0 || aViewport.Height() <= 0)
+        {
+        User::Leave(KErrArgument);
+        }
+    
+    CalculateExtentAndViewport(windowData, aExtent, aViewport);
+    
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::MedcpcExtDisplayCalculateExtentAndViewportL ---"));
+    }
+
+void CMediaClientVideoDisplayBody::CreateExtDisplayConnProvAndRemoveSurfaceL(TBool aRemoveBackgroundSurface)
+    {
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CreateExtDisplayConnProvAndRemoveSurfaceL +++"));
+
+    if((iExtDisplayConnectionProvider == NULL) && (iWindows.Count() > 0))
+        {
+        iExtDisplayConnectionProvider = CExtDisplayConnectionProviderInterface::NewL(*this, iSurfaceId);
+        iExtDisplayConnected = iExtDisplayConnectionProvider->ExtDisplayConnectedL();
+        
+        if(iExtDisplayConnected && aRemoveBackgroundSurface)
+            {
+            RemoveBackgroundSurface(ETrue);
+            }
+        }
+
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CreateExtDisplayConnProvAndRemoveSurfaceL ---"));
+    }
+   
+void CMediaClientVideoDisplayBody::RemoveExtDisplayConnProvAndRedrawL()
+    {
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveExtDisplayConnProvAndRedrawL +++"));
+
+    if(iExtDisplayConnectionProvider != NULL)
+        {
+        delete iExtDisplayConnectionProvider;
+        REComSession::FinalClose();
+        iExtDisplayConnectionProvider = NULL;
+        iExtDisplayConnected = EFalse;
+        User::LeaveIfError(RedrawWindows(iCropRegion));
+        }
+
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveExtDisplayConnProvAndRedrawL ---"));
+    }
+
+void CMediaClientVideoDisplayBody::RemoveExtDisplayConnProv()
+    {
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveExtDisplayConnProv +++"));
+
+    if(iExtDisplayConnectionProvider != NULL)
+        {
+        delete iExtDisplayConnectionProvider;
+        REComSession::FinalClose();
+        iExtDisplayConnectionProvider = NULL;
+        iExtDisplayConnected = EFalse;
+        }
+
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveExtDisplayConnProv ---"));
+    }
+
+void CMediaClientVideoDisplayBody::SetExternalDisplaySwitchingL(TBool aControl)
+    {
+    DEBUG_PRINT2(_L("CMediaClientVideoDisplayBody::SetExternalDisplaySwitchingL +++ aControl=%d"), aControl);
+
+    // not supported
+    if(!iExtDisplaySwitchingSupported)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    
+    // need active scheduler installed
+    if(CActiveScheduler::Current() == NULL)
+        {
+        User::Leave(KErrNotReady);
+        }
+
+    if(iClientRequestedExtDisplaySwitching != aControl)
+        {
+        iClientRequestedExtDisplaySwitching = aControl;
+        
+        if(IsSurfaceCreated())
+            {
+            if(iClientRequestedExtDisplaySwitching)
+                {
+                CreateExtDisplayConnProvAndRemoveSurfaceL(ETrue);
+                }
+            else
+                {
+                RemoveExtDisplayConnProvAndRedrawL();
+                }
+            }
+        else
+            {
+            DEBUG_PRINT(_L("No Surface exists"));
+            }
+        }
+    
+    DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetExternalDisplaySwitchingL ---"));
+    }
+
+void CMediaClientVideoDisplayBody::MedcpcExtDisplayNotifyConnected(TBool aExtDisplayConnected)
+	{
+	DEBUG_PRINT2(_L("CMediaClientVideoDisplayBody::MedcpcExtDisplayNotifyConnected +++ aExtDisplayConnected=%d"), aExtDisplayConnected);
+	
+	if(iExtDisplayConnected != aExtDisplayConnected)
+	    {
+	    iExtDisplayConnected = aExtDisplayConnected;
+	    if(iExtDisplayConnected)
+	        {
+	        RemoveBackgroundSurface(ETrue);
+	        }
+	    else
+	        {
+	        // ignore error - no need to tell provider - but lets log it in case it fails
+	        TInt err = RedrawWindows(iCropRegion);
+	        DEBUG_PRINT2(_L("RedrawWindows returned with %d"), err);
+	        }
+	    }
+	else
+	    {
+	    DEBUG_PRINT(_L("No change in ext display connection status"));
+	    }
+	
+	DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::MedcpcExtDisplayNotifyConnected ---"));
+	}