--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmappcomponents/harvester/metadataextractor/src/mpxmetadataextractor.cpp Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,828 @@
+/*
+* 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: Extracts metadata from a file
+* Version : %version: da1mmcf#38.1.4.2.6.1.5 % << Don't touch! Updated by Synergy at check-out.
+*
+*/
+
+
+#include <e32base.h>
+#include <badesca.h>
+#include <apgcli.h>
+#include <MetaDataUtility.h>
+#include <MetaDataFieldContainer.h>
+
+#ifdef RD_MPX_TNM_INTEGRATION
+#include <hash.h>
+#include <f32file.h>
+#include <sysutil.h>
+#include <thumbnailmanager.h>
+#endif //RD_MPX_TNM_INTEGRATION
+
+
+#include <mpxlog.h>
+#include <mpxmedia.h>
+#include <mpxcollectionpath.h>
+#include <mpxcollectiontype.h>
+#include <mpxdrmmediautility.h>
+
+#include <mpxmediamusicdefs.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxmediaaudiodefs.h>
+#include <mpxmediadrmdefs.h>
+#include <mpxmediamtpdefs.h>
+
+#include "mpxmetadataextractor.h"
+#include "mpxfileinfoutility.h"
+#ifdef RD_MPX_TNM_INTEGRATION
+_LIT( KImageFileType, "image/jpeg" );
+const TInt KMPXTimeoutTimer = 3000000; // 3 seconds
+const TInt KMPXMaxThumbnailRequest = 5;
+#endif //RD_MPX_TNM_INTEGRATION
+
+//Helper functions
+static void FindAndReplaceForbiddenChars(TDes& aString, TInt aLen)
+ {
+ MPX_ASSERT(aLen == aString.Length());
+
+ for (TInt i = 0; i < aLen; ++i)
+ {
+ if (aString[i] == TText('\t'))
+ {
+ aString[i] = TText(' ');
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CMPXMetadataExtractor::CMPXMetadataExtractor(
+ RFs& aFs,
+ RApaLsSession& aAppArc,
+ RPointerArray<CMPXCollectionType>& aTypes )
+ : iFs( aFs ),
+ iAppArc( aAppArc ),
+ iSupportedTypes( aTypes ),
+ iOutstandingThumbnailRequest(0),
+ iTNMBlockCount(0)
+ {
+
+ }
+
+
+// ---------------------------------------------------------------------------
+// 2nd Phase Constructor
+// ---------------------------------------------------------------------------
+//
+void CMPXMetadataExtractor::ConstructL()
+ {
+ iMetadataUtility = CMetaDataUtility::NewL();
+ iDrmMediaUtility = CMPXDrmMediaUtility::NewL();
+ iFileInfoUtil = CMPXFileInfoUtility::NewL();
+
+#ifdef RD_MPX_TNM_INTEGRATION
+ // Create Thumbnail Manager instance. This object is the observer.
+ iTNManager = CThumbnailManager::NewL( *this );
+ iTNManager->SetFlagsL( CThumbnailManager::EDefaultFlags );
+ iTNManager->SetQualityPreferenceL( CThumbnailManager::EOptimizeForQuality);
+ // create wait loop
+ iTNSyncWait = new (ELeave) CActiveSchedulerWait;
+ iTimer = CPeriodic::NewL( CActive::EPriorityIdle );
+#endif //RD_MPX_TNM_INTEGRATION
+ }
+
+// ---------------------------------------------------------------------------
+// Two-Phased Constructor
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CMPXMetadataExtractor* CMPXMetadataExtractor::NewL(
+ RFs& aFs,
+ RApaLsSession& aAppArc,
+ RPointerArray<CMPXCollectionType>& aTypes )
+ {
+ CMPXMetadataExtractor* self = new( ELeave ) CMPXMetadataExtractor( aFs,
+ aAppArc,
+ aTypes );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMPXMetadataExtractor::~CMPXMetadataExtractor()
+ {
+ delete iMetadataUtility;
+ delete iFileInfoUtil;
+ delete iDrmMediaUtility;
+#ifdef RD_MPX_TNM_INTEGRATION
+ delete iTNManager;
+ if (iTNSyncWait && iTNSyncWait->IsStarted() )
+ {
+ iTNSyncWait->AsyncStop();
+ }
+ delete iTNSyncWait;
+ delete iTimer;
+#endif //RD_MPX_TNM_INTEGRATION
+
+ MPX_DEBUG2("CMPXMetadataExtractor: TNM Block Count: %d ", iTNMBlockCount );
+ }
+
+// ---------------------------------------------------------------------------
+// Constructs a media properties object
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CMPXMetadataExtractor::CreateMediaL( const TDesC& aFile,
+ CMPXMedia*& aNewProperty,
+ TBool aMetadataOnly )
+ {
+ // make a copy of aFile
+ HBufC* fileName = HBufC::NewL(KMaxFileName);
+ CleanupStack::PushL( fileName );
+ fileName->Des().Append( aFile );
+ MPX_DEBUG2("CMPXMetadataExtractor::CreateMediaL %S <---", fileName );
+
+ RArray<TInt> contentIDs;
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+ contentIDs.AppendL( KMPXMediaIdAudio );
+ contentIDs.AppendL( KMPXMediaIdMusic );
+ contentIDs.AppendL( KMPXMediaIdDrm );
+ contentIDs.AppendL( KMPXMediaIdMTP );
+ aNewProperty = NULL;
+ CMPXMedia* media = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PushL( media );
+ contentIDs.Close();
+
+ // CMPXMedia default types
+
+ media->SetTObjectValueL<TMPXGeneralType>( KMPXMediaGeneralType,
+ EMPXItem );
+ media->SetTObjectValueL<TMPXGeneralCategory>( KMPXMediaGeneralCategory,
+ EMPXSong );
+
+ TParsePtrC parse( *fileName );
+
+ // Title, default is file name
+ media->SetTextValueL( KMPXMediaGeneralTitle,
+ parse.Name() );
+
+ // Default album track
+ media->SetTextValueL( KMPXMediaMusicAlbumTrack,
+ KNullDesC );
+
+ // Set the Mime Type and collection UID
+ //
+ if( !aMetadataOnly )
+ {
+ TInt index(KErrNotFound);
+ TInt count( iSupportedTypes.Count() );
+ for (TInt i=0; i <count; ++i)
+ {
+ TInt index2(KErrNotFound);
+ const CDesCArray& exts = iSupportedTypes[i]->Extensions();
+ const TDesC& ext = parse.Ext();
+ if (!exts.FindIsq(ext, index2))
+ { // found
+ index = i;
+ break;
+ }
+ }
+ if( KErrNotFound != index )
+ {
+ MPX_DEBUG1("CMPXMetadataExtractor::CreateMediaPropertiesL apparc <---" );
+ TInt mimeIndex = SupportedContainerTypeL( *fileName, index );
+ User::LeaveIfError( mimeIndex );
+ MPX_DEBUG1("CMPXMetadataExtractor::CreateMediaPropertiesL apparc --->" );
+
+ media->SetTextValueL( KMPXMediaGeneralMimeType,
+ iSupportedTypes[index]->Mimetypes()[mimeIndex] );
+
+ media->SetTObjectValueL( KMPXMediaGeneralCollectionId,
+ iSupportedTypes[index]->Uid() );
+ }
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+ else // other case use apparc to fetch and set mimetype
+ {
+ TDataType dataType;
+ TUid dummyUid(KNullUid);
+ iAppArc.AppForDocument(*fileName, dummyUid, dataType);
+ media->SetTextValueL( KMPXMediaGeneralMimeType,dataType.Des() );
+ }
+
+ // Use file handle here
+ //
+ RFile file;
+ TInt err = file.Open( iFs, *fileName, EFileRead | EFileShareReadersOrWriters );
+ CleanupClosePushL(file);
+
+ // Metadata related
+ //
+ if( err == KErrNone )
+ {
+ const TDesC& mimeType = media->ValueText( KMPXMediaGeneralMimeType );
+ HBufC8* mimeType8 = HBufC8::NewLC( mimeType.Length() );
+ mimeType8->Des().Append( mimeType );
+ TRAPD( metadataerror, iMetadataUtility->OpenFileL( file, *mimeType8 ) );
+ CleanupStack::PopAndDestroy( mimeType8 );
+
+ // No problem
+ if( KErrNone == metadataerror )
+ {
+ // Add TRAPD to capture exception KErrNoMemory.
+ //If album art size is too large, trap this exception and SetDefaultL.
+ //Fix EYLU-7ESE5L
+ TRAPD( err, SetMediaPropertiesL( *media, *fileName ) );
+ if ( KErrNoMemory == err )
+ {
+ SetDefaultL( *media );
+ }
+ }
+ else // Error, Set defaults
+ {
+ SetDefaultL( *media );
+ }
+
+ // Reset the utility
+ iMetadataUtility->ResetL();
+ }
+ else // Error, Set defaults
+ {
+ SetDefaultL( *media );
+ }
+
+ // Common properties that we can extract
+ //
+ SetExtMediaPropertiesL( *media, *fileName, aMetadataOnly, file, err );
+ CleanupStack::PopAndDestroy(&file);
+
+ // Set the pointers now that the object is ready
+ //
+ CleanupStack::Pop( media );
+ aNewProperty = media;
+
+ CleanupStack::PopAndDestroy( fileName );
+ MPX_DEBUG1("CMPXMetadataExtractor::CreateMediaPropertiesL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Sets all of the default media properties
+// ---------------------------------------------------------------------------
+//
+void CMPXMetadataExtractor::SetDefaultL( CMPXMedia& aMediaProp )
+ {
+ // Comment
+ aMediaProp.SetTextValueL( KMPXMediaGeneralComment,
+ KNullDesC );
+ // Artist
+ aMediaProp.SetTextValueL( KMPXMediaMusicArtist,
+ KNullDesC );
+ // Album
+ aMediaProp.SetTextValueL( KMPXMediaMusicAlbum,
+ KNullDesC );
+ // Year
+ aMediaProp.SetTObjectValueL<TInt64>( KMPXMediaMusicYear,
+ (TInt64) 0 );
+ // Track
+ aMediaProp.SetTextValueL( KMPXMediaMusicAlbumTrack,
+ KNullDesC );
+ // Genre
+ aMediaProp.SetTextValueL( KMPXMediaMusicGenre,
+ KNullDesC );
+ // Composer
+ aMediaProp.SetTextValueL( KMPXMediaMusicComposer,
+ KNullDesC );
+ // Album artFilename
+ aMediaProp.SetTextValueL( KMPXMediaMusicAlbumArtFileName,
+ KNullDesC );
+ // URL
+ aMediaProp.SetTextValueL( KMPXMediaMusicURL,
+ KNullDesC );
+ }
+
+// ---------------------------------------------------------------------------
+// Sets media object attributes from metadata utilities
+// ---------------------------------------------------------------------------
+//
+void CMPXMetadataExtractor::SetMediaPropertiesL( CMPXMedia& aMedia,
+ const TDesC& aFile )
+ {
+ MPX_DEBUG1("CMPXMetadataExtractor::SetMediaPropertiesL <---" );
+
+ const CMetaDataFieldContainer& metaCont =
+ iMetadataUtility->MetaDataFieldsL();
+ TInt count( metaCont.Count() );
+ for( TInt i=0; i<count; ++i )
+ {
+ TMetaDataFieldId fieldType;
+
+ HBufC* value = NULL;
+ TRAPD( err, value = metaCont.At( i, fieldType ).AllocL() );
+ CleanupStack::PushL(value);
+ if ( KErrNone != err )
+ {
+ CleanupStack::PopAndDestroy(value);
+ continue;
+ }
+
+ switch( fieldType )
+ {
+ case EMetaDataSongTitle:
+ {
+ TPtr valptr = value->Des();
+ valptr.Trim();
+ TInt vallen = value->Length();
+ if (vallen>0)
+ {
+ FindAndReplaceForbiddenChars(valptr, vallen);
+ aMedia.SetTextValueL(KMPXMediaGeneralTitle, *value);
+ }
+ break;
+ }
+ case EMetaDataArtist:
+ {
+ TPtr valptr = value->Des();
+ valptr.Trim();
+ TInt vallen = value->Length();
+ if (vallen>0)
+ {
+ FindAndReplaceForbiddenChars(valptr, vallen);
+ aMedia.SetTextValueL(KMPXMediaMusicArtist, *value);
+ }
+ break;
+ }
+ case EMetaDataAlbum:
+ {
+ TPtr valptr = value->Des();
+ valptr.Trim();
+ TInt vallen = value->Length();
+ if (vallen>0)
+ {
+ FindAndReplaceForbiddenChars(valptr, vallen);
+ aMedia.SetTextValueL(KMPXMediaMusicAlbum, *value );
+ }
+ break;
+ }
+ case EMetaDataYear:
+ {
+ // Perform the date time conversion
+ TLex lexer( *value );
+ TInt year( 0 );
+ lexer.Val( year );
+
+ // Convert from TInt -> TDateTime -> TTime -> TInt64
+ TDateTime dt;
+ dt.SetYear( year );
+ TTime time( dt );
+ aMedia.SetTObjectValueL<TInt64>( KMPXMediaMusicYear,
+ time.Int64() );
+ break;
+ }
+ case EMetaDataComment:
+ {
+ aMedia.SetTextValueL( KMPXMediaGeneralComment,
+ *value );
+ break;
+ }
+ case EMetaDataAlbumTrack:
+ {
+ aMedia.SetTextValueL( KMPXMediaMusicAlbumTrack,
+ *value );
+ break;
+ }
+ case EMetaDataGenre:
+ {
+ TPtr valptr = value->Des();
+ valptr.Trim();
+ TInt vallen = value->Length();
+ if (vallen>0)
+ {
+ FindAndReplaceForbiddenChars(valptr, vallen);
+ aMedia.SetTextValueL(KMPXMediaMusicGenre, *value);
+ }
+ break;
+ }
+ case EMetaDataComposer:
+ {
+ TPtr valptr = value->Des();
+ valptr.Trim();
+ TInt vallen = value->Length();
+ if (vallen>0)
+ {
+ FindAndReplaceForbiddenChars(valptr, vallen);
+ aMedia.SetTextValueL(KMPXMediaMusicComposer, *value);
+ }
+ break;
+ }
+ case EMetaDataUrl:
+ case EMetaDataUserUrl: // fall through
+ {
+ aMedia.SetTextValueL( KMPXMediaMusicURL,
+ *value );
+ break;
+ }
+ case EMetaDataJpeg:
+ {
+#ifdef RD_MPX_TNM_INTEGRATION
+ MPX_PERF_START(CMPXMetadataExtractor_SetMediaPropertiesL_JPEG_TNM);
+ HBufC8* value8 = MPXUser::Alloc8L(metaCont.At( i, fieldType ));
+ CleanupStack::PushL( value8 );
+ AddMediaAlbumArtL( aMedia, aFile, *value8 );
+ CleanupStack::Pop(value8);
+ MPX_PERF_END(CMPXMetadataExtractor_SetMediaPropertiesL_JPEG_TNM);
+#else //RD_MPX_TNM_INTEGRATION
+ aMedia.SetTextValueL( KMPXMediaMusicAlbumArtFileName,
+ aFile );
+#endif //RD_MPX_TNM_INTEGRATION
+ break;
+ }
+ case EMetaDataCopyright:
+ {
+ aMedia.SetTextValueL( KMPXMediaGeneralCopyright,
+ *value );
+ break;
+ }
+ case EMetaDataOriginalArtist: // fall through
+ case EMetaDataVendor: // fall through
+ case EMetaDataRating: // fall through
+ case EMetaDataUniqueFileIdentifier: // fall through
+ case EMetaDataDuration: // fall through
+ case EMetaDataDate: // fall through
+ {
+ // not used
+ break;
+ }
+ default:
+ {
+ //ASSERT(0);
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy(value);
+ }
+
+ MPX_DEBUG1("CMPXMetadataExtractor::SetMediaPropertiesL --->" );
+ }
+
+// ---------------------------------------------------------------------------
+// Sets extra media properties not returned by metadata utilities
+// ---------------------------------------------------------------------------
+//
+void CMPXMetadataExtractor::SetExtMediaPropertiesL( CMPXMedia& aProp,
+ const TDesC& aFile,
+ TBool aMetadataOnly,
+ RFile& aFileHandle,
+ TInt aFileErr )
+ {
+ MPX_DEBUG1("CMPXMetadataExtractor::SetExtMediaPropertiesL <---");
+
+ // DB Flags to set
+ //
+ TUint dbFlags(KMPXMediaGeneralFlagsSetOrUnsetBit);
+
+ // File Path
+ //
+ TParsePtrC parse( aFile );
+ aProp.SetTextValueL( KMPXMediaGeneralUri,
+ aFile );
+ aProp.SetTextValueL( KMPXMediaGeneralDrive,
+ parse.Drive() );
+
+ // DRM Rights
+ //
+ CMPXMedia* drm = NULL;
+ TRAPD( drmError, iDrmMediaUtility->InitL( aFile );
+ drm = CMPXMedia::NewL( *iDrmMediaUtility->GetMediaL( KMPXMediaDrmProtected.iAttributeId |
+ KMPXMediaDrmRightsStatus.iAttributeId ) );
+ );
+
+ TBool prot(EFalse);
+ if( drm )
+ {
+ CleanupStack::PushL( drm );
+ MPX_DEBUG1("CMPXMetadataExtractor::SetExtMediaPropertiesL -- is a drm file");
+ if( drm->IsSupported( KMPXMediaDrmProtected ) )
+ {
+ prot = drm->ValueTObjectL<TBool>( KMPXMediaDrmProtected );
+ MPX_DEBUG2("CMPXMetadataExtractor::SetExtMediaPropertiesL protected %i", prot);
+ }
+
+ TMPXMediaDrmRightsStatus status(EMPXDrmRightsFull);
+ if( drm->IsSupported( KMPXMediaDrmRightsStatus ) )
+ {
+ status = drm->ValueTObjectL<TMPXMediaDrmRightsStatus>(KMPXMediaDrmRightsStatus);
+ aProp.SetTObjectValueL<TInt>(KMPXMediaDrmRightsStatus, status );
+ MPX_DEBUG2("CMPXMetadataExtractor::SetExtMediaPropertiesL -- status %i", status);
+ }
+
+ // Set DB flags
+ dbFlags |= KMPXMediaGeneralFlagsIsDrmProtected;
+ if( status != EMPXDrmRightsFull && status != EMPXDrmRightsRestricted && status != EMPXDrmRightsPreview )
+ {
+ dbFlags |= KMPXMediaGeneralFlagsIsDrmLicenceInvalid;
+ }
+ CleanupStack::PopAndDestroy( drm );
+ }
+
+ // Trapped PV DRM error. If -46, we know the file has no rights
+ //
+ if( drmError == KErrPermissionDenied )
+ {
+ dbFlags |= KMPXMediaGeneralFlagsIsDrmLicenceInvalid;
+ }
+ else
+ {
+ User::LeaveIfError( drmError );
+ }
+
+ aProp.SetTObjectValueL<TBool>( KMPXMediaDrmProtected, prot );
+ aProp.SetTObjectValueL<TUint16>( KMPXMediaMTPDrmStatus, (TUint16)prot );
+
+ iDrmMediaUtility->Close();
+
+ // File Size
+ //
+ TInt size( 0 );
+ if( aFileErr == KErrNone )
+ {
+ aFileHandle.Size( size );
+ aProp.SetTObjectValueL<TInt>( KMPXMediaGeneralSize,
+ size );
+
+ // Duration, bitrate, samplerate, etc
+ //
+ if( !aMetadataOnly )
+ {
+ TRAPD(err2, iFileInfoUtil->OpenFileL(
+ aFileHandle,
+ aProp.ValueText(KMPXMediaGeneralMimeType)));
+ MPX_DEBUG2("CMPXMetadataExtractor::SetExtMediaPropertiesL, file info util error %i", err2);
+ if( KErrNone == err2 )
+ {
+ aProp.SetTObjectValueL<TUint>( KMPXMediaAudioBitrate,
+ iFileInfoUtil->BitRate() );
+ aProp.SetTObjectValueL<TUint>( KMPXMediaAudioSamplerate,
+ iFileInfoUtil->SampleRate() );
+ TInt64 duration = (TInt64) iFileInfoUtil->Duration().Int64() / 1000; // ms
+ aProp.SetTObjectValueL<TInt32>( KMPXMediaGeneralDuration,
+ duration );
+ MPX_DEBUG2("CMPXMetadataExtractor::SetExtMediaPropertiesL -- duration %i", duration);
+ }
+ }
+ }
+ else if( aFileErr == KErrNotFound || aFileErr == KErrPathNotFound )
+ {
+ dbFlags |= KMPXMediaGeneralFlagsIsInvalid;
+ }
+ // Finally set the db flag
+ //
+ aProp.SetTObjectValueL( KMPXMediaGeneralFlags,
+ dbFlags );
+
+ iFileInfoUtil->Reset();
+
+ MPX_DEBUG1("CMPXMetadataExtractor::SetExtMediaPropertiesL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Check to see if this file is a supported container
+// ---------------------------------------------------------------------------
+//
+TInt CMPXMetadataExtractor::SupportedContainerTypeL( const TDesC& aFile,
+ TInt aIndex )
+ {
+ TInt index(KErrNotFound);
+
+ TDataType dataType;
+ TUid dummyUid(KNullUid);
+ iAppArc.AppForDocument(aFile, dummyUid, dataType);
+
+ TInt index2(KErrNotFound);
+ const CDesCArray& mimeTypes = iSupportedTypes[aIndex]->Mimetypes();
+ if (!mimeTypes.FindIsq(dataType.Des(), index2))
+ { // found
+ index = index2;
+ }
+
+ return ( index == KErrNotFound ? KErrNotSupported : index );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMPXMetadataExtractor::ThumbnailPreviewReady
+// Callback but not used here
+// ---------------------------------------------------------------------------
+void CMPXMetadataExtractor::ThumbnailPreviewReady(
+ MThumbnailData& /*aThumbnail*/, TThumbnailRequestId /*aId*/ )
+ {
+ MPX_FUNC("CMPXMetadataExtractor::ThumbnailPreviewReady()");
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMPXMetadataExtractor::ThumbnailReady
+// Callback but not used here
+// ---------------------------------------------------------------------------
+void CMPXMetadataExtractor::ThumbnailReady( TInt /*aError*/,
+ MThumbnailData& /*aThumbnail*/, TThumbnailRequestId /*aId*/ )
+ {
+ MPX_FUNC("CMPXMetadataExtractor::ThumbnailReady()");
+ iOutstandingThumbnailRequest--;
+ if ( iOutstandingThumbnailRequest <= KMPXMaxThumbnailRequest )
+ {
+ StopWaitLoop();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Callback for timer.
+// ----------------------------------------------------------------------------
+TInt CMPXMetadataExtractor::TimeoutTimerCallback(TAny* aPtr)
+ {
+ MPX_FUNC("CMPXMetadataExtractor::TimeoutTimerCallback()");
+
+ CMPXMetadataExtractor* ptr =
+ static_cast<CMPXMetadataExtractor*>(aPtr);
+
+ // Timer expired before thumbnail callback occurred. Stop wait loop to unblock.
+ ptr->StopWaitLoop();
+ return KErrNone;
+ }
+
+// ----------------------------------------------------------------------------
+// Stop the wait loop.
+// ----------------------------------------------------------------------------
+void CMPXMetadataExtractor::StopWaitLoop()
+ {
+ MPX_FUNC("CMPXMetadataExtractor::StopWaitLoop()");
+ // Cancel timer
+ CancelTimeoutTimer();
+
+ // Stop wait loop to unblock.
+ if ( iTNSyncWait->IsStarted() )
+ {
+ MPX_DEBUG1("CMPXMetadataExtractor::StopWaitLoop(): Stopping the wait loop.");
+ iTNSyncWait->AsyncStop();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Cancel timer.
+// ----------------------------------------------------------------------------
+void CMPXMetadataExtractor::CancelTimeoutTimer()
+ {
+ MPX_FUNC("CMPXMetadataExtractor::CancelTimeoutTimer()");
+
+ // Cancel timer.
+ if ( iTimer && iTimer->IsActive() )
+ {
+ MPX_DEBUG1("CMPXMetadataExtractor::CancelTimeoutTimer(): Timer active, cancelling");
+ iTimer->Cancel();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Extract album art from a file and add to thumbnail manager.
+// ----------------------------------------------------------------------------
+EXPORT_C TInt CMPXMetadataExtractor::ExtractAlbumArtL( CMPXMedia* aMedia )
+ {
+ MPX_FUNC("CMPXMetadataExtractor::ExtractAlbumArtL()");
+ TInt err = KErrNone;
+
+ if ( !aMedia->IsSupported(KMPXMediaGeneralUri) )
+ {
+ return KErrArgument;
+ }
+
+ // Get full file name.
+ const TDesC& path = aMedia->ValueText(KMPXMediaGeneralUri);
+ MPX_DEBUG2("CMPXMetadataExtractor::ExtractAlbumArtL Filename:%S ", &path );
+
+ // create wanted fields array
+ RArray<TMetaDataFieldId> wantedFields;
+ CleanupClosePushL( wantedFields );
+ wantedFields.Append(EMetaDataJpeg);
+
+ // Open file
+ if ( aMedia->IsSupported(KMPXMediaGeneralMimeType) )
+ {
+ const TDesC& mimeType = aMedia->ValueText( KMPXMediaGeneralMimeType );
+ MPX_DEBUG2("CMPXMetadataExtractor::ExtractAlbumArtL MimeType:%S ", &mimeType );
+ HBufC8* mimeType8 = HBufC8::NewLC( mimeType.Length() );
+ mimeType8->Des().Append( mimeType );
+ TRAP( err, iMetadataUtility->OpenFileL( path, wantedFields, *mimeType8 ) );
+ CleanupStack::PopAndDestroy( mimeType8 );
+ }
+ else
+ {
+ TRAP( err, iMetadataUtility->OpenFileL( path, wantedFields ) );
+ }
+ CleanupStack::PopAndDestroy( &wantedFields );
+
+ if ( !err )
+ {
+ TRAP( err, GetMediaAlbumArtL( *aMedia, path ));
+ }
+
+ // Reset the utility
+ iMetadataUtility->ResetL();
+
+ return err;
+ }
+
+// ----------------------------------------------------------------------------
+// Set album art.
+// ----------------------------------------------------------------------------
+TInt CMPXMetadataExtractor::GetMediaAlbumArtL( CMPXMedia& aMedia,
+ const TDesC& aFile )
+ {
+ MPX_FUNC("CMPXMetadataExtractor::GetMediaAlbumArtL()");
+ TInt err = KErrNone;
+ // get metadata container.
+ const CMetaDataFieldContainer& metaCont = iMetadataUtility->MetaDataFieldsL();
+
+ TPtrC data = metaCont.Field( EMetaDataJpeg );
+
+ if ( data.Length() )
+ {
+ MPX_DEBUG1("CMPXMetadataExtractor::GetMediaAlbumArtL(): Album art exist.");
+#ifdef RD_MPX_TNM_INTEGRATION
+ HBufC8* value8 = MPXUser::Alloc8L( data );
+ CleanupStack::PushL( value8 );
+ AddMediaAlbumArtL( aMedia, aFile, *value8 );
+ CleanupStack::Pop(value8);
+#else // RD_MPX_TNM_INTEGRATION
+ aMedia.SetTextValueL( KMPXMediaMusicAlbumArtFileName, aFile );
+#endif // RD_MPX_TNM_INTEGRATION
+ }
+ else
+ {
+ err = KErrNotFound;
+ }
+
+ return err;
+ }
+
+// ----------------------------------------------------------------------------
+// Add album art to media object.
+// ----------------------------------------------------------------------------
+void CMPXMetadataExtractor::AddMediaAlbumArtL( CMPXMedia& aMedia,
+ const TDesC& aFile,
+ TDesC8& aValue )
+ {
+ MPX_FUNC("CMPXMetadataExtractor::AddMediaAlbumArtL()");
+#ifdef RD_MPX_TNM_INTEGRATION
+
+ // If thumbnail creation is ongoing, wait til it is done
+ if ( iOutstandingThumbnailRequest > KMPXMaxThumbnailRequest )
+ {
+ MPX_DEBUG1("CMPXMetadataExtractor::AddMediaAlbumArtL(): Thumbnail creation ongoing!");
+ iTNMBlockCount++;
+ // Cancel timer.
+ CancelTimeoutTimer();
+ // Start timer in case there is no callback from ThumbNail Manager.
+ iTimer->Start(
+ KMPXTimeoutTimer,
+ KMPXTimeoutTimer,
+ TCallBack(TimeoutTimerCallback, this ));
+
+ // Start wait loop until we get a callback from ThumbNail Manager.
+ if ( !iTNSyncWait->IsStarted() )
+ {
+ iTNSyncWait->Start();
+ }
+ }
+
+ aMedia.SetTextValueL( KMPXMediaMusicAlbumArtFileName, aFile );
+
+ TBuf<256> mimeType;
+ mimeType.Copy( KImageFileType );
+ CThumbnailObjectSource* source = CThumbnailObjectSource::NewLC(
+ &aValue, mimeType, aFile );
+ iTNManager->CreateThumbnails( *source );
+ CleanupStack::PopAndDestroy( source );
+ aMedia.SetTextValueL( KMPXMediaMusicOriginalAlbumArtFileName, aFile );
+ iOutstandingThumbnailRequest++;
+
+#endif // RD_MPX_TNM_INTEGRATION
+ }