]> git.sesse.net Git - vlc/blob - src/modules/entry.c
Do not save unloadable flag for submodule
[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 unused */
126     submodule->domain = NULL;
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             assert (module->parent == NULL);
230             module->b_unloadable = false;
231             break;
232
233         case VLC_MODULE_NAME:
234         {
235             const char *value = va_arg (ap, const char *);
236
237             assert (module->i_shortcuts == 0);
238             module->pp_shortcuts = malloc( sizeof( char ** ) );
239             module->pp_shortcuts[0] = (char*)value; /* dooh! */
240             module->i_shortcuts = 1;
241
242             if (module->psz_longname == NULL)
243                 module->psz_longname = (char*)value; /* dooh! */
244             break;
245         }
246
247         case VLC_MODULE_SHORTNAME:
248             module->psz_shortname = va_arg (ap, char *);
249             break;
250
251         case VLC_MODULE_DESCRIPTION:
252             module->psz_longname = va_arg (ap, char *);
253             break;
254
255         case VLC_MODULE_HELP:
256             assert (module->parent == NULL);
257             assert (module->psz_help == NULL);
258             module->psz_help = va_arg (ap, char *);
259             break;
260
261         case VLC_MODULE_TEXTDOMAIN:
262             module->domain = va_arg (ap, char *);
263             break;
264
265         case VLC_CONFIG_NAME:
266         {
267             const char *name = va_arg (ap, const char *);
268
269             assert (name != NULL);
270             item->psz_name = strdup (name);
271             break;
272         }
273
274         case VLC_CONFIG_VALUE:
275         {
276             if (IsConfigIntegerType (item->i_type)
277              || !CONFIG_ITEM(item->i_type))
278             {
279                 item->orig.i =
280                 item->value.i = va_arg (ap, int64_t);
281             }
282             else
283             if (IsConfigFloatType (item->i_type))
284             {
285                 item->orig.f =
286                 item->value.f = va_arg (ap, double);
287             }
288             else
289             if (IsConfigStringType (item->i_type))
290             {
291                 const char *value = va_arg (ap, const char *);
292                 item->value.psz = value ? strdup (value) : NULL;
293                 item->orig.psz = value ? strdup (value) : NULL;
294             }
295             break;
296         }
297
298         case VLC_CONFIG_RANGE:
299         {
300             if (IsConfigIntegerType (item->i_type)
301              || !CONFIG_ITEM(item->i_type))
302             {
303                 item->min.i = va_arg (ap, int64_t);
304                 item->max.i = va_arg (ap, int64_t);
305             }
306             else
307             if (IsConfigFloatType (item->i_type))
308             {
309                 item->min.f = va_arg (ap, double);
310                 item->max.f = va_arg (ap, double);
311             }
312             break;
313         }
314
315         case VLC_CONFIG_ADVANCED:
316             item->b_advanced = true;
317             break;
318
319         case VLC_CONFIG_VOLATILE:
320             item->b_unsaveable = true;
321             break;
322
323         case VLC_CONFIG_PRIVATE:
324             item->b_internal = true;
325             break;
326
327         case VLC_CONFIG_REMOVED:
328             item->b_removed = true;
329             break;
330
331         case VLC_CONFIG_CAPABILITY:
332         {
333             const char *cap = va_arg (ap, const char *);
334             item->psz_type = cap ? strdup (cap) : NULL;
335             break;
336         }
337
338         case VLC_CONFIG_SHORTCUT:
339             item->i_short = va_arg (ap, int);
340             break;
341
342         case VLC_CONFIG_OLDNAME:
343         {
344             const char *oldname = va_arg (ap, const char *);
345             assert (item->psz_oldname == NULL);
346             item->psz_oldname = oldname ? strdup (oldname) : NULL;
347             break;
348         }
349
350         case VLC_CONFIG_SAFE:
351             item->b_safe = true;
352             break;
353
354         case VLC_CONFIG_DESC:
355         {
356             const char *text = va_arg (ap, const char *);
357             const char *longtext = va_arg (ap, const char *);
358
359             item->psz_text = text ? strdup (text) : NULL;
360             item->psz_longtext = longtext ? strdup (longtext) : NULL;
361             break;
362         }
363
364         case VLC_CONFIG_LIST:
365         {
366             size_t len = va_arg (ap, size_t);
367
368             /* Copy values */
369             if (IsConfigIntegerType (item->i_type))
370             {
371                 const int *src = va_arg (ap, const int *);
372                 int *dst = malloc (sizeof (int) * (len + 1));
373
374                 if (dst != NULL)
375                 {
376                     memcpy (dst, src, sizeof (int) * len);
377                     dst[len] = 0;
378                 }
379                 item->pi_list = dst;
380             }
381             else
382             if (IsConfigStringType (item->i_type))
383             {
384                 const char *const *src = va_arg (ap, const char *const *);
385                 char **dst = malloc (sizeof (char *) * (len + 1));
386
387                 if (dst != NULL)
388                 {
389                     for (size_t i = 0; i < len; i++)
390                         dst[i] = src[i] ? strdup (src[i]) : NULL;
391                     dst[len] = NULL;
392                 }
393                 item->ppsz_list = dst;
394             }
395             else
396                 break;
397
398             /* Copy textual descriptions */
399             const char *const *text = va_arg (ap, const char *const *);
400             if (text != NULL)
401             {
402                 char **dtext = malloc (sizeof (char *) * (len + 1));
403                 if( dtext != NULL )
404                 {
405                     for (size_t i = 0; i < len; i++)
406                         dtext[i] = text[i] ? strdup (text[i]) : NULL;
407                     dtext[len] = NULL;
408                 }
409                 item->ppsz_list_text = dtext;
410             }
411             else
412                 item->ppsz_list_text = NULL;
413
414             item->i_list = len;
415             item->pf_update_list = va_arg (ap, vlc_callback_t);
416             break;
417         }
418
419         case VLC_CONFIG_ADD_ACTION:
420         {
421             vlc_callback_t cb = va_arg (ap, vlc_callback_t), *tabcb;
422             const char *name = va_arg (ap, const char *);
423             char **tabtext;
424
425             tabcb = realloc (item->ppf_action,
426                              (item->i_action + 2) * sizeof (cb));
427             if (tabcb == NULL)
428                 break;
429             item->ppf_action = tabcb;
430             tabcb[item->i_action] = cb;
431             tabcb[item->i_action + 1] = NULL;
432
433             tabtext = realloc (item->ppsz_action_text,
434                                (item->i_action + 2) * sizeof (name));
435             if (tabtext == NULL)
436                 break;
437             item->ppsz_action_text = tabtext;
438
439             if (name)
440                 tabtext[item->i_action] = strdup (name);
441             else
442                 tabtext[item->i_action] = NULL;
443             tabtext[item->i_action + 1] = NULL;
444
445             item->i_action++;
446             break;
447         }
448
449         default:
450             fprintf (stderr, "LibVLC: unknown module property %d\n", propid);
451             fprintf (stderr, "LibVLC: too old to use this module?\n");
452             ret = -1;
453             break;
454     }
455
456     va_end (ap);
457     return ret;
458 }