X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Faction.c;h=1f2657e1563d921a00de8f628a822b720c0643c2;hb=cd0c2c45c0198ec38cce4af877b033529639ddaa;hp=a9f79f39d80a5767f26efc514149a60c27b33cca;hpb=88226a802f38e75d0dbea4a74b8ec108a42ca653;p=vlc diff --git a/src/misc/action.c b/src/misc/action.c index a9f79f39d8..1f2657e156 100644 --- a/src/misc/action.c +++ b/src/misc/action.c @@ -2,6 +2,7 @@ * action.c: key to action mapping ***************************************************************************** * Copyright © 2008 Rémi Denis-Courmont + * © 2009 Antoine Cellerier * * 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 @@ -22,25 +23,112 @@ # include "config.h" #endif -#include +#include #include "../libvlc.h" +#include +#include +#include -int vlc_key_to_action (vlc_object_t *libvlc, const char *varname, - vlc_value_t prevkey, vlc_value_t curkey, void *priv) +static int keycmp (const void *a, const void *b) { - const struct hotkey *key = priv; + const struct hotkey *ka = a, *kb = b; +#if (INT_MAX >= 0x7fffffff) + return ka->i_key - kb->i_key; +#else + return (ka->i_key < kb->i_key) ? -1 : (ka->i_key > kb->i_key) ? +1 : 0; +#endif +} + +/** + * Get the action associated with a VLC key code, if any. + */ +static +vlc_key_t vlc_TranslateKey (const vlc_object_t *obj, uint_fast32_t keycode) +{ + struct hotkey k = { .psz_action = NULL, .i_key = keycode, .i_action = 0 }; + const struct hotkey *key; + key = bsearch (&k, obj->p_libvlc->p_hotkeys, libvlc_actions_count, + sizeof (*key), keycmp); + return (key != NULL) ? key->i_action : ACTIONID_NONE; +} + +static int vlc_key_to_action (vlc_object_t *libvlc, const char *varname, + vlc_value_t prevkey, vlc_value_t curkey, void *d) +{ (void)varname; (void)prevkey; + (void)d; - while (key->i_key != curkey.i_int) + vlc_key_t action = vlc_TranslateKey (libvlc, curkey.i_int); + if (!action) + return VLC_SUCCESS; + return var_SetInteger (libvlc, "key-action", action); +} + + +int vlc_InitActions (libvlc_int_t *libvlc) +{ + struct hotkey *keys; + + var_Create (libvlc, "key-pressed", VLC_VAR_INTEGER); + var_Create (libvlc, "key-action", VLC_VAR_INTEGER); + + keys = malloc ((libvlc_actions_count + 1) * sizeof (*keys)); + if (keys == NULL) { - if (key->psz_action == NULL) - return VLC_SUCCESS; /* key is not mapped to anything */ + libvlc->p_hotkeys = NULL; + return VLC_ENOMEM; + } - key++; + /* Initialize from configuration */ + for (size_t i = 0; i < libvlc_actions_count; i++) + { + keys[i].psz_action = libvlc_actions[i].name; + keys[i].i_key = var_InheritInteger (libvlc, libvlc_actions[i].name ); + keys[i].i_action = libvlc_actions[i].value; +#ifndef NDEBUG + if (i > 0 + && strcmp (libvlc_actions[i-1].name, libvlc_actions[i].name) >= 0) + { + msg_Err (libvlc, "%s and %s are not ordered properly", + libvlc_actions[i-1].name, libvlc_actions[i].name); + abort (); + } +#endif } + qsort (keys, libvlc_actions_count, sizeof (*keys), keycmp); + + keys[libvlc_actions_count].psz_action = NULL; + keys[libvlc_actions_count].i_key = 0; + keys[libvlc_actions_count].i_action = 0; + + libvlc->p_hotkeys = keys; + var_AddCallback (libvlc, "key-pressed", vlc_key_to_action, NULL); + return VLC_SUCCESS; +} + +void vlc_DeinitActions (libvlc_int_t *libvlc) +{ + if (unlikely(libvlc->p_hotkeys == NULL)) + return; + var_DelCallback (libvlc, "key-pressed", vlc_key_to_action, NULL); + free ((void *)libvlc->p_hotkeys); +} + + +static int actcmp(const void *key, const void *ent) +{ + const struct action *act = ent; + return strcmp(key, act->name); +} + +vlc_key_t vlc_GetActionId(const char *name) +{ + const struct action *act; - return var_SetInteger (libvlc, "key-action", key->i_action); + act = bsearch(name, libvlc_actions, libvlc_actions_count, sizeof(*act), + actcmp); + return (act != NULL) ? act->value : ACTIONID_NONE; }