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