videditor/SimpleVideoEditor/src/SimpleVideoEditorImpl.cpp
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "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:
* Ixonos Plc
*
* Description: 
*
*/


// INCLUDES
#include "SimpleVideoEditorImpl.h"
#include <SimpleVideoEditor.rsg>
#include <e32std.h>
#include <aknutils.h>
#include <bautils.h>
#include <data_caging_path_literals.hrh>
#include <mgfetch.h> 
#include <sysutil.h>
#include <stringloader.h>
#include <aknnotewrappers.h> 
#include <eikenv.h>
#include <errorui.h>
#include <PathInfo.h>
#include <eikprogi.h>
#include <stringloader.h>
#include <VedAudioClipInfo.h>
#include <CAknMemorySelectionDialog.h> 
#include <CAknFileNamePromptDialog.h> 
#include <AknCommonDialogsDynMem.h>
#include <CAknMemorySelectionDialogMultiDrive.h>
#include <apgcli.h>

#include "VideoEditorUtils.h"
#include "VeiAddQueue.h"
#include "VideoEditorCommon.h"
#include "VideoEditorDebugUtils.h"
#include "VeiTempMaker.h"
#include "ExtProgressDialog.h"
#include "VeiMGFetchVerifier.h"
#include "VeiImageClipGenerator.h"
#include "DummyControl.h"
#include "CMultiLineQueryDialog.h"

// CONSTANTS
_LIT(KResourceFile, "SimpleVideoEditor.rsc");
const TProcessPriority KLowPriority = EPriorityLow;
const TInt KAudioLevelMin = -127;
const TUint KFadeInTimeMicroSeconds = 50000;

#define KMediaGalleryUID3           0x101F8599 

//=======================================================================================================
CSimpleVideoEditorImpl* CSimpleVideoEditorImpl::NewL(MSimpleVideoEditorExitObserver& aExitObserver)
	{
	CSimpleVideoEditorImpl* self = new (ELeave)	CSimpleVideoEditorImpl(aExitObserver);
	CleanupStack::PushL (self);
	self->ConstructL();
	CleanupStack::Pop (self);
	return self;
	}
	
//=======================================================================================================
CSimpleVideoEditorImpl::~CSimpleVideoEditorImpl()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::~CSimpleVideoEditorImpl, In");

	// Remove foreground event observer
	iEnv.RemoveForegroundObserver( *this );

	Cancel();
	iResLoader.Close();

	if ( iMovie )
		{
		iMovie->Reset();	
		iMovie->UnregisterMovieObserver( this );				
		delete iMovie;
		iMovie = NULL;
		}		

	if ( iTempFile )
		{
		(void) iEnv.FsSession().Delete( *iTempFile );
		delete iTempFile;
		iTempFile = NULL;
		}

    if ( iProgressDialog )
		{
		iProgressDialog->SetCallback( NULL );		
		delete iProgressDialog;
		iProgressDialog = NULL;
		}
		
	if ( iWaitDialog )
		{
		iWaitDialog->SetCallback(NULL);
		delete iWaitDialog;
		iWaitDialog = NULL;
		}
	if ( iAnimatedProgressDialog )
		{			
		delete iAnimatedProgressDialog;	
		}
		
	if (iImageClipGenerator)
		{
		delete iImageClipGenerator;
		}
		
	if (iTextGenerator)
		{
		delete iTextGenerator;	
		}
		
	if (iAddText)
		{
		delete iAddText;	
		}
	
	if ( iErrorUI )
		{
		delete iErrorUI;
		}
    
    if ( iAudioClipInfo )
        {
        delete iAudioClipInfo;
        }

	if ( iAcceptedAudioTypes )
		{
		delete iAcceptedAudioTypes;
		iAcceptedAudioTypes = 0;
		}

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::~CSimpleVideoEditorImpl, Out");
    }

//=======================================================================================================
void CSimpleVideoEditorImpl::RestoreOrientation()
	{
	CAknAppUiBase* appUi = static_cast<CAknAppUiBase *>( iEnv.EikAppUi() );
	CAknAppUiBase::TAppUiOrientation orientation = appUi->Orientation();

	if (orientation != iOriginalOrientation)
		{
		TRAP_IGNORE( appUi->SetOrientationL(iOriginalOrientation) );

		// Send screen device change event to validate screen
		TWsEvent event;

		RWsSession& rws = iEnv.WsSession();
		event.SetType( EEventScreenDeviceChanged );
		event.SetTimeNow(); 
		event.SetHandle( rws.WsHandle() ); 

		(void)rws.SendEventToAllWindowGroups( event );
		}
	}

//=======================================================================================================
CSimpleVideoEditorImpl::CSimpleVideoEditorImpl(MSimpleVideoEditorExitObserver& aExitObserver) 
: 	CActive (EPriorityStandard), 
	iEnv( *CEikonEnv::Static() ), 
	iExitObserver (aExitObserver), 
	iResLoader( iEnv ),
	iGeneratorComplete( ETrue ),
	iDialogDismissed( EFalse )
	{
	CActiveScheduler::Add(this);   
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::ConstructL()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ConstructL: In");

	// Locate and open the resource file
    TFileName fileName;
    TParse p;    

    Dll::FileName(fileName);
    p.Set(KResourceFile, &KDC_RESOURCE_FILES_DIR, &fileName);
    fileName = p.FullName();
    
    LOGFMT(KVideoEditorLogFile, "\tLoading resource file: %S", &fileName);
	iResLoader.OpenL( fileName ); // RConeResourceLoader selects the correct language file

	// Always use automatic save quality for the result movie
	iMovie = CVedMovie::NewL( NULL );	
	iMovie->RegisterMovieObserverL( this );
	iMovie->SetQuality( CVedMovie::EQualityAutomatic );

	CVeiTempMaker* maker = CVeiTempMaker::NewLC();
	// this call can leave even though it does not end with 'L'
	maker->EmptyTempFolder();
	CleanupStack::PopAndDestroy(maker);
	//delete maker;
		
	iEnv.AddForegroundObserverL( *this );
	
		
	iErrorUI = CErrorUI::NewL( iEnv );

	iAcceptedAudioTypes = new ( ELeave ) CDesCArrayFlat( 4 );

	iAcceptedAudioTypes->Reset();

	iAcceptedAudioTypes->AppendL( _L( "audio/mpeg" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/aac" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/amr" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/mp3" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/x-mp3" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/3gpp" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/3gpp2" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/m4a" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/mp4" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/mpeg4" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/wav" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/x-wav" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/x-realaudio" ) );
	iAcceptedAudioTypes->AppendL( _L( "audio/wma" ) );
		
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ConstructL: Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::StartMerge( const TDesC& aSourceFileName )
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartMerge: In");

	iSourceFileName = aSourceFileName;
	iOperationMode = EOperationModeMerge;
	iState = EStateInitializing;

	CompleteRequest();

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartMerge: Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::StartChangeAudio( const TDesC& aSourceFileName )
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartChangeAudio: In");

	iSourceFileName = aSourceFileName;
	iOperationMode = EOperationModeChangeAudio;
	iState = EStateInitializing;

	CompleteRequest();

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartChangeAudio: Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::StartAddText( const TDesC& aSourceFileName )
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartAddText: In");

	iSourceFileName = aSourceFileName;
	iOperationMode = EOperationModeAddText;
	iState = EStateInitializing;

	CompleteRequest();

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartAddText: Out");
	}


//=============================================================================
void CSimpleVideoEditorImpl::RunL()
	{	
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunL: In");

	// Resetting these indicators. This is not necessary right now,
	// but might be in the future if the code is changed so it's reasonable to
	// to do it anyway, just in case.
	iGeneratorComplete = ETrue;
	iDialogDismissed = EFalse;
	
	// if RunL() leaves, RunError() is called and iState is changed to EStateFinalizing
	// (or to EStateReady if already in EStateFinalizing
	
	switch (iState)
		{
		case EStateInitializing:
			{
			InitializeOperationL();

			iState = EStateInsertInputFirst;
			CompleteRequest();
			break;
			}
		case EStateInsertInputFirst:
			{
			// Common to all operation modes: Insert the original video clip to the movie
			// (Operation continues from the NotifyVideoClipAdded() callback method).
			iMovie->InsertVideoClipL( iSourceFileName, 0 );
			StartWaitDialogL();

			break;
			}
		case EStateInsertInputSecond:
			{
			// Get the input - text, image, video or sound clip
			switch (iOperationMode)
				{
				case EOperationModeMerge:
					{											
					GetMergeInputFileL();						
					CompleteRequest();	
					break;
					}
								
				case EOperationModeChangeAudio:
					{
					GetAudioFileL();
					CompleteRequest();
					break;
					}
				
				case EOperationModeAddText:
					{
					GetTextL();
					CompleteRequest();
					break;
					}
					
				default:
					User::Invariant();
					break;
				}			
				break;
			}				
	    case EStateCheckAudioLength:
	        {
	        // NotifyAudioClipInfoReady is called instead of RunL
	        break;    
	        }
		case EStateInsertVideo:
			{																				
			iMovie->InsertVideoClipL(iMergeFileName, iVideoOrImageIndex); 
			StartWaitDialogL();
			break;
			}
		case EStateCreateImageGenerator:	
			{																						
			TTimeIntervalMicroSeconds duration( 3000000 );
		    TRgb background = KRgbBlack;
		    // Setting to false to indicate that the
		    // NewL() called below hasn't yet completed.
		    iGeneratorComplete = EFalse;

			// Create the image clip generator
		    iImageClipGenerator = CVeiImageClipGenerator::NewL( 
    			iMergeFileName, 
    			iMovie->Resolution(),
    			duration, 
    			background, 
    			KVideoClipGenetatorDisplayMode, 
    			iEnv.FsSession(), 
    			*this );
    		StartWaitDialogL();	    						    			
			break;
			}
		case EStateInsertImage:
			{		
			TRAPD(err, iMovie->InsertVideoClipL( *iImageClipGenerator, ETrue, iVideoOrImageIndex )); // generator owned by movie 
			if (KErrNone == err)
				{				
				// Generator is no longer our concern, ownership transferred to iMovie							
				iImageClipGenerator = 0;				
				StartWaitDialogL();
				}
			else
				{					
				iError = err;
				iError = FilterError();
				iState = EStateFinalizing;
				CompleteRequest();
				}
			break;			
			}	
		
		case EStateInsertAudio:
			{
			LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunL: Inserting audio clip %S", &iAudioFileName);

			iMovie->AddAudioClipL( iAudioFileName, TTimeIntervalMicroSeconds( 0 ));    
			StartWaitDialogL();
			break;
			}
					
		case EStateInsertTextToBegin:
			{	
			LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunL: 1");
			
			
			iTextGenerator = CVeiTitleClipGenerator::NewL( iMovie->Resolution(),
																			   EVeiTitleClipTransitionNone, 
																			   EVeiTitleClipHorizontalAlignmentCenter,
																			   EVeiTitleClipVerticalAlignmentCenter);
			
			HBufC* descriptiveName = StringLoader::LoadLC(R_VESM_EDIT_VIEW_TITLE_NAME, &iEnv );
			iTextGenerator->SetDescriptiveNameL(*descriptiveName);
			CleanupStack::PopAndDestroy(descriptiveName);			
			iTextGenerator->SetTextL(*iAddText);
			
			iTextGenerator->SetTransitionAndAlignmentsL(EVeiTitleClipTransitionNone, 
														EVeiTitleClipHorizontalAlignmentCenter, 
														EVeiTitleClipVerticalAlignmentCenter);
			LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunL: 2");			
			TRAPD(err, iMovie->InsertVideoClipL( *iTextGenerator, ETrue, 0));	
												
			if (KErrNone == err)
				{				
				// Generator is no longer our concern, ownership transferred to iMovie							
				iTextGenerator = 0;				
				LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunL: 3");		
				StartWaitDialogL();
				}
			else
				{				
				iError = err;
				iError = FilterError();
				iState = EStateFinalizing;
				CompleteRequest();
				}		
			break;
			}
		
		case EStateInsertTextToEnd:
			{
			LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunL: 4");									
			
			iTextGenerator = CVeiTitleClipGenerator::NewL( iMovie->Resolution(),
																		   EVeiTitleClipTransitionScrollBottomToTop, 
																		   EVeiTitleClipHorizontalAlignmentCenter,
																		   EVeiTitleClipVerticalAlignmentCenter);
			
			HBufC* descriptiveName = StringLoader::LoadLC(R_VESM_EDIT_VIEW_TITLE_NAME, &iEnv );
			iTextGenerator->SetDescriptiveNameL(*descriptiveName);
			CleanupStack::PopAndDestroy(descriptiveName);			
			iTextGenerator->SetTextL(*iAddText);
			
			iTextGenerator->SetTransitionAndAlignmentsL(EVeiTitleClipTransitionScrollBottomToTop,
													EVeiTitleClipHorizontalAlignmentCenter, 
													EVeiTitleClipVerticalAlignmentCenter);
			LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunL: 5");
			
			TRAPD(err, iMovie->InsertVideoClipL( *iTextGenerator, ETrue, 1));
				
			if (KErrNone == err)
				{				
				// Generator is no longer our concern, ownership transferred to iMovie							
				iTextGenerator = 0;				
				LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunL: 6");
				StartWaitDialogL();
				}
			else
				{	
				iError = err;
				iError = FilterError();
				iState = EStateFinalizing;
				CompleteRequest();
				}
			break;	
			}	

		case EStateProcessing:
			{			
			StartMovieProcessingL(iSourceFileName);
			break;
			}
		
		case EStateProcessingOk:
			{			
			ProcessingOkL();
			CompleteRequest();
			break;
			}
				
		case EStateProcessingFailed:
			{			
			ProcessingFailed();
			CompleteRequest();					
			break;
			}
			
		case EStateFinalizing:
			{			
			// Show possible error dialog etc.
			// in TRAP because endless call loop may otherwise be resulted in case of leave in HandleErrorL
			// @ : should FilterError() be called only from here?
			HandleError();
			iState = EStateReady;	
			CompleteRequest();
			break;
			}
			
		case EStateReady:
			{				
			// Notify completion to observer
			iExitObserver.HandleSimpleVideoEditorExit( iError, iOutputFileName );
			break;
			}

		default:
			{
			User::Invariant();
			break;
			}
		}

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunL: Out");
	}

//=============================================================================
void CSimpleVideoEditorImpl::DoCancel()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::DoCancel: In");
	CancelMovieProcessing();
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::DoCancel: Out");
	}
//=============================================================================	
	
void CSimpleVideoEditorImpl::CancelMovieProcessing()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::CancelMovieProcessing: In");

	if (iMovie)
		{
		iMovie->CancelProcessing();
		}	

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::CancelMovieProcessing: Out");
	}	
//=============================================================================

