]> git.sesse.net Git - vlc/blob - src/modules/entry.c
Revert "deinterlace: add basic support for YUY2 and NV12 (fixes #2206)"
[vlc] / src / modules / entry.c
1 /*****************************************************************************
2  * entry.c : Callbacks for module entry point
3  *****************************************************************************
4  * Copyright (C) 2007 VLC authors and VideoLAN
5  * Copyright © 2007-2008 Rémi Denis-Courmont
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * 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 (module_t *parent)
43 {
44     module_t *module = malloc (sizeof (*module));
45     if (module == NULL)
46         return NULL;
47
48     /* TODO: replace module/submodules with plugin/modules */
49     if (parent == NULL)
50     {
51         module->next = NULL;
52         module->parent = NULL;
53     }
54     else
55     {
56         module->next = parent->submodule;
57         parent->submodule = module;
58         parent->submodule_count++;
59         module->parent = parent;
60     }
61
62     module->submodule = NULL;
63     module->submodule_count = 0;
64
65     module->psz_shortname = NULL;
66     module->psz_longname = NULL;
67     module->psz_help = NULL;
68     module->pp_shortcuts = NULL;
69     module->i_shortcuts = 0;
70     module->psz_capability = NULL;
71     module->i_score = (parent != NULL) ? parent->i_score : 1;
72     module->b_loaded = false;
73     module->b_unloadable = parent == NULL;
74     module->pf_activate = NULL;
75     module->pf_deactivate = NULL;
76     module->p_config = NULL;
77     module->confsize = 0;
78     module->i_config_items = 0;
79     module->i_bool_items = 0;
80     /*module->handle = garbage */
81     module->psz_filename = NULL;
82     module->domain = NULL;
83     return module;
84 }
85
86 /**
87  * Destroys a plug-in.
88  * @warning If the plug-in is loaded in memory, the handle will be leaked.
89  */
90 void vlc_module_destroy (module_t *module)
91 {
92     assert (!module->b_loaded || !module->b_unloadable);
93
94     for (module_t *m = module->submodule, *next; m != NULL; m = next)
95     {
96         next = m->next;
97         vlc_module_destroy (m);
98     }
99
100     config_Free (module->p_config, module->confsize);
101
102     free (module->domain);
103     free (module->psz_filename);
104     for (unsigned i = 0; i < module->i_shortcuts; i++)
105         free (module->pp_shortcuts[i]);
106     free (module->pp_shortcuts);
107     free (module->psz_capability);
108     free (module->psz_help);
109     free (module->psz_longname);
110     free (module->psz_shortname);
111     free (module);
112 }
113
114 static module_config_t *vlc_config_create (module_t *module, int type)
115 {
116     unsigned confsize = module->confsize;
117     module_config_t *tab = module->p_config;
118
119     if ((confsize & 0xf) == 0)
120     {
121         tab = realloc_or_free (tab, (confsize + 17) * sizeof (*tab));
122         if (tab == NULL)
123             return NULL;
124
125         module->p_config = tab;
126     }
127
128     memset (tab + confsize, 0, sizeof (tab[confsize]));
129     if (IsConfigIntegerType (type))
130     {
131         tab[confsize].max.i = INT_MAX;
132         tab[confsize].min.i = INT_MIN;
133     }
134     tab[confsize].i_type = type;
135
136     if (CONFIG_ITEM(type))
137     {
138         module->i_config_items++;
139         if (type == CONFIG_ITEM_BOOL)
140             module->i_bool_items++;
141     }
142
143     module->confsize++;
144     return tab + confsize;
145 }
146
147
148 /**
149  * Callback for the plugin descriptor functions.
150  */
151 static int vlc_plugin_setter (void *plugin, void *tgt, int propid, ...)
152 {
153     module_t **pprimary = plugin;
154     module_t *module = tgt;
155     module_config_t *item = tgt;
156     va_list ap;
157     int ret = 0;
158
159     va_start (ap, propid);
160     switch (propid)
161     {
162         case VLC_MODULE_CREATE:
163         {
164             module = *pprimary;
165             module_t *submodule = vlc_module_create (module);
166             if (unlikely(submodule == NULL))
167             {
168                 ret = -1;
169                 break;
170             }
171
172             *(va_arg (ap, module_t **)) = submodule;
173             if (*pprimary == NULL)
174             {
175                 *pprimary = submodule;
176                 break;
177             }
178             /* Inheritance. Ugly!! */
179             submodule->pp_shortcuts = xmalloc (sizeof ( *submodule->pp_shortcuts ));
180             submodule->pp_shortcuts[0] = strdup_null (module->pp_shortcuts[0]);
181             submodule->i_shortcuts = 1; /* object name */
182
183             submodule->psz_shortname = strdup_null (module->psz_shortname);
184             submodule->psz_longname = strdup_null (module->psz_longname);
185             submodule->psz_capability = strdup_null (module->psz_capability);
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
194             item = vlc_config_create (*pprimary, type);
195             if (unlikely(item == NULL))
196             {
197                 ret = -1;
198                 break;
199             }
200             *pp = item;
201             break;
202         }
203
204         case VLC_MODULE_SHORTCUT:
205         {
206             unsigned i_shortcuts = va_arg (ap, unsigned);
207             unsigned index = module->i_shortcuts;
208             /* The cache loader accept only a small number of shortcuts */
209             assert(i_shortcuts + index <= MODULE_SHORTCUT_MAX);
210
211             const char *const *tab = va_arg (ap, const char *const *);
212             char **pp = realloc (module->pp_shortcuts,
213                                  sizeof (pp[0]) * (index + i_shortcuts));
214             if (unlikely(pp == NULL))
215             {
216                 ret = -1;
217                 break;
218             }
219             module->pp_shortcuts = pp;
220             module->i_shortcuts = index + i_shortcuts;
221             pp += index;
222             for (unsigned i = 0; i < i_shortcuts; i++)
223                 pp[i] = strdup (tab[i]);
224             break;
225         }
226
227         case VLC_MODULE_CAPABILITY:
228             free (module->psz_capability);
229             module->psz_capability = strdup (va_arg (ap, char *));
230             break;
231
232         case VLC_MODULE_SCORE:
233             module->i_score = va_arg (ap, int);
234             break;
235
236         case VLC_MODULE_CB_OPEN:
237             module->pf_activate = va_arg (ap, void *);
238             break;
239
240         case VLC_MODULE_CB_CLOSE:
241             module->pf_deactivate = va_arg (ap, void *);
242             break;
243
244         case VLC_MODULE_NO_UNLOAD:
245             assert (module->parent == NULL);
246             module->b_unloadable = false;
247             break;
248
249         case VLC_MODULE_NAME:
250         {
251             const char *value = va_arg (ap, const char *);
252
253             assert (module->i_shortcuts == 0);
254             module->pp_shortcuts = malloc( sizeof( *module->pp_shortcuts ) );
255             module->pp_shortcuts[0] = strdup (value);
256             module->i_shortcuts = 1;
257
258             assert (module->psz_longname == NULL);
259             module->psz_longname = strdup (value);
260             break;
261         }
262
263         case VLC_MODULE_SHORTNAME:
264             assert (module->psz_shortname == NULL || module->parent != NULL);
265             free (module->psz_shortname);
266             module->psz_shortname = strdup (va_arg (ap, char *));
267             break;
268
269         case VLC_MODULE_DESCRIPTION:
270             // TODO: do not set this in VLC_MODULE_NAME
271             free (module->psz_longname);
272             module->psz_longname = strdup (va_arg (ap, char *));
273             break;
274
275         case VLC_MODULE_HELP:
276             assert (module->parent == NULL);
277             assert (module->psz_help == NULL);
278             module->psz_help = strdup (va_arg (ap, char *));
279             break;
280
281         case VLC_MODULE_TEXTDOMAIN:
282             assert (module->parent == NULL);
283             assert (module->domain == NULL);
284             module->domain = strdup (va_arg (ap, char *));
285             break;
286
287         case VLC_CONFIG_NAME:
288         {
289             const char *name = va_arg (ap, const char *);
290
291             assert (name != NULL);
292             item->psz_name = strdup (name);
293             break;
294         }
295
296         case VLC_CONFIG_VALUE:
297         {
298             if (IsConfigIntegerType (item->i_type)
299              || !CONFIG_ITEM(item->i_type))
300             {
301                 item->orig.i =
302                 item->value.i = va_arg (ap, int64_t);
303             }
304             else
305             if (IsConfigFloatType (item->i_type))
306             {
307                 item->orig.f =
308                 item->value.f = va_arg (ap, double);
309             }
310             else
311             if (IsConfigStringType (item->i_type))
312             {
313                 const char *value = va_arg (ap, const char *);
314                 item->value.psz = value ? strdup (value) : NULL;
315                 item->orig.psz = value ? strdup (value) : NULL;
316             }
317             break;
318         }
319
320         case VLC_CONFIG_RANGE:
321         {
322             if (IsConfigFloatType (item->i_type))
323             {
324                 item->min.f = va_arg (ap, double);
325                 item->max.f = va_arg (ap, double);
326             }
327             else
328             {
329                 item->min.i = va_arg (ap, int64_t);
330                 item->max.i = va_arg (ap, int64_t);
331             }
332             break;
333         }
334
335         case VLC_CONFIG_ADVANCED:
336             item->b_advanced = true;
337             break;
338
339         case VLC_CONFIG_VOLATILE:
340             item->b_unsaveable = true;
341             break;
342
343         case VLC_CONFIG_PRIVATE:
344             item->b_internal = true;
345             break;
346
347         case VLC_CONFIG_REMOVED:
348             item->b_removed = true;
349             break;
350
351         case VLC_CONFIG_CAPABILITY:
352         {
353             const char *cap = va_arg (ap, const char *);
354             item->psz_type = cap ? strdup (cap) : NULL;
355             break;
356         }
357
358         case VLC_CONFIG_SHORTCUT:
359             item->i_short = va_arg (ap, int);
360             break;
361
362         case VLC_CONFIG_SAFE:
363             item->b_safe = true;
364             break;
365
366         case VLC_CONFIG_DESC:
367         {
368             const char *text = va_arg (ap, const char *);
369             const char *longtext = va_arg (ap, const char *);
370
371             item->psz_text = text ? strdup (text) : NULL;
372             item->psz_longtext = longtext ? strdup (longtext) : NULL;
373             break;
374         }
375
376         case VLC_CONFIG_LIST:
377         {
378             size_t len = va_arg (ap, size_t);
379
380             assert (item->list_count == 0); /* cannot replace choices */
381             assert (item->list.psz_cb == NULL);
382             if (len == 0)
383                 break; /* nothing to do */
384             /* Copy values */
385             if (IsConfigIntegerType (item->i_type))
386             {
387                 const int *src = va_arg (ap, const int *);
388                 int *dst = xmalloc (sizeof (int) * len);
389
390                 memcpy (dst, src, sizeof (int) * len);
391                 item->list.i = dst;
392             }
393             else
394             if (IsConfigStringType (item->i_type))
395             {
396                 const char *const *src = va_arg (ap, const char *const *);
397                 char **dst = xmalloc (sizeof (char *) * len);
398
399                 for (size_t i = 0; i < len; i++)
400                      dst[i] = src[i] ? strdup (src[i]) : NULL;
401                 item->list.psz = dst;
402             }
403             else
404                 break;
405
406             /* Copy textual descriptions */
407             const char *const *text = va_arg (ap, const char *const *);
408             char **dtext = xmalloc (sizeof (char *) * (len + 1));
409             for (size_t i = 0; i < len; i++)
410                 dtext[i] = text[i] ? strdup (text[i]) : NULL;
411             item->list_text = dtext;
412             item->list_count = len;
413             break;
414         }
415
416         case VLC_CONFIG_LIST_CB:
417             if (IsConfigIntegerType (item->i_type))
418                item->list.i_cb = va_arg (ap, vlc_integer_list_cb);
419             else
420             if (IsConfigStringType (item->i_type))
421                item->list.psz_cb = va_arg (ap, vlc_string_list_cb);
422             else
423                 break;
424             break;
425
426         default:
427             fprintf (stderr, "LibVLC: unknown module property %d\n", propid);
428             fprintf (stderr, "LibVLC: too old to use this module?\n");
429             ret = -1;
430             break;
431     }
432
433     va_end (ap);
434     return ret;
435 }
436
437 /**
438  * Runs a plug-in descriptor. This loads the plug-in meta-data in memory.
439  */
440 module_t *vlc_plugin_describe (vlc_plugin_cb entry)
441 {
442     module_t *module = NULL;
443
444     if (entry (vlc_plugin_setter, &module) != 0)
445     {
446         if (module != NULL) /* partially initialized plug-in... */
447             vlc_module_destroy (module);
448         module = NULL;
449     }
450     return module;
451 }