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