TInt CSimpleVideoEditorImpl::RunError( TInt aError )
	{
	LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::RunError: %d", aError);
	//@ :  think how to solve this
	
	// Show possible error dialog etc.
	iError = aError;
	// @: if leave and error happens so that Notify callbacks are not called
	iError = FilterError();
	
	// if leave happens in HandleError, iState must be changed to prevent same leave happening eternally 
	if (EStateReady == iState)
		{
		iExitObserver.HandleSimpleVideoEditorExit( iError, iOutputFileName );
		}
	else
		{			
		iState = EStateReady;	
		HandleError();
		iExitObserver.HandleSimpleVideoEditorExit( iError, iOutputFileName );
		// If CompleteRequest() is called here, system crashes because ~CSimpleVideoEditorImpl() gets
		// called from iExitObserver.HandleSimpleVideoEditorExitL(), stray signal resulted
		//CompleteRequest();
		}							

	return KErrNone;	
	}
//=======================================================================================================

void CSimpleVideoEditorImpl::InitializeOperationL()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::InitializeOperationL: In");

	iOutputFileName.Zero();

	if( !AknLayoutUtils::PenEnabled() && EOperationModeAddText == iOperationMode )
		{
		// Text input is always inserted in portrait mode.
		// Store the original screen orientation.
		CAknAppUiBase* appUi = static_cast<CAknAppUiBase *>( iEnv.EikAppUi() );
		iOriginalOrientation = appUi->Orientation();
		appUi->SetOrientationL(CAknAppUiBase::EAppUiOrientationPortrait);
		}

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::InitializeOperationL: Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::GetMergeInputFileL()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetMergeInputFileL: In");

	iVideoOrImageIndex = 0; 

	CDesCArrayFlat* selectedFiles = new ( ELeave ) CDesCArrayFlat( 1 );
	CleanupStack::PushL(selectedFiles);

	CDesCArrayFlat* mimetypesVideo = new ( ELeave ) CDesCArrayFlat( 1 );
	CleanupStack::PushL(mimetypesVideo);
	mimetypesVideo->AppendL(_L("video/*"));

	CDesCArrayFlat* mimetypesImage = new ( ELeave ) CDesCArrayFlat( 1 );
	CleanupStack::PushL(mimetypesImage);
	mimetypesImage->AppendL(_L("image/*"));
	
	TInt videoOrImage = -1;
	TBool chosen = EFalse;

	// Select the input type: video clip or image
	if ( ShowListQueryL(videoOrImage, R_VEI_QUERY_HEADING_MERGE_WITH, R_VED_VIDEO_OR_IMAGE_QUERY) )
		{
		CVeiMGFetchVerifier* mgFetchVerifier = CVeiMGFetchVerifier::NewLC();
		if (0 == videoOrImage) // video chosen
			{
			if ( MGFetch::RunL( *selectedFiles, EVideoFile, EFalse, KNullDesC(), KNullDesC(), mimetypesVideo, mgFetchVerifier))
				{
				chosen = ETrue;
				}
			}
		else if (1 == videoOrImage) // image chosen
			{
		    if ( MGFetch::RunL( *selectedFiles, EImageFile, EFalse, KNullDesC(), KNullDesC(), mimetypesImage, mgFetchVerifier))
				{
				chosen = ETrue;
				}
			}
		CleanupStack::PopAndDestroy( mgFetchVerifier );

		if (chosen)
			{
			iMergeFileName = selectedFiles->MdcaPoint(0);
			TInt headingResourceId = R_VIE_QUERY_HEADING_ADD_VIDEO_TO; 
			if (0 == videoOrImage) // video chosen
				{
				iOperationMode = EOperationModeMergeWithVideo;
				iState = EStateInsertVideo;				
				headingResourceId = R_VIE_QUERY_HEADING_ADD_VIDEO_TO; 
				LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetMergeInputFileL: 4");								
				} 
			else if (1 == videoOrImage) // image chosen
				{
				iOperationMode = EOperationModeMergeWithImage;
				iState = EStateCreateImageGenerator;			    			    
				headingResourceId = R_VIE_QUERY_HEADING_ADD_IMAGE_TO; 
				LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetMergeInputFileL: 5");				
				}

			TInt begOrEnd = -1;
			if ( ShowListQueryL(begOrEnd, headingResourceId, R_VED_INSERT_POSITION_QUERY) )
				{			
				LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetMergeInputFileL: 6");
																
				if (0 == begOrEnd) // video or image to the beginning
					{			
					iVideoOrImageIndex = 0;				
					}
				else // video or image to end 
					{				
					iVideoOrImageIndex = 1;				
					}		    
				}
			else
				{
				iState = EStateFinalizing;	
				}	
			} // if (chosen)
		else
			{
			iState = EStateFinalizing;	
			}
		} // if ( ShowListQueryL for image or video
	else
		{
		iState = EStateFinalizing;	
		}
	
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetMergeInputFileL: 7");
	CleanupStack::PopAndDestroy(mimetypesImage);
	CleanupStack::PopAndDestroy(mimetypesVideo);
	CleanupStack::PopAndDestroy(selectedFiles);
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetMergeInputFileL: Out");	
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::GetAudioFileL()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetAudioFileL: In");

	TFileName outputFile;

	CDesCArrayFlat* selectedFiles = new ( ELeave ) CDesCArrayFlat( 1 );
	CleanupStack::PushL(selectedFiles);
	CVeiMGFetchVerifier* mgFetchVerifier = CVeiMGFetchVerifier::NewLC();

	if ( MGFetch::RunL( *selectedFiles, EAudioFile, EFalse, KNullDesC, KNullDesC , iAcceptedAudioTypes, mgFetchVerifier ) )
		{
        iAudioFileName = selectedFiles->MdcaPoint(0);
        iAudioClipInfo = CVedAudioClipInfo::NewL( iAudioFileName, *this );
        iState = EStateCheckAudioLength;
		}
	else
		{
		iState = EStateFinalizing;	
		}
				
	CleanupStack::PopAndDestroy( mgFetchVerifier );
	CleanupStack::PopAndDestroy(selectedFiles);			

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetAudioFileL: Out");
	}
	
//=======================================================================================================
void CSimpleVideoEditorImpl::GetTextL()
	{	
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetTextL: In");

	// Ask for text. 
	iAddText = HBufC::NewL(AKNTEXT_QUERY_WIDTH * AKNTEXT_QUERY_LINES); // think what these limit values should be?	
	TPtr textPtr = iAddText->Des();
	CMultiLineQueryDialog* textQuery = CMultiLineQueryDialog::NewL(textPtr);	
	textQuery->SetMaxLength(AKNTEXT_QUERY_WIDTH * AKNTEXT_QUERY_LINES);	
	//textQuery->SetPredictiveTextInputPermitted(ETrue);

	if (textQuery->ExecuteLD(R_VESM_EDITVIDEO_TITLESCREEN_TEXT_QUERY))
		{					
		// Restore the original screen orientation immediately after the text input ends
		RestoreOrientation();
		
		TInt begOrEnd = -1;		
		
		if ( ShowListQueryL(begOrEnd, R_VEI_QUERY_HEADING_ADD_TEXT_TO, R_VED_INSERT_POSITION_QUERY) )
			{			
			LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetTextL: 1");
															
			if (0 == begOrEnd) // text to begin
				{			
				iState = EStateInsertTextToBegin;				
				}
			else // text to end in credits style (rolling down the screen)
				{				
				iState = EStateInsertTextToEnd;				
				}		    		    
			}
		else
			{
			iState = EStateFinalizing;	
			}
		}
	else
		{
		// Restore the original screen orientation immediately after the text input ends
		RestoreOrientation();
		iState = EStateFinalizing;
		}
	
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::GetTextL: Out");
	}

//=======================================================================================================
TInt CSimpleVideoEditorImpl::ShowListQueryL (TInt& aPosition, 
											 TInt aHeadingResourceId,
											 TInt aQueryResourceId) const
    {
    CAknListQueryDialog* dlg = new( ELeave ) CAknListQueryDialog( &aPosition );
    dlg->PrepareLC( aQueryResourceId );
    
    CAknPopupHeadingPane* heading = dlg->QueryHeading();
    HBufC* noteText = StringLoader::LoadLC( aHeadingResourceId, &iEnv );
    heading->SetTextL( noteText->Des() );
    CleanupStack::PopAndDestroy( noteText );

    return dlg->RunLD();        
    }

