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