]> git.sesse.net Git - vlc/blob - src/modules/entry.c
vlc security: As i've seen very little improvement on that front, i've decided to...
[vlc] / src / modules / entry.c
1 /*****************************************************************************
2  * entry.c : Callbacks for module entry point
3  *****************************************************************************
4  * Copyright (C) 2001-2007 the VideoLAN team
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #include <vlc/vlc.h>
22 #include <assert.h>
23 #include <stdarg.h>
24
25 #include "modules/modules.h"
26 #include "config/config.h"
27 #include "libvlc.h"
28
29 static const char default_name[] = "unnamed";
30
31 module_t *vlc_module_create (vlc_object_t *obj)
32 {
33     module_t *module =
34         (module_t *)vlc_custom_create (obj, sizeof (module_t),
35                                        VLC_OBJECT_MODULE, "module");
36     if (module == NULL)
37         return NULL;
38
39     module->b_reentrant = module->b_unloadable = VLC_TRUE;
40     module->psz_object_name = module->psz_longname = default_name;
41     module->psz_capability = "";
42     module->i_score = 1;
43     module->i_config_items = module->i_bool_items = 0;
44
45     return module;
46 }
47
48
49 module_t *vlc_submodule_create (module_t *module)
50 {
51     assert (module != NULL);
52     assert (!module->b_submodule); // subsubmodules are not supported
53
54     module_t *submodule =
55         (module_t *)vlc_custom_create (VLC_OBJECT (module), sizeof (module_t),
56                                        VLC_OBJECT_MODULE, "submodule");
57     if (submodule == NULL)
58         return NULL;
59
60     vlc_object_attach (submodule, module);
61     submodule->b_submodule = VLC_TRUE;
62
63     /* Muahahaha! Heritage! Polymorphism! Ugliness!! */
64     memcpy (submodule->pp_shortcuts, module->pp_shortcuts,
65             sizeof (submodule->pp_shortcuts));
66
67     submodule->psz_object_name = module->psz_object_name;
68     submodule->psz_shortname = module->psz_shortname;
69     submodule->psz_longname = module->psz_longname;
70     submodule->psz_capability = module->psz_capability;
71     submodule->i_score = module->i_score;
72     submodule->i_cpu = module->i_cpu;
73     return submodule;
74 }
75
76
77 int vlc_module_set (module_t *module, int propid, void *value)
78 {
79     switch (propid)
80     {
81         case VLC_MODULE_CPU_REQUIREMENT:
82             assert (!module->b_submodule);
83             module->i_cpu |= (intptr_t)value;
84             break;
85
86         case VLC_MODULE_SHORTCUT:
87         {
88             unsigned i;
89             for (i = 0; module->pp_shortcuts[i] != NULL; i++);
90             if (i >= (MODULE_SHORTCUT_MAX - 1))
91                 return VLC_ENOMEM;
92
93             module->pp_shortcuts[i] = (char *)value;
94             break;
95         }
96
97         case VLC_MODULE_SHORTNAME:
98             module->psz_shortname = (char *)value;
99             break;
100
101         case VLC_MODULE_DESCRIPTION:
102             module->psz_longname = (char *)value;
103             break;
104
105         case VLC_MODULE_HELP:
106             module->psz_help = (char *)value;
107             break;
108
109         case VLC_MODULE_CAPABILITY:
110             module->psz_capability = (char *)value;
111             break;
112
113         case VLC_MODULE_SCORE:
114             module->i_score = (intptr_t)value;
115             break;
116
117         case VLC_MODULE_CB_OPEN:
118             module->pf_activate = (int (*) (vlc_object_t *))value;
119             break;
120
121         case VLC_MODULE_CB_CLOSE:
122             module->pf_deactivate = (void (*) (vlc_object_t *))value;
123             break;
124
125         case VLC_MODULE_UNLOADABLE:
126             module->b_unloadable = (value != NULL);
127             break;
128
129         case VLC_MODULE_NAME:
130             module->pp_shortcuts[0] = module->psz_object_name = (char *)value;
131             if (module->psz_longname == default_name)
132                 module->psz_longname = (char *)value;
133             break;
134
135         case VLC_MODULE_PROGRAM:
136             msg_Warn (module, "deprecated module property %d", propid);
137             break;
138
139         default:
140             msg_Err (module, "unknown module property %d", propid);
141             msg_Err (module, "LibVLC might be too old to use this module.");
142             return VLC_EGENERIC;
143     }
144     return 0;
145 }
146
147 module_config_t *vlc_config_create (module_t *module, int type)
148 {
149     unsigned confsize = module->confsize;
150     module_config_t *tab = module->p_config;
151
152     if ((confsize & 0xf) == 0)
153     {
154         tab = realloc (tab, (confsize + 17) * sizeof (*tab));
155         if (tab == NULL)
156             return NULL;
157
158         module->p_config = tab;
159     }
160
161     memset (tab + confsize, 0, sizeof (tab[confsize]));
162     tab[confsize].i_type = type;
163     tab[confsize].p_lock = &module->object_lock;
164
165     if (type & CONFIG_ITEM)
166     {
167         module->i_config_items++;
168         if (type == CONFIG_ITEM_BOOL)
169             module->i_bool_items++;
170     }
171
172     module->confsize++;
173     return tab + confsize;
174 }
175
176 int vlc_config_set (module_config_t *restrict item, int id, ...)
177 {
178     int ret = -1;
179     va_list ap;
180
181     assert (item != NULL);
182     va_start (ap, id);
183
184     switch (id)
185     {
186         case VLC_CONFIG_NAME:
187         {
188             const char *name = va_arg (ap, const char *);
189             vlc_callback_t cb = va_arg (ap, vlc_callback_t);
190
191             assert (name != NULL);
192             item->psz_name = strdup (name);
193             item->pf_callback = cb;
194             ret = 0;
195             break;
196         }
197
198         case VLC_CONFIG_DESC:
199         {
200             const char *text = va_arg (ap, const char *);
201             const char *longtext = va_arg (ap, const char *);
202
203             item->psz_text = text ? strdup ( _(text)) : NULL;
204             item->psz_longtext = longtext ? strdup ( _(longtext)) : NULL;
205             ret = 0;
206             break;
207         }
208
209         case VLC_CONFIG_VALUE:
210         {
211             if (IsConfigIntegerType (item->i_type))
212             {
213                 item->orig.i = item->saved.i =
214                 item->value.i = va_arg (ap, int);
215                 ret = 0;
216             }
217             else
218             if (IsConfigFloatType (item->i_type))
219             {
220                 item->orig.f = item->saved.f =
221                 item->value.f = va_arg (ap, double);
222                 ret = 0;
223             }
224             else
225             if (IsConfigStringType (item->i_type))
226             {
227                 const char *value = va_arg (ap, const char *);
228                 item->value.psz = value ? strdup (value) : NULL;
229                 item->orig.psz = value ? strdup (value) : NULL;
230                 item->saved.psz = value ? strdup (value) : NULL;
231                 ret = 0;
232             }
233             break;
234         }
235
236         case VLC_CONFIG_RANGE:
237         {
238             if (IsConfigIntegerType (item->i_type))
239             {
240                 item->min.i = va_arg (ap, int);
241                 item->max.i = va_arg (ap, int);
242                 ret = 0;
243             }
244             else
245             if (IsConfigFloatType (item->i_type))
246             {
247                 item->min.f = va_arg (ap, double);
248                 item->max.f = va_arg (ap, double);
249                 ret = 0;
250             }
251             break;
252         }
253
254         case VLC_CONFIG_ADVANCED:
255             item->b_advanced = VLC_TRUE;
256             ret = 0;
257             break;
258
259         case VLC_CONFIG_VOLATILE:
260             item->b_unsaveable = VLC_TRUE;
261             ret = 0;
262             break;
263
264         case VLC_CONFIG_PERSISTENT:
265             item->b_autosave = VLC_TRUE;
266             ret = 0;
267             break;
268
269         case VLC_CONFIG_RESTART:
270             item->b_restart = VLC_TRUE;
271             ret = 0;
272             break;
273
274         case VLC_CONFIG_PRIVATE:
275             item->b_internal = VLC_TRUE;
276             ret = 0;
277             break;
278
279         case VLC_CONFIG_REMOVED:
280             item->b_removed = VLC_TRUE;
281             ret = 0;
282             break;
283
284         case VLC_CONFIG_CAPABILITY:
285         {
286             const char *cap = va_arg (ap, const char *);
287             item->psz_type = cap ? strdup (cap) : NULL;
288             ret = 0;
289             break;
290         }
291
292         case VLC_CONFIG_SHORTCUT:
293             item->i_short = va_arg (ap, int);
294             ret = 0;
295             break;
296
297         case VLC_CONFIG_LIST:
298         {
299             size_t len = va_arg (ap, size_t);
300             char **dtext = malloc (sizeof (char *) * (len + 1));
301
302             if (dtext == NULL)
303                 break;
304
305             /* Copy values */
306             if (IsConfigIntegerType (item->i_type))
307             {
308                 const int *src = va_arg (ap, const int *);
309                 int *dst = malloc (sizeof (int) * (len + 1));
310
311                 if (dst != NULL)
312                 {
313                     memcpy (dst, src, sizeof (int) * len);
314                     dst[len] = 0;
315                 }
316                 item->pi_list = dst;
317             }
318             else
319 #if 0
320             if (IsConfigFloatType (item->i_type))
321             {
322                 const float *src = va_arg (ap, const float *);
323                 float *dst = malloc (sizeof (float) * (len + 1));
324
325                 if (dst != NULL)
326                 {
327                     memcpy (dst, src, sizeof (float) * len);
328                     dst[len] = 0.;
329                 }
330                 item->pf_list = dst;
331             }
332             else
333 #endif
334             if (IsConfigStringType (item->i_type))
335             {
336                 const char *const *src = va_arg (ap, const char *const *);
337                 char **dst = malloc (sizeof (char *) * (len + 1));
338
339                 if (dst != NULL)
340                 {
341                     for (size_t i = 0; i < len; i++)
342                         dst[i] = src[i] ? strdup (src[i]) : NULL;
343                     dst[len] = NULL;
344                 }
345                 item->ppsz_list = dst;
346             }
347             else
348                 break;
349
350             /* Copy textual descriptions */
351             const char *const *text = va_arg (ap, const char *const *);
352             if (text != NULL)
353             {
354                 for (size_t i = 0; i < len; i++)
355                     dtext[i] = text[i] ? strdup ( _(text[i])) : NULL;
356
357                 dtext[len] = NULL;
358                 item->ppsz_list_text = dtext;
359             }
360             else
361             {
362                 free (dtext);
363                 item->ppsz_list_text = NULL;
364             }
365
366             item->i_list = len;
367             ret = 0;
368             break;
369         }
370
371         case VLC_CONFIG_ADD_ACTION:
372         {
373             vlc_callback_t cb = va_arg (ap, vlc_callback_t), *tabcb;
374             const char *name = va_arg (ap, const char *);
375             char **tabtext;
376
377             tabcb = realloc (item->ppf_action,
378                              (item->i_action + 2) * sizeof (cb));
379             if (tabcb == NULL)
380                 break;
381             item->ppf_action = tabcb;
382             tabcb[item->i_action] = cb;
383             tabcb[item->i_action + 1] = NULL;
384
385             tabtext = realloc (item->ppsz_action_text,
386                                (item->i_action + 2) * sizeof (name));
387             if (tabtext == NULL)
388                 break;
389             item->ppsz_action_text = tabtext;
390
391             if (name)
392                 tabtext[item->i_action] = strdup ( _(name));
393             else
394                 tabtext[item->i_action] = NULL;
395             tabtext[item->i_action + 1] = NULL;
396
397             item->i_action++;
398             ret = 0;
399             break;
400         }
401
402         case VLC_CONFIG_OLDNAME:
403         {
404             const char *oldname = va_arg (ap, const char *);
405             item->psz_oldname = oldname ? strdup (oldname) : NULL;
406             ret = 0;
407             break;
408         }
409
410         case VLC_CONFIG_UNSAFE:
411             item->b_unsafe = VLC_TRUE;
412             ret = 0;
413             break;
414     }
415
416     va_end (ap);
417     return ret;
418 }