]> git.sesse.net Git - vlc/blob - src/modules/modules.c
cfb2a40d7db9606045696517f9b2fd20de58596e
[vlc] / src / modules / modules.c
1 /*****************************************************************************
2  * modules.c : Builtin and plugin modules management functions
3  *****************************************************************************
4  * Copyright (C) 2001-2011 the VideoLAN team
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
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 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 General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, 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 <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_memory.h>
35 #include <vlc_modules.h>
36 #include "libvlc.h"
37
38 #include <stdlib.h>                                      /* free(), strtol() */
39 #include <stdio.h>                                              /* sprintf() */
40 #include <string.h>                                              /* strdup() */
41 #include <assert.h>
42
43 #include <sys/types.h>
44 #ifdef HAVE_SYS_STAT_H
45 #   include <sys/stat.h>
46 #endif
47 #ifdef HAVE_UNISTD_H
48 #   include <unistd.h>
49 #endif
50 #ifdef ENABLE_NLS
51 # include <libintl.h>
52 #endif
53
54 #include "config/configuration.h"
55
56 #include <vlc_fs.h>
57 #include "vlc_arrays.h"
58
59 #include "modules/modules.h"
60
61 static struct
62 {
63     vlc_mutex_t lock;
64     module_t *head;
65     unsigned usage;
66 } modules = { VLC_STATIC_MUTEX, NULL, 0 };
67
68 int vlc_entry__main( module_t * );
69
70 /*****************************************************************************
71  * Local prototypes
72  *****************************************************************************/
73 #ifdef HAVE_DYNAMIC_PLUGINS
74 typedef enum { CACHE_USE, CACHE_RESET, CACHE_IGNORE } cache_mode_t;
75 typedef struct module_bank module_bank_t;
76
77 static void AllocateAllPlugins (vlc_object_t *);
78 static void AllocatePluginPath (vlc_object_t *, const char *, cache_mode_t);
79 static void AllocatePluginDir( vlc_object_t *, module_bank_t *, const char *,
80                                unsigned, cache_mode_t );
81 static int  AllocatePluginFile( vlc_object_t *, module_bank_t *, const char *,
82                                 const struct stat *, cache_mode_t );
83 static module_t * AllocatePlugin( vlc_object_t *, const char *, bool );
84 #endif
85 static int  AllocateBuiltinModule( vlc_object_t *, int ( * ) ( module_t * ) );
86 static void DeleteModule (module_t **, module_t *);
87 #ifdef HAVE_DYNAMIC_PLUGINS
88 static void   DupModule        ( module_t * );
89 static void   UndupModule      ( module_t * );
90 #endif
91
92 #undef module_InitBank
93 /**
94  * Init bank
95  *
96  * Creates a module bank structure which will be filled later
97  * on with all the modules found.
98  * \param p_this vlc object structure
99  * \return nothing
100  */
101 void module_InitBank( vlc_object_t *p_this )
102 {
103     vlc_mutex_lock (&modules.lock);
104
105     if (modules.usage == 0)
106     {
107         /* Fills the module bank structure with the main module infos.
108          * This is very useful as it will allow us to consider the main
109          * library just as another module, and for instance the configuration
110          * options of main will be available in the module bank structure just
111          * as for every other module. */
112         AllocateBuiltinModule( p_this, vlc_entry__main );
113         vlc_rwlock_init (&config_lock);
114         config_SortConfig ();
115     }
116     modules.usage++;
117
118     /* We do retain the module bank lock until the plugins are loaded as well.
119      * This is ugly, this staged loading approach is needed: LibVLC gets
120      * some configuration parameters relevant to loading the plugins from
121      * the main (builtin) module. The module bank becomes shared read-only data
122      * once it is ready, so we need to fully serialize initialization.
123      * DO NOT UNCOMMENT the following line unless you managed to squeeze
124      * module_LoadPlugins() before you unlock the mutex. */
125     /*vlc_mutex_unlock (&modules.lock);*/
126 }
127
128 #undef module_EndBank
129 /**
130  * Unloads all unused plugin modules and empties the module
131  * bank in case of success.
132  * \param p_this vlc object structure
133  * \return nothing
134  */
135 void module_EndBank( vlc_object_t *p_this, bool b_plugins )
136 {
137     module_t *head = NULL;
138
139     /* If plugins were _not_ loaded, then the caller still has the bank lock
140      * from module_InitBank(). */
141     if( b_plugins )
142         vlc_mutex_lock (&modules.lock);
143     /*else
144         vlc_assert_locked (&modules.lock); not for static mutexes :( */
145
146     assert (modules.usage > 0);
147     if (--modules.usage == 0)
148     {
149         config_UnsortConfig ();
150         vlc_rwlock_destroy (&config_lock);
151         head = modules.head;
152         modules.head = NULL;
153     }
154     vlc_mutex_unlock (&modules.lock);
155
156     while (head != NULL)
157         DeleteModule (&head, head);
158 }
159
160 #undef module_LoadPlugins
161 /**
162  * Loads module descriptions for all available plugins.
163  * Fills the module bank structure with the plugin modules.
164  *
165  * \param p_this vlc object structure
166  * \return nothing
167  */
168 void module_LoadPlugins (vlc_object_t *obj)
169 {
170     /*vlc_assert_locked (&modules.lock); not for static mutexes :( */
171
172 #ifdef HAVE_DYNAMIC_PLUGINS
173     if (modules.usage == 1)
174     {
175         msg_Dbg (obj, "searching plug-in modules");
176         AllocateAllPlugins (obj);
177         config_UnsortConfig ();
178         config_SortConfig ();
179     }
180 #endif
181     vlc_mutex_unlock (&modules.lock);
182 }
183
184 /**
185  * Checks whether a module implements a capability.
186  *
187  * \param m the module
188  * \param cap the capability to check
189  * \return TRUE if the module have the capability
190  */
191 bool module_provides( const module_t *m, const char *cap )
192 {
193     if (unlikely(m->psz_capability == NULL))
194         return false;
195     return !strcmp( m->psz_capability, cap );
196 }
197
198 /**
199  * Get the internal name of a module
200  *
201  * \param m the module
202  * \return the module name
203  */
204 const char *module_get_object( const module_t *m )
205 {
206     return m->psz_object_name;
207 }
208
209 /**
210  * Get the human-friendly name of a module.
211  *
212  * \param m the module
213  * \param long_name TRUE to have the long name of the module
214  * \return the short or long name of the module
215  */
216 const char *module_get_name( const module_t *m, bool long_name )
217 {
218     if( long_name && ( m->psz_longname != NULL) )
219         return m->psz_longname;
220
221     return m->psz_shortname ? m->psz_shortname : m->psz_object_name;
222 }
223
224 /**
225  * Get the help for a module
226  *
227  * \param m the module
228  * \return the help
229  */
230 const char *module_get_help( const module_t *m )
231 {
232     return m->psz_help;
233 }
234
235 /**
236  * Get the capability for a module
237  *
238  * \param m the module
239  * return the capability
240  */
241 const char *module_get_capability( const module_t *m )
242 {
243     return m->psz_capability;
244 }
245
246 /**
247  * Get the score for a module
248  *
249  * \param m the module
250  * return the score for the capability
251  */
252 int module_get_score( const module_t *m )
253 {
254     return m->i_score;
255 }
256
257 /**
258  * Translate a string using the module's text domain
259  *
260  * \param m the module
261  * \param str the American English ASCII string to localize
262  * \return the gettext-translated string
263  */
264 const char *module_gettext (const module_t *m, const char *str)
265 {
266 #ifdef ENABLE_NLS
267     const char *domain = m->domain ? m->domain : PACKAGE_NAME;
268     if (unlikely(str == NULL || *str == '\0'))
269         return "";
270     return dgettext (domain, str);
271 #else
272     (void)m;
273     return str;
274 #endif
275 }
276
277 module_t *module_hold (module_t *m)
278 {
279     vlc_hold (&m->vlc_gc_data);
280     return m;
281 }
282
283 void module_release (module_t *m)
284 {
285     vlc_release (&m->vlc_gc_data);
286 }
287
288 #undef module_start
289 int module_start (vlc_object_t *obj, module_t *m)
290 {
291    int (*activate) (vlc_object_t *) = m->pf_activate;
292
293    return (activate != NULL) ? activate (obj) : VLC_SUCCESS;
294 }
295
296 #undef module_stop
297 void module_stop (vlc_object_t *obj, module_t *m)
298 {
299    void (*deactivate) (vlc_object_t *) = m->pf_deactivate;
300
301     if (deactivate != NULL)
302         deactivate (obj);
303 }
304
305 /**
306  * Frees the flat list of VLC modules.
307  * @param list list obtained by module_list_get()
308  * @param length number of items on the list
309  * @return nothing.
310  */
311 void module_list_free (module_t **list)
312 {
313     if (list == NULL)
314         return;
315
316     for (size_t i = 0; list[i] != NULL; i++)
317          module_release (list[i]);
318     free (list);
319 }
320
321 /**
322  * Gets the flat list of VLC modules.
323  * @param n [OUT] pointer to the number of modules or NULL
324  * @return NULL-terminated table of module pointers
325  *         (release with module_list_free()), or NULL in case of error.
326  */
327 module_t **module_list_get (size_t *n)
328 {
329     /* TODO: this whole module lookup is quite inefficient */
330     /* Remove this and improve module_need */
331     module_t **tab = NULL;
332     size_t i = 0;
333
334     for (module_t *mod = modules.head; mod; mod = mod->next)
335     {
336          module_t **nt;
337          nt  = realloc (tab, (i + 2 + mod->submodule_count) * sizeof (*tab));
338          if (nt == NULL)
339          {
340              module_list_free (tab);
341              return NULL;
342          }
343
344          tab = nt;
345          tab[i++] = module_hold (mod);
346          for (module_t *subm = mod->submodule; subm; subm = subm->next)
347              tab[i++] = module_hold (subm);
348          tab[i] = NULL;
349     }
350     if (n != NULL)
351         *n = i;
352     return tab;
353 }
354
355 typedef struct module_list_t
356 {
357     module_t *p_module;
358     int16_t  i_score;
359     bool     b_force;
360 } module_list_t;
361
362 static int modulecmp (const void *a, const void *b)
363 {
364     const module_list_t *la = a, *lb = b;
365     /* Note that qsort() uses _ascending_ order,
366      * so the smallest module is the one with the biggest score. */
367     return lb->i_score - la->i_score;
368 }
369
370 #undef vlc_module_load
371 /**
372  * Finds and instantiates the best module of a certain type.
373  * All candidates modules having the specified capability and name will be
374  * sorted in decreasing order of priority. Then the probe callback will be
375  * invoked for each module, until it succeeds (returns 0), or all candidate
376  * module failed to initialize.
377  *
378  * The probe callback first parameter is the address of the module entry point.
379  * Further parameters are passed as an argument list; it corresponds to the
380  * variable arguments passed to this function. This scheme is meant to
381  * support arbitrary prototypes for the module entry point.
382  *
383  * \param p_this VLC object
384  * \param psz_capability capability, i.e. class of module
385  * \param psz_name name name of the module asked, if any
386  * \param b_strict if true, do not fallback to plugin with a different name
387  *                 but the same capability
388  * \param probe module probe callback
389  * \return the module or NULL in case of a failure
390  */
391 module_t *vlc_module_load(vlc_object_t *p_this, const char *psz_capability,
392                           const char *psz_name, bool b_strict,
393                           vlc_activate_t probe, ...)
394 {
395     stats_TimerStart( p_this, "module_need()", STATS_TIMER_MODULE_NEED );
396
397     module_list_t *p_list;
398     module_t *p_module;
399     int i_shortcuts = 0;
400     char *psz_shortcuts = NULL, *psz_var = NULL, *psz_alias = NULL;
401     bool b_force_backup = p_this->b_force;
402
403     /* Deal with variables */
404     if( psz_name && psz_name[0] == '$' )
405     {
406         psz_name = psz_var = var_CreateGetString( p_this, psz_name + 1 );
407     }
408
409     /* Count how many different shortcuts were asked for */
410     if( psz_name && *psz_name )
411     {
412         char *psz_parser, *psz_last_shortcut;
413
414         /* If the user wants none, give him none. */
415         if( !strcmp( psz_name, "none" ) )
416         {
417             free( psz_var );
418             stats_TimerStop( p_this, STATS_TIMER_MODULE_NEED );
419             stats_TimerDump( p_this, STATS_TIMER_MODULE_NEED );
420             stats_TimerClean( p_this, STATS_TIMER_MODULE_NEED );
421             return NULL;
422         }
423
424         i_shortcuts++;
425         psz_parser = psz_shortcuts = psz_last_shortcut = strdup( psz_name );
426
427         while( ( psz_parser = strchr( psz_parser, ',' ) ) )
428         {
429              *psz_parser = '\0';
430              i_shortcuts++;
431              psz_last_shortcut = ++psz_parser;
432         }
433
434         /* Check if the user wants to override the "strict" mode */
435         if( psz_last_shortcut )
436         {
437             if( !strcmp(psz_last_shortcut, "none") )
438             {
439                 b_strict = true;
440                 i_shortcuts--;
441             }
442             else if( !strcmp(psz_last_shortcut, "any") )
443             {
444                 b_strict = false;
445                 i_shortcuts--;
446             }
447         }
448     }
449
450     /* Sort the modules and test them */
451     size_t count;
452     module_t **p_all = module_list_get (&count);
453     p_list = malloc( count * sizeof( module_list_t ) );
454
455     /* Parse the module list for capabilities and probe each of them */
456     count = 0;
457     for (size_t i = 0; (p_module = p_all[i]) != NULL; i++)
458     {
459         int i_shortcut_bonus = 0;
460
461         /* Test that this module can do what we need */
462         if( !module_provides( p_module, psz_capability ) )
463             continue;
464
465         /* If we required a shortcut, check this plugin provides it. */
466         if( i_shortcuts > 0 )
467         {
468             const char *name = psz_shortcuts;
469
470             for( unsigned i_short = i_shortcuts; i_short > 0; i_short-- )
471             {
472                 for( unsigned i = 0; i < p_module->i_shortcuts; i++ )
473                 {
474                     char *c;
475                     if( ( c = strchr( name, '@' ) )
476                         ? !strncasecmp( name, p_module->pp_shortcuts[i],
477                                         c-name )
478                         : !strcasecmp( name, p_module->pp_shortcuts[i] ) )
479                     {
480                         /* Found it */
481                         if( c && c[1] )
482                             psz_alias = c+1;
483                         i_shortcut_bonus = i_short * 10000;
484                         goto found_shortcut;
485                     }
486                 }
487
488                 /* Go to the next shortcut... This is so lame! */
489                 name += strlen( name ) + 1;
490             }
491
492             /* If we are in "strict" mode and we couldn't
493              * find the module in the list of provided shortcuts,
494              * then kick the bastard out of here!!! */
495             if( b_strict )
496                 continue;
497         }
498
499         /* Trash <= 0 scored plugins (they can only be selected by shortcut) */
500         if( p_module->i_score <= 0 )
501             continue;
502
503 found_shortcut:
504         /* Store this new module */
505         p_list[count].p_module = module_hold (p_module);
506         p_list[count].i_score = p_module->i_score + i_shortcut_bonus;
507         p_list[count].b_force = i_shortcut_bonus && b_strict;
508         count++;
509     }
510
511     /* We can release the list, interesting modules are held */
512     module_list_free (p_all);
513
514     /* Sort candidates by descending score */
515     qsort (p_list, count, sizeof (p_list[0]), modulecmp);
516     msg_Dbg( p_this, "looking for %s module: %zu candidate%s", psz_capability,
517              count, count == 1 ? "" : "s" );
518
519     /* Parse the linked list and use the first successful module */
520     va_list args;
521
522     va_start(args, probe);
523     p_module = NULL;
524
525     for (size_t i = 0; (i < count) && (p_module == NULL); i++)
526     {
527         module_t *p_cand = p_list[i].p_module;
528 #ifdef HAVE_DYNAMIC_PLUGINS
529         /* Make sure the module is loaded in mem */
530         module_t *p_real = p_cand->parent ? p_cand->parent : p_cand;
531
532         if( !p_real->b_builtin && !p_real->b_loaded )
533         {
534             module_t *p_new_module =
535                 AllocatePlugin( p_this, p_real->psz_filename, false );
536             if( p_new_module == NULL )
537             {   /* Corrupted module */
538                 msg_Err( p_this, "possibly corrupt module cache" );
539                 module_release( p_cand );
540                 continue;
541             }
542             CacheMerge( p_this, p_real, p_new_module );
543             DeleteModule (&modules.head, p_new_module);
544         }
545 #endif
546         p_this->b_force = p_list[i].b_force;
547
548         int ret;
549
550         if (likely(p_cand->pf_activate != NULL))
551         {
552             va_list ap;
553
554             va_copy(ap, args);
555             ret = probe(p_cand->pf_activate, ap);
556             va_end(ap);
557         }
558         else
559             ret = VLC_SUCCESS;
560
561         switch (ret)
562         {
563         case VLC_SUCCESS:
564             /* good module! */
565             p_module = p_cand;
566             break;
567
568         case VLC_ETIMEOUT:
569             /* good module, but aborted */
570             module_release( p_cand );
571             break;
572
573         default: /* bad module */
574             module_release( p_cand );
575             continue;
576         }
577
578         /* Release the remaining modules */
579         while (++i < count)
580             module_release (p_list[i].p_module);
581     }
582
583     va_end (args);
584     free( p_list );
585     p_this->b_force = b_force_backup;
586
587     if( p_module != NULL )
588     {
589         msg_Dbg( p_this, "using %s module \"%s\"",
590                  psz_capability, p_module->psz_object_name );
591         vlc_object_set_name( p_this, psz_alias ? psz_alias
592                                                : p_module->psz_object_name );
593     }
594     else if( count == 0 )
595         msg_Dbg( p_this, "no %s module matched \"%s\"",
596                  psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
597     else
598         msg_Dbg( p_this, "no %s module matching \"%s\" could be loaded",
599                   psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
600
601     free( psz_shortcuts );
602     free( psz_var );
603
604     stats_TimerStop( p_this, STATS_TIMER_MODULE_NEED );
605     stats_TimerDump( p_this, STATS_TIMER_MODULE_NEED );
606     stats_TimerClean( p_this, STATS_TIMER_MODULE_NEED );
607
608     /* Don't forget that the module is still locked */
609     return p_module;
610 }
611
612
613 /**
614  * Deinstantiates a module.
615  * \param module the module pointer as returned by vlc_module_load()
616  * \param deinit deactivation callback
617  */
618 void vlc_module_unload(module_t *module, vlc_deactivate_t deinit, ...)
619 {
620     if (module->pf_deactivate != NULL)
621     {
622         va_list ap;
623
624         va_start(ap, deinit);
625         deinit(module->pf_deactivate, ap);
626         va_end(ap);
627     }
628     module_release(module);
629 }
630
631
632 static int generic_start(void *func, va_list ap)
633 {
634     vlc_object_t *obj = va_arg(ap, vlc_object_t *);
635     int (*activate)(vlc_object_t *) = func;
636
637     return activate(obj);
638 }
639
640 static void generic_stop(void *func, va_list ap)
641 {
642     vlc_object_t *obj = va_arg(ap, vlc_object_t *);
643     void (*deactivate)(vlc_object_t *) = func;
644
645     deactivate(obj);
646 }
647
648 #undef module_need
649 module_t *module_need(vlc_object_t *obj, const char *cap, const char *name,
650                       bool strict)
651 {
652     return vlc_module_load(obj, cap, name, strict, generic_start, obj);
653 }
654
655 #undef module_unneed
656 void module_unneed(vlc_object_t *obj, module_t *module)
657 {
658     msg_Dbg(obj, "removing module \"%s\"", module->psz_object_name);
659     vlc_module_unload(module, generic_stop, obj);
660 }
661
662 /**
663  * Get a pointer to a module_t given it's name.
664  *
665  * \param psz_name the name of the module
666  * \return a pointer to the module or NULL in case of a failure
667  */
668 module_t *module_find( const char * psz_name )
669 {
670     module_t **list, *module;
671
672     list = module_list_get (NULL);
673     if (!list)
674         return NULL;
675
676     for (size_t i = 0; (module = list[i]) != NULL; i++)
677     {
678         const char *psz_module_name = module->psz_object_name;
679
680         if( psz_module_name && !strcmp( psz_module_name, psz_name ) )
681         {
682             module_hold (module);
683             break;
684         }
685     }
686     module_list_free (list);
687     return module;
688 }
689
690 /**
691  * Tell if a module exists and release it in thic case
692  *
693  * \param psz_name th name of the module
694  * \return TRUE if the module exists
695  */
696 bool module_exists (const char * psz_name)
697 {
698     module_t *p_module = module_find (psz_name);
699     if( p_module )
700         module_release (p_module);
701     return p_module != NULL;
702 }
703
704 /**
705  * Get a pointer to a module_t that matches a shortcut.
706  * This is a temporary hack for SD. Do not re-use (generally multiple modules
707  * can have the same shortcut, so this is *broken* - use module_need()!).
708  *
709  * \param psz_shortcut shortcut of the module
710  * \param psz_cap capability of the module
711  * \return a pointer to the module or NULL in case of a failure
712  */
713 module_t *module_find_by_shortcut (const char *psz_shortcut)
714 {
715     module_t **list, *module;
716
717     list = module_list_get (NULL);
718     if (!list)
719         return NULL;
720
721     for (size_t i = 0; (module = list[i]) != NULL; i++)
722     {
723         for (size_t j = 0; j < module->i_shortcuts; j++)
724         {
725             if (!strcmp (module->pp_shortcuts[j], psz_shortcut))
726             {
727                 module_hold (module);
728                 goto out;
729              }
730         }
731     }
732 out:
733     module_list_free (list);
734     return module;
735 }
736
737 /**
738  * Get the configuration of a module
739  *
740  * \param module the module
741  * \param psize the size of the configuration returned
742  * \return the configuration as an array
743  */
744 module_config_t *module_config_get( const module_t *module, unsigned *restrict psize )
745 {
746     unsigned i,j;
747     unsigned size = module->confsize;
748     module_config_t *config = malloc( size * sizeof( *config ) );
749
750     assert( psize != NULL );
751     *psize = 0;
752
753     if( !config )
754         return NULL;
755
756     for( i = 0, j = 0; i < size; i++ )
757     {
758         const module_config_t *item = module->p_config + i;
759         if( item->b_internal /* internal option */
760          || item->b_removed /* removed option */ )
761             continue;
762
763         memcpy( config + j, item, sizeof( *config ) );
764         j++;
765     }
766     *psize = j;
767
768     return config;
769 }
770
771 /**
772  * Release the configuration
773  *
774  * \param the configuration
775  * \return nothing
776  */
777 void module_config_free( module_config_t *config )
778 {
779     free( config );
780 }
781
782 /*****************************************************************************
783  * Following functions are local.
784  *****************************************************************************/
785
786 char *psz_vlcpath = NULL;
787
788 #ifdef HAVE_DYNAMIC_PLUGINS
789
790 /*****************************************************************************
791  * AllocateAllPlugins: load all plugin modules we can find.
792  *****************************************************************************/
793 static void AllocateAllPlugins (vlc_object_t *p_this)
794 {
795     const char *vlcpath = psz_vlcpath;
796     char *paths;
797     cache_mode_t mode;
798
799     if( !var_InheritBool( p_this, "plugins-cache" ) )
800         mode = CACHE_IGNORE;
801     else if( var_InheritBool( p_this, "reset-plugins-cache" ) )
802         mode = CACHE_RESET;
803     else
804         mode = CACHE_USE;
805
806     /* Contruct the special search path for system that have a relocatable
807      * executable. Set it to <vlc path>/plugins. */
808     assert( vlcpath );
809
810     if( asprintf( &paths, "%s" DIR_SEP "plugins", vlcpath ) != -1 )
811     {
812         AllocatePluginPath (p_this, paths, mode);
813         free( paths );
814     }
815
816     /* If the user provided a plugin path, we add it to the list */
817     paths = getenv( "VLC_PLUGIN_PATH" );
818     if( paths == NULL )
819         return;
820
821     paths = strdup( paths ); /* don't harm the environment ! :) */
822     if( unlikely(paths == NULL) )
823         return;
824
825     for( char *buf, *path = strtok_r( paths, PATH_SEP, &buf );
826          path != NULL;
827          path = strtok_r( NULL, PATH_SEP, &buf ) )
828         AllocatePluginPath (p_this, path, mode);
829
830     free( paths );
831 }
832
833 struct module_bank
834 {
835     /* Plugins cache */
836     size_t         i_cache;
837     module_cache_t *cache;
838
839     int            i_loaded_cache;
840     module_cache_t *loaded_cache;
841 };
842
843 static void AllocatePluginPath (vlc_object_t *p_this, const char *path,
844                                 cache_mode_t mode)
845 {
846     module_bank_t bank;
847     module_cache_t *cache = NULL;
848     size_t count = 0;
849
850     switch( mode )
851     {
852         case CACHE_USE:
853             count = CacheLoad( p_this, path, &cache );
854             break;
855         case CACHE_RESET:
856             CacheDelete( p_this, path );
857             break;
858         case CACHE_IGNORE:
859             msg_Dbg( p_this, "ignoring plugins cache file" );
860     }
861
862     msg_Dbg( p_this, "recursively browsing `%s'", path );
863
864     bank.cache = NULL;
865     bank.i_cache = 0;
866     bank.loaded_cache = cache;
867     bank.i_loaded_cache = count;
868
869     /* Don't go deeper than 5 subdirectories */
870     AllocatePluginDir (p_this, &bank, path, 5, mode);
871
872     switch( mode )
873     {
874         case CACHE_USE:
875             for( size_t i = 0; i < count; i++ )
876             {
877                 if (cache[i].p_module != NULL)
878                    DeleteModule (&modules.head, cache[i].p_module);
879                 free (cache[i].path);
880             }
881             free( cache );
882         case CACHE_RESET:
883             CacheSave (p_this, path, bank.cache, bank.i_cache);
884         case CACHE_IGNORE:
885             break;
886     }
887 }
888
889 /*****************************************************************************
890  * AllocatePluginDir: recursively parse a directory to look for plugins
891  *****************************************************************************/
892 static void AllocatePluginDir( vlc_object_t *p_this, module_bank_t *p_bank,
893                                const char *psz_dir, unsigned i_maxdepth,
894                                cache_mode_t mode )
895 {
896     if( i_maxdepth == 0 )
897         return;
898
899     DIR *dh = vlc_opendir (psz_dir);
900     if (dh == NULL)
901         return;
902
903     /* Parse the directory and try to load all files it contains. */
904     for (;;)
905     {
906         char *file = vlc_readdir (dh), *path;
907         struct stat st;
908
909         if (file == NULL)
910             break;
911
912         /* Skip ".", ".." */
913         if (!strcmp (file, ".") || !strcmp (file, ".."))
914         {
915             free (file);
916             continue;
917         }
918
919         const int pathlen = asprintf (&path, "%s"DIR_SEP"%s", psz_dir, file);
920         free (file);
921         if (pathlen == -1 || vlc_stat (path, &st))
922             continue;
923
924         if (S_ISDIR (st.st_mode))
925             /* Recurse into another directory */
926             AllocatePluginDir (p_this, p_bank, path, i_maxdepth - 1, mode);
927         else
928         if (S_ISREG (st.st_mode)
929          && strncmp (path, "lib", 3)
930          && ((size_t)pathlen >= sizeof ("_plugin"LIBEXT))
931          && !strncasecmp (path + pathlen - strlen ("_plugin"LIBEXT),
932                           "_plugin"LIBEXT, strlen ("_plugni"LIBEXT)))
933             /* ^^ We only load files matching "lib*_plugin"LIBEXT */
934             AllocatePluginFile (p_this, p_bank, path, &st, mode);
935
936         free (path);
937     }
938     closedir (dh);
939 }
940
941 /*****************************************************************************
942  * AllocatePluginFile: load a module into memory and initialize it.
943  *****************************************************************************
944  * This function loads a dynamically loadable module and allocates a structure
945  * for its information data. The module can then be handled by module_need
946  * and module_unneed. It can be removed by DeleteModule.
947  *****************************************************************************/
948 static int AllocatePluginFile( vlc_object_t * p_this, module_bank_t *p_bank,
949                                const char *path, const struct stat *st,
950                                cache_mode_t mode )
951 {
952     module_t * p_module = NULL;
953
954     /* msg_Dbg( p_this, "plugin \"%s\", %s",
955                 p_module->psz_object_name, p_module->psz_longname ); */
956     /* Check our plugins cache first then load plugin if needed */
957     if( mode == CACHE_USE )
958         p_module = CacheFind (p_bank->loaded_cache, p_bank->i_loaded_cache,
959                               path, st);
960     if( p_module == NULL )
961         p_module = AllocatePlugin( p_this, path, true );
962     if( p_module == NULL )
963         return -1;
964
965     /* We have not already scanned and inserted this module */
966     assert( p_module->next == NULL );
967
968     /* Unload plugin until we really need it */
969     assert( !p_module->b_builtin );
970     if( p_module->b_loaded && p_module->b_unloadable )
971     {
972         module_Unload( p_module->handle );
973         p_module->b_loaded = false;
974     }
975
976     /* For now we force loading if the module's config contains
977      * callbacks or actions.
978      * Could be optimized by adding an API call.*/
979     for( size_t n = p_module->confsize, i = 0; i < n; i++ )
980          if( p_module->p_config[i].i_action )
981          {
982              /* !unloadable not allowed for plugins with callbacks */
983              assert( !p_module->b_loaded );
984              DeleteModule (&modules.head, p_module);
985              p_module = AllocatePlugin( p_this, path, false );
986              break;
987          }
988
989     p_module->next = modules.head;
990     modules.head = p_module;
991
992     if( mode == CACHE_IGNORE )
993         return 0;
994
995     /* Add entry to cache */
996     CacheAdd (&p_bank->cache, &p_bank->i_cache, path, st, p_module);
997     /* TODO: deal with errors */
998     return  0;
999 }
1000
1001 /*****************************************************************************
1002  * AllocatePlugin: load a module into memory and initialize it.
1003  *****************************************************************************
1004  * This function loads a dynamically loadable module and allocates a structure
1005  * for its information data. The module can then be handled by module_need
1006  * and module_unneed. It can be removed by DeleteModule.
1007  *****************************************************************************/
1008 static module_t *AllocatePlugin( vlc_object_t * p_this, const char *psz_file,
1009                                  bool fast )
1010 {
1011     module_t * p_module = NULL;
1012     module_handle_t handle;
1013
1014     if( module_Load( p_this, psz_file, &handle, fast ) )
1015         return NULL;
1016
1017     /* Now that we have successfully loaded the module, we can
1018      * allocate a structure for it */
1019     p_module = vlc_module_create();
1020     if( p_module == NULL )
1021     {
1022         module_Unload( handle );
1023         return NULL;
1024     }
1025
1026     p_module->psz_filename = strdup( psz_file );
1027     p_module->handle = handle;
1028     p_module->b_loaded = true;
1029
1030     /* Initialize the module: fill p_module, default config */
1031     static const char entry[] = "vlc_entry" MODULE_SUFFIX;
1032
1033     /* Try to resolve the symbol */
1034     int (*pf_symbol)(module_t * p_module)
1035         = (int (*)(module_t *)) module_Lookup( p_module->handle,entry );
1036     if( pf_symbol == NULL )
1037     {
1038         msg_Warn( p_this, "cannot find symbol \"%s\" in plugin `%s'",
1039                   entry, psz_file );
1040         goto error;
1041     }
1042     else
1043     /* We can now try to call the symbol */
1044     if( pf_symbol( p_module ) != 0 )
1045     {
1046         /* With a well-written module we shouldn't have to print an
1047          * additional error message here, but just make sure. */
1048         msg_Err( p_this, "cannot initialize plugin `%s'", psz_file );
1049         goto error;
1050     }
1051
1052     DupModule( p_module );
1053     assert( !p_module->b_builtin );
1054     return p_module;
1055 error:
1056     free( p_module->psz_filename );
1057     module_release( p_module );
1058     module_Unload( handle );
1059     return NULL;
1060 }
1061
1062 /*****************************************************************************
1063  * DupModule: make a plugin module standalone.
1064  *****************************************************************************
1065  * This function duplicates all strings in the module, so that the dynamic
1066  * object can be unloaded. It acts recursively on submodules.
1067  *****************************************************************************/
1068 static void DupModule( module_t *p_module )
1069 {
1070     char **pp_shortcuts = p_module->pp_shortcuts;
1071     for( unsigned i = 0; i < p_module->i_shortcuts; i++ )
1072         pp_shortcuts[i] = strdup( p_module->pp_shortcuts[i] );
1073
1074     /* We strdup() these entries so that they are still valid when the
1075      * module is unloaded. */
1076     p_module->psz_capability =
1077         p_module->psz_capability ? strdup( p_module->psz_capability ) : NULL;
1078     p_module->psz_shortname = p_module->psz_shortname ?
1079                                  strdup( p_module->psz_shortname ) : NULL;
1080     p_module->psz_longname = strdup( p_module->psz_longname );
1081     p_module->psz_help = p_module->psz_help ? strdup( p_module->psz_help )
1082                                             : NULL;
1083     p_module->domain = p_module->domain ? strdup( p_module->domain ) : NULL;
1084
1085     for (module_t *subm = p_module->submodule; subm; subm = subm->next)
1086         DupModule (subm);
1087 }
1088
1089 /*****************************************************************************
1090  * UndupModule: free a duplicated module.
1091  *****************************************************************************
1092  * This function frees the allocations done in DupModule().
1093  *****************************************************************************/
1094 static void UndupModule( module_t *p_module )
1095 {
1096     char **pp_shortcuts = p_module->pp_shortcuts;
1097
1098     for (module_t *subm = p_module->submodule; subm; subm = subm->next)
1099         UndupModule (subm);
1100
1101     for( unsigned i = 0; i < p_module->i_shortcuts; i++ )
1102         free( pp_shortcuts[i] );
1103
1104     free( p_module->psz_capability );
1105     FREENULL( p_module->psz_shortname );
1106     free( p_module->psz_longname );
1107     FREENULL( p_module->psz_help );
1108     free( p_module->domain );
1109 }
1110
1111 #endif /* HAVE_DYNAMIC_PLUGINS */
1112
1113 /*****************************************************************************
1114  * AllocateBuiltinModule: initialize a builtin module.
1115  *****************************************************************************
1116  * This function registers a builtin module and allocates a structure
1117  * for its information data. The module can then be handled by module_need
1118  * and module_unneed. It can be removed by DeleteModule.
1119  *****************************************************************************/
1120 static int AllocateBuiltinModule( vlc_object_t * p_this,
1121                                   int ( *pf_entry ) ( module_t * ) )
1122 {
1123     module_t * p_module;
1124
1125     /* Now that we have successfully loaded the module, we can
1126      * allocate a structure for it */
1127     p_module = vlc_module_create();
1128     if( p_module == NULL )
1129         return -1;
1130
1131     /* Initialize the module : fill p_module->psz_object_name, etc. */
1132     if( pf_entry( p_module ) != 0 )
1133     {
1134         /* With a well-written module we shouldn't have to print an
1135          * additional error message here, but just make sure. */
1136         msg_Err( p_this, "failed calling entry point in builtin module" );
1137         module_release( p_module );
1138         return -1;
1139     }
1140
1141     /* Everything worked fine ! The module is ready to be added to the list. */
1142     p_module->b_builtin = true;
1143     /* LOCK */
1144     p_module->next = modules.head;
1145     modules.head = p_module;
1146     /* UNLOCK */
1147
1148     /* msg_Dbg( p_this, "builtin \"%s\", %s",
1149                 p_module->psz_object_name, p_module->psz_longname ); */
1150
1151     return 0;
1152 }
1153
1154 /*****************************************************************************
1155  * DeleteModule: delete a module and its structure.
1156  *****************************************************************************
1157  * This function can only be called if the module isn't being used.
1158  *****************************************************************************/
1159 static void DeleteModule (module_t **head, module_t *p_module)
1160 {
1161     assert( p_module );
1162
1163     /* Unlist the module (if it is in the list) */
1164     module_t **pp_self = head;
1165     while (*pp_self != NULL && *pp_self != p_module)
1166         pp_self = &((*pp_self)->next);
1167     if (*pp_self)
1168         *pp_self = p_module->next;
1169
1170     /* We free the structures that we strdup()ed in Allocate*Module(). */
1171 #ifdef HAVE_DYNAMIC_PLUGINS
1172     if( !p_module->b_builtin )
1173     {
1174         if( p_module->b_loaded && p_module->b_unloadable )
1175         {
1176             module_Unload( p_module->handle );
1177         }
1178         UndupModule( p_module );
1179         free( p_module->psz_filename );
1180     }
1181 #endif
1182
1183     /* Free and detach the object's children */
1184     while (p_module->submodule)
1185     {
1186         module_t *submodule = p_module->submodule;
1187         p_module->submodule = submodule->next;
1188         module_release (submodule);
1189     }
1190
1191     config_Free( p_module );
1192     module_release( p_module );
1193 }