mediakeys/KeyPublisherPlugin/src/KeyPublisher.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 15:08:06 +0300
changeset 21 c4cbaa4fb734
parent 0 2e3d3ce01487
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* Copyright (c) 2005 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: 
*       Animation plugin implementation file
*       
*
*/


// INCLUDE FILES
#include <e32std.h>
#include <e32cmn.h>
#include <mediakeysinternalpskeys.h>
#include <mmkeybearerscancodes.h>
#include <remconcoreapi.h>
#include <uikon.hrh>

#include "KeyPublisher.h"

// CONSTANTS

const TInt KScanCodeMask = 0xFFFF;

#if defined(__WINS__)
const TInt KVolumeUpKeyEmulator   = 0xAC;
const TInt KVolumeDownKeyEmulator = 0xAD;
#endif
// Change these values once peoblem with keys is fixed
const TInt KVolumeUpKeyHardware   = EStdKeyIncVolume;   //0xa3; 
const TInt KVolumeDownKeyHardware = EStdKeyDecVolume;  //0xa2; 

const TInt KMusicPlayHarware     = EStdKeyApplication2;
const TInt KMusicStopHarware     = EStdKeyApplication3;
const TInt KMusicForwardHardware = EStdKeyApplication4;
const TInt KMusicRewindHardware  = EStdKeyApplication5;

// Scan codes in this table are blocked by the Key Publisher Anim plugin
// Table KBlockedKeyCodes[] and KBlockedKeyCodesEvents[][3] must have same 
// number of rows and match correspondingly
const TInt KBlockedKeyCodes[]=
    {
#if defined(__WINS__)    
    /*0*/KVolumeUpKeyEmulator,
    /*1*/KVolumeDownKeyEmulator,
#endif
    /*2*/KVolumeUpKeyHardware,
    /*3*/KVolumeDownKeyHardware,

    /*4*/ KMusicPlayHarware,    
    /*5*/ KMusicStopHarware,    
    /*6*/ KMusicForwardHardware,
    /*7*/ KMusicRewindHardware 

    };
const TInt KBlockedKeyCodesEvents[][3]=
    {     /* Press - 0 */       /* Release - 1 */      /* Click - 2 */
#if defined(__WINS__)    
    /*0*/{KPSVolumeUpPressed,   KPSVolumeUpReleased,   KPSVolumeUpClicked },
    /*1*/{KPSVolumeDownPressed, KPSVolumeDownReleased, KPSVolumeDownClicked },
#endif
    /*2*/{KPSVolumeUpPressed,   KPSVolumeUpReleased,   KPSVolumeUpClicked },
    /*3*/{KPSVolumeDownPressed, KPSVolumeDownReleased, KPSVolumeDownClicked }, 

    /*4*/{EPlayPressed,         EPlayReleased,         EPlayClicked },
    /*5*/{EStopPressed,         EStopReleased,         EStopClicked },
    /*6*/{EFastForwardPressed,  EFastForwardReleased,  EForwardClicked },
    /*7*/{ERewindPressed,       ERewindReleased,       EBackwardClicked }

    };

const TInt KBlockedKeyCodeTableSize = sizeof(KBlockedKeyCodes) / sizeof(TInt);

const TInt KTimerMilliSecond = 1000; // in micro seconds

_LIT_SECURITY_POLICY_C1(KKeyPublisherReadPolicy,  ECapability_None);
_LIT_SECURITY_POLICY_C1(KKeyPublisherWritePolicy, ECapabilityWriteDeviceData);

// Following constants can subject change if duration is not suitable

const TInt KFirstTimerExpiryInterval = 600 * KTimerMilliSecond; // 600mSec
// For second time onwards ,the duration of the time interval, is below
// Should not be grater than 1 Minute
const TInt KTimerExpiryInterval      = 500 * KTimerMilliSecond; // 500mSec

// -----------------------------------------------------------------------
// CKeyPublisher::CKeyPublisher
// Description: Constuctor
// -----------------------------------------------------------------------
//
CKeyPublisher::CKeyPublisher()
: iTimerStarted (EFalse) ,iPressEventSent(EFalse) ,iReleaseEventSent(ETrue),
  iTimerCount(0), iConnected(EFalse)
    {
    }
// -----------------------------------------------------------------------
// CKeyPublisher::~CKeyPublisher
// Description: Destructor
// -----------------------------------------------------------------------
//
CKeyPublisher::~CKeyPublisher()
    {
    
    iSoundSession.Close();
    
    if (iFunctions)
        {
        //switch OFF the animation raw event receiving 
        iFunctions->GetRawEvents(EFalse);
        }
    if(iTimer)
        {
        delete iTimer;
        }
    }