//=======================================================================================================
void CSimpleVideoEditorImpl::StartMovieProcessingL(const TDesC& aSourceFile)
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartMovieProcessingL: In");

	RFs&	fs = iEnv.FsSession();

	if (QueryAndSaveL(aSourceFile)) 
	{	
		// Generate temp file.
		// Take the drive from the target file name.
		CAknMemorySelectionDialog::TMemory memory( CAknMemorySelectionDialog::EMemoryCard );
		if( 0 != iOutputFileName.Left(1).CompareF( PathInfo::MemoryCardRootPath().Left(1) ) )
			{
			memory = CAknMemorySelectionDialog::EPhoneMemory;
			}

		iTempFile = HBufC::NewL(KMaxFileName);
		CVeiTempMaker* maker = CVeiTempMaker::NewL();
		maker->GenerateTempFileName( *iTempFile, memory, iMovie->Format() );
		delete maker;

		// Start rendering video to the temporary file.
		LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartMovieProcessingL: 1, calling iMovie->ProcessL(%S)", iTempFile);
		iMovie->ProcessL(*iTempFile, *this);
	}
	else
	{
		LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartMovieProcessingL: User cancelled saving");
		iState = EStateProcessingFailed;
		CompleteRequest();
	}
	
	// Next: wait for MVedMovieProcessingObserver callback
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartMovieProcessingL: Out");
	}

//=============================================================================
TInt CSimpleVideoEditorImpl::QueryAndSaveL(const TDesC& aSourceFileName)
{

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::QueryAndSaveL: in");

	TBool ret = EFalse;
	
	RFs	fs = CCoeEnv::Static()->FsSession();

	// launch query with choices "Replace original" and "Save with a new file name" 
	TInt userSelection = LaunchSaveVideoQueryL(); 
	
  	if(userSelection == 0) 
  	// the user selects to save with a new file name
		{
		CAknMemorySelectionDialog::TMemory selectedMemory(CAknMemorySelectionDialog::EPhoneMemory);		

        // Multiple drive support
#ifdef RD_MULTIPLE_DRIVE
		
		TDriveNumber driveNumber;
        TFileName driveAndPath;
        CAknMemorySelectionDialogMultiDrive* multiDriveDlg = CAknMemorySelectionDialogMultiDrive::NewL(ECFDDialogTypeSave, EFalse );			
		CleanupStack::PushL(multiDriveDlg);
		
		// launch "Select memory" query
        if (multiDriveDlg->ExecuteL( driveNumber, &driveAndPath, NULL ))
			{
			iOutputFileName.Zero();				
			
			// Generate a default name for the new file
			TInt err = VideoEditorUtils::GenerateFileNameL (
                                    					fs,
                                    					aSourceFileName,		
                                    					iOutputFileName,
                                    					iMovie->Format(),
                                    					iMovie->GetSizeEstimateL(),
                                    					driveAndPath);	
				
            driveAndPath.Append( PathInfo::VideosPath() );					
				
			if ( KErrNone == err )
				{				
				// launch file name prompt dialog
				if (CAknFileNamePromptDialog::RunDlgLD(iOutputFileName, driveAndPath, KNullDesC))
					{
					driveAndPath.Append(iOutputFileName);
					iOutputFileName = driveAndPath;
		            ret = ETrue;
		            }
				}
			else // err != KErrNone 
				{
				iErrorUI->ShowGlobalErrorNoteL( err );
				ret = EFalse;
				}											
			}
		CleanupStack::PopAndDestroy( multiDriveDlg );

#else // no multiple drive support
			
		// launch "Select memory" query
		if (CAknMemorySelectionDialog::RunDlgLD(selectedMemory))
			{
			// create path for the image	
			TFileName driveAndPath;        		
			VideoEditor::TMemory memorySelection = VideoEditor::EMemPhoneMemory;		 
			if (selectedMemory == CAknMemorySelectionDialog::EPhoneMemory)
				{
				memorySelection = VideoEditor::EMemPhoneMemory;
				driveAndPath.Copy( PathInfo::PhoneMemoryRootPath() );
				driveAndPath.Append( PathInfo::VideosPath() );							
				}
			else if (selectedMemory == CAknMemorySelectionDialog::EMemoryCard)
				{	
				memorySelection = VideoEditor::EMemMemoryCard;				
				driveAndPath.Copy( PathInfo::MemoryCardRootPath() );
				driveAndPath.Append( PathInfo::VideosPath() );							
				}        				 


			// GenerateNewDocumentNameL also checks disk space
			iOutputFileName.Zero();
			TInt err = VideoEditorUtils::GenerateNewDocumentNameL (
				fs,
				aSourceFileName,		
				iOutputFileName,
				iMovie->Format(),
				iMovie->GetSizeEstimateL(),
				memorySelection);	
				
			if ( KErrNone == err )
				{				
				// launch file name prompt dialog
				if (CAknFileNamePromptDialog::RunDlgLD(iOutputFileName, driveAndPath, KNullDesC))
					{
					driveAndPath.Append(iOutputFileName);
					iOutputFileName = driveAndPath;
		            ret = ETrue;
		            }
				}
			else // err != KErrNone 
				{
				ret = EFalse;
				}						
			}
#endif
		}
	// user selects to overwrite
	else if (userSelection == 1)
	
		{
		iOutputFileName = aSourceFileName;
		return ETrue;	
		}
	else // user cancelled
		{
		ret = EFalse;
		}

	LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::QueryAndSaveL: out: %d", ret);

	return ret;
}



//=============================================================================
TInt CSimpleVideoEditorImpl::LaunchListQueryDialogL (
	MDesCArray *	aTextItems,
	const TDesC &	aPrompt
	) 
{

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::LaunchListQueryDialogL: in");
	//	Selected text item index
	TInt index (-1);

	//	Create a new list dialog
    CAknListQueryDialog * dlg = new (ELeave) CAknListQueryDialog (&index);

	//	Prepare list query dialog
	dlg->PrepareLC (R_VIE_LIST_QUERY);

	//	Set heading
	dlg->QueryHeading()->SetTextL (aPrompt);

	//	Set text item array
	dlg->SetItemTextArray (aTextItems);	

	//	Set item ownership
	dlg->SetOwnershipType (ELbmDoesNotOwnItemArray);

	//	Execute
	if (dlg->RunLD())
	{
		LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::LaunchListQueryDialogL: out: return %d", index);	
		return index;
	}
	else
	{
		LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::LaunchListQueryDialogL: out: return -1");		
		return -1;
	}
}

//=============================================================================
TInt CSimpleVideoEditorImpl::LaunchSaveVideoQueryL () 
{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::LaunchSaveVideoQueryL: in");
	//	Create dialog heading and options
    HBufC * heading = CEikonEnv::Static()->AllocReadResourceLC (R_VIE_QUERY_HEADING_SAVE);
    HBufC * option1 = CEikonEnv::Static()->AllocReadResourceLC (R_VIE_QUERY_SAVE_NEW);       
    HBufC * option2 = CEikonEnv::Static()->AllocReadResourceLC (R_VIE_QUERY_SAVE_REPLACE); 
                
	//	Query dialog texts
	CDesCArray * options = new (ELeave) CDesCArraySeg (2);
	CleanupStack::PushL (options);
	options->AppendL( option1->Des() );
	options->AppendL( option2->Des() );

	//	Execute query dialog
	TInt ret = LaunchListQueryDialogL (options, *heading);

	options->Reset();
	
	CleanupStack::PopAndDestroy( options ); 
	CleanupStack::PopAndDestroy( option2 ); 
	CleanupStack::PopAndDestroy( option1 ); 		
	CleanupStack::PopAndDestroy( heading ); 
	
	LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::LaunchListQueryDialogL: out: return %d", ret);			
	return ret;
}



