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