// -----------------------------------------------------------------------
// CKeyPublisher::ConstructL   (part of CWindowAnim)
// Description: Enable the Raw Event handling from Win server. and 
//              create timer (not starting)
// -----------------------------------------------------------------------
//
void CKeyPublisher::ConstructL(TAny* /*aArgs*/, TBool /*aHasFocus*/)
    {
    
    /* iFunction: protected member of CAnim /CWindowAnim
     * Pointer to a class containing functions implemented by the window 
     * server. These are available to any CAnim derived class. Note that 
     * this value is automatically set for you by the animation framework. 
     * we do not need to assign a value to this pointer.
     */
    
    /* This function switches animation raw event handling on and off. If 
     * raw event handling is switched on(ETrue), then raw events, 
     * e.g. pen events, key presses, power events etc., are all offered 
     * to the animation event handling code - MEventHandler::OfferRawEventL().
     */ 
    iFunctions->GetRawEvents(ETrue);
    
    TInt error = iSoundSession.Connect();
    if (error == KErrNone)
        {
        iConnected = ETrue;
		}
    
    // Timer for implementing Pressed/Released/Clicked feature.
    iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
    
    //Define the P&S for Volume keys and Media Keys
    RProperty::Define(KPSUidMediaKeysEventNotifier, KMediaKeysVolumeKeyEvent, 
           RProperty::EInt, KKeyPublisherReadPolicy, KKeyPublisherWritePolicy);
    RProperty::Define(KPSUidMediaKeysEventNotifier, KMediaKeysControlKeyEvent,
           RProperty::EInt, KKeyPublisherReadPolicy, KKeyPublisherWritePolicy);
    // Define Vol Sync Notifier in P & S
    RProperty::Define(KPSUidMediaKeysEventNotifier,KMediaKeysCurrentVolume, 
           RProperty::EInt, KKeyPublisherReadPolicy, KKeyPublisherWritePolicy);
    // Define P&S Key for Volume keys from Accessory device
    RProperty::Define(KPSUidMediaKeysEventNotifier,KMediaKeysAccessoryVolumeEvent, 
           RProperty::EInt, KKeyPublisherReadPolicy, KKeyPublisherWritePolicy);
    }
// -----------------------------------------------------------------------
// CKeyPublisher::IsBlockedKeyCode 
// Description: Search the list of blocked keys by comparing scan codes
// return : ETrue if key is blocked, else EFalse
// -----------------------------------------------------------------------
//
TBool CKeyPublisher::IsBlockedKeyCode(TInt aScanCode)
    {
    for (TInt index=0; index < KBlockedKeyCodeTableSize; index++)
        {
        if (aScanCode == KBlockedKeyCodes[index])
            {
            // Found the Key 
            return ETrue;
            }
        }
    // Not found
    return EFalse;
    }
// -----------------------------------------------------------------------
// CKeyPublisher::GetEnumVal
// Description: Based on the scancode and event, find the Enum value(which
//              are declared in the TRemConCoreApiButtonAction).
//              MMBearerPlugin will decript this enum value.
// return : 
// -----------------------------------------------------------------------
//
TInt CKeyPublisher::GetEnumVal(TInt aScanCode, 
                               TRemConCoreApiButtonAction aEvent)
    {
    TInt result = KPSVolumeNoKey;
    TInt index;

    // Find the Index of the Scan code in the KBlockedKeyCodes[] 
    // and use the same index in KBlockedKeyCodesEvents[][] 
    // for getting enum values
    for (index=0; index < KBlockedKeyCodeTableSize; index++)
        {
        if (aScanCode == KBlockedKeyCodes[index])
            {
            break;
            }
        }

    if (index == KBlockedKeyCodeTableSize)
    {
        // Not found 
        return result;
    }

    result = KBlockedKeyCodesEvents[index][aEvent];
    return result;
    }
// -----------------------------------------------------------------------
// CKeyPublisher::PublishEvent
// Description: Publish the event to P&S based on the Scancode, event
// return : 
// -----------------------------------------------------------------------
//
void CKeyPublisher::PublishEvent(TInt aScanCode, 
                                 TRemConCoreApiButtonAction aEvent)
    {
    TInt uidMMKey;
    
    if ( 
#if defined(__WINS__)        
         (aScanCode == KVolumeUpKeyEmulator)   ||
         (aScanCode == KVolumeDownKeyEmulator) ||
#endif         
         (aScanCode == KVolumeUpKeyHardware)   ||
         (aScanCode == KVolumeDownKeyHardware)  
       )
        {
        uidMMKey = KMediaKeysVolumeKeyEvent; // Volume Keys - Up / down
        }
    else
        {
        uidMMKey = KMediaKeysControlKeyEvent; //Media Keys - play ,stop ,etc
        }

    iProperty.Set(KPSUidMediaKeysEventNotifier,
                  uidMMKey,
                  GetEnumVal(aScanCode, aEvent));

    }   
    
// -----------------------------------------------------------------------
// CKeyPublisher::OfferRawEvent
// Description: This function starts getting called when animation raw 
//              event is switched on by calling GetRawEvents(ETrue)
// return : ETrue  - if key is handled and blocks it to applications
//          EFalse - if not handled here, Apps/other anim plugins will 
//               receive this key event.
// -----------------------------------------------------------------------
//
TBool CKeyPublisher::OfferRawEvent(const TRawEvent &aRawEvent)
    {
    TBool returnValue = EFalse;        // Key not blocked
    TInt scan;
    
    switch (aRawEvent.Type())
        {
        case TRawEvent::EKeyDown:
            {
            scan = aRawEvent.ScanCode() & KScanCodeMask;
            
            if (IsBlockedKeyCode(scan))
                {
                if (iConnected)
                    {
                    iSoundSession.KeyPressed(scan);  	
                    }
                
                if ((! iTimerStarted) && (iReleaseEventSent))
                    {
                    
                    if ((scan != KMusicForwardHardware) && (scan != KMusicRewindHardware))
                    {
	                    // Send Clicked Event
	                    PublishEvent(scan,ERemConCoreApiButtonClick);
                    }

                    //Start Timer
                    iTimer->Start(KFirstTimerExpiryInterval,
                                  KTimerExpiryInterval, 
                                  TCallBack(TimerCallback, this));
                    iTimerStarted  = ETrue;
                    iPrevScanCode    = scan;
                    iPressEventSent = EFalse;
                    returnValue     = ETrue; // Block   
                    iReleaseEventSent = EFalse; // For blocking multiple key
                                                // presses
                    }
                }
            }
            break;
        case TRawEvent::EKeyUp:
            {
            scan = aRawEvent.ScanCode() & KScanCodeMask;

            if ((iPrevScanCode == scan) && IsBlockedKeyCode(scan))
                { 
            
                // Clicked Scenario
                if ( iPressEventSent == EFalse ) 
                    {
                    
                    if ((iPrevScanCode == KMusicForwardHardware) ||  
                        (iPrevScanCode == KMusicRewindHardware))
                    {
	                    // Send Clicked Event
	                    PublishEvent(iPrevScanCode, ERemConCoreApiButtonClick);
                    }
                    
                    // Since Click event has been sent when pressed down,
                    // (except Frwd & Rewind)
                    // Just stop the timer
                    if (iTimerStarted)
                        {
                        iTimer->Cancel();
                        iTimerStarted  = EFalse;
                        }
                    iReleaseEventSent = ETrue;
                    iPrevScanCode     = 0;
                    returnValue       = ETrue; //Block it
                    }
                else  // Released Scenario
                    {
                    PublishEvent(scan,ERemConCoreApiButtonRelease);

                    iPrevScanCode   = 0;
                    iPressEventSent = EFalse;
                    returnValue     = ETrue; //Block it
                    iReleaseEventSent = ETrue;

                    }
                    
                } // end of if ((iPrevScanCode == scan) && IsBlockedK...
            }
            break;
        default:
            break;
        }
    return returnValue; // to allow the event to be passed back to app
    }
// -----------------------------------------------------------------------
// CKeyPublisher::HandleTimerEvent
// Description: When Timer is expired, this function is called from 
//              callback function. If the timer is expired for the first
//              time then KeyPressed event is published to P&S. And 
//              second and further expires, only count is incremented.
//              Once the count reaches some predefined value, Released 
//              Key event is posted to P&S. and timer is switched off.
// return : 
// -----------------------------------------------------------------------
//
void CKeyPublisher::HandleTimerEvent()
    {
    
    // Send Pressed Key Event
    PublishEvent(iPrevScanCode,ERemConCoreApiButtonPress);  
    iPressEventSent = ETrue;
    iTimer->Cancel();
    iTimerStarted  = EFalse;

    }

// -----------------------------------------------------------------------
// CKeyPublisher::TimerCallback
// Description: When Timer is expired, this function is called 
// return : 
// -----------------------------------------------------------------------
//
TInt CKeyPublisher::TimerCallback(TAny* aThis)
    {
    
    //STATIC_CAST(CKeyPublisher*,aThis)->HandleTimerEvent();
    static_cast<CKeyPublisher*>(aThis)->HandleTimerEvent();
    return 0;
    
    }

// -----------------------------------------------------------------------
// CKeyPublisher::Redraw   (part of CWindowAnim - pure virtual function) 
// Description: 
// -----------------------------------------------------------------------
//
void CKeyPublisher::Redraw()
    {
    //Pass
    }
// -----------------------------------------------------------------------
// CKeyPublisher::FocusChanged   (part of CWindowAnim - pure virtual function)
// Description: 
// -----------------------------------------------------------------------
//
void CKeyPublisher::FocusChanged(TBool /*aState*/)
    {
    //Pass
    }
// -----------------------------------------------------------------------
// CKeyPublisher::CommandReplyL  (part of CAnim - pure virtual function)
// Description: 
// -----------------------------------------------------------------------
//
TInt CKeyPublisher::CommandReplyL(TInt /*aOpcode*/, TAny* /*aArgs*/)
    {
    //Pass
    return KErrNone;
    }
// -----------------------------------------------------------------------
// CKeyPublisher::Command  (part of CAnim - pure virtual function)
// Description: 
// -----------------------------------------------------------------------
//
void CKeyPublisher::Command(TInt /*aOpcode*/, TAny* /*aArgs*/)
    {
    //Pass
    }
// -----------------------------------------------------------------------
// CKeyPublisher::Animate  (part of CAnim - pure virtual function)
// Description: 
// -----------------------------------------------------------------------
//
void CKeyPublisher::Animate(TDateTime* /*aDateTime*/)
    {
    //Pass
    }

// End of File