mpxmusicplayer/metadatahandler/src/mpxmetadatahandlerimp.cpp
changeset 0 ff3acec5bc43
child 5 2a40e88564c8
equal deleted inserted replaced
-1:000000000000 0:ff3acec5bc43
       
     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 
       
   150 // ---------------------------------------------------------------------------
       
   151 // Two-phased constructor.
       
   152 // ---------------------------------------------------------------------------
       
   153 //
       
   154 MMPXMetaDataHandler* CMPXMetaDataHandlerImp::NewL(CRemConInterfaceSelector &aInterfaceSelector)
       
   155     {
       
   156     CMPXMetaDataHandlerImp* self = new(ELeave)CMPXMetaDataHandlerImp();
       
   157     CleanupStack::PushL( self );
       
   158     self->ConstructL(aInterfaceSelector);
       
   159     CleanupStack::Pop(self);
       
   160 
       
   161     return self;
       
   162     }
       
   163 
       
   164 // ---------------------------------------------------------------------------
       
   165 // Destructor
       
   166 // ---------------------------------------------------------------------------
       
   167 //
       
   168 CMPXMetaDataHandlerImp::~CMPXMetaDataHandlerImp()
       
   169     {
       
   170     if( iEqPresetListener )
       
   171         {
       
   172         iEqPresetListener->Stop();
       
   173         delete iEqPresetListener;
       
   174         }
       
   175     if( iPlaybackUtility )
       
   176         {
       
   177         TRAP_IGNORE( iPlaybackUtility->RemoveObserverL( *this ) );
       
   178         iPlaybackUtility->Close();
       
   179         }
       
   180 
       
   181     delete iTrackTitle;
       
   182     delete iArtist;
       
   183     delete iAlbum;
       
   184     delete iGenre;
       
   185     }
       
   186 
       
   187 // ---------------------------------------------------------------------------
       
   188 // Handle playback message.
       
   189 // ---------------------------------------------------------------------------
       
   190 //
       
   191 void CMPXMetaDataHandlerImp::DoHandlePlaybackMessageL(
       
   192     const CMPXMessage& aMessage )
       
   193     {
       
   194     MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandlePlaybackMessageL(CMPXMessage)");
       
   195 
       
   196     TMPXMessageId id( aMessage.ValueTObjectL<TMPXMessageId>( KMPXMessageGeneralId ) );
       
   197     if ( KMPXMessagePbMediaChanged == id )
       
   198         {
       
   199         if ( aMessage.IsSupported( KMPXMessagePbMedia ) )
       
   200             {
       
   201             CMPXMedia* media( aMessage.Value<CMPXMedia>( KMPXMessagePbMedia ) );
       
   202             User::LeaveIfNull( media );
       
   203             iPlaybackPosition = 0;
       
   204             DoHandleMediaL( *media, KErrNone );
       
   205             }
       
   206         }
       
   207     else if ( KMPXMessageGeneral == id )
       
   208         {
       
   209         TInt type( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralType ));
       
   210         TInt data( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralData ));
       
   211         switch ( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralEvent ) )
       
   212             {
       
   213             case TMPXPlaybackMessage::EPropertyChanged:
       
   214                 {
       
   215                 TMPXPlaybackProperty property( static_cast<TMPXPlaybackProperty>( type ) );
       
   216                 TInt error( KErrNone );
       
   217                 DoHandlePropertyL( property, data, error );
       
   218                 break;
       
   219                 }
       
   220             case TMPXPlaybackMessage::EStateChanged:
       
   221                 {
       
   222                 MPX_DEBUG2( "CMPXMetaDataHandlerImp::HandlePlaybackMessageL - EStateChanged(%d)", type );
       
   223 
       
   224                 TMPXPlaybackState state = static_cast<TMPXPlaybackState>( type );
       
   225                 DoHandleStateChangedL( state );
       
   226                 break;
       
   227                 }
       
   228             case TMPXPlaybackMessage::EMediaChanged:
       
   229                 {
       
   230                 MMPXSource* s = iPlaybackUtility->Source();
       
   231                 if ( s )
       
   232                     {
       
   233                     RArray<TMPXAttribute> attrs;
       
   234                     CleanupClosePushL(attrs);
       
   235                     (void) attrs.Append( KMPXMediaGeneralTitle );
       
   236                     (void) attrs.Append( KMPXMediaGeneralDuration );
       
   237                     (void) attrs.Append( KMPXMediaGeneralId );
       
   238                     (void) attrs.Append( KMPXMediaMusicArtist );
       
   239                     (void) attrs.Append( KMPXMediaMusicAlbum );
       
   240                     (void) attrs.Append( KMPXMediaMusicGenre );
       
   241                     MPX_DEBUG1( "CMPXMetaDataHandlerImp::HandlePlaybackMessageL Media changed, calling MediaL to refresh" );
       
   242                     s->MediaL( attrs.Array(), *this, NULL );
       
   243                     CleanupStack::PopAndDestroy( &attrs );
       
   244                     }
       
   245                 break;
       
   246                 }
       
   247             default:
       
   248                 {
       
   249                 break;
       
   250                 }
       
   251             }
       
   252         }
       
   253     }
       
   254 
       
   255 // ---------------------------------------------------------------------------
       
   256 // Handle playback property.
       
   257 // ---------------------------------------------------------------------------
       
   258 //
       
   259 void CMPXMetaDataHandlerImp::DoHandlePropertyL(
       
   260     TMPXPlaybackProperty aProperty,
       
   261     TInt aValue,
       
   262     TInt aError )
       
   263     {
       
   264     MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandlePropertyL" );
       
   265     MPX_DEBUG4( "CMPXMetaDataHandlerImp::HandlePropertyL - Property(%d); Value(%d); Error(%d)", aProperty, aValue, aError );
       
   266 
       
   267     TInt attr = 0;
       
   268     TInt val = KAvrcpOff;
       
   269     if ( KErrNone == aError )
       
   270         {
       
   271         switch ( aProperty )
       
   272             {
       
   273             case EPbPropertyPosition:
       
   274                 {
       
   275                 iPlaybackPosition = aValue / KMPXOneSecInMilliSecs;
       
   276                     // AVRCP 1.3 - inform remote device of the new position 
       
   277                     // ( Todo: check that we don't call too often)
       
   278                 iPlayerEventsObserver->SetPlaybackPosition(aValue); // aPlaybackPosInMicroSeconds is converted to 32 bit value
       
   279                 break;
       
   280                 }
       
   281             case EPbPropertyRepeatMode:
       
   282                 {
       
   283                 attr = KAvrcpRepeatMode; // Repeat mode status
       
   284                     // TMPlayerRepeatMode values are in the same order as AVRCP 1.3, 
       
   285                     // but starting at 0 instead of 1.
       
   286                 val = (TInt) aValue + 1;
       
   287                 break;
       
   288                 }
       
   289             case EPbPropertyRandomMode:
       
   290                 {
       
   291                 attr = KAvrcpShuffleMode;    // Shuffle on/off status
       
   292                 TBool random = aValue;
       
   293                 if( random )
       
   294                     {
       
   295                     val = KAvrcpAllTracksShuffle;
       
   296                     }
       
   297                 break;
       
   298               }
       
   299             default:
       
   300                 {
       
   301                 break;
       
   302                 }
       
   303             }
       
   304         if( attr )
       
   305             {
       
   306             iPlayerApplicationSettingsObserver->SetAttributeL( attr, val );
       
   307             }
       
   308         }
       
   309     }
       
   310 
       
   311 // ---------------------------------------------------------------------------
       
   312 // Handle media properties.
       
   313 // Notes: The client is responsible for delete the object of aProperties.
       
   314 // ---------------------------------------------------------------------------
       
   315 //
       
   316 void CMPXMetaDataHandlerImp::DoHandleMediaL(
       
   317     const CMPXMedia& aMedia, TInt aError )
       
   318     {
       
   319     MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandleMediaL" );
       
   320 
       
   321     // Delete old title no matter there's error or not
       
   322     delete iTrackTitle;
       
   323     iTrackTitle = NULL;
       
   324     delete iArtist;
       
   325     iArtist = NULL;
       
   326     delete iAlbum;
       
   327     iAlbum = NULL;
       
   328     delete iGenre;
       
   329     iGenre = NULL;
       
   330     TInt lastTrackNumber = -1;
       
   331     if ( KErrNone == aError )
       
   332         {
       
   333         // Keep track of the current track's title
       
   334         iTrackTitle = aMedia.ValueText( KMPXMediaGeneralTitle ).AllocL();
       
   335         TInt *playingTime = aMedia.Value<TInt>( KMPXMediaGeneralDuration );
       
   336         if(playingTime)
       
   337             {
       
   338             iPlayingTime = *playingTime; // In milliseconds.
       
   339             }
       
   340         MMPXSource* s = iPlaybackUtility->Source();
       
   341         if ( s )
       
   342             {
       
   343             CMPXCollectionPlaylist* pl = s->PlaylistL();
       
   344             if( pl )
       
   345                 {
       
   346                 lastTrackNumber = pl->Path().Index() + 1; // What if PlaylistItemCount is zero?
       
   347                 delete pl;
       
   348                 }
       
   349             }
       
   350 
       
   351         iArtist = aMedia.ValueText( KMPXMediaMusicArtist ).AllocL();
       
   352         iAlbum = aMedia.ValueText( KMPXMediaMusicAlbum ).AllocL();
       
   353         iGenre = aMedia.ValueText( KMPXMediaMusicGenre ).AllocL();
       
   354 
       
   355         TUid colId = aMedia.ValueTObjectL<TUid>(KMPXMediaGeneralId);
       
   356 
       
   357         
       
   358         MPX_DEBUG2( "CMPXMetaDataHandlerImp::DoHandleMediaL - Track title(%S)", iTrackTitle);
       
   359         MPX_DEBUG4( "CMPXMetaDataHandlerImp::DoHandleMediaL - Artist(%S); Album(%S); Genre(%S)", iArtist, iAlbum, iGenre );
       
   360         MPX_DEBUG4( "CMPXMetaDataHandlerImp::DoHandleMediaL - Playing time(%d); Track number(%d); UID(%d)", iPlayingTime, lastTrackNumber, colId.iUid);
       
   361                 
       
   362         if ( colId.iUid != iColId.iUid || lastTrackNumber != iTrackNumber )
       
   363             {
       
   364             iColId = colId;
       
   365             iTrackNumber = lastTrackNumber;
       
   366             iPlayerEventsObserver->TrackChanged(iColId.iUid, iPlayingTime);
       
   367             }
       
   368         else
       
   369             {
       
   370             MPX_DEBUG1( "CMPXMetaDataHandlerImp::DoHandleMediaL DUPLICATE Trace Change Received" );
       
   371             }
       
   372         }
       
   373     }
       
   374 
       
   375 // ---------------------------------------------------------------------------
       
   376 // Handle playback state changed.
       
   377 // ---------------------------------------------------------------------------
       
   378 //
       
   379 void CMPXMetaDataHandlerImp::DoHandleStateChangedL(
       
   380     TMPXPlaybackState aState )
       
   381     {
       
   382     MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandleStateChangedL" );
       
   383     switch ( aState )
       
   384         {
       
   385         case EPbStateStopped:
       
   386             {
       
   387             iPlayerState = aState;
       
   388             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EStopped);
       
   389             break;
       
   390             }
       
   391         case EPbStatePlaying:
       
   392             iPlayerState = aState;
       
   393             // Start the time if needed, otherwise, update content if visible
       
   394             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EPlaying);
       
   395             break;
       
   396         case EPbStatePaused:
       
   397             {
       
   398             iPlayerState = aState;
       
   399             // Start the time if needed, otherwise, update content if visible
       
   400             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EPaused);
       
   401             break;
       
   402             }
       
   403         case EPbStateSeekingForward:
       
   404             {
       
   405             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EFwdSeek);
       
   406             break;
       
   407             }
       
   408         case EPbStateSeekingBackward:
       
   409             {
       
   410             iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::ERevSeek);
       
   411             break;
       
   412             }
       
   413         default:
       
   414             {
       
   415             // do nothing
       
   416             break;
       
   417             }
       
   418         }
       
   419     }
       
   420 
       
   421 // ---------------------------------------------------------------------------
       
   422 // From MMPXPlaybackObserver
       
   423 // Handle playback message.
       
   424 // ---------------------------------------------------------------------------
       
   425 //
       
   426 void CMPXMetaDataHandlerImp::HandlePlaybackMessage(
       
   427     CMPXMessage* aMessage, TInt aError )
       
   428     {
       
   429     if ( aError == KErrNone && aMessage )
       
   430         {
       
   431         TRAP_IGNORE( DoHandlePlaybackMessageL( *aMessage ) );
       
   432         }
       
   433     }
       
   434 
       
   435 // ---------------------------------------------------------------------------
       
   436 // From MMPXPlaybackCallback
       
   437 // Handle playback property.
       
   438 // ---------------------------------------------------------------------------
       
   439 //
       
   440 void CMPXMetaDataHandlerImp::HandlePropertyL(
       
   441     TMPXPlaybackProperty aProperty,
       
   442     TInt aValue,
       
   443     TInt aError )
       
   444     {
       
   445     TRAP_IGNORE( DoHandlePropertyL( aProperty, aValue, aError ) );
       
   446     }
       
   447 
       
   448 // ---------------------------------------------------------------------------
       
   449 // From MMPXPlaybackCallback
       
   450 // Handle sub player names.
       
   451 // ---------------------------------------------------------------------------
       
   452 //
       
   453 void CMPXMetaDataHandlerImp::HandleSubPlayerNamesL(
       
   454     TUid /* aPlayer */,
       
   455     const MDesCArray* /* aSubPlayers */,
       
   456     TBool /* aComplete */,
       
   457     TInt /* aError */ )
       
   458     {
       
   459     MPX_FUNC( "CMPXMediaKeyHandlerImp::HandleSubPlayerNamesL" );
       
   460     }
       
   461 
       
   462 // ---------------------------------------------------------------------------
       
   463 // From MMPXPlaybackCallback
       
   464 // Handle media properties.
       
   465 // Notes: The client is responsible for delete the object of aMedia.
       
   466 // ---------------------------------------------------------------------------
       
   467 //
       
   468 void CMPXMetaDataHandlerImp::HandleMediaL(
       
   469     const CMPXMedia& aMedia, TInt aError )
       
   470     {
       
   471     MPX_FUNC( "CMPXMetaDataHandlerImp::HandleMediaL" );
       
   472     TRAP_IGNORE( DoHandleMediaL( aMedia, aError ) );
       
   473     }
       
   474 
       
   475 // ---------------------------------------------------------------------------
       
   476 // From MMPXCollectionPlaylistObserver
       
   477 // Handle collection playlist change.
       
   478 // Notes: aError values:
       
   479 // KErrNotFound - Playlist is updated, current item removed
       
   480 // KErrNone - Playlist is updated, current item is valid
       
   481 // KErrEof - Playlist is updated, current item removed and reached to the end of playlist
       
   482 // ---------------------------------------------------------------------------
       
   483 //
       
   484 void CMPXMetaDataHandlerImp::HandleCollectionPlaylistChange(TInt aError)
       
   485     {
       
   486     MPX_FUNC( "CMPXMetaDataHandlerImp::HandleCollectionPlaylistChange" );
       
   487 
       
   488     if( aError )
       
   489         {
       
   490             // Update the media item.
       
   491         MMPXSource* s = iPlaybackUtility->Source();
       
   492         if ( s )
       
   493             {
       
   494             RArray<TMPXAttribute> attrs;
       
   495                 // Failing the next operations here is not fatal.
       
   496             (void) attrs.Append( KMPXMediaGeneralTitle );
       
   497             (void) attrs.Append( KMPXMediaGeneralDuration );
       
   498             (void) attrs.Append( KMPXMediaGeneralId );
       
   499             (void) attrs.Append( KMPXMediaMusicArtist );
       
   500             (void) attrs.Append( KMPXMediaMusicAlbum );
       
   501             (void) attrs.Append( KMPXMediaMusicGenre );
       
   502                 // Ignore the leave. If this occurs, we just don't get 
       
   503                 // an updated media information for time being.
       
   504             TRAP_IGNORE(s->MediaL( attrs.Array(), *this, NULL ));
       
   505             attrs.Close();
       
   506             }
       
   507         }
       
   508     }
       
   509 
       
   510 // ---------------------------------------------------------------------------
       
   511 // From MPlayerApplicationSettingsNotify
       
   512 // This is called when the controller has changed a setting
       
   513 // ---------------------------------------------------------------------------
       
   514 //
       
   515 void CMPXMetaDataHandlerImp::MpasnSetPlayerApplicationValueL(
       
   516     const RArray<TInt>& aAttributeID, const RArray<TInt>& aAttributeValue )
       
   517     {
       
   518     MPX_FUNC( "CMPXMetaDataHandlerImp::MpasnSetPlayerApplicationValueL" );
       
   519 
       
   520     for( TInt i = 0; i < aAttributeID.Count(); i++ )
       
   521         {
       
   522         switch( aAttributeID[ i ] )
       
   523             {
       
   524             case KAvrcpEqualizerMode:
       
   525                 {
       
   526                 TInt equalizer = aAttributeValue[ i ] == KAvrcpOff ? KEqualizerPresetNone : iLastEqPresetId;
       
   527                 iEqPresetListener->ChangePresetL(equalizer);
       
   528 //                iLastEqPresetId = equalizer;
       
   529                 break;
       
   530                 }
       
   531             case KAvrcpRepeatMode:
       
   532                 {
       
   533                     // TMPlayerRepeatMode values are in the same order 
       
   534                     // as AVRCP 1.3, but starting at 0 instead of 1.
       
   535                 TInt repeat = aAttributeValue[ i ] - 1;
       
   536                 iPlaybackUtility->SetL(EPbPropertyRepeatMode, repeat);
       
   537                 break;
       
   538                 }
       
   539             case KAvrcpShuffleMode:
       
   540                 {
       
   541                 TBool random = aAttributeValue[ i ] == KAvrcpOff ? EFalse : ETrue;
       
   542                 iPlaybackUtility->SetL(EPbPropertyRandomMode, random);
       
   543                 break;
       
   544                 }
       
   545             case KAvrcpBassBoostMode:
       
   546                 {
       
   547                 TBool boost = aAttributeValue[ i ] == KAvrcpOff ? EFalse : ETrue;
       
   548 //                iSettingModel->SetBassBoostL( boost );
       
   549                 break;
       
   550                 }
       
   551             case KAvrcpStereoWideningMode:
       
   552                 {
       
   553                 TBool widening = aAttributeValue[ i ] == KAvrcpOff ? EFalse : ETrue;
       
   554 //                iSettingModel->SetStereoWideningL( widening );
       
   555                 break;
       
   556                 }
       
   557             default:
       
   558                 {
       
   559                 // Leaving results in sending an error back to the controller.
       
   560                 User::Leave( KErrNotSupported );
       
   561                 break;
       
   562                 }
       
   563             }
       
   564         }
       
   565     }
       
   566 
       
   567 // -----------------------------------------------------------------------------
       
   568 // From MRemConMediaInformationTargetObserver
       
   569 // For each element in aAttributeList the client should respond by calling 
       
   570 // CRemConMediaInformationTarget::AttributeValue(). After all attributes have 
       
   571 // been supplied the client should call CRemConMediaInformationTarget::Completed().
       
   572 // @param aAttributeList A list of TAttributeID requested by the controller
       
   573 // -----------------------------------------------------------------------------
       
   574 //
       
   575 void CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata( 
       
   576     TMediaAttributeIter& aAttributeIter )
       
   577     {
       
   578     MPX_FUNC( "CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata" );
       
   579     const TInt KMaxMediaAttrLen = 50;   // Replace with suitable value
       
   580     TBuf8<KMaxMediaAttrLen> attrBuf;
       
   581     TMediaAttributeId attrId;
       
   582     aAttributeIter.Start();
       
   583     while( aAttributeIter.Next( attrId ) )
       
   584         {
       
   585         TInt err = KErrNotFound;
       
   586         HBufC* detail = NULL;
       
   587         TInt64 val = 0;
       
   588         switch( attrId )
       
   589             {
       
   590             case ETitleOfMedia:
       
   591                 {
       
   592                 detail = iTrackTitle;
       
   593                 break;
       
   594                 }
       
   595             case ENameOfArtist:
       
   596                 {
       
   597                 detail = iArtist;
       
   598                 break;
       
   599                 }
       
   600             case ENameOfAlbum:
       
   601                 {
       
   602                 detail = iAlbum;
       
   603                 break;
       
   604                 }
       
   605             case ETrackNumber:
       
   606                 {
       
   607                 val = iTrackNumber;
       
   608                 break;
       
   609                 }
       
   610             case ENumberOfTracks:
       
   611                 {
       
   612                 MMPXSource* s = iPlaybackUtility->Source();
       
   613                 if ( s )
       
   614                     {
       
   615                     CMPXCollectionPlaylist* pl = NULL;
       
   616                     TRAP(err, pl = s->PlaylistL());
       
   617                     if( !err && pl )
       
   618                         {
       
   619                         val = pl->Count(); // What if PlaylistItemCount is zero?
       
   620                         }
       
   621                     delete pl;
       
   622                     }
       
   623                 break;
       
   624                 }
       
   625             case EGenre:
       
   626                 {
       
   627                 detail = iGenre;
       
   628                 break;
       
   629                 }
       
   630             case EPlayingTime:
       
   631                 {
       
   632                 // No need to check for boundaries, assuming the file length < 10^15 seconds
       
   633                 val = iPlayingTime; // If playing time does not exist, what then?
       
   634                 break;
       
   635                 }
       
   636             default:
       
   637                 break;
       
   638             }
       
   639         if( val )
       
   640             {
       
   641             // 'val' and 'detail' are mutually exclusive. We still set detail to 
       
   642             // null, to avoid the possiblility that "delete detail" will delete 
       
   643             // a member variable if NewL fails.
       
   644             detail = NULL;
       
   645             TRAP_IGNORE( detail = HBufC::NewL( KMaxMediaAttrLen ) );
       
   646             if( detail )
       
   647                 {
       
   648                 detail->Des().NumUC( val );
       
   649                 }
       
   650             }
       
   651         if( detail )
       
   652             {
       
   653             if( CnvUtfConverter::ConvertFromUnicodeToUtf8( attrBuf, *detail ) )
       
   654                 {
       
   655                 attrBuf.Zero();     // Check if this generates the right response
       
   656                 }
       
   657             }
       
   658         if( val )
       
   659             {
       
   660             delete detail;
       
   661             detail = NULL;
       
   662             }
       
   663         iMediaInfoTarget->AttributeValue( attrId, attrBuf );
       
   664         }
       
   665     iMediaInfoTarget->Completed();
       
   666     }
       
   667 
       
   668 
       
   669 
       
   670 // ---------------------------------------------------------------------------
       
   671 // From class MRemConGroupNavigationTargetObserver.
       
   672 // A 'Next Group' command has been received.
       
   673 // ---------------------------------------------------------------------------
       
   674 //
       
   675 void CMPXMetaDataHandlerImp::MrcgntoNextGroup(TRemConCoreApiButtonAction aButtonAct)
       
   676     {
       
   677     MPX_FUNC( "CMPXMetaDataHandlerImp::MrcgntoNextGroup" );
       
   678     (void) aButtonAct;
       
   679     // Not supported yet, return an error.
       
   680     TRequestStatus* status = NULL;
       
   681     iGroupNavigationTarget->NextGroupResponse( status, KErrAvrcpMetadataInvalidParameter );
       
   682     }
       
   683 
       
   684 // ---------------------------------------------------------------------------
       
   685 // From class MRemConGroupNavigationTargetObserver.
       
   686 // A 'Previous Group' command has been received.
       
   687 // ---------------------------------------------------------------------------
       
   688 //
       
   689 void CMPXMetaDataHandlerImp::MrcgntoPreviousGroup(TRemConCoreApiButtonAction aButtonAct)
       
   690     {
       
   691     MPX_FUNC( "CMPXMetaDataHandlerImp::MrcgntoPreviousGroup" );
       
   692     (void) aButtonAct;
       
   693     // Not supported yet, return an error.
       
   694     TRequestStatus* status = NULL;
       
   695     iGroupNavigationTarget->PreviousGroupResponse( status, KErrAvrcpMetadataInvalidParameter );
       
   696     }
       
   697 
       
   698 
       
   699 // ---------------------------------------------------------------------------
       
   700 // From class MEqualizerPresetChangeListenerObserver
       
   701 // Callback for receiving changes in the equalizer preset settings.
       
   702 // ---------------------------------------------------------------------------
       
   703 //
       
   704 void CMPXMetaDataHandlerImp::EqualizerPresetChangedL(TInt aNewPreset)
       
   705     {
       
   706     MPX_FUNC( "CMPXMetaDataHandlerImp::EqualizerPresetChanged" );
       
   707     TInt val = KAvrcpOff;
       
   708     if( aNewPreset != KEqualizerPresetNone)
       
   709       {
       
   710       iLastEqPresetId = aNewPreset; // Store last used preset
       
   711       val = KAvrcpOn;
       
   712       }
       
   713     iPlayerApplicationSettingsObserver->SetAttributeL( KAvrcpEqualizerMode, val );
       
   714     }
       
   715 
       
   716 
       
   717 // ---------------------------------------------------------------------------
       
   718 // C++ default constructor
       
   719 // ---------------------------------------------------------------------------
       
   720 //
       
   721 CEqualizerPresetChangeListener::CEqualizerPresetChangeListener(MEqualizerPresetChangeListenerObserver& aObserver)
       
   722 :   CActive(EPriorityStandard), 
       
   723     iObserver(aObserver)
       
   724     {
       
   725     MPX_FUNC( "CEqualizerPresetChangeListener::CEqualizerPresetChangeListener" );
       
   726     }
       
   727 
       
   728 // ---------------------------------------------------------------------------
       
   729 // Symbian 2nd-phase constructor
       
   730 // ---------------------------------------------------------------------------
       
   731 //
       
   732 void CEqualizerPresetChangeListener::ConstructL()
       
   733     {
       
   734     MPX_FUNC( "CEqualizerPresetChangeListener::ConstructL" );
       
   735     CActiveScheduler::Add( this );
       
   736     iRepository = CRepository::NewL(KCRUidMusicPlayerSettings);
       
   737     }
       
   738 
       
   739 // ---------------------------------------------------------------------------
       
   740 // NewL
       
   741 // ---------------------------------------------------------------------------
       
   742 //
       
   743 CEqualizerPresetChangeListener* CEqualizerPresetChangeListener::NewL(MEqualizerPresetChangeListenerObserver& aObserver)
       
   744     {
       
   745     MPX_FUNC( "CEqualizerPresetChangeListener::NewL" );
       
   746     CEqualizerPresetChangeListener* self = new(ELeave)CEqualizerPresetChangeListener( aObserver );
       
   747     CleanupStack::PushL( self );
       
   748     self->ConstructL();
       
   749     CleanupStack::Pop(self);
       
   750     return self;
       
   751     }
       
   752 
       
   753 // ---------------------------------------------------------------------------
       
   754 // Destructor
       
   755 // ---------------------------------------------------------------------------
       
   756 //
       
   757 CEqualizerPresetChangeListener::~CEqualizerPresetChangeListener()
       
   758     {
       
   759     MPX_FUNC( "CEqualizerPresetChangeListener::~CEqualizerPresetChangeListener" );
       
   760     Stop();
       
   761     delete iRepository;
       
   762     }
       
   763 
       
   764 // ---------------------------------------------------------------------------
       
   765 // Get the current equalizer preset ID
       
   766 // ---------------------------------------------------------------------------
       
   767 //
       
   768 TInt CEqualizerPresetChangeListener::GetCurrentPresetL()
       
   769     {
       
   770     MPX_FUNC( "CEqualizerPresetChangeListener::GetCurrentPresetL" );
       
   771     TInt preset;
       
   772     User::LeaveIfError(iRepository->Get(KMPlayerEqPresetId, preset));
       
   773     return preset;
       
   774     }
       
   775 
       
   776 // ---------------------------------------------------------------------------
       
   777 // Set the equalizer preset
       
   778 // ---------------------------------------------------------------------------
       
   779 //
       
   780 void CEqualizerPresetChangeListener::ChangePresetL(TInt aNewPreset)
       
   781     {
       
   782     MPX_FUNC( "CEqualizerPresetChangeListener::ChangePresetL" );
       
   783     User::LeaveIfError(iRepository->Set(KMPlayerEqPresetId, aNewPreset));
       
   784     }
       
   785 
       
   786 // ---------------------------------------------------------------------------
       
   787 // Start listening to equalizer preset changes
       
   788 // ---------------------------------------------------------------------------
       
   789 //
       
   790 void CEqualizerPresetChangeListener::StartL()
       
   791     {
       
   792     MPX_FUNC( "CEqualizerPresetChangeListener::StartL" );
       
   793     User::LeaveIfError(iRepository->NotifyRequest(KMPlayerEqPresetId, iStatus));
       
   794     SetActive();
       
   795     }
       
   796 
       
   797 // ---------------------------------------------------------------------------
       
   798 // Stop listening to equalizer preset changes
       
   799 // ---------------------------------------------------------------------------
       
   800 //
       
   801 void CEqualizerPresetChangeListener::Stop()
       
   802     {
       
   803     MPX_FUNC( "CEqualizerPresetChangeListener::Stop" );
       
   804     Cancel();
       
   805     }
       
   806 
       
   807 // ---------------------------------------------------------------------------
       
   808 // From class CActive.
       
   809 // Called by the active scheduler when the request has been completed.
       
   810 // ---------------------------------------------------------------------------
       
   811 //
       
   812 void CEqualizerPresetChangeListener::RunL()
       
   813     {
       
   814     MPX_FUNC( "CEqualizerPresetChangeListener::RunL" );
       
   815     iObserver.EqualizerPresetChangedL(GetCurrentPresetL());
       
   816     StartL();
       
   817     }
       
   818 
       
   819 // ---------------------------------------------------------------------------
       
   820 // From class CActive.
       
   821 // Called by the active scheduler when the request has been cancelled.
       
   822 // ---------------------------------------------------------------------------
       
   823 //
       
   824 void CEqualizerPresetChangeListener::DoCancel()
       
   825     {
       
   826     MPX_FUNC( "CEqualizerPresetChangeListener::DoCancel" );
       
   827     iRepository->NotifyCancel(KMPlayerEqPresetId);
       
   828     delete iRepository;
       
   829     iRepository = NULL;
       
   830     }
       
   831 
       
   832 // ---------------------------------------------------------------------------
       
   833 // From class CActive.
       
   834 // Called by the active scheduler when an error in RunL has occurred.
       
   835 // ---------------------------------------------------------------------------
       
   836 //
       
   837 TInt CEqualizerPresetChangeListener::RunError( TInt aError )
       
   838     {
       
   839     MPX_FUNC( "CEqualizerPresetChangeListener::RunError" );
       
   840     (void) aError;
       
   841     // In case of an exception in RunL, re-subscribe to Central Repository, 
       
   842     // and ignore the return value. If it fails we just won't be sending 
       
   843     // equalizer updates anymore.
       
   844     if( !iRepository->NotifyRequest( KMPlayerEqPresetId, iStatus ) )
       
   845         {
       
   846         SetActive();
       
   847         }
       
   848     return KErrNone;
       
   849     }