qt: playlist: use item title if available
[vlc.git] / src / misc / actions.c
blob5b6e081f1ce8ab0db1248029e5d2c295e3be4fa9
1 /*****************************************************************************
2 * actions.c: handle vlc actions
3 *****************************************************************************
4 * Copyright (C) 2003-2016 VLC authors and VideoLAN
6 * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
27 /**
28 * \file
29 * This file defines functions and structures for hotkey handling in vlc
32 #include <assert.h>
33 #include <stdlib.h>
34 #include <limits.h>
35 #ifdef HAVE_SEARCH_H
36 # include <search.h>
37 #endif
38 #include <errno.h>
40 #include <vlc_common.h>
41 #include <vlc_actions.h>
42 #include <vlc_charset.h>
43 #include "config/configuration.h"
44 #include "libvlc.h"
46 static const struct key_descriptor
48 const char psz[20];
49 uint32_t i_code;
50 } s_keys[] =
51 { /* Alphabetical order */
52 { N_("Backspace"), KEY_BACKSPACE },
53 { N_("Brightness Down"), KEY_BRIGHTNESS_DOWN },
54 { N_("Brightness Up"), KEY_BRIGHTNESS_UP },
55 { N_("Browser Back"), KEY_BROWSER_BACK },
56 { N_("Browser Favorites"), KEY_BROWSER_FAVORITES },
57 { N_("Browser Forward"), KEY_BROWSER_FORWARD },
58 { N_("Browser Home"), KEY_BROWSER_HOME },
59 { N_("Browser Refresh"), KEY_BROWSER_REFRESH },
60 { N_("Browser Search"), KEY_BROWSER_SEARCH },
61 { N_("Browser Stop"), KEY_BROWSER_STOP },
62 { N_("Delete"), KEY_DELETE },
63 { N_("Down"), KEY_DOWN },
64 { N_("End"), KEY_END },
65 { N_("Enter"), KEY_ENTER },
66 { N_("Esc"), KEY_ESC },
67 { N_("F1"), KEY_F1 },
68 { N_("F10"), KEY_F10 },
69 { N_("F11"), KEY_F11 },
70 { N_("F12"), KEY_F12 },
71 { N_("F2"), KEY_F2 },
72 { N_("F3"), KEY_F3 },
73 { N_("F4"), KEY_F4 },
74 { N_("F5"), KEY_F5 },
75 { N_("F6"), KEY_F6 },
76 { N_("F7"), KEY_F7 },
77 { N_("F8"), KEY_F8 },
78 { N_("F9"), KEY_F9 },
79 { N_("Home"), KEY_HOME },
80 { N_("Insert"), KEY_INSERT },
81 { N_("Left"), KEY_LEFT },
82 { N_("Media Angle"), KEY_MEDIA_ANGLE },
83 { N_("Media Audio Track"), KEY_MEDIA_AUDIO },
84 { N_("Media Forward"), KEY_MEDIA_FORWARD },
85 { N_("Media Menu"), KEY_MEDIA_MENU },
86 { N_("Media Next Frame"), KEY_MEDIA_FRAME_NEXT },
87 { N_("Media Next Track"), KEY_MEDIA_NEXT_TRACK },
88 { N_("Media Play Pause"), KEY_MEDIA_PLAY_PAUSE },
89 { N_("Media Prev Frame"), KEY_MEDIA_FRAME_PREV },
90 { N_("Media Prev Track"), KEY_MEDIA_PREV_TRACK },
91 { N_("Media Record"), KEY_MEDIA_RECORD },
92 { N_("Media Repeat"), KEY_MEDIA_REPEAT },
93 { N_("Media Rewind"), KEY_MEDIA_REWIND },
94 { N_("Media Select"), KEY_MEDIA_SELECT },
95 { N_("Media Shuffle"), KEY_MEDIA_SHUFFLE },
96 { N_("Media Stop"), KEY_MEDIA_STOP },
97 { N_("Media Subtitle"), KEY_MEDIA_SUBTITLE },
98 { N_("Media Time"), KEY_MEDIA_TIME },
99 { N_("Media View"), KEY_MEDIA_VIEW },
100 { N_("Menu"), KEY_MENU },
101 { N_("Mouse Wheel Down"), KEY_MOUSEWHEELDOWN },
102 { N_("Mouse Wheel Left"), KEY_MOUSEWHEELLEFT },
103 { N_("Mouse Wheel Right"), KEY_MOUSEWHEELRIGHT },
104 { N_("Mouse Wheel Up"), KEY_MOUSEWHEELUP },
105 { N_("Page Down"), KEY_PAGEDOWN },
106 { N_("Page Up"), KEY_PAGEUP },
107 { N_("Pause"), KEY_PAUSE },
108 { N_("Print"), KEY_PRINT },
109 { N_("Right"), KEY_RIGHT },
110 { N_("Space"), ' ' },
111 { N_("Tab"), KEY_TAB },
112 { N_("Unset"), KEY_UNSET },
113 { N_("Up"), KEY_UP },
114 { N_("Volume Down"), KEY_VOLUME_DOWN },
115 { N_("Volume Mute"), KEY_VOLUME_MUTE },
116 { N_("Volume Up"), KEY_VOLUME_UP },
117 { N_("Zoom In"), KEY_ZOOM_IN },
118 { N_("Zoom Out"), KEY_ZOOM_OUT },
121 static int keystrcmp (const void *key, const void *elem)
123 const char *sa = key, *sb = elem;
124 return strcmp (sa, sb);
127 /* Convert Unicode code point to UTF-8 */
128 static char *utf8_cp (uint_fast32_t cp, char *buf)
130 if (cp < (1 << 7))
132 buf[1] = 0;
133 buf[0] = cp;
135 else if (cp < (1 << 11))
137 buf[2] = 0;
138 buf[1] = 0x80 | (cp & 0x3F);
139 cp >>= 6;
140 buf[0] = 0xC0 | cp;
142 else if (cp < (1 << 16))
144 buf[3] = 0;
145 buf[2] = 0x80 | (cp & 0x3F);
146 cp >>= 6;
147 buf[1] = 0x80 | (cp & 0x3F);
148 cp >>= 6;
149 buf[0] = 0xE0 | cp;
151 else if (cp < (1 << 21))
153 buf[4] = 0;
154 buf[3] = 0x80 | (cp & 0x3F);
155 cp >>= 6;
156 buf[2] = 0x80 | (cp & 0x3F);
157 cp >>= 6;
158 buf[1] = 0x80 | (cp & 0x3F);
159 cp >>= 6;
160 buf[0] = 0xE0 | cp;
162 else
163 return NULL;
164 return buf;
168 * Parse a human-readable string representation of a VLC key code.
169 * @note This only works with the American English representation
170 * (a.k.a. C or POSIX), not with the local representation returned from
171 * vlc_keycode2str().
172 * @return a VLC key code, or KEY_UNSET on failure.
174 uint_fast32_t vlc_str2keycode (const char *name)
176 uint_fast32_t mods = 0;
177 uint32_t code;
179 for (;;)
181 size_t len = strcspn (name, "-+");
182 if (len == 0 || name[len] == '\0')
183 break;
185 if (len == 4 && !strncasecmp (name, "Ctrl", 4))
186 mods |= KEY_MODIFIER_CTRL;
187 if (len == 3 && !strncasecmp (name, "Alt", 3))
188 mods |= KEY_MODIFIER_ALT;
189 if (len == 5 && !strncasecmp (name, "Shift", 5))
190 mods |= KEY_MODIFIER_SHIFT;
191 if (len == 4 && !strncasecmp (name, "Meta", 4))
192 mods |= KEY_MODIFIER_META;
193 if (len == 7 && !strncasecmp (name, "Command", 7))
194 mods |= KEY_MODIFIER_COMMAND;
196 name += len + 1;
199 struct key_descriptor *d = bsearch (name, s_keys, ARRAY_SIZE(s_keys),
200 sizeof (s_keys[0]), keystrcmp);
201 if (d != NULL)
202 code = d->i_code;
203 else
204 if (vlc_towc (name, &code) <= 0)
205 code = KEY_UNSET;
207 if (code != KEY_UNSET)
208 code |= mods;
209 return code;
212 static const char *nooptext (const char *txt)
214 return txt;
218 * Format a human-readable and unique representation of a VLC key code
219 * (including modifiers).
220 * @param code key code to translate to a string
221 * @param locale true to get a localized string,
222 * false to get a C string suitable for 'vlcrc'
223 * @return a heap-allocated string, or NULL on error.
225 char *vlc_keycode2str (uint_fast32_t code, bool locale)
227 const char *(*tr)(const char *) = locale ? vlc_gettext : nooptext;
228 const char *name;
229 char *str, buf[5];
230 uintptr_t key = code & ~KEY_MODIFIER;
232 for (size_t i = 0; i < ARRAY_SIZE(s_keys); i++)
233 if (s_keys[i].i_code == key)
235 name = s_keys[i].psz;
236 goto found;
239 if (utf8_cp (key, buf) == NULL)
240 return NULL;
241 name = buf;
243 found:
244 if (asprintf (&str, "%s%s%s%s%s%s",
245 (code & KEY_MODIFIER_CTRL) ? tr(N_("Ctrl+")) : "",
246 (code & KEY_MODIFIER_ALT) ? tr(N_("Alt+")) : "",
247 (code & KEY_MODIFIER_SHIFT) ? tr(N_("Shift+")) : "",
248 (code & KEY_MODIFIER_META) ? tr(N_("Meta+")) : "",
249 (code & KEY_MODIFIER_COMMAND) ? tr(N_("Command+")) : "",
250 tr(name)) == -1)
251 return NULL;
252 return str;
256 /*** VLC key map ***/
258 #define MAXACTION 27
259 static const struct name2action
261 char psz[MAXACTION];
262 vlc_action_id_t id;
263 } s_names2actions[] =
265 /* *MUST* be sorted (ASCII order) */
266 { "aspect-ratio", ACTIONID_ASPECT_RATIO, },
267 { "audio-track", ACTIONID_AUDIO_TRACK, },
268 { "audiodelay-down", ACTIONID_AUDIODELAY_DOWN, },
269 { "audiodelay-up", ACTIONID_AUDIODELAY_UP, },
270 { "audiodevice-cycle", ACTIONID_AUDIODEVICE_CYCLE, },
271 { "chapter-next", ACTIONID_CHAPTER_NEXT, },
272 { "chapter-prev", ACTIONID_CHAPTER_PREV, },
273 { "clear-playlist", ACTIONID_PLAY_CLEAR, },
274 { "crop", ACTIONID_CROP, },
275 { "crop-bottom", ACTIONID_CROP_BOTTOM, },
276 { "crop-left", ACTIONID_CROP_LEFT, },
277 { "crop-right", ACTIONID_CROP_RIGHT, },
278 { "crop-top", ACTIONID_CROP_TOP, },
279 { "decr-scalefactor", ACTIONID_SCALE_DOWN, },
280 { "deinterlace", ACTIONID_DEINTERLACE, },
281 { "deinterlace-mode", ACTIONID_DEINTERLACE_MODE, },
282 { "disc-menu", ACTIONID_DISC_MENU, },
283 { "faster", ACTIONID_RATE_FASTER, },
284 { "frame-next", ACTIONID_FRAME_NEXT, },
285 { "incr-scalefactor", ACTIONID_SCALE_UP, },
286 { "intf-boss", ACTIONID_INTF_BOSS, },
287 { "intf-popup-menu", ACTIONID_INTF_POPUP_MENU, },
288 { "intf-show", ACTIONID_INTF_TOGGLE_FSC, },
289 { "jump+extrashort", ACTIONID_JUMP_FORWARD_EXTRASHORT, },
290 { "jump+long", ACTIONID_JUMP_FORWARD_LONG, },
291 { "jump+medium", ACTIONID_JUMP_FORWARD_MEDIUM, },
292 { "jump+short", ACTIONID_JUMP_FORWARD_SHORT, },
293 { "jump-extrashort", ACTIONID_JUMP_BACKWARD_EXTRASHORT, },
294 { "jump-long", ACTIONID_JUMP_BACKWARD_LONG, },
295 { "jump-medium", ACTIONID_JUMP_BACKWARD_MEDIUM, },
296 { "jump-short", ACTIONID_JUMP_BACKWARD_SHORT, },
297 { "leave-fullscreen", ACTIONID_LEAVE_FULLSCREEN, },
298 { "loop", ACTIONID_LOOP, },
299 { "nav-activate", ACTIONID_NAV_ACTIVATE, },
300 { "nav-down", ACTIONID_NAV_DOWN, },
301 { "nav-left", ACTIONID_NAV_LEFT, },
302 { "nav-right", ACTIONID_NAV_RIGHT, },
303 { "nav-up", ACTIONID_NAV_UP, },
304 { "next", ACTIONID_NEXT, },
305 { "pause", ACTIONID_PAUSE, },
306 { "play", ACTIONID_PLAY, },
307 { "play-bookmark1", ACTIONID_PLAY_BOOKMARK1, },
308 { "play-bookmark10", ACTIONID_PLAY_BOOKMARK10, },
309 { "play-bookmark2", ACTIONID_PLAY_BOOKMARK2, },
310 { "play-bookmark3", ACTIONID_PLAY_BOOKMARK3, },
311 { "play-bookmark4", ACTIONID_PLAY_BOOKMARK4, },
312 { "play-bookmark5", ACTIONID_PLAY_BOOKMARK5, },
313 { "play-bookmark6", ACTIONID_PLAY_BOOKMARK6, },
314 { "play-bookmark7", ACTIONID_PLAY_BOOKMARK7, },
315 { "play-bookmark8", ACTIONID_PLAY_BOOKMARK8, },
316 { "play-bookmark9", ACTIONID_PLAY_BOOKMARK9, },
317 { "play-pause", ACTIONID_PLAY_PAUSE, },
318 { "position", ACTIONID_POSITION, },
319 { "prev", ACTIONID_PREV, },
320 { "program-sid-next", ACTIONID_PROGRAM_SID_NEXT, },
321 { "program-sid-prev", ACTIONID_PROGRAM_SID_PREV, },
322 { "quit", ACTIONID_QUIT, },
323 { "random", ACTIONID_RANDOM, },
324 { "rate-faster-fine", ACTIONID_RATE_FASTER_FINE, },
325 { "rate-normal", ACTIONID_RATE_NORMAL, },
326 { "rate-slower-fine", ACTIONID_RATE_SLOWER_FINE, },
327 { "record", ACTIONID_RECORD, },
328 { "set-bookmark1", ACTIONID_SET_BOOKMARK1, },
329 { "set-bookmark10", ACTIONID_SET_BOOKMARK10, },
330 { "set-bookmark2", ACTIONID_SET_BOOKMARK2, },
331 { "set-bookmark3", ACTIONID_SET_BOOKMARK3, },
332 { "set-bookmark4", ACTIONID_SET_BOOKMARK4, },
333 { "set-bookmark5", ACTIONID_SET_BOOKMARK5, },
334 { "set-bookmark6", ACTIONID_SET_BOOKMARK6, },
335 { "set-bookmark7", ACTIONID_SET_BOOKMARK7, },
336 { "set-bookmark8", ACTIONID_SET_BOOKMARK8, },
337 { "set-bookmark9", ACTIONID_SET_BOOKMARK9, },
338 { "slower", ACTIONID_RATE_SLOWER, },
339 { "snapshot", ACTIONID_SNAPSHOT, },
340 { "stop", ACTIONID_STOP, },
341 { "subdelay-down", ACTIONID_SUBDELAY_DOWN, },
342 { "subdelay-up", ACTIONID_SUBDELAY_UP, },
343 { "subpos-down", ACTIONID_SUBPOS_DOWN, },
344 { "subpos-up", ACTIONID_SUBPOS_UP, },
345 { "subsync-apply", ACTIONID_SUBSYNC_APPLY, },
346 { "subsync-markaudio", ACTIONID_SUBSYNC_MARKAUDIO, },
347 { "subsync-marksub", ACTIONID_SUBSYNC_MARKSUB, },
348 { "subsync-reset", ACTIONID_SUBSYNC_RESET, },
349 { "subtitle-control-secondary", ACTIONID_SUBTITLE_CONTROL_SECONDARY, },
350 { "subtitle-revtrack", ACTIONID_SUBTITLE_REVERSE_TRACK, },
351 { "subtitle-text-scale-down", ACTIONID_SUBTITLE_TEXT_SCALE_DOWN, },
352 { "subtitle-text-scale-normal", ACTIONID_SUBTITLE_TEXT_SCALE_NORMAL, },
353 { "subtitle-text-scale-up", ACTIONID_SUBTITLE_TEXT_SCALE_UP, },
354 { "subtitle-toggle", ACTIONID_SUBTITLE_TOGGLE, },
355 { "subtitle-track", ACTIONID_SUBTITLE_TRACK, },
356 { "title-next", ACTIONID_TITLE_NEXT, },
357 { "title-prev", ACTIONID_TITLE_PREV, },
358 { "toggle-autoscale", ACTIONID_TOGGLE_AUTOSCALE, },
359 { "toggle-fullscreen", ACTIONID_TOGGLE_FULLSCREEN, },
360 { "uncrop-bottom", ACTIONID_UNCROP_BOTTOM, },
361 { "uncrop-left", ACTIONID_UNCROP_LEFT, },
362 { "uncrop-right", ACTIONID_UNCROP_RIGHT, },
363 { "uncrop-top", ACTIONID_UNCROP_TOP, },
364 { "unzoom", ACTIONID_UNZOOM, },
365 { "viewpoint-fov-in", ACTIONID_VIEWPOINT_FOV_IN, },
366 { "viewpoint-fov-out", ACTIONID_VIEWPOINT_FOV_OUT, },
367 { "viewpoint-roll-anticlock", ACTIONID_VIEWPOINT_ROLL_ANTICLOCK, },
368 { "viewpoint-roll-clock", ACTIONID_VIEWPOINT_ROLL_CLOCK, },
369 { "vol-down", ACTIONID_VOL_DOWN, },
370 { "vol-mute", ACTIONID_VOL_MUTE, },
371 { "vol-up", ACTIONID_VOL_UP, },
372 { "wallpaper", ACTIONID_WALLPAPER, },
373 { "zoom", ACTIONID_ZOOM, },
374 { "zoom-double", ACTIONID_ZOOM_DOUBLE, },
375 { "zoom-half", ACTIONID_ZOOM_HALF, },
376 { "zoom-original", ACTIONID_ZOOM_ORIGINAL, },
377 { "zoom-quarter", ACTIONID_ZOOM_QUARTER, },
380 struct mapping
382 uint32_t key; ///< Key code
383 vlc_action_id_t action; ///< Action ID
386 static int keycmp (const void *a, const void *b)
388 const struct mapping *ka = a, *kb = b;
390 return (ka->key < kb->key) ? -1 : (ka->key > kb->key) ? +1 : 0;
393 struct vlc_actions_t
395 void *map; /* Key map */
396 void *global_map; /* Grabbed/global key map */
397 const char *ppsz_keys[];
400 static int vlc_key_to_action (vlc_object_t *obj, const char *varname,
401 vlc_value_t prevkey, vlc_value_t curkey, void *d)
403 void *const *map = d;
404 const void **pent;
405 uint32_t keycode = curkey.i_int;
407 pent = tfind (&keycode, map, keycmp);
408 if (pent == NULL)
409 return VLC_SUCCESS;
411 const struct mapping *ent = *pent;
413 (void) varname;
414 (void) prevkey;
415 return var_SetInteger (obj, "key-action", ent->action);
419 * Adds a mapping from a certain key code to a certain action.
421 static int add_mapping (void **map, uint32_t keycode, vlc_action_id_t action)
423 struct mapping *entry = malloc (sizeof (*entry));
424 if (entry == NULL)
425 return ENOMEM;
426 entry->key = keycode;
427 entry->action = action;
429 void **pent = tsearch (entry, map, keycmp);
430 if (unlikely(pent == NULL))
431 return ENOMEM;
432 if (*pent != entry)
434 free (entry);
435 return EEXIST;
437 return 0;
440 static void add_wheel_mapping (void **map, uint32_t kmore, uint32_t kless,
441 int mode)
443 vlc_action_id_t amore = ACTIONID_NONE, aless = ACTIONID_NONE;
445 switch (mode)
447 case 0: /* volume up/down */
448 amore = ACTIONID_COMBO_VOL_FOV_UP;
449 aless = ACTIONID_COMBO_VOL_FOV_DOWN;
450 break;
451 case 2: /* position latter/earlier */
452 amore = ACTIONID_JUMP_FORWARD_EXTRASHORT;
453 aless = ACTIONID_JUMP_BACKWARD_EXTRASHORT;
454 break;
455 case 3: /* position earlier/latter */
456 amore = ACTIONID_JUMP_BACKWARD_EXTRASHORT;
457 aless = ACTIONID_JUMP_FORWARD_EXTRASHORT;
458 break;
461 if (amore != ACTIONID_NONE)
462 add_mapping (map, kmore, amore);
463 if (aless != ACTIONID_NONE)
464 add_mapping (map, kless, aless);
469 * Sets up all key mappings for a given action.
470 * \param map tree (of struct mapping entries) to write mappings to
471 * \param confname VLC configuration item to read mappings from
472 * \param action action ID
474 static void init_action (vlc_object_t *obj, void **map,
475 const char *confname, vlc_action_id_t action)
477 char *keys = var_InheritString (obj, confname);
478 if (keys == NULL)
479 return;
481 for (char *buf, *key = strtok_r (keys, "\t", &buf);
482 key != NULL;
483 key = strtok_r (NULL, "\t", &buf))
485 uint32_t code = vlc_str2keycode (key);
486 if (code == KEY_UNSET)
488 msg_Warn (obj, "Key \"%s\" unrecognized", key);
489 continue;
492 if (add_mapping (map, code, action) == EEXIST)
493 msg_Warn (obj, "Key \"%s\" bound to multiple actions", key);
495 free (keys);
499 * Initializes the key map from configuration.
501 int libvlc_InternalActionsInit (libvlc_int_t *libvlc)
503 assert(libvlc != NULL);
505 vlc_object_t *obj = VLC_OBJECT(libvlc);
506 vlc_actions_t *as = malloc (sizeof (*as) + (1 + ARRAY_SIZE(s_names2actions))
507 * sizeof (*as->ppsz_keys));
509 if (unlikely(as == NULL))
510 return VLC_ENOMEM;
511 as->map = NULL;
512 as->global_map = NULL;
514 var_Create (obj, "key-pressed", VLC_VAR_INTEGER);
515 var_Create (obj, "global-key-pressed", VLC_VAR_INTEGER);
516 var_Create (obj, "key-action", VLC_VAR_INTEGER);
518 /* Initialize from configuration */
519 for (size_t i = 0; i < ARRAY_SIZE(s_names2actions); i++)
521 #ifndef NDEBUG
522 if (i > 0
523 && strcmp (s_names2actions[i-1].psz, s_names2actions[i].psz) >= 0)
525 msg_Err (libvlc, "key-%s and key-%s are not ordered properly",
526 s_names2actions[i-1].psz, s_names2actions[i].psz);
527 abort ();
529 #endif
530 as->ppsz_keys[i] = s_names2actions[i].psz;
532 char name[12 + MAXACTION];
534 snprintf (name, sizeof (name), "global-key-%s", s_names2actions[i].psz);
535 init_action (obj, &as->map, name + 7, s_names2actions[i].id);
536 init_action (obj, &as->global_map, name, s_names2actions[i].id);
538 as->ppsz_keys[ARRAY_SIZE(s_names2actions)] = NULL;
540 /* Initialize mouse wheel events */
541 add_wheel_mapping (&as->map, KEY_MOUSEWHEELRIGHT, KEY_MOUSEWHEELLEFT,
542 var_InheritInteger (obj, "hotkeys-x-wheel-mode"));
543 add_wheel_mapping (&as->map, KEY_MOUSEWHEELUP, KEY_MOUSEWHEELDOWN,
544 var_InheritInteger (obj, "hotkeys-y-wheel-mode"));
546 libvlc_priv(libvlc)->actions = as;
547 var_AddCallback (obj, "key-pressed", vlc_key_to_action, &as->map);
548 var_AddCallback (obj, "global-key-pressed", vlc_key_to_action,
549 &as->global_map);
550 return VLC_SUCCESS;
554 * Destroys the key map.
556 void libvlc_InternalActionsClean (libvlc_int_t *libvlc)
558 assert(libvlc != NULL);
560 vlc_actions_t *as = libvlc_priv(libvlc)->actions;
561 if (unlikely(as == NULL))
562 return;
564 var_DelCallback (libvlc, "global-key-pressed", vlc_key_to_action,
565 &as->global_map);
566 var_DelCallback (libvlc, "key-pressed", vlc_key_to_action, &as->map);
568 tdestroy (as->global_map, free);
569 tdestroy (as->map, free);
570 free (as);
571 libvlc_priv(libvlc)->actions = NULL;
575 static int actcmp(const void *key, const void *ent)
577 const struct name2action *act = ent;
578 return strcmp(key, act->psz);
582 * Get the action ID from the action name in the configuration subsystem.
583 * @return the action ID or ACTIONID_NONE on error.
585 vlc_action_id_t
586 vlc_actions_get_id (const char *name)
588 const struct name2action *act;
590 if (strncmp (name, "key-", 4))
591 return ACTIONID_NONE;
592 name += 4;
594 act = bsearch(name, s_names2actions, ARRAY_SIZE(s_names2actions),
595 sizeof(*act), actcmp);
596 return (act != NULL) ? act->id : ACTIONID_NONE;
599 #undef vlc_actions_get_keycodes
600 size_t
601 vlc_actions_get_keycodes(vlc_object_t *p_obj, const char *psz_key_name,
602 bool b_global, uint_fast32_t **pp_keycodes)
604 assert(strlen( psz_key_name ) <= MAXACTION);
605 char varname[12 /* "global-key-" */ + MAXACTION];
606 sprintf( varname, "%skey-%s", b_global ? "global-" : "", psz_key_name );
608 *pp_keycodes = NULL;
610 char *psz_keys = var_InheritString( p_obj, varname );
611 if( psz_keys == NULL )
612 return 0;
614 size_t i_nb_keycodes = 0;
615 for( const char* psz_it = psz_keys; *psz_it; ++psz_it )
617 if( *psz_it == '\t' )
618 ++i_nb_keycodes;
620 ++i_nb_keycodes;
621 *pp_keycodes = vlc_alloc( i_nb_keycodes, sizeof( **pp_keycodes ) );
622 if( unlikely( !*pp_keycodes ) )
624 free( psz_keys );
625 return 0;
627 size_t i = 0;
628 for( char *buf, *key = strtok_r( psz_keys, "\t", &buf );
629 key != NULL;
630 key = strtok_r( NULL, "\t", &buf ), ++i )
632 (*pp_keycodes)[i] = vlc_str2keycode( key );
634 assert( i == i_nb_keycodes );
635 free( psz_keys );
636 return i_nb_keycodes;
639 #undef vlc_actions_get_key_names
640 const char* const*
641 vlc_actions_get_key_names(vlc_object_t *p_obj)
643 vlc_actions_t *as = libvlc_priv(vlc_object_instance(p_obj))->actions;
644 return as->ppsz_keys;