mpxmusicplayer/mediakeyhandler/src/mpxmediakeyhandlerimp.cpp
changeset 0 ff3acec5bc43
child 2 b70d77332e66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpxmusicplayer/mediakeyhandler/src/mpxmediakeyhandlerimp.cpp	Thu Dec 17 08:45:05 2009 +0200
@@ -0,0 +1,1277 @@
+/*
+* Copyright (c) 2006 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 media key handler
+*
+*/
+
+
+// INCLUDE FILES
+#include <bldvariant.hrh>
+#include <remconcoreapitarget.h>
+#include <remconcoreapitargetobserver.h>
+#include <remconinterfaceselector.h>
+#include <aknconsts.h>
+#include <AknUtils.h>
+#include <eikenv.h>
+#include <bautils.h>
+#include <StringLoader.h>
+#include <apgwgnam.h>
+
+#ifdef UPNP_INCLUDED
+#include <upnpcopycommand.h>  
+#endif
+
+
+#include <aknnotewrappers.h>  // AknErrorNote
+#include <AknVolumePopup.h>
+
+#include <mpxplaybackutility.h>
+#include <mpxplaybackmessage.h>
+#include <data_caging_path_literals.hrh>
+#include <mpxmediakeyhandler.rsg>
+#include <mpxmedia.h>
+#include <mpxmessagegeneraldefs.h>
+#include <mpxplaybackmessagedefs.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxuser.h>
+#include <mpxmediakeyhandler.h>
+#include <mpxlog.h>
+#include <layoutmetadata.cdl.h>
+#include <mpxconstants.h>
+
+#include "mpxmetadatahandler.h"
+#include <mpxplaybackframeworkdefs.h>
+#include <sounddevice.h>
+#include "mpxmediakeyhandlerimp.h"
+#include "mpxremconkeyresponse.h"
+#include "mpxnotifierdialog.h"
+
+
+// CONSTANTS
+const TInt KFirstTimerExpiryInterval( 1 ); // Expire immediately
+const TInt KTimerExpiryInterval( KAknStandardKeyboardRepeatRate );
+const TInt KMPXOneSecInMilliSecs( 1000 );
+const TInt KMPXMinVolume(0);
+const TInt KMPXMaxVolume(100);		// Max volume used in volume popup
+const TInt KMPXVolumeSteps(1);
+const TInt KTenStepsVolume = 10;   
+const TInt KTwentyStepsVolume = 20;
+
+_LIT( KMPXMediaKeyHandlerRscPath, "mpxmediakeyhandler.rsc" );
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CMPXMediaKeyHandlerImp::CMPXMediaKeyHandlerImp(
+    MMPXMediaKeyHandlerObserver* aObserver ) :
+    iObserver( aObserver ),
+    iEnable( ETrue ),
+    iCurrentVol( KErrNotFound ),
+    iVolumeSteps(KMPXMaxVolume)
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::ConstructL(
+	TMPXMediaKeyPopupFlags aFlags )
+    {
+	ASSERT( iObserver );
+    CCoeEnv* coeEnv = CEikonEnv::Static();
+    TParse parse;
+    parse.Set( KMPXMediaKeyHandlerRscPath, &KDC_APP_RESOURCE_DIR, NULL );
+    TFileName resourceFile( parse.FullName() );
+    User::LeaveIfError( MPXUser::CompleteWithDllPath( resourceFile ) );
+    BaflUtils::NearestLanguageFile( coeEnv->FsSession(), resourceFile );
+    iResourceOffset = coeEnv->AddResourceFileL( resourceFile );
+
+    // Register to remote control framework
+    iInterfaceSelector = CRemConInterfaceSelector::NewL();
+    iCoreTarget = CRemConCoreApiTarget::NewL( *iInterfaceSelector, *this );
+    // For handling AVRCP 1.3 metadata
+    iMetaDataHandler = MMPXMetaDataHandler::NewL(*iInterfaceSelector);
+    iInterfaceSelector->OpenTargetL();
+    iResponseHandler = CMPXRemConKeyResponse::NewL( *iCoreTarget );
+
+    // Timer for implementing repeat
+    iTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+
+    // Get the playback utility instance from engine.
+    iPlaybackUtility = MMPXPlaybackUtility::UtilityL( KPbModeDefault );
+    iPlaybackUtility->AddObserverL( *this );
+    // get the current Volume and Max Volume
+    iPlaybackUtility->PropertyL(*this, EPbPropertyVolume);
+    iPlaybackUtility->PropertyL(*this, EPbPropertyMute);
+    CMMFDevSound* devsound = CMMFDevSound::NewL();	
+    MPX_DEBUG2( "CMPXMediaKeyHandlerImp::Constructdevsound->MaxVolume()%d",devsound->MaxVolume());
+    iVolumeSteps = KTenStepsVolume; //Default 10 steps
+    if ( devsound && devsound->MaxVolume() >= KTwentyStepsVolume ) 
+        {
+         // set 20-steps volume
+         iVolumeSteps = KTwentyStepsVolume;
+        }    
+    delete devsound;
+    if ( aFlags & EDisplayVolumePopup )
+        {
+        // Popup volume control
+        iVolPopup = CAknVolumePopup::NewL(NULL, ETrue);
+        iVolPopup->SetObserver(this);
+        iVolPopup->SetRange(KMPXMinVolume, iVolumeSteps);
+        iVolPopup->SetStepSize(KMPXVolumeSteps);
+
+        HBufC* popupText = StringLoader::LoadLC( R_MPX_VOLUME_POPUP_TEXT );
+        iVolPopup->SetTitleTextL( *popupText );
+        CleanupStack::PopAndDestroy( popupText );
+        }
+
+    if ( aFlags & EDisplayMediaPopup )
+        {
+        // Playback popup
+        iPlaybackPopup = CMPXNotifierDialog::NewL();
+        }
+
+    MMPXSource* s = iPlaybackUtility->Source();
+    if ( s )
+        {
+        RArray<TMPXAttribute> attrs;
+        CleanupClosePushL(attrs);
+        attrs.Append( KMPXMediaGeneralTitle );
+        s->MediaL( attrs.Array(), *this );
+        CleanupStack::PopAndDestroy( &attrs );
+        }
+    else
+        {
+        // No current track.
+        // This is constructed so that the first popup will display
+        // it doesn't hold anything.
+        iTrackTitle = HBufC::NewL( 1 );
+        }
+#ifdef UPNP_INCLUDED
+    if (!iUpnpCopyCommand )
+        {
+        MPX_TRAPD ( error, iUpnpCopyCommand = CUpnpCopyCommand::NewL() );   
+		    if ( error == KErrNone )
+            {
+            iUpnpFrameworkSupport = ETrue;
+            }
+        else
+            {
+            iUpnpFrameworkSupport = EFalse;
+			iUpnpCopyCommand = NULL;
+            }
+        }
+#endif
+    }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+MMPXMediaKeyHandler* CMPXMediaKeyHandlerImp::NewL(
+    TMPXMediaKeyPopupFlags aFlags,
+    MMPXMediaKeyHandlerObserver* aObserver )
+    {
+    CMPXMediaKeyHandlerImp* self =
+        new(ELeave)CMPXMediaKeyHandlerImp( aObserver );
+    CleanupStack::PushL( self );
+    self->ConstructL( aFlags );
+    CleanupStack::Pop();
+
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMPXMediaKeyHandlerImp::~CMPXMediaKeyHandlerImp()
+    {
+    if ( iPlaybackUtility )
+        {
+        TRAP_IGNORE( iPlaybackUtility->RemoveObserverL( *this ) );
+        iPlaybackUtility->Close();
+        }
+
+    delete iMetaDataHandler;
+
+    delete iResponseHandler;
+    delete iInterfaceSelector;
+
+    if( iTimer )
+        {
+        iTimer->Cancel();
+        delete iTimer;
+        }
+
+    if ( iResourceOffset )
+        {
+        CEikonEnv::Static()->DeleteResourceFile( iResourceOffset );
+        }
+
+    delete iTrackTitle;
+    delete iVolPopup;
+    delete iPlaybackPopup;
+#ifdef UPNP_INCLUDED
+    if ( iUpnpCopyCommand)
+        {
+        delete iUpnpCopyCommand;
+        }
+#endif
+    }
+
+// ---------------------------------------------------------------------------
+// Filter and send command to playback utility.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::FilterAndSendCommand(
+    TMPXPlaybackCommand aCommandId )
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::FilterAndSendCommand" );
+    TRAP_IGNORE( DoFilterAndSendCommandL( aCommandId ) );
+    }
+
+// ---------------------------------------------------------------------------
+// Help filter and send command to playback utility.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::DoFilterAndSendCommandL(
+    TMPXPlaybackCommand aCommandId )
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::DoFilterAndSendCommandL" );
+    // Only send media key events if the media key component is enabled
+    if( iEnable )
+        {
+        TBool forwardCommand = ETrue;
+        if ( iUpnpFrameworkSupport )
+            {
+            switch ( aCommandId )
+                {
+                case EPbCmdStartSeekForward:
+                case EPbCmdStartSeekBackward:
+                    {
+                    if ( IsUpnpVisibleL() )
+                        {
+                        TFileName subPlayerName;
+                        TMPXPlaybackPlayerType currentPlayerType = EPbLocal;
+                        GetSubPlayerInfoL(subPlayerName, currentPlayerType);
+
+                        if ( currentPlayerType != EPbLocal)
+                            {
+                            //show error note
+                            HBufC* dialogText = StringLoader::LoadLC(R_MPX_MEDIA_KEY_NOT_SUPPORTED);
+                            CAknErrorNote* errNote = new(ELeave) CAknErrorNote(ETrue);
+                            errNote->SetTimeout(CAknNoteDialog::ELongTimeout);
+                            errNote->ExecuteLD( *dialogText );
+                            CleanupStack::PopAndDestroy( dialogText );
+                            forwardCommand = EFalse;
+                            }
+                        }
+                    break;
+                    }
+                default:
+                    {
+                    //do nothing
+                    break;
+                    }
+                }
+            }
+
+        if ( forwardCommand )
+            {
+            iVolumeEventCount++;
+            
+            TInt volume = iUpnpVolume % ( KPbPlaybackVolumeLevelMax / iVolumeSteps )
+                    + iCurrentVol * KPbPlaybackVolumeLevelMax / iVolumeSteps;
+
+			if ( volume < KMPXMinVolume )
+				{
+				volume = KMPXMinVolume;
+				}
+			if ( volume > KMPXMaxVolume )
+				{
+				volume = KMPXMaxVolume;
+				}
+			
+			iObserver->HandleMediaKeyCommand( aCommandId, volume );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Handle playback message.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::DoHandlePlaybackMessageL(
+    const CMPXMessage& aMessage )
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::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( "CMPXMediaKeyHandlerImp::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);
+                    attrs.Append( KMPXMediaGeneralTitle );
+                    MPX_DEBUG1( "CMPXMediaKeyHandlerImp::HandlePlaybackMessageL Media changed, calling MediaL to refresh" );
+                    s->MediaL( attrs.Array(), *this );
+                    CleanupStack::PopAndDestroy( &attrs );
+                    }
+                break;
+                }
+            case TMPXPlaybackMessage::ECommandReceived:
+                {
+                MPX_DEBUG2( "CMPXMediaKeyHandlerImp::HandlePlaybackMessageL - ECommandReceived(%d)", type );
+                break;
+                }
+            case TMPXPlaybackMessage::ESkipping:
+                {
+                iSkipping = ETrue;
+                break;
+                }
+            case TMPXPlaybackMessage::ESkipEnd:
+                {
+                iSkipping = EFalse;
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Handle playback property.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::DoHandlePropertyL(
+    TMPXPlaybackProperty aProperty,
+    TInt aValue,
+    TInt aError )
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::DoHandlePropertyL" );
+    MPX_DEBUG4( "CMPXMediaKeyHandlerImp::HandlePropertyL - Property(%d); Value(%d); Error(%d)", aProperty, aValue, aError );
+
+    iUpnpVolume = aValue; 
+    if ( KErrNone == aError )
+        {
+        switch ( aProperty	)
+            {
+            case EPbPropertyPosition:
+                {
+                iPlaybackPosition = aValue / KMPXOneSecInMilliSecs;
+                ShowPlaybackPopupL( EMPXPopupShowIfVisible );
+                break;
+                }
+            case EPbPropertyMute:
+            	{
+                if ( iTouchVolEventCount > 0 )
+                    {
+                    --iTouchVolEventCount;
+                    }
+                if ( iVolumeEventCount > 0 )
+                	{
+                	--iVolumeEventCount;
+                	}
+            	iMuted = aValue;
+            	if ( iMuted )
+            	    {
+            	    iVolPopup->SetValue( 0 );
+            	    }
+            	else
+            		{
+            		iVolPopup->SetValue( iCurrentVol );
+            		}
+				break;
+				}
+			case EPbPropertyVolume:
+                {
+				if ( iVolPopup )
+					{
+	                if ( iTouchVolEventCount > 0 )
+	                    {
+	                    --iTouchVolEventCount;
+	                    }
+					// Avkon Volume has 10 steps, but the rest of the framework
+                    // has 100 steps. Need to scale it to 10 steps.
+                    if ( aValue > 0 )
+                        {
+                        aValue = aValue * iVolumeSteps;
+                        aValue = aValue / KPbPlaybackVolumeLevelMax;
+                        if ( aValue > iVolumeSteps )
+                        	{
+                        	aValue = iVolumeSteps;
+                        	}
+                        }
+
+					if( iMuted && aValue > 0 ) // unmute
+			            {
+			            iMuted = EFalse;
+			            iCurrentVol = aValue;
+			            iVolPopup->SetValue( iCurrentVol );
+			            }
+		            else if( aValue == 0 ) // mute
+			            {
+			            if( !iMuted ) 
+				            {
+				            iMuted = ETrue;
+				            iVolPopup->SetValue( 0 );
+				            }
+			            }
+                    else if ( aValue != iCurrentVol && !iTouchVolEventCount && !iVolumeEventCount )
+					    {
+					    if ( aValue != 0 )
+					        {
+					        iCurrentVol = aValue;
+					        }
+				        iVolPopup->SetValue( iCurrentVol );
+					    }
+
+				    if ( iVolumeEventCount > 0 )
+				    	{
+				    	--iVolumeEventCount;
+					    }
+
+                    // send a command to UI to display Volume bar on device when controlling volume via UPnP  
+                    if ( IsUpnpVisibleL() && iPlayerState != EPbStateNotInitialised )
+                        {
+                        TFileName subPlayerName;
+                        TMPXPlaybackPlayerType currentPlayerType = EPbLocal;
+                        GetSubPlayerInfoL( subPlayerName, currentPlayerType );
+
+                        if ( currentPlayerType != EPbLocal )
+                            {
+                            iObserver->HandleMediaKeyCommand( EPbCmdSetVolume, iUpnpVolume ); 
+                            }            
+                        }
+							  
+					if ( iUpnpFrameworkSupport )
+						{
+						SetVolumePopupTitleL();
+						}
+					}
+				break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+        }
+    else
+        {
+        switch ( aProperty	)
+            {
+            case EPbPropertyVolume:
+            case EPbPropertyMute:
+                {
+                if ( iVolPopup && iShowPopups & EDisplayVolumePopup )
+                    {
+                    //show error note
+                    HBufC* dialogText = StringLoader::LoadLC(R_MPX_VOLUME_KEYS_NOT_SUPPORTED);
+                    CAknErrorNote* errNote = new(ELeave) CAknErrorNote(ETrue);
+                    errNote->SetTimeout(CAknNoteDialog::ELongTimeout);
+                    errNote->ExecuteLD( *dialogText );
+                    CleanupStack::PopAndDestroy( dialogText );
+                    }
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Handle media properties.
+// Notes: The client is responsible for delete the object of aProperties.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::DoHandleMediaL(
+    const CMPXMedia& aMedia,
+    TInt aError )
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::DoHandleMediaL" );
+
+    // Delete old title no matter there's error or not
+    if ( iTrackTitle )
+        {
+        delete iTrackTitle;
+        iTrackTitle = NULL;
+        }
+
+    if ( KErrNone == aError )
+        {
+        // Keep track of the current track's title
+        iTrackTitle = aMedia.ValueText( KMPXMediaGeneralTitle ).AllocL();
+
+        // Update popup if visible
+        if ( iShowPopups & EDisplayMediaPopup )
+            {
+            MPX_DEBUG1( "CMPXMediaKeyHandlerImp::DoHandleMediaL EMPXPopupTimeout" );
+            ShowPlaybackPopupL( EMPXPopupTimeout );
+            }
+        else
+            {
+            ShowPlaybackPopupL( EMPXPopupShowIfVisible );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Handle playback state changed.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::DoHandleStateChangedL(
+    TMPXPlaybackState aState )
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::DoHandleStateChangedL" );
+    switch ( aState )
+        {
+        case EPbStateStopped:
+            {
+            iPlayerState = aState;
+            ShowPlaybackPopupL( EMPXPopupShowIfVisible );
+            break;
+            }
+        case EPbStatePlaying:
+        case EPbStatePaused:
+            {
+            iPlayerState = aState;
+            // Start the time if needed, otherwise, update content if visible
+            if ( iShowPopups & EDisplayMediaPopup )
+                {
+                MPX_DEBUG1( "CMPXMediaKeyHandlerImp::DoHandleStateChangedL EMPXPopupTimeout" );
+                ShowPlaybackPopupL( EMPXPopupTimeout );
+                }
+            else
+                {
+                ShowPlaybackPopupL( EMPXPopupShowIfVisibleRestartTimer );
+                }
+            break;
+            }
+        default:
+            {
+            // do nothing
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Callback for timer
+// ---------------------------------------------------------------------------
+//
+TInt CMPXMediaKeyHandlerImp::TimerCallback( TAny* aPtr )
+    {
+    static_cast<CMPXMediaKeyHandlerImp*>( aPtr )->HandleRepeatEvent();
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handle repeat event
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::HandleRepeatEvent()
+    {
+	UpdateVolume();
+    FilterAndSendCommand( iCommandId );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMediaKeyHandlerImp::GetSubPlayerInfoL
+// Retrieves the current player name and sets the volume popup title
+// -----------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::GetSubPlayerInfoL(
+    TDes& aSubPlayerName,
+    TMPXPlaybackPlayerType& aCurrentPlayerType )
+    {
+    aCurrentPlayerType = EPbLocal;
+    aSubPlayerName = KNullDesC;
+
+//#ifdef __UPNP_FRAMEWORK_2_0_
+    if ( iUpnpFrameworkSupport )
+        {
+        MMPXPlayerManager& manager = iPlaybackUtility->PlayerManager();
+        TUid currentlyUsedPlayer;
+        TInt currentlyUsedSubPlayer;
+        HBufC* subPlayerName = NULL;
+        TRAP_IGNORE( manager.GetSelectionL( aCurrentPlayerType,
+                                            currentlyUsedPlayer,
+                                            currentlyUsedSubPlayer,
+                                            subPlayerName ) );
+        if ( subPlayerName )
+            {
+            aSubPlayerName = (*subPlayerName);
+            delete subPlayerName;
+            }
+        }
+//#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMediaKeyHandlerImp::SetVolumePopupTitleL
+// Retrieves the current player name and sets the volume popup title
+// -----------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::SetVolumePopupTitleL()
+    {
+    if ( iUpnpFrameworkSupport && IsUpnpVisibleL() )
+        {
+        TFileName subPlayerName;
+        TMPXPlaybackPlayerType currentPlayerType = EPbLocal;
+
+        GetSubPlayerInfoL(subPlayerName, currentPlayerType);
+        if ( currentPlayerType != EPbLocal)
+            {
+            iVolPopup->SetTitleTextL( subPlayerName );
+            }
+        else  // need to restore original title
+            {
+            HBufC* popupText = StringLoader::LoadLC( R_MPX_VOLUME_POPUP_TEXT );
+            iVolPopup->SetTitleTextL( *popupText );
+            CleanupStack::PopAndDestroy( popupText );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMediaKeyHandlerImp::IsUpnpVisibleL
+// Taken from Gallery upnp support implementation
+// -----------------------------------------------------------------------------
+//
+TBool CMPXMediaKeyHandlerImp::IsUpnpVisibleL()
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::IsUpnpVisible" );
+    TBool returnValue = EFalse;
+#ifdef UPNP_INCLUDED
+   	if ( iUpnpCopyCommand && iUpnpFrameworkSupport ) 	  
+   	    {
+        returnValue = iUpnpCopyCommand->IsAvailableL();   
+        }
+#endif
+    return returnValue; 
+    }
+
+// ---------------------------------------------------------------------------
+// Updates the volume and the volume command
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::UpdateVolume()
+	{
+	// Current volume level is not yet initialised
+    if( iCurrentVol < 0 )
+        {
+        MPX_DEBUG1( "CMPXMediaKeyHandlerImp::UpdateVolume not initialised");
+        return;
+        }
+
+	if ( iIncreaseVol )
+		{
+		if ( iMuted )
+			{
+			iMuted = EFalse;
+			iCommandId = EPbCmdUnMuteVolume;
+			iVolPopup->SetValue( iCurrentVol );
+			}
+		else
+			{
+			iCommandId = EPbCmdSetVolume;
+			iCurrentVol = iCurrentVol < iVolumeSteps ? (iCurrentVol + 1) : iCurrentVol;	// +KMPXVolumeSteps; ?
+			iVolPopup->SetValue( iCurrentVol );
+			}
+		}
+	else
+		{
+		if ( iCurrentVol == 1 )
+			{
+			iMuted = ETrue;
+			iCommandId = EPbCmdMuteVolume;
+			iVolPopup->SetValue( 0 );
+			}
+		else if ( iMuted )	// Muted && volume > 1
+			{
+			iMuted = EFalse;
+			iCommandId = EPbCmdUnMuteVolume;
+			iVolPopup->SetValue( iCurrentVol );
+			}
+		else
+			{
+			iCommandId = EPbCmdSetVolume;
+			iCurrentVol = iCurrentVol - 1;	// KMPXVolumeSteps ?
+			iVolPopup->SetValue( iCurrentVol );
+			}
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// From MMPXMediaKeyHandler
+// Show playback popup.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::ShowPlaybackPopupL(
+    TMPXPlaybackPopupModes aMode )
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::ShowPlaybackPopupL" );
+
+    // Check to see is it ok to display popup
+    if ( !iPlaybackPopup || !iTrackTitle )
+        {
+        return;
+        }
+
+    switch ( aMode )
+        {
+        case EMPXPopupShowIfVisibleRestartTimer:
+        case EMPXPopupTimeout:
+            {
+            iShowPopups &= ~EDisplayMediaPopup;
+            break;
+            }
+        case EMPXPopupNoTimeout:
+            {
+            iShowPopups |= EDisplayMediaPopup;
+            break;
+            }
+        case EMPXPopupShowIfVisible:
+            {
+            if ( iShowPopups & EDisplayMediaPopup )
+                {
+                aMode = EMPXPopupNoTimeout;
+                }
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+
+    CMPXNotifierDialog::TMPXPlaybackPopupIcons icon(
+        CMPXNotifierDialog::EMPXPopupNoneIcon );
+    TMPXPlaybackState playerState( EPbStateNotInitialised );
+
+    // Get current playback state from playback utility
+    playerState = iPlaybackUtility->StateL();
+    switch ( playerState )
+        {
+        case EPbStatePlaying:
+            {
+            icon = CMPXNotifierDialog::EMPXPopupPlayIcon;
+            break;
+            }
+        case EPbStatePaused:
+            {
+            icon = CMPXNotifierDialog::EMPXPopupPauseIcon;
+            break;
+            }
+        case EPbStateSeekingForward:
+            icon = CMPXNotifierDialog::EMPXPopupFFIcon;
+            break;
+        case EPbStateSeekingBackward:
+            {
+            icon = CMPXNotifierDialog::EMPXPopupFRIcon;
+            break;
+            }
+        case EPbStateStopped:
+            {
+            // no icon if in stopped state
+            break;
+            }
+        default:
+            {
+            // not to display popup in other states
+            return;
+            }
+        }
+
+    if ( iTrackTitle->Length() )
+        {
+        MPX_DEBUG2( "CMPXMediaKeyHandlerImp::ShowPlaybackPopupL aMode = %d", aMode );
+        iPlaybackPopup->ShowInfoPopupL(
+            icon, *iTrackTitle, iSkipping ? KErrNotFound : iPlaybackPosition, aMode );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXMediaKeyHandler
+// Show Volume popup
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::ShowVolumePopupL()
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::ShowVolumePopupL" );
+    if ( iVolPopup )
+        {
+        iShowPopups |= EDisplayVolumePopup;
+        iVolPopup->ShowVolumePopupL();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXMediaKeyHandler
+// Dismiss notifier popup.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::DismissNotifier(
+    TMPXMediaKeyPopupFlags aFlags )
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::DismissNotifier" );
+    if ( aFlags & EDisplayMediaPopup && iPlaybackPopup )
+        {
+        iPlaybackPopup->CancelInfoPopup();
+        iShowPopups &= ~EDisplayMediaPopup;
+        }
+
+    if ( aFlags & EDisplayVolumePopup && iVolPopup )
+        {
+        iVolPopup->CloseVolumePopup();
+        iShowPopups &= ~EDisplayVolumePopup;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXMediaKeyHandler
+// Enable or disable media keys
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::SetEnableMediaKeys( TBool aEnable )
+    {
+    iEnable = aEnable;
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXMediaKeyHandler
+// Gets called when orientation change begins
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::NotifyOrientationChangeBegin()
+	{
+	iPlaybackPopup->NotifyOrientationChangeBegin();
+	}
+
+// From MMPXPlaybackObserver
+// Handle playback message.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::HandlePlaybackMessage(
+    CMPXMessage* aMessage, TInt aError )
+    {
+    if ( aError == KErrNone && aMessage )
+        {
+        TRAP_IGNORE( DoHandlePlaybackMessageL( *aMessage ) );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXPlaybackCallback
+// Handle playback property.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::HandlePropertyL(
+    TMPXPlaybackProperty aProperty,
+    TInt aValue,
+    TInt aError )
+    {
+    TRAP_IGNORE( DoHandlePropertyL( aProperty, aValue, aError ) );
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXPlaybackCallback
+// Method is called continously until aComplete=ETrue, signifying that
+// it is done and there will be no more callbacks
+// Only new items are passed each time
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::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 CMPXMediaKeyHandlerImp::HandleMediaL(
+    const CMPXMedia& aMedia,
+    TInt aError )
+    {
+    MPX_FUNC( "CMPXMediaKeyHandlerImp::HandleMediaL" );
+    TRAP_IGNORE( DoHandleMediaL( aMedia, aError ) );
+    }
+
+// ---------------------------------------------------------------------------
+// A 'play' command has been received.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::MrccatoPlay(
+    TRemConCoreApiPlaybackSpeed /* aSpeed */,
+    TRemConCoreApiButtonAction aButtonAct )
+    {
+    MPX_DEBUG2( "-->CMPXMediaKeyHandlerImp::MrccatoPlay(aButtonAct=%d)", aButtonAct );
+
+    if ( ( aButtonAct == ERemConCoreApiButtonClick ) ||
+        ( aButtonAct == ERemConCoreApiButtonPress ) )
+        {
+        FilterAndSendCommand( EPbCmdPlay );
+        }
+    iResponseHandler->CompleteAnyKey( ERemConCoreApiPlay );
+    MPX_DEBUG1( "<--CMPXMediaKeyHandlerImp::MrccatoPlay");
+    }
+
+// ---------------------------------------------------------------------------
+// A command has been received.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::MrccatoCommand(
+    TRemConCoreApiOperationId aOperationId,
+    TRemConCoreApiButtonAction aButtonAct )
+    {
+    MPX_DEBUG3( "CMPXMediaKeyHandlerImp::MrccatoCommand(aOperationId=%d, aButtonAct=%d)", aOperationId, aButtonAct );
+
+    switch (aOperationId)
+        {
+        case ERemConCoreApiPausePlayFunction:
+            {
+            if ( aButtonAct == ERemConCoreApiButtonClick )
+                {
+                FilterAndSendCommand( EPbCmdPlayPause );
+                }
+            break;
+            }
+        case ERemConCoreApiPlay:
+            {
+            if ( ( aButtonAct == ERemConCoreApiButtonClick ) ||
+                ( aButtonAct == ERemConCoreApiButtonPress ) )
+                {
+                FilterAndSendCommand( EPbCmdPlay );
+                }
+            break;
+            }
+        case ERemConCoreApiStop:
+            {
+            if ( ( aButtonAct == ERemConCoreApiButtonClick ) ||
+                ( aButtonAct == ERemConCoreApiButtonPress ) )
+                {
+                FilterAndSendCommand( EPbCmdStop );
+                }
+            break;
+            }
+        case ERemConCoreApiPause:
+            {
+            if ( ( aButtonAct == ERemConCoreApiButtonClick ) ||
+                ( aButtonAct == ERemConCoreApiButtonPress ) )
+                {
+                FilterAndSendCommand( EPbCmdPause );
+                }
+            break;
+            }
+        case ERemConCoreApiRewind:
+            {
+            switch ( aButtonAct )
+                {
+                case ERemConCoreApiButtonPress:
+                    {
+                    FilterAndSendCommand( EPbCmdStartSeekBackward );
+                    break;
+                    }
+                case ERemConCoreApiButtonRelease:
+                    {
+                    FilterAndSendCommand( EPbCmdStopSeeking );
+                    break;
+                    }
+                default:
+                    {
+                    break;
+                    }
+                }
+            break;
+            }
+        case ERemConCoreApiFastForward:
+            {
+            switch ( aButtonAct )
+                {
+                case ERemConCoreApiButtonPress:
+                    {
+                    FilterAndSendCommand( EPbCmdStartSeekForward );
+                    break;
+                    }
+                case ERemConCoreApiButtonRelease:
+                    {
+                    FilterAndSendCommand( EPbCmdStopSeeking );
+                    break;
+                    }
+                default:
+                    {
+                    break;
+                    }
+                }
+            break;
+            }
+        case ERemConCoreApiBackward:
+            {
+            if ( aButtonAct == ERemConCoreApiButtonClick )
+                {
+                FilterAndSendCommand( EPbCmdPrevious );
+                }
+            break;
+            }
+        case ERemConCoreApiForward:
+            {
+            if ( aButtonAct == ERemConCoreApiButtonClick )
+                {
+                FilterAndSendCommand( EPbCmdNext );
+                }
+            break;
+            }
+        case ERemConCoreApiVolumeUp:
+        case ERemConCoreApiVolumeDown:
+            {
+            iTimer->Cancel();
+            
+            MMPXPlaybackUtility* pbUtil = MMPXPlaybackUtility::UtilityL( KPbModeActivePlayer );
+            CleanupClosePushL(*pbUtil);
+                
+            TMPXPlaybackState playerState( EPbStateNotInitialised );
+            playerState = pbUtil->StateL();
+                    
+            CleanupStack::PopAndDestroy(pbUtil);
+            
+            if( playerState == EPbStatePlaying || IsAppForeground() )
+                {
+                iIncreaseVol = (aOperationId == ERemConCoreApiVolumeUp ? ETrue: EFalse);
+                switch (aButtonAct)
+                    {
+                    case ERemConCoreApiButtonPress:
+                        {
+                        //Start Timer
+                        iTimer->Start(
+                            KFirstTimerExpiryInterval,
+                            KTimerExpiryInterval,
+                            TCallBack( TimerCallback, this ) );
+                        break;
+                        }
+                    case ERemConCoreApiButtonClick:
+                        {
+                        UpdateVolume();
+                        FilterAndSendCommand( iCommandId );
+                        break;
+                        }
+                    case ERemConCoreApiButtonRelease:
+                    default:
+                        {
+                        break;
+                        }
+                    }
+                }
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+    iResponseHandler->CompleteAnyKey( aOperationId );
+    MPX_DEBUG1( "<--CMPXMediaKeyHandlerImp::MrccatoCommand");
+    }
+
+// ---------------------------------------------------------------------------
+// A 'tune function' command has been received.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::MrccatoTuneFunction(
+    TBool /* aTwoPart */,
+    TUint /* aMajorChannel */,
+    TUint /* aMinorChannel */,
+    TRemConCoreApiButtonAction /* aButtonAct */ )
+    {
+    iResponseHandler->CompleteAnyKey(
+        ERemConCoreApiTuneFunction );
+    }
+
+// ---------------------------------------------------------------------------
+// A 'select disk function' has been received.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::MrccatoSelectDiskFunction(
+    TUint /* aDisk */,
+    TRemConCoreApiButtonAction /* aButtonAct */ )
+    {
+    iResponseHandler->CompleteAnyKey(
+        ERemConCoreApiSelectDiskFunction );
+    }
+
+// ---------------------------------------------------------------------------
+// A 'select AV input function' has been received.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::MrccatoSelectAvInputFunction(
+    TUint8 /* aAvInputSignalNumber */,
+    TRemConCoreApiButtonAction /* aButtonAct */ )
+    {
+    iResponseHandler->CompleteAnyKey(
+        ERemConCoreApiSelectAvInputFunction );
+    }
+
+// ---------------------------------------------------------------------------
+// A 'select audio input function' has been received.
+// ---------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::MrccatoSelectAudioInputFunction(
+    TUint8 /* aAudioInputSignalNumber */,
+    TRemConCoreApiButtonAction /* aButtonAct */ )
+    {
+    iResponseHandler->CompleteAnyKey(
+        ERemConCoreApiSelectAudioInputFunction );
+    }
+
+// ----------------------------------------------------------------------------
+// void CMPlayerBaseView::HandleControlEventL
+// ----------------------------------------------------------------------------
+//
+void CMPXMediaKeyHandlerImp::HandleControlEventL( CCoeControl* aControl, TCoeEvent aEventType )
+	{
+	if ( !AknLayoutUtils::PenEnabled() )
+		{
+		return;
+		}
+
+	if( (aEventType == EEventStateChanged) && (aControl == iVolPopup) )
+		{
+		TInt vol = iVolPopup->Value();
+		if ( vol == iCurrentVol )
+		    {
+            if ( iMuted )
+                {
+                iMuted = EFalse;
+                FilterAndSendCommand( EPbCmdUnMuteVolume );
+                iTouchVolEventCount++;
+                }
+            else
+                {
+                return;
+                }
+		    }
+
+		if ( vol == 0 )
+			{
+			if ( iMuted )
+			    {
+			    return;
+			    }
+			else
+			    {
+			    iMuted = ETrue;
+			    FilterAndSendCommand( EPbCmdMuteVolume );
+			    iTouchVolEventCount++;
+			    }
+			}
+		else
+			{
+			if ( iMuted )
+				{
+				iMuted = EFalse;
+				iVolPopup->SetValue( iCurrentVol );
+				FilterAndSendCommand( EPbCmdUnMuteVolume );
+				iTouchVolEventCount++;
+				}
+			else
+				{
+				iCurrentVol = vol;
+				FilterAndSendCommand( EPbCmdSetVolume );
+				iTouchVolEventCount++;
+				}
+			}
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// Check the mpx app is foreground.
+// ---------------------------------------------------------------------------
+//
+TBool CMPXMediaKeyHandlerImp::IsAppForeground()
+    {
+    TBool isForeground( EFalse );
+    // Gets the window group id of the app in foreground
+    RWsSession& wsSession = CCoeEnv::Static()->WsSession();
+    TInt windowGroupId = wsSession.GetFocusWindowGroup();
+    if ( windowGroupId >= 0 )
+        {
+        TRAP_IGNORE(
+            {
+            CApaWindowGroupName* wgName = CApaWindowGroupName::NewL(
+                wsSession, windowGroupId );
+
+            isForeground = ( wgName->AppUid() == KAppUidMusicPlayerX );
+            delete wgName;
+            } );
+        }
+
+    return isForeground;
+    }
+// End of File