//=======================================================================================================
void CSimpleVideoEditorImpl::HandleLosingForeground()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleLosingForeground(): In");

	// Set the priority to low. This is needed to handle the situations 
	// where the engine is performing heavy processing while the application 
	// is in background.
	RProcess myProcess;
	iOriginalProcessPriority = myProcess.Priority();
	LOGFMT3(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleLosingForeground: changing priority of process %Ld from %d to %d", myProcess.Id().Id(), iOriginalProcessPriority, KLowPriority);
	myProcess.SetPriority( KLowPriority );
	iProcessPriorityAltered = ETrue;

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleLosingForeground(): Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::HandleGainingForeground()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleGainingForeground(): In");

	// Return to normal priority.
	RProcess myProcess;
	TProcessPriority priority = myProcess.Priority();
	if ( priority < iOriginalProcessPriority )
		{
		myProcess.SetPriority( iOriginalProcessPriority );
		}
	iProcessPriorityAltered = EFalse;

	LOGFMT2(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleGainingForeground: Out: process %Ld back to normal priority %d", myProcess.Id().Id(), priority);
	}

//=======================================================================================================
TInt CSimpleVideoEditorImpl::FilterError(/*const TInt& aErrEngine, const TInt& aErrUi*/) const
	{
	// here standard leave codes are converted to our own codes having correspondent localized error messages						
	if (KErrNone != iError && KErrCancel != iError)
		{		
		if (EStateInsertInputFirst == iState )
			{
			return KErrUnableToEditVideo;
			}
		else if (EStateInsertVideo == iState)
		    {
		    if (KErrNotSupported == iError)	
				{
				return KErrVideoFormatNotSupported;	
				}
			else return KErrUnableToInsertVideo;
		    }
		else if (EStateInsertImage == iState || EStateCreateImageGenerator == iState)
			{
			if (KErrNotSupported == iError)	
				{
				return KErrImageFormatNotSupported;	
				}		
			else return KErrUnableToInsertImage;
			}		
		else if (EStateInsertAudio == iState || EStateCheckAudioLength == iState )
			{
			if (KErrNotSupported == iError)	
				{
				return KErrAudioFormatNotSupported;	
				}
			else 
				{
				return KErrUnableToInsertSound;
				}
			}
		else if (EStateInsertTextToBegin == iState || EStateInsertTextToEnd == iState)
			{		
			return KErrUnableToInsertText;	
			}			
		else if (EOperationModeMergeWithVideo == iOperationMode)
			{
			return KErrUnableToMergeVideos;
			} 
		else if (EOperationModeMergeWithImage == iOperationMode)
			{
			return KErrUnableToMergeVideoAndImage;
			} 
		else if (EOperationModeChangeAudio == iOperationMode)
			{
			return KErrUnableToChangeSound;
			}
		else if (EOperationModeAddText == iOperationMode)
			{
			if (iError == KErrNoMemory) return KErrNoMemory;
			return KErrUnableToInsertText;
			} 
		}
	
	return iError;					
	}


//=============================================================================
void CSimpleVideoEditorImpl::CompleteRequest()
	{
	if ( IsActive() )
		{
		Cancel();
		}
	TRequestStatus * p = &iStatus;
	SetActive();
	User::RequestComplete (p, KErrNone);
	}

//=============================================================================
void CSimpleVideoEditorImpl::HandleError()
	{		
	LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleErrorL: In, iError:%d", iError);

	if (KErrNone != iError && KErrCancel != iError)
		{
						
		if (iTempFile)
			{			
			TInt delErr = iEnv.FsSession().Delete( *iTempFile );
			LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleErrorL: 1, delErr:%d", delErr);
			delete iTempFile;
			iTempFile = NULL;
			}
		
		switch (iError)
			{
		    case KErrInUse:
	            {
	            ShowErrorNote(R_VEI_IN_USE);
                break;	            
	            }
		    case KErrUnableToEditVideo:
	            {
	            ShowErrorNote(R_VEI_UNABLE_TO_EDIT);
                break;	            
	            }
			case KErrUnableToInsertVideo:
				{
				ShowErrorNote(R_VEI_UNABLE_TO_INSERT_VIDEO);
				break;
				}
			case KErrUnableToInsertSound:
				{
				ShowErrorNote(R_VEI_UNABLE_TO_INSERT_SOUND);
				break;
				}
			case KErrUnableToInsertImage:
				{
				ShowErrorNote(R_VEI_UNABLE_TO_INSERT_IMAGE);
				break;
				}
			case KErrUnableToInsertText:
				{
				ShowErrorNote(R_VEI_UNABLE_TO_INSERT_TEXT);
				break;
				}
			case KErrUnableToMergeVideos:
				{
				ShowErrorNote(R_VEI_UNABLE_TO_MERGE_VIDEOS);
				break;
				}		
			case KErrUnableToMergeVideoAndImage:
				{
				ShowErrorNote(R_VEI_UNABLE_TO_MERGE_VIDEO_IMAGE);
				break;
				}
			case KErrUnableToChangeSound:
				{
				ShowErrorNote(R_VEI_UNABLE_TO_CHANGE_SOUND);
				break;
				}
			case KErrVideoFormatNotSupported:
				{
				ShowErrorNote(R_VEI_UNABLE_TO_INSERT_VIDEO);
				break;
				}
			case KErrAudioFormatNotSupported:
				{
				ShowErrorNote(R_VEI_AUDIO_FORMAT_NOT_SUPPORTED);
				break;
				}
			case KErrImageFormatNotSupported:
				{
				ShowErrorNote(R_VEI_IMAGE_FORMAT_NOT_SUPPORTED);
				break;
				}					
			case KErrNoMemory:
				{
				ShowErrorNote(R_VEI_NOT_ENOUGH_MEMORY);
				break;
				}	
			default:
				{			
				LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleErrorL: 4");
				ShowErrorNote(R_VEI_ERROR_NOTE);
				LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleErrorL: 5");
				break;
				}
			}
		}

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::HandleErrorL: Out");
	}

//=============================================================================
void CSimpleVideoEditorImpl::ShowErrorNote( const TInt aResourceId ) const
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ShowErrorNoteL: In");

	TRAP_IGNORE(
		HBufC* stringholder = StringLoader::LoadLC( aResourceId, &iEnv );								
		CAknErrorNote* dlg = new ( ELeave ) CAknErrorNote( ETrue );
		dlg->ExecuteLD( *stringholder );
		CleanupStack::PopAndDestroy( stringholder ); 
		);

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ShowErrorNoteL: out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::StartWaitDialogL()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartWaitDialogL: In");
	if (iWaitDialog)
		{
		LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartWaitDialogL: 2");
		delete iWaitDialog;
		iWaitDialog = NULL;	
		}
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartWaitDialogL: 3");

	iWaitDialog = new ( ELeave ) CAknWaitDialog( 
		reinterpret_cast<CEikDialog**>(&iWaitDialog), ETrue ); // !!!
	iWaitDialog->PrepareLC(R_VEI_WAIT_NOTE_WITH_CANCEL);
	iWaitDialog->SetCallback( this );

	HBufC* stringholder = StringLoader::LoadLC( R_VEI_NOTE_PROCESSING, &iEnv );
	iWaitDialog->SetTextL( *stringholder );	
	CleanupStack::PopAndDestroy(stringholder);

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartWaitDialogL: 4");
	iWaitDialog->RunLD();
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartWaitDialogL: Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::StartProgressDialogL()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartProgressDialogL: In");	
	
	if (iProgressDialog)
		{		
		LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartProgressDialogL: 1");
		delete iProgressDialog;
		iProgressDialog = NULL;
		}
	
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartProgressDialogL: 2");	
	
	iProgressDialog = new (ELeave) CAknProgressDialog( 
		reinterpret_cast<CEikDialog**>(&iProgressDialog), ETrue );
	iProgressDialog->PrepareLC(R_VESM_PROGRESS_NOTE_WITH_CANCEL);	
	iProgressDialog->SetCallback( this );

	TInt resId = -1;
	HBufC* stringholder = NULL;
	switch (iOperationMode)
		{
		case EOperationModeMergeWithVideo:
		case EOperationModeMergeWithImage:
		    TApaAppCaption caption;
		    TRAPD( err, ResolveCaptionNameL( caption ) );
		    
		    // If something goes wrong, show basic "Saving" note
		    if ( err )
		        {
		        stringholder = iEnv.AllocReadResourceLC( R_VEI_NOTE_PROCESSING );
		        }
		    else
		        {
		        stringholder =  StringLoader::LoadLC( R_VEI_NOTE_MERGING, caption, &iEnv );
		        }        
			break;
		case EOperationModeChangeAudio:
			resId = R_VEI_NOTE_ADDING_AUDIO;
			stringholder = StringLoader::LoadLC( resId, &iEnv );
			break;
		case EOperationModeAddText:
			resId = R_VEI_NOTE_ADDING_TEXT;
			stringholder = StringLoader::LoadLC( resId, &iEnv );
			break;
		default :
			resId = R_VEI_NOTE_PROCESSING;
			stringholder = StringLoader::LoadLC( resId, &iEnv );
			break;
		}

	iProgressDialog->SetTextL( *stringholder );
	CleanupStack::PopAndDestroy(stringholder);

	iProgressDialog->GetProgressInfoL()->SetFinalValue( 100 );
	iProgressDialog->RunLD();
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::StartProgressDialogL: Out");	
	}

