]> git.sesse.net Git - vlc/blob - src/modules/entry.c
Submodules do not inherit shortcuts anymore (fix: #2696)
[vlc] / src / modules / entry.c
1 /*****************************************************************************
2  * entry.c : Callbacks for module entry point
3  *****************************************************************************
4  * Copyright (C) 2007 the VideoLAN team
5  * Copyright © 2007-2008 Rémi Denis-Courmont
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 <vlc_plugin.h>
28 #include <assert.h>
29 #include <stdarg.h>
30
31 #ifdef ENABLE_NLS
32 # include <libintl.h>
33 #endif
34
35 #include "modules/modules.h"
36 #include "config/configuration.h"
37 #include "libvlc.h"
38
39 static const char *mdgettext (const char *domain, const char *msg)
40 {
41     assert (msg);
42 #ifdef ENABLE_NLS
43     if (*msg) /* Do not translate ""! */
44         return dgettext (domain, msg);
45 #endif
46     return msg;
47 }
48
49 static void vlc_module_destruct (gc_object_t *obj)
50 {
51     module_t *module = vlc_priv (obj, module_t);
52
53     vlc_mutex_destroy (&module->lock);
54     free (module->psz_object_name);
55     free (module);
56 }
57
58 static const char default_name[] = "unnamed";
59
60 module_t *vlc_module_create (vlc_object_t *obj)
61 {
62     module_t *module = malloc (sizeof (*module));
63     if (module == NULL)
64         return NULL;
65
66     module->psz_object_name = strdup( default_name );
67     module->next = NULL;
68     module->submodule = NULL;
69     module->parent = NULL;
70     module->submodule_count = 0;
71     vlc_gc_init (module, vlc_module_destruct);
72     vlc_mutex_init (&module->lock);
73
74     module->psz_shortname = NULL;
75     module->psz_longname = (char*)default_name;
76     module->psz_help = NULL;
77     for (unsigned i = 0; i < MODULE_SHORTCUT_MAX; i++)
78         module->pp_shortcuts[i] = NULL;
79     module->psz_capability = (char*)"";
80     module->i_score = 1;
81     module->i_cpu = 0;
82     module->b_unloadable = true;
83     module->b_reentrant = true;
84     module->b_submodule = false;
85     module->pf_activate = NULL;
86     module->pf_deactivate = NULL;
87     module->p_config = NULL;
88     module->confsize = 0;
89     module->i_config_items = 0;
90     module->i_bool_items = 0;
91     /*module->handle = garbage */
92     module->psz_filename = NULL;
93     module->b_builtin = false;
94     module->b_loaded = false;
95
96     (void)obj;
97     return module;
98 }
99
100
101 static void vlc_submodule_destruct (gc_object_t *obj)
102 {
103     module_t *module = vlc_priv (obj, module_t);
104     free (module->psz_object_name);
105     free (module);
106 }
107
108 module_t *vlc_submodule_create (module_t *module)
109 {
110     assert (module != NULL);
111
112     module_t *submodule = calloc( 1, sizeof(*submodule) );
113     if( !submodule )
114         return NULL;
115
116     vlc_gc_init (submodule, vlc_submodule_destruct);
117
118     submodule->next = module->submodule;
119     submodule->parent = module;
120     module->submodule = submodule;
121     module->submodule_count++;
122
123     /* Muahahaha! Heritage! Polymorphism! Ugliness!! */
124     submodule->pp_shortcuts[0] = module->pp_shortcuts[0]; /* object name */
125     for (unsigned i = 1; i < MODULE_SHORTCUT_MAX; i++)
126         submodule->pp_shortcuts[i] = NULL;
127
128     submodule->psz_object_name = strdup( module->psz_object_name );
129     submodule->psz_shortname = module->psz_shortname;
130     submodule->psz_longname = module->psz_longname;
131     submodule->psz_capability = module->psz_capability;
132     submodule->i_score = module->i_score;
133     submodule->i_cpu = module->i_cpu;
134     submodule->b_submodule = true;
135     return submodule;
136 }
137
138 static module_config_t *vlc_config_create (module_t *module, int type)
139 {
140     unsigned confsize = module->confsize;
141     module_config_t *tab = module->p_config;
142
143     if ((confsize & 0xf) == 0)
144     {
145         tab = realloc (tab, (confsize + 17) * sizeof (*tab));
146         if (tab == NULL)
147             return NULL;
148
149         module->p_config = tab;
150     }
151
152     memset (tab + confsize, 0, sizeof (tab[confsize]));
153     tab[confsize].i_type = type;
154     tab[confsize].p_lock = &module->lock;
155
156     if (type & CONFIG_ITEM)
157     {
158         module->i_config_items++;
159         if (type == CONFIG_ITEM_BOOL)
160             module->i_bool_items++;
161     }
162
163     module->confsize++;
164     return tab + confsize;
165 }
166
167
168 int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
169 {
170     va_list ap;
171     int ret = 0;
172
173     va_start (ap, propid);
174     switch (propid)
175     {
176         case VLC_SUBMODULE_CREATE:
177         {
178             module_t **pp = va_arg (ap, module_t **);
179             *pp = vlc_submodule_create (module);
180             if (*pp == NULL)
181                 ret = -1;
182             break;
183         }
184
185         case VLC_CONFIG_CREATE:
186         {
187             int type = va_arg (ap, int);
188             module_config_t **pp = va_arg (ap, module_config_t **);
189             *pp = vlc_config_create (module, type);
190             if (*pp == NULL)
191                 ret = -1;
192             break;
193         }
194
195         case VLC_MODULE_CPU_REQUIREMENT:
196             assert (!module->b_submodule);
197             module->i_cpu |= va_arg (ap, int);
198             break;
199
200         case VLC_MODULE_SHORTCUT:
201         {
202             unsigned i;
203             for (i = 0; module->pp_shortcuts[i] != NULL; i++);
204                 if (i >= (MODULE_SHORTCUT_MAX - 1))
205                     break;
206
207             module->pp_shortcuts[i] = va_arg (ap, char *);
208             break;
209         }
210
211         case VLC_MODULE_CAPABILITY:
212             module->psz_capability = va_arg (ap, char *);
213             break;
214
215         case VLC_MODULE_SCORE:
216             module->i_score = va_arg (ap, int);
217             break;
218
219         case VLC_MODULE_CB_OPEN:
220             module->pf_activate = va_arg (ap, int (*) (vlc_object_t *));
221             break;
222
223         case VLC_MODULE_CB_CLOSE:
224             module->pf_deactivate = va_arg (ap, void (*) (vlc_object_t *));
225             break;
226
227         case VLC_MODULE_NO_UNLOAD:
228             module->b_unloadable = false;
229             break;
230
231         case VLC_MODULE_NAME:
232         {
233             const char *value = va_arg (ap, const char *);
234             free( module->psz_object_name );
235             module->psz_object_name = strdup( value );
236             module->pp_shortcuts[0] = (char*)value; /* dooh! */
237             if (module->psz_longname == default_name)
238                 module->psz_longname = (char*)value; /* dooh! */
239             break;
240         }
241
242         case VLC_MODULE_SHORTNAME:
243         {
244             const char *domain = va_arg (ap, const char *);
245             if (domain == NULL)
246                 domain = PACKAGE;
247             module->psz_shortname = mdgettext (domain, va_arg (ap, char *));
248             break;
249         }
250
251         case VLC_MODULE_DESCRIPTION:
252         {
253             const char *domain = va_arg (ap, const char *);
254             if (domain == NULL)
255                 domain = PACKAGE;
256             module->psz_longname = mdgettext (domain, va_arg (ap, char *));
257             break;
258         }
259
260         case VLC_MODULE_HELP:
261         {
262             const char *domain = va_arg (ap, const char *);
263             if (domain == NULL)
264                 domain = PACKAGE;
265             module->psz_help = mdgettext (domain, va_arg (ap, char *));
266             break;
267         }
268
269         case VLC_CONFIG_NAME:
270         {
271             const char *name = va_arg (ap, const char *);
272             vlc_callback_t cb = va_arg (ap, vlc_callback_t);
273
274             assert (name != NULL);
275             item->psz_name = strdup (name);
276             item->pf_callback = cb;
277             break;
278         }
279
280         case VLC_CONFIG_VALUE:
281         {
282             if (IsConfigIntegerType (item->i_type))
283             {
284                 item->orig.i = item->saved.i =
285                 item->value.i = va_arg (ap, int);
286             }
287             else
288             if (IsConfigFloatType (item->i_type))
289             {
290                 item->orig.f = item->saved.f =
291                 item->value.f = va_arg (ap, double);
292             }
293             else
294             if (IsConfigStringType (item->i_type))
295             {
296                 const char *value = va_arg (ap, const char *);
297                 item->value.psz = value ? strdup (value) : NULL;
298                 item->orig.psz = value ? strdup (value) : NULL;
299                 item->saved.psz = value ? strdup (value) : NULL;
300             }
301             break;
302         }
303
304         case VLC_CONFIG_RANGE:
305         {
306             if (IsConfigIntegerType (item->i_type)
307              || item->i_type == CONFIG_ITEM_MODULE_LIST_CAT
308              || item->i_type == CONFIG_ITEM_MODULE_CAT)
309             {
310                 item->min.i = va_arg (ap, int);
311                 item->max.i = va_arg (ap, int);
312             }
313             else
314             if (IsConfigFloatType (item->i_type))
315             {
316                 item->min.f = va_arg (ap, double);
317                 item->max.f = va_arg (ap, double);
318             }
319             break;
320         }
321
322         case VLC_CONFIG_ADVANCED:
323             item->b_advanced = true;
324             break;
325
326         case VLC_CONFIG_VOLATILE:
327             item->b_unsaveable = true;
328             break;
329
330         case VLC_CONFIG_PERSISTENT:
331             item->b_autosave = true;
332             break;
333
334         case VLC_CONFIG_RESTART:
335             item->b_restart = true;
336             break;
337
338         case VLC_CONFIG_PRIVATE:
339             item->b_internal = true;
340             break;
341
342         case VLC_CONFIG_REMOVED:
343             item->b_removed = true;
344             break;
345
346         case VLC_CONFIG_CAPABILITY:
347         {
348             const char *cap = va_arg (ap, const char *);
349             item->psz_type = cap ? strdup (cap) : NULL;
350             break;
351         }
352
353         case VLC_CONFIG_SHORTCUT:
354             item->i_short = va_arg (ap, int);
355             break;
356
357         case VLC_CONFIG_OLDNAME:
358         {
359             const char *oldname = va_arg (ap, const char *);
360             item->psz_oldname = oldname ? strdup (oldname) : NULL;
361             break;
362         }
363
364         case VLC_CONFIG_SAFE:
365             item->b_safe = true;
366             break;
367
368         case VLC_CONFIG_DESC:
369         {
370             const char *domain = va_arg (ap, const char *);
371             const char *text = va_arg (ap, const char *);
372             const char *longtext = va_arg (ap, const char *);
373
374             if (domain == NULL)
375                 domain = PACKAGE;
376             item->psz_text = text ? strdup (mdgettext (domain, text)) : NULL;
377             item->psz_longtext =
378                 longtext ? strdup (mdgettext (domain, longtext)) : NULL;
379             break;
380         }
381
382         case VLC_CONFIG_LIST:
383         {
384             const char *domain = va_arg (ap, const char *);
385             size_t len = va_arg (ap, size_t);
386
387             /* Copy values */
388             if (IsConfigIntegerType (item->i_type))
389             {
390                 const int *src = va_arg (ap, const int *);
391                 int *dst = malloc (sizeof (int) * (len + 1));
392
393                 if (dst != NULL)
394                 {
395                     memcpy (dst, src, sizeof (int) * len);
396                     dst[len] = 0;
397                 }
398                 item->pi_list = dst;
399             }
400             else
401             if (IsConfigStringType (item->i_type))
402             {
403                 const char *const *src = va_arg (ap, const char *const *);
404                 char **dst = malloc (sizeof (char *) * (len + 1));
405
406                 if (dst != NULL)
407                 {
408                     for (size_t i = 0; i < len; i++)
409                         dst[i] = src[i] ? strdup (src[i]) : NULL;
410                     dst[len] = NULL;
411                 }
412                 item->ppsz_list = dst;
413             }
414             else
415                 break;
416
417             /* Copy textual descriptions */
418             if (domain == NULL)
419                 domain = PACKAGE;
420
421             const char *const *text = va_arg (ap, const char *const *);
422             if (text != NULL)
423             {
424                 char **dtext = malloc (sizeof (char *) * (len + 1));
425                 if( dtext != NULL )
426                 {
427                     for (size_t i = 0; i < len; i++)
428                         dtext[i] = text[i] ?
429                                         strdup (mdgettext( domain, text[i] )) :
430                                         NULL;
431                     dtext[len] = NULL;
432                 }
433                 item->ppsz_list_text = dtext;
434             }
435             else
436                 item->ppsz_list_text = NULL;
437
438             item->i_list = len;
439             item->pf_update_list = va_arg (ap, vlc_callback_t);
440             break;
441         }
442
443         case VLC_CONFIG_ADD_ACTION:
444         {
445             const char *domain = va_arg (ap, const char *);
446             vlc_callback_t cb = va_arg (ap, vlc_callback_t), *tabcb;
447             const char *name = va_arg (ap, const char *);
448             char **tabtext;
449
450             tabcb = realloc (item->ppf_action,
451                              (item->i_action + 2) * sizeof (cb));
452             if (tabcb == NULL)
453                 break;
454             item->ppf_action = tabcb;
455             tabcb[item->i_action] = cb;
456             tabcb[item->i_action + 1] = NULL;
457
458             tabtext = realloc (item->ppsz_action_text,
459                                (item->i_action + 2) * sizeof (name));
460             if (tabtext == NULL)
461                 break;
462             item->ppsz_action_text = tabtext;
463
464             if (domain == NULL)
465                 domain = PACKAGE;
466             if (name)
467                 tabtext[item->i_action] = strdup (mdgettext (domain, name));
468             else
469                 tabtext[item->i_action] = NULL;
470             tabtext[item->i_action + 1] = NULL;
471
472             item->i_action++;
473             break;
474         }
475
476         default:
477             fprintf (stderr, "LibVLC: unknown module property %d\n", propid);
478             fprintf (stderr, "LibVLC: too old to use this module?\n");
479             ret = -1;
480             break;
481     }
482
483     va_end (ap);
484     return ret;
485 }