imaging/imagingfws/src/Test/TImageDisplay/TImageDisplay.cpp
changeset 0 5752a19fdefe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imaging/imagingfws/src/Test/TImageDisplay/TImageDisplay.cpp	Wed Aug 25 12:29:52 2010 +0300
@@ -0,0 +1,1416 @@
+// Copyright (c) 2005-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 <barsread.h>
+#include <bidi.h>
+#include <eikenv.h>
+#include <techview/eikchlst.h>
+#include <techview/eikinfo.h>
+#include <techview/eikmenup.h>
+#include <e32math.h>
+#include <badesca.h>
+#include <techview/eikon.rsg>
+#include <eikpriv.rsg>
+#include <bitmaptransforms.h>
+#include <icl/imagedisplayplugin.h>
+#include <icl/geniclimagedisplayext.h>
+
+#include "plugininfoarray.h"
+#include "TImageDisplayAppView.h"
+#include "TImageDisplayDlgs.h"
+
+#include "TImageDisplay.h"
+
+
+const TInt KVideoMinZoomFactor = -3;
+const TInt KVideoMaxZoomFactor = 3;
+
+const TInt KDefaultFolderDelay = 2000000; // 2s. Used when playing a folder
+
+const TInt KButtonMoveIncr = 16;
+
+const TInt KInfoBufferSize = 1024;
+const TInt KNoRotation=-1;
+const TInt KAutoRotate=(1<<16);
+
+_LIT(KDefPath, "C:\\");
+const TInt KShortestPossiblePath=4;
+
+// #define __CLEAR_BITMAPS_FIRST // for debugging purposes, get TImageViewer to clear bitmaps prior to
+							  // decode conversion. Really the codecs should do this, but...
+
+CPluginInfoArray* CPluginInfoArray::NewL()
+	{
+	CPluginInfoArray* self;
+	self = new (ELeave) CPluginInfoArray;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CPluginInfoArray::ConstructL()
+	{
+	RefreshPluginListL();
+	}
+
+CPluginInfoArray::CPluginInfoArray()
+	{
+	}
+
+void CPluginInfoArray::Reset()
+	{
+	iPluginArray.ResetAndDestroy();
+	}
+
+void CPluginInfoArray::RefreshPluginListL()
+	{
+	Reset();
+	CImageEncoder::GetImageTypesL(iPluginArray);
+	}
+
+CPluginInfoArray::~CPluginInfoArray()
+	{
+	Reset();
+	}
+
+TInt CPluginInfoArray::MdcaCount() const
+	{
+	return iPluginArray.Count();
+	}
+
+TPtrC CPluginInfoArray::MdcaPoint(TInt aIndex) const
+	{
+	return iPluginArray[aIndex]->Description(); 
+	}
+
+TUid CPluginInfoArray::ImageType(TInt aIndex)
+	{
+	return iPluginArray[aIndex]->ImageType(); 
+	}
+
+TUid CPluginInfoArray::SubType(TInt aIndex)
+	{
+	return iPluginArray[aIndex]->SubType(); 
+	}
+
+// CFrameInfoDialog
+class CFrameInfoDialog : public CEikDialog
+	{
+public:
+	CFrameInfoDialog(const TDesC& aPropertiesText);
+
+protected:
+	void PreLayoutDynInitL();
+
+private:
+	const TDesC& iPropertiesText;
+	};
+
+CFrameInfoDialog::CFrameInfoDialog(const TDesC& aPropertiesText)
+	: iPropertiesText(aPropertiesText)
+	{
+	}
+
+void CFrameInfoDialog::PreLayoutDynInitL()
+	{
+	// Grab each Edwin and set the text.
+	CEikEdwin* page = static_cast<CEikEdwin*>(Control(EFramePropertiesPage));
+	page->SetTextL(&iPropertiesText);
+
+	}
+
+
+//
+// CVideoWalker
+//
+
+class CVideoWalker : public CActive
+	{
+public:
+	static CVideoWalker* NewL(CImgDisplAppUi* aAppUi);
+	~CVideoWalker();
+	TRequestStatus& ActiveStatus();
+	void SelfComplete(TInt aError);
+protected:
+	CVideoWalker(CImgDisplAppUi* aAppUi);
+	// from CActive
+	void RunL();
+	void DoCancel();
+protected:
+	CImgDisplAppUi*const iAppUi; // not owned
+	};
+
+
+//
+//  CImgDisplAppUi
+//
+
+CImgDisplAppUi::CImgDisplAppUi():
+			iRotationAngle(KNoRotation),
+			iDrmIntent(ContentAccess::EPeek),
+			iScalingQuality(CBitmapScaler::EMinimumQuality)
+	{
+	}
+
+void CImgDisplAppUi::ConstructL()
+    {
+	CEikAppUi::ConstructL();
+
+    iAppView = CImgDisplayAppView::NewL(ClientRect());
+
+	iBackgroundColor = KRgbWhite.Color16();
+	(void) iAppView->SetBackgroundColor(TRgb::Color16(iBackgroundColor), ENoDrawNow);
+
+	iWalker = CVideoWalker::NewL(this);
+	User::LeaveIfError(iTimer.CreateLocal());
+
+	// Note iStreamSeed deliberated left as 0 to give consistent behaviour
+
+	iSaveInfo.iImageTypeUid = KImageTypeJPGUid;
+	iSaveInfo.iBpp = 6;
+	iSaveInfo.iColor = ETrue;
+	iSaveInfo.iQualityFactor = 40;
+	iSaveInfo.iSampling = 2;
+	}
+
+CImgDisplAppUi::~CImgDisplAppUi()
+	{
+	Cancel();
+
+	if (iAppView)
+		{
+		RemoveFromStack(iAppView);
+		delete iAppView;
+		}
+	delete iFrameImageData;
+	delete iSaveUtil;
+	delete iImageDisplay;
+	delete iWalker;
+	iTimer.Close();
+	delete iDir;
+	}
+
+void CImgDisplAppUi::Cancel()
+	{
+	if (iWalker)
+		{
+		iWalker->Cancel(); // if active will callback on DoCancel()
+		}
+	iState = EIdle;
+	}
+
+TKeyResponse CImgDisplAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
+	{
+	TKeyResponse ret = EKeyWasConsumed;
+
+	if (aType!=EEventKey)
+		return ret;
+
+	TUint code = aKeyEvent.iCode;
+
+	switch (code)
+		{
+	case EKeyLeftArrow:
+	case EKeyRightArrow:
+	case EKeyUpArrow:
+	case EKeyDownArrow:
+		{
+		TPoint moveBy;
+		switch (code)
+			{
+		case EKeyLeftArrow:
+			moveBy.SetXY(KButtonMoveIncr,0);
+			break;
+		case EKeyRightArrow:
+			moveBy.SetXY(-KButtonMoveIncr,0);
+			break;
+		case EKeyUpArrow:
+			moveBy.SetXY(0,KButtonMoveIncr);
+			break;
+		case EKeyDownArrow:
+			moveBy.SetXY(0,-KButtonMoveIncr);
+			break;
+			}
+		iAppView->MoveBy(moveBy);
+		}
+		break;
+	case EKeyEscape:
+		Cancel();
+		ASSERT(iState==EIdle);
+		iEikonEnv->BusyMsgCancel();
+		iEikonEnv->InfoMsg(_L("Cancelled"));
+		break;
+	default:
+		ret = EKeyWasNotConsumed;
+		break;
+		}
+	return ret;
+	}
+
+void CImgDisplAppUi::HandleCommandL(TInt aCommand)
+	{
+	switch (aCommand)
+		{
+	case EVideoCmdOpenFile:
+		OpenFileL(EFileTypeUnknown);
+		break;
+	case EVideoCmdOpenFolder:
+		OpenFolderL();
+		break;
+	case EVideoCmdSaveAs:
+		SaveAsL();
+		break;
+	case EVideoCmdMask:
+		iDisableMask = ! iDisableMask;
+		if (iDisableMask)
+			{
+			iEikonEnv->InfoMsg(_L("Mask reset"));
+			}
+		else
+			{
+			iEikonEnv->InfoMsg(_L("Mask enabled"));
+			}
+
+		break;
+	case EVideoCmdToggleFrameDump:
+		iDumpFrames = !iDumpFrames;
+		if (iDumpFrames)
+			{
+			iEikonEnv->InfoMsg(_L("Frame dump is ON"));
+			}
+		else
+			{
+			iEikonEnv->InfoMsg(_L("Frame dump is OFF"));
+			}
+		break;
+	case EVideoCmdDrmParams:
+		DrmParamsL();
+		break;
+	case EVideoCmdClipRectParams:
+		ClipRectParamsL();
+		break;
+	case EVideoCmdDecodeThumbnail:
+		iUseThumbnail = !iUseThumbnail;
+		LoadFileL();
+		break;
+	case EVideoCmdPauseAfterEachFrame:
+		iPauseAfterEachFrame = !iPauseAfterEachFrame;
+		if (iPauseAfterEachFrame)
+			{
+			iEikonEnv->InfoMsg(_L("Pause after each frame is ON"));
+			}
+		else
+			{
+			iEikonEnv->InfoMsg(_L("Pause after each frame is OFF"));
+			}
+		break;
+	case EVideoCmdScalingQuality:
+		ScalingQualityL();
+		break;
+	case EVideoCmdZoomIn:
+		iZoomFactor++;
+		if (iZoomFactor > KVideoMaxZoomFactor)
+			iZoomFactor = KVideoMinZoomFactor;
+		LoadFileL();
+		break;
+	case EVideoCmdZoomOut:
+		iZoomFactor--;
+		if (iZoomFactor < KVideoMinZoomFactor)
+			iZoomFactor = KVideoMaxZoomFactor;
+		LoadFileL();
+		break;
+	case EVideoCmdResetZoom:
+		iZoomFactor=0;
+		LoadFileL();
+		break;
+	case EVideoCmdDisplayMode:
+		DisplayModeL();
+		break;
+	case EVideoCmdMaxReduction:
+		MaxReductionL();
+		break;
+	case EVideoCmdBackgroundColor:
+		BackgroundColorL();
+		break;
+	case EVideoCmdPlay:
+		if (iState == ELoading)
+			iEikonEnv->InfoMsg(_L("Busy..."));
+		else
+			PlayClipL();
+		break;
+	case EVideoCmdPause:
+		Pause();
+		break;
+	case EVideoCmdRefresh:
+		LoadFileL();
+		break;
+	case EVideoCmdExtractFrame:
+		ExtractFrameL();
+		break;
+	case EVideoCmdFrameInfo:
+		FrameInfoL(); 
+		break;
+	case EVideoCmdRotateClockwise:
+		FrameRotateL(ETrue);
+		LoadFileL();
+		break;
+	case EVideoCmdRotateAntiClockwise:
+		FrameRotateL(EFalse);
+		LoadFileL();
+		break;
+	case EVideoCmdFlipVertical:
+		FrameFlipL(ETrue);
+		LoadFileL();
+		break;
+	case EVideoCmdFlipHorizontal:
+		FrameFlipL(EFalse);
+		LoadFileL();
+		break;
+	case EVideoCmdAutoRotate:
+		AutoRotateL();
+		LoadFileL();
+		break;
+	case EEikCmdExit:
+		Exit();
+		break;
+	default:
+		iEikonEnv->InfoMsg(R_VIDEO_UNKNOWN);
+		break;
+		}
+	}
+
+TBool CImgDisplAppUi::ProcessCommandParametersL(TApaCommand aCommand,TFileName& aDocumentName,const TDesC8& aTail)
+	{
+	switch (aCommand)
+		{
+	case EApaCommandOpen:
+		iLoadFileName = aDocumentName;
+		break;
+	case EApaCommandCreate:
+	case EApaCommandRun:
+		break;
+	case EApaCommandBackground:
+	default:
+		break;
+		}
+
+	return CEikAppUi::ProcessCommandParametersL(aCommand,aDocumentName,aTail);
+	}
+
+void CImgDisplAppUi::OpenFileL(TFileType aFileType)
+	{
+	if (iLoadFileName.Length() < KShortestPossiblePath)
+		{
+		iLoadFileName = KDefPath;
+		}
+
+	Cancel();
+
+	CEikDialog* dialog = new(ELeave) CEikFileOpenDialog(&iLoadFileName, 0);
+	if (!dialog->ExecuteLD(R_EIK_DIALOG_FILE_OPEN))
+		{
+		return;
+		}
+
+	iLastFileType = aFileType;
+	iOpeningFolder = EFalse;
+	LoadFileL();
+	}
+
+void CImgDisplAppUi::OpenFolderL()
+	{
+	Cancel();
+
+	if (iLoadFileName.Length() < KShortestPossiblePath)
+		iLoadFileName = KDefPath;
+
+	TFileName folderName = iLoadFileName;
+
+	CEikDialog* dialog = new(ELeave) CEikFileOpenDialog(&folderName, R_VIDEO_SELECT_FOLDER);
+	if (!dialog->ExecuteLD(R_EIK_DIALOG_FILE_OPEN))
+		return;
+
+	iLastFileType = EFileTypeUnknown;
+	iOpeningFolder = ETrue;
+	LoadFolderL(folderName);
+	}
+
+void CImgDisplAppUi::LoadFileL()
+	{
+	if (iLoadFileName.Length() < KShortestPossiblePath)
+		{
+		return;
+		}
+
+	Cancel();
+
+	TInt error=KErrNone;
+	if (iImageDisplay==NULL)
+		{
+		TRAP(error,iImageDisplay = CImageDisplay::NewL(*this, iCoeEnv->FsSession()));
+		}
+	else
+		{
+		iImageDisplay->Reset();
+		}
+	iFrameNumber = 0;
+	if (error!=KErrNone)
+		{
+		iEikonEnv->HandleError(error);
+		iAppView->Reset(EDrawNow); // ensure we redraw whole screen - replace previous cross if required
+		return;
+		}
+
+	HandleNewlyOpenedImageL();
+
+	StartFrameOpen(EPlaying);
+	}
+
+void CImgDisplAppUi::LoadFolderL(const TDesC& aDirName)
+	{
+	delete iDir; iDir = NULL;
+
+	TParsePtrC parse(aDirName);
+	iDirName = parse.DriveAndPath();
+
+	iEikonEnv->FsSession().GetDir(iDirName, 0, 0, iDir);
+
+	if (iDir->Count()==0)
+		{
+		iEikonEnv->InfoMsg(R_VIDEO_EMPTY_FOLDER);
+		return;
+		}
+
+	iDirIndex = 0; 
+	OpenNextFolderEntry();
+	}
+
+void CImgDisplAppUi::OpenNextFolderEntry()
+	{
+	if (iDirIndex >= iDir->Count())
+		{
+		// end of processing - so stop
+		iEikonEnv->BusyMsgCancel();
+		Cancel(); 
+		iState = EIdle;
+		return;
+		}
+
+	const TEntry& entry = (*iDir)[iDirIndex];
+	iLoadFileName.Copy(iDirName);
+	iLoadFileName.Append(entry.iName);
+
+	TRAPD(error, LoadFileL());
+
+	if (error==KErrNone)
+		iEikonEnv->InfoMsg(entry.iName);
+	else
+		{
+		TBuf<64> errorMsg;
+		errorMsg.Format(_L("%S - error %d"), &entry.iName, error);
+		iEikonEnv->InfoMsg(errorMsg);
+		LoadFolderWait();
+		}
+	}
+
+void CImgDisplAppUi::DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane)
+	{
+	if(aResourceId==R_VIDEO_CLIP_MENU)
+		{
+		if (iImageDisplay==NULL || iState!=EPlaying)
+			{
+			aMenuPane->SetItemDimmed(EVideoCmdPlay, (iImageDisplay==NULL) );
+			aMenuPane->SetItemDimmed(EVideoCmdPause, (iImageDisplay==NULL || iState!=EPlaying) );
+			aMenuPane->SetItemDimmed(EVideoCmdRefresh, (iImageDisplay==NULL) );
+			aMenuPane->SetItemDimmed(EVideoCmdFrameInfo,(iImageDisplay==NULL ));
+			}
+		if (iPauseAfterEachFrame)
+			{
+			aMenuPane->SetItemButtonState(EVideoCmdPauseAfterEachFrame, EEikMenuItemSymbolOn);
+			}
+		if (iDumpFrames)
+			{
+			aMenuPane->SetItemButtonState(EVideoCmdToggleFrameDump, EEikMenuItemSymbolOn);
+			}
+		}
+	else if (aResourceId==R_VIDEO_VIEW_MENU)
+		{
+		
+		switch (iRotationAngle)
+			{
+			case  CBitmapRotator::ERotation90DegreesClockwise:
+				aMenuPane->SetItemButtonState(EVideoCmdRotateClockwise,EEikMenuItemSymbolOn);
+				break;
+			case  CBitmapRotator::ERotation270DegreesClockwise:
+				aMenuPane->SetItemButtonState(EVideoCmdRotateAntiClockwise,EEikMenuItemSymbolOn);
+				break;
+			case  CBitmapRotator::EMirrorHorizontalAxis:
+				aMenuPane->SetItemButtonState(EVideoCmdFlipVertical,EEikMenuItemSymbolOn);
+				break;
+			case  CBitmapRotator::EMirrorVerticalAxis:
+				aMenuPane->SetItemButtonState(EVideoCmdFlipHorizontal,EEikMenuItemSymbolOn);
+				break;
+			case KAutoRotate:
+				aMenuPane->SetItemButtonState(EVideoCmdAutoRotate,EEikMenuItemSymbolOn);
+				break;
+			}
+		if (iUseThumbnail)
+			{
+			aMenuPane->SetItemButtonState(EVideoCmdDecodeThumbnail, EEikMenuItemSymbolOn);
+			}
+			
+		if (iImageDisplay==NULL || iState!=EPlaying)
+			{
+			
+			}
+		}
+	else if (aResourceId==R_OPTIONS_MENU)
+		{
+		}
+	}
+
+TBool CImgDisplAppUi::CheckHotKeyNotDimmedL(TInt aCommandId)
+	{
+	TInt result = ETrue;
+	switch (aCommandId)
+		{
+		case EVideoCmdRefresh:
+			result = (iImageDisplay!=NULL);
+			break;
+		case EVideoCmdPause:
+			result = (iImageDisplay!=NULL && iState==EPlaying);
+			break;
+		case EVideoCmdPlay:
+			result = (iImageDisplay!=NULL && iState!=EPlaying);
+			break;
+		case EVideoCmdFrameInfo:
+			result = (iImageDisplay!=NULL);
+			break;
+		}
+
+	return result;
+	}
+
+void CImgDisplAppUi::LoadFolderWait()
+	{
+	ASSERT(!iWalker->IsActive()); // if we get here, should not be doing anything
+	
+	iTimer.After(iWalker->ActiveStatus(), KDefaultFolderDelay);
+	iState = EFolderWait;
+	}
+
+TUint CImgDisplAppUi::ImageOptions() const
+	{
+	TUint options=0;
+	switch (iRotationAngle)
+		{
+		case  CBitmapRotator::ERotation90DegreesClockwise:
+			options |= CImageDisplay::EOptionRotateCw90;
+		break;
+		case  CBitmapRotator::ERotation180DegreesClockwise:
+			options |= CImageDisplay::EOptionRotateCw180;
+			break;
+		case  CBitmapRotator::ERotation270DegreesClockwise:
+			options |= CImageDisplay::EOptionRotateCw270;
+			break;
+		case  CBitmapRotator::EMirrorHorizontalAxis:
+			options |= CImageDisplay::EOptionMirrorHorizontal;
+			break;
+		case  CBitmapRotator::EMirrorVerticalAxis:
+			options |= CImageDisplay::EOptionMirrorVertical;
+			break;
+		case  KAutoRotate:
+			options |= CImageDisplay::EOptionAutoRotate;
+			break;
+		}
+	if (iUseThumbnail)
+		{
+		options |= CImageDisplay::EOptionThumbnail;
+		}
+	else
+		{
+		options |= CImageDisplay::EOptionMainImage;
+		}
+	return options;
+	}
+
+void CImgDisplAppUi::HandleNewlyOpenedImageL()
+	{
+	ASSERT(iImageDisplay); // should have already been opened
+
+	iImageDisplay->Reset();
+	iImageDisplay->SetImageSource(iDrmContentId.Length()==0? 
+									TMMFileSource(iLoadFileName):
+									TMMFileSource(iLoadFileName, iDrmContentId, iDrmIntent)
+								);
+	iImageDisplay->SetOptions(ImageOptions());
+	iImageDisplay->SetDisplayMode( iAppView->DisplayMode() );
+	if (iClippingSet)
+		{
+		iImageDisplay->SetSourceRect(iClipRect);
+		}
+	//
+	iImageDisplay->SetupL();
+	ASSERT( iImageDisplay->RecommendedImageSizes().Count() >0 ); // the mustn't be empty
+	TSize original(iImageDisplay->RecommendedImageSizes()[0]);
+	if (iZoomFactor>0)
+		{
+		iOverallSize.SetSize(original.iWidth<<iZoomFactor, original.iHeight<<iZoomFactor);
+		}
+	else
+		{
+		const TInt zoom=-iZoomFactor;
+		if (iImageDisplay->RecommendedImageSizes().Count() > zoom)
+			{
+			iOverallSize = iImageDisplay->RecommendedImageSizes()[zoom];
+			}
+		else
+			{
+			iOverallSize.SetSize(original.iWidth>>zoom, original.iHeight>>zoom);
+			}
+		}
+	
+	MGenIclImageDisplayExtension* iFace;
+	if (KErrNone == iImageDisplay->ExtensionInterface(KUidGenIclImageDisplayPluginExtUid, reinterpret_cast<TAny*&>(iFace)))
+		{
+		TInt err=iFace->SetScaleQuality(iScalingQuality);
+		ASSERT(err==KErrNone);
+		err=iFace->SetMaximumReductionFactor(iMaxReduction);
+		ASSERT(err==KErrNone);
+		iFace->Release();
+		}
+	iImageDisplay->SetSizeInPixels(iOverallSize);
+	iFrameNumber	= 0;
+	iViewResized	= EFalse;
+
+	iTime.HomeTime();
+	}
+
+void CImgDisplAppUi::MakeName(const TDesC& aDir, TBool aIsMask, TDes& aFileName) const
+	{
+	TParse parse;
+	parse.SetNoWild(iLoadFileName, NULL, NULL);
+	aFileName.Copy(aDir);
+	aFileName.Append(parse.Name());
+	if (aIsMask)
+		{
+		_LIT(KMask,"_mask_");
+		aFileName.Append(KMask);
+		}
+	else
+		{
+		_LIT(KFrame,"_frame_");
+		aFileName.Append(KFrame);
+		}
+	aFileName.AppendNum(iFrameNumber);
+	_LIT(KExt, ".mbm");
+	aFileName.Append(KExt);
+	}
+
+void CImgDisplAppUi::MiidoImageReady(const CFbsBitmap* /*aBitmap*/, TUint aStatus, const TRect& /*aUpdatedArea*/, TInt aError)
+	{
+	iLatestError	= aError;
+	iLatestStatus	= aStatus;
+	if (aError!=KErrNone)
+		{
+		TBuf<64> err;
+		err.Format(_L("Play error: %d"),aError);
+		User::InfoPrint(err);
+		iState = EIdle;
+		return;
+		}
+	if (aStatus&CImageDisplayPlugin::EStatusFrameReady)
+		{
+		++iFrameNumber;
+		iImageDisplay->GetBitmap(iFrame, iMask);
+		if (iDumpFrames)
+			{
+			_LIT(KDumpDir, "c:\\temp\\");
+			iEikonEnv->FsSession().MkDirAll(KDumpDir);
+			TFileName nm;
+			MakeName(KDumpDir, EFalse, nm);
+			const_cast<CFbsBitmap*>(iFrame)->Save(nm);
+			if (iMask && !iDisableMask)
+				{
+				MakeName(KDumpDir, ETrue, nm);
+				const_cast<CFbsBitmap*>(iMask)->Save(nm);
+				}
+			}
+		const TSize frameSize(iFrame->SizeInPixels());
+		if (!iViewResized )
+			{
+			TRAPD(error, iAppView->ResizeL(frameSize) );
+			iViewResized = ETrue;
+			TBuf<64> err;
+			err.Format(_L("Resize error: %d"),error);
+			if (error != KErrNone)
+				{
+				User::InfoPrint(err);
+				}
+			iAppView->Center(ENoDrawNow);
+			}
+
+		DrawConvertedFrame();
+		}
+	else
+		{
+		TBuf<64> err;
+		err.Format(_L("Strange status: %x"),aStatus);
+		User::InfoPrint(err);
+		iState = EIdle;
+		return;
+		}
+	if ((aStatus&CImageDisplayPlugin::EStatusNoMoreToDecode)==0)
+		{
+		if (iPauseAfterEachFrame)
+			{
+			User::InfoPrint(_L("Paused"));
+			iState = EPlayPaused;
+			}
+		else
+			{
+			iImageDisplay->Play();
+			}
+		}
+	else
+		{
+		User::InfoPrint(_L("Completed"));
+		iState = EIdle;
+		}
+	}
+
+void CImgDisplAppUi::ExtractFrameL()
+	{
+#if 0
+	if (iLoadFileName.Length() < KShortestPossiblePath)
+		return;
+
+	ASSERT(iImageDisplay);
+
+	Cancel();
+
+	TInt frameCount = iImageDisplay->FrameCount();
+
+	if (iFrameNumber >= frameCount)
+		iFrameNumber = 0;
+
+	CEikDialog* dialog = new(ELeave) CVideoCurrentFrameDialog(iFrameNumber,frameCount);
+	if (!dialog->ExecuteLD(R_VIDEO_FRAME_DIALOG))
+		return;
+
+	StartFrameOpen(ELoading);
+#endif
+	}
+
+void CImgDisplAppUi::StartFrameOpen(TState aNextState)
+	{
+	iImageDisplay->Play();
+	iState = aNextState; // what ever happens we go to next state, and will handle any error there
+	}
+
+void CImgDisplAppUi::PlayClipL()
+	{
+	if (iState != EPlayPaused)
+		{
+		iFrameNumber = 0;
+		}
+	iTime.HomeTime();
+
+	StartFrameOpen(EPlaying);
+	}
+
+void CImgDisplAppUi::Pause()
+	{
+	if (iImageDisplay && iState == EPlaying)
+		{
+		iImageDisplay->Pause();
+		iState = EPlayPaused;
+		}
+	}
+
+void CImgDisplAppUi::SaveAsL()
+	{
+	if (iSaveFileName.Length() < KShortestPossiblePath)
+		iSaveFileName = KDefPath;
+
+	Cancel();
+
+	CEikDialog* dialog = new(ELeave) CVideoSaveAsDialog(&iSaveFileName,iSaveInfo);
+	if (!dialog->ExecuteLD(R_VIDEO_FILE_SAVEAS_DIALOG))
+		return;
+	iEikonEnv->FsSession().Delete(iSaveFileName);
+
+	delete iFrameImageData; iFrameImageData = NULL;
+
+	const TUid imageType = iSaveInfo.iImageTypeUid;
+	TImageDataBlock *imageData = NULL;
+	TFrameDataBlock *frameData = NULL;
+
+	if(imageType == KImageTypeBMPUid)
+		{
+		imageData = new (ELeave) TBmpImageData;
+		TBmpImageData* data = STATIC_CAST(TBmpImageData*, imageData);
+		switch (iSaveInfo.iBpp)
+			{
+		case 0:		data->iBitsPerPixel = 1; break;
+		case 2:		data->iBitsPerPixel = 4; break;
+		case 3:		data->iBitsPerPixel = 8; break;
+		case 6:		data->iBitsPerPixel = 24; break;
+		default:	ASSERT(EFalse);			break;
+			}
+		}
+	else if(imageType == KImageTypeGIFUid)
+		{// gif does not have encoding options
+		}
+	else if(imageType == KImageTypeJPGUid)
+		{
+		imageData = new (ELeave) TJpegImageData;
+		TJpegImageData* data = STATIC_CAST(TJpegImageData*, imageData);
+		if (!iSaveInfo.iColor)
+			data->iSampleScheme = TJpegImageData::EMonochrome;
+		else
+			data->iSampleScheme = TJpegImageData::TColorSampling(3 - iSaveInfo.iSampling);
+		data->iQualityFactor = iSaveInfo.iQualityFactor;
+		}
+	else if(imageType == KImageTypeMBMUid)
+		{
+		frameData = new (ELeave) TMbmEncodeData;
+		TMbmEncodeData* data = STATIC_CAST(TMbmEncodeData*, frameData);
+		switch (iSaveInfo.iBpp)
+			{
+		case 0:		data->iDisplayMode = EGray2;		break;
+		case 1:		data->iDisplayMode = EGray4;		break;
+		case 2:		data->iDisplayMode = iSaveInfo.iColor ? EColor16 : EGray16;	break;
+		case 3:		data->iDisplayMode = iSaveInfo.iColor ? EColor256 : EGray256;	break;
+		case 4:		data->iDisplayMode = EColor4K;		break;
+		case 5:		data->iDisplayMode = EColor64K;	break;
+		case 6:		data->iDisplayMode = EColor16M;	break;
+		case 7:		data->iDisplayMode = EColor16MU;	break;
+		default:	ASSERT(EFalse);	break;
+			}
+		}
+	else if(imageType == KImageTypePNGUid)
+		{
+		frameData = new (ELeave) TPngEncodeData;
+		TPngEncodeData* data = STATIC_CAST(TPngEncodeData*, frameData);
+		// bpp
+		switch (iSaveInfo.iBpp)
+			{
+			case 0:		data->iBitsPerPixel = 1; break;		// 1 bpp 
+			case 1:		data->iBitsPerPixel = 2; break;		// 2 bpp
+			case 2:		data->iBitsPerPixel = 4; break;		// 4 bpp
+			case 3:		data->iBitsPerPixel = 8; break;		// 8 bpp
+			case 6:		data->iBitsPerPixel = 24; break;	// 24 bpp
+			default:	ASSERT(EFalse);	break;				// unsupported bit depth
+			}
+		// colour or grayscale?
+		data->iColor = iSaveInfo.iColor;
+		// compression level
+		switch (iSaveInfo.iCompression)
+			{
+			case 0:
+				data->iLevel = TPngEncodeData::EDefaultCompression;
+				break;
+			case 1:
+				data->iLevel = TPngEncodeData::ENoCompression;
+				break;
+			case 2:
+				data->iLevel = TPngEncodeData::EBestSpeed;
+				break;
+			case 3:
+				data->iLevel = TPngEncodeData::EBestCompression;
+				break;
+			default:			// unsupported compression
+				ASSERT(EFalse);
+				break;		
+			}
+		}
+	else
+		{
+		//custom encoder
+		}
+
+	if (frameData)
+		CleanupStack::PushL(frameData);
+
+	if (imageData)
+		CleanupStack::PushL(imageData);
+
+	delete iSaveUtil; iSaveUtil = NULL;
+	iSaveUtil = CImageEncoder::FileNewL(iCoeEnv->FsSession(), iSaveFileName, CImageEncoder::EOptionNone, imageType);
+
+	ASSERT(iFrameImageData==NULL); // deleted above
+	if (imageData)
+		{
+		iFrameImageData = CFrameImageData::NewL();
+
+		User::LeaveIfError(iFrameImageData->AppendImageData(imageData));
+		CleanupStack::Pop(); // imageData - ownership now passed to iFrameImageData
+		}
+
+	if (frameData)
+		{
+		if (iFrameImageData == NULL)
+			iFrameImageData = CFrameImageData::NewL();
+
+		User::LeaveIfError(iFrameImageData->AppendFrameData(frameData));
+		CleanupStack::Pop(); // frameData - ownership now passed to iFrameImageData
+		}
+
+	StartFrameSave();
+	}
+
+void CImgDisplAppUi::DisplayModeL()
+	{
+	TDisplayMode displayMode = iAppView->DisplayMode();
+	CEikDialog* dialog = new(ELeave) CDisplayModeDialog(displayMode);
+	if (dialog->ExecuteLD(R_VIDEO_DISPLAY_MODE_DIALOG))
+		{
+		iAppView->SetDisplayModeL(displayMode);
+		LoadFileL(); // redraw
+		}
+	}
+
+void CImgDisplAppUi::ScalingQualityL()
+	{
+	CEikDialog* dialog = new(ELeave) CScalingQualityDialog(iScalingQuality);
+	if (dialog->ExecuteLD(R_SCALING_QUALITY_DIALOG))
+		{
+		LoadFileL(); // redraw
+		}
+	}
+
+void CImgDisplAppUi::DrmParamsL()
+	{
+	CEikDialog* dialog = new(ELeave) CDrmContentIdDialog(iDrmContentId);
+	dialog->ExecuteLD(R_DRM_CONTENT_PARAMS_DIALOG);
+	}
+
+void CImgDisplAppUi::MaxReductionL()
+	{
+	CEikDialog* dialog = new(ELeave) CMaxReductionDialog(iMaxReduction);
+	dialog->ExecuteLD(R_IMAGE_MAX_REDUCTION_FACTOR);
+	}
+
+void CImgDisplAppUi::ClipRectParamsL()
+	{
+	CEikDialog* dialog = new(ELeave) CClipRectParamsDialog(iClippingSet, iClipRect);
+	dialog->ExecuteLD(R_IMAGE_CLIP_RECT_DIALOG);
+	}
+
+void CImgDisplAppUi::BackgroundColorL()
+	{
+	TInt backgroundColor = iBackgroundColor;
+	TBool override = iOverrideBackgroundColor;
+	CEikDialog* dialog = new(ELeave) CVideoBackgroundColorDialog(backgroundColor, override);
+	if (dialog->ExecuteLD(R_VIDEO_BACKGROUND_COLOR_DIALOG))
+		{
+		iBackgroundColor = backgroundColor;
+		iOverrideBackgroundColor = override;
+		LoadFileL(); // redraw
+		}
+	}
+
+void CImgDisplAppUi::FrameInfoL()
+	{
+	HBufC* info=HBufC::NewLC(KInfoBufferSize);
+	TPtr commentTPtr(info->Des());
+
+	_LIT(KImgStatus, "Img status value=0x%x (");
+	TUint status=iImageDisplay->ImageStatus();
+	commentTPtr.AppendFormat(KImgStatus, status);
+	if (status&CImageDisplay::EImageSingleFrame)
+		{
+		commentTPtr.Append(_L("EImageSingleFrame "));
+		}
+	if (status&CImageDisplay::EImageMultiFrame)
+		{
+		commentTPtr.Append(_L("EImageMultiFrame "));
+		}
+	if (status&CImageDisplay::EImageAnimated)
+		{
+		commentTPtr.Append(_L("EImageAnimated "));
+		}
+	if (status&CImageDisplay::EImageMasked)
+		{
+		commentTPtr.Append(_L("EImageMasked "));
+		}
+	if (status&CImageDisplay::EImageHasThumbnail)
+		{
+		commentTPtr.Append(_L("EImageHasThumbnail "));
+		}
+	if (status&CImageDisplay::EImageTypeUnknown)
+		{
+		commentTPtr.Append(_L("EImageTypeUnknown "));
+		}
+	commentTPtr.Append(_L(")\n"));
+
+	TInt numFrames;
+	TInt err=iImageDisplay->NumFrames(numFrames);
+	_LIT(KImgNumFrames, "Num Frames=%d (err=%d)\n");
+	commentTPtr.AppendFormat(KImgNumFrames,numFrames,err);
+	commentTPtr.Append(_L("---------\n"));
+	commentTPtr.AppendFormat(_L("Frame number %d\n"),iFrameNumber);
+	if (iFrame)
+		{
+		commentTPtr.AppendFormat(_L("Frame size %d x %d\n"),iFrame->SizeInPixels().iWidth,iFrame->SizeInPixels().iHeight);
+		}
+	commentTPtr.AppendFormat(_L("Latest status 0x%x\n"),iLatestStatus);
+	commentTPtr.AppendFormat(_L("Latest error %d\n"),iLatestError);
+	if (iState == EPlaying)
+		{
+		if (iImageDisplay->ValidBitmap())
+			{
+			commentTPtr.Append(_L("Bitmap status: Valid\n"));
+			}
+		else
+			{
+			commentTPtr.Append(_L("Bitmap status: NOT Valid\n"));
+			}
+		}
+	
+	ReplaceNewlinesWithLineBreaks(commentTPtr);
+	TBool needPlay= (iState == EPlaying);
+	Pause();	
+
+	CEikDialog* dialog = new(ELeave) CFrameInfoDialog(commentTPtr);
+	TRAP(err, dialog->ExecuteLD(R_VIDEO_INFO_DIALOG) );
+	CleanupStack::PopAndDestroy(); //info
+	if (needPlay)
+		{
+		PlayClipL();
+		}
+	}
+
+void CImgDisplAppUi::FrameRotateL(TBool aClockwise)
+	{
+	TInt newAngle= aClockwise ?
+			CBitmapRotator::ERotation90DegreesClockwise :
+			CBitmapRotator::ERotation270DegreesClockwise;
+	if (iRotationAngle  == newAngle )
+		{
+		iRotationAngle = KNoRotation;
+		}
+	else
+		{
+		iRotationAngle  = newAngle;
+		}
+
+	iViewResized = EFalse;
+	}
+
+void CImgDisplAppUi::FrameFlipL(TBool aVertical)
+	{
+	TInt newAngle=aVertical ?
+						CBitmapRotator::EMirrorHorizontalAxis :
+						CBitmapRotator::EMirrorVerticalAxis;
+
+	if (iRotationAngle  == newAngle )
+		{
+		iRotationAngle = KNoRotation;
+		}
+	else
+		{
+		iRotationAngle  = newAngle;
+		}
+	iViewResized = EFalse;
+	}
+void CImgDisplAppUi::AutoRotateL()
+	{
+	if (iRotationAngle  == KAutoRotate )
+		{
+		iRotationAngle  = KNoRotation;
+		}
+	else
+		{
+		iRotationAngle  = KAutoRotate;
+		}
+	iViewResized = EFalse;
+	}
+
+void CImgDisplAppUi::StartFrameSave()
+	{
+	ASSERT(iSaveUtil); // should be true by now
+	ASSERT(iState==EIdle); 
+	ASSERT(!iWalker->IsActive()); // we are going to use it
+#if 0
+	iSaveUtil->Convert(&(iWalker->ActiveStatus()),iFrame,iFrameImageData); 
+#endif
+	iState = ESaving;
+	}
+
+void CImgDisplAppUi::DrawConvertedFrame()
+	{
+	if (iOverrideBackgroundColor)
+		{
+		iAppView->SetBackgroundColor(TRgb(iBackgroundColor), ENoDrawNow);
+		}
+	TBool fullRedrawReq=ETrue;
+	if (iMask==NULL || iDisableMask)
+		iAppView->DrawImage(iFrame, iOffset, fullRedrawReq?ENoDrawNow:EDrawNow);
+	else
+		iAppView->DrawImage(iFrame, iMask, iOffset, fullRedrawReq?ENoDrawNow:EDrawNow);
+
+	if (fullRedrawReq)
+		{
+		iAppView->DrawNow();
+		}
+	}
+
+void CImgDisplAppUi::HandleConvertCompleteL()
+	{
+	DrawConvertedFrame();
+
+	iPrevFrameNumber = iFrameNumber;
+
+	if (iState==EPlaying)
+		{
+		ASSERT(!iWalker->IsActive()); // we will use it again
+
+		if (iState==EPlaying)
+			{
+			iState = EPlayingWait;
+			}
+			
+		else 
+			{
+			ASSERT(EFalse);
+			}
+		}
+	else if (iOpeningFolder)
+		{
+		LoadFolderWait();
+		}
+	else
+		{
+		iEikonEnv->BusyMsgCancel();
+		Cancel(); // cancel any background streaming
+		iState = EIdle;
+		}
+	}
+
+void CImgDisplAppUi::RunL(CVideoWalker* aWalker, TInt aStatus)
+	{
+	ASSERT(aWalker==iWalker); // ones we know about
+
+#if defined(_DEBUG) && defined(__ENABLE_DEBUG_OUTPUT)
+	RDebug::Print(_L("RunL(%x,%d,%d)(%x,%x)"), aWalker, aStatus, iState, iWalker, iStreamGen);
+#endif 
+
+	switch (iState)
+		{
+	case EIdle:
+		ASSERT(EFalse); // should not happen
+		break;
+	case ELoading:
+	case EPlaying:
+		{
+		ASSERT(aWalker==iWalker);
+		TInt error = aStatus;
+		if (error==KErrNone)
+			TRAP(error, HandleConvertCompleteL());
+		if (error!=KErrNone)
+			HandleRunError(aWalker, error);
+		}
+		break;
+	case EPlayingWait:
+		{
+		ASSERT(iWalker==aWalker);
+		iTime.HomeTime(); // whatever reset the time here
+		if (aStatus!=KErrNone)
+			{
+			HandleRunError(aWalker, aStatus);
+			}
+		else if (iOpeningFolder)
+			{
+			LoadFolderWait();
+			}
+		else
+			{
+			ASSERT(!iWalker->IsActive()); // should have stopped naturally
+			iEikonEnv->BusyMsgCancel();
+			iState = EIdle;
+			}
+		}
+		break;
+	case ESaving:
+		{
+		ASSERT(iWalker==aWalker);
+		iEikonEnv->BusyMsgCancel();
+		iState = EIdle;
+		if (aStatus!=KErrNone)
+			HandleRunError(aWalker, aStatus);
+		}
+		break;
+	case EFolderWait:
+		iDirIndex++;
+		OpenNextFolderEntry();
+		break;
+	default:
+		ASSERT(EFalse); // unknown state
+		}
+	}
+
+void CImgDisplAppUi::DoCancel(CVideoWalker *aWalker)
+	{
+	ASSERT(aWalker==iWalker); // only ones we know about
+
+#if defined(_DEBUG) && defined(__ENABLE_DEBUG_OUTPUT)
+	RDebug::Print(_L("DoCancel(%x,%d)(%x,%x)"), aWalker, iState, iWalker, iStreamGen); 
+#endif 
+
+	if (aWalker==iWalker)
+		{
+		switch (iState)
+			{
+		case ELoading:
+		case EPlaying:
+			iImageDisplay->StopPlay();
+			break;
+		case ESaving:
+			iSaveUtil->Cancel();
+			break;
+		case EPlayingWait: // ignore scenario where we self complete - will not get here
+		case EFolderWait:
+			iTimer.Cancel();
+			break;
+		default:
+			ASSERT(EFalse); // unknown state or should not happen
+			}
+		}
+	else
+		{
+		ASSERT(EFalse); // unknown state or should not happen
+		}
+	}
+
+void CImgDisplAppUi::HandleRunError(CVideoWalker* /*aWalker*/, TInt aError)
+	{
+	Cancel();
+	iEikonEnv->BusyMsgCancel();
+	iEikonEnv->HandleError(aError);
+	ASSERT(iState == EIdle);
+	}
+
+void CImgDisplAppUi::ReplaceNewlinesWithLineBreaks(TDes& aText)
+	{
+	TInt pos=0;
+
+	for (;;)
+		{
+		if (pos >= aText.Length()) // will occur if last character in comment is new line
+			break;
+		const TPtrC restOfText(aText.Mid(pos));
+		TInt posOfNextNewLine = restOfText.Locate(TChar('\n'));
+		if (posOfNextNewLine<0) // no more new lines in text
+			break;
+		posOfNextNewLine += pos; // position relative to whole descriptor
+		aText[posOfNextNewLine] = CEditableText::ELineBreak;
+		pos = posOfNextNewLine + 1; // next cycle, start at next character
+		}
+	}
+
+
+//
+// CVideoWalker implementation
+//
+
+CVideoWalker* CVideoWalker::NewL(CImgDisplAppUi* aAppUi)
+	{
+	CVideoWalker* result = new (ELeave) CVideoWalker(aAppUi);
+	return result;
+	}
+
+CVideoWalker::CVideoWalker(CImgDisplAppUi* aAppUi):
+	CActive(CActive::EPriorityStandard),
+	iAppUi(aAppUi)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CVideoWalker::~CVideoWalker()
+	{
+	Cancel();
+	}
+
+// used when we need to pass status variable - simultaneously calls SetActive
+TRequestStatus& CVideoWalker::ActiveStatus()
+	{
+	SetActive();
+	return iStatus;
+	}
+
+// for completion ASAP on this
+void CVideoWalker::SelfComplete(TInt aError)
+	{
+	TRequestStatus* status = &ActiveStatus();
+	User::RequestComplete(status, aError);
+	}
+
+// calls AppUi->RunL() which is expected to handle the call
+void CVideoWalker::RunL()
+	{
+	iAppUi->RunL(this, iStatus.Int());
+	}
+
+// calls AppUi->DoCancel() which is expected to handle the call
+void CVideoWalker::DoCancel()
+	{
+	iAppUi->DoCancel(this);
+	}
+
+//
+// CImgDisplDocument
+//
+
+CImgDisplDocument::CImgDisplDocument(CEikApplication& aApp)
+		: CEikDocument(aApp)
+	{
+	}
+
+CEikAppUi* CImgDisplDocument::CreateAppUiL()
+	{
+    return new(ELeave) CImgDisplAppUi;
+	}
+
+//
+// CImgDisplApp
+//
+
+TUid CImgDisplApp::AppDllUid() const
+	{
+	return KUidTVideo;
+	}
+
+CApaDocument* CImgDisplApp::CreateDocumentL()
+	{
+	return new(ELeave) CImgDisplDocument(*this);
+	}
+
+#include <eikstart.h>
+
+
+CApaApplication* NewApplication()
+   {
+   return new CImgDisplApp;
+   }
+
+TInt E32Main()
+   {
+   return EikStart::RunApplication(NewApplication);
+   }
+
+