//=============================================================================
void CSimpleVideoEditorImpl::ResolveCaptionNameL( TApaAppCaption& aCaption ) const
    {   
    RApaLsSession appArcSession;
    CleanupClosePushL( appArcSession );
    User::LeaveIfError( appArcSession.Connect() );       	    

    // Get Media Gallery caption
    TApaAppInfo appInfo;
    User::LeaveIfError( appArcSession.GetAppInfo( appInfo, TUid::Uid( KMediaGalleryUID3 ) ) );

    aCaption = appInfo.iCaption;

    CleanupStack::PopAndDestroy( &appArcSession );  
    }

//=======================================================================================================	
void CSimpleVideoEditorImpl::StartAnimatedProgressDialogL ()
	{
    delete iAnimatedProgressDialog;
    iAnimatedProgressDialog = NULL;
	iAnimatedProgressDialog = new (ELeave) CExtProgressDialog( &iAnimatedProgressDialog );
	
	iAnimatedProgressDialog->PrepareLC(R_WAIT_DIALOG);	
	iAnimatedProgressDialog->SetCallback( this );

	TInt labelResId = -1;
	TInt animResId = -1;
	switch (iOperationMode)
		{
		case EOperationModeMerge:
			labelResId = R_VEI_NOTE_MERGING;
			animResId = VideoEditor::EAnimationMerging;
			break;
		case EOperationModeChangeAudio:
			labelResId = R_VEI_NOTE_ADDING_AUDIO;
			animResId = VideoEditor::EAnimationChangeAudio;
			break;
		case EOperationModeAddText:
			labelResId = R_VEI_NOTE_ADDING_TEXT;
			animResId = VideoEditor::EAnimationAddText;
			break;
		default :
			labelResId = R_VEI_NOTE_PROCESSING;
			// @ : what is best default animation?
			animResId = VideoEditor::EAnimationMerging;
			break;
		}

	HBufC* stringholder = StringLoader::LoadLC( labelResId, &iEnv );
	iAnimatedProgressDialog->SetTextL( *stringholder );
	CleanupStack::PopAndDestroy(stringholder);
		
	iAnimatedProgressDialog->SetAnimationResourceIdL( animResId );

	iAnimatedProgressDialog->GetProgressInfoL()->SetFinalValue( 100 );
	iAnimatedProgressDialog->StartAnimationL();
	iAnimatedProgressDialog->RunLD();		 	    
	}


//=======================================================================================================
void CSimpleVideoEditorImpl::NotifyMovieProcessingStartedL(CVedMovie& /*aMovie*/)
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyMovieProcessingStartedL: In");

	iPercentagesProcessed = 0;

	StartProgressDialogL();
	//StartAnimatedProgressDialogL();

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyMovieProcessingStartedL: Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::NotifyMovieProcessingProgressed(CVedMovie& /*aMovie*/, TInt aPercentage)
    {
    iPercentagesProcessed = aPercentage;
   	User::ResetInactivityTime();
   	if (iAnimatedProgressDialog)
   	    {   		
		TRAP_IGNORE( iAnimatedProgressDialog->GetProgressInfoL()->SetAndDraw( aPercentage ) );
   	    }

   	if (iProgressDialog)
   	    {
		TRAP_IGNORE( iProgressDialog->GetProgressInfoL()->SetAndDraw( aPercentage ) );
   	    }
    
    if ( iCancelPercentage <= aPercentage )
        {
        iCancelPercentage = 101;
        }
    }

