]> git.sesse.net Git - vlc/blob - src/misc/modules.c
* ./include/modules_inner.h: replaced _X with __VLC_SYMBOL because _X was
[vlc] / src / misc / modules.c
1 /*****************************************************************************
2  * modules.c : Built-in and plugin modules management functions
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: modules.c,v 1.47 2002/01/09 02:01:14 sam Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Ethan C. Baldridge <BaldridgeE@cadmus.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /* Some faulty libcs have a broken struct dirent when _FILE_OFFSET_BITS
26  * is set to 64. Don't try to be cleverer. */
27 #ifdef _FILE_OFFSET_BITS
28 #undef _FILE_OFFSET_BITS
29 #endif
30
31 #include <stdlib.h>                                      /* free(), strtol() */
32 #include <stdio.h>                                              /* sprintf() */
33 #include <string.h>                                              /* strdup() */
34
35 #include <videolan/vlc.h>
36
37 #if !defined( _MSC_VER )
38 #include <dirent.h>
39 #endif
40
41 #if defined(HAVE_DLFCN_H)                                /* Linux, BSD, Hurd */
42 #   include <dlfcn.h>                        /* dlopen(), dlsym(), dlclose() */
43 #   define HAVE_DYNAMIC_PLUGINS
44 #elif defined(HAVE_IMAGE_H)                                          /* BeOS */
45 #   include <image.h>
46 #   define HAVE_DYNAMIC_PLUGINS
47 #elif defined(WIN32) && defined( __MINGW32__ )
48 #   define HAVE_DYNAMIC_PLUGINS
49 #else
50 #   undef HAVE_DYNAMIC_PLUGINS
51 #endif
52
53 #include "netutils.h"
54
55 #include "interface.h"
56 #include "intf_playlist.h"
57 #include "intf_eject.h"
58
59 #include "stream_control.h"
60 #include "input_ext-intf.h"
61 #include "input_ext-dec.h"
62 #include "input_ext-plugins.h"
63
64 #include "video.h"
65 #include "video_output.h"
66
67 #include "audio_output.h"
68
69 #include "iso_lang.h"
70
71 #ifdef HAVE_DYNAMIC_PLUGINS
72 #   include "modules_plugin.h"
73 #endif
74 #include "modules_builtin.h"
75
76 /*****************************************************************************
77  * Local prototypes
78  *****************************************************************************/
79 #ifdef HAVE_DYNAMIC_PLUGINS
80 static void AllocateAllPlugins   ( void );
81 static int  AllocatePluginModule ( char * );
82 #endif
83 static void AllocateAllBuiltins  ( void );
84 static int  AllocateBuiltinModule( int ( * ) ( module_t * ),
85                                    int ( * ) ( module_t * ),
86                                    int ( * ) ( module_t * ) );
87 static int  DeleteModule ( module_t * );
88 static int  LockModule   ( module_t * );
89 static int  UnlockModule ( module_t * );
90 #ifdef HAVE_DYNAMIC_PLUGINS
91 static int  HideModule   ( module_t * );
92 static int  CallSymbol   ( module_t *, char * );
93 #endif
94
95 static module_symbols_t symbols;
96
97 /*****************************************************************************
98  * module_InitBank: create the module bank.
99  *****************************************************************************
100  * This function creates a module bank structure and fills it with the
101  * built-in modules, as well as all the plugin modules it can find.
102  *****************************************************************************/
103 void module_InitBank( void )
104 {
105     p_module_bank->first = NULL;
106     p_module_bank->i_count = 0;
107     vlc_mutex_init( &p_module_bank->lock );
108
109     /*
110      * Store the symbols to be exported
111      */
112     STORE_SYMBOLS( &symbols );
113
114     /*
115      * Check all the built-in modules
116      */
117     intf_WarnMsg( 2, "module: checking built-in modules" );
118     AllocateAllBuiltins();
119
120     /*
121      * Check all the plugin modules we can find
122      */
123 #ifdef HAVE_DYNAMIC_PLUGINS
124     intf_WarnMsg( 2, "module: checking plugin modules" );
125     AllocateAllPlugins();
126 #endif
127
128     intf_WarnMsg( 2, "module: module bank initialized, found %i modules",
129                      p_module_bank->i_count );
130
131     return;
132 }
133
134 /*****************************************************************************
135  * module_EndBank: empty the module bank.
136  *****************************************************************************
137  * This function unloads all unused plugin modules and empties the module
138  * bank in case of success.
139  *****************************************************************************/
140 void module_EndBank( void )
141 {
142     module_t * p_next;
143
144     while( p_module_bank->first != NULL )
145     {
146         if( DeleteModule( p_module_bank->first ) )
147         {
148             /* Module deletion failed */
149             intf_ErrMsg( "module error: `%s' can't be removed, trying harder",
150                          p_module_bank->first->psz_name );
151
152             /* We just free the module by hand. Niahahahahaha. */
153             p_next = p_module_bank->first->next;
154             free(p_module_bank->first);
155             p_module_bank->first = p_next;
156         }
157     }
158
159     /* Destroy the lock */
160     vlc_mutex_destroy( &p_module_bank->lock );
161
162     return;
163 }
164
165 /*****************************************************************************
166  * module_ResetBank: reset the module bank.
167  *****************************************************************************
168  * This function resets the module bank by unloading all unused plugin
169  * modules.
170  *****************************************************************************/
171 void module_ResetBank( void )
172 {
173     intf_ErrMsg( "FIXME: module_ResetBank unimplemented" );
174     return;
175 }
176
177 /*****************************************************************************
178  * module_ManageBank: manage the module bank.
179  *****************************************************************************
180  * This function parses the module bank and hides modules that have been
181  * unused for a while.
182  *****************************************************************************/
183 void module_ManageBank( void )
184 {
185 #ifdef HAVE_DYNAMIC_PLUGINS
186     module_t * p_module;
187
188     /* We take the global lock */
189     vlc_mutex_lock( &p_module_bank->lock );
190
191     /* Parse the module list to see if any modules need to be unloaded */
192     for( p_module = p_module_bank->first ;
193          p_module != NULL ;
194          p_module = p_module->next )
195     {
196         /* If the module is unused and if it is a plugin module... */
197         if( p_module->i_usage == 0 && !p_module->b_builtin )
198         {
199             if( p_module->i_unused_delay < MODULE_HIDE_DELAY )
200             {
201                 p_module->i_unused_delay++;
202             }
203             else
204             {
205                 intf_WarnMsg( 3, "module: hiding unused plugin module `%s'",
206                               p_module->psz_name );
207                 HideModule( p_module );
208
209                 /* Break here, so that we only hide one module at a time */
210                 break;
211             }
212         }
213     }
214
215     /* We release the global lock */
216     vlc_mutex_unlock( &p_module_bank->lock );
217 #endif /* HAVE_DYNAMIC_PLUGINS */
218
219     return;
220 }
221
222 int module_NeedMemcpy( memcpy_module_t *p_memcpy )
223 {
224     p_memcpy->p_module = module_Need( MODULE_CAPABILITY_MEMCPY, NULL, NULL );
225
226     if( p_memcpy->p_module == NULL )
227     {
228         return -1;
229     }
230
231     p_memcpy->pf_memcpy = p_memcpy->p_module->p_functions->memcpy.functions.memcpy.fast_memcpy;
232
233     return 0;
234 }
235
236 void module_UnneedMemcpy( memcpy_module_t *p_memcpy )
237 {
238     module_Unneed( p_memcpy->p_module );
239 }
240
241 #if 0
242 int module_NeedIntf( intf_module_t *p_intf )
243 {
244     p_intf->p_module = module_Need( MODULE_CAPABILITY_INTF, NULL );
245
246     if( p_intf->p_module == NULL )
247     {
248         return -1;
249     }
250
251     p_intf->pf_open = p_intf->p_module->p_functions->intf.functions.intf.pf_open;
252     p_intf->pf_run = p_intf->p_module->p_functions->intf.functions.intf.pf_run;
253     p_intf->pf_close = p_intf->p_module->p_functions->intf.functions.intf.pf_close;
254
255     return 0;
256 }
257 #endif
258
259 /*****************************************************************************
260  * module_Need: return the best module function, given a capability list.
261  *****************************************************************************
262  * This function returns the module that best fits the asked capabilities.
263  *****************************************************************************/
264 module_t * module_Need( int i_capability, char *psz_name, probedata_t *p_data )
265 {
266     module_t * p_module;
267
268     /* We take the global lock */
269     vlc_mutex_lock( &p_module_bank->lock );
270
271     if( psz_name != NULL && *psz_name )
272     {
273         /* A module name was requested. Use the first matching one. */
274         int       i_index;
275         boolean_t b_ok = 0;
276
277         for( p_module = p_module_bank->first;
278              p_module != NULL;
279              p_module = p_module->next )
280         {
281             /* Test that this module can do everything we need */
282             if( !(p_module->i_capabilities & ( 1 << i_capability )) )
283             {
284                 continue;
285             }
286
287             /* Test if we have the required CPU */
288             if( (p_module->i_cpu_capabilities & p_main->i_cpu_capabilities)
289                   != p_module->i_cpu_capabilities )
290             {
291                 continue;
292             }
293
294             /* Test if this plugin exports the required shortcut */
295             for( i_index = 0;
296                  !b_ok && p_module->pp_shortcuts[i_index];
297                  i_index++ )
298             {
299                 b_ok = !strcmp( psz_name, p_module->pp_shortcuts[i_index] );
300             }
301
302             if( b_ok )
303             {
304                 break;
305             }
306         }
307
308         if( b_ok )
309         {
310             /* Open it ! */
311             LockModule( p_module );
312         }
313         else
314         {
315             intf_ErrMsg( "module error: requested %s module `%s' not found",
316                          GetCapabilityName( i_capability ), psz_name );
317         }
318     }
319     else
320     {
321         /* No module name was requested. Sort the modules and test them */
322         typedef struct module_list_s
323         {
324             struct module_s *p_module;
325             struct module_list_s* p_next;
326         } module_list_t;
327
328         int i_score = 0;
329         int i_index = 0;
330         struct module_list_s *p_list = malloc( p_module_bank->i_count
331                                                 * sizeof( module_list_t ) );
332         struct module_list_s *p_first = NULL;
333
334         /* Parse the module list for capabilities and probe each of them */
335         for( p_module = p_module_bank->first ;
336              p_module != NULL ;
337              p_module = p_module->next )
338         {
339             /* Test that this module can do everything we need */
340             if( !(p_module->i_capabilities & ( 1 << i_capability )) )
341             {
342                 continue;
343             }
344
345             /* Test if we have the required CPU */
346             if( (p_module->i_cpu_capabilities & p_main->i_cpu_capabilities)
347                   != p_module->i_cpu_capabilities )
348             {
349                 continue;
350             }
351
352             /* Test if we requested a particular intf plugin */
353 #if 0
354             if( i_capability == MODULE_CAPABILITY_INTF
355                  && p_module->psz_program != NULL
356                  && strcmp( p_module->psz_program, p_main->psz_arg0 ) )
357             {
358                 continue;
359             }
360 #endif
361
362             /* Store this new module */
363             p_list[ i_index ].p_module = p_module;
364
365             if( i_index == 0 )
366             {
367                 p_list[ i_index ].p_next = NULL;
368                 p_first = p_list;
369             }
370             else
371             {
372                 /* Ok, so at school you learned that quicksort is quick, and
373                  * bubble sort sucks raw eggs. But that's when dealing with
374                  * thousands of items. Here we have barely 50. */
375                 struct module_list_s *p_newlist = p_first;
376
377                 if( p_first->p_module->pi_score[i_capability]
378                      < p_module->pi_score[i_capability] )
379                 {
380                     p_list[ i_index ].p_next = p_first;
381                     p_first = &p_list[ i_index ];
382                 }
383                 else
384                 {
385                     while( p_newlist->p_next != NULL
386                             && p_newlist->p_next
387                                  ->p_module->pi_score[i_capability]
388                                 >= p_module->pi_score[i_capability] )
389                     {
390                         p_newlist = p_newlist->p_next;
391                     }
392
393                     p_list[ i_index ].p_next = p_newlist->p_next;
394                     p_newlist->p_next = &p_list[ i_index ];
395                 }
396             }
397
398             i_index++;
399         }
400
401         /* Parse the linked list and use the first successful module */
402         while( p_first != NULL )
403         {
404             LockModule( p_first->p_module );
405
406             /* Test the requested capability */
407             i_score += ((function_list_t *)p_first->p_module->p_functions)
408                                             [i_capability].pf_probe( p_data );
409
410             /* If the high score was broken, we have a new champion */
411             if( i_score )
412             {
413                 break;
414             }
415
416             UnlockModule( p_first->p_module );
417
418             p_first = p_first->p_next;
419         }
420
421         p_module = (p_first == NULL) ? NULL : p_first->p_module;
422         free( p_list );
423     }
424
425     /* We can release the global lock, module refcount was incremented */
426     vlc_mutex_unlock( &p_module_bank->lock );
427
428     if( p_module != NULL )
429     {
430         intf_WarnMsg( 1, "module: locking %s module `%s'",
431                          GetCapabilityName( i_capability ),
432                          p_module->psz_name );
433     }
434
435     /* Don't forget that the module is still locked if bestmodule != NULL */
436     return( p_module );
437 }
438
439 /*****************************************************************************
440  * module_Unneed: decrease the usage count of a module.
441  *****************************************************************************
442  * This function must be called by the thread that called module_Need, to
443  * decrease the reference count and allow for hiding of modules.
444  *****************************************************************************/
445 void module_Unneed( module_t * p_module )
446 {
447     /* We take the global lock */
448     vlc_mutex_lock( &p_module_bank->lock );
449
450     /* Just unlock the module - we can't do anything if it fails,
451      * so there is no need to check the return value. */
452     UnlockModule( p_module );
453
454     intf_WarnMsg( 1, "module: unlocking module `%s'", p_module->psz_name );
455
456     /* We release the global lock */
457     vlc_mutex_unlock( &p_module_bank->lock );
458
459     return;
460 }
461
462 /*****************************************************************************
463  * Following functions are local.
464  *****************************************************************************/
465
466 /*****************************************************************************
467  * AllocateAllPlugins: load all plugin modules we can find.
468  *****************************************************************************/
469 #ifdef HAVE_DYNAMIC_PLUGINS
470 static void AllocateAllPlugins( void )
471 {
472     static char * path[] = { ".", "plugins", PLUGIN_PATH, NULL, NULL };
473
474     char **         ppsz_path = path;
475     char *          psz_fullpath;
476     char *          psz_file;
477 #if defined( SYS_BEOS ) || defined( SYS_DARWIN )
478     char *          psz_vlcpath = system_GetProgramPath();
479     int             i_vlclen = strlen( psz_vlcpath );
480     boolean_t       b_notinroot;
481 #endif
482     DIR *           dir;
483     struct dirent * file;
484
485     for( ; *ppsz_path != NULL ; ppsz_path++ )
486     {
487         /* Store strlen(*ppsz_path) for later use. */
488         int i_dirlen = strlen( *ppsz_path );
489
490 #if defined( SYS_BEOS ) || defined( SYS_DARWIN )
491         b_notinroot = 0;
492         /* Under BeOS, we need to add beos_GetProgramPath() to access
493          * files under the current directory */
494         if( ( i_dirlen > 1 ) && strncmp( *ppsz_path, "/", 1 ) )
495         {
496             i_dirlen += i_vlclen + 2;
497             b_notinroot = 1;
498
499             psz_fullpath = malloc( i_dirlen );
500             if( psz_fullpath == NULL )
501             {
502                 continue;
503             }
504             sprintf( psz_fullpath, "%s/%s", psz_vlcpath, *ppsz_path );
505         }
506         else
507 #endif
508         {
509             psz_fullpath = *ppsz_path;
510         }
511
512         intf_WarnMsgImm( 1, "module: browsing `%s'", psz_fullpath );
513
514         if( (dir = opendir( psz_fullpath )) )
515         {
516             /* Parse the directory and try to load all files it contains. */
517             while( (file = readdir( dir )) )
518             {
519                 int i_filelen = strlen( file->d_name );
520
521                 /* We only load files ending with ".so" */
522                 if( i_filelen > 3
523                         && !strncmp( file->d_name + i_filelen - 3, ".so", 3 ) )
524                 {
525                     psz_file = malloc( i_dirlen + i_filelen + 2 );
526                     if( psz_file == NULL )
527                     {
528                         continue;
529                     }
530                     sprintf( psz_file, "%s/%s", psz_fullpath, file->d_name );
531
532                     /* We created a nice filename -- now we just try to load
533                      * it as a plugin module. */
534                     AllocatePluginModule( psz_file );
535
536                     /* We don't care if the allocation succeeded */
537                     free( psz_file );
538                 }
539             }
540
541             /* Close the directory if successfully opened */
542             closedir( dir );
543         }
544
545 #if defined( SYS_BEOS ) || defined( SYS_DARWIN )
546         if( b_notinroot )
547         {
548             free( psz_fullpath );
549         }
550 #endif
551     }
552 }
553
554 /*****************************************************************************
555  * AllocatePluginModule: load a module into memory and initialize it.
556  *****************************************************************************
557  * This function loads a dynamically loadable module and allocates a structure
558  * for its information data. The module can then be handled by module_Need,
559  * module_Unneed and HideModule. It can be removed by DeleteModule.
560  *****************************************************************************/
561 static int AllocatePluginModule( char * psz_filename )
562 {
563     char **pp_shortcut;
564     module_t * p_module, * p_othermodule;
565     module_handle_t handle;
566
567     /* Try to dynamically load the module. */
568     if( module_load( psz_filename, &handle ) )
569     {
570         /* The plugin module couldn't be opened */
571         intf_WarnMsgImm( 1, "module warning: cannot open %s (%s)",
572                          psz_filename, module_error() );
573         return( -1 );
574     }
575
576     /* Now that we have successfully loaded the module, we can
577      * allocate a structure for it */ 
578     p_module = malloc( sizeof( module_t ) );
579     if( p_module == NULL )
580     {
581         intf_ErrMsg( "module error: can't allocate p_module" );
582         module_unload( handle );
583         return( -1 );
584     }
585
586     /* We need to fill these since they may be needed by CallSymbol() */
587     p_module->is.plugin.psz_filename = psz_filename;
588     p_module->is.plugin.handle = handle;
589     p_module->p_symbols = &symbols;
590
591     /* Initialize the module : fill p_module->psz_name, etc. */
592     if( CallSymbol( p_module, "InitModule" MODULE_SUFFIX ) != 0 )
593     {
594         /* We couldn't call InitModule() */
595         free( p_module );
596         module_unload( handle );
597         return( -1 );
598     }
599
600     /* Check that we don't already have a module with this name */
601     for( p_othermodule = p_module_bank->first ;
602          p_othermodule != NULL ;
603          p_othermodule = p_othermodule->next )
604     {
605         if( !strcmp( p_othermodule->psz_name, p_module->psz_name ) )
606         {
607             intf_WarnMsg( 5, "module warning: cannot load %s, a module named "
608                              "`%s' already exists",
609                              psz_filename, p_module->psz_name );
610             free( p_module );
611             module_unload( handle );
612             return( -1 );
613         }
614     }
615
616     /* Activate the module : fill the capability structure, etc. */
617     if( CallSymbol( p_module, "ActivateModule" MODULE_SUFFIX ) != 0 )
618     {
619         /* We couldn't call ActivateModule() */
620         free( p_module );
621         module_unload( handle );
622         return( -1 );
623     }
624
625     for( pp_shortcut = p_module->pp_shortcuts ; *pp_shortcut ; pp_shortcut++ )
626     {
627         *pp_shortcut = strdup( *pp_shortcut );
628     }
629
630     /* We strdup() these entries so that they are still valid when the
631      * module is unloaded. */
632     p_module->is.plugin.psz_filename =
633             strdup( p_module->is.plugin.psz_filename );
634     p_module->psz_name = strdup( p_module->psz_name );
635     p_module->psz_longname = strdup( p_module->psz_longname );
636
637     if( p_module->is.plugin.psz_filename == NULL 
638             || p_module->psz_name == NULL
639             || p_module->psz_longname == NULL )
640     {
641         intf_ErrMsg( "module error: can't duplicate strings" );
642
643         free( p_module->is.plugin.psz_filename );
644         free( p_module->psz_name );
645         free( p_module->psz_longname );
646         free( p_module->psz_program );
647
648         free( p_module );
649         module_unload( handle );
650         return( -1 );
651     }
652
653     if( p_module->psz_program != NULL )
654     {
655         p_module->psz_program = strdup( p_module->psz_program );
656     }
657
658     /* Everything worked fine ! The module is ready to be added to the list. */
659     p_module->i_usage = 0;
660     p_module->i_unused_delay = 0;
661
662     p_module->b_builtin = 0;
663
664     /* Link module into the linked list */
665     if( p_module_bank->first != NULL )
666     {
667         p_module_bank->first->prev = p_module;
668     }
669     p_module->next = p_module_bank->first;
670     p_module->prev = NULL;
671     p_module_bank->first = p_module;
672     p_module_bank->i_count++;
673
674     /* Immediate message so that a slow module doesn't make the user wait */
675     intf_WarnMsgImm( 2, "module: new plugin module `%s', %s",
676                      p_module->psz_name, p_module->psz_longname );
677
678     return( 0 );
679 }
680 #endif /* HAVE_DYNAMIC_PLUGINS */
681
682 /*****************************************************************************
683  * AllocateAllBuiltins: load all modules we were built with.
684  *****************************************************************************/
685 static void AllocateAllBuiltins( void )
686 {
687     ALLOCATE_ALL_BUILTINS();
688 }
689
690 /*****************************************************************************
691  * AllocateBuiltinModule: initialize a built-in module.
692  *****************************************************************************
693  * This function registers a built-in module and allocates a structure
694  * for its information data. The module can then be handled by module_Need,
695  * module_Unneed and HideModule. It can be removed by DeleteModule.
696  *****************************************************************************/
697 static int AllocateBuiltinModule( int ( *pf_init ) ( module_t * ),
698                                   int ( *pf_activate ) ( module_t * ),
699                                   int ( *pf_deactivate ) ( module_t * ) )
700 {
701     module_t * p_module, * p_othermodule;
702
703     /* Now that we have successfully loaded the module, we can
704      * allocate a structure for it */ 
705     p_module = malloc( sizeof( module_t ) );
706     if( p_module == NULL )
707     {
708         intf_ErrMsg( "module error: can't allocate p_module" );
709         return( -1 );
710     }
711
712     /* Initialize the module : fill p_module->psz_name, etc. */
713     if( pf_init( p_module ) != 0 )
714     {
715         /* With a well-written module we shouldn't have to print an
716          * additional error message here, but just make sure. */
717         intf_ErrMsg( "module error: failed calling init in builtin module" );
718         free( p_module );
719         return( -1 );
720     }
721
722     /* Check that we don't already have a module with this name */
723     for( p_othermodule = p_module_bank->first ;
724          p_othermodule != NULL ;
725          p_othermodule = p_othermodule->next )
726     {
727         if( !strcmp( p_othermodule->psz_name, p_module->psz_name ) )
728         {
729             intf_WarnMsg( 5, "module warning: cannot load builtin `%s', a "
730                              "module named `%s' already exists",
731                              p_module->psz_name, p_module->psz_name );
732             free( p_module );
733             return( -1 );
734         }
735     }
736
737     if( pf_activate( p_module ) != 0 )
738     {
739         /* With a well-written module we shouldn't have to print an
740          * additional error message here, but just make sure. */
741         intf_ErrMsg( "module error: failed calling activate "
742                      "in builtin module" );
743         free( p_module );
744         return( -1 );
745     }
746
747     /* Everything worked fine ! The module is ready to be added to the list. */
748     p_module->i_usage = 0;
749     p_module->i_unused_delay = 0;
750
751     p_module->b_builtin = 1;
752     p_module->is.builtin.pf_deactivate = pf_deactivate;
753
754     /* Link module into the linked list */
755     if( p_module_bank->first != NULL )
756     {
757         p_module_bank->first->prev = p_module;
758     }
759     p_module->next = p_module_bank->first;
760     p_module->prev = NULL;
761     p_module_bank->first = p_module;
762     p_module_bank->i_count++;
763
764     /* Immediate message so that a slow module doesn't make the user wait */
765     intf_WarnMsgImm( 2, "module: new builtin module `%s', %s",
766                      p_module->psz_name, p_module->psz_longname );
767
768     return( 0 );
769 }
770
771 /*****************************************************************************
772  * DeleteModule: delete a module and its structure.
773  *****************************************************************************
774  * This function can only be called if i_usage <= 0.
775  *****************************************************************************/
776 static int DeleteModule( module_t * p_module )
777 {
778     /* If the module is not in use but is still in memory, we first have
779      * to hide it and remove it from memory before we can free the
780      * data structure. */
781     if( p_module->b_builtin )
782     {
783         if( p_module->i_usage != 0 )
784         {
785             intf_ErrMsg( "module error: trying to free builtin module `%s' with"
786                          " usage %i", p_module->psz_name, p_module->i_usage );
787             return( -1 );
788         }
789         else
790         {
791             /* We deactivate the module now. */
792             p_module->is.builtin.pf_deactivate( p_module );
793         }
794     }
795 #ifdef HAVE_DYNAMIC_PLUGINS
796     else
797     {
798         if( p_module->i_usage >= 1 )
799         {
800             intf_ErrMsg( "module error: trying to free module `%s' which is"
801                          " still in use", p_module->psz_name );
802             return( -1 );
803         }
804
805         /* Two possibilities here: i_usage == -1 and the module is already
806          * unloaded, we can continue, or i_usage == 0, and we have to hide
807          * the module before going on. */
808         if( p_module->i_usage == 0 )
809         {
810             if( HideModule( p_module ) != 0 )
811             {
812                 return( -1 );
813             }
814         }
815     }
816 #endif
817
818     /* Unlink the module from the linked list. */
819     if( p_module->prev != NULL )
820     {
821         p_module->prev->next = p_module->next;
822     }
823     else
824     {
825         p_module_bank->first = p_module->next;
826     }
827
828     if( p_module->next != NULL )
829     {
830         p_module->next->prev = p_module->prev;
831     }
832
833     p_module_bank->i_count--;
834
835     /* We free the structures that we strdup()ed in Allocate*Module(). */
836 #ifdef HAVE_DYNAMIC_PLUGINS
837     if( !p_module->b_builtin )
838     {
839         char **pp_shortcut = p_module->pp_shortcuts;
840
841         for( ; *pp_shortcut ; pp_shortcut++ )
842         {
843             free( *pp_shortcut );
844         }
845
846         free( p_module->is.plugin.psz_filename );
847         free( p_module->psz_name );
848         free( p_module->psz_longname );
849         free( p_module->psz_program );
850     }
851 #endif
852
853     free( p_module );
854
855     return( 0 );
856 }
857
858 /*****************************************************************************
859  * LockModule: increase the usage count of a module and load it if needed.
860  *****************************************************************************
861  * This function has to be called before a thread starts using a module. If
862  * the module is already loaded, we just increase its usage count. If it isn't
863  * loaded, we have to dynamically open it and initialize it.
864  * If you successfully call LockModule() at any moment, be careful to call
865  * UnlockModule() when you don't need it anymore.
866  *****************************************************************************/
867 static int LockModule( module_t * p_module )
868 {
869     if( p_module->i_usage >= 0 )
870     {
871         /* This module is already loaded and activated, we can return */
872         p_module->i_usage++;
873         return( 0 );
874     }
875
876     if( p_module->b_builtin )
877     {
878         /* A built-in module should always have a refcount >= 0 ! */
879         intf_ErrMsg( "module error: built-in module `%s' has refcount %i",
880                      p_module->psz_name, p_module->i_usage );
881         return( -1 );
882     }
883
884 #ifdef HAVE_DYNAMIC_PLUGINS
885     if( p_module->i_usage != -1 )
886     {
887         /* This shouldn't happen. Ever. We have serious problems here. */
888         intf_ErrMsg( "module error: plugin module `%s' has refcount %i",
889                      p_module->psz_name, p_module->i_usage );
890         return( -1 );
891     }
892
893     /* i_usage == -1, which means that the module isn't in memory */
894     if( module_load( p_module->is.plugin.psz_filename,
895                      &p_module->is.plugin.handle ) )
896     {
897         /* The plugin module couldn't be opened */
898         intf_ErrMsg( "module error: cannot open %s (%s)",
899                      p_module->is.plugin.psz_filename, module_error() );
900         return( -1 );
901     }
902
903     /* FIXME: what to do if the guy modified the plugin while it was
904      * unloaded ? It makes XMMS crash nastily, perhaps we should try
905      * to be a bit more clever here. */
906
907     /* Activate the module : fill the capability structure, etc. */
908     if( CallSymbol( p_module, "ActivateModule" MODULE_SUFFIX ) != 0 )
909     {
910         /* We couldn't call ActivateModule() -- looks nasty, but
911          * we can't do much about it. Just try to unload module. */
912         module_unload( p_module->is.plugin.handle );
913         p_module->i_usage = -1;
914         return( -1 );
915     }
916
917     /* Everything worked fine ! The module is ready to be used */
918     p_module->i_usage = 1;
919 #endif /* HAVE_DYNAMIC_PLUGINS */
920
921     return( 0 );
922 }
923
924 /*****************************************************************************
925  * UnlockModule: decrease the usage count of a module.
926  *****************************************************************************
927  * We decrease the usage count of a module so that we know when a module
928  * becomes unused and can be hidden.
929  *****************************************************************************/
930 static int UnlockModule( module_t * p_module )
931 {
932     if( p_module->i_usage <= 0 )
933     {
934         /* This shouldn't happen. Ever. We have serious problems here. */
935         intf_ErrMsg( "module error: trying to call module_Unneed() on `%s'"
936                      " which isn't even in use", p_module->psz_name );
937         return( -1 );
938     }
939
940     /* This module is still in use, we can return */
941     p_module->i_usage--;
942     p_module->i_unused_delay = 0;
943
944     return( 0 );
945 }
946
947 #ifdef HAVE_DYNAMIC_PLUGINS
948 /*****************************************************************************
949  * HideModule: remove a module from memory but keep its structure.
950  *****************************************************************************
951  * This function can only be called if i_usage == 0. It will make a call
952  * to the module's inner DeactivateModule() symbol, and then unload it
953  * from memory. A call to module_Need() will automagically load it again.
954  *****************************************************************************/
955 static int HideModule( module_t * p_module )
956 {
957     if( p_module->b_builtin )
958     {
959         /* A built-in module should never be hidden. */
960         intf_ErrMsg( "module error: trying to hide built-in module `%s'",
961                      p_module->psz_name );
962         return( -1 );
963     }
964
965     if( p_module->i_usage >= 1 )
966     {
967         intf_ErrMsg( "module error: trying to hide module `%s' which is still"
968                      " in use", p_module->psz_name );
969         return( -1 );
970     }
971
972     if( p_module->i_usage <= -1 )
973     {
974         intf_ErrMsg( "module error: trying to hide module `%s' which is already"
975                      " hidden", p_module->psz_name );
976         return( -1 );
977     }
978
979     /* Deactivate the module : free the capability structure, etc. */
980     if( CallSymbol( p_module, "DeactivateModule" MODULE_SUFFIX ) != 0 )
981     {
982         /* We couldn't call DeactivateModule() -- looks nasty, but
983          * we can't do much about it. Just try to unload module anyway. */
984         module_unload( p_module->is.plugin.handle );
985         p_module->i_usage = -1;
986         return( -1 );
987     }
988
989     /* Everything worked fine, we can safely unload the module. */
990     module_unload( p_module->is.plugin.handle );
991     p_module->i_usage = -1;
992
993     return( 0 );
994 }
995
996 /*****************************************************************************
997  * CallSymbol: calls a module symbol.
998  *****************************************************************************
999  * This function calls a symbol given its name and a module structure. The
1000  * symbol MUST refer to a function returning int and taking a module_t* as
1001  * an argument.
1002  *****************************************************************************/
1003 static int CallSymbol( module_t * p_module, char * psz_name )
1004 {
1005     int (* pf_symbol) ( module_t * p_module );
1006
1007     /* Try to resolve the symbol */
1008     pf_symbol = module_getsymbol( p_module->is.plugin.handle, psz_name );
1009
1010     if( pf_symbol == NULL )
1011     {
1012         /* We couldn't load the symbol */
1013         intf_WarnMsg( 1, "module warning: "
1014                          "cannot find symbol %s in module %s (%s)",
1015                          psz_name, p_module->is.plugin.psz_filename,
1016                          module_error() );
1017         return( -1 );
1018     }
1019
1020     /* We can now try to call the symbol */
1021     if( pf_symbol( p_module ) != 0 )
1022     {
1023         /* With a well-written module we shouldn't have to print an
1024          * additional error message here, but just make sure. */
1025         intf_ErrMsg( "module error: failed calling symbol %s in module %s",
1026                      psz_name, p_module->is.plugin.psz_filename );
1027         return( -1 );
1028     }
1029
1030     /* Everything worked fine, we can return */
1031     return( 0 );
1032 }
1033 #endif /* HAVE_DYNAMIC_PLUGINS */
1034