diff -r 000000000000 -r 951a5db380a0 videditor/SimpleVideoEditor/src/SimpleVideoEditorImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videditor/SimpleVideoEditor/src/SimpleVideoEditorImpl.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,1866 @@ +/* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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( 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( 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(&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(&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