//=======================================================================================================
void CSimpleVideoEditorImpl::NotifyMovieProcessingCompleted(CVedMovie& /*aMovie*/, TInt aError)
    {    
    LOGFMT2(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyMovieProcessingCompleted: In, aError:%d, iPercentagesProcessed:%d", aError, iPercentagesProcessed);		

	iError = aError;	
	iError = FilterError();
    
    if (KErrNone == aError)
		{		
		LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyMovieProcessingCompleted: 1");
		iState = EStateProcessingOk;
		}
    else 
		{		
		LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyMovieProcessingCompleted: 2");
		iState = EStateProcessingFailed;
		}
    
    if (iAnimatedProgressDialog)
   		{
   		TRAP_IGNORE( iAnimatedProgressDialog->GetProgressInfoL()->SetAndDraw( 100 ) );
		delete iAnimatedProgressDialog;
		iAnimatedProgressDialog = NULL;
   		}
    if (iProgressDialog)
    	{
    	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyMovieProcessingCompleted: 3");
		TRAP_IGNORE( iProgressDialog->GetProgressInfoL()->SetAndDraw( 100 ) );
		TRAP_IGNORE( iProgressDialog->ProcessFinishedL() );
		LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyMovieProcessingCompleted: 4");
    	}

    // CompleteRequest() moved to DialogDismissed()    
    LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyMovieProcessingCompleted: Out");
    }
    
    
    
//=======================================================================================================    
void CSimpleVideoEditorImpl::NotifyAudioClipInfoReady( CVedAudioClipInfo& aInfo, TInt aError )
    {    
    
    LOGFMT( KVideoEditorLogFile, "CVeiEditVideoView::NotifyAudioClipInfoReady: in, aError:%d", aError );
        
    if ( aError == KErrNone )
        {        
        LOG( KVideoEditorLogFile, "CVeiEditVideoView::NotifyAudioClipInfoReady: 1" );

        TTimeIntervalMicroSeconds audioDuration = aInfo.Duration();
        TTimeIntervalMicroSeconds videoDuration = iMovie->Duration();
        TInt changeSound = 1;

        TRAP_IGNORE( changeSound = QueryAudioInsertionL( videoDuration, audioDuration ));
        
        if ( changeSound )
            {
            iState = EStateInsertAudio;
            }
        else 
            {
            iState = EStateFinalizing;             
            }
        CompleteRequest();
        
        LOG( KVideoEditorLogFile, "CVeiEditVideoView::NotifyAudioClipInfoReady: 2" );
        }
    else
        {
        iError = aError;
        iError = FilterError();
        iState = EStateFinalizing;
        CompleteRequest();   
        }

    LOG( KVideoEditorLogFile, "CVeiEditVideoView::NotifyAudioClipInfoReady: out" );    
    }
    
    
//=======================================================================================================
TInt CSimpleVideoEditorImpl::QueryAudioInsertionL( TTimeIntervalMicroSeconds aVideoDuration, 
                                                   TTimeIntervalMicroSeconds aAudioDuration )
    {
    TInt changeSound = 1;
    
    // round the durations to seconds so that the comparing will be more realistic
    TTimeIntervalSeconds videoDurationInSeconds = aVideoDuration.Int64()/1000000;
    TTimeIntervalSeconds audioDurationInSeconds = aAudioDuration.Int64()/1000000;
        
    if ( audioDurationInSeconds < videoDurationInSeconds )
        {
        HBufC* queryString = StringLoader::LoadLC( R_VIE_QUERY_INSERT_SHORT_AUDIO );
        CAknQueryDialog* dlg = new( ELeave )CAknQueryDialog( *queryString, CAknQueryDialog::ENoTone );
        changeSound = dlg->ExecuteLD( R_VIE_CONFIRMATION_QUERY );
        CleanupStack::PopAndDestroy( queryString );
        }
    else if ( audioDurationInSeconds > videoDurationInSeconds )
        {
        HBufC* queryString = StringLoader::LoadLC( R_VIE_QUERY_INSERT_LONG_AUDIO );
        CAknQueryDialog* dlg = new( ELeave )CAknQueryDialog( *queryString, CAknQueryDialog::ENoTone );
        changeSound = dlg->ExecuteLD( R_VIE_CONFIRMATION_QUERY );
        CleanupStack::PopAndDestroy( queryString );            
        }
    //else the audio clip is the same length as the video clip

    return changeSound;
    }
    
    
    
//=======================================================================================================

void CSimpleVideoEditorImpl::ProcessingOkL()
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ProcessingOkL: In");
	RFs& fs = iEnv.FsSession();
	CFileMan* fileman = CFileMan::NewL( fs );	
	CleanupStack::PushL( fileman );
	
	TInt moveErr( KErrNone );
	if ( iTempFile->Left(1) == iOutputFileName.Left(1) )
		{
		moveErr = fileman->Rename( *iTempFile, iOutputFileName );
		LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ProcessingOkL: 1 renamed temp file: err %d", moveErr);
		}
	else
		{
		moveErr = fileman->Move( *iTempFile, iOutputFileName );
		LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ProcessingOkL: 2 moved tem file: err %d", moveErr);
		}
	CleanupStack::PopAndDestroy( fileman );  

	delete iTempFile;
	iTempFile = NULL;		
	iError = moveErr;

	iState = EStateFinalizing;	
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ProcessingOkL: Out");
	}
//=======================================================================================================	

void CSimpleVideoEditorImpl::ProcessingFailed()
	{		
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ProcessingFailed: In");
	TInt delErr = iEnv.FsSession().Delete( *iTempFile );
	LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ProcessingFailed: 1, delErr:%d", delErr);
	if ( delErr ) 
		{
		// @: should something be done?
		}
	delete iTempFile;
	iTempFile = NULL;		
	iState = EStateFinalizing;	
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::ProcessingFailed: Out");
	}	

//=======================================================================================================
void CSimpleVideoEditorImpl::NotifyVideoClipAdded(CVedMovie& /*aMovie*/, TInt /*aIndex*/)
    {
    LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyVideoClipAdded: In");	   	

	if ( EStateInsertInputFirst == iState )
		{
		// Next insert the second item (i.e. video|image|audio|text)
		iState = EStateInsertInputSecond;
		}
	else if ( EStateInsertVideo == iState ||	EStateInsertImage == iState 
				|| EStateInsertTextToBegin == iState || EStateInsertTextToEnd == iState)
		{
		// Next start processing the movie		
		iState = EStateProcessing;
		}	
	// if cancel is pressed in the middle of iMovie->InsertVideoClip(), state is put to iStateFinalizing to stop
	// the process			
	else if ( EStateFinalizing == iState || EStateReady == iState )	
		{
		;
		}
	else
		{
		User::Invariant();
		}
		
	if ( iWaitDialog )
		{		
		TRAP_IGNORE(iWaitDialog->ProcessFinishedL());
		}	
	//CompleteRequest();

    LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyVideoClipAdded: Out");
    }

//=======================================================================================================
void CSimpleVideoEditorImpl::NotifyVideoClipAddingFailed(CVedMovie& /*aMovie*/, TInt aError)
	{
	LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyVideoClipAddingFailed: In, aError:%d", aError);
	
	iError = aError;		
	iError = FilterError();
	
	// Next handle error and exit
	iState = EStateFinalizing;

	if ( iWaitDialog )
		{
		TRAP_IGNORE(iWaitDialog->ProcessFinishedL());
		}

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyVideoClipAddingFailed: Out");
	}



