]> git.sesse.net Git - vlc/blob - src/modules/entry.c
Internally merge vlc_module_set() and vlc_config_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 module_config_t *vlc_config_create (module_t *module, int type)
129 {
130     unsigned confsize = module->confsize;
131     module_config_t *tab = module->p_config;
132
133     if ((confsize & 0xf) == 0)
134     {
135         tab = realloc (tab, (confsize + 17) * sizeof (*tab));
136         if (tab == NULL)
137             return NULL;
138
139         module->p_config = tab;
140     }
141
142     memset (tab + confsize, 0, sizeof (tab[confsize]));
143     tab[confsize].i_type = type;
144     tab[confsize].p_lock = &module->lock;
145
146     if (type & CONFIG_ITEM)
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_MODULE_CPU_REQUIREMENT:
167             assert (!module->b_submodule);
168             module->i_cpu |= va_arg (ap, int);
169             break;
170
171         case VLC_MODULE_SHORTCUT:
172         {
173             unsigned i;
174             for (i = 0; module->pp_shortcuts[i] != NULL; i++);
175                 if (i >= (MODULE_SHORTCUT_MAX - 1))
176                     break;
177
178             module->pp_shortcuts[i] = va_arg (ap, char *);
179             break;
180         }
181
182         case VLC_MODULE_CAPABILITY:
183             module->psz_capability = va_arg (ap, char *);
184             break;
185
186         case VLC_MODULE_SCORE:
187             module->i_score = va_arg (ap, int);
188             break;
189
190         case VLC_MODULE_CB_OPEN:
191             module->pf_activate = va_arg (ap, int (*) (vlc_object_t *));
192             break;
193
194         case VLC_MODULE_CB_CLOSE:
195             module->pf_deactivate = va_arg (ap, void (*) (vlc_object_t *));
196             break;
197
198         case VLC_MODULE_NO_UNLOAD:
199             module->b_unloadable = false;
200             break;
201
202         case VLC_MODULE_NAME:
203         {
204             const char *value = va_arg (ap, const char *);
205             free( module->psz_object_name );
206             module->psz_object_name = strdup( value );
207             module->pp_shortcuts[0] = (char*)value; /* dooh! */
208             if (module->psz_longname == default_name)
209                 module->psz_longname = (char*)value; /* dooh! */
210             break;
211         }
212
213         case VLC_MODULE_SHORTNAME:
214         {
215             const char *domain = va_arg (ap, const char *);
216             if (domain == NULL)
217                 domain = PACKAGE;
218             module->psz_shortname = dgettext (domain, va_arg (ap, char *));
219             break;
220         }
221
222         case VLC_MODULE_DESCRIPTION:
223         {
224             const char *domain = va_arg (ap, const char *);
225             if (domain == NULL)
226                 domain = PACKAGE;
227             module->psz_longname = dgettext (domain, va_arg (ap, char *));
228             break;
229         }
230
231         case VLC_MODULE_HELP:
232         {
233             const char *domain = va_arg (ap, const char *);
234             if (domain == NULL)
235                 domain = PACKAGE;
236             module->psz_help = dgettext (domain, va_arg (ap, char *));
237             break;
238         }
239
240         case VLC_CONFIG_NAME:
241         {
242             const char *name = va_arg (ap, const char *);
243             vlc_callback_t cb = va_arg (ap, vlc_callback_t);
244
245             assert (name != NULL);
246             item->psz_name = strdup (name);
247             item->pf_callback = cb;
248             break;
249         }
250
251         case VLC_CONFIG_VALUE:
252         {
253             if (IsConfigIntegerType (item->i_type))
254             {
255                 item->orig.i = item->saved.i =
256                 item->value.i = va_arg (ap, int);
257             }
258             else
259             if (IsConfigFloatType (item->i_type))
260             {
261                 item->orig.f = item->saved.f =
262                 item->value.f = va_arg (ap, double);
263             }
264             else
265             if (IsConfigStringType (item->i_type))
266             {
267                 const char *value = va_arg (ap, const char *);
268                 item->value.psz = value ? strdup (value) : NULL;
269                 item->orig.psz = value ? strdup (value) : NULL;
270                 item->saved.psz = value ? strdup (value) : NULL;
271             }
272             break;
273         }
274
275         case VLC_CONFIG_RANGE:
276         {
277             if (IsConfigIntegerType (item->i_type)
278              || item->i_type == CONFIG_ITEM_MODULE_LIST_CAT
279              || item->i_type == CONFIG_ITEM_MODULE_CAT)
280             {
281                 item->min.i = va_arg (ap, int);
282                 item->max.i = va_arg (ap, int);
283             }
284             else
285             if (IsConfigFloatType (item->i_type))
286             {
287                 item->min.f = va_arg (ap, double);
288                 item->max.f = va_arg (ap, double);
289             }
290             break;
291         }
292
293         case VLC_CONFIG_ADVANCED:
294             item->b_advanced = true;
295             break;
296
297         case VLC_CONFIG_VOLATILE:
298             item->b_unsaveable = true;
299             break;
300
301         case VLC_CONFIG_PERSISTENT:
302             item->b_autosave = true;
303             break;
304
305         case VLC_CONFIG_RESTART:
306             item->b_restart = true;
307             break;
308
309         case VLC_CONFIG_PRIVATE:
310             item->b_internal = true;
311             break;
312
313         case VLC_CONFIG_REMOVED:
314             item->b_removed = true;
315             break;
316
317         case VLC_CONFIG_CAPABILITY:
318         {
319             const char *cap = va_arg (ap, const char *);
320             item->psz_type = cap ? strdup (cap) : NULL;
321             break;
322         }
323
324         case VLC_CONFIG_SHORTCUT:
325             item->i_short = va_arg (ap, int);
326             break;
327
328         case VLC_CONFIG_OLDNAME:
329         {
330             const char *oldname = va_arg (ap, const char *);
331             item->psz_oldname = oldname ? strdup (oldname) : NULL;
332             break;
333         }
334
335         case VLC_CONFIG_SAFE:
336             item->b_safe = true;
337             break;
338
339         case VLC_CONFIG_DESC:
340         {
341             const char *domain = va_arg (ap, const char *);
342             const char *text = va_arg (ap, const char *);
343             const char *longtext = va_arg (ap, const char *);
344
345             if (domain == NULL)
346                 domain = PACKAGE;
347             item->psz_text = text ? strdup (dgettext (domain, text)) : NULL;
348             item->psz_longtext =
349                 longtext ? strdup (dgettext (domain, longtext)) : NULL;
350             break;
351         }
352
353         case VLC_CONFIG_LIST:
354         {
355             const char *domain = va_arg (ap, const char *);
356             size_t len = va_arg (ap, size_t);
357
358             /* Copy values */
359             if (IsConfigIntegerType (item->i_type))
360             {
361                 const int *src = va_arg (ap, const int *);
362                 int *dst = malloc (sizeof (int) * (len + 1));
363
364                 if (dst != NULL)
365                 {
366                     memcpy (dst, src, sizeof (int) * len);
367                     dst[len] = 0;
368                 }
369                 item->pi_list = dst;
370             }
371             else
372 #if 0
373             if (IsConfigFloatType (item->i_type))
374             {
375                 const float *src = va_arg (ap, const float *);
376                 float *dst = malloc (sizeof (float) * (len + 1));
377
378                 if (dst != NULL)
379                 {
380                     memcpy (dst, src, sizeof (float) * len);
381                     dst[len] = 0.;
382                 }
383                 item->pf_list = dst;
384             }
385             else
386 #endif
387             if (IsConfigStringType (item->i_type))
388             {
389                 const char *const *src = va_arg (ap, const char *const *);
390                 char **dst = malloc (sizeof (char *) * (len + 1));
391
392                 if (dst != NULL)
393                 {
394                     for (size_t i = 0; i < len; i++)
395                         dst[i] = src[i] ? strdup (src[i]) : NULL;
396                     dst[len] = NULL;
397                 }
398                 item->ppsz_list = dst;
399             }
400             else
401                 break;
402
403             /* Copy textual descriptions */
404             if (domain == NULL)
405                 domain = PACKAGE;
406
407             const char *const *text = va_arg (ap, const char *const *);
408             if (text != NULL)
409             {
410                 char **dtext = malloc (sizeof (char *) * (len + 1));
411                 if( dtext != NULL )
412                 {
413                     for (size_t i = 0; i < len; i++)
414                         dtext[i] = text[i] ?
415                                         strdup( dgettext( domain, text[i] ) ) :
416                                         NULL;
417                     dtext[len] = NULL;
418                 }
419                 item->ppsz_list_text = dtext;
420             }
421             else
422                 item->ppsz_list_text = NULL;
423
424             item->i_list = len;
425             item->pf_update_list = va_arg (ap, vlc_callback_t);
426             break;
427         }
428
429         case VLC_CONFIG_ADD_ACTION:
430         {
431             const char *domain = va_arg (ap, const char *);
432             vlc_callback_t cb = va_arg (ap, vlc_callback_t), *tabcb;
433             const char *name = va_arg (ap, const char *);
434             char **tabtext;
435
436             tabcb = realloc (item->ppf_action,
437                              (item->i_action + 2) * sizeof (cb));
438             if (tabcb == NULL)
439                 break;
440             item->ppf_action = tabcb;
441             tabcb[item->i_action] = cb;
442             tabcb[item->i_action + 1] = NULL;
443
444             tabtext = realloc (item->ppsz_action_text,
445                                (item->i_action + 2) * sizeof (name));
446             if (tabtext == NULL)
447                 break;
448             item->ppsz_action_text = tabtext;
449
450             if (domain == NULL)
451                 domain = PACKAGE;
452             if (name)
453                 tabtext[item->i_action] = strdup (dgettext (domain, name));
454             else
455                 tabtext[item->i_action] = NULL;
456             tabtext[item->i_action + 1] = NULL;
457
458             item->i_action++;
459             break;
460         }
461
462         default:
463             fprintf (stderr, "LibVLC: unknown module property %d", propid);
464             fprintf (stderr, "LibVLC: too old to use this module?");
465             ret = -1;
466             break;
467     }
468
469     va_end (ap);
470     return ret;
471 }