]> git.sesse.net Git - vlc/blob - src/modules/modules.c
Revert "deinterlace: add basic support for YUY2 and NV12 (fixes #2206)"
[vlc] / src / modules / modules.c
1 /*****************************************************************************
2  * modules.c : Builtin and plugin modules management functions
3  *****************************************************************************
4  * Copyright (C) 2001-2011 VLC authors and VideoLAN
5  * $Id$
6  *
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
12  *
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.
17  *
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.
22  *
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  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdlib.h>
33 #include <string.h>
34 #ifdef ENABLE_NLS
35 # include <libintl.h>
36 #endif
37 #include <assert.h>
38
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"
45
46 /**
47  * Checks whether a module implements a capability.
48  *
49  * \param m the module
50  * \param cap the capability to check
51  * \return true if the module has the capability
52  */
53 bool module_provides (const module_t *m, const char *cap)
54 {
55     return !strcmp (module_get_capability (m), cap);
56 }
57
58 /**
59  * Get the internal name of a module
60  *
61  * \param m the module
62  * \return the module name
63  */
64 const char *module_get_object( const module_t *m )
65 {
66     if (unlikely(m->i_shortcuts == 0))
67         return "unnamed";
68     return m->pp_shortcuts[0];
69 }
70
71 /**
72  * Get the human-friendly name of a module.
73  *
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
77  */
78 const char *module_get_name( const module_t *m, bool long_name )
79 {
80     if( long_name && ( m->psz_longname != NULL) )
81         return m->psz_longname;
82
83     if (m->psz_shortname != NULL)
84         return m->psz_shortname;
85     return module_get_object (m);
86 }
87
88 /**
89  * Get the help for a module
90  *
91  * \param m the module
92  * \return the help
93  */
94 const char *module_get_help( const module_t *m )
95 {
96     return m->psz_help;
97 }
98
99 /**
100  * Gets the capability of a module
101  *
102  * \param m the module
103  * \return the capability, or "none" if unspecified
104  */
105 const char *module_get_capability (const module_t *m)
106 {
107     return (m->psz_capability != NULL) ? m->psz_capability : "none";
108 }
109
110 /**
111  * Get the score for a module
112  *
113  * \param m the module
114  * return the score for the capability
115  */
116 int module_get_score( const module_t *m )
117 {
118     return m->i_score;
119 }
120
121 /**
122  * Translate a string using the module's text domain
123  *
124  * \param m the module
125  * \param str the American English ASCII string to localize
126  * \return the gettext-translated string
127  */
128 const char *module_gettext (const module_t *m, const char *str)
129 {
130     if (m->parent != NULL)
131         m = m->parent;
132     if (unlikely(str == NULL || *str == '\0'))
133         return "";
134 #ifdef ENABLE_NLS
135     const char *domain = m->domain;
136     return dgettext ((domain != NULL) ? domain : PACKAGE_NAME, str);
137 #else
138     (void)m;
139     return str;
140 #endif
141 }
142
143 #undef module_start
144 int module_start (vlc_object_t *obj, const module_t *m)
145 {
146    int (*activate) (vlc_object_t *) = m->pf_activate;
147
148    return (activate != NULL) ? activate (obj) : VLC_SUCCESS;
149 }
150
151 #undef module_stop
152 void module_stop (vlc_object_t *obj, const module_t *m)
153 {
154    void (*deactivate) (vlc_object_t *) = m->pf_deactivate;
155
156     if (deactivate != NULL)
157         deactivate (obj);
158 }
159
160 static bool module_match_name (const module_t *m, const char *name)
161 {
162      /* Plugins with zero score must be matched explicitly. */
163      if (!strcasecmp ("any", name))
164          return m->i_score > 0;
165
166      for (unsigned i = 0; i < m->i_shortcuts; i++)
167           if (!strcasecmp (m->pp_shortcuts[i], name))
168               return true;
169      return false;
170 }
171
172 static int module_load (vlc_object_t *obj, module_t *m,
173                         vlc_activate_t init, va_list args)
174 {
175     int ret = VLC_SUCCESS;
176
177     if (module_Map (obj, m))
178         return VLC_EGENERIC;
179
180     if (m->pf_activate != NULL)
181     {
182         va_list ap;
183
184         va_copy (ap, args);
185         ret = init (m->pf_activate, ap);
186         va_end (ap);
187     }
188     return ret;
189 }
190
191 #undef vlc_module_load
192 /**
193  * Finds and instantiates the best module of a certain type.
194  * All candidates modules having the specified capability and name will be
195  * sorted in decreasing order of priority. Then the probe callback will be
196  * invoked for each module, until it succeeds (returns 0), or all candidate
197  * module failed to initialize.
198  *
199  * The probe callback first parameter is the address of the module entry point.
200  * Further parameters are passed as an argument list; it corresponds to the
201  * variable arguments passed to this function. This scheme is meant to
202  * support arbitrary prototypes for the module entry point.
203  *
204  * \param obj VLC object
205  * \param capability capability, i.e. class of module
206  * \param name name name of the module asked, if any
207  * \param strict if true, do not fallback to plugin with a different name
208  *                 but the same capability
209  * \param probe module probe callback
210  * \return the module or NULL in case of a failure
211  */
212 module_t *vlc_module_load(vlc_object_t *obj, const char *capability,
213                           const char *name, bool strict,
214                           vlc_activate_t probe, ...)
215 {
216     char *var = NULL;
217
218     if (name == NULL || name[0] == '\0')
219         name = "any";
220
221     /* Deal with variables */
222     if (name[0] == '$')
223     {
224         var = var_InheritString (obj, name + 1);
225         name = (var != NULL) ? var : "any";
226     }
227
228     /* Find matching modules */
229     module_t **mods;
230     ssize_t total = module_list_cap (&mods, capability);
231
232     msg_Dbg (obj, "looking for %s module matching \"%s\": %zd candidates",
233              capability, name, total);
234     if (total <= 0)
235     {
236         module_list_free (mods);
237         msg_Dbg (obj, "no %s modules", capability);
238         return NULL;
239     }
240
241     module_t *module = NULL;
242     const bool b_force_backup = obj->b_force; /* FIXME: remove this */
243     va_list args;
244
245     va_start(args, probe);
246     while (*name)
247     {
248         char buf[32];
249         size_t slen = strcspn (name, ",");
250
251         if (likely(slen < sizeof (buf)))
252         {
253             memcpy(buf, name, slen);
254             buf[slen] = '\0';
255         }
256         name += slen;
257         name += strspn (name, ",");
258         if (unlikely(slen >= sizeof (buf)))
259             continue;
260
261         const char *shortcut = buf;
262         assert (shortcut != NULL);
263
264         if (!strcasecmp ("none", shortcut))
265             goto done;
266
267         obj->b_force = strict && strcasecmp ("any", shortcut);
268         for (ssize_t i = 0; i < total; i++)
269         {
270             module_t *cand = mods[i];
271             if (cand == NULL)
272                 continue; // module failed in previous iteration
273             if (!module_match_name (cand, shortcut))
274                 continue;
275             mods[i] = NULL; // only try each module once at most...
276
277             int ret = module_load (obj, cand, probe, args);
278             switch (ret)
279             {
280                 case VLC_SUCCESS:
281                     module = cand;
282                     /* fall through */
283                 case VLC_ETIMEOUT:
284                     goto done;
285             }
286         }
287     }
288
289     /* None of the shortcuts matched, fall back to any module */
290     if (!strict)
291     {
292         obj->b_force = false;
293         for (ssize_t i = 0; i < total; i++)
294         {
295             module_t *cand = mods[i];
296             if (cand == NULL || module_get_score (cand) <= 0)
297                 continue;
298
299             int ret = module_load (obj, cand, probe, args);
300             switch (ret)
301             {
302                 case VLC_SUCCESS:
303                     module = cand;
304                     /* fall through */
305                 case VLC_ETIMEOUT:
306                     goto done;
307             }
308         }
309     }
310 done:
311     va_end (args);
312     obj->b_force = b_force_backup;
313     module_list_free (mods);
314     free (var);
315
316     if (module != NULL)
317     {
318         msg_Dbg (obj, "using %s module \"%s\"", capability,
319                  module_get_object (module));
320         vlc_object_set_name (obj, module_get_object (module));
321     }
322     else
323         msg_Dbg (obj, "no %s modules matched", capability);
324     return module;
325 }
326
327
328 /**
329  * Deinstantiates a module.
330  * \param module the module pointer as returned by vlc_module_load()
331  * \param deinit deactivation callback
332  */
333 void vlc_module_unload(module_t *module, vlc_deactivate_t deinit, ...)
334 {
335     if (module->pf_deactivate != NULL)
336     {
337         va_list ap;
338
339         va_start(ap, deinit);
340         deinit(module->pf_deactivate, ap);
341         va_end(ap);
342     }
343 }
344
345
346 static int generic_start(void *func, va_list ap)
347 {
348     vlc_object_t *obj = va_arg(ap, vlc_object_t *);
349     int (*activate)(vlc_object_t *) = func;
350
351     return activate(obj);
352 }
353
354 static void generic_stop(void *func, va_list ap)
355 {
356     vlc_object_t *obj = va_arg(ap, vlc_object_t *);
357     void (*deactivate)(vlc_object_t *) = func;
358
359     deactivate(obj);
360 }
361
362 #undef module_need
363 module_t *module_need(vlc_object_t *obj, const char *cap, const char *name,
364                       bool strict)
365 {
366     return vlc_module_load(obj, cap, name, strict, generic_start, obj);
367 }
368
369 #undef module_unneed
370 void module_unneed(vlc_object_t *obj, module_t *module)
371 {
372     msg_Dbg(obj, "removing module \"%s\"", module_get_object(module));
373     vlc_module_unload(module, generic_stop, obj);
374 }
375
376 /**
377  * Get a pointer to a module_t given it's name.
378  *
379  * \param name the name of the module
380  * \return a pointer to the module or NULL in case of a failure
381  */
382 module_t *module_find (const char *name)
383 {
384     size_t count;
385     module_t **list = module_list_get (&count);
386
387     assert (name != NULL);
388
389     for (size_t i = 0; i < count; i++)
390     {
391         module_t *module = list[i];
392
393         if (unlikely(module->i_shortcuts == 0))
394             continue;
395         if (!strcmp (module->pp_shortcuts[0], name))
396         {
397             module_list_free (list);
398             return module;
399         }
400     }
401     module_list_free (list);
402     return NULL;
403 }
404
405 /**
406  * Tell if a module exists
407  *
408  * \param psz_name th name of the module
409  * \return TRUE if the module exists
410  */
411 bool module_exists (const char * psz_name)
412 {
413     return module_find (psz_name) != NULL;
414 }
415
416 /**
417  * Get a pointer to a module_t that matches a shortcut.
418  * This is a temporary hack for SD. Do not re-use (generally multiple modules
419  * can have the same shortcut, so this is *broken* - use module_need()!).
420  *
421  * \param psz_shortcut shortcut of the module
422  * \param psz_cap capability of the module
423  * \return a pointer to the module or NULL in case of a failure
424  */
425 module_t *module_find_by_shortcut (const char *psz_shortcut)
426 {
427     size_t count;
428     module_t **list = module_list_get (&count);
429
430     for (size_t i = 0; i < count; i++)
431     {
432         module_t *module = list[count];
433
434         for (size_t j = 0; j < module->i_shortcuts; j++)
435             if (!strcmp (module->pp_shortcuts[j], psz_shortcut))
436             {
437                 module_list_free (list);
438                 return module;
439             }
440     }
441     module_list_free (list);
442     return NULL;
443 }
444
445 /**
446  * Get the configuration of a module
447  *
448  * \param module the module
449  * \param psize the size of the configuration returned
450  * \return the configuration as an array
451  */
452 module_config_t *module_config_get( const module_t *module, unsigned *restrict psize )
453 {
454     unsigned i,j;
455     unsigned size = module->confsize;
456     module_config_t *config = malloc( size * sizeof( *config ) );
457
458     assert( psize != NULL );
459     *psize = 0;
460
461     if( !config )
462         return NULL;
463
464     for( i = 0, j = 0; i < size; i++ )
465     {
466         const module_config_t *item = module->p_config + i;
467         if( item->b_internal /* internal option */
468          || item->b_removed /* removed option */ )
469             continue;
470
471         memcpy( config + j, item, sizeof( *config ) );
472         j++;
473     }
474     *psize = j;
475
476     return config;
477 }
478
479 /**
480  * Release the configuration
481  *
482  * \param the configuration
483  * \return nothing
484  */
485 void module_config_free( module_config_t *config )
486 {
487     free( config );
488 }