/*
* Copyright (c) 2008 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: Implementation of metadata handler
*
*/
#include <bldvariant.hrh>
#include <remconinterfaceselector.h>
#include <bautils.h>
#include <mpxplaybackutility.h>
#include <mpxplaybackframeworkdefs.h>
#include <mpxplaybackmessage.h>
#include <data_caging_path_literals.hrh>
#include <mpxmedia.h>
#include <mpxmessagegeneraldefs.h>
#include <mpxplaybackmessagedefs.h>
#include <mpxmediageneraldefs.h>
#include <mpxuser.h>
#include <mpxlog.h>
#include <playerinformationtarget.h>
#include <remcongroupnavigationtarget.h>
#include <utf.h>
#include <remcon/avrcpspec.h>
#include <mpxmediamusicdefs.h>
#include <mpxcollectionplaylist.h>
#include <mpxcollectionpath.h>
#include <EqualizerConstants.h>
#include <centralrepository.h>
#include "mpxmetadatahandler.h"
#include "mpxmetadatahandlerimp.h"
// CONSTANTS
const TInt KMPXOneSecInMilliSecs( 1000 );
// Definition of remotely controllable application settings
// The commented settings are not used here, included for reference.
_LIT( KMPlayerSettingsDefs, "mplayeravrcpsettings.rsc" );
const TInt KAvrcpEqualizerMode = 0x01;
const TInt KAvrcpRepeatMode = 0x02;
const TInt KAvrcpShuffleMode = 0x03;
//const TInt KAvrcpScanMode = 0x04;
const TInt KAvrcpOff = 0x01;
const TInt KAvrcpOn = 0x02;
// Off 0x01
//const TInt KAvrcpSingleTrackRepeat = 0x02;
//const TInt KAvrcpAllTracksRepeat = 0x03;
//const TInt KAvrcpGroupRepeat = 0x04;
// Off 0x01
const TInt KAvrcpAllTracksShuffle = 0x02;
//const TInt KAvrcpGroupShuffle = 0x03;
// Extended settings defined for Music Player
// Note that these are also defined in mplayeravrcpsettings.rss
const TInt KAvrcpBassBoostMode = 0x80;
const TInt KAvrcpStereoWideningMode = 0x81;
const TUid KCRUidMusicPlayerSettings = {0x101FFCDC};
const TUint32 KMPlayerEqPresetId = 0x00000001;
// ======== MEMBER FUNCTIONS ========
// ---------------------------------------------------------------------------
// C++ default constructor can NOT contain any code, that might leave.
// ---------------------------------------------------------------------------
//
CMPXMetaDataHandlerImp::CMPXMetaDataHandlerImp()
{
}
// ---------------------------------------------------------------------------
// Symbian 2nd phase constructor can leave.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::ConstructL(CRemConInterfaceSelector &aInterfaceSelector)
{
MPX_FUNC( "CMPXMetaDataHandlerImp::ConstructL(CRemConInterfaceSelector)");
iPlayerInformationTarget = CPlayerInfoTarget::NewL(aInterfaceSelector,
iPlayerCapabilitiesObserver,
iPlayerApplicationSettingsObserver,
iPlayerEventsObserver, *this);
iMediaInfoTarget = CRemConMediaInformationTarget::NewL( aInterfaceSelector, *this );
iGroupNavigationTarget = CRemConGroupNavigationApiTarget::NewL( aInterfaceSelector, *this );
// Get the playback utility instance from engine.
iPlaybackUtility = MMPXPlaybackUtility::UtilityL( KPbModeDefault );
iPlaybackUtility->AddObserverL( *this );
MMPXSource* s = iPlaybackUtility->Source();
if ( s )
{
RArray<TMPXAttribute> attrs;
CleanupClosePushL(attrs);
(void) attrs.Append( KMPXMediaGeneralTitle );
(void) attrs.Append( KMPXMediaGeneralDuration );
(void) attrs.Append( KMPXMediaGeneralId );
(void) attrs.Append( KMPXMediaMusicArtist );
(void) attrs.Append( KMPXMediaMusicAlbum );
(void) attrs.Append( KMPXMediaMusicGenre );
s->MediaL( attrs.Array(), *this, NULL );
CleanupStack::PopAndDestroy( &attrs );
}
RFs fs;
User::LeaveIfError( fs.Connect() );
CleanupClosePushL( fs );
TParse parse;
parse.Set( KMPlayerSettingsDefs, &KDC_RESOURCE_FILES_DIR, NULL );
TFileName resourceFile( parse.FullName() );
User::LeaveIfError( MPXUser::CompleteWithDllPath( resourceFile ) );
BaflUtils::NearestLanguageFile( fs, resourceFile );
CResourceFile* playerSettingsResourceFile = CResourceFile::NewLC( fs, resourceFile, 0, 0 );
PlayerApplicationSettingsResourceInit::DefineAttributesL( *iPlayerApplicationSettingsObserver, *playerSettingsResourceFile );
CleanupStack::PopAndDestroy( playerSettingsResourceFile );
CleanupStack::PopAndDestroy( &fs );
// Adding two optional events, mandatory ERegisterNotificationPlaybackStatusChanged
// and ERegisterNotificationTrackChanged are added by SOS.
User::LeaveIfError( iPlayerCapabilitiesObserver->AddEvent(ERegisterNotificationPlaybackPosChanged));
User::LeaveIfError( iPlayerCapabilitiesObserver->AddEvent(ERegisterNotificationPlayerApplicationSettingChanged));
iEqPresetListener = CEqualizerPresetChangeListener::NewL(*this);
iLastEqPresetId = iEqPresetListener->GetCurrentPresetL();
iEqPresetListener->StartL();
iTrackNumber = 0;
iColId.iUid = -1;
}
// ---------------------------------------------------------------------------
// Two-phased constructor.
// ---------------------------------------------------------------------------
//
MMPXMetaDataHandler* CMPXMetaDataHandlerImp::NewL(CRemConInterfaceSelector &aInterfaceSelector)
{
CMPXMetaDataHandlerImp* self = new(ELeave)CMPXMetaDataHandlerImp();
CleanupStack::PushL( self );
self->ConstructL(aInterfaceSelector);
CleanupStack::Pop(self);
return self;
}
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CMPXMetaDataHandlerImp::~CMPXMetaDataHandlerImp()
{
if( iEqPresetListener )
{
iEqPresetListener->Stop();
delete iEqPresetListener;
}
if( iPlaybackUtility )
{
TRAP_IGNORE( iPlaybackUtility->RemoveObserverL( *this ) );
iPlaybackUtility->Close();
}
delete iTrackTitle;
delete iArtist;
delete iAlbum;
delete iGenre;
}
// ---------------------------------------------------------------------------
// Handle playback message.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::DoHandlePlaybackMessageL(
const CMPXMessage& aMessage )
{
MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandlePlaybackMessageL(CMPXMessage)");
TMPXMessageId id( aMessage.ValueTObjectL<TMPXMessageId>( KMPXMessageGeneralId ) );
if ( KMPXMessagePbMediaChanged == id )
{
if ( aMessage.IsSupported( KMPXMessagePbMedia ) )
{
CMPXMedia* media( aMessage.Value<CMPXMedia>( KMPXMessagePbMedia ) );
User::LeaveIfNull( media );
iPlaybackPosition = 0;
DoHandleMediaL( *media, KErrNone );
}
}
else if ( KMPXMessageGeneral == id )
{
TInt type( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralType ));
TInt data( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralData ));
switch ( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralEvent ) )
{
case TMPXPlaybackMessage::EPropertyChanged:
{
TMPXPlaybackProperty property( static_cast<TMPXPlaybackProperty>( type ) );
TInt error( KErrNone );
DoHandlePropertyL( property, data, error );
break;
}
case TMPXPlaybackMessage::EStateChanged:
{
MPX_DEBUG2( "CMPXMetaDataHandlerImp::HandlePlaybackMessageL - EStateChanged(%d)", type );
TMPXPlaybackState state = static_cast<TMPXPlaybackState>( type );
DoHandleStateChangedL( state );
break;
}
case TMPXPlaybackMessage::EMediaChanged:
{
MMPXSource* s = iPlaybackUtility->Source();
if ( s )
{
RArray<TMPXAttribute> attrs;
CleanupClosePushL(attrs);
(void) attrs.Append( KMPXMediaGeneralTitle );
(void) attrs.Append( KMPXMediaGeneralDuration );
(void) attrs.Append( KMPXMediaGeneralId );
(void) attrs.Append( KMPXMediaMusicArtist );
(void) attrs.Append( KMPXMediaMusicAlbum );
(void) attrs.Append( KMPXMediaMusicGenre );
MPX_DEBUG1( "CMPXMetaDataHandlerImp::HandlePlaybackMessageL Media changed, calling MediaL to refresh" );
s->MediaL( attrs.Array(), *this, NULL );
CleanupStack::PopAndDestroy( &attrs );
}
break;
}
default:
{
break;
}
}
}
}
// ---------------------------------------------------------------------------
// Handle playback property.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::DoHandlePropertyL(
TMPXPlaybackProperty aProperty,
TInt aValue,
TInt aError )
{
MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandlePropertyL" );
MPX_DEBUG4( "CMPXMetaDataHandlerImp::HandlePropertyL - Property(%d); Value(%d); Error(%d)", aProperty, aValue, aError );
TInt attr = 0;
TInt val = KAvrcpOff;
if ( KErrNone == aError )
{
switch ( aProperty )
{
case EPbPropertyPosition:
{
iPlaybackPosition = aValue / KMPXOneSecInMilliSecs;
// AVRCP 1.3 - inform remote device of the new position
// ( Todo: check that we don't call too often)
iPlayerEventsObserver->SetPlaybackPosition(aValue); // aPlaybackPosInMicroSeconds is converted to 32 bit value
break;
}
case EPbPropertyRepeatMode:
{
attr = KAvrcpRepeatMode; // Repeat mode status
// TMPlayerRepeatMode values are in the same order as AVRCP 1.3,
// but starting at 0 instead of 1.
val = (TInt) aValue + 1;
break;
}
case EPbPropertyRandomMode:
{
attr = KAvrcpShuffleMode; // Shuffle on/off status
TBool random = aValue;
if( random )
{
val = KAvrcpAllTracksShuffle;
}
break;
}
default:
{
break;
}
}
if( attr )
{
iPlayerApplicationSettingsObserver->SetAttributeL( attr, val );
}
}
}
// ---------------------------------------------------------------------------
// Handle media properties.
// Notes: The client is responsible for delete the object of aProperties.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::DoHandleMediaL(
const CMPXMedia& aMedia, TInt aError )
{
MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandleMediaL" );
// Delete old title no matter there's error or not
delete iTrackTitle;
iTrackTitle = NULL;
delete iArtist;
iArtist = NULL;
delete iAlbum;
iAlbum = NULL;
delete iGenre;
iGenre = NULL;
TInt lastTrackNumber = -1;
if ( KErrNone == aError )
{
// Keep track of the current track's title
iTrackTitle = aMedia.ValueText( KMPXMediaGeneralTitle ).AllocL();
TInt *playingTime = aMedia.Value<TInt>( KMPXMediaGeneralDuration );
if(playingTime)
{
iPlayingTime = *playingTime; // In milliseconds.
}
MMPXSource* s = iPlaybackUtility->Source();
if ( s )
{
CMPXCollectionPlaylist* pl = s->PlaylistL();
if( pl )
{
lastTrackNumber = pl->Path().Index() + 1; // What if PlaylistItemCount is zero?
delete pl;
}
}
iArtist = aMedia.ValueText( KMPXMediaMusicArtist ).AllocL();
iAlbum = aMedia.ValueText( KMPXMediaMusicAlbum ).AllocL();
iGenre = aMedia.ValueText( KMPXMediaMusicGenre ).AllocL();
TUid colId = aMedia.ValueTObjectL<TUid>(KMPXMediaGeneralId);
MPX_DEBUG2( "CMPXMetaDataHandlerImp::DoHandleMediaL - Track title(%S)", iTrackTitle);
MPX_DEBUG4( "CMPXMetaDataHandlerImp::DoHandleMediaL - Artist(%S); Album(%S); Genre(%S)", iArtist, iAlbum, iGenre );
MPX_DEBUG4( "CMPXMetaDataHandlerImp::DoHandleMediaL - Playing time(%d); Track number(%d); UID(%d)", iPlayingTime, lastTrackNumber, colId.iUid);
if ( colId.iUid != iColId.iUid || lastTrackNumber != iTrackNumber )
{
iColId = colId;
iTrackNumber = lastTrackNumber;
iPlayerEventsObserver->TrackChanged(iColId.iUid, iPlayingTime);
}
else
{
MPX_DEBUG1( "CMPXMetaDataHandlerImp::DoHandleMediaL DUPLICATE Trace Change Received" );
}
}
}
// ---------------------------------------------------------------------------
// Handle playback state changed.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::DoHandleStateChangedL(
TMPXPlaybackState aState )
{
MPX_FUNC( "CMPXMetaDataHandlerImp::DoHandleStateChangedL" );
switch ( aState )
{
case EPbStateStopped:
{
iPlayerState = aState;
iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EStopped);
break;
}
case EPbStatePlaying:
iPlayerState = aState;
// Start the time if needed, otherwise, update content if visible
iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EPlaying);
break;
case EPbStatePaused:
{
iPlayerState = aState;
// Start the time if needed, otherwise, update content if visible
iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EPaused);
break;
}
case EPbStateSeekingForward:
{
iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::EFwdSeek);
break;
}
case EPbStateSeekingBackward:
{
iPlayerEventsObserver->PlaybackStatusChanged(MPlayerEventsObserver::ERevSeek);
break;
}
default:
{
// do nothing
break;
}
}
}
// ---------------------------------------------------------------------------
// From MMPXPlaybackObserver
// Handle playback message.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::HandlePlaybackMessage(
CMPXMessage* aMessage, TInt aError )
{
if ( aError == KErrNone && aMessage )
{
TRAP_IGNORE( DoHandlePlaybackMessageL( *aMessage ) );
}
}
// ---------------------------------------------------------------------------
// From MMPXPlaybackCallback
// Handle playback property.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::HandlePropertyL(
TMPXPlaybackProperty aProperty,
TInt aValue,
TInt aError )
{
TRAP_IGNORE( DoHandlePropertyL( aProperty, aValue, aError ) );
}
// ---------------------------------------------------------------------------
// From MMPXPlaybackCallback
// Handle sub player names.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::HandleSubPlayerNamesL(
TUid /* aPlayer */,
const MDesCArray* /* aSubPlayers */,
TBool /* aComplete */,
TInt /* aError */ )
{
MPX_FUNC( "CMPXMediaKeyHandlerImp::HandleSubPlayerNamesL" );
}
// ---------------------------------------------------------------------------
// From MMPXPlaybackCallback
// Handle media properties.
// Notes: The client is responsible for delete the object of aMedia.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::HandleMediaL(
const CMPXMedia& aMedia, TInt aError )
{
MPX_FUNC( "CMPXMetaDataHandlerImp::HandleMediaL" );
TRAP_IGNORE( DoHandleMediaL( aMedia, aError ) );
}
// ---------------------------------------------------------------------------
// From MMPXCollectionPlaylistObserver
// Handle collection playlist change.
// Notes: aError values:
// KErrNotFound - Playlist is updated, current item removed
// KErrNone - Playlist is updated, current item is valid
// KErrEof - Playlist is updated, current item removed and reached to the end of playlist
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::HandleCollectionPlaylistChange(TInt aError)
{
MPX_FUNC( "CMPXMetaDataHandlerImp::HandleCollectionPlaylistChange" );
if( aError )
{
// Update the media item.
MMPXSource* s = iPlaybackUtility->Source();
if ( s )
{
RArray<TMPXAttribute> attrs;
// Failing the next operations here is not fatal.
(void) attrs.Append( KMPXMediaGeneralTitle );
(void) attrs.Append( KMPXMediaGeneralDuration );
(void) attrs.Append( KMPXMediaGeneralId );
(void) attrs.Append( KMPXMediaMusicArtist );
(void) attrs.Append( KMPXMediaMusicAlbum );
(void) attrs.Append( KMPXMediaMusicGenre );
// Ignore the leave. If this occurs, we just don't get
// an updated media information for time being.
TRAP_IGNORE(s->MediaL( attrs.Array(), *this, NULL ));
attrs.Close();
}
}
}
// ---------------------------------------------------------------------------
// From MPlayerApplicationSettingsNotify
// This is called when the controller has changed a setting
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::MpasnSetPlayerApplicationValueL(
const RArray<TInt>& aAttributeID, const RArray<TInt>& aAttributeValue )
{
MPX_FUNC( "CMPXMetaDataHandlerImp::MpasnSetPlayerApplicationValueL" );
for( TInt i = 0; i < aAttributeID.Count(); i++ )
{
switch( aAttributeID[ i ] )
{
case KAvrcpEqualizerMode:
{
TInt equalizer = aAttributeValue[ i ] == KAvrcpOff ? KEqualizerPresetNone : iLastEqPresetId;
iEqPresetListener->ChangePresetL(equalizer);
// iLastEqPresetId = equalizer;
break;
}
case KAvrcpRepeatMode:
{
// TMPlayerRepeatMode values are in the same order
// as AVRCP 1.3, but starting at 0 instead of 1.
TInt repeat = aAttributeValue[ i ] - 1;
iPlaybackUtility->SetL(EPbPropertyRepeatMode, repeat);
break;
}
case KAvrcpShuffleMode:
{
TBool random = aAttributeValue[ i ] == KAvrcpOff ? EFalse : ETrue;
iPlaybackUtility->SetL(EPbPropertyRandomMode, random);
break;
}
case KAvrcpBassBoostMode:
{
TBool boost = aAttributeValue[ i ] == KAvrcpOff ? EFalse : ETrue;
// iSettingModel->SetBassBoostL( boost );
break;
}
case KAvrcpStereoWideningMode:
{
TBool widening = aAttributeValue[ i ] == KAvrcpOff ? EFalse : ETrue;
// iSettingModel->SetStereoWideningL( widening );
break;
}
default:
{
// Leaving results in sending an error back to the controller.
User::Leave( KErrNotSupported );
break;
}
}
}
}
// -----------------------------------------------------------------------------
// From MRemConMediaInformationTargetObserver
// For each element in aAttributeList the client should respond by calling
// CRemConMediaInformationTarget::AttributeValue(). After all attributes have
// been supplied the client should call CRemConMediaInformationTarget::Completed().
// @param aAttributeList A list of TAttributeID requested by the controller
// -----------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata(
TMediaAttributeIter& aAttributeIter )
{
MPX_FUNC( "CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata" );
const TInt KMaxMediaAttrLen = 300; // >110 is required for AVRCP fragmentation
TBuf8<KMaxMediaAttrLen> attrBuf;
TMediaAttributeId attrId;
aAttributeIter.Start();
while( aAttributeIter.Next( attrId ) )
{
TInt err = KErrNotFound;
HBufC* detail = NULL;
TInt64 val = 0;
switch( attrId )
{
case ETitleOfMedia:
{
detail = iTrackTitle;
break;
}
case ENameOfArtist:
{
detail = iArtist;
break;
}
case ENameOfAlbum:
{
detail = iAlbum;
break;
}
case ETrackNumber:
{
val = iTrackNumber;
break;
}
case ENumberOfTracks:
{
MMPXSource* s = iPlaybackUtility->Source();
if ( s )
{
CMPXCollectionPlaylist* pl = NULL;
TRAP(err, pl = s->PlaylistL());
if( !err && pl )
{
val = pl->Count(); // What if PlaylistItemCount is zero?
}
delete pl;
}
break;
}
case EGenre:
{
detail = iGenre;
break;
}
case EPlayingTime:
{
// No need to check for boundaries, assuming the file length < 10^15 seconds
val = iPlayingTime; // If playing time does not exist, what then?
break;
}
default:
break;
}
if( val )
{
// 'val' and 'detail' are mutually exclusive. We still set detail to
// null, to avoid the possiblility that "delete detail" will delete
// a member variable if NewL fails.
detail = NULL;
TRAP_IGNORE( detail = HBufC::NewL( KMaxMediaAttrLen ) );
if( detail )
{
detail->Des().NumUC( val );
}
}
if( detail )
{
const TInt returnValue = CnvUtfConverter::ConvertFromUnicodeToUtf8( attrBuf, *detail );
if ( returnValue == CnvUtfConverter::EErrorIllFormedInput)
{
MPX_DEBUG1( "CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata - Illformed string, sending zero length response" );
attrBuf.Zero();
}
else if ( returnValue > 0 )
{
MPX_DEBUG1( "CMPXMetaDataHandlerImp::MrcmitoGetCurrentlyPlayingMetadata - Could not convert whole string, sending converted fragment" );
}
}
if( val )
{
delete detail;
detail = NULL;
}
iMediaInfoTarget->AttributeValue( attrId, attrBuf );
}
iMediaInfoTarget->Completed();
}
// ---------------------------------------------------------------------------
// From class MRemConGroupNavigationTargetObserver.
// A 'Next Group' command has been received.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::MrcgntoNextGroup(TRemConCoreApiButtonAction aButtonAct)
{
MPX_FUNC( "CMPXMetaDataHandlerImp::MrcgntoNextGroup" );
(void) aButtonAct;
// Not supported yet, return an error.
TRequestStatus* status = NULL;
iGroupNavigationTarget->NextGroupResponse( status, KErrAvrcpMetadataInvalidParameter );
}
// ---------------------------------------------------------------------------
// From class MRemConGroupNavigationTargetObserver.
// A 'Previous Group' command has been received.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::MrcgntoPreviousGroup(TRemConCoreApiButtonAction aButtonAct)
{
MPX_FUNC( "CMPXMetaDataHandlerImp::MrcgntoPreviousGroup" );
(void) aButtonAct;
// Not supported yet, return an error.
TRequestStatus* status = NULL;
iGroupNavigationTarget->PreviousGroupResponse( status, KErrAvrcpMetadataInvalidParameter );
}
// ---------------------------------------------------------------------------
// From class MEqualizerPresetChangeListenerObserver
// Callback for receiving changes in the equalizer preset settings.
// ---------------------------------------------------------------------------
//
void CMPXMetaDataHandlerImp::EqualizerPresetChangedL(TInt aNewPreset)
{
MPX_FUNC( "CMPXMetaDataHandlerImp::EqualizerPresetChanged" );
TInt val = KAvrcpOff;
if( aNewPreset != KEqualizerPresetNone)
{
iLastEqPresetId = aNewPreset; // Store last used preset
val = KAvrcpOn;
}
iPlayerApplicationSettingsObserver->SetAttributeL( KAvrcpEqualizerMode, val );
}
// ---------------------------------------------------------------------------
// C++ default constructor
// ---------------------------------------------------------------------------
//
CEqualizerPresetChangeListener::CEqualizerPresetChangeListener(MEqualizerPresetChangeListenerObserver& aObserver)
: CActive(EPriorityStandard),
iObserver(aObserver)
{
MPX_FUNC( "CEqualizerPresetChangeListener::CEqualizerPresetChangeListener" );
}
// ---------------------------------------------------------------------------
// Symbian 2nd-phase constructor
// ---------------------------------------------------------------------------
//
void CEqualizerPresetChangeListener::ConstructL()
{
MPX_FUNC( "CEqualizerPresetChangeListener::ConstructL" );
CActiveScheduler::Add( this );
iRepository = CRepository::NewL(KCRUidMusicPlayerSettings);
}
// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CEqualizerPresetChangeListener* CEqualizerPresetChangeListener::NewL(MEqualizerPresetChangeListenerObserver& aObserver)
{
MPX_FUNC( "CEqualizerPresetChangeListener::NewL" );
CEqualizerPresetChangeListener* self = new(ELeave)CEqualizerPresetChangeListener( aObserver );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CEqualizerPresetChangeListener::~CEqualizerPresetChangeListener()
{
MPX_FUNC( "CEqualizerPresetChangeListener::~CEqualizerPresetChangeListener" );
Stop();
delete iRepository;
}
// ---------------------------------------------------------------------------
// Get the current equalizer preset ID
// ---------------------------------------------------------------------------
//
TInt CEqualizerPresetChangeListener::GetCurrentPresetL()
{
MPX_FUNC( "CEqualizerPresetChangeListener::GetCurrentPresetL" );
TInt preset;
User::LeaveIfError(iRepository->Get(KMPlayerEqPresetId, preset));
return preset;
}
// ---------------------------------------------------------------------------
// Set the equalizer preset
// ---------------------------------------------------------------------------
//
void CEqualizerPresetChangeListener::ChangePresetL(TInt aNewPreset)
{
MPX_FUNC( "CEqualizerPresetChangeListener::ChangePresetL" );
User::LeaveIfError(iRepository->Set(KMPlayerEqPresetId, aNewPreset));
}
// ---------------------------------------------------------------------------
// Start listening to equalizer preset changes
// ---------------------------------------------------------------------------
//
void CEqualizerPresetChangeListener::StartL()
{
MPX_FUNC( "CEqualizerPresetChangeListener::StartL" );
User::LeaveIfError(iRepository->NotifyRequest(KMPlayerEqPresetId, iStatus));
SetActive();
}
// ---------------------------------------------------------------------------
// Stop listening to equalizer preset changes
// ---------------------------------------------------------------------------
//
void CEqualizerPresetChangeListener::Stop()
{
MPX_FUNC( "CEqualizerPresetChangeListener::Stop" );
Cancel();
}
// ---------------------------------------------------------------------------
// From class CActive.
// Called by the active scheduler when the request has been completed.
// ---------------------------------------------------------------------------
//
void CEqualizerPresetChangeListener::RunL()
{
MPX_FUNC( "CEqualizerPresetChangeListener::RunL" );
iObserver.EqualizerPresetChangedL(GetCurrentPresetL());
StartL();
}
// ---------------------------------------------------------------------------
// From class CActive.
// Called by the active scheduler when the request has been cancelled.
// ---------------------------------------------------------------------------
//
void CEqualizerPresetChangeListener::DoCancel()
{
MPX_FUNC( "CEqualizerPresetChangeListener::DoCancel" );
iRepository->NotifyCancel(KMPlayerEqPresetId);
delete iRepository;
iRepository = NULL;
}
// ---------------------------------------------------------------------------
// From class CActive.
// Called by the active scheduler when an error in RunL has occurred.
// ---------------------------------------------------------------------------
//
TInt CEqualizerPresetChangeListener::RunError( TInt aError )
{
MPX_FUNC( "CEqualizerPresetChangeListener::RunError" );
(void) aError;
// In case of an exception in RunL, re-subscribe to Central Repository,
// and ignore the return value. If it fails we just won't be sending
// equalizer updates anymore.
if( !iRepository->NotifyRequest( KMPlayerEqPresetId, iStatus ) )
{
SetActive();
}
return KErrNone;
}