Commit c85aed3c authored by Hannes Domani's avatar Hannes Domani Committed by Laurent Aimar

Global Hotkeys for windows

Signed-off-by: default avatarLaurent Aimar <fenrir@videolan.org>
parent 8bcd3c6f
......@@ -1191,6 +1191,7 @@ elif test "${SYS}" != "mingwce"; then
VLC_ADD_PLUGIN([dmo])
VLC_ADD_PLUGIN([msn])
VLC_ADD_LIBS([dmo],[-lole32 -luuid])
VLC_ADD_PLUGIN([globalhotkeys])
else
VLC_ADD_PLUGIN([win32text])
fi
......
......@@ -353,9 +353,17 @@ enum vlc_config_properties
add_int_inner( CONFIG_ITEM_INTEGER, name, text, longtext, advc, \
p_callback, value )
#ifndef WIN32
#define add_key( name, value, p_callback, text, longtext, advc ) \
add_int_inner( CONFIG_ITEM_KEY, name, text, longtext, advc, p_callback, \
value )
#else
#define add_key( name, value, p_callback, text, longtext, advc ) \
add_int_inner( CONFIG_ITEM_KEY, name, text, longtext, advc, \
p_callback, value ) \
add_int_inner( CONFIG_ITEM_KEY, "global-" name, text, longtext, advc, \
p_callback, KEY_UNSET )
#endif
#define add_integer_with_range( name, value, i_min, i_max, p_callback, text, longtext, advc ) \
add_integer( name, value, p_callback, text, longtext, advc ) \
......
......@@ -5,6 +5,7 @@ SOURCES_telnet = telnet.c
SOURCES_netsync = netsync.c
SOURCES_ntservice = ntservice.c
SOURCES_hotkeys = hotkeys.c
SOURCES_globalhotkeys = globalhotkeys.c
SOURCES_lirc = lirc.c
SOURCES_rc = rc.c
SOURCES_dbus = dbus.c dbus.h
......
/*****************************************************************************
* globalhotkeys.c: Global-Hotkey handling for vlc
*****************************************************************************
* Copyright (C) 2008-2009 the VideoLAN team
*
* Authors: Domani Hannes <ssbssa at yahoo dot de>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#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 );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_shortname( _("Global Hotkeys") );
set_category( CAT_INTERFACE );
set_subcategory( SUBCAT_INTERFACE_HOTKEYS );
set_description( _("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;
};
/*****************************************************************************
* 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;
/* 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 */
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, GWL_WNDPROC,
(LONG_PTR)WMHOTKEYPROC );
SetWindowLongPtr( p_sys->hotkeyWindow, GWL_USERDATA,
(LONG_PTR)p_intf );
/* Registering of Hotkeys */
for( 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 = config_GetInt( 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
#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( 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:
{
int i;
char psz_atomName[40];
intf_thread_t *p_intf =
(intf_thread_t*)GetWindowLongPtr( hwnd, GWL_USERDATA );
struct hotkey *p_hotkeys = p_intf->p_libvlc->p_hotkeys;
i = GlobalGetAtomNameA(
wParam, psz_atomName, sizeof( psz_atomName ) );
if( !i ) return 0;
/* search for key associated with VLC */
for( 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;
}
......@@ -896,6 +896,9 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
* Always load the hotkeys interface if it exists
*/
libvlc_InternalAddIntf( p_libvlc, "hotkeys,none" );
#ifdef WIN32
libvlc_InternalAddIntf( p_libvlc, "globalhotkeys,none" );
#endif
#ifdef HAVE_DBUS
/* loads dbus control interface if in one-instance mode
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment