1 /*****************************************************************************
2 * entry.c : Callbacks for module entry point
3 *****************************************************************************
4 * Copyright (C) 2007 VLC authors and VideoLAN
5 * Copyright © 2007-2008 Rémi Denis-Courmont
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
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 Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20 *****************************************************************************/
26 #include <vlc_common.h>
27 #include <vlc_plugin.h>
28 #include <vlc_memory.h>
33 #include "modules/modules.h"
34 #include "config/configuration.h"
37 static char *strdup_null (const char *str
)
39 return (str
!= NULL
) ? strdup (str
) : NULL
;
42 module_t
*vlc_module_create (module_t
*parent
)
44 module_t
*module
= malloc (sizeof (*module
));
48 /* TODO: replace module/submodules with plugin/modules */
52 module
->parent
= NULL
;
56 module
->next
= parent
->submodule
;
57 parent
->submodule
= module
;
58 parent
->submodule_count
++;
59 module
->parent
= parent
;
62 module
->submodule
= NULL
;
63 module
->submodule_count
= 0;
65 module
->psz_shortname
= NULL
;
66 module
->psz_longname
= NULL
;
67 module
->psz_help
= NULL
;
68 module
->pp_shortcuts
= NULL
;
69 module
->i_shortcuts
= 0;
70 module
->psz_capability
= NULL
;
71 module
->i_score
= (parent
!= NULL
) ? parent
->i_score
: 1;
72 module
->b_loaded
= false;
73 module
->b_unloadable
= parent
== NULL
;
74 module
->pf_activate
= NULL
;
75 module
->pf_deactivate
= NULL
;
76 module
->p_config
= NULL
;
78 module
->i_config_items
= 0;
79 module
->i_bool_items
= 0;
80 /*module->handle = garbage */
81 module
->psz_filename
= NULL
;
82 module
->domain
= NULL
;
88 * @warning If the plug-in is loaded in memory, the handle will be leaked.
90 void vlc_module_destroy (module_t
*module
)
92 assert (!module
->b_loaded
|| !module
->b_unloadable
);
94 for (module_t
*m
= module
->submodule
, *next
; m
!= NULL
; m
= next
)
97 vlc_module_destroy (m
);
100 config_Free (module
->p_config
, module
->confsize
);
102 free (module
->domain
);
103 free (module
->psz_filename
);
104 for (unsigned i
= 0; i
< module
->i_shortcuts
; i
++)
105 free (module
->pp_shortcuts
[i
]);
106 free (module
->pp_shortcuts
);
107 free (module
->psz_capability
);
108 free (module
->psz_help
);
109 free (module
->psz_longname
);
110 free (module
->psz_shortname
);
114 static module_config_t
*vlc_config_create (module_t
*module
, int type
)
116 unsigned confsize
= module
->confsize
;
117 module_config_t
*tab
= module
->p_config
;
119 if ((confsize
& 0xf) == 0)
121 tab
= realloc_or_free (tab
, (confsize
+ 17) * sizeof (*tab
));
125 module
->p_config
= tab
;
128 memset (tab
+ confsize
, 0, sizeof (tab
[confsize
]));
129 if (IsConfigIntegerType (type
))
131 tab
[confsize
].max
.i
= INT_MAX
;
132 tab
[confsize
].min
.i
= INT_MIN
;
134 tab
[confsize
].i_type
= type
;
136 if (CONFIG_ITEM(type
))
138 module
->i_config_items
++;
139 if (type
== CONFIG_ITEM_BOOL
)
140 module
->i_bool_items
++;
144 return tab
+ confsize
;
149 * Callback for the plugin descriptor functions.
151 static int vlc_plugin_setter (void *plugin
, void *tgt
, int propid
, ...)
153 module_t
**pprimary
= plugin
;
154 module_t
*module
= tgt
;
155 module_config_t
*item
= tgt
;
159 va_start (ap
, propid
);
162 case VLC_MODULE_CREATE
:
165 module_t
*submodule
= vlc_module_create (module
);
166 if (unlikely(submodule
== NULL
))
172 *(va_arg (ap
, module_t
**)) = submodule
;
173 if (*pprimary
== NULL
)
175 *pprimary
= submodule
;
178 /* Inheritance. Ugly!! */
179 submodule
->pp_shortcuts
= xmalloc (sizeof ( *submodule
->pp_shortcuts
));
180 submodule
->pp_shortcuts
[0] = strdup_null (module
->pp_shortcuts
[0]);
181 submodule
->i_shortcuts
= 1; /* object name */
183 submodule
->psz_shortname
= strdup_null (module
->psz_shortname
);
184 submodule
->psz_longname
= strdup_null (module
->psz_longname
);
185 submodule
->psz_capability
= strdup_null (module
->psz_capability
);
189 case VLC_CONFIG_CREATE
:
191 int type
= va_arg (ap
, int);
192 module_config_t
**pp
= va_arg (ap
, module_config_t
**);
194 item
= vlc_config_create (*pprimary
, type
);
195 if (unlikely(item
== NULL
))
204 case VLC_MODULE_SHORTCUT
:
206 unsigned i_shortcuts
= va_arg (ap
, unsigned);
207 unsigned index
= module
->i_shortcuts
;
208 /* The cache loader accept only a small number of shortcuts */
209 assert(i_shortcuts
+ index
<= MODULE_SHORTCUT_MAX
);
211 const char *const *tab
= va_arg (ap
, const char *const *);
212 char **pp
= realloc (module
->pp_shortcuts
,
213 sizeof (pp
[0]) * (index
+ i_shortcuts
));
214 if (unlikely(pp
== NULL
))
219 module
->pp_shortcuts
= pp
;
220 module
->i_shortcuts
= index
+ i_shortcuts
;
222 for (unsigned i
= 0; i
< i_shortcuts
; i
++)
223 pp
[i
] = strdup (tab
[i
]);
227 case VLC_MODULE_CAPABILITY
:
228 free (module
->psz_capability
);
229 module
->psz_capability
= strdup (va_arg (ap
, char *));
232 case VLC_MODULE_SCORE
:
233 module
->i_score
= va_arg (ap
, int);
236 case VLC_MODULE_CB_OPEN
:
237 module
->pf_activate
= va_arg (ap
, void *);
240 case VLC_MODULE_CB_CLOSE
:
241 module
->pf_deactivate
= va_arg (ap
, void *);
244 case VLC_MODULE_NO_UNLOAD
:
245 assert (module
->parent
== NULL
);
246 module
->b_unloadable
= false;
249 case VLC_MODULE_NAME
:
251 const char *value
= va_arg (ap
, const char *);
253 assert (module
->i_shortcuts
== 0);
254 module
->pp_shortcuts
= malloc( sizeof( *module
->pp_shortcuts
) );
255 module
->pp_shortcuts
[0] = strdup (value
);
256 module
->i_shortcuts
= 1;
258 assert (module
->psz_longname
== NULL
);
259 module
->psz_longname
= strdup (value
);
263 case VLC_MODULE_SHORTNAME
:
264 assert (module
->psz_shortname
== NULL
|| module
->parent
!= NULL
);
265 free (module
->psz_shortname
);
266 module
->psz_shortname
= strdup (va_arg (ap
, char *));
269 case VLC_MODULE_DESCRIPTION
:
270 // TODO: do not set this in VLC_MODULE_NAME
271 free (module
->psz_longname
);
272 module
->psz_longname
= strdup (va_arg (ap
, char *));
275 case VLC_MODULE_HELP
:
276 assert (module
->parent
== NULL
);
277 assert (module
->psz_help
== NULL
);
278 module
->psz_help
= strdup (va_arg (ap
, char *));
281 case VLC_MODULE_TEXTDOMAIN
:
282 assert (module
->parent
== NULL
);
283 assert (module
->domain
== NULL
);
284 module
->domain
= strdup (va_arg (ap
, char *));
287 case VLC_CONFIG_NAME
:
289 const char *name
= va_arg (ap
, const char *);
291 assert (name
!= NULL
);
292 item
->psz_name
= strdup (name
);
296 case VLC_CONFIG_VALUE
:
298 if (IsConfigIntegerType (item
->i_type
)
299 || !CONFIG_ITEM(item
->i_type
))
302 item
->value
.i
= va_arg (ap
, int64_t);
305 if (IsConfigFloatType (item
->i_type
))
308 item
->value
.f
= va_arg (ap
, double);
311 if (IsConfigStringType (item
->i_type
))
313 const char *value
= va_arg (ap
, const char *);
314 item
->value
.psz
= value
? strdup (value
) : NULL
;
315 item
->orig
.psz
= value
? strdup (value
) : NULL
;
320 case VLC_CONFIG_RANGE
:
322 if (IsConfigFloatType (item
->i_type
))
324 item
->min
.f
= va_arg (ap
, double);
325 item
->max
.f
= va_arg (ap
, double);
329 item
->min
.i
= va_arg (ap
, int64_t);
330 item
->max
.i
= va_arg (ap
, int64_t);
335 case VLC_CONFIG_ADVANCED
:
336 item
->b_advanced
= true;
339 case VLC_CONFIG_VOLATILE
:
340 item
->b_unsaveable
= true;
343 case VLC_CONFIG_PRIVATE
:
344 item
->b_internal
= true;
347 case VLC_CONFIG_REMOVED
:
348 item
->b_removed
= true;
351 case VLC_CONFIG_CAPABILITY
:
353 const char *cap
= va_arg (ap
, const char *);
354 item
->psz_type
= cap
? strdup (cap
) : NULL
;
358 case VLC_CONFIG_SHORTCUT
:
359 item
->i_short
= va_arg (ap
, int);
362 case VLC_CONFIG_SAFE
:
366 case VLC_CONFIG_DESC
:
368 const char *text
= va_arg (ap
, const char *);
369 const char *longtext
= va_arg (ap
, const char *);
371 item
->psz_text
= text
? strdup (text
) : NULL
;
372 item
->psz_longtext
= longtext
? strdup (longtext
) : NULL
;
376 case VLC_CONFIG_LIST
:
378 size_t len
= va_arg (ap
, size_t);
380 assert (item
->list_count
== 0); /* cannot replace choices */
381 assert (item
->list
.psz_cb
== NULL
);
383 break; /* nothing to do */
385 if (IsConfigIntegerType (item
->i_type
))
387 const int *src
= va_arg (ap
, const int *);
388 int *dst
= xmalloc (sizeof (int) * len
);
390 memcpy (dst
, src
, sizeof (int) * len
);
394 if (IsConfigStringType (item
->i_type
))
396 const char *const *src
= va_arg (ap
, const char *const *);
397 char **dst
= xmalloc (sizeof (char *) * len
);
399 for (size_t i
= 0; i
< len
; i
++)
400 dst
[i
] = src
[i
] ? strdup (src
[i
]) : NULL
;
401 item
->list
.psz
= dst
;
406 /* Copy textual descriptions */
407 const char *const *text
= va_arg (ap
, const char *const *);
408 char **dtext
= xmalloc (sizeof (char *) * (len
+ 1));
409 for (size_t i
= 0; i
< len
; i
++)
410 dtext
[i
] = text
[i
] ? strdup (text
[i
]) : NULL
;
411 item
->list_text
= dtext
;
412 item
->list_count
= len
;
416 case VLC_CONFIG_LIST_CB
:
417 if (IsConfigIntegerType (item
->i_type
))
418 item
->list
.i_cb
= va_arg (ap
, vlc_integer_list_cb
);
420 if (IsConfigStringType (item
->i_type
))
421 item
->list
.psz_cb
= va_arg (ap
, vlc_string_list_cb
);
427 fprintf (stderr
, "LibVLC: unknown module property %d\n", propid
);
428 fprintf (stderr
, "LibVLC: too old to use this module?\n");
438 * Runs a plug-in descriptor. This loads the plug-in meta-data in memory.
440 module_t
*vlc_plugin_describe (vlc_plugin_cb entry
)
442 module_t
*module
= NULL
;
444 if (entry (vlc_plugin_setter
, &module
) != 0)
446 if (module
!= NULL
) /* partially initialized plug-in... */
447 vlc_module_destroy (module
);