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