<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:times new roman,new york,times,serif;font-size:12pt"><div>Hello All,<br><br>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.<br><br><br>/*****************************************************************************<br> * win32.c:
Global-Hotkey WIN32 handling for vlc<br> *****************************************************************************<br> * Copyright (C) 2008-2009 the VideoLAN team<br> *<br> * Authors: Domani Hannes <ssbssa at yahoo dot de><br>+ * Elangovan <elangovv at gmail dot com><br> *<br> * This program is free software; you can redistribute it and/or modify<br> * it under the terms of the GNU General Public License as published by<br><br><br>#ifdef HAVE_CONFIG_H<br># include "config.h"<br>#endif<br><br>#include <ctype.h><br><br>#include <vlc_common.h><br>#include <vlc_plugin.h><br>#include <vlc_interface.h><br>#include <vlc_keys.h><br><br>/*****************************************************************************<br> * Local
prototypes<br> *****************************************************************************/<br> static int Open( vlc_object_t *p_this );<br> static void Close( vlc_object_t *p_this );<br> static void *Thread( void *p_data );<br> LRESULT CALLBACK WMHOTKEYPROC( HWND, UINT, WPARAM, LPARAM );<br>+ LRESULT CALLBACK WINTRAYSUPPORTPROC( int nCode, WPARAM wParam, LPARAM lParam);<br><br> /*****************************************************************************<br> * Module descriptor<br> *****************************************************************************/<br> vlc_module_begin()<br> set_shortname( N_("Global Hotkeys") )<br> set_category( CAT_INTERFACE )<br>
set_subcategory( SUBCAT_INTERFACE_HOTKEYS )<br> set_description( N_("Global Hotkeys interface") )<br> set_capability( "interface", 0 )<br> set_callbacks( Open, Close )<br> vlc_module_end()<br> <br> struct intf_sys_t<br> {<br> vlc_thread_t thread;<br> HWND hotkeyWindow;<br> vlc_mutex_t lock;<br> vlc_cond_t wait;<br> HHOOK hHook;<br> };<br><br> /*****************************************************************************<br> * Open: initialize interface<br>
*****************************************************************************/<br> static int Open( vlc_object_t *p_this )<br> {<br> intf_thread_t *p_intf = (intf_thread_t *)p_this;<br> intf_sys_t *p_sys = malloc( sizeof (intf_sys_t) );<br> <br> if( p_sys == NULL )<br> return VLC_ENOMEM;<br><br> p_intf->p_sys = p_sys;<br> p_sys->hotkeyWindow = NULL;<br> vlc_mutex_init( &p_sys->lock );<br> vlc_cond_init( &p_sys->wait );<br><br> if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW ) )<br>
{<br> vlc_mutex_destroy( &p_sys->lock );<br> vlc_cond_destroy( &p_sys->wait );<br> free( p_sys );<br> p_intf->p_sys = NULL;<br> <br> return VLC_ENOMEM;<br> }<br><br> vlc_mutex_lock( &p_sys->lock );<br> while( p_sys->hotkeyWindow == NULL )<br> vlc_cond_wait( &p_sys->wait, &p_sys->lock );<br> if( p_sys->hotkeyWindow == INVALID_HANDLE_VALUE )<br>
{<br> vlc_mutex_unlock( &p_sys->lock );<br> vlc_join( p_sys->thread, NULL );<br> vlc_mutex_destroy( &p_sys->lock );<br> vlc_cond_destroy( &p_sys->wait );<br> free( p_sys );<br> p_intf->p_sys = NULL;<br> <br> return VLC_ENOMEM;<br> }<br> vlc_mutex_unlock( &p_sys->lock );<br> <br> return VLC_SUCCESS;<br>
} <br><br> /*****************************************************************************<br> *Close: destroy interface<br> *****************************************************************************/<br> static void Close( vlc_object_t *p_this )<br> {<br> intf_thread_t *p_intf = (intf_thread_t *)p_this;<br> intf_sys_t *p_sys = p_intf->p_sys;<br>+ /* Unregister the HOOK Procedure */<br>+ if( p_sys->hHook !=NULL )<br>+ UnhookWindowsHookEx(p_sys->hHook);<br><br> /* stop hotkey window */<br> vlc_mutex_lock( &p_sys->lock );<br> if( p_sys->hotkeyWindow !=
NULL )<br> PostMessage( p_sys->hotkeyWindow, WM_CLOSE, 0, 0 );<br> vlc_mutex_unlock( &p_sys->lock );<br><br> vlc_join( p_sys->thread, NULL );<br> vlc_mutex_destroy( &p_sys->lock );<br> vlc_cond_destroy( &p_sys->wait );<br> free( p_sys );<br>}<br><br>/*****************************************************************************<br> * Thread: main loop<br> *****************************************************************************/<br>static void *Thread( void *p_data )<br>{<br> MSG message;<br> UINT i_key, i_keyMod, i_vk;<br> ATOM atom;<br> char *psz_hotkey = NULL;<br><br> intf_thread_t *p_intf = p_data;<br> intf_sys_t *p_sys = p_intf->p_sys;<br><br> /* Window
which receives Hotkeys */<br> vlc_mutex_lock( &p_sys->lock );<br> p_sys->hotkeyWindow =<br> (void*)CreateWindow( _T("STATIC"), /* name of window class */<br> _T("VLC ghk ") _T(VERSION), /* window title bar text */<br> 0, /* window style */<br>
0, /* default X coordinate */<br> 0, /* default Y coordinate */<br> 0, /* window width
*/<br> 0, /* window height */<br> NULL, /* no parent window */<br>
NULL, /* no menu in this window */<br> GetModuleHandle(NULL), /* handle of this program instance */<br> NULL ); /* sent to WM_CREATE */<br><br>+ //Get Module handle and register the HOOK<br>+ HINSTANCE hExe = GetModuleHandle(NULL);<br>+ if (hExe !=NULL)<br>+ {<br>+ p_sys->hHook = SetWindowsHookEx(
WH_KEYBOARD_LL, (HOOKPROC)WINTRAYSUPPORTPROC, hExe, NULL);<br>+ }<br> if( p_sys->hotkeyWindow == NULL )<br> {<br> p_sys->hotkeyWindow = INVALID_HANDLE_VALUE;<br> vlc_cond_signal( &p_sys->wait );<br> vlc_mutex_unlock( &p_sys->lock );<br> return NULL;<br> }<br> vlc_cond_signal( &p_sys->wait );<br> vlc_mutex_unlock( &p_sys->lock );<br><br> SetWindowLongPtr( p_sys->hotkeyWindow, GWLP_WNDPROC,<br> (LONG_PTR)WMHOTKEYPROC );<br> SetWindowLongPtr( p_sys->hotkeyWindow, GWLP_USERDATA,<br>
(LONG_PTR)p_intf );<br><br> /* Registering of Hotkeys */<br> for( const struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys;<br> p_hotkey->psz_action != NULL;<br> p_hotkey++ )<br> {<br> if( asprintf( &psz_hotkey, "global-%s", p_hotkey->psz_action ) < 0 )<br> break;<br><br> i_key = var_InheritInteger( p_intf, psz_hotkey );<br><br> free( psz_hotkey );<br><br> i_keyMod = 0;<br> if( i_key & KEY_MODIFIER_SHIFT ) i_keyMod |= MOD_SHIFT;<br>
if( i_key & KEY_MODIFIER_ALT ) i_keyMod |= MOD_ALT;<br> if( i_key & KEY_MODIFIER_CTRL ) i_keyMod |= MOD_CONTROL;<br><br>#define HANDLE( key ) case KEY_##key: i_vk = VK_##key; break<br>#define HANDLE2( key, key2 ) case KEY_##key: i_vk = VK_##key2; break<br><br>#define KEY_SPACE ' '<br><br>#ifndef VK_VOLUME_DOWN<br>#define VK_VOLUME_DOWN 0xAE<br>#define VK_VOLUME_UP 0xAF<br>#endif<br><br>#ifndef VK_MEDIA_NEXT_TRACK<br>#define VK_MEDIA_NEXT_TRACK 0xB0<br>#define VK_MEDIA_PREV_TRACK 0xB1<br>#define VK_MEDIA_STOP 0xB2<br>#define VK_MEDIA_PLAY_PAUSE 0xB3<br>#endif<br><br>#ifndef VK_PAGEUP<br>#define
VK_PAGEUP 0x21<br>#define VK_PAGEDOWN 0x22<br>#endif<br><br> i_vk = 0;<br> switch( i_key & ~KEY_MODIFIER )<br> {<br> HANDLE( LEFT );<br> HANDLE( RIGHT );<br> HANDLE( UP );<br> HANDLE( DOWN );<br> HANDLE( SPACE );<br> HANDLE2( ESC, ESCAPE
);<br> HANDLE2( ENTER, RETURN );<br> HANDLE( F1 );<br> HANDLE( F2 );<br> HANDLE( F3 );<br> HANDLE( F4 );<br> HANDLE( F5 );<br> HANDLE( F6 );<br> HANDLE( F7 );<br> HANDLE( F8 );<br> HANDLE( F9 );<br> HANDLE( F10
);<br> HANDLE( F11 );<br> HANDLE( F12 );<br> HANDLE( PAGEUP );<br> HANDLE( PAGEDOWN );<br> HANDLE( HOME );<br> HANDLE( END );<br> HANDLE( INSERT );<br> HANDLE( DELETE );<br> HANDLE( VOLUME_DOWN );<br> HANDLE( VOLUME_UP );<br> HANDLE(
MEDIA_PLAY_PAUSE );<br> HANDLE( MEDIA_STOP );<br> HANDLE( MEDIA_PREV_TRACK );<br> HANDLE( MEDIA_NEXT_TRACK );<br><br> default:<br> i_vk = toupper( i_key & ~KEY_MODIFIER );<br> break;<br> }<br> if( !i_vk ) continue;<br><br>#undef HANDLE<br>#undef HANDLE2<br><br> atom = GlobalAddAtomA( p_hotkey->psz_action );<br> if( !atom )
continue;<br><br> if( !RegisterHotKey( p_sys->hotkeyWindow, atom, i_keyMod, i_vk ) )<br> GlobalDeleteAtom( atom );<br> }<br><br> /* Main message loop */<br> while( GetMessage( &message, NULL, 0, 0 ) )<br> DispatchMessage( &message );<br><br> /* Unregistering of Hotkeys */<br> for( const struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys;<br> p_hotkey->psz_action != NULL;<br> p_hotkey++ )<br> {<br> atom = GlobalFindAtomA( p_hotkey->psz_action );<br> if( !atom )
continue;<br><br> if( UnregisterHotKey( p_sys->hotkeyWindow, atom ) )<br> GlobalDeleteAtom( atom );<br> }<br><br> /* close window */<br> vlc_mutex_lock( &p_sys->lock );<br> DestroyWindow( p_sys->hotkeyWindow );<br> p_sys->hotkeyWindow = NULL;<br> vlc_mutex_unlock( &p_sys->lock );<br><br> return NULL;<br>}<br><br>/*****************************************************************************<br> * WMHOTKEYPROC: event callback<br> *****************************************************************************/<br>LRESULT CALLBACK WMHOTKEYPROC( HWND hwnd, UINT uMsg, WPARAM wParam,<br> LPARAM lParam )<br>{<br> switch( uMsg
)<br> {<br> case WM_HOTKEY:<br> {<br> char psz_atomName[40];<br><br> LONG_PTR ret = GetWindowLongPtr( hwnd, GWLP_USERDATA );<br> intf_thread_t *p_intf = (intf_thread_t*)ret;<br> const struct hotkey *p_hotkeys = p_intf->p_libvlc->p_hotkeys;<br><br> if(
!GlobalGetAtomNameA(<br> wParam, psz_atomName, sizeof( psz_atomName ) ) )<br> return 0;<br><br> /* search for key associated with VLC */<br> for( int i = 0; p_hotkeys[i].psz_action != NULL; i++ )<br> {<br> if( strcmp( p_hotkeys[i].psz_action, psz_atomName )
)<br> continue;<br><br> var_SetInteger( p_intf->p_libvlc,<br> "key-action", p_hotkeys[i].i_action );<br><br> return 1;<br> }<br> }<br> break;<br><br> case
WM_DESTROY:<br> PostQuitMessage( 0 );<br> break;<br><br> default:<br> return DefWindowProc( hwnd, uMsg, wParam, lParam );<br> }<br><br> return 0;<br>}<br><br>+ /*****************************************************************************<br>+ * WINTRAYSUPPORTPROC: event callback method<br>+ *****************************************************************************/<br> + LRESULT CALLBACK WINTRAYSUPPORTPROC( int nCode, WPARAM wParam, LPARAM lParam)<br> + {<br>+ #ifndef VK_MEDIA_NEXT_TRACK<br> + #define
VK_MEDIA_NEXT_TRACK 0xB0<br>+ #define VK_MEDIA_PREV_TRACK 0xB1<br>+ #define VK_MEDIA_STOP 0xB2<br>+ #define VK_MEDIA_PLAY_PAUSE 0xB3<br>+ #endif<br> + static HHOOK hkb=NULL;<br>+ if ((nCode == HC_ACTION) && (wParam == WM_KEYDOWN))<br>+ {<br>+ KBDLLHOOKSTRUCT hookstruct = *((KBDLLHOOKSTRUCT*)lParam);<br>+ if( VK_MEDIA_PLAY_PAUSE == hookstruct.vkCode || VK_MEDIA_NEXT_TRACK == hookstruct.vkCode || VK_MEDIA_STOP == hookstruct.vkCode || VK_MEDIA_PREV_TRACK ==
hookstruct.vkCode)<br>+ {<br>+ HANDLE hotkeyWindow = FindWindow(_T("STATIC"), _T("VLC ghk ") _T(VERSION));<br>+ if(hotkeyWindow !=NULL)<br>+ {<br>+ LONG_PTR ret = GetWindowLongPtr( hotkeyWindow, GWLP_USERDATA );<br>+ intf_thread_t *p_intf = (intf_thread_t*)ret;<br>+ switch(hookstruct.vkCode)<br>+
{<br>+ case VK_MEDIA_PLAY_PAUSE:<br>+ var_SetInteger( p_intf->p_libvlc,"key-action", ACTIONID_PLAY_PAUSE );<br>+ break;<br>+ case VK_MEDIA_STOP:<br>+ var_SetInteger( p_intf->p_libvlc,"key-action", ACTIONID_STOP );<br>+
break;<br>+ case VK_MEDIA_PREV_TRACK:<br>+ var_SetInteger( p_intf->p_libvlc,"key-action", ACTIONID_PREV );<br>+ break;<br>+ case VK_MEDIA_NEXT_TRACK:<br>+ var_SetInteger( p_intf->p_libvlc,"key-action", ACTIONID_NEXT );<br>+
}<br>+ }<br>+ }<br>+ }<br>+ return CallNextHookEx( hkb, nCode, wParam, lParam );<br>+ } <br><br><br>Regards<br>Elangovan<br></div>
</div><br></body></html>