mpxmusicplayer/metadatahandler/src/mpxmetadatahandlerimp.cpp
branchRCL_3
changeset 26 3de6c4cf6b67
equal deleted inserted replaced
25:14979e23cb5e 26:3de6c4cf6b67
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of metadata handler
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <bldvariant.hrh>
       
    20 #include <remconinterfaceselector.h>
       
    21 
       
    22 #include <bautils.h>
       
    23 #include <mpxplaybackutility.h>
       
    24 #include <mpxplaybackframeworkdefs.h>
       
    25 #include <mpxplaybackmessage.h>
       
    26 #include <data_caging_path_literals.hrh>
       
    27 #include <mpxmedia.h>
       
    28 #include <mpxmessagegeneraldefs.h>
       
    29 #include <mpxplaybackmessagedefs.h>
       
    30 #include <mpxmediageneraldefs.h>
       
    31 #include <mpxuser.h>
       
    32 #include <mpxlog.h>
       
    33 #include <playerinformationtarget.h>
       
    34 #include <remcongroupnavigationtarget.h>
       
    35 #include <utf.h>
       
    36 #include <remcon/avrcpspec.h>
       
    37 #include <mpxmediamusicdefs.h>
       
    38 #include <mpxcollectionplaylist.h>
       
    39 #include <mpxcollectionpath.h>
       
    40 #include <EqualizerConstants.h>
       
    41 #include <centralrepository.h>
       
    42 #include "mpxmetadatahandler.h"
       
    43 #include "mpxmetadatahandlerimp.h"
       
    44 
       
    45 // CONSTANTS
       
    46 const TInt KMPXOneSecInMilliSecs( 1000 );
       
    47 
       
    48 // Definition of remotely controllable application settings
       
    49 // The commented settings are not used here, included for reference.
       
    50 _LIT( KMPlayerSettingsDefs, "mplayeravrcpsettings.rsc" );
       
    51 const TInt KAvrcpEqualizerMode = 0x01;
       
    52 const TInt KAvrcpRepeatMode = 0x02;
       
    53 const TInt KAvrcpShuffleMode = 0x03;
       
    54 //const TInt KAvrcpScanMode = 0x04;
       
    55 
       
    56 const TInt KAvrcpOff = 0x01;
       
    57 const TInt KAvrcpOn = 0x02;
       
    58 
       
    59 // Off                      0x01
       
    60 //const TInt KAvrcpSingleTrackRepeat = 0x02;
       
    61 //const TInt KAvrcpAllTracksRepeat = 0x03;
       
    62 //const TInt KAvrcpGroupRepeat = 0x04;
       
    63 
       
    64 // Off                      0x01
       
    65 const TInt KAvrcpAllTracksShuffle = 0x02;
       
    66 //const TInt KAvrcpGroupShuffle = 0x03;
       
    67 
       
    68 // Extended settings defined for Music Player
       
    69 // Note that these are also defined in mplayeravrcpsettings.rss
       
    70 const TInt KAvrcpBassBoostMode = 0x80;
       
    71 const TInt KAvrcpStereoWideningMode = 0x81;
       
    72 
       
    73 const TUid KCRUidMusicPlayerSettings = {0x101FFCDC};
       
    74 const TUint32 KMPlayerEqPresetId = 0x00000001;
       
    75 
       
    76 
       
    77 // ======== MEMBER FUNCTIONS ========
       
    78 
       
    79 // ---------------------------------------------------------------------------
       
    80 // C++ default constructor can NOT contain any code, that might leave.
       
    81 // ---------------------------------------------------------------------------
       
    82 //
       
    83 CMPXMetaDataHandlerImp::CMPXMetaDataHandlerImp()
       
    84     {
       
    85     }
       
    86 
       
    87 // ---------------------------------------------------------------------------
       
    88 // Symbian 2nd phase constructor can leave.
       
    89 // ---------------------------------------------------------------------------
       
    90 //
       
    91 void CMPXMetaDataHandlerImp::ConstructL(CRemConInterfaceSelector &aInterfaceSelector)
       
    92     {
       
    93     MPX_FUNC( "CMPXMetaDataHandlerImp::ConstructL(CRemConInterfaceSelector)");
       
    94 
       
    95     iPlayerInformationTarget = CPlayerInfoTarget::NewL(aInterfaceSelector, 
       
    96                                                 iPlayerCapabilitiesObserver, 
       
    97                                                 iPlayerApplicationSettingsObserver, 
       
    98                                                 iPlayerEventsObserver, *this);
       
    99     iMediaInfoTarget = CRemConMediaInformationTarget::NewL( aInterfaceSelector, *this );
       
   100 
       
   101     iGroupNavigationTarget = CRemConGroupNavigationApiTarget::NewL( aInterfaceSelector, *this );
       
   102 
       
   103     // Get the playback utility instance from engine.
       
   104     iPlaybackUtility = MMPXPlaybackUtility::UtilityL( KPbModeDefault );
       
   105     iPlaybackUtility->AddObserverL( *this );
       
   106 
       
   107     MMPXSource* s = iPlaybackUtility->Source();
       
   108     if ( s )
       
   109         {
       
   110         RArray<TMPXAttribute> attrs;
       
   111         CleanupClosePushL(attrs);
       
   112         (void) attrs.Append( KMPXMediaGeneralTitle );
       
   113         (void) attrs.Append( KMPXMediaGeneralDuration );
       
   114         (void) attrs.Append( KMPXMediaGeneralId );
       
   115         (void) attrs.Append( KMPXMediaMusicArtist );
       
   116         (void) attrs.Append( KMPXMediaMusicAlbum );
       
   117         (void) attrs.Append( KMPXMediaMusicGenre );
       
   118         s->MediaL( attrs.Array(), *this, NULL );
       
   119         CleanupStack::PopAndDestroy( &attrs );
       
   120         }
       
   121 
       
   122     RFs fs;
       
   123     User::LeaveIfError( fs.Connect() );
       
   124     CleanupClosePushL( fs );
       
   125 
       
   126     TParse parse;   
       
   127     parse.Set( KMPlayerSettingsDefs, &KDC_RESOURCE_FILES_DIR, NULL );
       
   128     
       
   129     TFileName resourceFile( parse.FullName() );
       
   130 
       
   131     User::LeaveIfError( MPXUser::CompleteWithDllPath( resourceFile ) );
       
   132     BaflUtils::NearestLanguageFile( fs, resourceFile );
       
   133     CResourceFile* playerSettingsResourceFile = CResourceFile::NewLC( fs, resourceFile, 0, 0 );
       
   134     PlayerApplicationSettingsResourceInit::DefineAttributesL( *iPlayerApplicationSettingsObserver, *playerSettingsResourceFile );
       
   135     CleanupStack::PopAndDestroy( playerSettingsResourceFile );
       
   136     CleanupStack::PopAndDestroy( &fs );
       
   137 
       
   138         // Adding two optional events, mandatory ERegisterNotificationPlaybackStatusChanged 
       
   139         // and ERegisterNotificationTrackChanged are added by SOS.
       
   140     User::LeaveIfError( iPlayerCapabilitiesObserver->AddEvent(ERegisterNotificationPlaybackPosChanged));
       
   141     User::LeaveIfError( iPlayerCapabilitiesObserver->AddEvent(ERegisterNotificationPlayerApplicationSettingChanged));
       
   142 
       
   143     iEqPresetListener = CEqualizerPresetChangeListener::NewL(*this);
       
   144     iLastEqPresetId = iEqPresetListener->GetCurrentPresetL();
       
   145     iEqPresetListener->StartL();
       
   146     iTrackNumber = 0;
       
   147     iColId.iUid = -1;
       
   148     
       
   149     //Notify accessories that currently no track is playing.
       
   150     iPlayerEventsObserver->TrackChanged(MPlayerEventsObserver::KNoTrackSelected, 
       
   151         MPlayerEventsObserver::KPlaybackPositionUnknown);
       
   152     }
       
   153 
       
   154 // ---------------------------------------------------------------------------
       
   155 // Two-phased constructor.
       
   156 // ---------------------------------------------------------------------------
       
   157 //
       
   158 MMPXMetaDataHandler* CMPXMetaDataHandlerImp::NewL(CRemConInterfaceSelector &aInterfaceSelector)
       
   159     {
       
   160     CMPXMetaDataHandlerImp* self = new(ELeave)CMPXMetaDataHandlerImp();
       
   161     CleanupStack::PushL( self );
       
   162     self->ConstructL(aInterfaceSelector);
       
   163     CleanupStack::Pop(self);
       
   164 
       
   165     return self;
       
   166     }
       
   167 
       
   168 // ---------------------------------------------------------------------------
       
   169 // Destructor
       
   170 // ---------------------------------------------------------------------------
       
   171 //
       
   172 CMPXMetaDataHandlerImp::~CMPXMetaDataHandlerImp()
       
   173     {
       
   174     if( iEqPresetListener )
       
   175         {
       
   176         iEqPresetListener->Stop();
       
   177         delete iEqPresetListener;
       
   178         }
       
   179     if( iPlaybackUtility )
       
   180         {
       
   181         TRAP_IGNORE( iPlaybackUtility->RemoveObserverL( *this ) );
       
   182         iPlaybackUtility->Close();
       
   183         }
       
   184 
       
   185     delete iTrackTitle;
       
   186     delete iArtist;
       
   187     delete iAlbum;
       
   188     delete iGenre;
       
   189     delete iMetadataIter;
       
   190     }
       
   191 
       
   192 // ---------------------------------------------------------------------------
       
   193 // Handle playback message.
       
   194 // ---------------------------------------------------------------------------
       
   195 //
       
   196 void CMPXMetaDataHandlerImp::DoHandlePlaybackMessageL(
       
   197     const CMPXMessage& aMessage )
       
   198     {
       
   199     MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandlePlaybackMessageL(CMPXMessage)");
       
   200 
       
   201     TMPXMessageId id( aMessage.ValueTObjectL<TMPXMessageId>( KMPXMessageGeneralId ) );
       
   202     if ( KMPXMessagePbMediaChanged == id )
       
   203         {
       
   204         if ( aMessage.IsSupported( KMPXMessagePbMedia ) )
       
   205             {
       
   206             CMPXMedia* media( aMessage.Value<CMPXMedia>( KMPXMessagePbMedia ) );
       
   207             User::LeaveIfNull( media );
       
   208             iPlaybackPosition = 0;
       
   209             DoHandleMediaL( *media, KErrNone );
       
   210             }
       
   211         }
       
   212     else if ( KMPXMessageGeneral == id )
       
   213         {
       
   214         TInt type( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralType ));
       
   215         TInt data( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralData ));
       
   216         switch ( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralEvent ) )
       
   217             {
       
   218             case TMPXPlaybackMessage::EPropertyChanged:
       
   219                 {
       
   220                 TMPXPlaybackProperty property( static_cast<TMPXPlaybackProperty>( type ) );
       
   221                 TInt error( KErrNone );
       
   222                 DoHandlePropertyL( property, data, error );
       
   223                 break;
       
   224                 }
       
   225             case TMPXPlaybackMessage::EStateChanged:
       
   226                 {
       
   227                 MPX_DEBUG2( "CMPXMetaDataHandlerImp::HandlePlaybackMessageL - EStateChanged(%d)", type );
       
   228 
       
   229                 TMPXPlaybackState state = static_cast<TMPXPlaybackState>( type );
       
   230                 DoHandleStateChangedL( state );
       
   231                 break;
       
   232                 }
       
   233             case TMPXPlaybackMessage::EMediaChanged:
       
   234                 {
       
   235                 MMPXSource* s = iPlaybackUtility->Source();
       
   236                 if ( s )
       
   237                     {
       
   238                     RArray<TMPXAttribute> attrs;
       
   239                     CleanupClosePushL(attrs);
       
   240                     (void) attrs.Append( KMPXMediaGeneralTitle );
       
   241                     (void) attrs.Append( KMPXMediaGeneralDuration );
       
   242                     (void) attrs.Append( KMPXMediaGeneralId );
       
   243                     (void) attrs.Append( KMPXMediaMusicArtist );
       
   244                     (void) attrs.Append( KMPXMediaMusicAlbum );
       
   245                     (void) attrs.Append( KMPXMediaMusicGenre );
       
   246                     MPX_DEBUG1( "CMPXMetaDataHandlerImp::HandlePlaybackMessageL Media changed, calling MediaL to refresh" );
       
   247                     s->MediaL( attrs.Array(), *this, NULL );
       
   248                     CleanupStack::PopAndDestroy( &attrs );
       
   249                     }
       
   250                 break;
       
   251                 }
       
   252             default:
       
   253                 {
       
   254                 break;
       
   255                 }
       
   256             }
       
   257         }
       
   258     }
       
   259 
       
   260 // ---------------------------------------------------------------------------
       
   261 // Handle playback property.
       
   262 // ---------------------------------------------------------------------------
       
   263 //
       
   264 void CMPXMetaDataHandlerImp::DoHandlePropertyL(
       
   265     TMPXPlaybackProperty aProperty,
       
   266     TInt aValue,
       
   267     TInt aError )
       
   268     {
       
   269     MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandlePropertyL" );
       
   270     MPX_DEBUG4( "CMPXMetaDataHandlerImp::HandlePropertyL - Property(%d); Value(%d); Error(%d)", aProperty, aValue, aError );
       
   271 
       
   272     TInt attr = 0;
       
   273     TInt val = KAvrcpOff;
       
   274     if ( KErrNone == aError )
       
   275         {
       
   276         switch ( aProperty )
       
   277             {
       
   278             case EPbPropertyPosition:
       
   279                 {
       
   280                 iPlaybackPosition = aValue / KMPXOneSecInMilliSecs;
       
   281                     // AVRCP 1.3 - inform remote device of the new position 
       
   282                     // ( Todo: check that we don't call too often)
       
   283                 iPlayerEventsObserver->SetPlaybackPosition(aValue); // aPlaybackPosInMicroSeconds is converted to 32 bit value
       
   284                 break;
       
   285                 }
       
   286             case EPbPropertyRepeatMode:
       
   287                 {
       
   288                 attr = KAvrcpRepeatMode; // Repeat mode status
       
   289                     // TMPlayerRepeatMode values are in the same order as AVRCP 1.3, 
       
   290                     // but starting at 0 instead of 1.
       
   291                 val = (TInt) aValue + 1;
       
   292                 break;
       
   293                 }
       
   294             case EPbPropertyRandomMode:
       
   295                 {
       
   296                 attr = KAvrcpShuffleMode;    // Shuffle on/off status
       
   297                 TBool random = aValue;
       
   298                 if( random )
       
   299                     {
       
   300                     val = KAvrcpAllTracksShuffle;
       
   301                     }
       
   302                 break;
       
   303               }
       
   304             default:
       
   305                 {
       
   306                 break;
       
   307                 }
       
   308             }
       
   309         if( attr )
       
   310             {
       
   311             iPlayerApplicationSettingsObserver->SetAttributeL( attr, val );
       
   312             }
       
   313         }
       
   314     }
       
   315 
       
   316 // ---------------------------------------------------------------------------
       
   317 // Handle media properties.
       
   318 // Notes: The client is responsible for delete the object of aProperties.
       
   319 // ---------------------------------------------------------------------------
       
   320 //
       
   321 void CMPXMetaDataHandlerImp::DoHandleMediaL(
       
   322     const CMPXMedia& aMedia, TInt aError )
       
   323     {
       
   324     MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandleMediaL" );
       
   325 
       
   326     // Delete old title no matter there's error or not
       
   327     delete iTrackTitle;
       
   328     iTrackTitle = NULL;
       
   329     delete iArtist;
       
   330     iArtist = NULL;
       
   331     delete iAlbum;
       
   332     iAlbum = NULL;
       
   333     delete iGenre;
       
   334     iGenre = NULL;
       
   335     TInt lastTrackNumber = -1;
       
   336     if ( KErrNone == aError )
       
   337         {
       
   338         // Keep track of the current track's title
       
   339         iTrackTitle = aMedia.ValueText( KMPXMediaGeneralTitle ).AllocL();
       
   340         TInt *playingTime = aMedia.Value<TInt>( KMPXMediaGeneralDuration );
       
   341         if(playingTime)
       
   342             {
       
   343             iPlayingTime = *playingTime; // In milliseconds.
       
   344             }
       
   345         MMPXSource* s = iPlaybackUtility->Source();
       
   346         if ( s )
       
   347             {
       
   348             CMPXCollectionPlaylist* pl = s->PlaylistL();
       
   349             if( pl )
       
   350                 {
       
   351                 lastTrackNumber = pl->Path().Index() + 1; // What if PlaylistItemCount is zero?
       
   352                 delete pl;
       
   353                 }
       
   354             }
       
   355 
       
   356         iArtist = aMedia.ValueText( KMPXMediaMusicArtist ).AllocL();
       
   357         iAlbum = aMedia.ValueText( KMPXMediaMusicAlbum ).AllocL();
       
   358         iGenre = aMedia.ValueText( KMPXMediaMusicGenre ).AllocL();
       
   359 
       
   360         TUid colId = aMedia.ValueTObjectL<TUid>(KMPXMediaGeneralId);
       
   361 
       
   362         
       
   363         MPX_DEBUG2( "CMPXMetaDataHandlerImp::DoHandleMediaL - Track title(%S)", iTrackTitle);
       
   364         MPX_DEBUG4( "CMPXMetaDataHandlerImp::DoHandleMediaL - Artist(%S); Album(%S); Genre(%S)", iArtist, iAlbum, iGenre );
       
   365         MPX_DEBUG4( "CMPXMetaDataHandlerImp::DoHandleMediaL - Playing time(%d); Track number(%d); UID(%d)", iPlayingTime, lastTrackNumber, colId.iUid);
       
   366                 
       
   367         if ( colId.iUid != iColId.iUid || lastTrackNumber != iTrackNumber )
       
   368             {
       
   369             iColId = colId;
       
   370             iTrackNumber = lastTrackNumber;
       
   371             iPlayerEventsObserver->TrackChanged(iColId.iUid, iPlayingTime);
       
   372             
       
   373             if ( iMetadataIter )
       
   374                 {
       
   375                 SendCurrentlyPlayingMetadata( *iMetadataIter );
       
   376                 delete iMetadataIter;
       
   377                 iMetadataIter = NULL;
       
   378                 }
       
   379             }
       
   380         else
       
   381             {
       
   382             MPX_DEBUG1( "CMPXMetaDataHandlerImp::DoHandleMediaL DUPLICATE Trace Change Received" );
       
   383             }
       
   384         }
       
   385     }
       
   386 
       
   387 // ---------------------------------------------------------------------------
       
   388 // Handle playback state changed.
       
   389 // ---------------------------------------------------------------------------
       
   390 //
       
   391 void CMPXMetaDataHandlerImp::DoHandleStateChangedL(
       
   392     TMPXPlaybackState aState )
       
   393     {
       
   394     MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandleStateChangedL" );
       
   395     switch ( aState )
       
   396         {
       
   397         case EPbStateStopped:
       
   398             {
       
   399             iPlayerState = aState;
       
   400             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EStopped);
       
   401             break;
       
   402             }
       
   403         case EPbStatePlaying:
       
   404             iPlayerState = aState;
       
   405             // Start the time if needed, otherwise, update content if visible
       
   406             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EPlaying);
       
   407             break;
       
   408         case EPbStatePaused:
       
   409             {
       
   410             iPlayerState = aState;
       
   411             // Start the time if needed, otherwise, update content if visible
       
   412             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EPaused);
       
   413             break;
       
   414             }
       
   415         case EPbStateSeekingForward:
       
   416             {
       
   417             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EFwdSeek);
       
   418             break;
       
   419             }
       
   420         case EPbStateSeekingBackward:
       
   421             {
       
   422             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::ERevSeek);
       
   423             break;
       
   424             }
       
   425         default:
       
   426             {
       
   427             // do nothing
       
   428             break;
       
   429             }
       
   430         }
       
   431     }
       
   432 
       
   433 // ---------------------------------------------------------------------------
       
   434 // From MMPXPlaybackObserver
       
   435 // Handle playback message.
       
   436 // ---------------------------------------------------------------------------
       
   437 //
       
   438 void CMPXMetaDataHandlerImp::HandlePlaybackMessage(
       
   439     CMPXMessage* aMessage, TInt aError )
       
   440     {
       
   441     if ( aError == KErrNone && aMessage )
       
   442         {
       
   443         TRAP_IGNORE( DoHandlePlaybackMessageL( *aMessage ) );
       
   444         }
       
   445     }
       
   446 
       
   447 // ---------------------------------------------------------------------------
       
   448 // From MMPXPlaybackCallback
       
   449 // Handle playback property.
       
   450 // ---------------------------------------------------------------------------
       
   451 //
       
   452 void CMPXMetaDataHandlerImp::HandlePropertyL(
       
   453     TMPXPlaybackProperty aProperty,
       
   454     TInt aValue,
       
   455     TInt aError )
       
   456     {
       
   457     TRAP_IGNORE( DoHandlePropertyL( aProperty, aValue, aError ) );
       
   458     }
       
   459 
       
   460 // ---------------------------------------------------------------------------
       
   461 // From MMPXPlaybackCallback
       
   462 // Handle sub player names.
       
   463 // ---------------------------------------------------------------------------
       
   464 //
       
   465 void CMPXMetaDataHandlerImp::HandleSubPlayerNamesL(
       
   466     TUid /* aPlayer */,
       
   467     const MDesCArray* /* aSubPlayers */,
       
   468     TBool /* aComplete */,
       
   469     TInt /* aError */ )
       
   470     {
       
   471     MPX_FUNC( "CMPXMediaKeyHandlerImp::HandleSubPlayerNamesL" );
       
   472     }
       
   473 
       
   474 // ---------------------------------------------------------------------------
       
   475 // From MMPXPlaybackCallback
       
   476 // Handle media properties.
       
   477 // Notes: The client is responsible for delete the object of aMedia.
       
   478 // ---------------------------------------------------------------------------
       
   479 //
       
   480 void CMPXMetaDataHandlerImp::HandleMediaL(
       
   481     const CMPXMedia& aMedia, TInt aError )
       
   482     {
       
   483     MPX_FUNC( "CMPXMetaDataHandlerImp::HandleMediaL" );
       
   484     TRAP_IGNORE( DoHandleMediaL( aMedia, aError ) );
       
   485     }
       
   486 
       
   487 // ---------------------------------------------------------------------------
       
   488 // From MMPXCollectionPlaylistObserver
       
   489 // Handle collection playlist change.
       
   490 // Notes: aError values:
       
   491 // KErrNotFound - Playlist is updated, current item removed
       
   492 // KErrNone - Playlist is updated, current item is valid
       
   493 // KErrEof - Playlist is updated, current item removed and reached to the end of playlist
       
   494 // ---------------------------------------------------------------------------
       
   495 //
       
   496 void CMPXMetaDataHandlerImp::HandleCollectionPlaylistChange(TInt aError)
       
   497     {
       
   498     MPX_FUNC( "CMPXMetaDataHandlerImp::HandleCollectionPlaylistChange" );
       
   499 
       
   500     if( aError )
       
   501         {
       
   502             // Update the media item.
       
   503         MMPXSource* s = iPlaybackUtility->Source();
       
   504         if ( s )
       
   505             {
       
   506             RArray<TMPXAttribute> attrs;
       
   507                 // Failing the next operations here is not fatal.
       
   508             (void) attrs.Append( KMPXMediaGeneralTitle );
       
   509             (void) attrs.Append( KMPXMediaGeneralDuration );
       
   510             (void) attrs.Append( KMPXMediaGeneralId );
       
   511             (void) attrs.Append( KMPXMediaMusicArtist );
       
   512             (void) attrs.Append( KMPXMediaMusicAlbum );
       
   513             (void) attrs.Append( KMPXMediaMusicGenre );
       
   514                 // Ignore the leave. If this occurs, we just don't get 
       
   515                 // an updated media information for time being.
       
   516             TRAP_IGNORE(s->MediaL( attrs.Array(), *this, NULL ));
       
   517             attrs.Close();
       
   518             }
       
   519         }
       
   520     }
       
   521 
       
   522 // ---------------------------------------------------------------------------
       
   523 // From MPlayerApplicationSettingsNotify
       
   524 // This is called when the controller has changed a setting
       
   525 // ---------------------------------------------------------------------------
       
   526 //
       
   527 void CMPXMetaDataHandlerImp::MpasnSetPlayerApplicationValueL(
       
   528     const RArray<TInt>& aAttributeID, const RArray<TInt>& aAttributeValue )
       
   529     {
       
   530     MPX_FUNC( "CMPXMetaDataHandlerImp::MpasnSetPlayerApplicationValueL" );
       
   531 
       
   532     for( TInt i = 0; i < aAttributeID.Count(); i++ )
       
   533         {
       
   534         switch( aAttributeID[ i ] )
       
   535             {
       
   536             case KAvrcpEqualizerMode:
       
   537                 {
       
   538                 TInt equalizer = aAttributeValue[ i ] == KAvrcpOff ? KEqualizerPresetNone : iLastEqPresetId;
       
   539                 iEqPresetListener->ChangePresetL(equalizer);
       
   540 //                iLastEqPresetId = equalizer;
       
   541                 break;
       
   542                 }
       
   543             case KAvrcpRepeatMode:
       
   544                 {
       
   545                     // TMPlayerRepeatMode values are in the same order 
       
   546                     // as AVRCP 1.3, but starting at 0 instead of 1.
       
   547                 TInt repeat = aAttributeValue[ i ] - 1;
       
   548                 iPlaybackUtility->SetL(EPbPropertyRepeatMode, repeat);
       
   549                 break;
       
   550                 }
       
   551             case KAvrcpShuffleMode:
       
   552                 {
       
   553                 TBool random = aAttributeValue[ i ] == KAvrcpOff ? EFalse : ETrue;
       
   554                 iPlaybackUtility->SetL(EPbPropertyRandomMode, random);
       
   555                 break;
       
   556                 }
       
   557             case KAvrcpBassBoostMode:
       
   558                 {
       
   559                 TBool boost = aAttributeValue[ i ] == KAvrcpOff ? EFalse : ETrue;
       
   560 //                iSettingModel->SetBassBoostL( boost );
       
   561                 break;
       
   562                 }
       
   563             case KAvrcpStereoWideningMode:
       
   564                 {
       
   565                 TBool widening = aAttributeValue[ i ] == KAvrcpOff ? EFalse : ETrue;
       
   566 //                iSettingModel->SetStereoWideningL( widening );
       
   567                 break;
       
   568                 }
       
   569             default:
       
   570                 {
       
   571                 // Leaving results in sending an error back to the controller.
       
   572                 User::Leave( KErrNotSupported );
       
   573                 break;
       
   574                 }
       
   575             }
       
   576         }
       
   577     }
       
   578 
       
   579 // -----------------------------------------------------------------------------
       
   580 // Sends currently playing metadata.
       
   581 // see MrcmitoGetCurrentlyPlayingMetadata
       
   582 // -----------------------------------------------------------------------------
       
   583 //
       
   584 void CMPXMetaDataHandlerImp::SendCurrentlyPlayingMetadata( 
       
   585     TMediaAttributeIter& aAttributeIter )
       
   586     {
       
   587     MPX_FUNC( "CMPXMetaDataHandlerImp::SendCurrentlyPlayingMetadata" );
       
   588     const TInt KMaxMediaAttrLen = 300;  // >110 is required for AVRCP fragmentation
       
   589     TBuf8<KMaxMediaAttrLen> attrBuf;
       
   590     TMediaAttributeId attrId;
       
   591     aAttributeIter.Start();
       
   592     while( aAttributeIter.Next( attrId ) )
       
   593         {
       
   594         TInt err = KErrNotFound;
       
   595         HBufC* detail = NULL;
       
   596         TInt64 val = 0;
       
   597         switch( attrId )
       
   598             {
       
   599             case ETitleOfMedia:
       
   600                 {
       
   601                 detail = iTrackTitle;
       
   602                 break;
       
   603                 }
       
   604             case ENameOfArtist:
       
   605                 {
       
   606                 detail = iArtist;
       
   607                 break;
       
   608                 }
       
   609             case ENameOfAlbum:
       
   610                 {
       
   611                 detail = iAlbum;
       
   612                 break;
       
   613                 }
       
   614             case ETrackNumber:
       
   615                 {
       
   616                 val = iTrackNumber;
       
   617                 break;
       
   618                 }
       
   619             case ENumberOfTracks:
       
   620                 {
       
   621                 MMPXSource* s = iPlaybackUtility->Source();
       
   622                 if ( s )
       
   623                     {
       
   624                     CMPXCollectionPlaylist* pl = NULL;
       
   625                     TRAP(err, pl = s->PlaylistL());
       
   626                     if( !err && pl )
       
   627                         {
       
   628                         val = pl->Count(); // What if PlaylistItemCount is zero?
       
   629                         }
       
   630                     delete pl;
       
   631                     }
       
   632                 break;
       
   633                 }
       
   634             case EGenre:
       
   635                 {
       
   636                 detail = iGenre;
       
   637                 break;
       
   638                 }
       
   639             case EPlayingTime:
       
   640                 {
       
   641                 // No need to check for boundaries, assuming the file length < 10^15 seconds
       
   642                 val = iPlayingTime; // If playing time does not exist, what then?
       
   643                 break;
       
   644                 }
       
   645             default:
       
   646                 break;
       
   647             }
       
   648         if( val )
       
   649             {
       
   650             // 'val' and 'detail' are mutually exclusive. We still set detail to 
       
   651             // null, to avoid the possiblility that "delete detail" will delete 
       
   652             // a member variable if NewL fails.
       
   653             detail = NULL;
       
   654             TRAP_IGNORE( detail = HBufC::NewL( KMaxMediaAttrLen ) );
       
   655             if( detail )
       
   656                 {
       
   657                 detail->Des().NumUC( val );
       
   658                 }
       
   659             }
       
   660         if( detail )
       
   661             {
       
   662             const TInt returnValue = CnvUtfConverter::ConvertFromUnicodeToUtf8( attrBuf, *detail );
       
   663             if ( returnValue == CnvUtfConverter::EErrorIllFormedInput)
       
   664                 {
       
   665                 MPX_DEBUG1( "CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata - Illformed string, sending zero length response" );
       
   666                 attrBuf.Zero();
       
   667                 }
       
   668             else if ( returnValue > 0 )
       
   669                 {
       
   670                 MPX_DEBUG1( "CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata - Could not convert whole string, sending converted fragment" );    
       
   671                 }
       
   672             }
       
   673         if( val )
       
   674             {
       
   675             delete detail;
       
   676             detail = NULL;
       
   677             }
       
   678         iMediaInfoTarget->AttributeValue( attrId, attrBuf );
       
   679         }
       
   680     iMediaInfoTarget->Completed();
       
   681     }
       
   682 
       
   683 // -----------------------------------------------------------------------------
       
   684 // From MRemConMediaInformationTargetObserver
       
   685 // For each element in aAttributeList the client should respond by calling 
       
   686 // CRemConMediaInformationTarget::AttributeValue(). After all attributes have 
       
   687 // been supplied the client should call CRemConMediaInformationTarget::Completed().
       
   688 // @param aAttributeList A list of TAttributeID requested by the controller
       
   689 // -----------------------------------------------------------------------------
       
   690 //
       
   691 void CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata( 
       
   692     TMediaAttributeIter& aAttributeIter )
       
   693     {
       
   694     MPX_FUNC( "CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata" );
       
   695     
       
   696     if ( iTrackTitle ) 
       
   697         {
       
   698         SendCurrentlyPlayingMetadata( aAttributeIter );
       
   699         delete iMetadataIter;
       
   700         iMetadataIter = NULL;
       
   701         }
       
   702     else
       
   703         {
       
   704         delete iMetadataIter;
       
   705         iMetadataIter = new TMediaAttributeIter( aAttributeIter );
       
   706         }
       
   707     }
       
   708 
       
   709 // ---------------------------------------------------------------------------
       
   710 // From class MRemConGroupNavigationTargetObserver.
       
   711 // A 'Next Group' command has been received.
       
   712 // ---------------------------------------------------------------------------
       
   713 //
       
   714 void CMPXMetaDataHandlerImp::MrcgntoNextGroup(TRemConCoreApiButtonAction aButtonAct)
       
   715     {
       
   716     MPX_FUNC( "CMPXMetaDataHandlerImp::MrcgntoNextGroup" );
       
   717     (void) aButtonAct;
       
   718     // Not supported yet, return an error.
       
   719     TRequestStatus* status = NULL;
       
   720     iGroupNavigationTarget->NextGroupResponse( status, KErrAvrcpMetadataInvalidParameter );
       
   721     }
       
   722 
       
   723 // ---------------------------------------------------------------------------
       
   724 // From class MRemConGroupNavigationTargetObserver.
       
   725 // A 'Previous Group' command has been received.
       
   726 // ---------------------------------------------------------------------------
       
   727 //
       
   728 void CMPXMetaDataHandlerImp::MrcgntoPreviousGroup(TRemConCoreApiButtonAction aButtonAct)
       
   729     {
       
   730     MPX_FUNC( "CMPXMetaDataHandlerImp::MrcgntoPreviousGroup" );
       
   731     (void) aButtonAct;
       
   732     // Not supported yet, return an error.
       
   733     TRequestStatus* status = NULL;
       
   734     iGroupNavigationTarget->PreviousGroupResponse( status, KErrAvrcpMetadataInvalidParameter );
       
   735     }
       
   736 
       
   737 
       
   738 // ---------------------------------------------------------------------------
       
   739 // From class MEqualizerPresetChangeListenerObserver
       
   740 // Callback for receiving changes in the equalizer preset settings.
       
   741 // ---------------------------------------------------------------------------
       
   742 //
       
   743 void CMPXMetaDataHandlerImp::EqualizerPresetChangedL(TInt aNewPreset)
       
   744     {
       
   745     MPX_FUNC( "CMPXMetaDataHandlerImp::EqualizerPresetChanged" );
       
   746     TInt val = KAvrcpOff;
       
   747     if( aNewPreset != KEqualizerPresetNone)
       
   748       {
       
   749       iLastEqPresetId = aNewPreset; // Store last used preset
       
   750       val = KAvrcpOn;
       
   751       }
       
   752     iPlayerApplicationSettingsObserver->SetAttributeL( KAvrcpEqualizerMode, val );
       
   753     }
       
   754 
       
   755 
       
   756 // ---------------------------------------------------------------------------
       
   757 // C++ default constructor
       
   758 // ---------------------------------------------------------------------------
       
   759 //
       
   760 CEqualizerPresetChangeListener::CEqualizerPresetChangeListener(MEqualizerPresetChangeListenerObserver& aObserver)
       
   761 :   CActive(EPriorityStandard), 
       
   762     iObserver(aObserver)
       
   763     {
       
   764     MPX_FUNC( "CEqualizerPresetChangeListener::CEqualizerPresetChangeListener" );
       
   765     }
       
   766 
       
   767 // ---------------------------------------------------------------------------
       
   768 // Symbian 2nd-phase constructor
       
   769 // ---------------------------------------------------------------------------
       
   770 //
       
   771 void CEqualizerPresetChangeListener::ConstructL()
       
   772     {
       
   773     MPX_FUNC( "CEqualizerPresetChangeListener::ConstructL" );
       
   774     CActiveScheduler::Add( this );
       
   775     iRepository = CRepository::NewL(KCRUidMusicPlayerSettings);
       
   776     }
       
   777 
       
   778 // ---------------------------------------------------------------------------
       
   779 // NewL
       
   780 // ---------------------------------------------------------------------------
       
   781 //
       
   782 CEqualizerPresetChangeListener* CEqualizerPresetChangeListener::NewL(MEqualizerPresetChangeListenerObserver& aObserver)
       
   783     {
       
   784     MPX_FUNC( "CEqualizerPresetChangeListener::NewL" );
       
   785     CEqualizerPresetChangeListener* self = new(ELeave)CEqualizerPresetChangeListener( aObserver );
       
   786     CleanupStack::PushL( self );
       
   787     self->ConstructL();
       
   788     CleanupStack::Pop(self);
       
   789     return self;
       
   790     }
       
   791 
       
   792 // ---------------------------------------------------------------------------
       
   793 // Destructor
       
   794 // ---------------------------------------------------------------------------
       
   795 //
       
   796 CEqualizerPresetChangeListener::~CEqualizerPresetChangeListener()
       
   797     {
       
   798     MPX_FUNC( "CEqualizerPresetChangeListener::~CEqualizerPresetChangeListener" );
       
   799     Stop();
       
   800     delete iRepository;
       
   801     }
       
   802 
       
   803 // ---------------------------------------------------------------------------
       
   804 // Get the current equalizer preset ID
       
   805 // ---------------------------------------------------------------------------
       
   806 //
       
   807 TInt CEqualizerPresetChangeListener::GetCurrentPresetL()
       
   808     {
       
   809     MPX_FUNC( "CEqualizerPresetChangeListener::GetCurrentPresetL" );
       
   810     TInt preset;
       
   811     User::LeaveIfError(iRepository->Get(KMPlayerEqPresetId, preset));
       
   812     return preset;
       
   813     }
       
   814 
       
   815 // ---------------------------------------------------------------------------
       
   816 // Set the equalizer preset
       
   817 // ---------------------------------------------------------------------------
       
   818 //
       
   819 void CEqualizerPresetChangeListener::ChangePresetL(TInt aNewPreset)
       
   820     {
       
   821     MPX_FUNC( "CEqualizerPresetChangeListener::ChangePresetL" );
       
   822     User::LeaveIfError(iRepository->Set(KMPlayerEqPresetId, aNewPreset));
       
   823     }
       
   824 
       
   825 // ---------------------------------------------------------------------------
       
   826 // Start listening to equalizer preset changes
       
   827 // ---------------------------------------------------------------------------
       
   828 //
       
   829 void CEqualizerPresetChangeListener::StartL()
       
   830     {
       
   831     MPX_FUNC( "CEqualizerPresetChangeListener::StartL" );
       
   832     User::LeaveIfError(iRepository->NotifyRequest(KMPlayerEqPresetId, iStatus));
       
   833     SetActive();
       
   834     }
       
   835 
       
   836 // ---------------------------------------------------------------------------
       
   837 // Stop listening to equalizer preset changes
       
   838 // ---------------------------------------------------------------------------
       
   839 //
       
   840 void CEqualizerPresetChangeListener::Stop()
       
   841     {
       
   842     MPX_FUNC( "CEqualizerPresetChangeListener::Stop" );
       
   843     Cancel();
       
   844     }
       
   845 
       
   846 // ---------------------------------------------------------------------------
       
   847 // From class CActive.
       
   848 // Called by the active scheduler when the request has been completed.
       
   849 // ---------------------------------------------------------------------------
       
   850 //
       
   851 void CEqualizerPresetChangeListener::RunL()
       
   852     {
       
   853     MPX_FUNC( "CEqualizerPresetChangeListener::RunL" );
       
   854     iObserver.EqualizerPresetChangedL(GetCurrentPresetL());
       
   855     StartL();
       
   856     }
       
   857 
       
   858 // ---------------------------------------------------------------------------
       
   859 // From class CActive.
       
   860 // Called by the active scheduler when the request has been cancelled.
       
   861 // ---------------------------------------------------------------------------
       
   862 //
       
   863 void CEqualizerPresetChangeListener::DoCancel()
       
   864     {
       
   865     MPX_FUNC( "CEqualizerPresetChangeListener::DoCancel" );
       
   866     iRepository->NotifyCancel(KMPlayerEqPresetId);
       
   867     delete iRepository;
       
   868     iRepository = NULL;
       
   869     }
       
   870 
       
   871 // ---------------------------------------------------------------------------
       
   872 // From class CActive.
       
   873 // Called by the active scheduler when an error in RunL has occurred.
       
   874 // ---------------------------------------------------------------------------
       
   875 //
       
   876 TInt CEqualizerPresetChangeListener::RunError( TInt aError )
       
   877     {
       
   878     MPX_FUNC( "CEqualizerPresetChangeListener::RunError" );
       
   879     (void) aError;
       
   880     // In case of an exception in RunL, re-subscribe to Central Repository, 
       
   881     // and ignore the return value. If it fails we just won't be sending 
       
   882     // equalizer updates anymore.
       
   883     if( !iRepository->NotifyRequest( KMPlayerEqPresetId, iStatus ) )
       
   884         {
       
   885         SetActive();
       
   886         }
       
   887     return KErrNone;
       
   888     }