//=======================================================================================================
void CSimpleVideoEditorImpl::NotifyAudioClipAdded(CVedMovie& /*aMovie*/, TInt /*aIndex*/)
	{
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyAudioClipAdded: In");

	ASSERT(iMovie && iMovie->VideoClipCount() == 1);

	if ( EStateInsertAudio == iState )
		{
		TInt audioClipCount = iMovie->AudioClipCount();
		TTimeIntervalMicroSeconds currentAudioClipEndTime = iMovie->AudioClipEndTime( audioClipCount - 1 ); // in movie timebase

		TTimeIntervalMicroSeconds videoClipEndTime = iMovie->VideoClipEndTime(0); // in movie timebase
		if( currentAudioClipEndTime > videoClipEndTime )
			{
			// Adjust the length so that the audio duration does not exceed video duration. 				
			CVedAudioClipInfo* audioClip = iMovie->AudioClipInfo( audioClipCount - 1 );
			TInt64 cutOutTime = audioClip->Duration().Int64() - ( currentAudioClipEndTime.Int64() - videoClipEndTime.Int64() );
			iMovie->AudioClipSetCutOutTime( audioClipCount - 1, TTimeIntervalMicroSeconds(cutOutTime) ); // in clip timebase
			}
		ASSERT( iMovie->Duration() == videoClipEndTime );
		
		TTimeIntervalMicroSeconds audioClipEndTime = iMovie->AudioClipEndTime( audioClipCount - 1);				

        ASSERT( audioClipEndTime.Int64() <= videoClipEndTime.Int64() );

        TInt error = KErrNone;
        
		if ( audioClipEndTime == videoClipEndTime )
		    {
		    if ( iMovie->VideoClipIsMuteable(0) )
		        {
		        iMovie->VideoClipSetMuted(0, ETrue);
		        }
		    } 
		    
        // if the audio clip is shorter than the video clip, the original sound 
        // of the video clip has to be muted until the end of the new sound clip
		else if ( audioClipEndTime < videoClipEndTime )
		    {
		
		    if ( iMovie->VideoClipEditedHasAudio(0) )
		        {
    		
		        TVedDynamicLevelMark mark1( TTimeIntervalMicroSeconds(0), KAudioLevelMin );
    		    
    		    TInt64 time = audioClipEndTime.Int64() - KFadeInTimeMicroSeconds; 
    		    
		        TVedDynamicLevelMark mark2( TTimeIntervalMicroSeconds(time) , KAudioLevelMin );
    		    
    		    TVedDynamicLevelMark mark3( audioClipEndTime, 0 );
    		
    		    TRAP( error, iMovie->VideoClipInsertDynamicLevelMarkL( 0, mark1 ) );
    		    
    		    if ( error == KErrNone )
    		        {
    		        TRAP( error, iMovie->VideoClipInsertDynamicLevelMarkL( 0, mark2 ) );
    		        }
    		        
    		    if ( error == KErrNone )
    		        {		    
    		        TRAP( error, iMovie->VideoClipInsertDynamicLevelMarkL( 0, mark3 ) );
    		        }
    		        
    		    if ( error != KErrNone ) 
        		    {
        		    iError = error;	
    	            iError = FilterError();		        		    
        		    }
        		        
		        }
		    }
		    
		if ( error == KErrNone )
		    {
		    iState = EStateProcessing;        
		    }
		else
		    {
		    iState = EStateProcessingFailed;    
		    }
		}
		
	if( iWaitDialog )
		{
		TRAP_IGNORE(iWaitDialog->ProcessFinishedL());
		}	
		
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyAudioClipAdded: Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::NotifyAudioClipAddingFailed(CVedMovie& /*aMovie*/, TInt aError)
    {    
    LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyAudioClipAddingFailed: In, aError:%d", aError);

    iError = aError;	    
		
	iError = FilterError();	

	// Next handle error and exit
	iState = EStateFinalizing;
	if ( iWaitDialog )
		{
		TRAP_IGNORE(iWaitDialog->ProcessFinishedL());
		}

    LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyAudioClipAddingFailed: Out");
    }

//=======================================================================================================
void CSimpleVideoEditorImpl::NotifyImageClipGeneratorInitializationComplete(CVeiImageClipGenerator& /*aGenerator*/, TInt aError)
	{
	LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyImageClipGeneratorInitializationComplete, In, aError:%d", aError);

	iError = aError;			
	
	// If the wait dialog has been dismissed, i.e the action has been cancelled,
	// we expect that the DialogDismissedL() method has set the correct state and won't
	// set the state ourselves.
	iGeneratorComplete = ETrue;
	if( !iDialogDismissed ) 
		{
		if (KErrNone == aError)
			{
			iState = EStateInsertImage;
			LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyImageClipGeneratorInitializationComplete: 2");		    
			}
		else
			{		
			iError = FilterError();
			// Next handle error and exit				
					
			/*
			If iImageClipGenerator is deleted here (in NotifyImageClipGeneratorInitializationComplete), endless
			loop is  resulted, because calling iImageClipGenerator's destructor leads to calling NotifyImageClipGeneratorInitializationComplete
			again until stack overdoses etc.
			iImageClipGenerator does not have to be deleted here, it is deleted in destructor.
			delete iImageClipGenerator;
			iImageClipGenerator = 0;		
			*/
		
			iState = EStateFinalizing;
			}
		}

	CompleteRequest();	

	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::NotifyImageClipGeneratorInitializationComplete, Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::DialogDismissedL( TInt aButtonId )
	{
	LOGFMT(KVideoEditorLogFile, "CSimpleVideoEditorImpl::DialogDismissedL, In, aButtonId:%d", aButtonId);

	if ( aButtonId != EAknSoftkeyDone)
		{
		// If the action was cancelled, we set up the correspondig state
		// and also set the iDialogDismissed property to indicate that.
		iDialogDismissed = ETrue;
		
		LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::DialogDismissedL, 1");
	
		if (EStateProcessing == iState && iMovie)
			{
			LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::DialogDismissedL, 2, canceling processing...");
			iState = EStateProcessingFailed;
			/* 
			 It depends on scheduling of active objects whether NotifyMovieProcessingCompleted()
			 gets called. If iProgressDialog is NULLed by itself in the time DialogDismissed() gets called
			 it should be nonrelevant whether NotifyMovieProcessingCompleted() called or not because
			 in NotifyMovieProcessingCompleted() iProgressDialog->ProcessFinished() is called only if
			 it is not NULL leading to another call to DialogDismissed(). But even if DialogDismissed()
			 gets called multiple times it should not cause any harm.
			*/ 
			iMovie->CancelProcessing();									
			LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::DialogDismissedL, 4, ...canceling called");
			}
		else
			{
			// if wait dialog is canceled during inserts
			iError = KErrCancel;
			iState = EStateFinalizing;	
			}
		
		// this problem is because in add text mode orientation is forced to portrait in 
		// such an early stage
		// ask Heikki's opinion, why appUi->SetOrientationL(CAknAppUiBase::EAppUiOrientationPortrait);
		// is called in InitializeOperationL()?
		// Can it be moved to where it is neede, in GetText()?
		if (EOperationModeAddText == iOperationMode)
			{
			RestoreOrientation();
			}
		}
	
	// Only if the VeiImageClipGenerator::NewL() called from the RunL() has finished and called 
	// the NotifyImageClipGeneratorInitializationComplete() method we complete and activate again.
	// If not, we rely that the NotifyImageClipGeneratorInitializationComplete() method
	// calls CompleteRequest() when it's called. 
	if( iGeneratorComplete )
		{
		CompleteRequest();		
		}
	
	LOG(KVideoEditorLogFile, "CSimpleVideoEditorImpl::DialogDismissedL, Out");
	}

//=======================================================================================================
void CSimpleVideoEditorImpl::NotifyVideoClipRemoved(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyVideoClipIndicesChanged(CVedMovie& /*aMovie*/, TInt /*aOldIndex*/, TInt /*aNewIndex*/){}
void CSimpleVideoEditorImpl::NotifyVideoClipTimingsChanged(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyVideoClipSettingsChanged(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyVideoClipColorEffectChanged(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyVideoClipAudioSettingsChanged(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyVideoClipGeneratorSettingsChanged(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyVideoClipDescriptiveNameChanged(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyStartTransitionEffectChanged(CVedMovie& /*aMovie*/){}
void CSimpleVideoEditorImpl::NotifyMiddleTransitionEffectChanged(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyEndTransitionEffectChanged(CVedMovie& /*aMovie*/){}
void CSimpleVideoEditorImpl::NotifyAudioClipRemoved(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyAudioClipIndicesChanged(CVedMovie& /*aMovie*/, TInt /*aOldIndex*/, TInt /*aNewIndex*/){}
void CSimpleVideoEditorImpl::NotifyAudioClipTimingsChanged(CVedMovie& /*aMovie*/, TInt /*aIndex*/){}
void CSimpleVideoEditorImpl::NotifyMovieQualityChanged(CVedMovie& /*aMovie*/){}
void CSimpleVideoEditorImpl::NotifyMovieReseted(CVedMovie& /*aMovie*/){}
void CSimpleVideoEditorImpl::NotifyMovieOutputParametersChanged(CVedMovie& /*aMovie*/){}
void CSimpleVideoEditorImpl::NotifyAudioClipDynamicLevelMarkInserted(CVedMovie& /*aMovie*/, TInt /*aClipIndex*/, TInt /*aMarkIndex*/){}
void CSimpleVideoEditorImpl::NotifyAudioClipDynamicLevelMarkRemoved(CVedMovie& /*aMovie*/, TInt /*aClipIndex*/, TInt /*aMarkIndex*/){}
void CSimpleVideoEditorImpl::NotifyVideoClipDynamicLevelMarkInserted(CVedMovie& /*aMovie*/, TInt /*aClipIndex*/, TInt /*aMarkIndex*/){}
void CSimpleVideoEditorImpl::NotifyVideoClipDynamicLevelMarkRemoved(CVedMovie& /*aMovie*/, TInt /*aClipIndex*/, TInt /*aMarkIndex*/){}
// End of file