videocollection/mpxmyvideoscollection/src/vcxmyvideosasyncfileoperations.cpp
changeset 0 96612d01cf9f
child 9 5294c000a26d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videocollection/mpxmyvideoscollection/src/vcxmyvideosasyncfileoperations.cpp	Mon Jan 18 20:21:12 2010 +0200
@@ -0,0 +1,732 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:    Implementation for MPX My Videos Collection Move, Copy and Delete operations.*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <e32cmn.h>
+#include <s32mem.h>
+#include <mpxlog.h>
+#include <mpxmediacontainerdefs.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxcollectionpluginobserver.h>
+#include <mpxmessagegeneraldefs.h>
+#include <mpxcommandgeneraldefs.h>
+#include <mpxcollectioncommanddefs.h>
+#include <mpxmessagecontainerdefs.h>
+#include <vcxmyvideosuids.h>
+#include <drmutility.h>
+#include <bautils.h>
+#include "vcxmyvideoscollectionplugin.h"
+#include "vcxmyvideoscollection.hrh"
+#include "vcxmyvideoscollectionutil.h"
+#include "vcxmyvideosdownloadutil.h"
+#include "vcxmyvideosvideocache.h"
+#include "vcxmyvideoscategories.h"
+#include "vcxmyvideosmessagelist.h"
+#include "vcxmyvideosasyncfileoperations.h"
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CVcxMyVideosAsyncFileOperations* CVcxMyVideosAsyncFileOperations::NewL(
+    CVcxMyVideosCollectionPlugin& aCollection )
+    {
+    MPX_FUNC("CVcxMyVideosAsyncFileOperations::NewL");
+
+    CVcxMyVideosAsyncFileOperations* self = new (ELeave) CVcxMyVideosAsyncFileOperations(
+            aCollection );
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// Destructor.
+// ----------------------------------------------------------------------------
+//
+CVcxMyVideosAsyncFileOperations::~CVcxMyVideosAsyncFileOperations()
+    {
+    MPX_FUNC("CVcxMyVideosAsyncFileOperations::~CVcxMyVideosAsyncFileOperations");
+        
+    iOperationIdArray.Close();
+    iOperationResult.Close();
+    }
+
+// ----------------------------------------------------------------------------
+// Constructor.
+// ----------------------------------------------------------------------------
+//
+CVcxMyVideosAsyncFileOperations::CVcxMyVideosAsyncFileOperations( CVcxMyVideosCollectionPlugin& aCollection )
+: iCollection( aCollection )
+    {
+    MPX_FUNC("CVcxMyVideosAsyncFileOperations::CVcxMyVideosAsyncFileOperations");
+    }
+
+// ----------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ----------------------------------------------------------------------------
+//
+void CVcxMyVideosAsyncFileOperations::ConstructL ()
+    {
+    MPX_FUNC("CVcxMyVideosAsyncFileOperations::ConstructL");
+    }
+    
+// ----------------------------------------------------------------------------
+// CVcxMyVideosCollectionPlugin::DeleteVideoL
+// ----------------------------------------------------------------------------
+//
+void CVcxMyVideosAsyncFileOperations::DeleteVideoL( TUint32 aMdsId, TBool aForce )
+    {
+    MPX_FUNC("CVcxMyVideosAsyncFileOperations::DeleteVideoL");
+            
+    TInt pos;
+    CMPXMedia* videoInCache = iCollection.iCache->FindVideoByMdsIdL( aMdsId, pos );
+                    
+    if ( !videoInCache )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: delete failed, MPX item not found from cache.");
+        User::Leave( KErrNotFound );
+        }
+    
+    TUint32 downloadId = TVcxMyVideosCollectionUtil::DownloadIdL( *videoInCache );            
+    if ( downloadId )
+        {
+        TVcxMyVideosDownloadState dlState =
+                TVcxMyVideosCollectionUtil::DownloadStateL( *videoInCache );
+                        
+        if ( aForce )
+            {
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: aForce is ETrue, the video will be deleted even if download is ongoing");
+            }
+        else if ( dlState != EVcxMyVideosDlStateNone )
+            {
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: delete failed since there is download going on.");
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: use download cancel instead.");
+            User::Leave( KErrArgument );
+            }
+        else
+            {
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: download id was != 0 but download state was EVcxMyVideosDlStateNone");
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: -> we delete the video, it is prob gone from Download Manager already.");
+            }        
+        }
+            
+    if ( !videoInCache->IsSupported( KMPXMediaGeneralUri ) )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations::DeleteVideoL() KMPXMediaGeneralUri attribute missing -> leaving");
+        User::Leave( KErrArgument );
+        }
+    
+    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: trying to delete: %S",
+            &videoInCache->ValueText( KMPXMediaGeneralUri ));
+    TInt err = iCollection.iFs.Delete( videoInCache->ValueText( KMPXMediaGeneralUri ) );
+        
+    if ( err != KErrNone )
+        {
+        MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: file delete failed: %d", err );
+
+        if ( err == KErrNotFound || err == KErrPathNotFound )
+            {
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: file was not found, trying to remove mds object anyways");
+            TInt result = iCollection.iMyVideosMdsDb->RemoveVideo( aMdsId );
+            if ( result == KErrNone )
+                {
+                MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: %d removed from mds", aMdsId); 
+                //mds events will clean cache
+                }
+            else
+                {
+                if ( result == KErrNotFound )
+                    {
+                    // file is gone, and mds item is gone -> try to delete from cache
+                    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: %d not found from MDS, trying to delete from cache", aMdsId );
+                    TInt result = iCollection.iCache->RemoveL( aMdsId );
+                    if ( result == KErrNone )
+                        {
+                        MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: %d deleted from cache, generating event", aMdsId );
+                        iCollection.iMessageList->AddEventL( TMPXItemId( aMdsId, 0),
+                                EMPXItemDeleted, EVcxMyVideosListNoInfo );
+                        iCollection.iMessageList->SendL();
+                        } 
+                    }
+                else
+                    {
+                    //file is gone, mds item and cache are still present, couldnt remove them
+                    MPX_DEBUG3("CVcxMyVideosAsyncFileOperations:: failed to remove %d from mds (%d)", aMdsId, result);
+                    User::Leave( result );
+                    }
+                }
+            }            
+        else
+            {
+            // file delete failed and file still exists
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: leaving mds object intact");
+            User::Leave( err );
+            }
+        }
+    else
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: file delete successful, deleting item from MDS also to speed things up");
+        TInt result = iCollection.iMyVideosMdsDb->RemoveVideo( aMdsId );
+        if ( result == KErrNone )
+            {
+            MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: %d removed from mds", aMdsId);
+            //mds events will clean cache
+            }
+        else
+            {
+            if ( result == KErrNotFound )
+                {
+                // file is gone, and mds item is gone -> try to delete from cache
+                MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: %d not found from MDS, trying to delete from cache", aMdsId );
+                TInt result = iCollection.iCache->RemoveL( aMdsId );
+                if ( result == KErrNone )
+                    {
+                    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: %d deleted from cache, generating event", aMdsId );
+                    iCollection.iMessageList->AddEventL( TMPXItemId( aMdsId, 0),
+                            EMPXItemDeleted, EVcxMyVideosListNoInfo );
+                    iCollection.iMessageList->SendL();
+                    }
+                }
+            else
+                {
+                //mds item and cache are still present, couldnt remove them
+                MPX_DEBUG3("CVcxMyVideosAsyncFileOperations:: failed to remove %d from mds (%d)", aMdsId, result);
+                User::Leave( result );
+                }
+            }
+        }   
+    }
+    
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileOperations::HandleMoveOrCopyStepL
+// ----------------------------------------------------------------------------
+//
+TBool CVcxMyVideosAsyncFileOperations::HandleMoveOrCopyStepL()
+    {
+    CMPXMedia& cmd = iCollection.iActiveTask->GetCommand();
+    
+    TBool done;
+    
+    TBool isMoveOperation = EFalse;    
+    TUint32 cmdId = cmd.ValueTObjectL<TUint32>( KVcxMediaMyVideosCommandId );    
+    if ( cmdId == KVcxCommandMyVideosMove )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: move operation");
+        isMoveOperation = ETrue;
+        }
+        
+    // Start operations
+    if ( iCurrentOperationIndex == 0 )
+        {
+        if ( !cmd.IsSupported( KMPXMediaArrayContents ) )
+            {
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: error, no array defined");
+            User::Leave( KErrArgument );
+            }
+    
+        CMPXMediaArray* idMediaArray = cmd.Value<CMPXMediaArray>(
+                KMPXMediaArrayContents );
+
+        if ( idMediaArray->Count() == 0 )
+            {
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: error, no items in array ");
+            User::Leave( KErrArgument );
+            }
+        
+        iTargetDrive = cmd.ValueTObjectL<TInt32>( KVcxMediaMyVideosInt32Value );
+        
+        TMPXItemId mpxId;    
+        iOperationIdArray.Reset();
+        TInt count = idMediaArray->Count();
+        for ( TInt i = 0; i < count; i++ )
+            {
+            mpxId = idMediaArray->AtL( i )->
+                            ValueTObjectL<TMPXItemId>( KMPXMediaGeneralId );
+            MPX_DEBUG3("CVcxMyVideosAsyncFileOperations:: MPX ID: (%d, %d) will be moved ",
+                    mpxId.iId1,
+                    mpxId.iId2);
+            iOperationIdArray.AppendL( idMediaArray->AtL( i )->
+                    ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId ).iId1 );
+            }
+        
+        iCollection.SendMyVideosMessageL( KVcxMessageMyVideosMoveOrCopyStarted, &cmd );
+
+        iOperationResult.Reset();
+        }
+
+    TRAPD( err, MoveOrCopyVideoL( iOperationIdArray[iCurrentOperationIndex],
+            iTargetDrive, isMoveOperation ));
+
+    iOperationResult.AppendL( err );
+    
+    iCurrentOperationIndex++;
+    
+    // End operations
+    if ( iCurrentOperationIndex > (iOperationIdArray.Count() - 1) )
+        {
+        iCurrentOperationIndex = 0;
+        done                   = ETrue;
+        if ( isMoveOperation )
+            {
+            SendOperationRespL( KVcxMessageMyVideosMoveResp );
+            }
+        else
+            {
+            SendOperationRespL( KVcxMessageMyVideosCopyResp );
+            }
+        }
+    else
+        {
+        done = EFalse;
+        }
+        
+    return done;
+    }
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileOperations::CancelOperationL
+// Called when leave or cancel occurs for the operation, generates resp msg.
+// ----------------------------------------------------------------------------
+//
+void CVcxMyVideosAsyncFileOperations::CancelOperationL( TInt aErr )
+    {
+    if ( iCollection.iActiveTask->IsActive() )
+        {
+        TInt mvCmdId = -1;
+        CMPXMedia& cmd = iCollection.iActiveTask->GetCommand();
+        TMPXCommandId commandId = *cmd.Value<TMPXCommandId>( KMPXCommandGeneralId );
+        
+        if ( commandId == KVcxCommandIdMyVideos )
+            {
+            mvCmdId = cmd.ValueTObjectL<TUint32>( KVcxMediaMyVideosCommandId );
+            }
+                    
+        TInt messageId; 
+        
+        switch ( mvCmdId )
+            {
+            case KVcxCommandMyVideosMove:
+                MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: generating KVcxMessageMyVideosMoveResp");
+                messageId = KVcxMessageMyVideosMoveResp;
+                break;
+                
+            case KVcxCommandMyVideosCopy:
+                MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: generating KVcxMessageMyVideosCopyResp");
+                messageId = KVcxMessageMyVideosCopyResp;
+                break;
+                
+            case KVcxCommandMyVideosDelete:
+                MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: generating KVcxMessageMyVideosDeleteResp");
+                messageId = KVcxMessageMyVideosDeleteResp;
+                break;
+            
+            default:
+                MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: no resp msg for this operation");
+                return;
+            }
+                        
+        // generates response array and resp message
+        for ( TInt i = iCurrentOperationIndex; i < iOperationIdArray.Count(); i++ )
+            {
+            iOperationResult.Append( aErr );
+            }
+        iCurrentOperationIndex = 0;
+
+        SendOperationRespL( messageId );
+        }
+    else
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: no move,copy or delete operations were going on (nor anything else)");
+        User::Leave( KErrNotFound );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileOperations::SendOperationRespL
+// ----------------------------------------------------------------------------
+//
+void CVcxMyVideosAsyncFileOperations::SendOperationRespL( TInt aCmdId )
+    {
+    CMPXMessage* message = TVcxMyVideosCollectionUtil::CreateEmptyMediaListL();
+    CleanupStack::PushL( message ); // 1->
+
+    CMPXMediaArray* messageArray = message->Value<CMPXMediaArray>(
+            KMPXMediaArrayContents );
+    message->SetTObjectValueL<TUid>(KMPXMessageCollectionId,
+            TUid::Uid(KVcxUidMyVideosMpxCollection));        
+            
+    // Add results
+    CMPXMedia* media;
+    TInt count = iOperationIdArray.Count();
+    for ( TInt i = 0; i < count; i++ )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: item added to array");
+        
+        media = CMPXMedia::NewL();
+        CleanupStack::PushL( media ); // 2->
+        media->SetTObjectValueL<TMPXItemId>( KMPXMediaGeneralId,
+                TMPXItemId( iOperationIdArray[i], 0) );
+        media->SetTObjectValueL<TInt32>( KVcxMediaMyVideosInt32Value,
+                iOperationResult[i] );
+        
+        messageArray->AppendL( media );
+        CleanupStack::Pop( media ); // <-2                            
+        }
+        
+    // Set message attributes
+    //
+    message->SetTObjectValueL<TMPXMessageId>( KMPXMessageGeneralId,
+            TMPXItemId( KVcxCommandIdMyVideos, 0 ));
+
+    message->SetTObjectValueL<TInt>( KVcxMediaMyVideosCommandId, aCmdId );
+    
+    iCollection.iMessageList->AddL( message );
+    CleanupStack::Pop( message ); // <-1
+    iCollection.iMessageList->SendL();
+    }
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileOperations::MoveOrCopyVideoL
+// ----------------------------------------------------------------------------
+//
+void CVcxMyVideosAsyncFileOperations::MoveOrCopyVideoL( TUint32 aMdsId, TInt aTargetDrive,
+        TBool aMove )
+    {
+    MPX_FUNC("CVcxMyVideosAsyncFileOperations::MoveOrCopyVideoL");
+
+    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: mds id = %d", aMdsId);
+    
+    //get media from cache or mds
+    TInt pos;
+    CMPXMedia* videoInCache = iCollection.iCache->FindVideoByMdsIdL( aMdsId, pos );
+
+    CMPXMedia* video = NULL;
+    if ( videoInCache )
+        {
+        video = CMPXMedia::NewL( *videoInCache );
+        }
+        
+    if ( !video )
+        {
+        video = iCollection.iMyVideosMdsDb->CreateVideoL( aMdsId, EFalse /* brief details */ );
+        }
+        
+    if ( !video )
+        {
+        MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: mds id %d not found from mds or cache", aMdsId);
+        User::Leave( KErrNotFound );
+        }
+
+    CleanupStack::PushL( video ); // 1->
+    
+    // sanity checks
+    if ( video->ValueTObjectL<TUint32>( KVcxMediaMyVideosDownloadId ) != 0 )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: file is being downloaded, fail, leaving with KErrInUse code.");
+        User::Leave( KErrInUse );
+        }
+
+    const TInt KMaxPathLength = 255;    
+    TBuf<KMaxPathLength> sourcePath( video->ValueText( KMPXMediaGeneralUri ) );
+            
+    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: source path = %S", &sourcePath);
+
+    if ( !DriveHasEnoughFreeSpaceL( sourcePath, aTargetDrive ) )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: target drive full -> skipping");
+        User::Leave( KErrDiskFull );
+        }
+
+    TInt sourceDrive;
+    User::LeaveIfError( iCollection.iFs.CharToDrive( sourcePath[0], sourceDrive ) );
+
+    if ( sourceDrive == aTargetDrive )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: source and target drives are the same, doing nothing.");
+        CleanupStack::PopAndDestroy( video ); // <-1
+        return;
+        }
+
+    TBuf<KMaxPathLength> targetPath;
+    
+    GenerateTargetPathForMoveOrCopyL( sourcePath, targetPath, aTargetDrive );
+
+    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: target path = %S", &targetPath );
+    
+    // update mds and cache
+    CMPXMedia* mediaForMoveOp = NULL;
+    CMPXMedia* mediaForCopyOp = NULL;
+    if ( aMove )
+        {
+        // Update existing media.
+        // Create new media object with only KMPXMediaGeneralId, and KMPXMediaGeneralUri
+        // attributes set, that way update is lighter operation.
+        mediaForMoveOp = CMPXMedia::NewL();
+        CleanupStack::PushL( mediaForMoveOp ); // 2->
+        mediaForMoveOp->SetTObjectValueL<TMPXItemId>( KMPXMediaGeneralId,
+               video->ValueTObjectL<TMPXItemId>( KMPXMediaGeneralId ) );
+        mediaForMoveOp->SetTextValueL( KMPXMediaGeneralUri, targetPath );
+        
+        iCollection.SetVideoL( *mediaForMoveOp );
+        }
+    else
+        {
+        // Create new media.
+        mediaForCopyOp = CMPXMedia::CopyL( *video );
+        CleanupStack::PushL( mediaForCopyOp ); // 2->
+        mediaForCopyOp->SetTextValueL( KMPXMediaGeneralUri, targetPath );
+        iCollection.AddVideoToMdsAndCacheL( *mediaForCopyOp );
+        }
+        
+    //copy file, delete original if move case
+    TRAPD( err, BaflUtils::EnsurePathExistsL( iCollection.iFs, targetPath ) );
+    
+    TUint att = 0;
+    iCollection.iFs.Att( sourcePath, att);    
+    if ( aMove && (att & KEntryAttReadOnly) )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: move operation and source file is read only -> skipping");
+        err = KErrAccessDenied;
+        }
+         
+    if ( err == KErrNone )
+        {
+        MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: copying: %S", &sourcePath);
+        MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: to     : %S", &targetPath);
+        err = BaflUtils::CopyFile( iCollection.iFs, sourcePath, targetPath );
+        if ( err == KErrNone )
+            {
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: Copy succeeded");
+            if ( aMove )
+                {
+                MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: move case");
+                err = BaflUtils::DeleteFile( iCollection.iFs, sourcePath );
+                if ( err != KErrNone )
+                    {
+                    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: delete for source file failed: %d", err );
+                    MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: deleting target file");
+                    TInt delErr = BaflUtils::DeleteFile( iCollection.iFs, targetPath );
+                    if ( delErr != KErrNone )
+                        {
+                        MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: delete for target file failed: %d", delErr );
+                        }
+                    }
+                }
+            }
+        else
+            {
+            MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: CopyFile failed: %d", err);
+            }
+        }
+    
+    // roll mds and cache back if file operations failed
+    if ( err != KErrNone )
+        {
+        if ( aMove )
+            {
+            MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: move failed %d", err );
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: setting media path back and leaving." );
+            mediaForMoveOp->SetTextValueL( KMPXMediaGeneralUri, sourcePath );
+            iCollection.SetVideoL( *mediaForMoveOp );
+            }
+        else
+            {
+            MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: copy failed %d", err );
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: deleting the added media object and leaving");
+            iCollection.iMyVideosMdsDb->RemoveVideo( mediaForCopyOp->ValueTObjectL<TMPXItemId>(
+                    KMPXMediaGeneralId ).iId1 );
+            }
+        User::Leave( err );
+        }
+    
+    if ( aMove )
+        {
+        CleanupStack::PopAndDestroy( mediaForMoveOp ); // <-2
+        }
+    else
+        {
+        CleanupStack::PopAndDestroy( mediaForCopyOp ); // <-2
+        }
+    CleanupStack::PopAndDestroy( video ); // <-1
+    }    
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileOperations::DriveHasEnoughFreeSpaceL
+// ----------------------------------------------------------------------------
+//
+TBool CVcxMyVideosAsyncFileOperations::DriveHasEnoughFreeSpaceL( const TDesC& aPath, TInt aDrive )
+    {
+    TEntry entry;
+    User::LeaveIfError( iCollection.iFs.Entry( aPath, entry ) );
+    TUint32 size = static_cast<TUint32>( entry.iSize );
+    
+    TVolumeInfo volInfo;
+    User::LeaveIfError( iCollection.iFs.Volume( volInfo, aDrive ) );
+    
+    TInt64 freeSpace = volInfo.iFree;
+
+    const TInt K4MBSlack = 0x400000;
+
+    MPX_DEBUG3("CVcxMyVideosAsyncFileOperations:: space needed: %d, space available: %d", size + K4MBSlack,
+            freeSpace );
+    
+    if ( freeSpace < ( size + K4MBSlack ) )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: target drive does not have enough free space");
+        return EFalse;
+        }
+    else
+        {
+        return ETrue;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileOperations::GenerateTargetPathForMoveOrCopyL
+// ----------------------------------------------------------------------------
+//    
+void CVcxMyVideosAsyncFileOperations::GenerateTargetPathForMoveOrCopyL(
+        const TDesC& aSourcePath, TDes& aTargetPath, TInt aTargetDrive )
+    {
+    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: source path = %S", &aSourcePath );
+    
+    TChar targetDriveChar;
+    User::LeaveIfError( iCollection.iFs.DriveToChar( aTargetDrive, targetDriveChar ) );    
+    aTargetPath.Append( targetDriveChar );
+    aTargetPath.Append( ':' );
+    
+    TInt sourceDrive;
+    User::LeaveIfError( iCollection.iFs.CharToDrive( aSourcePath[0], sourceDrive ) );
+
+    TInt systemDrive = iCollection.iFs.GetSystemDrive();
+    
+    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: source drive: %d", sourceDrive);
+    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: target drive: %d", aTargetDrive);
+    MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: system drive: %d", systemDrive);
+
+    _LIT(KDataDes, "data");
+        
+    if ( sourceDrive == systemDrive )
+        {
+        //remove *:\data\* from the path
+        TPtrC pathData( aSourcePath.Mid(3,4) );
+        MPX_DEBUG2("CVcxMyVideosAsyncFileOperations:: sourcePath.Mid(3,4)= %S", &pathData);
+
+        if ( aSourcePath.Mid(3,4) == KDataDes )
+            {
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: source drive is system drive and 'data' exists in sourcePath");
+            MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: not copying 'data' to the target path");
+            aTargetPath.Append( aSourcePath.Mid( 7 ) );
+            }
+        else
+            {
+            aTargetPath.Append( aSourcePath.Mid( 2 ) );
+            }
+        }    
+    else if ( aTargetDrive == systemDrive )
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: target drive is system drive -> adding 'data' to path");
+        aTargetPath.Append( '\\' );
+        aTargetPath.Append( KDataDes );
+        aTargetPath.Append( aSourcePath.Mid( 2 ) );
+        }
+    else 
+        {
+        MPX_DEBUG1("CVcxMyVideosAsyncFileOperations:: source and target drives are not system drive, not adding or removing 'data'");        
+        aTargetPath.Append( aSourcePath.Mid( 2 ) );        
+        }
+    const TInt KMaxPathLength = 255;
+    TBuf<KMaxPathLength> uniquePath;
+    TVcxMyVideosCollectionUtil::MakeUniqueFileNameL( iCollection.iFs, aTargetPath, uniquePath );
+    aTargetPath = uniquePath;
+    }
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileOperations::HandleDeleteStepL
+// ----------------------------------------------------------------------------
+//
+TBool CVcxMyVideosAsyncFileOperations::HandleDeleteStepL()
+    {
+    CMPXMedia& cmd = iCollection.iActiveTask->GetCommand();
+    
+    //no sanity checks for array items, since we want to generate all events, even if there is nothing to delete
+    
+    TBool done;
+    
+    TUint32 cmdId = cmd.ValueTObjectL<TUint32>( KVcxMediaMyVideosCommandId );    
+        
+    // Start operations
+    if ( iCurrentOperationIndex == 0 )
+        {
+        iOperationIdArray.Reset();
+
+        if ( cmd.IsSupported( KMPXMediaArrayContents ) )
+            {    
+            CMPXMediaArray* idMediaArray = cmd.Value<CMPXMediaArray>(
+                KMPXMediaArrayContents );
+                
+            TMPXItemId mpxId;
+            TInt count = idMediaArray->Count();
+            for ( TInt i = 0; i < count; i++ )
+                {
+                mpxId = idMediaArray->AtL( i )->
+                                ValueTObjectL<TMPXItemId>( KMPXMediaGeneralId );
+                MPX_DEBUG3("CVcxMyVideosAsyncFileOperations:: MPX ID: (%d, %d) will be deleted ",
+                        mpxId.iId1,
+                        mpxId.iId2);
+                iOperationIdArray.AppendL( idMediaArray->AtL( i )->
+                        ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId ).iId1 );
+                }
+
+            }
+                    
+        iCollection.SendMyVideosMessageL( KVcxMessageMyVideosDeleteStarted, &cmd );
+
+        iOperationResult.Reset();
+        }
+
+    if ( iOperationIdArray.Count() > 0 )
+        {
+        TRAPD( err, DeleteVideoL( iOperationIdArray[iCurrentOperationIndex] ) );
+        iOperationResult.AppendL( err );
+        }
+        
+    iCurrentOperationIndex++;
+    
+    // End operations
+    if ( iCurrentOperationIndex > (iOperationIdArray.Count() - 1) )
+        {
+        iCurrentOperationIndex = 0;
+        done                   = ETrue;
+
+        SendOperationRespL( KVcxMessageMyVideosDeleteResp );
+        }
+    else
+        {
+        done = EFalse;
+        }
+        
+    return done;
+    }
+
+