/*
* 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