mpxmusicplayer/mediakeyhandler/src/mpxmediakeyhandlerimp.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 12 Mar 2010 15:42:25 +0200
branchRCL_3
changeset 14 943ff5625028
parent 2 b70d77332e66
child 18 c54d95799c80
permissions -rw-r--r--
Revision: 201007 Kit: 201008

/*
* 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(0);
            TFileName subPlayerName;
            TMPXPlaybackPlayerType currentPlayerType = EPbLocal;
            GetSubPlayerInfoL(subPlayerName, currentPlayerType);
            
        	if ( currentPlayerType == EPbRemote )
                {
        	    volume = iUpnpVolume % ( KPbPlaybackVolumeLevelMax / iVolumeSteps )
            	                    + iCurrentVol * KPbPlaybackVolumeLevelMax / iVolumeSteps;
        	    }
        	else
        	    {
        	    volume = 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