entry.c 14.1 KB
Newer Older
1
2
3
/*****************************************************************************
 * entry.c : Callbacks for module entry point
 *****************************************************************************
4
5
 * Copyright (C) 2007 the VideoLAN team
 * Copyright © 2007-2008 Rémi Denis-Courmont
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

22
23
24
25
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

26
#include <vlc_common.h>
27
#include <vlc_plugin.h>
28
#include <assert.h>
29
#include <stdarg.h>
30

31
32
33
34
#ifdef ENABLE_NLS
# include <libintl.h>
#endif

35
#include "modules/modules.h"
36
#include "config/configuration.h"
37
#include "libvlc.h"
38
39
40
41
42
43
44

static const char *mdgettext (const char *domain, const char *msg)
{
    assert (msg);
#ifdef ENABLE_NLS
    if (*msg) /* Do not translate ""! */
        return dgettext (domain, msg);
45
46
#else
    VLC_UNUSED(domain);
47
#endif
48
49
    return msg;
}
50

51
52
53
54
55
static void vlc_module_destruct (gc_object_t *obj)
{
    module_t *module = vlc_priv (obj, module_t);

    vlc_mutex_destroy (&module->lock);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
56
    free (module->psz_object_name);
57
58
59
    free (module);
}

60
61
62
63
static const char default_name[] = "unnamed";

module_t *vlc_module_create (vlc_object_t *obj)
{
64
    module_t *module = malloc (sizeof (*module));
65
66
67
    if (module == NULL)
        return NULL;

68
    module->psz_object_name = strdup( default_name );
69
70
71
72
73
74
75
76
    module->next = NULL;
    module->submodule = NULL;
    module->parent = NULL;
    module->submodule_count = 0;
    vlc_gc_init (module, vlc_module_destruct);
    vlc_mutex_init (&module->lock);

    module->psz_shortname = NULL;
77
    module->psz_longname = (char*)default_name;
78
79
80
    module->psz_help = NULL;
    for (unsigned i = 0; i < MODULE_SHORTCUT_MAX; i++)
        module->pp_shortcuts[i] = NULL;
Rafaël Carré's avatar
Rafaël Carré committed
81
    module->psz_capability = (char*)"";
82
    module->i_score = 1;
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
    module->i_cpu = 0;
    module->b_unloadable = true;
    module->b_reentrant = true;
    module->b_submodule = false;
    module->pf_activate = NULL;
    module->pf_deactivate = NULL;
    module->p_config = NULL;
    module->confsize = 0;
    module->i_config_items = 0;
    module->i_bool_items = 0;
    /*module->handle = garbage */
    module->psz_filename = NULL;
    module->b_builtin = false;
    module->b_loaded = false;

    (void)obj;
99
100
101
    return module;
}

102

103
104
105
static void vlc_submodule_destruct (gc_object_t *obj)
{
    module_t *module = vlc_priv (obj, module_t);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
106
    free (module->psz_object_name);
107
108
109
    free (module);
}

110
111
112
113
module_t *vlc_submodule_create (module_t *module)
{
    assert (module != NULL);

ivoire's avatar
ivoire committed
114
115
    module_t *submodule = calloc( 1, sizeof(*submodule) );
    if( !submodule )
116
117
        return NULL;

118
119
120
121
122
123
    vlc_gc_init (submodule, vlc_submodule_destruct);

    submodule->next = module->submodule;
    submodule->parent = module;
    module->submodule = submodule;
    module->submodule_count++;
124
125

    /* Muahahaha! Heritage! Polymorphism! Ugliness!! */
126
127
128
    submodule->pp_shortcuts[0] = module->pp_shortcuts[0]; /* object name */
    for (unsigned i = 1; i < MODULE_SHORTCUT_MAX; i++)
        submodule->pp_shortcuts[i] = NULL;
129

130
    submodule->psz_object_name = strdup( module->psz_object_name );
131
132
133
134
135
    submodule->psz_shortname = module->psz_shortname;
    submodule->psz_longname = module->psz_longname;
    submodule->psz_capability = module->psz_capability;
    submodule->i_score = module->i_score;
    submodule->i_cpu = module->i_cpu;
136
    submodule->b_submodule = true;
137
138
139
    return submodule;
}

140
static module_config_t *vlc_config_create (module_t *module, int type)
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
{
    unsigned confsize = module->confsize;
    module_config_t *tab = module->p_config;

    if ((confsize & 0xf) == 0)
    {
        tab = realloc (tab, (confsize + 17) * sizeof (*tab));
        if (tab == NULL)
            return NULL;

        module->p_config = tab;
    }

    memset (tab + confsize, 0, sizeof (tab[confsize]));
    tab[confsize].i_type = type;
    tab[confsize].p_lock = &module->lock;
157

158
159
160
161
162
163
164
165
166
167
168
169
170
    if (type & CONFIG_ITEM)
    {
        module->i_config_items++;
        if (type == CONFIG_ITEM_BOOL)
            module->i_bool_items++;
    }

    module->confsize++;
    return tab + confsize;
}


