diff -r 000000000000 -r a2952bb97e68 mmappcomponents/mmmtpdataprovider/src/cmmmtpdpmetadatampxaccess.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// from MPX +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ( attrib ) ); + TBuf 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( 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 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 ( 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(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 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( KMPXMediaGeneralId, + KMtpInvalidSongID ); + searchMedia->SetTextValueL( KMPXMediaGeneralDrive, iStoreRoot ); + + RArray 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( aWMPMediaID, aFlag ); + + searchMedia->SetTextValueL( KMPXMediaGeneralDrive, iStoreRoot ); + + RArray 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( 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( 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( + KMPXMediaArrayContents ); + + for ( TInt j = 0; j < foundItemCount; j++ ) + { + CMPXMedia* media = CMPXMedia::NewL( *(*foundArray)[j] ); + CleanupStack::PushL( media ); + media->SetTObjectValueL( + 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( 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( + KMPXMediaArrayContents ); + + for ( TInt j = 0; j < foundItemCount; j++ ) + { + CMPXMedia* media = CMPXMedia::NewL( *(*foundArray2)[j] ); + CleanupStack::PushL( media ); // + media + media->SetTObjectValueL( + 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 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( + KMPXMediaGeneralCategory, + EMPXSong ); + + // MPXMedia default types + media->SetTObjectValueL( 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 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( + 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( + KMPXMediaGeneralCategory, + EMPXSong ); + } + + // MPXMedia default types + media->SetTObjectValueL( 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 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( 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( attrib, uint32Data.Value() ); + PRINT1( _L( "MM MTP <> CMmMtpDpMetadataMpxAccess::SetMetadataValueL uint32 value = %u" ), uint32Data.Value() ); + } + break; + + case EMTPObjectPropCodeOriginalReleaseDate: + { + MMTPType::CopyL( aNewData, *textData ); + + TBuf 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 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( 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 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 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( 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 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( + KMPXMediaGeneralType, + EMPXItem ); + media->SetTObjectValueL( + 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( KMPXMediaGeneralDeleted, EFalse ); + media->SetTObjectValueL( KMPXMediaGeneralModified, EFalse ); + media->SetTObjectValueL( KMPXMediaGeneralSynchronized, ETrue ); + media->SetTObjectValueL( 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 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 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( 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 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( KMPXMediaGeneralType, + EMPXItem ); + media->SetTObjectValueL( KMPXMediaGeneralCategory, + EMPXPlaylist ); + // File Path + // + media->SetTextValueL( KMPXMediaGeneralUri, aFullFileName ); + + TParsePtrC parse( aFullFileName ); + + media->SetTextValueL( KMPXMediaGeneralDrive, parse.Drive() ); + media->SetTextValueL( KMPXMediaGeneralTitle, parse.Name() ); + media->SetTObjectValueL( 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 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( KMPXMediaGeneralType, + EMPXItem ); + media->SetTObjectValueL( 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 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( 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 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 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 ( 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 ( + 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 ( KMPXMediaGeneralId ); + + // find the media object that contains a list of songs in the playlist + RArray 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 ( KMPXMediaGeneralId, playlistId ); + + RArray 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 ( KMPXMediaArrayCount ); + if ( numOfRefs > 0 ) + { + if ( !foundMedia->IsSupported( KMPXMediaArrayContents ) ) + { + User::Leave( KErrNotSupported ); + } + + const CMPXMediaArray* refArray = foundMedia->Value ( + 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( 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( 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 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 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( KMPXMediaArrayCount ); + + delete foundMedia; + foundMedia = NULL; + + PRINT1( _L( "MM MTP <= CMmMtpDpMetadataMpxAccess::IsExist foundItemCount(%d)" ), foundItemCount ); + return ( foundItemCount > 0 ? ETrue : EFalse ); + } + +//end of file