--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmappcomponents/harvester/filehandler/src/mpxharvesterfilehandlerimp.cpp Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,2340 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Handles all file related activities
+* Version : %version: da1mmcf#72.1.14.2.4.1.4.1.2 % << Don't touch! Updated by Synergy at check-out.
+*
+*/
+
+
+#include <e32base.h>
+#include <f32file.h>
+#include <centralrepository.h>
+#ifdef RD_MULTIPLE_DRIVE
+#include <pathinfo.h>
+#include <driveinfo.h>
+#endif //RD_MULTIPLE_DRIVE
+
+#include <mpxlog.h>
+#include <mpxharvestercommon.h>
+#include <mpxmedia.h>
+#include <mpxmediaarray.h>
+#include <mpxcollectiontype.h>
+#include <mpxcollectionutility.h>
+#include <mpxcollectionpath.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxmediacontainerdefs.h>
+
+#include <mpxdrmmediautility.h>
+#include <mpxmediadrmdefs.h>
+#include <mpxcollectionplugin.hrh>
+#include <mpxcollectionmediator.h>
+
+#include <mpxcommandgeneraldefs.h>
+#include <mpxcollectioncommanddefs.h>
+#include <DRMNotifier.h>
+#include <DRMEventAddRemove.h>
+#include <Oma2Agent.h>
+#include <caf/caferr.h>
+#include <caf/content.h>
+#include <caf/data.h>
+#include <UsbWatcherInternalPSKeys.h>
+#include <usbpersonalityids.h>
+
+#include "mpxharvesterfilehandlerimp.h"
+#include "mpxfolderscanner.h"
+#include "mpxdbsynchronizer.h"
+#include "mpxfoldermonitor.h"
+#include "mpxmetadatascanner.h"
+#include "mpxplaylistscanner.h"
+#include "mpxharvesterdbmanager.h"
+#include "mpxharvesterdbtable.h"
+#include "mpxharvesterdbitem.h"
+#include "mpxfhcommon.h"
+#include "mpxbrokenlinkcleanup.h"
+
+// ============ CONSTANTS ==========
+_LIT( KDefaultScanPath, "C:\\DATA\\|E:\\" );
+_LIT( KDefaultBlockPath, "\\SYS\\|\\PRIVATE\\|\\SYSTEM\\|\\CITIES\\");
+_LIT( KDefaultContainers, ".odf|.dcf|.asf|.m4a|.mp4" );
+_LIT( KDefaultAutoScanFolder, "C:\\data\\sounds\\digital\\|E:\\sounds\\digital\\");
+const TUid KCRUIDHarvesterFeatures = { 0x101FFCD2 };
+const TUid KMusicPlayerUid = {0x102072C3};
+const TInt KHarvesterScanPathKey = 1;
+const TInt KHarvesterBlockPathKey = 2;
+const TInt KHarvesterContainerKey = 3;
+const TInt KAutoScanDirectoryKey = 4;
+const TInt KDisablePodcasting = 5;
+const TInt KAutoScanDelay = 10000000; // 10 second delay for rights to arrive
+const TInt KAutoScanAfter = 10000000;
+
+// ==========LOCAL FUNCTIONS ========
+static void CleanupArray( TAny* item )
+ {
+ ((RPointerArray<CMPXHarvesterDbItem>*) item )->ResetAndDestroy();
+ }
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ Constructor
+// ---------------------------------------------------------------------------
+//
+CMPXHarvesterFileHandlerImp::CMPXHarvesterFileHandlerImp( RFs& aFs ) :
+ iFs( aFs ),
+ iSynchronizing(EFalse),
+ iDisablePodcasting(EFalse)
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// 2nd Phase Constructor
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::ConstructL()
+ {
+ // Folder monitoring related,
+ //
+ User::LeaveIfError( iAppArc.Connect() );
+ iFolderScanner = CMPXFolderScanner::NewL( *this, *this, iFs );
+ iMetadataScanner = CMPXMetadataScanner::NewL( iFs,
+ iAppArc,
+ iSupportedTypes,
+ *this, *this );
+ iPlaylistScanner = CMPXPlaylistScanner::NewL( *this,
+ *this,
+ iSupportedTypes );
+
+ iBrokenLink = CMPXBrokenLinkCleanup::NewL( *this, *this );
+
+ // Database related
+ //
+ iDBManager = CMPXHarvesterDatabaseManager::NewL( iFs );
+
+ // List of watchers for different drives
+ //
+#ifdef RD_MULTIPLE_DRIVE
+ TDriveList driveList;
+ TInt driveCount(0);
+ User::LeaveIfError( DriveInfo::GetUserVisibleDrives(
+ iFs, driveList, driveCount ) );
+
+ for( TInt driveNum = EDriveA; driveNum <= EDriveZ; driveNum++ )
+ {
+ if ( driveList[driveNum] && (!iDBManager->IsRemoteDrive(static_cast<TDriveNumber>(driveNum))))
+ {
+ CMPXDiskSpaceWatcher* dw = CMPXDiskSpaceWatcher::NewL(
+ iFs, static_cast<TDriveNumber>(driveNum), *this );
+ CleanupStack::PushL( dw );
+ iDiskMonitors.AppendL( dw );
+ CleanupStack::Pop( dw );
+ }
+ }
+#else
+ CMPXDiskSpaceWatcher* dw_e = CMPXDiskSpaceWatcher::NewL( iFs, EDriveE, *this );
+ CleanupStack::PushL( dw_e );
+ iDiskMonitors.AppendL( dw_e );
+ CleanupStack::Pop( dw_e );
+ CMPXDiskSpaceWatcher* dw_c = CMPXDiskSpaceWatcher::NewL( iFs, EDriveC, *this );
+ CleanupStack::PushL( dw_c );
+ iDiskMonitors.AppendL( dw_c );
+ CleanupStack::Pop( dw_c );
+#endif // RD_MULTIPLE_DRIVE
+
+
+ TInt openerr = iDBManager->OpenAllDatabasesL();
+
+ // Temporary collection utility
+ //
+ MMPXCollectionUtility* colUtil =
+ MMPXCollectionUtility::NewL( NULL, KMcModeDefault );
+ CleanupStack::PushL( colUtil );
+
+ // Get the collection UIDs
+ RArray<TUid> ary;
+ CleanupClosePushL( ary );
+ ary.AppendL( TUid::Uid(EMPXCollectionPluginMusic) );
+ iMusicCollectionId = colUtil->CollectionIDL( ary.Array() );
+ ary.Reset();
+ ary.AppendL( TUid::Uid(EMPXCollectionPluginPodCast) );
+ iPodcastCollectionId = colUtil->CollectionIDL( ary.Array() );
+ CleanupStack::PopAndDestroy( &ary );
+
+ // If harvester db was corrupted, mark podcast and music db as corrupt
+ if( openerr == KErrCorrupt )
+ {
+ colUtil->Collection().CommandL(EMcCmdDbCorrupted, iMusicCollectionId.iUid );
+ colUtil->Collection().CommandL(EMcCmdDbCorrupted, iPodcastCollectionId.iUid );
+ }
+
+ // Get the list of supported types from the collection
+ //
+ colUtil->Collection().GetSupportedTypesL( iSupportedTypes );
+ CleanupStack::Pop( colUtil );
+ colUtil->Close();
+
+ // Get the scan drives from cenrep.
+ //
+ ParseScanPathL();
+
+ // Get the list of container types
+ iContainerTypes = new(ELeave) CDesCArrayFlat(2); // granularity
+ ParseContainersL();
+
+ // Get the list of automatic scanned folders
+ ParseAutoScanL();
+ iIdle = CPeriodic::NewL( CActive::EPriorityLow );
+
+ // Get the podcasting enabled / disabled flag
+ //
+ CRepository* cenrep(NULL);
+ TRAPD( err, cenrep = CRepository::NewL( KCRUIDHarvesterFeatures ) );
+ if( err == KErrNone )
+ {
+ cenrep->Get( KDisablePodcasting, iDisablePodcasting );
+ delete cenrep;
+ }
+ else
+ {
+ iDisablePodcasting = EFalse;
+ }
+
+ // Create the database synchronizer
+ iDbSynchronizer = CMPXDbSynchronizer::NewL(*this,*iDBManager,iMusicCollectionId,
+ iPodcastCollectionId,iFs, iDisablePodcasting);
+
+#ifdef RD_MULTIPLE_DRIVE
+ // Use default MMC drive as the Removable drive
+ User::LeaveIfError( DriveInfo::GetDefaultDrive(
+ DriveInfo::EDefaultRemovableMassStorage,
+ iRemovedDrive ) );
+#endif
+
+ // Create DRM Notifier and register for AddRemove event
+ iDrmNotifier = CDRMNotifier::NewL();
+ iDrmNotifier->RegisterEventObserverL( *this, KEventAddRemove );
+ }
+
+// ---------------------------------------------------------------------------
+// Two-Phased Constructor
+// ---------------------------------------------------------------------------
+//
+CMPXHarvesterFileHandlerImp* CMPXHarvesterFileHandlerImp::NewL( RFs& aFs )
+ {
+ CMPXHarvesterFileHandlerImp* self =
+ new( ELeave ) CMPXHarvesterFileHandlerImp(aFs);
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMPXHarvesterFileHandlerImp::~CMPXHarvesterFileHandlerImp()
+ {
+ MPX_DEBUG1("~CMPXHarvesterFileHandlerImp <---");
+ delete iDbSynchronizer;
+ delete iFolderScanner;
+ delete iMetadataScanner;
+ delete iPlaylistScanner;
+ delete iBrokenLink;
+
+ iDiskMonitors.ResetAndDestroy();
+ iDiskMonitors.Close();
+
+ iFolderMonitors.ResetAndDestroy();
+ iFolderMonitors.Close();
+
+
+ iSupportedTypes.ResetAndDestroy();
+ iSupportedTypes.Close();
+
+ if( iContainerTypes )
+ {
+ iContainerTypes->Reset();
+ }
+ delete iContainerTypes;
+
+ iFilteredDrivesToScan.Reset();
+ iFilteredDrivesToScan.Close();
+ iDrivesToScan.Reset();
+ iDrivesToScan.Close();
+ iPathsToBlock.Reset();
+ iPathsToBlock.Close();
+
+ // Cleans up the scanning tables and arrays
+ Reset();
+
+ delete iDBManager;
+
+ if( iCollectionUtil )
+ {
+ iCollectionUtil->Close();
+ }
+
+ iAppArc.Close();
+
+ iAutoScanPaths.Reset();
+ iAutoScanPaths.Close();
+ delete iIdle;
+
+ if(iDrmNotifier)
+ {
+ TRAP_IGNORE( iDrmNotifier->UnRegisterEventObserverL( *this, KEventAddRemove ) );
+ delete iDrmNotifier;
+ }
+ MPX_DEBUG1("~CMPXHarvesterFileHandlerImp --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Scans all drives in the list of interested drives
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::ScanL()
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::ScanL <---");
+
+ // Reset all previous states
+ CancelScan();
+ Reset();
+
+ // Construct the collection utility
+ if( iCollectionUtil )
+ {
+ iCollectionUtil->Close();
+ iCollectionUtil = NULL;
+ }
+ iCollectionUtil = MMPXCollectionUtility::NewL( NULL, KMusicPlayerUid );
+
+ // cenrep key need to be checked whether USB cable is connected in MTP/Combined Mode
+ // to prevent refresh
+ TInt usbStatus;
+ RProperty::Get(KPSUidUsbWatcher, KUsbWatcherSelectedPersonality, usbStatus);
+
+ if ((usbStatus == KUsbPersonalityIdMTP) || (usbStatus == KUsbPersonalityIdPCSuiteMTP))
+ {
+ MPX_DEBUG1("USB is active, Leave with KErrLocked");
+ // need to call back even if it leaves here
+ iCollectionUtil->Collection().NotifyL( EMcMsgRefreshEnd, KErrLocked );
+ //User::Leave(KErrLocked);
+ return;
+ }
+
+ iCollectionUtil->Collection().NotifyL( EMcMsgRefreshStart, KErrNone );
+
+ // Reopen databases
+ iDBManager->OpenAllDatabasesL();
+
+ // Begin transaction on databases
+ iDBManager->BeginL();
+
+ //Remove out of disk space drives from scanned drives list
+ iFilteredDrivesToScan.Reset();
+ CopyArrayL(iDrivesToScan.Array(),iFilteredDrivesToScan);
+
+ iOutOfDisk = EFalse;
+ TInt driveCount (iDiskMonitors.Count());
+ TBool outOfDisk(EFalse);
+ for( TInt driveIndex = 0; driveIndex < driveCount; ++driveIndex )
+ {
+ //Check if the current drive is low on disk
+ outOfDisk = iDiskMonitors[driveIndex]->IsLowOnDisk();
+ iDiskMonitors[driveIndex]->StartL();
+
+ if(outOfDisk)
+ {
+ TInt count( iFilteredDrivesToScan.Count() );
+ TInt index(0);
+ TInt currentDriveNumber = iDiskMonitors[driveIndex]->CurrentDrive();
+ while(index < count)
+ {
+ // Remove current drive from the scanned drives list
+ TParse fileNameParser;
+ User::LeaveIfError(fileNameParser.Set(iFilteredDrivesToScan[index],NULL,NULL));
+ TFileName driveName(fileNameParser.Drive());
+ TInt driveNumber = TDriveUnit( driveName );
+ if (currentDriveNumber == driveNumber)
+ {
+ iFilteredDrivesToScan.Remove(index);
+ count--;
+ }
+ else
+ {
+ index++;
+ }
+ }
+ TRAP_IGNORE(iDBManager->RemoveDatabaseL(static_cast<TDriveNumber>(currentDriveNumber)));
+ }
+ }
+
+ iSynchronizing = CheckDbInSyncL();
+
+ if(!iSynchronizing)
+ {
+ // Start the scanning process
+ iRefreshCount++;
+ iFolderScanner->ScanL( iFilteredDrivesToScan );
+ iMetadataScanner->Reset();
+ iBrokenLink->Reset();
+ iPlaylistScanner->Reset();
+ iIdle->Cancel();
+
+ // Keep a count of how many we added to synchronize the number
+ iAddedCount = 0;
+ iRefreshing = ETrue;
+ }
+
+ if (iFilteredDrivesToScan.Count() == 0 )
+ {
+ iOutOfDisk = ETrue;
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::ScanL -- cancelling scan");
+ // Cancel the scan in this case, will goto HandleScanStateCompleteL()
+ CancelScan();
+ }
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::ScanL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Cancels Scanning
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::CancelScan()
+ {
+ iDbSynchronizer->Cancel();
+ iFolderScanner->Cancel();
+ iBrokenLink->Cancel();
+ iMetadataScanner->Stop();
+ iPlaylistScanner->Cancel();
+ }
+
+// ---------------------------------------------------------------------------
+// Handles a system event
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleSystemEventL( TSystemEvent aEvent,
+ TInt aData )
+ {
+ MPX_DEBUG2("CMPXHarvesterFileHandlerImp::HandleSystemEventL %i", aEvent);
+ // How to handle each event
+ //
+ // 1: Format and eject, we stop scanning and close only the mmc db
+ // 2: Format end and disk insert we reopen db and scan for new files
+ // 3: USB start we stop scan and close all db
+ // 4: USB end we re-open all db and scan for new files
+ // 5: MTP start we stop monitoring for new files (no dismount)
+ // 6: MTP end we re-open all db, files added already, restart monitor
+ //
+#ifdef RD_MULTIPLE_DRIVE
+ // Get all visible drives
+ TDriveList driveList;
+ TInt driveCount(0);
+ TPtrC drivePresent(_L("present"));
+ TPtrC driveNotPresent(_L("not present"));
+ TPtrC driveInUse(_L("in use"));
+ TPtrC driveAvailable(_L("available"));
+ TPtrC driveFormatted(_L("formatted"));
+ TPtrC driveNotFormatted(_L("not formatted"));
+ User::LeaveIfError( DriveInfo::GetUserVisibleDrives(
+ iFs, driveList, driveCount ) );
+ MPX_DEBUG2 ("CMPXHarvesterFileHandlerImp::HandleSystemEventL - driveCount = %d", driveCount);
+
+ for( TInt driveNum = EDriveA; driveNum <= EDriveZ; driveNum++ )
+ {
+ if (driveList[driveNum])
+ {
+ // Get the drive status
+ TUint driveStatus(0);
+ User::LeaveIfError( DriveInfo::GetDriveStatus(
+ iFs, driveNum, driveStatus ) );
+ MPX_DEBUG3 ("CMPXHarvesterFileHandlerImp::HandleSystemEventL - drive %d status=0x%x", driveNum, driveStatus);
+ TChar driveChar;
+ User::LeaveIfError(
+ iFs.DriveToChar( driveNum, driveChar ) );
+ MPX_DEBUG5 ("CMPXHarvesterFileHandlerImp::HandleSystemEventL - drive %c: is %S, %S and %S",
+ driveChar,
+ (driveStatus&DriveInfo::EDrivePresent)?&drivePresent:&driveNotPresent,
+ (driveStatus&DriveInfo::EDriveInUse)?&driveInUse:&driveAvailable,
+ (driveStatus&DriveInfo::EDriveFormatted)?&driveFormatted:&driveNotFormatted);
+ }
+ }
+#endif //RD_MULTIPLE_DRIVE
+ switch( aEvent )
+ {
+ case EFormatStartEvent:
+ {
+ MPX_DEBUG1("Disk Format start event");
+ CancelScan();
+ iDBManager->CloseDatabase( (TDriveNumber) aData );
+ break;
+ }
+ case EDiskRemovedEvent:
+ {
+ MPX_DEBUG1("Disk Removed event");
+ iIdle->Cancel();
+ CancelScan();
+#ifdef RD_MULTIPLE_DRIVE
+ for( TInt driveNum = EDriveA; driveNum <= EDriveZ; driveNum++ )
+ {
+ if (driveList[driveNum] && (!iDBManager->IsRemoteDrive(static_cast<TDriveNumber>(driveNum))))
+ {
+ TUint driveStatus(0);
+ User::LeaveIfError( DriveInfo::GetDriveStatus(
+ iFs, driveNum, driveStatus ) );
+ if (!(driveStatus & DriveInfo::EDrivePresent ))
+ {
+ // Close database for non-present drive
+ iDBManager->CloseDatabase( (TDriveNumber) driveNum );
+ // Save the drive
+ iRemovedDrive = driveNum;
+ break;
+ }
+ }
+ }
+#else
+ iDBManager->CloseDatabase( (TDriveNumber) aData );
+#endif // RD_MULTIPLE_DRIVE
+ break;
+ }
+ case EFormatEndEvent:
+ {
+ MPX_DEBUG1("Disk Format end event");
+ CancelScan();
+ iDBManager->OpenDatabaseL( (TDriveNumber) aData );
+ break;
+ }
+ case EDiskInsertedEvent:
+ {
+ MPX_DEBUG1("Disk Insert event");
+ CancelScan();
+#ifdef RD_MULTIPLE_DRIVE
+ iDBManager->OpenDatabaseL( (TDriveNumber) iRemovedDrive );
+#else
+ iDBManager->OpenDatabaseL( (TDriveNumber) aData );
+#endif // RD_MULTIPLE_DRIVE
+ break;
+ }
+ case EUSBMassStorageStartEvent:
+ {
+ iIdle->Cancel();
+ CancelScan();
+#ifdef RD_MULTIPLE_DRIVE
+ // Close all databases other than the phone memory database
+ for( TInt driveNum = EDriveA; driveNum <= EDriveZ; driveNum++ )
+ {
+ if (driveList[driveNum] && (!iDBManager->IsRemoteDrive(static_cast<TDriveNumber>(driveNum))))
+ {
+ if ( driveNum != EDriveC )
+ {
+ iDBManager->CloseDatabase( (TDriveNumber) driveNum );
+ }
+ }
+ }
+#else
+ iDBManager->CloseDatabase( (TDriveNumber) aData );
+#endif // RD_MULTIPLE_DRIVE
+ break;
+ }
+ case EUSBMassStorageEndEvent:
+ {
+#ifdef RD_MULTIPLE_DRIVE
+ // Open all databases other than the phone memory
+ for( TInt driveNum = EDriveA; driveNum <= EDriveZ; driveNum++ )
+ {
+ if (driveList[driveNum] && (!iDBManager->IsRemoteDrive(static_cast<TDriveNumber>(driveNum))))
+ {
+ if ( driveNum != EDriveC )
+ {
+ iDBManager->OpenDatabaseL( (TDriveNumber) driveNum );
+ }
+ }
+ }
+#else
+ iDBManager->OpenDatabaseL( (TDriveNumber) aData );
+#endif // RD_MULTIPLE_DRIVE
+ break;
+ }
+ case EUSBMTPNotActiveEvent: // deliberate fall through
+ {
+ if ( iRefreshing )
+ {
+ // Notify clients that refresh is cancelled.
+ iCollectionUtil->Collection().NotifyL( EMcMsgRefreshEnd, KErrLocked );
+ }
+ }
+ case EUSBMTPStartEvent:
+ {
+ CancelScan();
+ // nothing to do, db is needed for MTP
+ break;
+ }
+ case EUSBMTPEndEvent:
+ {
+ // nothing to do, db is updated by MTP
+ break;
+ }
+ case EPowerKeyEjectEvent:
+ {
+ CancelScan();
+ break;
+ }
+ default:
+ {
+ MPX_DEBUG1("CCMPXHarvesterFileHandlerImp::HandleSystemEventL Unknown system event!");
+ break;
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Add a file to the harvester db
+// ---------------------------------------------------------------------------
+//
+CMPXMedia* CMPXHarvesterFileHandlerImp::AddFileL( const TDesC& aPath )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFileL <---");
+
+ // Create the media properties and add as usual.
+ //
+ CMPXMedia* prop = iMetadataScanner->ExtractFileL( aPath );
+ CleanupStack::PushL( prop );
+ AddFileL( *prop );
+ CleanupStack::Pop( prop );
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFileL --->");
+ return prop;
+ }
+
+// ---------------------------------------------------------------------------
+// Add a file to the harvester db
+// ---------------------------------------------------------------------------
+//
+TInt CMPXHarvesterFileHandlerImp::AddFileL( CMPXMedia& aMediaProp )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFileL <---");
+
+ // Parse
+ TPtrC path = aMediaProp.ValueText( TMPXAttribute( KMPXMediaIdGeneral,
+ EMPXMediaGeneralUri) );
+ TInt r(0);
+ // Make sure we have a "file"
+ if( path.Compare(KNullDesC) )
+ {
+ // Last modified time
+ TTime lastModTime;
+ iFs.Modified( path, lastModTime );
+
+ // Collection UID,
+ CMPXCollectionMediator* mediator = CMPXCollectionMediator::NewL();
+ CleanupStack::PushL( mediator );
+ mediator->CheckItemL( aMediaProp );
+ CleanupStack::PopAndDestroy( mediator );
+
+ TUid col( KNullUid );
+ if( aMediaProp.IsSupported( TMPXAttribute( KMPXMediaIdGeneral,
+ EMPXMediaGeneralCollectionId ) ) )
+ {
+ col = aMediaProp.ValueTObjectL<TUid>( TMPXAttribute(
+ KMPXMediaIdGeneral,
+ EMPXMediaGeneralCollectionId ) );
+ }
+ MPX_DEBUG2("CMPXHarvesterFileHandlerImp::AddFileL aMediaProp->Value<TUid> col = %i", col.iUid);
+ // Collection not set yet
+ if( col.iUid == 0 )
+ {
+ TInt index = IsMediaFileL( path );
+ if( index >= KErrNone )
+ {
+ MPX_DEBUG2(_L("CMPXHarvesterFileHandlerImp::AddFileL - count: %i"),iSupportedTypes.Count());
+ col = iSupportedTypes[index]->Uid();
+ MPX_DEBUG2(_L("CMPXHarvesterFileHandlerImp::AddFileL Selected Collection %i"), col.iUid);
+ aMediaProp.SetTObjectValueL<TUid>( TMPXAttribute(
+ KMPXMediaIdGeneral,
+ EMPXMediaGeneralCollectionId ),
+ col );
+ }
+ }
+
+ // drm
+ TBool drm(EFalse);
+ if( aMediaProp.IsSupported( TMPXAttribute(KMPXMediaIdDrm,
+ EMPXMediaDrmProtected) ) )
+ {
+ if( aMediaProp.ValueTObjectL<TBool>(TMPXAttribute(KMPXMediaIdDrm,
+ EMPXMediaDrmProtected)) )
+ {
+ TInt rights( EMPXDrmRightsFull );
+
+ if( aMediaProp.IsSupported( TMPXAttribute(KMPXMediaIdDrm,
+ EMPXMediaDrmRightsStatus) ) )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFiles -- getting rights");
+ rights = aMediaProp.ValueTObjectL<TInt>( TMPXAttribute(KMPXMediaIdDrm,
+ EMPXMediaDrmRightsStatus) );
+ }
+ MPX_DEBUG2("CMPXHarvesterFileHandlerImp::AddFiles -- rights %i", rights);
+ if( rights == EMPXDrmRightsMissing ||
+ rights == EMPXDrmRightsExpired )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFiles -- drm");
+ drm = ETrue;
+ }
+ }
+ }
+ if( aMediaProp.IsSupported(KMPXMediaGeneralFlags) )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFiles -- db flags");
+ TUint dbflags( aMediaProp.ValueTObjectL<TUint>(KMPXMediaGeneralFlags) );
+ if( dbflags&KMPXMediaGeneralFlagsIsDrmLicenceInvalid )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFiles -- db flags drm invalid");
+ drm = ETrue;
+ }
+ }
+ // Add to database
+ CMPXHarvesterDB& db = iDBManager->GetDatabaseL( ::ExtractDrive( path ) );
+ CMPXHarvesterDatabaseTable* table = db.OpenFileL( path );
+ CleanupStack::PushL( table );
+
+ // Don't add something we already have
+ //
+ if( table->CountL() == 0 )
+ {
+ TParsePtrC parse( path );
+ table->AddItemL( parse.DriveAndPath(), parse.NameAndExt(),
+ lastModTime, col.iUid, drm );
+ }
+ CleanupStack::PopAndDestroy( table );
+
+ // Return the collection that it should belong to.
+ r = col.iUid;
+ }
+ else
+ {
+ // No file path, leave KErrArgument!
+ User::Leave( KErrArgument );
+ }
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFileL --->");
+ return r;
+ }
+
+// ---------------------------------------------------------------------------
+// Remove a file from the harvester db
+// ---------------------------------------------------------------------------
+//
+TInt CMPXHarvesterFileHandlerImp::RemoveFileL( const TDesC& aPath, TBool aEndTransaction )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RemoveFileL <---");
+ TInt r(0);
+
+ // Open the db
+ CMPXHarvesterDB& db = iDBManager->GetDatabaseL( ::ExtractDrive(aPath) );
+ MPX_PERF_START( MPX_PERF_HARV_DB_DELETE_SUB1 );
+ CMPXHarvesterDatabaseTable* table = db.OpenFileL( aPath );
+ MPX_PERF_END( MPX_PERF_HARV_DB_DELETE_SUB1 );
+
+ CleanupStack::PushL( table );
+
+ // Create a cached copy of the db
+ MPX_PERF_START( MPX_PERF_HARV_DB_DELETE_SUB2 );
+ RPointerArray<CMPXHarvesterDbItem>* ary =
+ table->CreateTableRepresentationL();
+ TCleanupItem cleanup( CleanupArray, ary );
+ CleanupStack::PushL( cleanup );
+ MPX_PERF_END( MPX_PERF_HARV_DB_DELETE_SUB2 );
+
+ // Delete the item from db
+ MPX_PERF_START( MPX_PERF_HARV_DB_DELETE_SUB3 );
+ TRAPD( err, table->DeleteItemL(aEndTransaction) );
+ MPX_PERF_END( MPX_PERF_HARV_DB_DELETE_SUB3 );
+
+ // If delete was successful, that means the item existed
+ // find the collection db id for return
+ //
+ if( err == KErrNone )
+ {
+ CMPXHarvesterDbItem* item = (*ary)[0];
+ if( item != NULL )
+ {
+ r = item->iColId;
+ }
+ }
+ else
+ {
+ r=err;
+ }
+ CleanupStack::Pop( ary );
+ ary->ResetAndDestroy();
+ delete ary;
+ CleanupStack::PopAndDestroy( table );
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RemoveFileL --->");
+ return r;
+ }
+
+// ---------------------------------------------------------------------------
+// Update the properties of a file
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::UpdateFileL( const TDesC& aFile, TInt aCollection )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::UpdateFileL <---");
+
+ OpenDBForPathL( aFile );
+
+ // Last modified time
+ TTime lastModTime;
+ iFs.Modified( aFile, lastModTime );
+
+ iCurTable->UpdateItemL( lastModTime, aCollection,!iRefreshing );
+ Reset();
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::UpdateFileL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Rename a file
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::RenameFileL( const TDesC& aOldPath,
+ const TDesC& aNewPath,
+ TInt aCollection )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RenameFileL <---");
+
+ // update harvester database
+ OpenDBForPathL( aOldPath );
+
+ // Last modified time
+ TTime lastModTime;
+ iFs.Modified( aNewPath, lastModTime );
+
+ iCurTable->UpdateItemL( lastModTime, aCollection, !iRefreshing, aNewPath );
+ Reset();
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RenameFileL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Finds the associated collection id for a file
+// ---------------------------------------------------------------------------
+//
+TInt CMPXHarvesterFileHandlerImp::FindCollectionIdL( const TDesC& aFile )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::FindCollectionIdL <---");
+ TInt r(0);
+
+ // Open the db
+ CMPXHarvesterDB& db = iDBManager->GetDatabaseL( ::ExtractDrive(aFile) );
+ CMPXHarvesterDatabaseTable* table = db.OpenFileL( aFile );
+ CleanupStack::PushL( table );
+
+ // Create a cached copy of the db
+ RPointerArray<CMPXHarvesterDbItem>* ary =
+ table->CreateTableRepresentationL();
+ if( ary->Count() > 0 )
+ {
+ CMPXHarvesterDbItem* item = (*ary)[0]; // not owned
+ r = item->iColId;
+ }
+ else
+ {
+ r = KErrNotFound;
+ }
+ ary->ResetAndDestroy();
+ delete ary;
+ CleanupStack::PopAndDestroy( table );
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::FindCollectionIdL --->");
+ return r;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Re-create all databases
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::RecreateDatabases()
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RecreateDatabasesL <--");
+ iDBManager->RecreateDatabases();
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RecreateDatabasesL -->");
+ }
+
+// ---------------------------------------------------------------------------
+// Close database transaction
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::CloseTransactionL()
+ {
+ iDBManager->CommitL();
+ }
+
+// ---------------------------------------------------------------------------
+// Get a media object for the file
+// ---------------------------------------------------------------------------
+//
+CMPXMedia* CMPXHarvesterFileHandlerImp::GetMediaForFileL( const TDesC& aPath )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::GetMediaForFileL <---");
+
+ // Create the media properties
+ //
+ CMPXMedia* prop = iMetadataScanner->ExtractFileL( aPath );
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::GetMediaForFileL --->");
+ return prop;
+ }
+
+// ---------------------------------------------------------------------------
+// Get Collection Uid for the file
+// ---------------------------------------------------------------------------
+//
+TInt CMPXHarvesterFileHandlerImp::GetColUidForFileL( const TDesC& aPath )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::GetColUidForFileL <---");
+
+ if(aPath == KNullDesC)
+ {
+ // No file path, leave KErrArgument!
+ User::Leave( KErrArgument );
+ }
+
+ TInt ret(0);
+ TInt index = IsMediaFileL( aPath );
+ if( index >= KErrNone )
+ {
+ ret = iSupportedTypes[index]->Uid().iUid;
+ }
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::GetColUidForFileL --->");
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// Remove multiple files from the harvester db
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::RemoveFilesL( const MDesCArray& aFilePaths )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RemoveFilesL <---");
+
+ TInt count( aFilePaths.MdcaCount() );
+ TBool endTransaction(EFalse);
+ for( TInt i=0; i<count; ++i )
+ {
+ if ( (i == count-1) || (i%KBatchCommit == 0) )
+ {
+ endTransaction = ETrue;
+ }
+ User::LeaveIfError( RemoveFileL( aFilePaths.MdcaPoint(i), endTransaction ) );
+ }
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RemoveFilesL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Remove all files from the harvester db
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::RemoveAllFilesL()
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RemoveAllFilesL <---");
+ TInt dbCount( iDBManager->Count() );
+ for( TInt i=0; i< dbCount; ++i )
+ {
+ CMPXHarvesterDB& db = iDBManager->GetDatabaseL( i );
+ db.RemoveAllFilesL();
+ }
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::RemoveAllFilesL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Handles a state change event
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleScanStateCompleteL( TScanState aState,
+ TInt aErr )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleScanStateCompleteL <---");
+
+ // Cleanup associated with each state
+ //
+ switch( aState )
+ {
+ case EScanFiles:
+ {
+#ifdef __PRINTDB__
+ if( iCurTable )
+ iCurTable->PrintItemsInTableL();
+#endif //__PRINTDB__
+
+ // Look for removed items
+ // Do not look for removed files if there was an error
+ if( aErr == KErrNone )
+ {
+ HandleBrokenItemsL();
+ }
+ Reset();
+ break;
+ }
+ case ECleanupBrokenLink:
+ {
+ iBrokenLink->Reset();
+ break;
+ }
+ case EScanPlaylists:
+ {
+ iPlaylistScanner->Reset();
+ break;
+ }
+ case EScanMetadata:
+ {
+ iMetadataScanner->Reset();
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Next state handling
+ //
+ if( KErrNone == aErr )
+ {
+ switch( aState )
+ {
+ case EScanFiles:
+ {
+ MPX_DEBUG1("Start Broken Link");
+ iBrokenLink->Start();
+ break;
+ }
+ case ECleanupBrokenLink:
+ {
+ MPX_DEBUG1("Start Metadata Scan");
+ iMetadataScanner->Start();
+ break;
+ }
+ case EScanMetadata:
+ {
+ MPX_DEBUG1("Start Metadata Scan");
+ iPlaylistScanner->ScanL();
+ break;
+ }
+ case EScanPlaylists:
+ {
+ MPX_DEBUG1("Scan complete");
+
+ TRAPD(err, DoCompleteRefreshL( KErrNone ));
+
+ // handle DoCompleteRefreshL leave
+ if( err != KErrNone )
+ {
+ // finish refresh, close waitnote
+ iCollectionUtil->Collection().NotifyL( EMcMsgRefreshEnd, err );
+ }
+
+ // Reset all scan states
+ Reset();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // Error occured, check for out of disk
+ //
+ TInt error = iOutOfDisk ? KErrDiskFull : aErr;
+ TRAPD(err, DoCompleteRefreshL( error ));
+
+ // handle DoCompleteRefreshL leave
+ if( err != KErrNone )
+ {
+ // finish refresh, close waitnote
+ iCollectionUtil->Collection().NotifyL( EMcMsgRefreshEnd, err );
+ }
+ }
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleScanStateCompleteL <---");
+ }
+
+// ---------------------------------------------------------------------------
+// Handles a state change event
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleSynchronizationComplete( TInt aErr )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleSynchronizationComplete enter");
+
+ iSynchronizing = EFalse;
+
+ if(aErr == KErrNone)
+ {
+ // Start the scanning process
+ iRefreshCount++;
+ // Keep a count of how many we added to syncrhonize the number
+ iAddedCount = 0;
+ iRefreshing = ETrue;
+
+ TRAPD(err,iFolderScanner->ScanL( iFilteredDrivesToScan ));
+ if(err == KErrNone)
+ {
+ iMetadataScanner->Reset();
+ iBrokenLink->Reset();
+ iPlaylistScanner->Reset();
+ iIdle->Cancel();
+ }
+ else
+ {
+ TRAPD(error, DoCompleteRefreshL( err ));
+
+ // handle DoCompleteRefreshL leave
+ if( error != KErrNone )
+ {
+ // finish refresh, close waitnote
+ TRAP_IGNORE( iCollectionUtil->Collection().NotifyL( EMcMsgRefreshEnd, error ) );
+ }
+ }
+ }
+ else
+ {
+ iRefreshCount++;
+ iRefreshing = ETrue;
+ TInt error = iOutOfDisk ? KErrDiskFull : aErr;
+ TRAPD(err, DoCompleteRefreshL( error ));
+
+ // handle DoCompleteRefreshL leave
+ if( err != KErrNone )
+ {
+ // finish refresh, close waitnote
+ TRAP_IGNORE( iCollectionUtil->Collection().NotifyL( EMcMsgRefreshEnd, err ) );
+ }
+ }
+ MPX_DEBUG1("<--- CMPXHarvesterFileHandlerImp::HandleSynchronizationCompleteL exit");
+ }
+
+// ---------------------------------------------------------------------------
+// Handle adding a single file
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleFileAdditionL( const TDesC& aFileName,
+ TInt /*aColIndex*/,
+ TBool /*aPlaylist*/ )
+ {
+ MPX_DEBUG2("CMPXHarvesterFileHandlerImp::HandleFileAdditionL %S<---", &aFileName );
+
+ // Find the item in the array
+ //
+ CMPXHarvesterDbItem tmp;
+ tmp.iFile = aFileName.AllocL();
+
+ // Last modified time
+ //
+ TTime lastModTime;
+ iFs.Modified( aFileName, lastModTime );
+
+ // This is very inefficient, should hash.
+ //
+ if( iCurList )
+ {
+ TInt index = iCurList->FindInOrder( &tmp, CMPXHarvesterDbItem::Compare );
+ if( index != KErrNotFound )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleFileAdditionL found file");
+
+ // Check modified time stamp to see if it was modified
+ // Also check files that did not have rights, see if we have rights now
+ //
+ CMPXHarvesterDbItem* item = (*iCurList)[index];
+ if( item->iLastModifiedTime != lastModTime || item->iDrm )
+ {
+ MPX_DEBUG1("Rescanning a file because of modified or drm");
+ HandleUpdatedItemL( aFileName );
+ }
+
+ // If found, we remove it from the list, items left should be deleted
+ //
+ delete item;
+ iCurList->Remove( index );
+ }
+ else // new file
+ {
+ HandleNewItemL( aFileName );
+ }
+ }
+ else
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleFileAdditionL Scan cancelled");
+ }
+
+ delete tmp.iFile;
+ tmp.iFile = NULL;
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleFileAdditionL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Handle a change in the file system, could be a file added/removed
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleDirectoryChangedL( const TDesC& aPath )
+ {
+ // Delay the scanning for a few seconds so the files are finished
+ // copying. If already active, means we just append onto the list
+ //
+ iAutoScanPaths.AppendL( aPath );
+ if( !iIdle->IsActive() )
+ {
+ TCallBack cb( Callback, this );
+ iIdle->Start( TTimeIntervalMicroSeconds32( KAutoScanDelay ),
+ TTimeIntervalMicroSeconds32( KAutoScanAfter ),
+ cb );
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// Handles opening the drive
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleOpenDriveL( TDriveNumber aDrive,
+ const TDesC& aFolder )
+ {
+#ifdef __PRINTDB__
+ if( iCurTable )
+ iCurTable->PrintItemsInTableL();
+#endif //__PRINTDB__
+
+ // Look for broken files
+ HandleBrokenItemsL();
+
+ // Delete previous table and open the next one
+ Reset();
+ MPX_TRAPD( err, iCurDB = &iDBManager->GetDatabaseL( aDrive ) );
+ if ( err != KErrNone )
+ {
+ iDBManager->OpenAllDatabasesL();
+ iCurDB = &iDBManager->GetDatabaseL( aDrive );
+ }
+
+ if( iDrivesToScan.Find( aFolder ) != KErrNotFound )
+ {
+ iCurTable = iCurDB->OpenAllFilesTableL();
+ }
+ else
+ {
+ iCurTable = iCurDB->OpenDirectoryL( aFolder );
+ }
+ iCurList = iCurTable->CreateTableRepresentationL();
+ }
+
+// ---------------------------------------------------------------------------
+// Is this a media file we are interested in
+// ---------------------------------------------------------------------------
+//
+TInt CMPXHarvesterFileHandlerImp::IsMediaFileL( const TDesC& aFile )
+ {
+ MPX_DEBUG2("CMPXHarvesterFileHandlerImp::IsMediaFileL %S <---", &aFile);
+
+ TParsePtrC parse( aFile );
+ TInt index(KErrNotFound);
+ TInt count( iSupportedTypes.Count() );
+ for (TInt i=0; i <count; ++i)
+ {
+ TInt index2(KErrNotFound);
+ const CDesCArray& exts = iSupportedTypes[i]->Extensions();
+ if (!exts.FindIsq(parse.Ext(), index2))
+ { // found
+ index = i;
+ break;
+ }
+ }
+
+ if( index == KErrNotFound )
+ {
+ index = IsPlaylistFileL( aFile ) ? ETrue : KErrNotFound;
+ }
+
+ MPX_DEBUG2("CMPXHarvesterFileHandlerImp::IsMediaFileL %i --->", index);
+ return index;
+ }
+
+// ---------------------------------------------------------------------------
+// Is this a playlist file we are interested in
+// ---------------------------------------------------------------------------
+//
+TInt CMPXHarvesterFileHandlerImp::IsPlaylistFileL( const TDesC& aFile )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::IsPlaylistFileL <---");
+ return iPlaylistScanner->IsPlaylistFileL( aFile );
+ }
+
+// ---------------------------------------------------------------------------
+// Checks if this path is in the blocked list
+// ---------------------------------------------------------------------------
+//
+TBool CMPXHarvesterFileHandlerImp::IsPathBlockedL( const TDesC& aPath )
+ {
+ TInt count( iPathsToBlock.Count() );
+ TBool isBlocked(EFalse);
+ HBufC* buf = aPath.AllocLC();
+ TPtr ptr = buf->Des();
+ ptr.UpperCase();
+ for( TInt i=0; i<count; ++i )
+ {
+ if( ptr.Find( iPathsToBlock[i] ) != KErrNotFound )
+ {
+ isBlocked = ETrue;
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy( buf );
+ return isBlocked;
+ }
+
+// ---------------------------------------------------------------------------
+// Adds multiple files to the collection
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::AddFilesToCollectionL(
+ CMPXMediaArray& aMediaArray )
+ {
+ MPX_DEBUG1("MPXHarvesterFileHandlerImp::AddFilesToCollectionL <---");
+
+ // Add to collection db
+ CMPXCollectionMediator* mediator =
+ CMPXCollectionMediator::NewL( iCollectionUtil->Collection(),
+ this );
+ CleanupStack::PushL( mediator );
+ TRAPD( addErr, mediator->AddItemL( aMediaArray ) );
+ CleanupStack::PopAndDestroy( mediator );
+
+ // Now we add them to the harvester db
+ //
+ if( addErr == KErrNone )
+ {
+ TInt count = aMediaArray.Count();
+ for( TInt i=0; i<count; ++i )
+ {
+ const TDesC& path = aMediaArray.AtL(i)->ValueText( TMPXAttribute(
+ KMPXMediaIdGeneral,
+ EMPXMediaGeneralUri ) );
+ OpenDBForPathL( path );
+
+ // Collection
+ const TUid& collection = aMediaArray.AtL(i)->ValueTObjectL<TUid>(
+ TMPXAttribute( KMPXMediaIdGeneral,
+ EMPXMediaGeneralCollectionId ) );
+
+ // Last modified time
+ TTime lastModTime;
+ iFs.Modified( path, lastModTime );
+
+ // drm
+ TBool drm(EFalse);
+ if( aMediaArray[i]->IsSupported( TMPXAttribute(KMPXMediaIdDrm,
+ EMPXMediaDrmProtected) ) &&
+ aMediaArray.AtL(i)->ValueTObjectL<TBool>(TMPXAttribute(KMPXMediaIdDrm,
+ EMPXMediaDrmProtected)) )
+ {
+ TInt rights = EMPXDrmRightsFull;
+ if( aMediaArray[i]->IsSupported( TMPXAttribute(KMPXMediaIdDrm,
+ EMPXMediaDrmRightsStatus)) )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFilesToCollectionL -- getting rights");
+ rights = aMediaArray.AtL(i)->ValueTObjectL<TInt>(
+ TMPXAttribute(KMPXMediaIdDrm, EMPXMediaDrmRightsStatus) );
+ }
+ if( rights == EMPXDrmRightsMissing ||
+ rights == EMPXDrmRightsExpired )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddFilesToCollectionL -- rights missing/expired");
+ drm = ETrue;
+ }
+ }
+
+ TParsePtrC parse( path );
+ iCurTable->AddItemL( parse.DriveAndPath(),
+ parse.NameAndExt(),
+ lastModTime, collection.iUid, drm );
+
+ iAddedCount++;
+ }
+ }
+ else if ( addErr == KErrDiskFull )
+ {
+ User::Leave( KErrDiskFull );
+ }
+
+ MPX_DEBUG1("MPXHarvesterFileHandlerImp::AddFilesToCollectionL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Updates some files to the collection
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::UpdatesFilesInCollectionL(
+ CMPXMediaArray& aMediaArray )
+ {
+ MPX_DEBUG1("MPXHarvesterFileHandlerImp::UpdatesFilesInCollectionL <---");
+
+ // Do not update files which still do not have rights
+ //
+ TInt c( aMediaArray.Count() );
+ for( TInt i=0; i<c; ++i )
+ {
+ TInt rights = EMPXDrmRightsFull;
+
+ if( aMediaArray.AtL(i)->IsSupported( KMPXMediaDrmRightsStatus ) )
+ {
+ rights = aMediaArray.AtL(i)->ValueTObjectL<TInt>( KMPXMediaDrmRightsStatus );
+ }
+ if( rights == EMPXDrmRightsMissing )
+ {
+ aMediaArray.Remove(i);
+ i--;
+ c--;
+ }
+ }
+
+ // Update collection db
+ CMPXCollectionMediator* mediator =
+ CMPXCollectionMediator::NewL( iCollectionUtil->Collection(),
+ this );
+ CleanupStack::PushL( mediator );
+ TRAPD( setErr , mediator->SetItemL( aMediaArray ) );
+ CleanupStack::PopAndDestroy( mediator );
+
+ // Now we update them to the harvester db
+ //
+ if( setErr == KErrNone )
+ {
+ TInt count( aMediaArray.Count() );
+ for( TInt i=0; i<count; ++i )
+ {
+ const TDesC& filepath = aMediaArray.AtL(i)->ValueText( KMPXMediaGeneralUri );
+ OpenDBForPathL( filepath );
+
+ // Collection
+ TUid collection = aMediaArray.AtL(i)->ValueTObjectL<TUid>( KMPXMediaGeneralCollectionId );
+ // Last modified time
+ TTime lastModTime;
+ iFs.Modified( filepath, lastModTime );
+
+ // drm
+ TBool drm(EFalse);
+ if( aMediaArray.AtL(i)->IsSupported(KMPXMediaDrmProtected) &&
+ aMediaArray.AtL(i)->ValueTObjectL<TBool>(KMPXMediaDrmProtected) )
+ {
+ TInt rights = EMPXDrmRightsFull;
+
+ if( aMediaArray.AtL(i)->IsSupported(KMPXMediaDrmRightsStatus) )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::UpdateFilesToCollectionL -- getting rights");
+ rights = aMediaArray.AtL(i)->ValueTObjectL<TInt>(KMPXMediaDrmRightsStatus);
+ }
+ if( rights == EMPXDrmRightsMissing ||
+ rights == EMPXDrmRightsExpired )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::UpdateFilesToCollectionL -- updating rights");
+ drm = ETrue;
+ }
+ }
+
+ iCurTable->UpdateItemL( filepath, lastModTime, collection.iUid, drm, !iRefreshing );
+ }
+ }
+ else if ( setErr == KErrDiskFull )
+ {
+ User::Leave( KErrDiskFull );
+ }
+
+ MPX_DEBUG1("MPXHarvesterFileHandlerImp::UpdatesFilesInCollectionL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Updates the db based on mediator decisions
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleMediatorPathUpdatedL(
+ CMPXMedia*& aProperty,
+ TUid /*aOldPath*/ )
+ {
+ MPX_DEBUG1("MPXHarvesterFileHandlerImp::UpdatesFilesInCollectionL <---");
+
+ // Update harvester database based on mediator changes
+ //
+ const TDesC& filepath = aProperty->ValueText( KMPXMediaGeneralUri );
+ OpenDBForPathL( filepath );
+
+ // Collection
+ //
+ TUid colUid = aProperty->ValueTObjectL<TUid>( KMPXMediaGeneralCollectionId );
+
+ // Last modified time
+ //
+ TTime lastModTime;
+ iFs.Modified( filepath, lastModTime );
+
+ // Update DB, only if the record existed. No record means this is a new
+ // entry
+ if( iCurTable->CountL() )
+ {
+ iCurTable->UpdateItemL( lastModTime, colUid.iUid, !iRefreshing );
+ }
+
+ MPX_DEBUG1("MPXHarvesterFileHandlerImp::UpdatesFilesInCollectionL <---");
+ }
+
+// ---------------------------------------------------------------------------
+// Add playlists to the collection
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::AddPlaylistToCollectionL(
+ CMPXMediaArray& aMediaArray )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddPlaylistToCollectionL <---");
+
+ //
+ // add to collection one by one to avoid the following scenario:
+ // 2 playlists to add to the collection. The 1st one is successfully
+ // added but the 2nd playlist isn't. When AddL leaves, it does not
+ // indicate which one is successfully added and which one isn't.
+ // As a result, the successfully added playlist isn't added to
+ // harvester database and during the next scan, it will be picked
+ // up again and added to the database with auto-numbered title.
+ //
+ TInt count( aMediaArray.Count() );
+ for (TInt i=0; i<count; ++i)
+ {
+ CMPXMedia* media = aMediaArray.AtL(i);
+
+ TRAPD(addErr, DoCommandL( KMPXCommandIdCollectionAdd,
+ media->ValueTObjectL<TUid>(KMPXMediaGeneralCollectionId),
+ TMPXAttribute(KMPXCommandColAddMedia),
+ media,
+ ETrue ) );
+
+ // Now we add the item to the harvester db
+ //
+ if( addErr == KErrNone )
+ {
+ const TDesC& path =
+ media->ValueText( TMPXAttribute( KMPXMediaIdGeneral, EMPXMediaGeneralUri ) );
+ OpenDBForPathL( path );
+
+ // Collection
+ TUid collection =
+ media->ValueTObjectL<TUid>( TMPXAttribute( KMPXMediaIdGeneral, EMPXMediaGeneralCollectionId ) );
+
+ // Last modified time
+ TTime lastModTime;
+ iFs.Modified( path, lastModTime );
+
+ TParsePtrC parse( path );
+ iCurTable->AddItemL( parse.DriveAndPath(),
+ parse.NameAndExt(),
+ lastModTime, collection.iUid, EFalse );
+ iAddedCount++;
+ }
+ else if ( addErr == KErrDiskFull )
+ {
+ User::Leave( KErrDiskFull );
+ }
+ }
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::AddPlaylistToCollectionL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Update Playlists in the collection
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::UpdatePlaylistToCollectionL(
+ CMPXMediaArray& aMediaArray )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::UpdatePlaylistToCollectionL <---");
+
+ // Update the collection
+ //
+ TInt count( aMediaArray.Count() );
+ for (TInt i=0; i<count; ++i)
+ {
+ CMPXMedia* media = aMediaArray.AtL(i);
+
+ TRAPD( setErr, DoCommandL( KMPXCommandIdCollectionSet,
+ media->ValueTObjectL<TUid>(KMPXMediaGeneralCollectionId),
+ KMPXCommandColSetMedia,
+ media,
+ ETrue ) );
+
+ // Now we update them to the harvester db
+ //
+ if( setErr == KErrNone )
+ {
+ const TDesC& filepath =
+ media->ValueText( TMPXAttribute( KMPXMediaIdGeneral, EMPXMediaGeneralUri ) );
+ OpenDBForPathL( filepath );
+
+ // Collection
+ const TUid& collection =
+ media->ValueTObjectL<TUid>( TMPXAttribute( KMPXMediaIdGeneral, EMPXMediaGeneralCollectionId ) );
+
+ // Last modified time
+ TTime lastModTime;
+ iFs.Modified( filepath, lastModTime );
+
+ iCurTable->UpdateItemL( filepath, lastModTime, collection.iUid, EFalse, !iRefreshing);
+ }
+ else if ( setErr == KErrDiskFull )
+ {
+ User::Leave( KErrDiskFull );
+ }
+ }
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::UpdatePlaylistToCollectionL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Handle low disk events
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleLowDiskEvent( TInt /*aDrive*/ )
+ {
+ // Cancel the scanning process, set low disk flag to true
+ iOutOfDisk = ETrue;
+ CancelScan();
+ }
+
+// ---------------------------------------------------------------------------
+// Handle Broken Links
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleBrokenLinkL( MDesCArray& aFileArray,
+ RArray<TInt>& aColIds ,
+ RPointerArray<CMPXHarvesterDB>& aDbs,
+ TInt aCount )
+ {
+ // Common local variables
+ //
+ RArray<TInt> contId;
+ CleanupClosePushL( contId );
+ contId.AppendL( KMPXMediaIdGeneral );
+ contId.AppendL( KMPXMediaIdContainer );
+
+ RArray<TInt> itemId;
+ CleanupClosePushL( itemId );
+ itemId.AppendL( KMPXMediaIdGeneral );
+
+ // Remove from Collection db
+ //
+ CMPXMediaArray* musicArray = CMPXMediaArray::NewL();
+ CleanupStack::PushL( musicArray );
+ CMPXMediaArray* podcastArray = CMPXMediaArray::NewL();
+ CleanupStack::PushL( podcastArray );
+
+ for(TInt j=0; j<aCount; ++j )
+ {
+ TPtrC uri(aFileArray.MdcaPoint(j));
+ TUid uid = TUid::Uid( aColIds[j] );
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleBrokenLinkL -- \
+ Want to remove an item");
+ MPX_DEBUG2("%S", &uri);
+ if (!(IsPlaylistFileL( uri )))
+ {
+ // Construct a CMPXMedia to represent the deleted object
+ CMPXMedia* media = CMPXMedia::NewL( itemId.Array() );
+ CleanupStack::PushL( media );
+ media->SetTObjectValueL<TMPXGeneralType>(KMPXMediaGeneralType,
+ EMPXItem);
+ media->SetTextValueL( KMPXMediaGeneralUri,
+ uri );
+ media->SetTObjectValueL<TMPXGeneralCategory>(KMPXMediaGeneralCategory,
+ EMPXSong );
+ media->SetTObjectValueL<TUid>( KMPXMediaGeneralCollectionId,
+ uid );
+ if( uid == iMusicCollectionId )
+ {
+ musicArray->AppendL( media );
+ }
+ else
+ {
+ podcastArray->AppendL( media );
+ }
+ CleanupStack::Pop( media ); // ownership xfer
+
+ // Cleanup harvester DB
+ aDbs[j]->DeleteFileL( uri );
+ }
+ else
+ {
+ OpenDBForPathL( uri );
+
+ // Last modified time
+ TTime lastModTime;
+ lastModTime.HomeTime();
+
+ iCurTable->UpdateItemL(uri, lastModTime, uid.iUid, EFalse);
+ }
+ }
+
+ // Package the media array and send to collection
+ //
+ if( musicArray->Count() )
+ {
+ CMPXMedia* rootMedia = CMPXMedia::NewL( contId.Array() );
+ CleanupStack::PushL( rootMedia );
+ rootMedia->SetTObjectValueL<TMPXGeneralType>( KMPXMediaGeneralType, EMPXGroup );
+ rootMedia->SetTObjectValueL<TMPXGeneralCategory>( KMPXMediaGeneralCategory, EMPXCollection );
+ rootMedia->SetCObjectValueL<CMPXMediaArray>( KMPXMediaArrayContents, musicArray );
+ rootMedia->SetTObjectValueL<TInt>( KMPXMediaArrayCount, musicArray->Count() );
+ DoRemoveL( rootMedia, iMusicCollectionId );
+ CleanupStack::PopAndDestroy( rootMedia );
+ }
+ if( podcastArray->Count() )
+ {
+ CMPXMedia* rootMedia = CMPXMedia::NewL( contId.Array() );
+ CleanupStack::PushL( rootMedia );
+ rootMedia->SetTObjectValueL<TMPXGeneralType>( KMPXMediaGeneralType, EMPXGroup );
+ rootMedia->SetTObjectValueL<TMPXGeneralCategory>( KMPXMediaGeneralCategory, EMPXCollection );
+ rootMedia->SetCObjectValueL<CMPXMediaArray>( KMPXMediaArrayContents, podcastArray );
+ rootMedia->SetTObjectValueL<TInt>( KMPXMediaArrayCount, podcastArray->Count() );
+ DoRemoveL( rootMedia, iPodcastCollectionId );
+ CleanupStack::PopAndDestroy( rootMedia );
+ }
+
+ // Cleanup
+ //
+ CleanupStack::PopAndDestroy( podcastArray );
+ CleanupStack::PopAndDestroy( musicArray );
+
+ contId.Reset();
+ itemId.Reset();
+ CleanupStack::PopAndDestroy( &itemId );
+ CleanupStack::PopAndDestroy( &contId );
+ }
+
+// ---------------------------------------------------------------------------
+// Parses cenrep setting for scan paths
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::ParseScanPathL()
+ {
+ // Gets the string from cenrep, use default if leave
+ // string should be in the form 'item1' 'item2'
+ //
+ TBuf<255> scanPath;
+ TBuf<255> blockPath;
+ CRepository* cenrep(NULL);
+ TRAPD( err, cenrep = CRepository::NewL( KCRUIDHarvesterFeatures ) );
+ if( err == KErrNone )
+ {
+ cenrep->Get( KHarvesterScanPathKey, scanPath );
+ cenrep->Get( KHarvesterBlockPathKey, blockPath );
+ delete cenrep;
+ }
+ else
+ {
+ scanPath = KDefaultScanPath;
+ blockPath = KDefaultBlockPath;
+ }
+
+ MPX_DEBUG2("ParseScanPathL scanPaths: %S", &scanPath);
+ MPX_DEBUG2("ParseScanPathL blockPaths: %S", &blockPath);
+ ::ExtractTokensL( scanPath, iDrivesToScan );
+ ::ExtractTokensL( blockPath, iPathsToBlock );
+ }
+
+// ---------------------------------------------------------------------------
+// Parses cenrep setting for container file types
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::ParseContainersL()
+ {
+ TBuf<255> containers;
+ CRepository* cenrep( NULL );
+ TRAPD( err, cenrep = CRepository::NewL( KCRUIDHarvesterFeatures ) );
+ if( err == KErrNone )
+ {
+ cenrep->Get( KHarvesterContainerKey, containers );
+ delete cenrep;
+ }
+ else
+ {
+ containers = KDefaultContainers;
+ }
+
+ MPX_DEBUG2("Container types: %S", &containers);
+ ::ExtractTokensL( containers, *iContainerTypes);
+ }
+
+// ---------------------------------------------------------------------------
+// Parses cenrep setting for automatic scan folders
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::ParseAutoScanL()
+ {
+ // Make sure we don't insert duplicates
+ iFolderMonitors.ResetAndDestroy();
+
+ TBuf<255> folders;
+ CRepository* cenrep( NULL );
+ TRAPD( err, cenrep = CRepository::NewL( KCRUIDHarvesterFeatures ) );
+ if( err == KErrNone )
+ {
+ err = cenrep->Get( KAutoScanDirectoryKey, folders );
+ delete cenrep;
+ }
+ if( err != KErrNone )
+ {
+ folders = KDefaultAutoScanFolder;
+ }
+
+ MPX_DEBUG2("AutoScanFolders: %S", &folders);
+
+ CDesCArrayFlat* array = new(ELeave) CDesCArrayFlat(2);
+ CleanupStack::PushL( array );
+ ::ExtractTokensL( folders, *array);
+
+ TInt count( array->Count() );
+ for( TInt i=0; i<count; ++i )
+ {
+ CMPXFolderMonitor* monitor = CMPXFolderMonitor::NewL( *this, iFs );
+ CleanupStack::PushL( monitor );
+ iFolderMonitors.AppendL( monitor ); // ownership xfer
+ CleanupStack::Pop( monitor );
+ monitor->StartL( array->MdcaPoint(i) );
+ }
+ CleanupStack::PopAndDestroy( array );
+ }
+
+// ---------------------------------------------------------------------------
+// Resets the scanning table and array
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::Reset()
+ {
+ delete iCurTable;
+ iCurTable = NULL;
+
+ if( iCurList )
+ {
+ iCurList->ResetAndDestroy();
+ delete iCurList;
+ iCurList = NULL;
+ }
+ iCurDB = NULL; // not owned
+ }
+
+// ---------------------------------------------------------------------------
+// Handles a new file added to the collection
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleNewItemL( const TDesC& aFileName )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleNewItemL new file");
+
+ // Add it to the database
+ //
+ if( IsPlaylistFileL( aFileName ) )
+ {
+ iPlaylistScanner->AddPlaylistToScanL( aFileName );
+ }
+ else
+ {
+ iMetadataScanner->AddNewFileToScanL( aFileName );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Handles broken items
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleBrokenItemsL()
+ {
+ // Add the item to the broken links list
+ //
+ if( iCurList )
+ {
+ TInt count( iCurList->Count() );
+ for( TInt i=0; i<count; ++i )
+ {
+ TPtrC filename = (*iCurList)[i]->iFile->Des();
+ TInt colId = (*iCurList)[i]->iColId;
+ iBrokenLink->AddBrokenLinkL( filename, colId, iCurDB );
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Handles Updated items
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleUpdatedItemL( const TDesC& aFile )
+ {
+ TBool playlist = IsPlaylistFileL( aFile );
+ if( playlist )
+ {
+ iPlaylistScanner->AddUpdatedPlaylistToScanL( aFile );
+ }
+ else
+ {
+ iMetadataScanner->AddModifiedFileToScanL( aFile );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Finds the associated collection for a file
+// ---------------------------------------------------------------------------
+//
+TInt CMPXHarvesterFileHandlerImp::CollectionForExtensionL( const TDesC& aFile )
+ {
+ TInt index = IsMediaFileL( aFile );
+ TInt val(0);
+ if( KErrNotFound != index )
+ {
+ const CMPXCollectionType& type = *iSupportedTypes[index];
+ val = type.Uid().iUid;
+ }
+ return val;
+ }
+
+// ---------------------------------------------------------------------------
+// Setup the internal variables when opening a path
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::OpenDBForPathL( const TDesC& aPath )
+ {
+ Reset();
+ TDriveNumber num = ::ExtractDrive( aPath );
+ iCurDB = &iDBManager->GetDatabaseL( num );
+ iCurTable = iCurDB->OpenFileL( aPath );
+ }
+
+// ---------------------------------------------------------------------------
+// Complete a refreshing event
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::DoCompleteRefreshL( TInt aErr )
+
+ {
+ // If no error or cancel, return the final number of items added
+ MPX_DEBUG2("Scan error %i", aErr );
+
+ // Reopen databases (in case we removed them for out of disk drives before scan)
+ iDBManager->OpenAllDatabasesL();
+
+ if( aErr == KErrNone )
+ {
+ // Commit the changes on databases in transaction
+ iDBManager->CommitL();
+ }
+ else
+ {
+ // Rollback the changes on databases in transaction
+ iDBManager->Rollback();
+ }
+
+ if( aErr == KErrNone || aErr == KErrCancel )
+ {
+ aErr = iAddedCount;
+ }
+
+ if (iFilteredDrivesToScan.Count() != iDrivesToScan.Count())
+ {
+ aErr = KErrDiskFull;
+ }
+
+ if( iRefreshing )
+ {
+ iCollectionUtil->Collection().NotifyL( EMcMsgRefreshEnd, aErr );
+ }
+ iRefreshCount--;
+ if ( iRefreshCount < 0 )
+ {
+ iRefreshCount = 0;
+ }
+ if( iCollectionUtil && (iRefreshCount == 0) )
+ {
+ iCollectionUtil->Close();
+ iCollectionUtil = NULL;
+ }
+ iRefreshing = EFalse;
+
+ // Cancel disk monitors
+ TInt c (iDiskMonitors.Count());
+ iOutOfDisk = EFalse;
+
+ for( TInt i=0; i<c; ++i )
+ {
+ iDiskMonitors[i]->Cancel();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Issue a command to the collection
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::DoCommandL( TInt aCommandId,
+ TUid aCollectionId,
+ const TMPXAttribute& aMediaAttribute,
+ CMPXMedia* aMedia,
+ TBool aSync )
+ {
+ CMPXCommand* cmd = CMPXCommand::NewL();
+ CleanupStack::PushL( cmd );
+
+ cmd->SetTObjectValueL( KMPXCommandGeneralId, aCommandId );
+ cmd->SetTObjectValueL( KMPXCommandGeneralCollectionId, aCollectionId.iUid );
+ cmd->SetTObjectValueL( KMPXCommandGeneralDoSync, aSync );
+ if( aMedia )
+ {
+ cmd->SetCObjectValueL<CMPXMedia>( aMediaAttribute, aMedia );
+ }
+
+
+ iCollectionUtil->Collection().CommandL( *cmd );
+ CleanupStack::PopAndDestroy( cmd );
+ }
+
+// ---------------------------------------------------------------------------
+// Remove an item from the collection
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::DoRemoveL( CMPXMedia* aMedia, TUid aCollectionId )
+ {
+ CMPXCommand* cmd = CMPXCommand::NewL();
+ CleanupStack::PushL( cmd );
+
+ cmd->SetTObjectValueL( KMPXCommandGeneralId, KMPXCommandIdCollectionRemoveMedia );
+ cmd->SetTObjectValueL( KMPXCommandGeneralDoSync, ETrue );
+ cmd->SetTObjectValueL( KMPXCommandCollectionRemoveMediaDeleteRecord, ETrue );
+ cmd->SetTObjectValueL( KMPXCommandGeneralCollectionId, aCollectionId.iUid );
+ cmd->SetCObjectValueL<CMPXMedia>( KMPXCommandCollectionRemoveMedia, aMedia );
+
+ iCollectionUtil->Collection().CommandL( *cmd );
+ CleanupStack::PopAndDestroy( cmd );
+ }
+
+// ---------------------------------------------------------------------------
+// Check DB logical synchronization
+// ---------------------------------------------------------------------------
+//
+TBool CMPXHarvesterFileHandlerImp::CheckDbInSyncL()
+ {
+ ASSERT(iCollectionUtil != NULL);
+ TBool needsync(EFalse);
+ RArray<TInt> dbDrives;
+
+ TInt dbCount(iDBManager->Count());
+ for(TInt i=0; i < dbCount; ++i)
+ {
+ TInt harv_count = 0; //records count from harvester database
+ TInt coll_count = 0; //records count from collection database
+
+ CMPXHarvesterDB& db = iDBManager->GetDatabaseL(i);
+ TDriveNumber drive = db.GetDbDrive();
+ harv_count = db.CountAllFilesL();
+
+ //get count from music db
+ coll_count = GetTrackCountL(drive,iMusicCollectionId.iUid,EMPXCollectionCountTotal);
+
+ if ( !iDisablePodcasting )
+ {
+ //get count from podcast db
+ coll_count += GetTrackCountL(drive,iPodcastCollectionId.iUid,EMPXCollectionCountTrack);
+ }
+
+ if(harv_count != coll_count)
+ {
+ needsync = ETrue;
+ dbDrives.Append(drive);
+ }
+ }
+
+ if(needsync)
+ {
+ iDbSynchronizer->Synchronize(dbDrives,iCollectionUtil);
+ }
+ dbDrives.Close();
+
+ return needsync;
+ }
+
+// ---------------------------------------------------------------------------
+// Idle callback from CPerioidic
+// ---------------------------------------------------------------------------
+//
+TInt CMPXHarvesterFileHandlerImp::Callback( TAny* aPtr )
+ {
+ TBool rtn(EFalse);
+ TRAP_IGNORE( rtn = ((CMPXHarvesterFileHandlerImp*)aPtr)->DoAutoScanL() ); //lint !e665
+ return rtn; // done
+ }
+
+// ---------------------------------------------------------------------------
+// Perform the automatic scan event
+// ---------------------------------------------------------------------------
+//
+TBool CMPXHarvesterFileHandlerImp::DoAutoScanL()
+ {
+ TBool again(EFalse);
+ // Make sure to create a collection utility instance if it has not been
+ //
+ if( !iCollectionUtil )
+ {
+ iCollectionUtil = MMPXCollectionUtility::NewL( NULL, KMusicPlayerUid );
+ }
+
+ if( !iRefreshing && !iSynchronizing )
+ {
+ // Add a path to scan
+ iRefreshCount++;
+ CancelScan();
+ Reset();
+ iFolderScanner->ScanL( iAutoScanPaths );
+
+ // Cleanup
+ iAutoScanPaths.Reset();
+ iIdle->Cancel();
+ }
+ else
+ {
+ again = ETrue;
+ }
+
+ return again;
+ }
+
+// ---------------------------------------------------------------------------
+// Get track count for given table in the db
+// ---------------------------------------------------------------------------
+//
+TInt CMPXHarvesterFileHandlerImp::GetTrackCountL(TDriveNumber aDrive,TInt aColDbId, TInt aColTable)
+ {
+ TInt count(0);
+
+ //get count from music db
+ CMPXCommand* cmdCountM = CMPXMedia::NewL();
+ CleanupStack::PushL(cmdCountM);
+ cmdCountM->SetTObjectValueL<TMPXCommandId>(KMPXCommandGeneralId, KMPXCommandCollectionGetCount);
+ cmdCountM->SetTObjectValueL<TBool>(KMPXCommandGeneralDoSync, ETrue);
+ cmdCountM->SetTObjectValueL<TInt>(KMPXCommandGeneralCollectionId, aColDbId);
+ cmdCountM->SetTObjectValueL<TInt>(KMPXCommandCollectionCountDrive, aDrive);
+ cmdCountM->SetTObjectValueL<TInt>(KMPXCommandCollectionCountTable, aColTable);
+
+ iCollectionUtil->Collection().CommandL(*cmdCountM);
+
+ // returned command should contain count
+ if (!cmdCountM->IsSupported(KMPXCommandCollectionCountValue))
+ {
+ User::Leave(KErrAbort);
+ }
+
+ count = cmdCountM->ValueTObjectL<TInt>(KMPXCommandCollectionCountValue);
+ CleanupStack::PopAndDestroy(cmdCountM);
+
+ return count;
+ }
+
+// ---------------------------------------------------------------------------
+// Event callback from MDRMEventObserver
+// ---------------------------------------------------------------------------
+//
+void CMPXHarvesterFileHandlerImp::HandleEventL( MDRMEvent* aEvent )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleEventL <---");
+ CDRMEventAddRemove *event = reinterpret_cast<CDRMEventAddRemove*>(aEvent);
+
+ if( event->Status() == ERightsObjectRecieved )
+ {
+ HBufC8 *url = event->GetContentIDL();
+ CleanupStack::PushL(url);
+ // Convert 8 bit data to 16 bit.
+ TBufC<ContentAccess::KMaxCafUniqueId> rightsCid;
+ TPtr cidPtr( rightsCid.Des() );
+ cidPtr.Copy( url->Des() );
+
+ // get list of files with DRM flag set
+ RPointerArray<CMPXHarvesterDbItem>* list = GetDrmFilesL();
+ CleanupStack::PushL( list );
+
+ // match incoming rights to the correct file
+ TBool found = EFalse;
+ for ( TInt i=0; i<list->Count(); i++ )
+ {
+ CMPXHarvesterDbItem* item = (*list)[i];
+ CContent* content = CContent::NewL( item->iFile->Des() );
+ CleanupStack::PushL( content );
+ CData* data = content->OpenContentL( EPeek );
+ CleanupStack::PushL( data );
+
+ // Get content ID from file
+ TInt err = KErrNone;
+ TPtr cid( NULL, 0 );
+ HBufC* uniqueId( HBufC::NewLC( ContentAccess::KMaxCafUniqueId ) );
+ cid.Set( uniqueId->Des() );
+ err = data->GetStringAttribute( ContentAccess::EContentID, cid );
+ if ( (err == KErrNone ) && (cid.Compare( cidPtr ) == 0) )
+ {
+ // Add file for metadata scanning
+ iMetadataScanner->AddModifiedFileToScanL( item->iFile->Des() );
+ found = ETrue;
+ }
+ CleanupStack::PopAndDestroy( 3 ); // uniqueId, data, content
+ }
+
+ // Start metadata scanning if match found
+ if ( found )
+ {
+ if( !iCollectionUtil )
+ {
+ iCollectionUtil = MMPXCollectionUtility::NewL( NULL, KMusicPlayerUid );
+ }
+ iMetadataScanner->Start();
+ }
+ list->ResetAndDestroy();
+ CleanupStack::PopAndDestroy( list );
+ CleanupStack::PopAndDestroy( url );
+ }
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::HandleEventL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Get a list of files with DRM flag set from the Harvester DB.
+// ---------------------------------------------------------------------------
+//
+RPointerArray<CMPXHarvesterDbItem>* CMPXHarvesterFileHandlerImp::GetDrmFilesL()
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::GetDrmFiles <---");
+ CMPXHarvesterDB* db=NULL; // Current db reference
+ CMPXHarvesterDatabaseTable* table=NULL; // owned, must delete
+ RPointerArray<CMPXHarvesterDbItem>* tempList=NULL;
+ RPointerArray<CMPXHarvesterDbItem>* drmFileList = new (ELeave) RPointerArray<CMPXHarvesterDbItem>;
+
+ CleanupStack::PushL( drmFileList );
+
+#ifdef RD_MULTIPLE_DRIVE
+ TDriveList driveList;
+ TInt driveCount(0);
+
+ // Get all visible drives
+ if ( KErrNone == DriveInfo::GetUserVisibleDrives(
+ iFs, driveList, driveCount ) )
+ {
+ for( TInt driveNum = EDriveA; driveNum <= EDriveZ; driveNum++ )
+ {
+ if ( driveList[driveNum] )
+ {
+ TDriveNumber drive = (TDriveNumber)driveNum;
+ // Get DRM files from database
+ db = &iDBManager->GetDatabaseL( drive );
+ table = db->OpenDrmFileL();
+ CleanupStack::PushL( table );
+ tempList = table->CreateTableRepresentationL();
+ CleanupStack::PushL( tempList );
+ // copy content to drm file list
+ for ( TInt i=0; i<tempList->Count(); i++ )
+ {
+ drmFileList->AppendL( (*tempList)[i] );
+ }
+ // reset
+ tempList->Reset();
+ CleanupStack::PopAndDestroy( tempList );
+ CleanupStack::PopAndDestroy( table );
+ }
+ }
+ }
+#else
+ //ensure drive E is ready
+ //otherwise GetDataBaseL will leave if MMC is removed
+ if ( IsDriveReady( EDriveE ) )
+ {
+ // Get DRM files from database in E drive
+ db = &iDBManager->GetDatabaseL( EDriveE );
+ table = db->OpenDrmFileL();
+ CleanupStack::PushL( table );
+ tempList = table->CreateTableRepresentationL();
+ CleanupStack::PushL( tempList );
+ // copy content to drm file list
+ for ( TInt i=0; i<tempList->Count(); i++ )
+ {
+ drmFileList->AppendL( (*tempList)[i] );
+ }
+ // reset
+ tempList->Reset();
+ CleanupStack::PopAndDestroy( tempList );
+ CleanupStack::PopAndDestroy( table );
+ }
+
+ // Get DRM files from database in C drive
+ db = &iDBManager->GetDatabaseL( EDriveC );
+ table = db->OpenDrmFileL();
+ CleanupStack::PushL( table );
+ tempList = table->CreateTableRepresentationL();
+ CleanupStack::PushL( tempList );
+ // copy content to iCurList
+ for ( TInt i=0; i<tempList->Count(); i++ )
+ {
+ drmFileList->AppendL( (*tempList)[i] );
+ }
+ tempList->Reset();
+ CleanupStack::PopAndDestroy( tempList );
+ CleanupStack::PopAndDestroy( table );
+#endif
+ CleanupStack::Pop( drmFileList );
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::GetDrmFiles --->");
+ return drmFileList;
+ }
+
+// ---------------------------------------------------------------------------
+// Verifies if aDrive is ready.
+// ---------------------------------------------------------------------------
+//
+TBool CMPXHarvesterFileHandlerImp::IsDriveReady( TDriveNumber aDrive )
+ {
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::IsDriveReady <---");
+
+ TDriveInfo driveInfo;
+ TInt error = iFs.Drive( driveInfo, aDrive );
+ TBool ready = ETrue;
+ if ( error != KErrNone )
+ {
+ ready = EFalse;
+ }
+ else if ( driveInfo.iDriveAtt == static_cast<TUint>( KDriveAbsent ) )
+ {
+ //aDrive is absent
+ ready = EFalse;
+ }
+ else
+ {
+ TVolumeInfo volumeInfo;
+ TInt errCode = iFs.Volume( volumeInfo, aDrive );
+ if( errCode != KErrNone )
+ {
+ //aDrive is ready for use
+ ready = EFalse;
+ }
+ }
+
+ MPX_DEBUG1("CMPXHarvesterFileHandlerImp::IsDriveReady --->");
+ return ready;
+ }
+
+// END OF FILE