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