1 /*****************************************************************************
2 * modules.c : Built-in and dynamic modules management functions
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
6 * Authors: Samuel Hocevar <sam@zoy.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
26 #include <stdlib.h> /* free(), strtol() */
27 #include <stdio.h> /* sprintf() */
28 #include <string.h> /* strerror() */
29 #include <errno.h> /* ENOMEM */
30 #include <sys/types.h> /* open */
33 #include <unistd.h> /* close */
35 #if defined(HAVE_DLFCN_H) /* Linux, BSD, Hurd */
36 #include <dlfcn.h> /* dlopen(), dlsym(), dlclose() */
38 #elif defined(HAVE_IMAGE_H) /* BeOS */
42 /* FIXME: this isn't supposed to be an error */
43 #error no dynamic plugins available on your system !
47 #include "beos_specific.h"
55 #include "modules_core.h"
57 /* Local prototypes */
58 static int AllocateDynModule( module_bank_t * p_bank, char * psz_filename );
59 static int HideModule( module_t * p_module );
60 static int FreeModule( module_bank_t * p_bank, module_t * p_module );
61 static int CallSymbol( module_t * p_module, char * psz_name );
63 /*****************************************************************************
64 * module_InitBank: create the module bank.
65 *****************************************************************************
66 * This function creates a module bank structure and fills it with the
67 * built-in modules, as well as all the dynamic modules it can find.
68 *****************************************************************************/
69 module_bank_t * module_InitBank( void )
71 module_bank_t * p_bank;
73 intf_ErrMsg( "FIXME: module_InitBank unimplemented" );
74 p_bank = malloc( sizeof( module_bank_t ) );
79 /*****************************************************************************
80 * module_DestroyBank: destroy the module bank.
81 *****************************************************************************
82 * This function unloads all unused dynamic modules and removes the module
83 * bank in case of success.
84 *****************************************************************************/
85 int module_DestroyBank( module_bank_t * p_bank )
87 intf_ErrMsg( "FIXME: module_DestroyBank unimplemented" );
91 /*****************************************************************************
92 * module_ResetBank: reset the module bank.
93 *****************************************************************************
94 * This function resets the plugin bank by unloading all unused dynamic
96 *****************************************************************************/
97 int module_ResetBank( module_bank_t * p_bank )
99 intf_ErrMsg( "FIXME: module_ResetBank unimplemented" );
103 /*****************************************************************************
104 * module_ManageBank: manage the module bank.
105 *****************************************************************************
106 * This function parses the module bank and hides modules that have been
107 * unused for a while.
108 *****************************************************************************/
109 void module_ManageBank( module_bank_t * p_bank )
113 /* We take the global lock */
114 vlc_mutex_lock( &p_bank->lock );
116 /* Parse the module list to see if any modules need to be unloaded */
117 for( p_module = p_bank->first ;
119 p_module = p_module->next )
121 /* If the module is unused and if it is a dynamic module... */
122 if( p_module->i_usage == 0 && !p_module->b_builtin )
124 if( p_module->i_unused_delay < MODULE_HIDE_DELAY )
126 p_module->i_unused_delay++;
130 intf_Msg( "hiding unused module %s", p_module->psz_name );
131 HideModule( p_module );
136 /* We release the global lock */
137 vlc_mutex_lock( &p_bank->lock );
142 /*****************************************************************************
143 * module_Need: increase the usage count of a module and load it if needed.
144 *****************************************************************************
145 * This function has to be called before a thread starts using a module. If
146 * the module is already loaded, we just increase its usage count. If it isn't
147 * loaded, we have to dynamically open it and initialize it.
148 * If you successfully call module_Need() at any moment, be careful to call
149 * module_Unneed() when you don't need it anymore.
150 *****************************************************************************/
151 int module_Need( module_t * p_module )
153 if( p_module->i_usage >= 0 )
155 /* This module is already loaded and activated, we can return */
160 if( p_module->b_builtin )
162 /* A built-in module should always have a refcount >= 0 ! */
163 intf_ErrMsg( "module error: built-in module %s has refcount %i",
164 p_module->psz_name, p_module->i_usage );
168 if( p_module->i_usage != -1 )
170 /* This shouldn't happen. Ever. We have serious problems here. */
171 intf_ErrMsg( "module error: dynamic module %s has refcount %i",
172 p_module->psz_name, p_module->i_usage );
176 /* i_usage == -1, which means that the module isn't in memory */
177 if( ! module_load( p_module->psz_filename, &p_module->handle ) )
179 /* The dynamic module couldn't be opened */
180 intf_ErrMsg( "module error: cannot open %s (%s)",
181 p_module->psz_filename, module_error() );
185 if( CallSymbol( p_module, "ActivateModule" ) != 0 )
187 /* We couldn't call ActivateModule() -- looks nasty, but
188 * we can't do much about it. Just try to unload module. */
189 module_unload( p_module->handle );
190 p_module->i_usage = -1;
194 /* Everything worked fine ! The module is ready to be used */
195 p_module->i_usage = 1;
200 /*****************************************************************************
201 * module_Unneed: decrease the usage count of a module.
202 *****************************************************************************
203 * This function has to be called before a thread starts using a module. If
204 * the module is already loaded, we just increase its usage count. If it isn't
205 * loaded, we have to dynamically open it and initialize it.
206 * If you successfully call module_Need() at any moment, be careful to call
207 * module_Unneed() when you don't need it anymore.
208 *****************************************************************************/
209 int module_Unneed( module_t * p_module )
211 if( p_module->i_usage <= 0 )
213 /* This shouldn't happen. Ever. We have serious problems here. */
214 intf_ErrMsg( "module error: trying to call module_Unneed() on %s"
215 " which isn't even in use", p_module->psz_name );
219 /* This module is still in use, we can return */
221 p_module->i_unused_delay = 0;
226 /*****************************************************************************
227 * Following functions are local.
228 *****************************************************************************/
230 /*****************************************************************************
231 * AllocateDynModule: load a module into memory and initialize it.
232 *****************************************************************************
233 * This function loads a dynamically loadable module and allocates a structure
234 * for its information data. The module can then be handled by module_Need,
235 * module_Unneed and HideModule. It can be removed by FreeModule.
236 *****************************************************************************/
237 static int AllocateDynModule( module_bank_t * p_bank, char * psz_filename )
240 module_handle_t handle;
242 /* Try to dynamically load the module. */
243 if( ! module_load( psz_filename, &handle ) )
245 /* The dynamic module couldn't be opened */
246 intf_ErrMsg( "module error: cannot open %s (%s)",
247 psz_filename, module_error() );
251 /* Now that we have successfully loaded the module, we can
252 * allocate a structure for it */
253 p_module = malloc( sizeof( module_t ) );
254 if( p_module == NULL )
256 intf_ErrMsg( "module error: can't allocate p_module" );
257 module_unload( handle );
261 /* We need to fill these since they may be needed by CallSymbol() */
262 p_module->psz_filename = psz_filename;
263 p_module->handle = handle;
265 if( CallSymbol( p_module, "InitModule" ) != 0 )
267 /* We couldn't call InitModule() */
269 module_unload( handle );
273 if( CallSymbol( p_module, "ActivateModule" ) != 0 )
275 /* We couldn't call ActivateModule() */
277 module_unload( handle );
281 /* We strdup() these entries so that they are still valid when the
282 * module is unloaded. */
283 p_module->psz_filename = strdup( p_module->psz_filename );
284 p_module->psz_name = strdup( p_module->psz_name );
285 p_module->psz_longname = strdup( p_module->psz_longname );
286 p_module->psz_version = strdup( p_module->psz_version );
287 if( p_module->psz_filename == NULL
288 || p_module->psz_name == NULL
289 || p_module->psz_longname == NULL
290 || p_module->psz_version == NULL )
292 intf_ErrMsg( "module error: can't duplicate strings" );
293 free( p_module->psz_filename );
294 free( p_module->psz_name );
295 free( p_module->psz_longname );
296 free( p_module->psz_version );
298 module_unload( handle );
302 /* Everything worked fine ! The module is ready to be added to the list. */
303 p_module->i_usage = 0;
304 p_module->i_unused_delay = 0;
306 p_module->b_builtin = 0;
308 /* Link module across linked list */
309 if( p_bank->first != NULL )
311 p_bank->first->prev = p_module;
313 p_module->next = p_bank->first;
314 p_bank->first = p_module;
319 /*****************************************************************************
320 * HideModule: remove a module from memory but keep its structure.
321 *****************************************************************************
322 * This function can only be called if i_usage == 0. It will make a call
323 * to the module's inner DeactivateModule() symbol, and then unload it
324 * from memory. A call to module_Need() will automagically load it again.
325 *****************************************************************************/
326 static int HideModule( module_t * p_module )
328 if( p_module->b_builtin )
330 /* A built-in module should never be hidden. */
331 intf_ErrMsg( "module error: trying to hide built-in module %s",
332 p_module->psz_name );
336 if( p_module->i_usage >= 1 )
338 intf_ErrMsg( "module error: trying to hide module %s which is still"
339 " in use", p_module->psz_name );
343 if( p_module->i_usage <= -1 )
345 intf_ErrMsg( "module error: trying to hide module %s which is already"
346 " hidden", p_module->psz_name );
350 if( CallSymbol( p_module, "DeactivateModule" ) != 0 )
352 /* We couldn't call DeactivateModule() -- looks nasty, but
353 * we can't do much about it. Just try to unload module anyway. */
354 module_unload( p_module->handle );
355 p_module->i_usage = -1;
359 /* Everything worked fine, we can safely unload the module. */
360 module_unload( p_module->handle );
361 p_module->i_usage = -1;
366 /*****************************************************************************
367 * FreeModule: delete a module and its structure.
368 *****************************************************************************
369 * This function can only be called if i_usage <= 0.
370 *****************************************************************************/
371 static int FreeModule( module_bank_t * p_bank, module_t * p_module )
373 /* If the module is not in use but is still in memory, we first have
374 * to hide it and remove it from memory before we can free the
376 if( p_module->b_builtin )
378 if( p_module->i_usage != 0 )
380 intf_ErrMsg( "module error: trying to free builtin module %s with"
381 " usage %i", p_module->psz_name, p_module->i_usage );
387 if( p_module->i_usage >= 1 )
389 intf_ErrMsg( "module error: trying to free module %s which is"
390 " still in use", p_module->psz_name );
394 /* Two possibilities here: i_usage == -1 and the module is already
395 * unloaded, we can continue, or i_usage == 0, and we have to hide
396 * the module before going on. */
397 if( p_module->i_usage == 0 )
399 if( HideModule( p_module ) != 0 )
406 /* Unlink the module from the linked list. */
407 if( p_module == p_bank->first )
409 p_bank->first = p_module->next;
412 if( p_module->prev != NULL )
414 p_module->prev->next = p_module->next;
417 if( p_module->next != NULL )
419 p_module->next->prev = p_module->prev;
422 /* We free the structures that we strdup()ed in Allocate*Module(). */
423 free( p_module->psz_filename );
424 free( p_module->psz_name );
425 free( p_module->psz_longname );
426 free( p_module->psz_version );
433 /*****************************************************************************
434 * CallSymbol: calls a module symbol.
435 *****************************************************************************
436 * This function calls a symbol given its name and a module structure. The
437 * symbol MUST refer to a function returning int and taking a module_t* as
439 *****************************************************************************/
440 static int CallSymbol( module_t * p_module, char * psz_name )
442 typedef int ( symbol_t ) ( module_t * p_module );
445 /* Try to resolve the symbol */
446 p_symbol = module_getsymbol( p_module->handle, psz_name );
450 /* We couldn't load the symbol */
451 intf_ErrMsg( "module error: cannot find %s in module %s (%s)",
452 psz_name, p_module->psz_filename, module_error() );
456 /* We can now try to call the symbol */
457 if( p_symbol( p_module ) != 0 )
459 /* With a well-written module we shouldn't have to print an
460 * additional error message here, but just make sure. */
461 intf_ErrMsg( "module error: failed calling %s in module %s",
462 psz_name, p_module->psz_filename );
466 /* Everything worked fine, we can return */