]> git.sesse.net Git - vlc/blob - src/misc/action.c
Refactor key mapping internals
[vlc] / src / misc / action.c
1 /*****************************************************************************
2  * action.c: key to action mapping
3  *****************************************************************************
4  * Copyright © 2008 Rémi Denis-Courmont
5  *           © 2009 Antoine Cellerier
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20  *****************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <vlc_common.h>
27 #include "../libvlc.h"
28 #include <vlc_keys.h>
29 #include <stdlib.h>
30
31 /**
32  * Get the action associated with a VLC key code, if any.
33  */
34 static
35 vlc_key_t vlc_TranslateKey (const vlc_object_t *obj, uint_fast32_t keycode)
36 {
37     /* TODO: search should be O(log n), not O(n) */
38     for (const struct hotkey *key = obj->p_libvlc->p_hotkeys;
39          key->psz_action != NULL;
40          key++)
41     {
42         if (key->i_key == keycode)
43             return key->i_action;
44     }
45     return ACTIONID_NONE;
46 }
47
48 static int vlc_key_to_action (vlc_object_t *libvlc, const char *varname,
49                               vlc_value_t prevkey, vlc_value_t curkey, void *d)
50 {
51     (void)varname;
52     (void)prevkey;
53     (void)d;
54
55     vlc_key_t action = vlc_TranslateKey (libvlc, curkey.i_int);
56     if (!action)
57         return VLC_SUCCESS;
58     return var_SetInteger (libvlc, "key-action", action);
59 }
60
61
62 int vlc_InitActions (libvlc_int_t *libvlc)
63 {
64     struct hotkey *keys;
65
66     var_Create (libvlc, "key-pressed", VLC_VAR_INTEGER);
67     var_Create (libvlc, "key-action", VLC_VAR_INTEGER);
68
69     keys = malloc ((libvlc_actions_count + 1) * sizeof (*keys));
70     if (keys == NULL)
71     {
72         libvlc->p_hotkeys = NULL;
73         return VLC_ENOMEM;
74     }
75
76     /* Initialize from configuration */
77     for (size_t i = 0; i < libvlc_actions_count; i++)
78     {
79         keys[i].psz_action = libvlc_actions[i].name;
80         keys[i].i_key = config_GetInt (libvlc, libvlc_actions[i].name );
81         keys[i].i_action = libvlc_actions[i].value;
82 #ifndef NDEBUG
83         if (i > 0
84          && strcmp (libvlc_actions[i-1].name, libvlc_actions[i].name) >= 0)
85         {
86             msg_Err (libvlc, "%s and %s are not ordered properly",
87                      libvlc_actions[i-1].name, libvlc_actions[i].name);
88             abort ();
89         }
90 #endif
91     }
92     keys[libvlc_actions_count].psz_action = NULL;
93     keys[libvlc_actions_count].i_key = 0;
94     keys[libvlc_actions_count].i_action = 0;
95
96     libvlc->p_hotkeys = keys;
97     var_AddCallback (libvlc, "key-pressed", vlc_key_to_action, NULL);
98     return VLC_SUCCESS;
99 }
100
101 void vlc_DeinitActions (libvlc_int_t *libvlc)
102 {
103     if (unlikely(libvlc->p_hotkeys == NULL))
104         return;
105     var_DelCallback (libvlc, "key-pressed", vlc_key_to_action, NULL);
106     free ((void *)libvlc->p_hotkeys);
107 }
108
109
110 static int actcmp(const void *key, const void *ent)
111 {
112     const struct action *act = ent;
113     return strcmp(key, act->name);
114 }
115
116 vlc_key_t vlc_GetActionId(const char *name)
117 {
118     const struct action *act;
119
120     act = bsearch(name, libvlc_actions, libvlc_actions_count, sizeof(*act),
121                   actcmp);
122     return (act != NULL) ? act->value : ACTIONID_NONE;
123 }
124