]> git.sesse.net Git - vlc/blob - src/misc/modules.c
d684b24c9ee7932f4e99b25226722486b55131e7
[vlc] / src / misc / modules.c
1 /*****************************************************************************
2  * modules.c : Built-in and dynamic modules management functions
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  *
6  * Authors: Samuel Hocevar <sam@zoy.org>
7  *          Ethan C. Baldridge <BaldridgeE@cadmus.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23 #include "defs.h"
24
25 #include "config.h"
26
27 #include <stdlib.h>                                      /* free(), strtol() */
28 #include <stdio.h>                                              /* sprintf() */
29 #include <string.h>                                              /* strdup() */
30 #include <dirent.h>
31
32 #if defined(HAVE_DLFCN_H)                                /* Linux, BSD, Hurd */
33 #include <dlfcn.h>                           /* dlopen(), dlsym(), dlclose() */
34
35 #elif defined(HAVE_IMAGE_H)                                          /* BeOS */
36 #include <image.h>
37
38 #else
39 /* FIXME: this isn't supposed to be an error */
40 #error no dynamic plugins available on your system !
41 #endif
42
43 #ifdef SYS_BEOS
44 #include "beos_specific.h"
45 #endif
46
47 #include "common.h"
48 #include "threads.h"
49
50 #include "intf_msg.h"
51 #include "modules.h"
52 #include "modules_core.h"
53
54 /* Local prototypes */
55 static int AllocateDynModule( module_bank_t * p_bank, char * psz_filename );
56 static int HideModule( module_t * p_module );
57 static int FreeModule( module_bank_t * p_bank, module_t * p_module );
58 static int CallSymbol( module_t * p_module, char * psz_name );
59
60 /*****************************************************************************
61  * module_CreateBank: create the module bank.
62  *****************************************************************************
63  * This function creates a module bank structure.
64  *****************************************************************************/
65 module_bank_t * module_CreateBank( void )
66 {
67     module_bank_t * p_bank;
68
69     p_bank = malloc( sizeof( module_bank_t ) );
70
71     return( p_bank );
72 }
73
74 /*****************************************************************************
75  * module_InitBank: create the module bank.
76  *****************************************************************************
77  * This function creates a module bank structure and fills it with the
78  * built-in modules, as well as all the dynamic modules it can find.
79  *****************************************************************************/
80 void module_InitBank( module_bank_t * p_bank )
81 {
82     static char * path[] = { ".", "lib", PLUGIN_PATH, NULL } ;
83
84     char **         ppsz_path = path;
85     char *          psz_file;
86 #ifdef SYS_BEOS
87     char *          psz_program_path = beos_GetProgramPath();
88     int             i_programlen = strlen( psz_program_path );
89 #endif
90     DIR *           dir;
91     struct dirent * file;
92
93     p_bank->first = NULL;
94     vlc_mutex_init( &p_bank->lock );
95
96     intf_Msg( "module: module bank initialized" );
97
98     for( ; *ppsz_path != NULL ; ppsz_path++ )
99     {
100         if( (dir = opendir( *ppsz_path )) )
101         {
102             /* Store strlen(*ppsz_path) for later use. */
103             int i_dirlen = strlen( *ppsz_path );
104
105             /* Parse the directory and try to load all files it contains. */
106             while( (file = readdir( dir )) )
107             {
108                 if( memcmp( file->d_name, ".", 1 ) )
109                 {
110 #ifdef SYS_BEOS
111                     /* Under BeOS, we need to add beos_GetProgramPath() to
112                      * access files under the current directory */
113                     if( memcmp( file->d_name, "/", 1 ) )
114                     {
115                         psz_file = malloc( i_programlen + i_dirlen
116                                                + strlen( file->d_name ) + 3 );
117                         if( psz_file == NULL )
118                         {
119                             continue;
120                         }
121                         sprintf( psz_file, "%s/%s/%s", psz_programlen,
122                                  *ppsz_path, file->d_name );
123                     }
124                     else
125 #endif
126                     {
127                         psz_file = malloc( i_dirlen
128                                                + strlen( file->d_name ) + 2 );
129                         if( psz_file == NULL )
130                         {
131                             continue;
132                         }
133                         sprintf( psz_file, "%s/%s", *ppsz_path, file->d_name );
134                     }
135
136                     /* We created a nice filename -- now we just try to load
137                      * it as a dynamic module. */
138                     AllocateDynModule( p_bank, psz_file );
139
140                     /* We don't care if the allocation succeeded */
141                     free( psz_file );
142                 }
143             }
144         }
145     }
146
147     return;
148 }
149
150 /*****************************************************************************
151  * module_DestroyBank: destroy the module bank.
152  *****************************************************************************
153  * This function unloads all unused dynamic modules and removes the module
154  * bank in case of success.
155  *****************************************************************************/
156 void module_DestroyBank( module_bank_t * p_bank )
157 {
158     module_t * p_next;
159
160     while( p_bank->first != NULL )
161     {
162         if( FreeModule( p_bank, p_bank->first ) )
163         {
164             /* Module deletion failed */
165             intf_ErrMsg( "module error: `%s' can't be removed. trying harder.",
166                          p_bank->first->psz_name );
167
168             /* We just free the module by hand. Niahahahahaha. */
169             p_next = p_bank->first->next;
170             free(p_bank->first);
171             p_bank->first = p_next;
172         }
173     }
174
175     /* We can free the module bank */
176     free( p_bank );
177
178     return;
179 }
180
181 /*****************************************************************************
182  * module_ResetBank: reset the module bank.
183  *****************************************************************************
184  * This function resets the module bank by unloading all unused dynamic
185  * modules.
186  *****************************************************************************/
187 void module_ResetBank( module_bank_t * p_bank )
188 {
189     intf_ErrMsg( "FIXME: module_ResetBank unimplemented" );
190     return;
191 }
192
193 /*****************************************************************************
194  * module_ManageBank: manage the module bank.
195  *****************************************************************************
196  * This function parses the module bank and hides modules that have been
197  * unused for a while.
198  *****************************************************************************/
199 void module_ManageBank( module_bank_t * p_bank )
200 {
201     module_t * p_module;
202
203     /* We take the global lock */
204     vlc_mutex_lock( &p_bank->lock );
205
206     /* Parse the module list to see if any modules need to be unloaded */
207     for( p_module = p_bank->first ;
208          p_module != NULL ;
209          p_module = p_module->next )
210     {
211         /* If the module is unused and if it is a dynamic module... */
212         if( p_module->i_usage == 0 && !p_module->b_builtin )
213         {
214             if( p_module->i_unused_delay < MODULE_HIDE_DELAY )
215             {
216                 p_module->i_unused_delay++;
217             }
218             else
219             {
220                 intf_Msg( "module: hiding unused module `%s'",
221                           p_module->psz_name );
222                 HideModule( p_module );
223             }
224         }
225     }
226
227     /* We release the global lock */
228     vlc_mutex_unlock( &p_bank->lock );
229
230     return;
231 }
232
233 /*****************************************************************************
234  * module_Need: increase the usage count of a module and load it if needed.
235  *****************************************************************************
236  * This function has to be called before a thread starts using a module. If
237  * the module is already loaded, we just increase its usage count. If it isn't
238  * loaded, we have to dynamically open it and initialize it.
239  * If you successfully call module_Need() at any moment, be careful to call
240  * module_Unneed() when you don't need it anymore.
241  *****************************************************************************/
242 int module_Need( module_t * p_module )
243 {
244     if( p_module->i_usage >= 0 )
245     {
246         /* This module is already loaded and activated, we can return */
247         p_module->i_usage++;
248         return( 0 );
249     }
250
251     if( p_module->b_builtin )
252     {
253         /* A built-in module should always have a refcount >= 0 ! */
254         intf_ErrMsg( "module error: built-in module `%s' has refcount %i",
255                      p_module->psz_name, p_module->i_usage );
256         return( -1 );
257     }
258
259     if( p_module->i_usage != -1 )
260     {
261         /* This shouldn't happen. Ever. We have serious problems here. */
262         intf_ErrMsg( "module error: dynamic module `%s' has refcount %i",
263                      p_module->psz_name, p_module->i_usage );
264         return( -1 );
265     }
266
267     /* i_usage == -1, which means that the module isn't in memory */
268     if( ! module_load( p_module->psz_filename, &p_module->handle ) )
269     {
270         /* The dynamic module couldn't be opened */
271         intf_ErrMsg( "module error: cannot open %s (%s)",
272                      p_module->psz_filename, module_error() );
273         return( -1 );
274     }
275
276     if( CallSymbol( p_module, "ActivateModule" ) != 0 )
277     {
278         /* We couldn't call ActivateModule() -- looks nasty, but
279          * we can't do much about it. Just try to unload module. */
280         module_unload( p_module->handle );
281         p_module->i_usage = -1;
282         return( -1 );
283     }
284
285     /* Everything worked fine ! The module is ready to be used */
286     p_module->i_usage = 1;
287
288     return( 0 );
289 }
290
291 /*****************************************************************************
292  * module_Unneed: decrease the usage count of a module.
293  *****************************************************************************
294  * This function has to be called before a thread starts using a module. If
295  * the module is already loaded, we just increase its usage count. If it isn't
296  * loaded, we have to dynamically open it and initialize it.
297  * If you successfully call module_Need() at any moment, be careful to call
298  * module_Unneed() when you don't need it anymore.
299  *****************************************************************************/
300 int module_Unneed( module_t * p_module )
301 {
302     if( p_module->i_usage <= 0 )
303     {
304         /* This shouldn't happen. Ever. We have serious problems here. */
305         intf_ErrMsg( "module error: trying to call module_Unneed() on `%s'"
306                      " which isn't even in use", p_module->psz_name );
307         return( -1 );
308     }
309
310     /* This module is still in use, we can return */
311     p_module->i_usage--;
312     p_module->i_unused_delay = 0;
313
314     return( 0 );
315 }
316
317 /*****************************************************************************
318  * Following functions are local.
319  *****************************************************************************/
320
321 /*****************************************************************************
322  * AllocateDynModule: load a module into memory and initialize it.
323  *****************************************************************************
324  * This function loads a dynamically loadable module and allocates a structure
325  * for its information data. The module can then be handled by module_Need,
326  * module_Unneed and HideModule. It can be removed by FreeModule.
327  *****************************************************************************/
328 static int AllocateDynModule( module_bank_t * p_bank, char * psz_filename )
329 {
330     module_t * p_module;
331     module_handle_t handle;
332
333     /* Try to dynamically load the module. */
334     if( ! module_load( psz_filename, &handle ) )
335     {
336         /* The dynamic module couldn't be opened */
337         intf_DbgMsg( "module error: cannot open %s (%s)",
338                      psz_filename, module_error() );
339         return( -1 );
340     }
341
342     /* Now that we have successfully loaded the module, we can
343      * allocate a structure for it */ 
344     p_module = malloc( sizeof( module_t ) );
345     if( p_module == NULL )
346     {
347         intf_ErrMsg( "module error: can't allocate p_module" );
348         module_unload( handle );
349         return( -1 );
350     }
351
352     /* We need to fill these since they may be needed by CallSymbol() */
353     p_module->psz_filename = psz_filename;
354     p_module->handle = handle;
355
356     if( CallSymbol( p_module, "InitModule" ) != 0 )
357     {
358         /* We couldn't call InitModule() */
359         free( p_module );
360         module_unload( handle );
361         return( -1 );
362     }
363
364     if( CallSymbol( p_module, "ActivateModule" ) != 0 )
365     {
366         /* We couldn't call ActivateModule() */
367         free( p_module );
368         module_unload( handle );
369         return( -1 );
370     }
371
372     /* We strdup() these entries so that they are still valid when the
373      * module is unloaded. */
374     p_module->psz_filename = strdup( p_module->psz_filename );
375     p_module->psz_name = strdup( p_module->psz_name );
376     p_module->psz_longname = strdup( p_module->psz_longname );
377     p_module->psz_version = strdup( p_module->psz_version );
378     if( p_module->psz_filename == NULL 
379             || p_module->psz_name == NULL
380             || p_module->psz_longname == NULL
381             || p_module->psz_version == NULL )
382     {
383         intf_ErrMsg( "module error: can't duplicate strings" );
384         free( p_module->psz_filename );
385         free( p_module->psz_name );
386         free( p_module->psz_longname );
387         free( p_module->psz_version );
388         free( p_module );
389         module_unload( handle );
390         return( -1 );
391     }
392
393     /* Everything worked fine ! The module is ready to be added to the list. */
394     p_module->i_usage = 0;
395     p_module->i_unused_delay = 0;
396
397     p_module->b_builtin = 0;
398
399     /* Link module into the linked list */
400     if( p_bank->first != NULL )
401     {
402         p_bank->first->prev = p_module;
403     }
404     p_module->next = p_bank->first;
405     p_module->prev = NULL;
406     p_bank->first = p_module;
407
408     intf_Msg( "module: dynamic module `%s', %s",
409               p_module->psz_name, p_module->psz_longname );
410
411     return( 0 );
412 }
413
414 /*****************************************************************************
415  * HideModule: remove a module from memory but keep its structure.
416  *****************************************************************************
417  * This function can only be called if i_usage == 0. It will make a call
418  * to the module's inner DeactivateModule() symbol, and then unload it
419  * from memory. A call to module_Need() will automagically load it again.
420  *****************************************************************************/
421 static int HideModule( module_t * p_module )
422 {
423     if( p_module->b_builtin )
424     {
425         /* A built-in module should never be hidden. */
426         intf_ErrMsg( "module error: trying to hide built-in module `%s'",
427                      p_module->psz_name );
428         return( -1 );
429     }
430
431     if( p_module->i_usage >= 1 )
432     {
433         intf_ErrMsg( "module error: trying to hide module `%s' which is still"
434                      " in use", p_module->psz_name );
435         return( -1 );
436     }
437
438     if( p_module->i_usage <= -1 )
439     {
440         intf_ErrMsg( "module error: trying to hide module `%s' which is already"
441                      " hidden", p_module->psz_name );
442         return( -1 );
443     }
444
445     if( CallSymbol( p_module, "DeactivateModule" ) != 0 )
446     {
447         /* We couldn't call DeactivateModule() -- looks nasty, but
448          * we can't do much about it. Just try to unload module anyway. */
449         module_unload( p_module->handle );
450         p_module->i_usage = -1;
451         return( -1 );
452     }
453
454     /* Everything worked fine, we can safely unload the module. */
455     module_unload( p_module->handle );
456     p_module->i_usage = -1;
457
458     return( 0 );
459 }
460
461 /*****************************************************************************
462  * FreeModule: delete a module and its structure.
463  *****************************************************************************
464  * This function can only be called if i_usage <= 0.
465  *****************************************************************************/
466 static int FreeModule( module_bank_t * p_bank, module_t * p_module )
467 {
468     /* If the module is not in use but is still in memory, we first have
469      * to hide it and remove it from memory before we can free the
470      * data structure. */
471     if( p_module->b_builtin )
472     {
473         if( p_module->i_usage != 0 )
474         {
475             intf_ErrMsg( "module error: trying to free builtin module `%s' with"
476                          " usage %i", p_module->psz_name, p_module->i_usage );
477             return( -1 );
478         }
479     }
480     else
481     {
482         if( p_module->i_usage >= 1 )
483         {
484             intf_ErrMsg( "module error: trying to free module `%s' which is"
485                          " still in use", p_module->psz_name );
486             return( -1 );
487         }
488
489         /* Two possibilities here: i_usage == -1 and the module is already
490          * unloaded, we can continue, or i_usage == 0, and we have to hide
491          * the module before going on. */
492         if( p_module->i_usage == 0 )
493         {
494             if( HideModule( p_module ) != 0 )
495             {
496                 return( -1 );
497             }
498         }
499     }
500
501     /* Unlink the module from the linked list. */
502     if( p_module == p_bank->first )
503     {
504         p_bank->first = p_module->next;
505     }
506
507     if( p_module->prev != NULL )
508     {
509         p_module->prev->next = p_module->next;
510     }
511
512     if( p_module->next != NULL )
513     {
514         p_module->next->prev = p_module->prev;
515     }
516
517     /* We free the structures that we strdup()ed in Allocate*Module(). */
518     free( p_module->psz_filename );
519     free( p_module->psz_name );
520     free( p_module->psz_longname );
521     free( p_module->psz_version );
522
523     free( p_module );
524
525     return( 0 );
526 }
527
528 /*****************************************************************************
529  * CallSymbol: calls a module symbol.
530  *****************************************************************************
531  * This function calls a symbol given its name and a module structure. The
532  * symbol MUST refer to a function returning int and taking a module_t* as
533  * an argument.
534  *****************************************************************************/
535 static int CallSymbol( module_t * p_module, char * psz_name )
536 {
537     typedef int ( symbol_t ) ( module_t * p_module );
538     symbol_t * p_symbol;
539
540     /* Try to resolve the symbol */
541     p_symbol = module_getsymbol( p_module->handle, psz_name );
542
543     if( !p_symbol )
544     {
545         /* We couldn't load the symbol */
546         intf_DbgMsg( "module warning: cannot find symbol %s in module %s (%s)",
547                      psz_name, p_module->psz_filename, module_error() );
548         return( -1 );
549     }
550
551     /* We can now try to call the symbol */
552     if( p_symbol( p_module ) != 0 )
553     {
554         /* With a well-written module we shouldn't have to print an
555          * additional error message here, but just make sure. */
556         intf_ErrMsg( "module error: failed calling symbol %s in module %s",
557                      psz_name, p_module->psz_filename );
558         return( -1 );
559     }
560
561     /* Everything worked fine, we can return */
562     return( 0 );
563 }
564