--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmappcomponents/mmmtpdataprovider/src/cmmmtpdpmetadatampxaccess.cpp Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,1625 @@
+/*
+* Copyright (c) 2009 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: Meta data Mpx access
+*
+*/
+
+
+// from Symbian MTP
+#include <mtp/tmtptypeuint8.h>
+#include <mtp/tmtptypeuint16.h>
+#include <mtp/tmtptypeuint32.h>
+#include <mtp/tmtptypeuint64.h>
+#include <mtp/tmtptypeuint128.h>
+#include <mtp/cmtptypestring.h>
+#include <mtp/cmtptypearray.h>
+#include <mtp/cmtpobjectmetadata.h>
+#include <mtp/mmtpdataproviderframework.h>
+#include <mtp/mmtpreferencemgr.h>
+#include <mtp/mtpprotocolconstants.h>
+// from MPX
+#include <mpxmedia.h>
+#include <mpxmediaarray.h>
+#include <mpxmediamusicdefs.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxmediaaudiodefs.h>
+#include <mpxmediamtpdefs.h>
+#include <mpxmediacontainerdefs.h>
+#include <mpxcollectionhelperfactory.h>
+#include <mpxcollectionhelper.h>
+#include <pathinfo.h>
+
+#include "cmmmtpdpmetadatampxaccess.h"
+#include "mmmtpdplogger.h"
+#include "mmmtpdputility.h"
+#include "tmmmtpdppanic.h"
+
+static const TInt KMtpInvalidSongID = 0x1FFFFFFF;
+static const TInt KMtpChannelMono = 1;
+static const TInt KMtpChannelStereo = 2;
+static const TInt KMtpDateTimeStringLength = 15;
+static const TInt KMtpMaxStringLength = 255;
+static const TInt KMtpMaxDescriptionLength = 0x200;
+
+_LIT( KMtpDateTimeFormat, "%F%Y%M%DT%H%T%S" );
+_LIT( KMtpDateTimeConnector, "T" );
+_LIT( KEmptyText, "" );
+
+#ifdef _DEBUG
+_LIT( KMtpMpxPanic, "CMmMtpDpMetadataMpxAccess" );
+#endif
+
+CMmMtpDpMetadataMpxAccess* CMmMtpDpMetadataMpxAccess::NewL( RFs& aRfs,
+ MMTPDataProviderFramework& aFramework )
+ {
+ CMmMtpDpMetadataMpxAccess* self = new(ELeave) CMmMtpDpMetadataMpxAccess( aRfs, aFramework );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+CMmMtpDpMetadataMpxAccess::CMmMtpDpMetadataMpxAccess( RFs& aRfs,
+ MMTPDataProviderFramework& aFramework ):
+ iRfs( aRfs ),
+ iFramework( aFramework )
+ {
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::ConstructL
+// Second-phase
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::ConstructL()
+ {
+ // for performance measurement purpose
+#if defined(_DEBUG) || defined(MMMTPDP_PERFLOG)
+ iPerfLog = CMmMtpDpPerfLog::NewL( _L( "CMmMtpDpMetadataMpxAccess" ) );
+#endif
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::~CMmMtpDpMetadataMpxAccess
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMmMtpDpMetadataMpxAccess::~CMmMtpDpMetadataMpxAccess()
+ {
+ if ( iCollectionHelper )
+ {
+ iCollectionHelper->Close();
+ iCollectionHelper = NULL;
+ }
+
+ // for performance measurement purpose
+#if defined(_DEBUG) || defined(MMMTPDP_PERFLOG)
+ delete iPerfLog;
+#endif
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::GetObjectMetadataValueL
+// Gets a piece of metadata from the collection
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::GetObjectMetadataValueL( const TUint16 aPropCode,
+ MMTPType& aNewData,
+ const CMTPObjectMetaData& aObjectMetaData )
+ {
+ PRINT1( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::GetObjectMetadataValueL aPropCode = 0x%x" ), aPropCode );
+
+ // File Path
+ HBufC* suid = aObjectMetaData.DesC( CMTPObjectMetaData::ESuid ).AllocLC(); // + suid
+ TUint format = aObjectMetaData.Uint( CMTPObjectMetaData::EFormatCode );
+ TMPXGeneralCategory category = ( format == EMTPFormatCodeAbstractAudioVideoPlaylist ) ||
+ ( format == EMTPFormatCodeM3UPlaylist ) ? EMPXPlaylist : EMPXSong;
+
+ PERFLOGSTART( KMpxCollectionGetL );
+ const CMPXMedia& media = CollectionHelperL()->GetL( *suid, category );
+ PERFLOGSTOP( KMpxCollectionGetL );
+
+ CleanupStack::PopAndDestroy( suid ); // - suid
+
+ TMPXAttributeData attrib( MpxAttribFromPropL( media, aPropCode ) );
+ TBool isSupported = media.IsSupported( attrib );
+ PRINT1(_L( "MM MTP <> CMmMtpDpMetadataMpxAccess::GetObjectMetadataValueL isSupported = %d" ), isSupported);
+
+ if ( aPropCode != EMTPObjectPropCodeOriginalReleaseDate
+ && aPropCode != EMTPObjectPropCodeDRMStatus
+ && !isSupported )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ switch ( aPropCode )
+ {
+ case EMTPObjectPropCodeName:
+ case EMTPObjectPropCodeArtist:
+ case EMTPObjectPropCodeAlbumName:
+ case EMTPObjectPropCodeComposer:
+ case EMTPObjectPropCodeGenre:
+ case EMTPObjectPropCodeAlbumArtist:
+ {
+ if ( EMTPTypeString == aNewData.Type() )
+ {
+ ( ( CMTPTypeString& ) aNewData ).SetL( media.ValueText( attrib ) );
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ break;
+
+ case EMTPObjectPropCodeDescription:
+ {
+ HBufC* data;
+ data = media.ValueText( KMPXMediaGeneralComment ).AllocLC(); // + data
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::GetObjectMetadataValue data = %S" ), data );
+ if ( EMTPTypeAUINT16 == aNewData.Type() )
+ {
+ TInt len = data->Length();
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::GetObjectMetadataValue len = %d" ),len );
+ if( len != 0 )
+ {
+ for( TInt i = 0; i < len; i++ )
+ ( ( CMTPTypeArray& ) aNewData ).AppendUintL( (*data)[i] );
+ }
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ CleanupStack::PopAndDestroy( data ); // - data
+ }
+ break;
+
+ case EMTPObjectPropCodeDateModified:
+ case EMTPObjectPropCodeDateAdded:
+ case EMTPObjectPropCodeDateCreated:
+ {
+ TTime time( *media.Value<TInt64> ( attrib ) );
+ TBuf<KMtpDateTimeStringLength> timeStr;
+ time.FormatL( timeStr, KMtpDateTimeFormat );
+
+ if ( EMTPTypeString == aNewData.Type() )
+ {
+ ( ( CMTPTypeString & ) aNewData ).SetL( timeStr );
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::GetObjectMetadataValue - get DC4E DateAdded = %Ld" ), time.Int64() );
+ }
+ break;
+
+ case EMTPObjectPropCodeDuration:
+ case EMTPObjectPropCodeAudioBitRate:
+ case EMTPObjectPropCodeSampleRate:
+ case EMTPObjectPropCodeAudioWAVECodec:
+ {
+ if ( EMTPTypeUINT32 == aNewData.Type() )
+ {
+ ( ( TMTPTypeUint32& ) aNewData ).Set( *media.Value<TUint32>( attrib ) );
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ break;
+
+ case EMTPObjectPropCodeTrack:
+ {
+ TLex lex( media.ValueText( attrib ) );
+ TUint16 uint16( 0 );
+ lex.Val( uint16, EDecimal );
+
+ if ( EMTPTypeUINT16 == aNewData.Type() )
+ {
+ ( ( TMTPTypeUint16 & ) aNewData ).Set( uint16 );
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::GetObjectMetadataValue - get DC8B Track = %d" ), uint16 );
+ }
+ break;
+
+ case EMTPObjectPropCodeOriginalReleaseDate:
+ {
+ // Compose DateTime string in format YYYYMMDDTHHMMSS
+ TBuf<KMtpDateTimeStringLength> dateTime;
+ dateTime.Zero();
+
+ // NOTE: Handled specially, shouldn't leave like other property, following S60
+ if ( !isSupported )
+ {
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::GetObjectMetadataValue 0xDC99 date hasn't been set before" ) );
+ dateTime.Copy( KEmptyText );
+ }
+ else
+ {
+ TTime time = *media.Value<TInt64> ( attrib );
+#ifdef _DEBUG
+ RDebug::Print( _L( "MM MTP <> GetObjectMetadataValue 0xDC99 time = %Ld, Year = %d, Month = %d, Day = %d, Hour = %d, Minute = %d, Second = %d" ),
+ time.Int64(),
+ time.DateTime().Year(),
+ time.DateTime().Month(),
+ time.DateTime().Day(),
+ time.DateTime().Hour(),
+ time.DateTime().Minute(),
+ time.DateTime().Second() );
+#endif // _DEBUG
+ // Compose DateTime string in format YYYYMMDDTHHMMSS
+ dateTime.AppendNumFixedWidth( time.DateTime().Year(),
+ EDecimal,
+ 4 );
+ dateTime.AppendNumFixedWidth( time.DateTime().Month() + 1,
+ EDecimal,
+ 2 );
+ dateTime.AppendNumFixedWidth( time.DateTime().Day() + 1,
+ EDecimal,
+ 2 );
+ dateTime.Append( KMtpDateTimeConnector );
+ dateTime.AppendNumFixedWidth( time.DateTime().Hour(),
+ EDecimal,
+ 2 );
+ dateTime.AppendNumFixedWidth( time.DateTime().Minute(),
+ EDecimal, 2 );
+ dateTime.AppendNumFixedWidth( time.DateTime().Second(),
+ EDecimal, 2 );
+
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::GetObjectMetadataValue 0xDC99 dateString = %S" ), &dateTime );
+ }
+ if ( EMTPTypeString == aNewData.Type() )
+ {
+ ( ( CMTPTypeString & ) aNewData ).SetL( dateTime );
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ break;
+
+ case EMTPObjectPropCodeNumberOfChannels:
+ case EMTPObjectPropCodeDRMStatus:
+ if ( !isSupported)
+ {
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::GetObjectMetadataValue 0xDC9D date hasn't been set before" ) );
+ TInt16 zeroValue = 0x0;
+ ( ( TMTPTypeUint16 & ) aNewData ).Set( zeroValue );
+ }
+ else
+ {
+ if (EMTPTypeUINT16 == aNewData.Type() )
+ {
+ ( ( TMTPTypeUint16 & ) aNewData ).Set( *media.Value<TUint16>(attrib) );
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+ break;
+
+ default:
+ {
+ User::Leave( KErrNotSupported );
+ }
+ break;
+ }
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::GetObjectMetadataValueL" ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::CollectionHelperL
+// Returns the collection helper
+// ---------------------------------------------------------------------------
+//
+MMPXCollectionHelper* CMmMtpDpMetadataMpxAccess::CollectionHelperL()
+ {
+ PRINT( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::CollectionHelperL()" ) );
+
+ // This is for the case when drive is completely full but Music DB is not
+ // yet created. NewCollectionCachedHelperL() will attempt to create a
+ // DB file on the spot when MPX Collection helper is accessed. For the
+ // case of Music DB creation failure, it will be handled by MTP server
+ // as a General Error
+ if ( iCollectionHelper == NULL )
+ {
+ PERFLOGSTART(KMpxCollectionNewL);
+ iCollectionHelper = CMPXCollectionHelperFactory::NewCollectionCachedHelperL();
+ PERFLOGSTOP(KMpxCollectionNewL);
+
+ // Do a search for a song ID that does not exist
+ // This is to validate the presence of the media database.
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+
+ CMPXMedia* searchMedia = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( searchMedia ); // + searchMedia
+
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralType, EMPXItem );
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralCategory, EMPXSong );
+ searchMedia->SetTObjectValueL<TMPXItemId>( KMPXMediaGeneralId,
+ KMtpInvalidSongID );
+ searchMedia->SetTextValueL( KMPXMediaGeneralDrive, iStoreRoot );
+
+ RArray<TMPXAttribute> songAttributes;
+ CleanupClosePushL( songAttributes ); // + songAttributes
+ songAttributes.AppendL( KMPXMediaGeneralId );
+
+ CMPXMedia* foundMedia = NULL;
+
+ PERFLOGSTART( KMpxCollectionFindAllLValidate );
+ TRAPD( err, foundMedia = iCollectionHelper->FindAllL(
+ *searchMedia,
+ songAttributes.Array() ) );
+ PERFLOGSTOP( KMpxCollectionFindAllLValidate );
+
+ CleanupStack::PopAndDestroy( &songAttributes ); // - songAttributes
+ CleanupStack::PopAndDestroy( searchMedia ); // - searchMedia
+
+ CleanupStack::PushL( foundMedia ); // + foundMedia
+ if ( err != KErrNone )
+ {
+ PRINT1( _L("MM MTP <> CMmMtpDpMetadataMpxAccess::CollectionHelperL() Had err (%d) accessing the Music Database!!!"), err );
+ // Delete the collection helper for now
+ iCollectionHelper->Close();
+ iCollectionHelper = NULL;
+ User::Leave( KErrGeneral );
+ }
+ else
+ {
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::CollectionHelperL() Music Database successfully created and validated!!!" ) );
+ }
+
+ CleanupStack::PopAndDestroy( foundMedia ); // - foundMedia
+ }
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::CollectionHelperL()" ) );
+ return iCollectionHelper;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::FindWMPMediaLC
+// Finds Media with specific WMP values
+// ---------------------------------------------------------------------------
+//
+CMPXMedia* CMmMtpDpMetadataMpxAccess::FindWMPMediaLC( TMPXAttributeData aWMPMediaID,
+ TBool aFlag )
+ {
+ PRINT( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::FindWMPMediaLC" ) );
+
+ CMPXMedia* searchMedia = CMPXMedia::NewL();
+ CleanupStack::PushL( searchMedia ); // + searchMeida
+
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralType, EMPXGroup );
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralCategory, EMPXSong );
+ searchMedia->SetTObjectValueL<TBool>( aWMPMediaID, aFlag );
+
+ searchMedia->SetTextValueL( KMPXMediaGeneralDrive, iStoreRoot );
+
+ RArray<TMPXAttribute> songAttributes;
+ CleanupClosePushL( songAttributes ); // + songAttributes
+ songAttributes.AppendL( KMPXMediaGeneralUri );
+
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::FindWMPMediaLC searchMedia setup with no problems" ) );
+
+ CMPXMedia* foundMedia = CollectionHelperL()->FindAllL(
+ *searchMedia,
+ songAttributes.Array() );
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::FindWMPMediaLC foundMedia assigned from FindAllL" ) );
+
+ CleanupStack::PopAndDestroy( &songAttributes ); // - songAttributes
+ CleanupStack::PopAndDestroy( searchMedia ); // - searchMedia
+ CleanupStack::PushL( foundMedia ); // + foundMedia
+
+ if ( !foundMedia->IsSupported( KMPXMediaArrayCount ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+#ifdef _DEBUG
+ TInt foundItemCount = *foundMedia->Value<TInt>( KMPXMediaArrayCount );
+ PRINT1( _L( "MM MTP <> %d Media Objects found in the WMP search" ), foundItemCount );
+#endif
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::FindWMPMediaLC" ) );
+ return foundMedia;
+ }
+
+// ---------------------------------------------------------------------------
+// Update the Sync flag for those not synchronized, Update the Modified flag for those have been modified, and delete the stale
+// records for files that have been deleted.
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::UpdateMusicCollectionL()
+ {
+ PRINT( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::UpdateMusicCollectionL" ) );
+ CMPXMedia* foundMedia= NULL;
+ TInt foundItemCount( 0 );
+
+ // We Should Consider this!!!
+ // if (iWmpRoundTripUsed) // Only update values if they've been read by the PC...
+ // {
+ // Change flag on acquired content so they won't be reported twice
+
+ //when thousands of the file are being copied in with mass storage, and MTP is connected/disconnected for the first time
+ //updateing the sync bit cause a serious performance issue issue
+ //since our DP is not presistent, and we are not depedns on KMPXMediaGeneralSynchronized flag to tell whether a file is newly added or not
+ //reseting this flag is not needed in reality, comment out for now
+ /*foundMedia = FindWMPMediaLC( KMPXMediaGeneralSynchronized, EFalse );// + foundMedia
+
+ if ( !foundMedia->IsSupported( KMPXMediaArrayCount ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ foundItemCount = *foundMedia->Value<TInt>( KMPXMediaArrayCount );
+
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::UpdateMusicCollectionL found %d Media Objects" ), foundItemCount );
+
+ if ( foundItemCount )
+ {
+ if ( !foundMedia->IsSupported( KMPXMediaArrayContents ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ const CMPXMediaArray* foundArray = foundMedia->Value<CMPXMediaArray>(
+ KMPXMediaArrayContents );
+
+ for ( TInt j = 0; j < foundItemCount; j++ )
+ {
+ CMPXMedia* media = CMPXMedia::NewL( *(*foundArray)[j] );
+ CleanupStack::PushL( media );
+ media->SetTObjectValueL<TBool>(
+ KMPXMediaGeneralSynchronized,
+ ETrue );
+ // Update the song's metadata with the media object
+ PERFLOGSTART(KMpxCollectionSetL);
+ CollectionHelperL()->SetL( media );
+ PERFLOGSTOP(KMpxCollectionSetL);
+
+ CleanupStack::PopAndDestroy( media );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( foundMedia );// - foundMedia*/
+
+ //we are indeed depends on KMPXMediaGeneralModified for modified content to be report correctly
+ //hence it should be reset everytime to ensure integrity
+ // Change flag for files with updated metadata
+ PRINT( _L( "MM MTP <> Updating the mod bit for files..." ) );
+
+ foundMedia = FindWMPMediaLC( KMPXMediaGeneralModified, ETrue ); // + foundMedia
+
+ if ( !foundMedia->IsSupported( KMPXMediaArrayCount ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ foundItemCount = *foundMedia->Value<TInt>( KMPXMediaArrayCount );
+
+ PRINT1( _L( "MM MTP <> CMtpMpxMetadataAccess::UpdateMusicCollectionL found %d Media Objects" ), foundItemCount );
+
+ if ( foundItemCount )
+ {
+ if ( !foundMedia->IsSupported( KMPXMediaArrayContents ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ const CMPXMediaArray* foundArray2 = foundMedia->Value<CMPXMediaArray>(
+ KMPXMediaArrayContents );
+
+ for ( TInt j = 0; j < foundItemCount; j++ )
+ {
+ CMPXMedia* media = CMPXMedia::NewL( *(*foundArray2)[j] );
+ CleanupStack::PushL( media ); // + media
+ media->SetTObjectValueL<TBool>(
+ KMPXMediaGeneralModified,
+ EFalse );
+ // Update the song's metadata with the media object
+ PERFLOGSTART(KMpxCollectionSetL);
+ CollectionHelperL()->SetL( media );
+ PERFLOGSTOP(KMpxCollectionSetL);
+
+ CleanupStack::PopAndDestroy( media ); // - media
+ }
+ }
+
+ CleanupStack::PopAndDestroy( foundMedia ); // - foundMedia
+
+ //although as a non-presistent DP, we are not depending on KMPXMediaGeneralDeleted to report deleted file,
+ //however, mark as deleted entry should be cleanup to improve music db performance
+ // Delete stale records from the audio collection, for files that have been deleted.
+ // Records are deleted everytime in CloseSession to improve the audio database performance
+ // as there is NOT a separate database for deleted files.
+ PRINT( _L( "MM MTP <> Deleting metadata for deleted files" ) );
+
+ CollectionHelperL()->CleanupDeletedMediasL();
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::UpdateMusicCollectionL" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::RemoveL
+// Remove the file from MPX DB
+// -----------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::DeleteObjectL( const TDesC& aFullFileName,
+ TMPXGeneralCategory aCategory )
+ {
+ TRAPD( err, CollectionHelperL()->RemoveL( aFullFileName, aCategory ) );
+
+ if ( err == KErrNotFound )
+ {
+ // Ignore songs not found in MPX DB
+ PRINT1( _L( "MM MTP <> DeleteObjectL deletion failed: %S not found" ), &aFullFileName );
+ }
+ else if ( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::RenameRecordL
+// Rename the filename onto MPX DB
+// -----------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::RenameObjectL( const TDesC& aOldFileName,
+ const TDesC& aNewFileName,
+ TUint aFormatCode )
+ {
+ PRINT2( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::RenameObjectL aOldFileName = %S, aNewFileName = %S" ),
+ &aOldFileName, &aNewFileName );
+
+ TInt err = KErrNone;
+
+ if ( ( aFormatCode == EMTPFormatCodeAbstractAudioVideoPlaylist )
+ || ( aFormatCode == EMTPFormatCodeM3UPlaylist ) )
+ {
+ PRINT( _L( "MM MTP <> Playlist" ) );
+ TRAP( err, CollectionHelperL()->RenameL(
+ aOldFileName,
+ aNewFileName,
+ EMPXPlaylist ) );
+ }
+ else // Not a playlist
+ {
+ PRINT( _L( "MM MTP <> Non-Playlist" ) );
+ TRAP( err, CollectionHelperL()->RenameL( aOldFileName, aNewFileName, EMPXSong ) );
+ }
+
+ if ( KErrNotFound == err )
+ {
+ PRINT1( _L( "MM MTP <> Not found the %S in the MPX DB" ), &aOldFileName );
+ }
+ else if ( KErrNone != err )
+ {
+ User::Leave( err );
+ }
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::RenameObjectL" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL
+// Updated object metadata in MPX database
+// -----------------------------------------------------------------------------
+void CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL( const TUint16 aPropCode,
+ const MMTPType& aNewData,
+ const TDesC& aSuid )
+ {
+ PRINT2( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL aPropCode = 0x%x aSuid = %S" ),
+ aPropCode,
+ &aSuid );
+ CMPXMedia* media = NULL;
+
+ // Creat media properties for the song
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+ contentIDs.AppendL( KMPXMediaIdAudio );
+ contentIDs.AppendL( KMPXMediaIdMusic );
+ contentIDs.AppendL( KMPXMediaIdMTP );
+
+ media = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( media ); // + media
+
+ media->SetTObjectValueL<TMPXGeneralCategory>(
+ KMPXMediaGeneralCategory,
+ EMPXSong );
+
+ // MPXMedia default types
+ media->SetTObjectValueL<TMPXGeneralType>( KMPXMediaGeneralType, EMPXItem );
+
+ // Get file path
+ TParsePtrC parse( aSuid );
+ media->SetTextValueL( KMPXMediaGeneralUri, aSuid );
+ media->SetTextValueL( KMPXMediaGeneralDrive, parse.Drive() );
+
+ TRAPD( err, SetMetadataValueL( aPropCode, aNewData, *media ) );
+
+ if ( err == KErrNone )
+ {
+ SetStorageRootL( parse.Drive() );
+
+ // Update the song's metadata with the media object
+ PERFLOGSTART( KMpxCollectionSetL );
+ CollectionHelperL()->SetL( media );
+ PERFLOGSTOP( KMpxCollectionSetL );
+ }
+ else
+ {
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL ERROR = %d" ), err );
+
+ User::Leave( err );
+ }
+
+ CleanupStack::PopAndDestroy( media ); // - media
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL
+// Updated object metadata in MPX database
+// -----------------------------------------------------------------------------
+void CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL( const TUint16 aPropCode,
+ const MMTPType& aNewData,
+ const CMTPObjectMetaData& aObjectMetaData )
+ {
+ PRINT1( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL aPropCode = 0x%x" ), aPropCode );
+ CMPXMedia* media = NULL;
+
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+
+ TUint format = aObjectMetaData.Uint( CMTPObjectMetaData::EFormatCode );
+ if ( ( format == EMTPFormatCodeAbstractAudioVideoPlaylist )
+ || ( format == EMTPFormatCodeM3UPlaylist ) )
+ {
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL format is playlist" ) );
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+
+ media = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PushL( media ); // + media
+
+ media->SetTObjectValueL<TMPXGeneralCategory>(
+ KMPXMediaGeneralCategory,
+ EMPXPlaylist );
+ }
+ else
+ {
+ // Creat media properties for the song
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+ contentIDs.AppendL( KMPXMediaIdAudio );
+ contentIDs.AppendL( KMPXMediaIdMusic );
+ contentIDs.AppendL( KMPXMediaIdMTP );
+
+ media = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PushL( media ); // + media
+
+ media->SetTObjectValueL<TMPXGeneralCategory>(
+ KMPXMediaGeneralCategory,
+ EMPXSong );
+ }
+
+ // MPXMedia default types
+ media->SetTObjectValueL<TMPXGeneralType>( KMPXMediaGeneralType, EMPXItem );
+
+ // Get file path
+ HBufC* suid = aObjectMetaData.DesC( CMTPObjectMetaData::ESuid ).AllocLC(); // + suid
+ TParsePtrC parse( *suid );
+ media->SetTextValueL( KMPXMediaGeneralUri, *suid );
+ media->SetTextValueL( KMPXMediaGeneralDrive, parse.Drive() );
+ CleanupStack::PopAndDestroy( suid ); // - suid
+
+ SetMetadataValueL( aPropCode, aNewData, *media );
+
+ // Update the song's metadata with the media object
+ PERFLOGSTART(KMpxCollectionSetL);
+ CollectionHelperL()->SetL( media );
+ PERFLOGSTOP(KMpxCollectionSetL);
+
+ CleanupStack::PopAndDestroy( 2, &contentIDs ); // - media, contentIDs
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::SetObjectMetadataValueL" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::SetMetadataValueL
+// private, Set property value into MPX object according to property code
+// -----------------------------------------------------------------------------
+void CMmMtpDpMetadataMpxAccess::SetMetadataValueL( const TUint16 aPropCode,
+ const MMTPType& aNewData,
+ CMPXMedia& aMediaProp )
+ {
+ PRINT1( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::SetMetadataValueL aPropCode = 0x%x" ), aPropCode );
+ CMTPTypeString* textData = CMTPTypeString::NewLC(); // + textData
+ CMTPTypeArray* desData = NULL;
+ TMTPTypeUint16 uint16Data;
+ TMTPTypeUint32 uint32Data;
+
+ TMPXAttributeData attrib( MpxAttribFromPropL( aMediaProp, aPropCode ) );
+
+ switch ( aPropCode )
+ {
+ case EMTPObjectPropCodeName:
+ case EMTPObjectPropCodeArtist:
+ case EMTPObjectPropCodeGenre:
+ case EMTPObjectPropCodeAlbumName:
+ case EMTPObjectPropCodeComposer:
+ case EMTPObjectPropCodeAlbumArtist:
+ {
+ PRINT1( _L( "MM MTP <> SetMetadataValueL Before Copy, string length = %d" ), aNewData.Size() );
+ MMTPType::CopyL( aNewData, *textData );
+ PRINT1( _L( "MM MTP <> SetMetadataValueL string length = %d" ), textData->StringChars().Length() );
+ aMediaProp.SetTextValueL( attrib, textData->StringChars() );
+ HBufC* log = textData->StringChars().AllocL();
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL string = %S" ), log );
+ delete log;
+ log = NULL;
+ }
+ break;
+
+ case EMTPObjectPropCodeTrack:
+ {
+ MMTPType::CopyL( aNewData, uint16Data );
+ TBuf<KMtpMaxStringLength> data;
+ data.AppendNum( uint16Data.Value() );
+ aMediaProp.SetTextValueL( KMPXMediaMusicAlbumTrack, data );
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL Track = %S" ), &data );
+ }
+ break;
+
+ case EMTPObjectPropCodeNumberOfChannels:
+ {
+ MMTPType::CopyL( aNewData, uint16Data );
+ // Device currently supports types 1(mono) & 2(Stereo) only
+ if ( ( uint16Data.Value() != KMtpChannelMono )
+ && ( uint16Data.Value() != KMtpChannelStereo )
+ && ( uint16Data.Value() != 0 ) )// 0 not used
+ {
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL NumberOfChannels NOT SUPPORT!" ) );
+ User::Leave( KErrNotSupported );
+ }
+ aMediaProp.SetTObjectValueL<TUint32>( KMPXMediaAudioNumberOfChannels,
+ uint16Data.Value() );
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL NumberOfChannels = %u" ), uint16Data.Value() );
+ }
+ break;
+
+ case EMTPObjectPropCodeSampleRate:
+ case EMTPObjectPropCodeAudioWAVECodec:
+ case EMTPObjectPropCodeAudioBitRate:
+ case EMTPObjectPropCodeDuration:
+ {
+ MMTPType::CopyL( aNewData, uint32Data );
+ aMediaProp.SetTObjectValueL<TUint32>( attrib, uint32Data.Value() );
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL uint32 value = %u" ), uint32Data.Value() );
+ }
+ break;
+
+ case EMTPObjectPropCodeOriginalReleaseDate:
+ {
+ MMTPType::CopyL( aNewData, *textData );
+
+ TBuf<KMtpMaxStringLength> data;
+ data.Copy( textData->StringChars().Left( KMtpDateTimeStringLength ) );
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL 0xDC99 date = %S" ),
+ &data );
+ if ( data.Length() < KMtpDateTimeStringLength )
+ {
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL 0xDC99 date string is too short" ) );
+ break;
+ }
+
+ TLex dateBuf( data.Left( 4 ) );
+ TInt year;
+ dateBuf.Val( year );
+
+ dateBuf = data.Mid( 4, 2 );
+ TInt month;
+ dateBuf.Val( month );
+
+ dateBuf = data.Mid( 6, 2 );
+ TInt day;
+ dateBuf.Val( day );
+
+ dateBuf = data.Mid( 9, 2 );
+ TInt hour;
+ dateBuf.Val( hour );
+
+ dateBuf = data.Mid( 11, 2 );
+ TInt minute;
+ dateBuf.Val( minute );
+
+ dateBuf = data.Mid( 13, 2 );
+ TInt second;
+ dateBuf.Val( second );
+
+#ifdef _DEBUG
+ RDebug::Print( _L( "MM MTP <> SetMetadataValueL 0xDC99 dateTime Year = %d, Month = %d, Day = %d, Hour = %d, Minute = %d, Second = %d" ),
+ year, month, day, hour, minute, second );
+#endif // _DEBUG
+ TDateTime dateTime;
+ if ( ( month > 0 && month < 13 )
+ && ( day > 0 && day < 32 )
+ && ( hour >= 0 && hour < 60 )
+ && ( minute >= 0 && minute < 60 )
+ && ( second >= 0 && second < 60 ) )
+ {
+ // microsecond is ignored because MPX doesn't support it, following s60
+ dateTime.Set( year,
+ TMonth( --month ),
+ --day,
+ hour,
+ minute,
+ second,
+ 0 );
+ }
+ else
+ {
+ // date string syntax is wrong
+ User::Leave( KErrGeneral );
+ }
+ TTime time( dateTime );
+#ifdef _DEBUG
+ RDebug::Print( _L( "MM MTP <> SetMetadataValueL 0xDC99 time = %Ld, Year = %d, Month = %d, Day = %d, Hour = %d, Minute = %d, Second = %d"),
+ time.Int64(),
+ time.DateTime().Year(),
+ time.DateTime().Month(),
+ time.DateTime().Day(),
+ time.DateTime().Hour(),
+ time.DateTime().Minute(),
+ time.DateTime().Second() );
+#endif // _DEBUG
+ aMediaProp.SetTObjectValueL( KMPXMediaMusicYear, time.Int64() );
+ }
+ break;
+
+ case EMTPObjectPropCodeDescription:
+ {
+#ifdef __MUSIC_ID_SUPPORT
+ //WriteMusicIdsL(*longString);
+#else
+ desData = CMTPTypeArray::NewLC( EMTPTypeAUINT16 ); // + desData
+ MMTPType::CopyL( aNewData, *desData );
+ TUint length = desData->NumElements();
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL length = %d" ),
+ length );
+ if ( length != 0 )
+ {
+ TBuf<KMtpMaxDescriptionLength> text;
+ text.Zero();
+ for ( TUint i = 0; i < length; i++ )
+ text.Append( desData->ElementUint( i ) );
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL text = %S" ),
+ &text );
+ aMediaProp.SetTextValueL( KMPXMediaGeneralComment, text );
+ }
+ else
+ {
+ aMediaProp.SetTextValueL( KMPXMediaGeneralComment, KEmptyText );
+ }
+ CleanupStack::PopAndDestroy( desData ); // - desData
+#endif //__MUSIC_ID_SUPPORT
+ }
+ break;
+
+ case EMTPObjectPropCodeDRMStatus:
+ {
+ MMTPType::CopyL( aNewData, uint16Data );
+ aMediaProp.SetTObjectValueL<TUint16>( attrib, uint16Data.Value() );
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL DRM Status uint16 value = %u" ), uint16Data.Value() );
+ }
+ break;
+
+ default:
+ {
+ User::Leave( KErrNotSupported );
+ }
+ break;
+ }
+
+ CleanupStack::PopAndDestroy( textData ); // - textData
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::SetMetadataValueL" ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::AddSongL
+// Adds song info to the database
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::AddSongL( const TDesC& aFullFileName )
+ {
+ PRINT1( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::AddSongL aFullFileName = %S" ), &aFullFileName );
+
+ // Does a record already exist for this song?
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+
+ CMPXMedia* searchMedia = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( searchMedia ); // + searchMedia
+
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralType, EMPXItem );
+
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralCategory, EMPXSong );
+
+ searchMedia->SetTextValueL( KMPXMediaGeneralUri, aFullFileName );
+
+ RArray<TMPXAttribute> songAttributes;
+ CleanupClosePushL( songAttributes ); // + songAttributes
+ songAttributes.AppendL( KMPXMediaGeneralUri );
+
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::AddSongL searchMedia setup with no problems" ) );
+
+ PERFLOGSTART(KMpxCollectionFindAllLBeforeAdd);
+ CMPXMedia* foundMedia = CollectionHelperL()->FindAllL(
+ *searchMedia,
+ songAttributes.Array() );
+ PERFLOGSTOP(KMpxCollectionFindAllLBeforeAdd);
+
+ CleanupStack::PopAndDestroy( &songAttributes ); // - songAttributes
+ CleanupStack::PopAndDestroy( searchMedia ); // - searchMedia
+
+ CleanupStack::PushL( foundMedia ); // + foundMedia
+
+ if ( !foundMedia->IsSupported( KMPXMediaArrayCount ) )
+ {
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::AddSongL Not supported KMPXMediaArrayCount" ) );
+ User::Leave( KErrNotSupported );
+ }
+
+ TInt foundItemCount = *foundMedia->Value<TInt>( KMPXMediaArrayCount );
+
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::AddSongL %d Media Objects found in the WMP search" ), foundItemCount );
+
+ if ( foundItemCount > 1 )
+ {
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::AddSongL Multiple medias already exist in the collection. Error!!!" ) );
+ }
+ else
+ {
+ // Create media properties for the song
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::AddSongL Create media properties" ) );
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ) ; // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+ contentIDs.AppendL( KMPXMediaIdAudio );
+ contentIDs.AppendL( KMPXMediaIdMusic );
+ contentIDs.AppendL( KMPXMediaIdMTP );
+
+ CMPXMedia* media = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( media ); // + media
+
+ // MPXMedia default types
+ media->SetTObjectValueL<TMPXGeneralType>(
+ KMPXMediaGeneralType,
+ EMPXItem );
+ media->SetTObjectValueL<TMPXGeneralCategory>(
+ KMPXMediaGeneralCategory,
+ EMPXSong );
+ // File Path
+ //
+ TParsePtrC parse( aFullFileName );
+ media->SetTextValueL( KMPXMediaGeneralUri, aFullFileName );
+ media->SetTextValueL( KMPXMediaGeneralDrive, parse.Drive() );
+
+ if ( foundItemCount == 0 )
+ {
+ // Set default Metadata
+ SetDefaultL( *media );
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::AddSongL Default values set to Media" ) );
+ }
+
+ // Update MPX WMP Roundtrip Metadata of the media object
+ media->SetTObjectValueL<TBool>( KMPXMediaGeneralDeleted, EFalse );
+ media->SetTObjectValueL<TBool>( KMPXMediaGeneralModified, EFalse );
+ media->SetTObjectValueL<TBool>( KMPXMediaGeneralSynchronized, ETrue );
+ media->SetTObjectValueL<TUint>( KMPXMediaGeneralFlags,
+ KMPXMediaGeneralFlagsIsInvalid | KMPXMediaGeneralFlagsIsCorrupted );
+
+ if ( foundItemCount == 0 )
+ {
+ PERFLOGSTART(KMpxCollectionAddL);
+ CollectionHelperL()->AddL( media );
+ PERFLOGSTOP(KMpxCollectionAddL);
+
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::AddSongL Media added into collection" ) );
+ }
+ else
+ {
+ PERFLOGSTART(KMpxCollectionSetL);
+ CollectionHelperL()->SetL( media );
+ PERFLOGSTOP(KMpxCollectionSetL);
+
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::AddSongL Media metadata updated in collection" ) );
+ }
+
+ CleanupStack::PopAndDestroy( media ); // - media
+ }
+
+ CleanupStack::PopAndDestroy( foundMedia ); // - foundMedia
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::AddSongL" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::AddPlaylistL
+// Adds Playlist to Mpx DB
+// -----------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::AddPlaylistL( const TDesC& aFullFileName )
+ {
+ PRINT1( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::AddPlaylistL aFullFileName = %S" ), &aFullFileName );
+
+ // Does a record already exist for this playlist?
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+
+ CMPXMedia* searchMedia = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( searchMedia ); // + searchMedia
+
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralType, EMPXItem );
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralCategory, EMPXPlaylist );
+ searchMedia->SetTextValueL( KMPXMediaGeneralUri, aFullFileName );
+
+ RArray<TMPXAttribute> playlistAttributes;
+ CleanupClosePushL( playlistAttributes ); // + playlistAttributes
+ playlistAttributes.AppendL( KMPXMediaGeneralId );
+ playlistAttributes.AppendL( KMPXMediaGeneralTitle );
+ playlistAttributes.AppendL( KMPXMediaGeneralUri );
+
+ PERFLOGSTART(KMpxCollectionFindAllLBeforeAdd);
+ CMPXMedia* foundMedia = CollectionHelperL()->FindAllL( *searchMedia,
+ playlistAttributes.Array() );
+ PERFLOGSTOP(KMpxCollectionFindAllLBeforeAdd);
+
+ CleanupStack::PopAndDestroy( &playlistAttributes ); // - playlistAttributes
+ CleanupStack::PopAndDestroy( searchMedia ); // - searchMedia
+ CleanupStack::PushL( foundMedia ); // + foundMedia
+
+ if ( !foundMedia->IsSupported( KMPXMediaArrayCount ) )
+ User::Leave( KErrNotSupported );
+
+ TInt foundItemCount = *foundMedia->Value<TInt>( KMPXMediaArrayCount );
+
+ if ( foundItemCount != 0 )
+ {
+ PRINT( _L( "MM MTP <> Playlist Media already exists in the collection" ) );
+ }
+ else
+ {
+ // Creat media properties for the playlist
+ PRINT( _L( "MM MTP <> Create playlist media properties" ) );
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+
+ CMPXMedia* media = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( media ); // + media
+
+ CMPXMediaArray* playlistArray = CMPXMediaArray::NewL();
+ CleanupStack::PushL( playlistArray ); // + playlistArray;
+
+ // MPXMedia default types
+ media->SetTObjectValueL<TMPXGeneralType>( KMPXMediaGeneralType,
+ EMPXItem );
+ media->SetTObjectValueL<TMPXGeneralCategory>( KMPXMediaGeneralCategory,
+ EMPXPlaylist );
+ // File Path
+ //
+ media->SetTextValueL( KMPXMediaGeneralUri, aFullFileName );
+
+ TParsePtrC parse( aFullFileName );
+
+ media->SetTextValueL( KMPXMediaGeneralDrive, parse.Drive() );
+ media->SetTextValueL( KMPXMediaGeneralTitle, parse.Name() );
+ media->SetTObjectValueL<TBool>( KMPXMediaGeneralSynchronized, ETrue );
+ media->SetCObjectValueL( KMPXMediaArrayContents, playlistArray );
+ media->SetTObjectValueL( KMPXMediaArrayCount, playlistArray->Count() );
+
+ PERFLOGSTART(KMpxCollectionAddL);
+ CollectionHelperL()->AddL( media );
+ PERFLOGSTOP(KMpxCollectionAddL);
+
+ // Clear the array
+ CleanupStack::PopAndDestroy( playlistArray ); // - playlistArray
+
+ CleanupStack::PopAndDestroy( media ); // - media
+ }
+
+ CleanupStack::PopAndDestroy( foundMedia ); // - foundMedia
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::AddPlaylistL" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::SetPlaylistL
+// Set playlist to DB
+// -----------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::SetPlaylistL( const TDesC& aPlaylistFileName,
+ CDesCArray& aRefFileArray )
+ {
+ PRINT( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::SetPlaylistL" ) );
+ CMPXMediaArray* playlistArray = CMPXMediaArray::NewL();
+ CleanupStack::PushL( playlistArray ); // + playlistArray
+
+ TUint count = aRefFileArray.Count();
+ for ( TUint j = 0; j < count; j++ )
+ {
+ // if the file is video, skip it and continue
+ if ( MmMtpDpUtility::IsVideoL( aRefFileArray[j], iFramework ) )
+ {
+ continue;
+ }
+
+ // Creat media properties for the song
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+ contentIDs.AppendL( KMPXMediaIdAudio );
+ contentIDs.AppendL( KMPXMediaIdMusic );
+ contentIDs.AppendL( KMPXMediaIdMTP );
+
+ CMPXMedia* media = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( media ); // + media
+
+ // MPXMedia default types
+ media->SetTObjectValueL<TMPXGeneralType>( KMPXMediaGeneralType,
+ EMPXItem );
+ media->SetTObjectValueL<TMPXGeneralCategory>( KMPXMediaGeneralCategory,
+ EMPXSong );
+ // File Path
+ //
+ TParsePtrC parse( aRefFileArray[j] );
+ media->SetTextValueL( KMPXMediaGeneralUri, aRefFileArray[j] );
+ media->SetTextValueL( KMPXMediaGeneralDrive, parse.Drive() );
+
+ // Add media into array contents
+ playlistArray->AppendL( media );
+
+ CleanupStack::Pop( media ); // - media
+ }
+
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+
+ CMPXMedia* playlistMedia = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( playlistMedia ); // + playlistMedia
+
+ playlistMedia->SetTObjectValueL( KMPXMediaGeneralType, EMPXItem );
+
+ playlistMedia->SetTObjectValueL( KMPXMediaGeneralCategory, EMPXPlaylist );
+
+ playlistMedia->SetTextValueL( KMPXMediaGeneralUri, aPlaylistFileName );
+
+ TParsePtrC parse( aPlaylistFileName );
+ playlistMedia->SetTextValueL( KMPXMediaGeneralDrive, parse.Drive() );
+ playlistMedia->SetTObjectValueL<TBool>( KMPXMediaGeneralSynchronized,
+ ETrue );
+ playlistMedia->SetCObjectValueL( KMPXMediaArrayContents, playlistArray );
+ playlistMedia->SetTObjectValueL( KMPXMediaArrayCount,
+ playlistArray->Count() );
+
+ // Update the duplicate playlist(s) with the new playlist array
+ PERFLOGSTART(KMpxCollectionSetL);
+ CollectionHelperL()->SetL( playlistMedia );
+ PERFLOGSTOP(KMpxCollectionSetL);
+
+ CleanupStack::PopAndDestroy( playlistMedia ); // - playlistMedia
+
+ // Clear the array
+ CleanupStack::PopAndDestroy( playlistArray ); // - playlistArray
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::SetPlaylistL" ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::SetStorageRootL
+// Set storage root of the MPX DB
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::SetStorageRootL( const TDesC& aStorageRoot )
+ {
+ PRINT1( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::SetStorageRoot aStoreRoot = %S" ), &aStorageRoot );
+
+ // get the drive number
+ TParse pathParser;
+ User::LeaveIfError( pathParser.Set( aStorageRoot, NULL, NULL ) );
+ TChar driveChar( pathParser.Drive()[0] );
+
+ TInt driveNumber;
+ User::LeaveIfError( RFs::CharToDrive( driveChar, driveNumber ) );
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetStorageRoot drive number = %d" ), driveNumber );
+
+ // get root path
+ User::LeaveIfError( PathInfo::GetRootPath( iStoreRoot, driveNumber ) );
+
+ PRINT1( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::SetStorageRoot root path: %S" ), &iStoreRoot );
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::SetDefaultL
+// Sets all of the default media properties
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::SetDefaultL( CMPXMedia& aMediaProp )
+ {
+ PRINT( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::SetDefaultL" ) );
+ // Title
+ aMediaProp.SetTextValueL( KMPXMediaGeneralTitle, KNullDesC );
+ // Comment
+ aMediaProp.SetTextValueL( KMPXMediaGeneralComment, KNullDesC );
+ // Artist
+ aMediaProp.SetTextValueL( KMPXMediaMusicArtist, KNullDesC );
+ // Album
+ aMediaProp.SetTextValueL( KMPXMediaMusicAlbum, KNullDesC );
+ // Year
+ //aMediaProp.SetTextValueL(KMPXMediaMusicYear, KNullDesC); // should never set year to KNullDesC, it is a TInt64 value
+ // 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 );
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::SetDefaultL" ) );
+ }
+
+TMPXAttributeData CMmMtpDpMetadataMpxAccess::MpxAttribFromPropL( const CMPXMedia& aMedia,
+ const TUint16 aPropCode )
+ {
+ const TMetadataTable KMetadataTable[] =
+ {
+ { EMTPObjectPropCodeName, KMPXMediaGeneralTitle },
+ { EMTPObjectPropCodeArtist, KMPXMediaMusicArtist },
+ { EMTPObjectPropCodeAlbumName, KMPXMediaMusicAlbum },
+ { EMTPObjectPropCodeDateModified, KMPXMediaGeneralDate },
+ { EMTPObjectPropCodeDateAdded, KMPXMediaGeneralDate },
+ { EMTPObjectPropCodeDuration, KMPXMediaGeneralDuration },
+ { EMTPObjectPropCodeTrack, KMPXMediaMusicAlbumTrack },
+ { EMTPObjectPropCodeComposer, KMPXMediaMusicComposer },
+ { EMTPObjectPropCodeOriginalReleaseDate, KMPXMediaMusicYear },
+ { EMTPObjectPropCodeGenre, KMPXMediaMusicGenre },
+ { EMTPObjectPropCodeDRMStatus, KMPXMediaMTPDrmStatus },
+ { EMTPObjectPropCodeDescription, KMPXMediaGeneralComment },
+ { EMTPObjectPropCodeNumberOfChannels, KMPXMediaAudioNumberOfChannels },
+ { EMTPObjectPropCodeAudioBitRate, KMPXMediaAudioBitrate },
+ { EMTPObjectPropCodeSampleRate, KMPXMediaAudioSamplerate },
+ { EMTPObjectPropCodeAudioWAVECodec, KMPXMediaAudioAudioCodec },
+ { EMTPObjectPropCodeAlbumArtist, KMPXMediaMusicArtist }
+ };
+
+ TInt i = 0;
+ TInt count = sizeof( KMetadataTable ) / sizeof( KMetadataTable[0] );
+ while ( ( KMetadataTable[i].iPropCode != aPropCode )
+ && ( i < count ) )
+ {
+ i++;
+ }
+
+ if ( i == count )
+ {
+ // Not supported by MPX, shouldn't call this function
+ PRINT( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::MpxAttribFromPropL NOT SUPPORTED ATTRIBUTE" ) );
+ User::Leave( KErrNotSupported );
+ }
+
+ return KMetadataTable[i].iMpxAttrib;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::GetAllPlaylistL
+// Get all playlists from MPX database in the assigned store
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::GetAllPlaylistL( const TDesC& aStoreRoot,
+ CMPXMediaArray** aPlaylists )
+ {
+ PRINT( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::GetAllPlaylistL" ) );
+
+ SetStorageRootL( aStoreRoot );
+
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+
+ CMPXMedia* searchMedia = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( searchMedia ); // + searchMedia
+
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralType, EMPXItem );
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralCategory, EMPXPlaylist );
+ searchMedia->SetTextValueL( KMPXMediaGeneralDrive, iStoreRoot );
+
+ RArray<TMPXAttribute> playlistAttributes;
+ CleanupClosePushL( playlistAttributes ); // + playlistAttributes
+ playlistAttributes.AppendL( KMPXMediaGeneralId );
+ playlistAttributes.AppendL( KMPXMediaGeneralTitle );
+ playlistAttributes.AppendL( KMPXMediaGeneralUri );
+
+ PERFLOGSTART(KMpxCollectionGetPlaylist);
+ CMPXMedia* foundMedia = CollectionHelperL()->FindAllL( *searchMedia,
+ playlistAttributes.Array() );
+ PERFLOGSTOP(KMpxCollectionGetPlaylist);
+
+ CleanupStack::PopAndDestroy( &playlistAttributes ); // - playlistAttributes
+ CleanupStack::PopAndDestroy( searchMedia ); // - searchMedia
+ CleanupStack::PushL( foundMedia ); // + foundMedia
+
+ if ( !foundMedia->IsSupported( KMPXMediaArrayCount ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ TInt count = *foundMedia->Value<TInt> ( KMPXMediaArrayCount );
+
+ PRINT1( _L("MM MTP <> CMmMtpDpMetadataMpxAccess::GetAllPlaylistL [%d] playlists found in Playlist Database"), count );
+
+ if ( count > 0 )
+ {
+ if ( !foundMedia->IsSupported( KMPXMediaArrayContents ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ *aPlaylists = CMPXMediaArray::NewL( *( foundMedia->Value<CMPXMediaArray> (
+ KMPXMediaArrayContents ) ) );
+ }
+
+ CleanupStack::PopAndDestroy( foundMedia ); // - foundMedia
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::GetAllPlaylistL" ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::GetAllReferenceL
+// Get all references of specified playlist
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::GetAllReferenceL( CMPXMedia* aPlaylist,
+ CDesCArray& aReferences )
+ {
+ PRINT( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::GetAllReferenceL" ) );
+
+ __ASSERT_DEBUG( aPlaylist, User::Panic( KMtpMpxPanic, KErrArgument ) );
+
+ // Extract the playlist id from the found object
+ TUint32 playlistId = *(*aPlaylist).Value<TMPXItemId> ( KMPXMediaGeneralId );
+
+ // find the media object that contains a list of songs in the playlist
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+
+ CMPXMedia* searchMedia = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( searchMedia ); // + searchMedia
+
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralType, EMPXGroup );
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralCategory, EMPXSong );
+ searchMedia->SetTObjectValueL<TMPXItemId> ( KMPXMediaGeneralId, playlistId );
+
+ RArray<TMPXAttribute> songAttributes;
+ CleanupClosePushL( songAttributes ); // + songAttributes
+ songAttributes.AppendL( KMPXMediaGeneralId );
+ songAttributes.AppendL( KMPXMediaGeneralUri );
+
+ PERFLOGSTART(KMpxCollectionGetReference);
+ CMPXMedia* foundMedia = CollectionHelperL()->FindAllL( *searchMedia,
+ songAttributes.Array() );
+ PERFLOGSTOP(KMpxCollectionGetReference);
+
+ CleanupStack::PopAndDestroy( &songAttributes ); // - songAttributes
+ CleanupStack::PopAndDestroy( searchMedia ); // - searchMedia
+ CleanupStack::PushL( foundMedia ); // + foundMedia
+
+ if ( !foundMedia->IsSupported( KMPXMediaArrayCount ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ // Number of references
+ TInt numOfRefs = *foundMedia->Value<TInt> ( KMPXMediaArrayCount );
+ if ( numOfRefs > 0 )
+ {
+ if ( !foundMedia->IsSupported( KMPXMediaArrayContents ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ const CMPXMediaArray* refArray = foundMedia->Value<CMPXMediaArray> (
+ KMPXMediaArrayContents );
+
+ // Import the references
+ for ( TInt i = 0; i < numOfRefs; i++ )
+ {
+ const CMPXMedia* refMedia = ( *refArray )[i];
+
+ if ( !refMedia->IsSupported( KMPXMediaGeneralUri ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ // may replace the following 3 statements into the following:
+ // AppendL(refMedia->ValueText(KMPXMediaGeneralUri));
+ HBufC* musicFileLocation = refMedia->ValueText( KMPXMediaGeneralUri ).AllocLC();
+ aReferences.AppendL( *musicFileLocation );
+
+ PRINT1( _L("MM MTP <> CMmMtpDpMetadataMpxAccess::GetAllReferenceL, [%S] found from MPX db"), musicFileLocation );
+
+ CleanupStack::PopAndDestroy( musicFileLocation ); // - musicFileLocation
+ }
+ }
+
+ CleanupStack::PopAndDestroy( foundMedia ); // - foundMedia
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::GetAllReferenceL" ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::GetPlaylistNameL
+//
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::GetPlaylistNameL( CMPXMedia* aPlaylist,
+ TDes& aPlaylistName )
+ {
+ PRINT( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::GetPlaylistNameL" ) );
+
+ if ( !aPlaylist->IsSupported( KMPXMediaGeneralUri ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ aPlaylistName.Copy( aPlaylist->ValueText( KMPXMediaGeneralUri ) );
+
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::GetPlaylistNameL" ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::GetModifiedContentL
+// Get modified content
+// ---------------------------------------------------------------------------
+//
+void CMmMtpDpMetadataMpxAccess::GetModifiedContentL( TInt& arrayCount,
+ CDesCArray& aModifiedcontent )
+ {
+ PRINT( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::GetModifiedContentL" ) );
+ CMPXMedia* foundMedia;
+ TInt foundItemCount( 0 );
+ HBufC* musicFileLocation( NULL );
+
+ // Modified content
+ PRINT( _L( "MM MTP <> Modified contents are:" ) );
+
+ foundMedia = FindWMPMediaLC( KMPXMediaGeneralModified, ETrue ); // + foundMedia
+
+ if ( !foundMedia->IsSupported( KMPXMediaArrayCount ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ foundItemCount = *foundMedia->Value<TInt>( KMPXMediaArrayCount );
+
+ PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::GetModifiedContentL() found %d Media Objects" ), foundItemCount );
+
+ if ( foundItemCount )
+ {
+ if ( !foundMedia->IsSupported( KMPXMediaArrayContents ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ const CMPXMediaArray* foundArray = foundMedia->Value<CMPXMediaArray>( KMPXMediaArrayContents );
+
+ for ( TInt j = 0; j < foundItemCount; j++ )
+ {
+ CMPXMedia* media = CMPXMedia::NewL( *(*foundArray)[j] );
+ CleanupStack::PushL( media ); // + media
+
+ if ( !media->IsSupported( KMPXMediaGeneralUri ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ musicFileLocation = media->ValueText( KMPXMediaGeneralUri ).AllocLC(); // + musicFileLoaction
+
+ aModifiedcontent.AppendL( *musicFileLocation );
+ arrayCount++;
+ PRINT1( _L("arrayCount = %d"), arrayCount);
+
+ CleanupStack::PopAndDestroy( musicFileLocation ); // - musicFileLocation
+ CleanupStack::PopAndDestroy( media ); // - media
+ }
+ }
+
+ CleanupStack::PopAndDestroy( foundMedia ); // + foundMedia
+ PRINT( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::GetModifiedContentL" ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CMmMtpDpMetadataMpxAccess::IsExistL
+// if the playlsit exist in the MPX DB
+// ---------------------------------------------------------------------------
+//
+TBool CMmMtpDpMetadataMpxAccess::IsExistL( const TDesC& aSuid )
+ {
+ PRINT1( _L( "MM MTP => CMmMtpDpMetadataMpxAccess::IsExist aSuid(%S)" ), &aSuid );
+ RArray<TInt> contentIDs;
+ CleanupClosePushL( contentIDs ); // + contentIDs
+ contentIDs.AppendL( KMPXMediaIdGeneral );
+
+ CMPXMedia* searchMedia = CMPXMedia::NewL( contentIDs.Array() );
+ CleanupStack::PopAndDestroy( &contentIDs ); // - contentIDs
+ CleanupStack::PushL( searchMedia ); // + searchMedia
+
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralType, EMPXItem );
+ searchMedia->SetTObjectValueL( KMPXMediaGeneralCategory, EMPXPlaylist );
+ searchMedia->SetTextValueL( KMPXMediaGeneralUri, aSuid );
+
+ RArray<TMPXAttribute> playlistAttributes;
+ CleanupClosePushL( playlistAttributes ); // + playlistAttributes
+ playlistAttributes.AppendL( KMPXMediaGeneralId );
+ playlistAttributes.AppendL( KMPXMediaGeneralTitle );
+ playlistAttributes.AppendL( KMPXMediaGeneralUri );
+
+ CMPXMedia* foundMedia = CollectionHelperL()->FindAllL( *searchMedia,
+ playlistAttributes.Array() );
+
+ CleanupStack::PopAndDestroy( &playlistAttributes ); // - playlistAttributes
+ CleanupStack::PopAndDestroy( searchMedia ); // - searchMedia
+
+ if ( !foundMedia->IsSupported( KMPXMediaArrayCount ) )
+ User::Leave( KErrNotSupported );
+
+ TInt foundItemCount = *foundMedia->Value<TInt>( KMPXMediaArrayCount );
+
+ delete foundMedia;
+ foundMedia = NULL;
+
+ PRINT1( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::IsExist foundItemCount(%d)" ), foundItemCount );
+ return ( foundItemCount > 0 ? ETrue : EFalse );
+ }
+
+//end of file