sout: display: handle SOUT_STREAM_ID_SPU_HIGHLIGHT
[vlc.git] / src / modules / modules.c
blob6201def20fc6e03cdd9966ec7406d6726d51f810
1 /*****************************************************************************
2 * modules.c : Builtin and plugin modules management functions
3 *****************************************************************************
4 * Copyright (C) 2001-2011 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Sam Hocevar <sam@zoy.org>
8 * Ethan C. Baldridge <BaldridgeE@cadmus.com>
9 * Hans-Peter Jansen <hpj@urpla.net>
10 * Gildas Bazin <gbazin@videolan.org>
11 * RĂ©mi Denis-Courmont
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation; either version 2.1 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this program; if not, write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include <stdlib.h>
33 #include <string.h>
34 #ifdef ENABLE_NLS
35 # include <libintl.h>
36 #endif
37 #include <assert.h>
39 #include <vlc_common.h>
40 #include <vlc_modules.h>
41 #include "libvlc.h"
42 #include "config/configuration.h"
43 #include "vlc_arrays.h"
44 #include "modules/modules.h"
46 /**
47 * Checks whether a module implements a capability.
49 * \param m the module
50 * \param cap the capability to check
51 * \return true if the module has the capability
53 bool module_provides (const module_t *m, const char *cap)
55 return !strcmp (module_get_capability (m), cap);
58 /**
59 * Get the internal name of a module
61 * \param m the module
62 * \return the module name
64 const char *module_get_object( const module_t *m )
66 if (unlikely(m->i_shortcuts == 0))
67 return "unnamed";
68 return m->pp_shortcuts[0];
71 /**
72 * Get the human-friendly name of a module.
74 * \param m the module
75 * \param long_name TRUE to have the long name of the module
76 * \return the short or long name of the module
78 const char *module_get_name( const module_t *m, bool long_name )
80 if( long_name && ( m->psz_longname != NULL) )
81 return m->psz_longname;
83 if (m->psz_shortname != NULL)
84 return m->psz_shortname;
85 return module_get_object (m);
88 /**
89 * Get the help for a module
91 * \param m the module
92 * \return the help
94 const char *module_get_help( const module_t *m )
96 return m->psz_help;
99 /**
100 * Gets the capability of a module
102 * \param m the module
103 * \return the capability, or "none" if unspecified
105 const char *module_get_capability (const module_t *m)
107 return (m->psz_capability != NULL) ? m->psz_capability : "none";
111 * Get the score for a module
113 * \param m the module
114 * return the score for the capability
116 int module_get_score( const module_t *m )
118 return m->i_score;
122 * Translate a string using the module's text domain
124 * \param m the module
125 * \param str the American English ASCII string to localize
126 * \return the gettext-translated string
128 const char *module_gettext (const module_t *m, const char *str)
130 if (unlikely(str == NULL || *str == '\0'))
131 return "";
132 #ifdef ENABLE_NLS
133 const char *domain = m->plugin->textdomain;
134 return dgettext ((domain != NULL) ? domain : PACKAGE_NAME, str);
135 #else
136 (void)m;
137 return str;
138 #endif
141 static bool module_match_name(const module_t *m, const char *name, size_t len)
143 /* Plugins with zero score must be matched explicitly. */
144 if (len == 3 && strncasecmp("any", name, len) == 0)
145 return m->i_score > 0;
147 for (size_t i = 0; i < m->i_shortcuts; i++)
148 if (strncasecmp(m->pp_shortcuts[i], name, len) == 0
149 && m->pp_shortcuts[i][len] == '\0')
150 return true;
152 return false;
155 static int module_load (vlc_object_t *obj, module_t *m,
156 vlc_activate_t init, va_list args)
158 int ret = VLC_SUCCESS;
160 if (module_Map(obj, m->plugin))
161 return VLC_EGENERIC;
163 if (m->pf_activate != NULL)
165 va_list ap;
167 va_copy (ap, args);
168 ret = init (m->pf_activate, ap);
169 va_end (ap);
172 if (ret != VLC_SUCCESS)
173 vlc_objres_clear(obj);
175 return ret;
178 #undef vlc_module_load
180 * Finds and instantiates the best module of a certain type.
181 * All candidates modules having the specified capability and name will be
182 * sorted in decreasing order of priority. Then the probe callback will be
183 * invoked for each module, until it succeeds (returns 0), or all candidate
184 * module failed to initialize.
186 * The probe callback first parameter is the address of the module entry point.
187 * Further parameters are passed as an argument list; it corresponds to the
188 * variable arguments passed to this function. This scheme is meant to
189 * support arbitrary prototypes for the module entry point.
191 * \param obj VLC object
192 * \param capability capability, i.e. class of module
193 * \param name name of the module asked, if any
194 * \param strict if true, do not fallback to plugin with a different name
195 * but the same capability
196 * \param probe module probe callback
197 * \return the module or NULL in case of a failure
199 module_t *vlc_module_load(vlc_object_t *obj, const char *capability,
200 const char *name, bool strict,
201 vlc_activate_t probe, ...)
203 if (name == NULL || name[0] == '\0')
204 name = "any";
206 /* Find matching modules */
207 module_t **mods;
208 ssize_t total = module_list_cap (&mods, capability);
210 msg_Dbg (obj, "looking for %s module matching \"%s\": %zd candidates",
211 capability, name, total);
212 if (total <= 0)
214 module_list_free (mods);
215 msg_Dbg (obj, "no %s modules", capability);
216 return NULL;
219 module_t *module = NULL;
220 const bool b_force_backup = obj->obj.force; /* FIXME: remove this */
221 va_list args;
223 va_start(args, probe);
224 while (*name)
226 const char *shortcut = name;
227 size_t slen = strcspn (name, ",");
229 name += slen;
230 name += strspn (name, ",");
232 if (!strcasecmp ("none", shortcut))
233 goto done;
235 obj->obj.force = strict && strcasecmp ("any", shortcut);
236 for (ssize_t i = 0; i < total; i++)
238 module_t *cand = mods[i];
239 if (cand == NULL)
240 continue; // module failed in previous iteration
241 if (!module_match_name(cand, shortcut, slen))
242 continue;
243 mods[i] = NULL; // only try each module once at most...
245 int ret = module_load (obj, cand, probe, args);
246 switch (ret)
248 case VLC_SUCCESS:
249 module = cand;
250 /* fall through */
251 case VLC_ETIMEOUT:
252 goto done;
257 /* None of the shortcuts matched, fall back to any module */
258 if (!strict)
260 obj->obj.force = false;
261 for (ssize_t i = 0; i < total; i++)
263 module_t *cand = mods[i];
264 if (cand == NULL || module_get_score (cand) <= 0)
265 continue;
267 int ret = module_load (obj, cand, probe, args);
268 switch (ret)
270 case VLC_SUCCESS:
271 module = cand;
272 /* fall through */
273 case VLC_ETIMEOUT:
274 goto done;
278 done:
279 va_end (args);
280 obj->obj.force = b_force_backup;
281 module_list_free (mods);
283 if (module != NULL)
285 msg_Dbg (obj, "using %s module \"%s\"", capability,
286 module_get_object (module));
287 vlc_object_set_name (obj, module_get_object (module));
289 else
290 msg_Dbg (obj, "no %s modules matched", capability);
291 return module;
294 #undef vlc_module_unload
296 * Deinstantiates a module.
297 * \param module the module pointer as returned by vlc_module_load()
298 * \param deinit deactivation callback
300 void vlc_module_unload(vlc_object_t *obj, module_t *module,
301 vlc_deactivate_t deinit, ...)
303 if (module->pf_deactivate != NULL)
305 va_list ap;
307 va_start(ap, deinit);
308 deinit(module->pf_deactivate, ap);
309 va_end(ap);
312 vlc_objres_clear(obj);
316 static int generic_start(void *func, va_list ap)
318 vlc_object_t *obj = va_arg(ap, vlc_object_t *);
319 int (*activate)(vlc_object_t *) = func;
321 return activate(obj);
324 static void generic_stop(void *func, va_list ap)
326 vlc_object_t *obj = va_arg(ap, vlc_object_t *);
327 void (*deactivate)(vlc_object_t *) = func;
329 deactivate(obj);
332 #undef module_need
333 module_t *module_need(vlc_object_t *obj, const char *cap, const char *name,
334 bool strict)
336 return vlc_module_load(obj, cap, name, strict, generic_start, obj);
339 #undef module_unneed
340 void module_unneed(vlc_object_t *obj, module_t *module)
342 msg_Dbg(obj, "removing module \"%s\"", module_get_object(module));
343 vlc_module_unload(obj, module, generic_stop, obj);
347 * Get a pointer to a module_t given it's name.
349 * \param name the name of the module
350 * \return a pointer to the module or NULL in case of a failure
352 module_t *module_find (const char *name)
354 size_t count;
355 module_t **list = module_list_get (&count);
357 assert (name != NULL);
359 for (size_t i = 0; i < count; i++)
361 module_t *module = list[i];
363 if (unlikely(module->i_shortcuts == 0))
364 continue;
365 if (!strcmp (module->pp_shortcuts[0], name))
367 module_list_free (list);
368 return module;
371 module_list_free (list);
372 return NULL;
376 * Tell if a module exists
378 * \param psz_name th name of the module
379 * \return TRUE if the module exists
381 bool module_exists (const char * psz_name)
383 return module_find (psz_name) != NULL;
387 * Get the configuration of a module
389 * \param module the module
390 * \param psize the size of the configuration returned
391 * \return the configuration as an array
393 module_config_t *module_config_get( const module_t *module, unsigned *restrict psize )
395 const vlc_plugin_t *plugin = module->plugin;
397 if (plugin->module != module)
398 { /* For backward compatibility, pretend non-first modules have no
399 * configuration items. */
400 *psize = 0;
401 return NULL;
404 unsigned i,j;
405 size_t size = plugin->conf.size;
406 module_config_t *config = vlc_alloc( size, sizeof( *config ) );
408 assert( psize != NULL );
409 *psize = 0;
411 if( !config )
412 return NULL;
414 for( i = 0, j = 0; i < size; i++ )
416 const module_config_t *item = plugin->conf.items + i;
417 if( item->b_internal /* internal option */
418 || item->b_removed /* removed option */ )
419 continue;
421 memcpy( config + j, item, sizeof( *config ) );
422 j++;
424 *psize = j;
426 return config;
430 * Release the configuration
432 * \param the configuration
433 * \return nothing
435 void module_config_free( module_config_t *config )
437 free( config );