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