Win32: add a new build-script helper
[vlc.git] / modules / control / globalhotkeys / win32.c
blobf575735a66189ff138160fe32513c2ec20209a86
1 /*****************************************************************************
2 * win32.c: Global-Hotkey _WIN32 handling for vlc
3 *****************************************************************************
4 * Copyright (C) 2008-2009 the VideoLAN team
6 * Authors: Domani Hannes <ssbssa at yahoo dot de>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <ctype.h>
29 #define VLC_MODULE_LICENSE VLC_LICENSE_GPL_2_PLUS
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_interface.h>
33 #include <vlc_actions.h>
35 /*****************************************************************************
36 * Local prototypes
37 *****************************************************************************/
38 static int Open( vlc_object_t *p_this );
39 static void Close( vlc_object_t *p_this );
40 static void *Thread( void *p_data );
41 LRESULT CALLBACK WMHOTKEYPROC( HWND, UINT, WPARAM, LPARAM );
43 /*****************************************************************************
44 * Module descriptor
45 *****************************************************************************/
46 vlc_module_begin()
47 set_shortname( N_("Global Hotkeys") )
48 set_category( CAT_INTERFACE )
49 set_subcategory( SUBCAT_INTERFACE_HOTKEYS )
50 set_description( N_("Global Hotkeys interface") )
51 set_capability( "interface", 0 )
52 set_callbacks( Open, Close )
53 add_shortcut( "globalhotkeys" )
54 vlc_module_end()
56 struct intf_sys_t
58 vlc_thread_t thread;
59 HWND hotkeyWindow;
60 vlc_mutex_t lock;
61 vlc_cond_t wait;
64 /*****************************************************************************
65 * Open: initialize interface
66 *****************************************************************************/
67 static int Open( vlc_object_t *p_this )
69 intf_thread_t *p_intf = (intf_thread_t *)p_this;
70 intf_sys_t *p_sys = malloc( sizeof (intf_sys_t) );
72 if( p_sys == NULL )
73 return VLC_ENOMEM;
75 p_intf->p_sys = p_sys;
76 p_sys->hotkeyWindow = NULL;
77 vlc_mutex_init( &p_sys->lock );
78 vlc_cond_init( &p_sys->wait );
80 if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW ) )
82 vlc_mutex_destroy( &p_sys->lock );
83 vlc_cond_destroy( &p_sys->wait );
84 free( p_sys );
85 p_intf->p_sys = NULL;
87 return VLC_ENOMEM;
90 vlc_mutex_lock( &p_sys->lock );
91 while( p_sys->hotkeyWindow == NULL )
92 vlc_cond_wait( &p_sys->wait, &p_sys->lock );
93 if( p_sys->hotkeyWindow == INVALID_HANDLE_VALUE )
95 vlc_mutex_unlock( &p_sys->lock );
96 vlc_join( p_sys->thread, NULL );
97 vlc_mutex_destroy( &p_sys->lock );
98 vlc_cond_destroy( &p_sys->wait );
99 free( p_sys );
100 p_intf->p_sys = NULL;
102 return VLC_ENOMEM;
104 vlc_mutex_unlock( &p_sys->lock );
106 return VLC_SUCCESS;
109 /*****************************************************************************
110 * Close: destroy interface
111 *****************************************************************************/
112 static void Close( vlc_object_t *p_this )
114 intf_thread_t *p_intf = (intf_thread_t *)p_this;
115 intf_sys_t *p_sys = p_intf->p_sys;
117 /* stop hotkey window */
118 vlc_mutex_lock( &p_sys->lock );
119 if( p_sys->hotkeyWindow != NULL )
120 PostMessage( p_sys->hotkeyWindow, WM_CLOSE, 0, 0 );
121 vlc_mutex_unlock( &p_sys->lock );
123 vlc_join( p_sys->thread, NULL );
124 vlc_mutex_destroy( &p_sys->lock );
125 vlc_cond_destroy( &p_sys->wait );
126 free( p_sys );
129 /*****************************************************************************
130 * Thread: main loop
131 *****************************************************************************/
132 static void *Thread( void *p_data )
134 MSG message;
136 intf_thread_t *p_intf = p_data;
137 intf_sys_t *p_sys = p_intf->p_sys;
139 /* Window which receives Hotkeys */
140 vlc_mutex_lock( &p_sys->lock );
141 p_sys->hotkeyWindow =
142 (void*)CreateWindow( _T("STATIC"), /* name of window class */
143 _T("VLC ghk ") _T(VERSION), /* window title bar text */
144 0, /* window style */
145 0, /* default X coordinate */
146 0, /* default Y coordinate */
147 0, /* window width */
148 0, /* window height */
149 NULL, /* no parent window */
150 NULL, /* no menu in this window */
151 GetModuleHandle(NULL), /* handle of this program instance */
152 NULL ); /* sent to WM_CREATE */
154 if( p_sys->hotkeyWindow == NULL )
156 p_sys->hotkeyWindow = INVALID_HANDLE_VALUE;
157 vlc_cond_signal( &p_sys->wait );
158 vlc_mutex_unlock( &p_sys->lock );
159 return NULL;
161 vlc_cond_signal( &p_sys->wait );
162 vlc_mutex_unlock( &p_sys->lock );
164 SetWindowLongPtr( p_sys->hotkeyWindow, GWLP_WNDPROC,
165 (LONG_PTR)WMHOTKEYPROC );
166 SetWindowLongPtr( p_sys->hotkeyWindow, GWLP_USERDATA,
167 (LONG_PTR)p_intf );
169 /* Registering of Hotkeys */
170 for( const char* const* ppsz_keys = vlc_actions_get_key_names( p_intf );
171 *ppsz_keys != NULL; ppsz_keys++ )
173 uint_fast32_t *p_keys;
174 size_t i_nb_keys = vlc_actions_get_keycodes( p_intf, *ppsz_keys, true,
175 &p_keys );
176 for( size_t i = 0; i < i_nb_keys; ++i )
178 uint_fast32_t i_key = p_keys[i];
179 UINT i_keyMod = 0;
180 if( i_key & KEY_MODIFIER_SHIFT ) i_keyMod |= MOD_SHIFT;
181 if( i_key & KEY_MODIFIER_ALT ) i_keyMod |= MOD_ALT;
182 if( i_key & KEY_MODIFIER_CTRL ) i_keyMod |= MOD_CONTROL;
184 #define HANDLE( key ) case KEY_##key: i_vk = VK_##key; break
185 #define HANDLE2( key, key2 ) case KEY_##key: i_vk = VK_##key2; break
187 #define KEY_SPACE ' '
189 #ifndef VK_VOLUME_DOWN
190 #define VK_VOLUME_DOWN 0xAE
191 #define VK_VOLUME_UP 0xAF
192 #endif
194 #ifndef VK_MEDIA_NEXT_TRACK
195 #define VK_MEDIA_NEXT_TRACK 0xB0
196 #define VK_MEDIA_PREV_TRACK 0xB1
197 #define VK_MEDIA_STOP 0xB2
198 #define VK_MEDIA_PLAY_PAUSE 0xB3
199 #endif
201 #ifndef VK_PAGEUP
202 #define VK_PAGEUP 0x21
203 #define VK_PAGEDOWN 0x22
204 #endif
206 UINT i_vk = 0;
207 switch( i_key & ~KEY_MODIFIER )
209 HANDLE( LEFT );
210 HANDLE( RIGHT );
211 HANDLE( UP );
212 HANDLE( DOWN );
213 HANDLE( SPACE );
214 HANDLE2( ESC, ESCAPE );
215 HANDLE2( ENTER, RETURN );
216 HANDLE( F1 );
217 HANDLE( F2 );
218 HANDLE( F3 );
219 HANDLE( F4 );
220 HANDLE( F5 );
221 HANDLE( F6 );
222 HANDLE( F7 );
223 HANDLE( F8 );
224 HANDLE( F9 );
225 HANDLE( F10 );
226 HANDLE( F11 );
227 HANDLE( F12 );
228 HANDLE( PAGEUP );
229 HANDLE( PAGEDOWN );
230 HANDLE( HOME );
231 HANDLE( END );
232 HANDLE( INSERT );
233 HANDLE( DELETE );
234 HANDLE( VOLUME_DOWN );
235 HANDLE( VOLUME_UP );
236 HANDLE( MEDIA_PLAY_PAUSE );
237 HANDLE( MEDIA_STOP );
238 HANDLE( MEDIA_PREV_TRACK );
239 HANDLE( MEDIA_NEXT_TRACK );
241 default:
242 i_vk = toupper( (uint8_t)(i_key & ~KEY_MODIFIER) );
243 break;
245 if( !i_vk ) continue;
247 #undef HANDLE
248 #undef HANDLE2
250 ATOM atom = GlobalAddAtomA( *ppsz_keys );
251 if( !atom ) continue;
253 if( !RegisterHotKey( p_sys->hotkeyWindow, atom, i_keyMod, i_vk ) )
254 GlobalDeleteAtom( atom );
256 free( p_keys );
259 /* Main message loop */
260 while( GetMessage( &message, NULL, 0, 0 ) )
261 DispatchMessage( &message );
263 /* Unregistering of Hotkeys */
264 for( const char* const* ppsz_keys = vlc_actions_get_key_names( p_intf );
265 *ppsz_keys != NULL; ppsz_keys++ )
267 ATOM atom = GlobalFindAtomA( *ppsz_keys );
268 if( !atom ) continue;
270 if( UnregisterHotKey( p_sys->hotkeyWindow, atom ) )
271 GlobalDeleteAtom( atom );
274 /* close window */
275 vlc_mutex_lock( &p_sys->lock );
276 DestroyWindow( p_sys->hotkeyWindow );
277 p_sys->hotkeyWindow = NULL;
278 vlc_mutex_unlock( &p_sys->lock );
280 return NULL;
283 /*****************************************************************************
284 * WMHOTKEYPROC: event callback
285 *****************************************************************************/
286 LRESULT CALLBACK WMHOTKEYPROC( HWND hwnd, UINT uMsg, WPARAM wParam,
287 LPARAM lParam )
289 switch( uMsg )
291 case WM_HOTKEY:
293 char psz_atomName[44];
295 LONG_PTR ret = GetWindowLongPtr( hwnd, GWLP_USERDATA );
296 intf_thread_t *p_intf = (intf_thread_t*)ret;
297 strcpy( psz_atomName, "key-" );
299 if( !GlobalGetAtomNameA(
300 wParam, psz_atomName + 4,
301 sizeof( psz_atomName ) - 4 ) )
302 return 0;
304 /* search for key associated with VLC */
305 vlc_action_id_t action = vlc_actions_get_id( psz_atomName );
306 if( action != ACTIONID_NONE )
308 var_SetInteger( p_intf->obj.libvlc,
309 "key-action", action );
310 return 1;
313 break;
315 case WM_DESTROY:
316 PostQuitMessage( 0 );
317 break;
319 default:
320 return DefWindowProc( hwnd, uMsg, wParam, lParam );
323 return 0;