[vlc-devel] [PATCH] Code changes in Globalhokey module to support special keys when application in system tray/minimized for Windows
elangovan elango
elangovv at yahoo.co.in
Fri Oct 29 18:31:15 CEST 2010
Hello All,
This patch is created to support windows special key functionality even when the
application is in system tray/minimized/not interacted by the user. This is
added in windows globalhotkey module. This will enable the user to interact with
VLC even when it is system tray. This is implemented using windows hook concept
to detect the user key press of PLAY,PAUSE, NEXT and PREVIOUS keys. Here am used
WH_KEYBOARD_LL instead of WH_KEYBOARD which eliminates the need of DLL and makes
it as Window Global hook which does not require any dependencies and can be part
of any exe. This Current implementation only handles the This can be extended to
other keys when needed.
/*****************************************************************************
* win32.c: Global-Hotkey WIN32 handling for vlc
*****************************************************************************
* Copyright (C) 2008-2009 the VideoLAN team
*
* Authors: Domani Hannes <ssbssa at yahoo dot de>
+ * Elangovan <elangovv at gmail dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ctype.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_interface.h>
#include <vlc_keys.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Open( vlc_object_t *p_this );
static void Close( vlc_object_t *p_this );
static void *Thread( void *p_data );
LRESULT CALLBACK WMHOTKEYPROC( HWND, UINT, WPARAM, LPARAM );
+ LRESULT CALLBACK WINTRAYSUPPORTPROC( int nCode, WPARAM wParam, LPARAM
lParam);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin()
set_shortname( N_("Global Hotkeys") )
set_category( CAT_INTERFACE )
set_subcategory( SUBCAT_INTERFACE_HOTKEYS )
set_description( N_("Global Hotkeys interface") )
set_capability( "interface", 0 )
set_callbacks( Open, Close )
vlc_module_end()
struct intf_sys_t
{
vlc_thread_t thread;
HWND hotkeyWindow;
vlc_mutex_t lock;
vlc_cond_t wait;
HHOOK hHook;
};
/*****************************************************************************
* Open: initialize interface
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
intf_thread_t *p_intf = (intf_thread_t *)p_this;
intf_sys_t *p_sys = malloc( sizeof (intf_sys_t) );
if( p_sys == NULL )
return VLC_ENOMEM;
p_intf->p_sys = p_sys;
p_sys->hotkeyWindow = NULL;
vlc_mutex_init( &p_sys->lock );
vlc_cond_init( &p_sys->wait );
if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW )
)
{
vlc_mutex_destroy( &p_sys->lock );
vlc_cond_destroy( &p_sys->wait );
free( p_sys );
p_intf->p_sys = NULL;
return VLC_ENOMEM;
}
vlc_mutex_lock( &p_sys->lock );
while( p_sys->hotkeyWindow == NULL )
vlc_cond_wait( &p_sys->wait, &p_sys->lock );
if( p_sys->hotkeyWindow == INVALID_HANDLE_VALUE )
{
vlc_mutex_unlock( &p_sys->lock );
vlc_join( p_sys->thread, NULL );
vlc_mutex_destroy( &p_sys->lock );
vlc_cond_destroy( &p_sys->wait );
free( p_sys );
p_intf->p_sys = NULL;
return VLC_ENOMEM;
}
vlc_mutex_unlock( &p_sys->lock );
return VLC_SUCCESS;
}
/*****************************************************************************
*Close: destroy interface
*****************************************************************************/
static void Close( vlc_object_t *p_this )
{
intf_thread_t *p_intf = (intf_thread_t *)p_this;
intf_sys_t *p_sys = p_intf->p_sys;
+ /* Unregister the HOOK Procedure */
+ if( p_sys->hHook !=NULL )
+ UnhookWindowsHookEx(p_sys->hHook);
/* stop hotkey window */
vlc_mutex_lock( &p_sys->lock );
if( p_sys->hotkeyWindow != NULL )
PostMessage( p_sys->hotkeyWindow, WM_CLOSE, 0, 0 );
vlc_mutex_unlock( &p_sys->lock );
vlc_join( p_sys->thread, NULL );
vlc_mutex_destroy( &p_sys->lock );
vlc_cond_destroy( &p_sys->wait );
free( p_sys );
}
/*****************************************************************************
* Thread: main loop
*****************************************************************************/
static void *Thread( void *p_data )
{
MSG message;
UINT i_key, i_keyMod, i_vk;
ATOM atom;
char *psz_hotkey = NULL;
intf_thread_t *p_intf = p_data;
intf_sys_t *p_sys = p_intf->p_sys;
/* Window which receives Hotkeys */
vlc_mutex_lock( &p_sys->lock );
p_sys->hotkeyWindow =
(void*)CreateWindow( _T("STATIC"), /* name of window class */
_T("VLC ghk ") _T(VERSION), /* window title bar text */
0, /* window style */
0, /* default X coordinate */
0, /* default Y coordinate */
0, /* window width */
0, /* window height */
NULL, /* no parent window */
NULL, /* no menu in this window */
GetModuleHandle(NULL), /* handle of this program instance */
NULL ); /* sent to WM_CREATE */
+ //Get Module handle and register the HOOK
+ HINSTANCE hExe = GetModuleHandle(NULL);
+ if (hExe !=NULL)
+ {
+ p_sys->hHook = SetWindowsHookEx( WH_KEYBOARD_LL,
(HOOKPROC)WINTRAYSUPPORTPROC, hExe, NULL);
+ }
if( p_sys->hotkeyWindow == NULL )
{
p_sys->hotkeyWindow = INVALID_HANDLE_VALUE;
vlc_cond_signal( &p_sys->wait );
vlc_mutex_unlock( &p_sys->lock );
return NULL;
}
vlc_cond_signal( &p_sys->wait );
vlc_mutex_unlock( &p_sys->lock );
SetWindowLongPtr( p_sys->hotkeyWindow, GWLP_WNDPROC,
(LONG_PTR)WMHOTKEYPROC );
SetWindowLongPtr( p_sys->hotkeyWindow, GWLP_USERDATA,
(LONG_PTR)p_intf );
/* Registering of Hotkeys */
for( const struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys;
p_hotkey->psz_action != NULL;
p_hotkey++ )
{
if( asprintf( &psz_hotkey, "global-%s", p_hotkey->psz_action ) < 0 )
break;
i_key = var_InheritInteger( p_intf, psz_hotkey );
free( psz_hotkey );
i_keyMod = 0;
if( i_key & KEY_MODIFIER_SHIFT ) i_keyMod |= MOD_SHIFT;
if( i_key & KEY_MODIFIER_ALT ) i_keyMod |= MOD_ALT;
if( i_key & KEY_MODIFIER_CTRL ) i_keyMod |= MOD_CONTROL;
#define HANDLE( key ) case KEY_##key: i_vk = VK_##key; break
#define HANDLE2( key, key2 ) case KEY_##key: i_vk = VK_##key2; break
#define KEY_SPACE ' '
#ifndef VK_VOLUME_DOWN
#define VK_VOLUME_DOWN 0xAE
#define VK_VOLUME_UP 0xAF
#endif
#ifndef VK_MEDIA_NEXT_TRACK
#define VK_MEDIA_NEXT_TRACK 0xB0
#define VK_MEDIA_PREV_TRACK 0xB1
#define VK_MEDIA_STOP 0xB2
#define VK_MEDIA_PLAY_PAUSE 0xB3
#endif
#ifndef VK_PAGEUP
#define VK_PAGEUP 0x21
#define VK_PAGEDOWN 0x22
#endif
i_vk = 0;
switch( i_key & ~KEY_MODIFIER )
{
HANDLE( LEFT );
HANDLE( RIGHT );
HANDLE( UP );
HANDLE( DOWN );
HANDLE( SPACE );
HANDLE2( ESC, ESCAPE );
HANDLE2( ENTER, RETURN );
HANDLE( F1 );
HANDLE( F2 );
HANDLE( F3 );
HANDLE( F4 );
HANDLE( F5 );
HANDLE( F6 );
HANDLE( F7 );
HANDLE( F8 );
HANDLE( F9 );
HANDLE( F10 );
HANDLE( F11 );
HANDLE( F12 );
HANDLE( PAGEUP );
HANDLE( PAGEDOWN );
HANDLE( HOME );
HANDLE( END );
HANDLE( INSERT );
HANDLE( DELETE );
HANDLE( VOLUME_DOWN );
HANDLE( VOLUME_UP );
HANDLE( MEDIA_PLAY_PAUSE );
HANDLE( MEDIA_STOP );
HANDLE( MEDIA_PREV_TRACK );
HANDLE( MEDIA_NEXT_TRACK );
default:
i_vk = toupper( i_key & ~KEY_MODIFIER );
break;
}
if( !i_vk ) continue;
#undef HANDLE
#undef HANDLE2
atom = GlobalAddAtomA( p_hotkey->psz_action );
if( !atom ) continue;
if( !RegisterHotKey( p_sys->hotkeyWindow, atom, i_keyMod, i_vk ) )
GlobalDeleteAtom( atom );
}
/* Main message loop */
while( GetMessage( &message, NULL, 0, 0 ) )
DispatchMessage( &message );
/* Unregistering of Hotkeys */
for( const struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys;
p_hotkey->psz_action != NULL;
p_hotkey++ )
{
atom = GlobalFindAtomA( p_hotkey->psz_action );
if( !atom ) continue;
if( UnregisterHotKey( p_sys->hotkeyWindow, atom ) )
GlobalDeleteAtom( atom );
}
/* close window */
vlc_mutex_lock( &p_sys->lock );
DestroyWindow( p_sys->hotkeyWindow );
p_sys->hotkeyWindow = NULL;
vlc_mutex_unlock( &p_sys->lock );
return NULL;
}
/*****************************************************************************
* WMHOTKEYPROC: event callback
*****************************************************************************/
LRESULT CALLBACK WMHOTKEYPROC( HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam )
{
switch( uMsg )
{
case WM_HOTKEY:
{
char psz_atomName[40];
LONG_PTR ret = GetWindowLongPtr( hwnd, GWLP_USERDATA );
intf_thread_t *p_intf = (intf_thread_t*)ret;
const struct hotkey *p_hotkeys = p_intf->p_libvlc->p_hotkeys;
if( !GlobalGetAtomNameA(
wParam, psz_atomName, sizeof( psz_atomName ) ) )
return 0;
/* search for key associated with VLC */
for( int i = 0; p_hotkeys[i].psz_action != NULL; i++ )
{
if( strcmp( p_hotkeys[i].psz_action, psz_atomName ) )
continue;
var_SetInteger( p_intf->p_libvlc,
"key-action", p_hotkeys[i].i_action );
return 1;
}
}
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hwnd, uMsg, wParam, lParam );
}
return 0;
}
+
/*****************************************************************************
+ * WINTRAYSUPPORTPROC: event callback method
+
*****************************************************************************/
+ LRESULT CALLBACK WINTRAYSUPPORTPROC( int nCode, WPARAM wParam, LPARAM
lParam)
+ {
+ #ifndef VK_MEDIA_NEXT_TRACK
+ #define VK_MEDIA_NEXT_TRACK 0xB0
+ #define VK_MEDIA_PREV_TRACK 0xB1
+ #define VK_MEDIA_STOP 0xB2
+ #define VK_MEDIA_PLAY_PAUSE 0xB3
+ #endif
+ static HHOOK hkb=NULL;
+ if ((nCode == HC_ACTION) && (wParam == WM_KEYDOWN))
+ {
+ KBDLLHOOKSTRUCT hookstruct = *((KBDLLHOOKSTRUCT*)lParam);
+ if( VK_MEDIA_PLAY_PAUSE == hookstruct.vkCode || VK_MEDIA_NEXT_TRACK
== hookstruct.vkCode || VK_MEDIA_STOP == hookstruct.vkCode ||
VK_MEDIA_PREV_TRACK == hookstruct.vkCode)
+ {
+ HANDLE hotkeyWindow = FindWindow(_T("STATIC"), _T("VLC ghk ")
_T(VERSION));
+ if(hotkeyWindow !=NULL)
+ {
+ LONG_PTR ret = GetWindowLongPtr( hotkeyWindow,
GWLP_USERDATA );
+ intf_thread_t *p_intf = (intf_thread_t*)ret;
+ switch(hookstruct.vkCode)
+ {
+ case VK_MEDIA_PLAY_PAUSE:
+ var_SetInteger( p_intf->p_libvlc,"key-action",
ACTIONID_PLAY_PAUSE );
+ break;
+ case VK_MEDIA_STOP:
+ var_SetInteger( p_intf->p_libvlc,"key-action",
ACTIONID_STOP );
+ break;
+ case VK_MEDIA_PREV_TRACK:
+ var_SetInteger( p_intf->p_libvlc,"key-action",
ACTIONID_PREV );
+ break;
+ case VK_MEDIA_NEXT_TRACK:
+ var_SetInteger( p_intf->p_libvlc,"key-action",
ACTIONID_NEXT );
+ }
+ }
+ }
+ }
+ return CallNextHookEx( hkb, nCode, wParam, lParam );
+ }
Regards
Elangovan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20101029/f5193803/attachment.html>
More information about the vlc-devel
mailing list