int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
171
{
172
173
    va_list ap;
    int ret = 0;
174

175
    va_start (ap, propid);
176
177
    switch (propid)
    {
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
        case VLC_SUBMODULE_CREATE:
        {
            module_t **pp = va_arg (ap, module_t **);
            *pp = vlc_submodule_create (module);
            if (*pp == NULL)
                ret = -1;
            break;
        }

        case VLC_CONFIG_CREATE:
        {
            int type = va_arg (ap, int);
            module_config_t **pp = va_arg (ap, module_config_t **);
            *pp = vlc_config_create (module, type);
            if (*pp == NULL)
                ret = -1;
            break;
        }

197
198
        case VLC_MODULE_CPU_REQUIREMENT:
            assert (!module->b_submodule);
199
            module->i_cpu |= va_arg (ap, int);
200
201
202
203
204
205
            break;

        case VLC_MODULE_SHORTCUT:
        {
            unsigned i;
            for (i = 0; module->pp_shortcuts[i] != NULL; i++);
206
207
                if (i >= (MODULE_SHORTCUT_MAX - 1))
                    break;
208

209
            module->pp_shortcuts[i] = va_arg (ap, char *);
210
211
212
213
            break;
        }

        case VLC_MODULE_CAPABILITY:
214
            module->psz_capability = va_arg (ap, char *);
215
216
217
            break;

        case VLC_MODULE_SCORE:
218
            module->i_score = va_arg (ap, int);
219
220
221
            break;

        case VLC_MODULE_CB_OPEN:
222
            module->pf_activate = va_arg (ap, int (*) (vlc_object_t *));
223
224
225
            break;

        case VLC_MODULE_CB_CLOSE:
226
            module->pf_deactivate = va_arg (ap, void (*) (vlc_object_t *));
227
228
            break;

229
230
        case VLC_MODULE_NO_UNLOAD:
            module->b_unloadable = false;
231
232
            break;

233
        case VLC_MODULE_NAME:
234
235
        {
            const char *value = va_arg (ap, const char *);
236
            free( module->psz_object_name );
237
            module->psz_object_name = strdup( value );
238
            module->pp_shortcuts[0] = (char*)value; /* dooh! */
239
            if (module->psz_longname == default_name)
240
                module->psz_longname = (char*)value; /* dooh! */
241
            break;
242
        }
243

244
245
246
247
248
        case VLC_MODULE_SHORTNAME:
        {
            const char *domain = va_arg (ap, const char *);
            if (domain == NULL)
                domain = PACKAGE;
249
            module->psz_shortname = mdgettext (domain, va_arg (ap, char *));
250
251
252
253
254
255
256
257
            break;
        }

        case VLC_MODULE_DESCRIPTION:
        {
            const char *domain = va_arg (ap, const char *);
            if (domain == NULL)
                domain = PACKAGE;
258
            module->psz_longname = mdgettext (domain, va_arg (ap, char *));
259
            break;
260
261
262
263
264
265
266
        }

        case VLC_MODULE_HELP:
        {
            const char *domain = va_arg (ap, const char *);
            if (domain == NULL)
                domain = PACKAGE;
267
            module->psz_help = mdgettext (domain, va_arg (ap, char *));
268
269
            break;
        }
270

271
272
273
274
275
276
277
278
279
280
281
282
        case VLC_CONFIG_NAME:
        {
            const char *name = va_arg (ap, const char *);
            vlc_callback_t cb = va_arg (ap, vlc_callback_t);

            assert (name != NULL);
            item->psz_name = strdup (name);
            item->pf_callback = cb;
            break;
        }

        case VLC_CONFIG_VALUE:
283
284
285
        {
            if (IsConfigIntegerType (item->i_type))
            {
286
                item->orig.i = item->saved.i =
287
288
289
290
291
                item->value.i = va_arg (ap, int);
            }
            else
            if (IsConfigFloatType (item->i_type))
            {
292
                item->orig.f = item->saved.f =
293
294
295
296
297
298
299
                item->value.f = va_arg (ap, double);
            }
            else
            if (IsConfigStringType (item->i_type))
            {
                const char *value = va_arg (ap, const char *);
                item->value.psz = value ? strdup (value) : NULL;
300
301
                item->orig.psz = value ? strdup (value) : NULL;
                item->saved.psz = value ? strdup (value) : NULL;
302
303
304
305
            }
            break;
        }

306
        case VLC_CONFIG_RANGE:
307
        {
308
309
310
            if (IsConfigIntegerType (item->i_type)
             || item->i_type == CONFIG_ITEM_MODULE_LIST_CAT
             || item->i_type == CONFIG_ITEM_MODULE_CAT)
311
312
313
314
315
316
317
318
319
320
321
322
323
            {
                item->min.i = va_arg (ap, int);
                item->max.i = va_arg (ap, int);
            }
            else
            if (IsConfigFloatType (item->i_type))
            {
                item->min.f = va_arg (ap, double);
                item->max.f = va_arg (ap, double);
            }
            break;
        }

324
        case VLC_CONFIG_ADVANCED:
325
            item->b_advanced = true;
326
327
            break;

328
        case VLC_CONFIG_VOLATILE:
329
            item->b_unsaveable = true;
330
331
332
            break;

        case VLC_CONFIG_PERSISTENT:
333
            item->b_autosave = true;
334
335
336
            break;

        case VLC_CONFIG_RESTART:
337
            item->b_restart = true;
338
339
            break;

340
        case VLC_CONFIG_PRIVATE:
341
            item->b_internal = true;
342
            break;
343
344

        case VLC_CONFIG_REMOVED:
345
            item->b_removed = true;
346
347
348
349
350
351
352
353
            break;

        case VLC_CONFIG_CAPABILITY:
        {
            const char *cap = va_arg (ap, const char *);
            item->psz_type = cap ? strdup (cap) : NULL;
            break;
        }
354
355
356
357
358

        case VLC_CONFIG_SHORTCUT:
            item->i_short = va_arg (ap, int);
            break;

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
        case VLC_CONFIG_OLDNAME:
        {
            const char *oldname = va_arg (ap, const char *);
            item->psz_oldname = oldname ? strdup (oldname) : NULL;
            break;
        }

        case VLC_CONFIG_SAFE:
            item->b_safe = true;
            break;

        case VLC_CONFIG_DESC:
        {
            const char *domain = va_arg (ap, const char *);
            const char *text = va_arg (ap, const char *);
            const char *longtext = va_arg (ap, const char *);

            if (domain == NULL)
                domain = PACKAGE;
378
            item->psz_text = text ? strdup (mdgettext (domain, text)) : NULL;
379
            item->psz_longtext =
380
                longtext ? strdup (mdgettext (domain, longtext)) : NULL;
381
382
383
            break;
        }

384
385
        case VLC_CONFIG_LIST:
        {
386
            const char *domain = va_arg (ap, const char *);
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
            size_t len = va_arg (ap, size_t);

            /* Copy values */
            if (IsConfigIntegerType (item->i_type))
            {
                const int *src = va_arg (ap, const int *);
                int *dst = malloc (sizeof (int) * (len + 1));

                if (dst != NULL)
                {
                    memcpy (dst, src, sizeof (int) * len);
                    dst[len] = 0;
                }
                item->pi_list = dst;
            }
            else
            if (IsConfigStringType (item->i_type))
            {
                const char *const *src = va_arg (ap, const char *const *);
                char **dst = malloc (sizeof (char *) * (len + 1));

                if (dst != NULL)
                {
                    for (size_t i = 0; i < len; i++)
                        dst[i] = src[i] ? strdup (src[i]) : NULL;
                    dst[len] = NULL;
                }
                item->ppsz_list = dst;
            }
            else
                break;

            /* Copy textual descriptions */
420
421
422
            if (domain == NULL)
                domain = PACKAGE;

423
424
425
            const char *const *text = va_arg (ap, const char *const *);
            if (text != NULL)
            {
ivoire's avatar
ivoire committed
426
427
428
429
430
                char **dtext = malloc (sizeof (char *) * (len + 1));
                if( dtext != NULL )
                {
                    for (size_t i = 0; i < len; i++)
                        dtext[i] = text[i] ?
431
                                        strdup (mdgettext( domain, text[i] )) :
ivoire's avatar
ivoire committed
432
433
434
                                        NULL;
                    dtext[len] = NULL;
                }
435
436
437
438
439
440
                item->ppsz_list_text = dtext;
            }
            else
                item->ppsz_list_text = NULL;

            item->i_list = len;
441
            item->pf_update_list = va_arg (ap, vlc_callback_t);
442
443
            break;
        }
444
445
446

        case VLC_CONFIG_ADD_ACTION:
        {
447
            const char *domain = va_arg (ap, const char *);
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
            vlc_callback_t cb = va_arg (ap, vlc_callback_t), *tabcb;
            const char *name = va_arg (ap, const char *);
            char **tabtext;

            tabcb = realloc (item->ppf_action,
                             (item->i_action + 2) * sizeof (cb));
            if (tabcb == NULL)
                break;
            item->ppf_action = tabcb;
            tabcb[item->i_action] = cb;
            tabcb[item->i_action + 1] = NULL;

            tabtext = realloc (item->ppsz_action_text,
                               (item->i_action + 2) * sizeof (name));
            if (tabtext == NULL)
                break;
            item->ppsz_action_text = tabtext;

466
467
            if (domain == NULL)
                domain = PACKAGE;
468
            if (name)
469
                tabtext[item->i_action] = strdup (mdgettext (domain, name));
470
471
472
473
474
            else
                tabtext[item->i_action] = NULL;
            tabtext[item->i_action + 1] = NULL;

            item->i_action++;
475
476
            break;
        }
477

478
        default:
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
479
480
            fprintf (stderr, "LibVLC: unknown module property %d\n", propid);
            fprintf (stderr, "LibVLC: too old to use this module?\n");
481
482
483
            ret = -1;
            break;
    }
484

485
486
487
    va_end (ap);
    return ret;
}