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