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