]> git.sesse.net Git - vlc/blob - src/modules/entry.c
Support for using a custom text domain for configuration strings
[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 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_NODOMAIN:
112         {
113             const char *name = va_arg (ap, char *);
114             ret = vlc_module_set (module, VLC_MODULE_SHORTNAME, NULL, name);
115             break;
116         }
117
118         case VLC_MODULE_DESCRIPTION_NODOMAIN:
119         {
120             const char *desc = va_arg (ap, char *);
121             ret = vlc_module_set (module, VLC_MODULE_DESCRIPTION, NULL, desc);
122             break;
123         }
124
125         case VLC_MODULE_HELP_NODOMAIN:
126         {
127             const char *help = va_arg (ap, char *);
128             ret = vlc_module_set (module, VLC_MODULE_HELP, NULL, help);
129             break;
130         }
131
132         case VLC_MODULE_CAPABILITY:
133             module->psz_capability = va_arg (ap, char *);
134             break;
135
136         case VLC_MODULE_SCORE:
137             module->i_score = va_arg (ap, int);
138             break;
139
140         case VLC_MODULE_PROGRAM:
141             msg_Warn (module, "deprecated module property %d", propid);
142             break;
143
144         case VLC_MODULE_CB_OPEN:
145             module->pf_activate = va_arg (ap, int (*) (vlc_object_t *));
146             break;
147
148         case VLC_MODULE_CB_CLOSE:
149             module->pf_deactivate = va_arg (ap, void (*) (vlc_object_t *));
150             break;
151
152         case VLC_MODULE_NO_UNLOAD:
153             module->b_unloadable = false;
154             break;
155
156         case VLC_MODULE_NAME:
157         {
158             const char *value = va_arg (ap, const char *);
159             free( module->psz_object_name );
160             module->psz_object_name = strdup( value );
161             module->pp_shortcuts[0] = value;
162             if (module->psz_longname == default_name)
163                 module->psz_longname = value;
164             break;
165         }
166
167         case VLC_MODULE_SHORTNAME:
168         {
169             const char *domain = va_arg (ap, const char *);
170             if (domain == NULL)
171                 domain = PACKAGE;
172             module->psz_shortname = dgettext (domain, va_arg (ap, char *));
173             break;
174         }
175
176         case VLC_MODULE_DESCRIPTION:
177         {
178             const char *domain = va_arg (ap, const char *);
179             if (domain == NULL)
180                 domain = PACKAGE;
181             module->psz_longname = dgettext (domain, va_arg (ap, char *));
182             break;
183         }
184
185         case VLC_MODULE_HELP:
186         {
187             const char *domain = va_arg (ap, const char *);
188             if (domain == NULL)
189                 domain = PACKAGE;
190             module->psz_help = dgettext (domain, va_arg (ap, char *));
191             break;
192         }
193
194         default:
195             msg_Err (module, "unknown module property %d", propid);
196             msg_Err (module, "LibVLC might be too old to use this module.");
197             ret = VLC_EGENERIC;
198             break;
199     }
200     va_end (ap);
201     return ret;
202 }
203
204 module_config_t *vlc_config_create (module_t *module, int type)
205 {
206     unsigned confsize = module->confsize;
207     module_config_t *tab = module->p_config;
208
209     if ((confsize & 0xf) == 0)
210     {
211         tab = realloc (tab, (confsize + 17) * sizeof (*tab));
212         if (tab == NULL)
213             return NULL;
214
215         module->p_config = tab;
216     }
217
218     memset (tab + confsize, 0, sizeof (tab[confsize]));
219     tab[confsize].i_type = type;
220     tab[confsize].p_lock = &module->object_lock;
221
222     if (type & CONFIG_ITEM)
223     {
224         module->i_config_items++;
225         if (type == CONFIG_ITEM_BOOL)
226             module->i_bool_items++;
227     }
228
229     module->confsize++;
230     return tab + confsize;
231 }
232
233 int vlc_config_set (module_config_t *restrict item, int id, ...)
234 {
235     int ret = -1;
236     va_list ap;
237
238     assert (item != NULL);
239     va_start (ap, id);
240
241     switch (id)
242     {
243         case VLC_CONFIG_NAME:
244         {
245             const char *name = va_arg (ap, const char *);
246             vlc_callback_t cb = va_arg (ap, vlc_callback_t);
247
248             assert (name != NULL);
249             item->psz_name = strdup (name);
250             item->pf_callback = cb;
251             ret = 0;
252             break;
253         }
254
255         case VLC_CONFIG_DESC_NODOMAIN:
256         {
257             const char *text = va_arg (ap, const char *);
258             const char *longtext = va_arg (ap, const char *);
259             ret = vlc_config_set (item, VLC_CONFIG_DESC, NULL, text, longtext);
260             break;
261         }
262
263         case VLC_CONFIG_VALUE:
264         {
265             if (IsConfigIntegerType (item->i_type))
266             {
267                 item->orig.i = item->saved.i =
268                 item->value.i = va_arg (ap, int);
269                 ret = 0;
270             }
271             else
272             if (IsConfigFloatType (item->i_type))
273             {
274                 item->orig.f = item->saved.f =
275                 item->value.f = va_arg (ap, double);
276                 ret = 0;
277             }
278             else
279             if (IsConfigStringType (item->i_type))
280             {
281                 const char *value = va_arg (ap, const char *);
282                 item->value.psz = value ? strdup (value) : NULL;
283                 item->orig.psz = value ? strdup (value) : NULL;
284                 item->saved.psz = value ? strdup (value) : NULL;
285                 ret = 0;
286             }
287             break;
288         }
289
290         case VLC_CONFIG_RANGE:
291         {
292             if (IsConfigIntegerType (item->i_type))
293             {
294                 item->min.i = va_arg (ap, int);
295                 item->max.i = va_arg (ap, int);
296                 ret = 0;
297             }
298             else
299             if (IsConfigFloatType (item->i_type))
300             {
301                 item->min.f = va_arg (ap, double);
302                 item->max.f = va_arg (ap, double);
303                 ret = 0;
304             }
305             break;
306         }
307
308         case VLC_CONFIG_ADVANCED:
309             item->b_advanced = true;
310             ret = 0;
311             break;
312
313         case VLC_CONFIG_VOLATILE:
314             item->b_unsaveable = true;
315             ret = 0;
316             break;
317
318         case VLC_CONFIG_PERSISTENT:
319             item->b_autosave = true;
320             ret = 0;
321             break;
322
323         case VLC_CONFIG_RESTART:
324             item->b_restart = true;
325             ret = 0;
326             break;
327
328         case VLC_CONFIG_PRIVATE:
329             item->b_internal = true;
330             ret = 0;
331             break;
332
333         case VLC_CONFIG_REMOVED:
334             item->b_removed = true;
335             ret = 0;
336             break;
337
338         case VLC_CONFIG_CAPABILITY:
339         {
340             const char *cap = va_arg (ap, const char *);
341             item->psz_type = cap ? strdup (cap) : NULL;
342             ret = 0;
343             break;
344         }
345
346         case VLC_CONFIG_SHORTCUT:
347             item->i_short = va_arg (ap, int);
348             ret = 0;
349             break;
350
351         case VLC_CONFIG_LIST_NODOMAIN:
352         {
353             size_t len = va_arg (ap, size_t);
354             if (IsConfigIntegerType (item->i_type))
355             {
356                 const int *src = va_arg (ap, const int *);
357                 const char *const *text = va_arg (ap, const char *const *);
358                 ret = vlc_config_set (item, VLC_CONFIG_LIST, NULL, len, src,
359                                       text);
360             }
361             else
362             if (IsConfigStringType (item->i_type))
363             {
364                 const char *const *src = va_arg (ap, const char *const *);
365                 const char *const *text = va_arg (ap, const char *const *);
366                 ret = vlc_config_set (item, VLC_CONFIG_LIST, NULL, len, src,
367                                       text);
368             }
369             break;
370         }
371
372         case VLC_CONFIG_ADD_ACTION_NODOMAIN:
373         {
374             vlc_callback_t cb = va_arg (ap, vlc_callback_t);
375             const char *name = va_arg (ap, const char *);
376             ret = vlc_config_set (item, VLC_CONFIG_ADD_ACTION, NULL, cb, name);
377             break;
378         }
379
380         case VLC_CONFIG_OLDNAME:
381         {
382             const char *oldname = va_arg (ap, const char *);
383             item->psz_oldname = oldname ? strdup (oldname) : NULL;
384             ret = 0;
385             break;
386         }
387
388         case VLC_CONFIG_SAFE:
389             item->b_safe = true;
390             ret = 0;
391             break;
392
393         case VLC_CONFIG_DESC:
394         {
395             const char *domain = va_arg (ap, const char *);
396             const char *text = va_arg (ap, const char *);
397             const char *longtext = va_arg (ap, const char *);
398
399             if (domain == NULL)
400                 domain = PACKAGE;
401             item->psz_text = text ? strdup (dgettext (domain, text)) : NULL;
402             item->psz_longtext =
403                 longtext ? strdup (dgettext (domain, longtext)) : NULL;
404             ret = 0;
405             break;
406         }
407
408         case VLC_CONFIG_LIST:
409         {
410             const char *domain = va_arg (ap, const char *);
411             size_t len = va_arg (ap, size_t);
412             char **dtext = malloc (sizeof (char *) * (len + 1));
413
414             if (dtext == NULL)
415                 break;
416
417             /* Copy values */
418             if (IsConfigIntegerType (item->i_type))
419             {
420                 const int *src = va_arg (ap, const int *);
421                 int *dst = malloc (sizeof (int) * (len + 1));
422
423                 if (dst != NULL)
424                 {
425                     memcpy (dst, src, sizeof (int) * len);
426                     dst[len] = 0;
427                 }
428                 item->pi_list = dst;
429             }
430             else
431 #if 0
432             if (IsConfigFloatType (item->i_type))
433             {
434                 const float *src = va_arg (ap, const float *);
435                 float *dst = malloc (sizeof (float) * (len + 1));
436
437                 if (dst != NULL)
438                 {
439                     memcpy (dst, src, sizeof (float) * len);
440                     dst[len] = 0.;
441                 }
442                 item->pf_list = dst;
443             }
444             else
445 #endif
446             if (IsConfigStringType (item->i_type))
447             {
448                 const char *const *src = va_arg (ap, const char *const *);
449                 char **dst = malloc (sizeof (char *) * (len + 1));
450
451                 if (dst != NULL)
452                 {
453                     for (size_t i = 0; i < len; i++)
454                         dst[i] = src[i] ? strdup (src[i]) : NULL;
455                     dst[len] = NULL;
456                 }
457                 item->ppsz_list = dst;
458             }
459             else
460                 break;
461
462             /* Copy textual descriptions */
463             if (domain == NULL)
464                 domain = PACKAGE;
465
466             const char *const *text = va_arg (ap, const char *const *);
467             if (text != NULL)
468             {
469                 for (size_t i = 0; i < len; i++)
470                     dtext[i] =
471                         text[i] ? strdup (dgettext (domain, text[i])) : NULL;
472
473                 dtext[len] = NULL;
474                 item->ppsz_list_text = dtext;
475             }
476             else
477             {
478                 free (dtext);
479                 item->ppsz_list_text = NULL;
480             }
481
482             item->i_list = len;
483             item->pf_update_list = va_arg (ap, vlc_callback_t);
484             ret = 0;
485             break;
486         }
487
488         case VLC_CONFIG_ADD_ACTION:
489         {
490             const char *domain = va_arg (ap, const char *);
491             vlc_callback_t cb = va_arg (ap, vlc_callback_t), *tabcb;
492             const char *name = va_arg (ap, const char *);
493             char **tabtext;
494
495             tabcb = realloc (item->ppf_action,
496                              (item->i_action + 2) * sizeof (cb));
497             if (tabcb == NULL)
498                 break;
499             item->ppf_action = tabcb;
500             tabcb[item->i_action] = cb;
501             tabcb[item->i_action + 1] = NULL;
502
503             tabtext = realloc (item->ppsz_action_text,
504                                (item->i_action + 2) * sizeof (name));
505             if (tabtext == NULL)
506                 break;
507             item->ppsz_action_text = tabtext;
508
509             if (domain == NULL)
510                 domain = PACKAGE;
511             if (name)
512                 tabtext[item->i_action] = strdup (dgettext (domain, name));
513             else
514                 tabtext[item->i_action] = NULL;
515             tabtext[item->i_action + 1] = NULL;
516
517             item->i_action++;
518             ret = 0;
519             break;
520         }
521     }
522
523     va_end (ap);
524     return ret;
525 }