1 /*****************************************************************************
2 * modules.c : Builtin and plugin modules management functions
3 *****************************************************************************
4 * Copyright (C) 2001-2004 VideoLAN
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>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
25 *****************************************************************************/
27 /* Some faulty libcs have a broken struct dirent when _FILE_OFFSET_BITS
28 * is set to 64. Don't try to be cleverer. */
29 #ifdef _FILE_OFFSET_BITS
30 #undef _FILE_OFFSET_BITS
33 #include <stdlib.h> /* free(), strtol() */
34 #include <stdio.h> /* sprintf() */
35 #include <string.h> /* strdup() */
38 #include <vlc/input.h>
42 #elif defined( UNDER_CE )
43 # include <windows.h> /* GetFileAttributes() */
45 # include "../extras/dirent.h"
48 #ifdef HAVE_SYS_TYPES_H
49 # include <sys/types.h>
51 #ifdef HAVE_SYS_STAT_H
52 # include <sys/stat.h>
58 #define HAVE_DYNAMIC_PLUGINS
59 #if defined(HAVE_DL_DYLD)
60 # if defined(HAVE_MACH_O_DYLD_H)
61 # include <mach-o/dyld.h>
63 #elif defined(HAVE_DL_BEOS)
64 # if defined(HAVE_IMAGE_H)
67 #elif defined(HAVE_DL_WINDOWS)
69 #elif defined(HAVE_DL_DLOPEN)
70 # if defined(HAVE_DLFCN_H) /* Linux, BSD, Hurd */
73 # if defined(HAVE_SYS_DL_H)
76 #elif defined(HAVE_DL_SHL_LOAD)
77 # if defined(HAVE_DL_H)
81 # undef HAVE_DYNAMIC_PLUGINS
84 #include "vlc_error.h"
86 #include "vlc_interface.h"
87 #include "intf_eject.h"
89 #include "vlc_playlist.h"
91 #include "vlc_video.h"
92 #include "video_output.h"
93 #include "vout_synchro.h"
96 #include "audio_output.h"
97 #include "aout_internal.h"
99 #include "stream_output.h"
101 #include "vlc_httpd.h"
103 #include "iso_lang.h"
106 #include "vlc_block.h"
110 #ifdef HAVE_DYNAMIC_PLUGINS
111 # include "modules_plugin.h"
114 #if defined( UNDER_CE )
115 # include "modules_builtin_evc.h"
116 #elif defined( _MSC_VER )
117 # include "modules_builtin_msvc.h"
119 # include "modules_builtin.h"
123 #if defined( WIN32) || defined( UNDER_CE )
124 /* Avoid name collisions */
125 # define LoadModule(a,b,c) _LoadModule(a,b,c)
128 /*****************************************************************************
130 *****************************************************************************/
131 #ifdef HAVE_DYNAMIC_PLUGINS
132 static void AllocateAllPlugins ( vlc_object_t
* );
133 static void AllocatePluginDir ( vlc_object_t
*, const char *, int );
134 static int AllocatePluginFile ( vlc_object_t
*, char *, int64_t, int64_t );
135 static module_t
* AllocatePlugin( vlc_object_t
*, char * );
137 static int AllocateBuiltinModule( vlc_object_t
*, int ( * ) ( module_t
* ) );
138 static int DeleteModule ( module_t
* );
139 #ifdef HAVE_DYNAMIC_PLUGINS
140 static void DupModule ( module_t
* );
141 static void UndupModule ( module_t
* );
142 static int CallEntry ( module_t
* );
143 static int LoadModule ( vlc_object_t
*, char *, module_handle_t
* );
144 static void CloseModule ( module_handle_t
);
145 static void * GetSymbol ( module_handle_t
, const char * );
146 static void CacheLoad ( vlc_object_t
* );
147 static int CacheLoadConfig ( module_t
*, FILE * );
148 static void CacheSave ( vlc_object_t
* );
149 static void CacheSaveConfig ( module_t
*, FILE * );
150 static char * CacheName ( void );
151 static void CacheMerge ( vlc_object_t
*, module_t
*, module_t
* );
152 static module_cache_t
* CacheFind( vlc_object_t
*, char *, int64_t, int64_t );
154 #if defined(HAVE_DL_WINDOWS)
155 static char * GetWindowsError ( void );
159 /*****************************************************************************
160 * module_InitBank: create the module bank.
161 *****************************************************************************
162 * This function creates a module bank structure which will be filled later
163 * on with all the modules found.
164 *****************************************************************************/
165 void __module_InitBank( vlc_object_t
*p_this
)
167 module_bank_t
*p_bank
;
170 var_Create( p_this
->p_libvlc
, "libvlc", VLC_VAR_MUTEX
);
171 var_Get( p_this
->p_libvlc
, "libvlc", &lockval
);
172 vlc_mutex_lock( lockval
.p_address
);
173 if( p_this
->p_libvlc
->p_module_bank
)
175 p_this
->p_libvlc
->p_module_bank
->i_usage
++;
176 vlc_mutex_unlock( lockval
.p_address
);
177 var_Destroy( p_this
->p_libvlc
, "libvlc" );
180 vlc_mutex_unlock( lockval
.p_address
);
181 var_Destroy( p_this
->p_libvlc
, "libvlc" );
183 p_bank
= vlc_object_create( p_this
, sizeof(module_bank_t
) );
184 p_bank
->psz_object_name
= "module bank";
186 p_bank
->i_cache
= p_bank
->i_loaded_cache
= 0;
187 p_bank
->pp_cache
= p_bank
->pp_loaded_cache
= 0;
188 p_bank
->b_cache
= p_bank
->b_cache_dirty
=
189 p_bank
->b_cache_delete
= VLC_FALSE
;
192 * Store the symbols to be exported
194 #ifdef HAVE_DYNAMIC_PLUGINS
195 STORE_SYMBOLS( &p_bank
->symbols
);
198 /* Everything worked, attach the object */
199 p_this
->p_libvlc
->p_module_bank
= p_bank
;
200 vlc_object_attach( p_bank
, p_this
->p_libvlc
);
202 module_LoadMain( p_this
);
207 /*****************************************************************************
208 * module_ResetBank: reset the module bank.
209 *****************************************************************************
210 * This function resets the module bank by unloading all unused plugin
212 *****************************************************************************/
213 void __module_ResetBank( vlc_object_t
*p_this
)
215 msg_Err( p_this
, "FIXME: module_ResetBank unimplemented" );
219 /*****************************************************************************
220 * module_EndBank: empty the module bank.
221 *****************************************************************************
222 * This function unloads all unused plugin modules and empties the module
223 * bank in case of success.
224 *****************************************************************************/
225 void __module_EndBank( vlc_object_t
*p_this
)
230 var_Create( p_this
->p_libvlc
, "libvlc", VLC_VAR_MUTEX
);
231 var_Get( p_this
->p_libvlc
, "libvlc", &lockval
);
232 vlc_mutex_lock( lockval
.p_address
);
233 if( !p_this
->p_libvlc
->p_module_bank
)
235 vlc_mutex_unlock( lockval
.p_address
);
236 var_Destroy( p_this
->p_libvlc
, "libvlc" );
239 if( --p_this
->p_libvlc
->p_module_bank
->i_usage
)
241 vlc_mutex_unlock( lockval
.p_address
);
242 var_Destroy( p_this
->p_libvlc
, "libvlc" );
245 vlc_mutex_unlock( lockval
.p_address
);
246 var_Destroy( p_this
->p_libvlc
, "libvlc" );
248 #ifdef HAVE_DYNAMIC_PLUGINS
249 #define p_bank p_this->p_libvlc->p_module_bank
250 if( p_bank
->b_cache
) CacheSave( p_this
);
251 while( p_bank
->i_loaded_cache
-- )
253 free( p_bank
->pp_loaded_cache
[p_bank
->i_loaded_cache
]->psz_file
);
254 free( p_bank
->pp_loaded_cache
[p_bank
->i_loaded_cache
] );
255 if( !p_bank
->i_loaded_cache
) free( p_bank
->pp_loaded_cache
);
257 while( p_bank
->i_cache
-- )
259 free( p_bank
->pp_cache
[p_bank
->i_cache
]->psz_file
);
260 free( p_bank
->pp_cache
[p_bank
->i_cache
] );
261 if( !p_bank
->i_cache
) free( p_bank
->pp_cache
);
266 vlc_object_detach( p_this
->p_libvlc
->p_module_bank
);
268 while( p_this
->p_libvlc
->p_module_bank
->i_children
)
270 p_next
= (module_t
*)p_this
->p_libvlc
->p_module_bank
->pp_children
[0];
272 if( DeleteModule( p_next
) )
274 /* Module deletion failed */
275 msg_Err( p_this
, "module \"%s\" can't be removed, trying harder",
276 p_next
->psz_object_name
);
278 /* We just free the module by hand. Niahahahahaha. */
279 vlc_object_detach( p_next
);
280 vlc_object_destroy( p_next
);
284 vlc_object_destroy( p_this
->p_libvlc
->p_module_bank
);
289 /*****************************************************************************
290 * module_LoadMain: load the main program info into the module bank.
291 *****************************************************************************
292 * This function fills the module bank structure with the main module infos.
293 * This is very useful as it will allow us to consider the main program just
294 * as another module, and for instance the configuration options of main will
295 * be available in the module bank structure just as for every other module.
296 *****************************************************************************/
297 void __module_LoadMain( vlc_object_t
*p_this
)
299 AllocateBuiltinModule( p_this
, vlc_entry__main
);
302 /*****************************************************************************
303 * module_LoadBuiltins: load all modules which we built with.
304 *****************************************************************************
305 * This function fills the module bank structure with the builtin modules.
306 *****************************************************************************/
307 void __module_LoadBuiltins( vlc_object_t
* p_this
)
309 msg_Dbg( p_this
, "checking builtin modules" );
310 ALLOCATE_ALL_BUILTINS();
313 /*****************************************************************************
314 * module_LoadPlugins: load all plugin modules we can find.
315 *****************************************************************************
316 * This function fills the module bank structure with the plugin modules.
317 *****************************************************************************/
318 void __module_LoadPlugins( vlc_object_t
* p_this
)
320 #ifdef HAVE_DYNAMIC_PLUGINS
321 msg_Dbg( p_this
, "checking plugin modules" );
323 if( config_GetInt( p_this
, "plugins-cache" ) )
324 p_this
->p_libvlc
->p_module_bank
->b_cache
= VLC_TRUE
;
326 if( p_this
->p_libvlc
->p_module_bank
->b_cache
||
327 p_this
->p_libvlc
->p_module_bank
->b_cache_delete
) CacheLoad( p_this
);
329 AllocateAllPlugins( p_this
);
333 /*****************************************************************************
334 * module_Need: return the best module function, given a capability list.
335 *****************************************************************************
336 * This function returns the module that best fits the asked capabilities.
337 *****************************************************************************/
338 module_t
* __module_Need( vlc_object_t
*p_this
, const char *psz_capability
,
339 const char *psz_name
, vlc_bool_t b_strict
)
341 typedef struct module_list_t module_list_t
;
348 module_list_t
*p_next
;
351 module_list_t
*p_list
, *p_first
, *p_tmp
;
354 int i_which_module
, i_index
= 0;
355 vlc_bool_t b_intf
= VLC_FALSE
;
360 char *psz_shortcuts
= NULL
, *psz_var
= NULL
;
361 vlc_bool_t b_force_backup
= p_this
->b_force
;
363 msg_Dbg( p_this
, "looking for %s module", psz_capability
);
365 /* Deal with variables */
366 if( psz_name
&& psz_name
[0] == '$' )
369 var_Create( p_this
, psz_name
+ 1, VLC_VAR_MODULE
| VLC_VAR_DOINHERIT
);
370 var_Get( p_this
, psz_name
+ 1, &val
);
371 psz_var
= val
.psz_string
;
375 /* Count how many different shortcuts were asked for */
376 if( psz_name
&& *psz_name
)
378 char *psz_parser
, *psz_last_shortcut
;
380 /* If the user wants none, give him none. */
381 if( !strcmp( psz_name
, "none" ) )
383 if( psz_var
) free( psz_var
);
388 psz_shortcuts
= psz_last_shortcut
= strdup( psz_name
);
390 for( psz_parser
= psz_shortcuts
; *psz_parser
; psz_parser
++ )
392 if( *psz_parser
== ',' )
396 psz_last_shortcut
= psz_parser
+ 1;
400 /* Check if the user wants to override the "strict" mode */
401 if( psz_last_shortcut
)
403 if( !strcmp(psz_last_shortcut
, "none") )
408 else if( !strcmp(psz_last_shortcut
, "any") )
410 b_strict
= VLC_FALSE
;
416 /* Sort the modules and test them */
417 p_all
= vlc_list_find( p_this
, VLC_OBJECT_MODULE
, FIND_ANYWHERE
);
418 p_list
= malloc( p_all
->i_count
* sizeof( module_list_t
) );
421 /* Parse the module list for capabilities and probe each of them */
422 for( i_which_module
= 0; i_which_module
< p_all
->i_count
; i_which_module
++ )
424 int i_shortcut_bonus
= 0;
426 p_module
= (module_t
*)p_all
->p_values
[i_which_module
].p_object
;
428 /* Test that this module can do what we need */
429 if( strcmp( p_module
->psz_capability
, psz_capability
) )
431 /* Don't recurse through the sub-modules because vlc_list_find()
432 * will list them anyway. */
436 /* Test if we have the required CPU */
437 if( (p_module
->i_cpu
& p_this
->p_libvlc
->i_cpu
) != p_module
->i_cpu
)
442 /* If we required a shortcut, check this plugin provides it. */
443 if( i_shortcuts
> 0 )
446 int i_dummy
, i_short
= i_shortcuts
;
447 char *psz_name
= psz_shortcuts
;
449 /* Let's drop modules with a <= 0 score (unless they are
450 * explicitly requested) */
451 b_trash
= p_module
->i_score
<= 0;
455 for( i_dummy
= 0; p_module
->pp_shortcuts
[i_dummy
]; i_dummy
++ )
457 if( !strcasecmp( psz_name
,
458 p_module
->pp_shortcuts
[i_dummy
] ) )
462 i_shortcut_bonus
= i_short
* 10000;
467 if( i_shortcut_bonus
)
469 /* We found it... remember ? */
473 /* Go to the next shortcut... This is so lame! */
482 /* If we are in "strict" mode and we couldn't
483 * find the module in the list of provided shortcuts,
484 * then kick the bastard out of here!!! */
485 if( i_short
== 0 && b_strict
)
495 /* If we didn't require a shortcut, trash <= 0 scored plugins */
496 else if( p_module
->i_score
<= 0 )
501 /* Special case: test if we requested a particular intf plugin */
502 if( !i_shortcuts
&& p_module
->psz_program
503 && !strcmp( p_module
->psz_program
,
504 p_this
->p_vlc
->psz_object_name
) )
508 /* Remove previous non-matching plugins */
515 /* This one doesn't match */
519 /* Store this new module */
520 p_list
[ i_index
].p_module
= p_module
;
521 p_list
[ i_index
].i_score
= p_module
->i_score
+ i_shortcut_bonus
;
522 p_list
[ i_index
].b_force
= !!i_shortcut_bonus
;
524 /* Add it to the modules-to-probe list */
527 p_list
[ 0 ].p_next
= NULL
;
532 /* Ok, so at school you learned that quicksort is quick, and
533 * bubble sort sucks raw eggs. But that's when dealing with
534 * thousands of items. Here we have barely 50. */
535 module_list_t
*p_newlist
= p_first
;
537 if( p_first
->i_score
< p_list
[ i_index
].i_score
)
539 p_list
[ i_index
].p_next
= p_first
;
540 p_first
= &p_list
[ i_index
];
544 while( p_newlist
->p_next
!= NULL
&&
545 p_newlist
->p_next
->i_score
>= p_list
[ i_index
].i_score
)
547 p_newlist
= p_newlist
->p_next
;
550 p_list
[ i_index
].p_next
= p_newlist
->p_next
;
551 p_newlist
->p_next
= &p_list
[ i_index
];
558 msg_Dbg( p_this
, "probing %i candidate%s",
559 i_index
, i_index
== 1 ? "" : "s" );
561 /* Lock all candidate modules */
563 while( p_tmp
!= NULL
)
565 vlc_object_yield( p_tmp
->p_module
);
566 p_tmp
= p_tmp
->p_next
;
569 /* We can release the list, interesting modules were yielded */
570 vlc_list_release( p_all
);
572 /* Parse the linked list and use the first successful module */
574 while( p_tmp
!= NULL
)
576 #ifdef HAVE_DYNAMIC_PLUGINS
577 /* Make sure the module is loaded in mem */
578 module_t
*p_module
= p_tmp
->p_module
->b_submodule
?
579 (module_t
*)p_tmp
->p_module
->p_parent
: p_tmp
->p_module
;
580 if( !p_module
->b_builtin
&& !p_module
->b_loaded
)
582 module_t
*p_new_module
=
583 AllocatePlugin( p_this
, p_module
->psz_filename
);
586 CacheMerge( p_this
, p_module
, p_new_module
);
587 vlc_object_attach( p_new_module
, p_module
);
588 DeleteModule( p_new_module
);
593 p_this
->b_force
= p_tmp
->b_force
;
594 if( p_tmp
->p_module
->pf_activate
595 && p_tmp
->p_module
->pf_activate( p_this
) == VLC_SUCCESS
)
600 vlc_object_release( p_tmp
->p_module
);
601 p_tmp
= p_tmp
->p_next
;
604 /* Store the locked module value */
607 p_module
= p_tmp
->p_module
;
608 p_tmp
= p_tmp
->p_next
;
615 /* Unlock the remaining modules */
616 while( p_tmp
!= NULL
)
618 vlc_object_release( p_tmp
->p_module
);
619 p_tmp
= p_tmp
->p_next
;
623 p_this
->b_force
= b_force_backup
;
625 if( p_module
!= NULL
)
627 msg_Dbg( p_module
, "using %s module \"%s\"",
628 psz_capability
, p_module
->psz_object_name
);
630 else if( p_first
== NULL
)
632 if( !strcmp( psz_capability
, "access_demux" ) )
634 msg_Warn( p_this
, "no %s module matched \"%s\"",
635 psz_capability
, (psz_name
&& *psz_name
) ? psz_name
: "any" );
639 msg_Err( p_this
, "no %s module matched \"%s\"",
640 psz_capability
, (psz_name
&& *psz_name
) ? psz_name
: "any" );
643 else if( psz_name
!= NULL
&& *psz_name
)
645 msg_Warn( p_this
, "no %s module matching \"%s\" could be loaded",
646 psz_capability
, (psz_name
&& *psz_name
) ? psz_name
: "any" );
651 free( psz_shortcuts
);
659 /* Don't forget that the module is still locked */
663 /*****************************************************************************
664 * module_Unneed: decrease the usage count of a module.
665 *****************************************************************************
666 * This function must be called by the thread that called module_Need, to
667 * decrease the reference count and allow for hiding of modules.
668 *****************************************************************************/
669 void __module_Unneed( vlc_object_t
* p_this
, module_t
* p_module
)
671 /* Use the close method */
672 if( p_module
->pf_deactivate
)
674 p_module
->pf_deactivate( p_this
);
677 msg_Dbg( p_module
, "unlocking module \"%s\"", p_module
->psz_object_name
);
679 vlc_object_release( p_module
);
684 /*****************************************************************************
685 * Following functions are local.
686 *****************************************************************************/
688 /*****************************************************************************
689 * AllocateAllPlugins: load all plugin modules we can find.
690 *****************************************************************************/
691 #ifdef HAVE_DYNAMIC_PLUGINS
692 static void AllocateAllPlugins( vlc_object_t
*p_this
)
694 /* Yes, there are two NULLs because we replace one with "plugin-path". */
695 #if defined( WIN32 ) || defined( UNDER_CE )
696 char *path
[] = { "modules", "", "plugins", 0, 0 };
698 char *path
[] = { "modules", PLUGIN_PATH
, "plugins", 0, 0 };
701 char **ppsz_path
= path
;
704 /* If the user provided a plugin path, we add it to the list */
705 path
[ sizeof(path
)/sizeof(char*) - 2 ] =
706 config_GetPsz( p_this
, "plugin-path" );
708 for( ; *ppsz_path
!= NULL
; ppsz_path
++ )
710 if( !(*ppsz_path
)[0] ) continue;
712 #if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
714 /* Handle relative as well as absolute paths */
716 if( (*ppsz_path
)[0] != '\\' && (*ppsz_path
)[0] != '/' &&
717 (*ppsz_path
)[1] != ':' )
719 if( (*ppsz_path
)[0] != '/' )
722 int i_dirlen
= strlen( *ppsz_path
);
723 i_dirlen
+= strlen( p_this
->p_libvlc
->psz_vlcpath
) + 2;
725 psz_fullpath
= malloc( i_dirlen
);
726 if( psz_fullpath
== NULL
)
731 sprintf( psz_fullpath
, "%s\\%s",
732 p_this
->p_libvlc
->psz_vlcpath
, *ppsz_path
);
734 sprintf( psz_fullpath
, "%s/%s",
735 p_this
->p_libvlc
->psz_vlcpath
, *ppsz_path
);
741 psz_fullpath
= strdup( *ppsz_path
);
744 msg_Dbg( p_this
, "recursively browsing `%s'", psz_fullpath
);
746 /* Don't go deeper than 5 subdirectories */
747 AllocatePluginDir( p_this
, psz_fullpath
, 5 );
749 free( psz_fullpath
);
752 /* Free plugin-path */
753 if( path
[ sizeof(path
)/sizeof(char*) - 2 ] )
754 free( path
[ sizeof(path
)/sizeof(char*) - 2 ] );
755 path
[ sizeof(path
)/sizeof(char*) - 2 ] = NULL
;
758 /*****************************************************************************
759 * AllocatePluginDir: recursively parse a directory to look for plugins
760 *****************************************************************************/
761 static void AllocatePluginDir( vlc_object_t
*p_this
, const char *psz_dir
,
764 #if defined( UNDER_CE ) || defined( _MSC_VER )
766 wchar_t psz_wpath
[MAX_PATH
+ 256];
767 wchar_t psz_wdir
[MAX_PATH
];
769 char psz_path
[MAX_PATH
+ 256];
770 WIN32_FIND_DATA finddata
;
776 struct dirent
* file
;
780 if( p_this
->p_vlc
->b_die
|| i_maxdepth
< 0 )
785 #if defined( UNDER_CE ) || defined( _MSC_VER )
787 MultiByteToWideChar( CP_ACP
, 0, psz_dir
, -1, psz_wdir
, MAX_PATH
);
789 rc
= GetFileAttributes( psz_wdir
);
790 if( !(rc
& FILE_ATTRIBUTE_DIRECTORY
) ) return; /* Not a directory */
792 /* Parse all files in the directory */
793 swprintf( psz_wpath
, L
"%ls\\*", psz_wdir
);
795 rc
= GetFileAttributes( psz_dir
);
796 if( !(rc
& FILE_ATTRIBUTE_DIRECTORY
) ) return; /* Not a directory */
799 /* Parse all files in the directory */
800 sprintf( psz_path
, "%s\\*", psz_dir
);
803 handle
= FindFirstFile( psz_wpath
, &finddata
);
805 handle
= FindFirstFile( psz_path
, &finddata
);
807 if( handle
== INVALID_HANDLE_VALUE
)
809 /* Empty directory */
813 /* Parse the directory and try to load all files it contains. */
817 unsigned int i_len
= wcslen( finddata
.cFileName
);
818 swprintf( psz_wpath
, L
"%ls\\%ls", psz_wdir
, finddata
.cFileName
);
819 sprintf( psz_path
, "%s\\%ls", psz_dir
, finddata
.cFileName
);
821 unsigned int i_len
= strlen( finddata
.cFileName
);
822 sprintf( psz_path
, "%s\\%s", psz_dir
, finddata
.cFileName
);
825 /* Skip ".", ".." and anything starting with "." */
826 if( !*finddata
.cFileName
|| *finddata
.cFileName
== '.' )
828 if( !FindNextFile( handle
, &finddata
) ) break;
833 if( GetFileAttributes( psz_wpath
) & FILE_ATTRIBUTE_DIRECTORY
)
835 if( GetFileAttributes( psz_path
) & FILE_ATTRIBUTE_DIRECTORY
)
838 AllocatePluginDir( p_this
, psz_path
, i_maxdepth
- 1 );
840 else if( i_len
> strlen( LIBEXT
)
841 /* We only load files ending with LIBEXT */
842 && !strncasecmp( psz_path
+ strlen( psz_path
)
844 LIBEXT
, strlen( LIBEXT
) ) )
846 WIN32_FILE_ATTRIBUTE_DATA attrbuf
;
847 int64_t i_time
= 0, i_size
= 0;
850 if( GetFileAttributesEx( psz_wpath
, GetFileExInfoStandard
,
853 if( GetFileAttributesEx( psz_path
, GetFileExInfoStandard
,
857 i_time
= attrbuf
.ftLastWriteTime
.dwHighDateTime
;
859 i_time
|= attrbuf
.ftLastWriteTime
.dwLowDateTime
;
860 i_size
= attrbuf
.nFileSizeHigh
;
862 i_size
|= attrbuf
.nFileSizeLow
;
866 AllocatePluginFile( p_this
, psz_file
, i_time
, i_size
);
869 while( !p_this
->p_vlc
->b_die
&& FindNextFile( handle
, &finddata
) );
871 /* Close the directory */
875 dir
= opendir( psz_dir
);
881 i_dirlen
= strlen( psz_dir
);
883 /* Parse the directory and try to load all files it contains. */
884 while( !p_this
->p_vlc
->b_die
&& (file
= readdir( dir
)) )
890 /* Skip ".", ".." and anything starting with "." */
891 if( !*file
->d_name
|| *file
->d_name
== '.' )
896 i_len
= strlen( file
->d_name
);
897 psz_file
= malloc( i_dirlen
+ 1 + i_len
+ 1 );
899 sprintf( psz_file
, "%s\\%s", psz_dir
, file
->d_name
);
901 sprintf( psz_file
, "%s/%s", psz_dir
, file
->d_name
);
904 i_stat
= stat( psz_file
, &statbuf
);
905 if( !i_stat
&& statbuf
.st_mode
& S_IFDIR
)
907 AllocatePluginDir( p_this
, psz_file
, i_maxdepth
- 1 );
909 else if( i_len
> strlen( LIBEXT
)
910 /* We only load files ending with LIBEXT */
911 && !strncasecmp( file
->d_name
+ i_len
- strlen( LIBEXT
),
912 LIBEXT
, strlen( LIBEXT
) ) )
914 int64_t i_time
= 0, i_size
= 0;
918 i_time
= statbuf
.st_mtime
;
919 i_size
= statbuf
.st_size
;
922 AllocatePluginFile( p_this
, psz_file
, i_time
, i_size
);
928 /* Close the directory */
934 /*****************************************************************************
935 * AllocatePluginFile: load a module into memory and initialize it.
936 *****************************************************************************
937 * This function loads a dynamically loadable module and allocates a structure
938 * for its information data. The module can then be handled by module_Need
939 * and module_Unneed. It can be removed by DeleteModule.
940 *****************************************************************************/
941 static int AllocatePluginFile( vlc_object_t
* p_this
, char * psz_file
,
942 int64_t i_file_time
, int64_t i_file_size
)
945 module_cache_t
*p_cache_entry
= NULL
;
948 * Check our plugins cache first then load plugin if needed
951 CacheFind( p_this
, psz_file
, i_file_time
, i_file_size
);
955 p_module
= AllocatePlugin( p_this
, psz_file
);
959 /* If junk dll, don't try to load it */
960 if( p_cache_entry
->b_junk
)
966 module_config_t
*p_item
;
968 p_module
= p_cache_entry
->p_module
;
969 p_module
->b_loaded
= VLC_FALSE
;
971 /* For now we force loading if the module's config contains
972 * callbacks or actions.
973 * Could be optimized by adding an API call.*/
974 for( p_item
= p_module
->p_config
;
975 p_item
->i_type
!= CONFIG_HINT_END
; p_item
++ )
977 if( p_item
->pf_callback
|| p_item
->i_action
)
978 p_module
= AllocatePlugin( p_this
, psz_file
);
985 /* Everything worked fine !
986 * The module is ready to be added to the list. */
987 p_module
->b_builtin
= VLC_FALSE
;
989 /* msg_Dbg( p_this, "plugin \"%s\", %s",
990 p_module->psz_object_name, p_module->psz_longname ); */
992 vlc_object_attach( p_module
, p_this
->p_libvlc
->p_module_bank
);
995 if( !p_this
->p_libvlc
->p_module_bank
->b_cache
) return 0;
997 /* Add entry to cache */
998 #define p_bank p_this->p_libvlc->p_module_bank
1000 realloc( p_bank
->pp_cache
, (p_bank
->i_cache
+ 1) * sizeof(void *) );
1001 p_bank
->pp_cache
[p_bank
->i_cache
] = malloc( sizeof(module_cache_t
) );
1002 p_bank
->pp_cache
[p_bank
->i_cache
]->psz_file
= strdup( psz_file
);
1003 p_bank
->pp_cache
[p_bank
->i_cache
]->i_time
= i_file_time
;
1004 p_bank
->pp_cache
[p_bank
->i_cache
]->i_size
= i_file_size
;
1005 p_bank
->pp_cache
[p_bank
->i_cache
]->b_junk
= p_module
? 0 : 1;
1006 p_bank
->pp_cache
[p_bank
->i_cache
]->p_module
= p_module
;
1009 return p_module
? 0 : -1;
1012 /*****************************************************************************
1013 * AllocatePlugin: load a module into memory and initialize it.
1014 *****************************************************************************
1015 * This function loads a dynamically loadable module and allocates a structure
1016 * for its information data. The module can then be handled by module_Need
1017 * and module_Unneed. It can be removed by DeleteModule.
1018 *****************************************************************************/
1019 static module_t
* AllocatePlugin( vlc_object_t
* p_this
, char * psz_file
)
1021 module_t
* p_module
;
1022 module_handle_t handle
;
1024 if( LoadModule( p_this
, psz_file
, &handle
) ) return NULL
;
1026 /* Now that we have successfully loaded the module, we can
1027 * allocate a structure for it */
1028 p_module
= vlc_object_create( p_this
, VLC_OBJECT_MODULE
);
1029 if( p_module
== NULL
)
1031 msg_Err( p_this
, "out of memory" );
1032 CloseModule( handle
);
1036 /* We need to fill these since they may be needed by CallEntry() */
1037 p_module
->psz_filename
= psz_file
;
1038 p_module
->handle
= handle
;
1039 p_module
->p_symbols
= &p_this
->p_libvlc
->p_module_bank
->symbols
;
1040 p_module
->b_loaded
= VLC_TRUE
;
1042 /* Initialize the module: fill p_module, default config */
1043 if( CallEntry( p_module
) != 0 )
1045 /* We couldn't call module_init() */
1046 vlc_object_destroy( p_module
);
1047 CloseModule( handle
);
1051 DupModule( p_module
);
1052 p_module
->psz_filename
= strdup( p_module
->psz_filename
);
1054 /* Everything worked fine ! The module is ready to be added to the list. */
1055 p_module
->b_builtin
= VLC_FALSE
;
1060 /*****************************************************************************
1061 * DupModule: make a plugin module standalone.
1062 *****************************************************************************
1063 * This function duplicates all strings in the module, so that the dynamic
1064 * object can be unloaded. It acts recursively on submodules.
1065 *****************************************************************************/
1066 static void DupModule( module_t
*p_module
)
1071 for( pp_shortcut
= p_module
->pp_shortcuts
; *pp_shortcut
; pp_shortcut
++ )
1073 *pp_shortcut
= strdup( *pp_shortcut
);
1076 /* We strdup() these entries so that they are still valid when the
1077 * module is unloaded. */
1078 p_module
->psz_object_name
= strdup( p_module
->psz_object_name
);
1079 p_module
->psz_capability
= strdup( p_module
->psz_capability
);
1080 p_module
->psz_shortname
= strdup( p_module
->psz_shortname
);
1081 p_module
->psz_longname
= strdup( p_module
->psz_longname
);
1083 if( p_module
->psz_program
!= NULL
)
1085 p_module
->psz_program
= strdup( p_module
->psz_program
);
1088 for( i_submodule
= 0; i_submodule
< p_module
->i_children
; i_submodule
++ )
1090 DupModule( (module_t
*)p_module
->pp_children
[ i_submodule
] );
1094 /*****************************************************************************
1095 * UndupModule: free a duplicated module.
1096 *****************************************************************************
1097 * This function frees the allocations done in DupModule().
1098 *****************************************************************************/
1099 static void UndupModule( module_t
*p_module
)
1104 for( i_submodule
= 0; i_submodule
< p_module
->i_children
; i_submodule
++ )
1106 UndupModule( (module_t
*)p_module
->pp_children
[ i_submodule
] );
1109 for( pp_shortcut
= p_module
->pp_shortcuts
; *pp_shortcut
; pp_shortcut
++ )
1111 free( *pp_shortcut
);
1114 free( p_module
->psz_object_name
);
1115 free( p_module
->psz_capability
);
1116 free( p_module
->psz_shortname
);
1117 free( p_module
->psz_longname
);
1119 if( p_module
->psz_program
!= NULL
)
1121 free( p_module
->psz_program
);
1125 #endif /* HAVE_DYNAMIC_PLUGINS */
1127 /*****************************************************************************
1128 * AllocateBuiltinModule: initialize a builtin module.
1129 *****************************************************************************
1130 * This function registers a builtin module and allocates a structure
1131 * for its information data. The module can then be handled by module_Need
1132 * and module_Unneed. It can be removed by DeleteModule.
1133 *****************************************************************************/
1134 static int AllocateBuiltinModule( vlc_object_t
* p_this
,
1135 int ( *pf_entry
) ( module_t
* ) )
1137 module_t
* p_module
;
1139 /* Now that we have successfully loaded the module, we can
1140 * allocate a structure for it */
1141 p_module
= vlc_object_create( p_this
, VLC_OBJECT_MODULE
);
1142 if( p_module
== NULL
)
1144 msg_Err( p_this
, "out of memory" );
1148 /* Initialize the module : fill p_module->psz_object_name, etc. */
1149 if( pf_entry( p_module
) != 0 )
1151 /* With a well-written module we shouldn't have to print an
1152 * additional error message here, but just make sure. */
1153 msg_Err( p_this
, "failed calling entry point in builtin module" );
1154 vlc_object_destroy( p_module
);
1158 /* Everything worked fine ! The module is ready to be added to the list. */
1159 p_module
->b_builtin
= VLC_TRUE
;
1161 /* msg_Dbg( p_this, "builtin \"%s\", %s",
1162 p_module->psz_object_name, p_module->psz_longname ); */
1164 vlc_object_attach( p_module
, p_this
->p_libvlc
->p_module_bank
);
1169 /*****************************************************************************
1170 * DeleteModule: delete a module and its structure.
1171 *****************************************************************************
1172 * This function can only be called if the module isn't being used.
1173 *****************************************************************************/
1174 static int DeleteModule( module_t
* p_module
)
1176 vlc_object_detach( p_module
);
1178 /* We free the structures that we strdup()ed in Allocate*Module(). */
1179 #ifdef HAVE_DYNAMIC_PLUGINS
1180 if( !p_module
->b_builtin
)
1182 if( p_module
->b_loaded
&& p_module
->b_unloadable
)
1184 CloseModule( p_module
->handle
);
1186 UndupModule( p_module
);
1187 free( p_module
->psz_filename
);
1191 /* Free and detach the object's children */
1192 while( p_module
->i_children
)
1194 vlc_object_t
*p_this
= p_module
->pp_children
[0];
1195 vlc_object_detach( p_this
);
1196 vlc_object_destroy( p_this
);
1199 config_Free( p_module
);
1200 vlc_object_destroy( p_module
);
1205 #ifdef HAVE_DYNAMIC_PLUGINS
1206 /*****************************************************************************
1207 * CallEntry: call an entry point.
1208 *****************************************************************************
1209 * This function calls a symbol given its name and a module structure. The
1210 * symbol MUST refer to a function returning int and taking a module_t* as
1212 *****************************************************************************/
1213 static int CallEntry( module_t
* p_module
)
1215 static char *psz_name
= "vlc_entry" MODULE_SUFFIX
;
1216 int (* pf_symbol
) ( module_t
* p_module
);
1218 /* Try to resolve the symbol */
1219 pf_symbol
= (int (*)(module_t
*)) GetSymbol( p_module
->handle
, psz_name
);
1221 if( pf_symbol
== NULL
)
1223 #if defined(HAVE_DL_DYLD) || defined(HAVE_DL_BEOS)
1224 msg_Warn( p_module
, "cannot find symbol \"%s\" in file `%s'",
1225 psz_name
, p_module
->psz_filename
);
1226 #elif defined(HAVE_DL_WINDOWS)
1227 char *psz_error
= GetWindowsError();
1228 msg_Warn( p_module
, "cannot find symbol \"%s\" in file `%s' (%s)",
1229 psz_name
, p_module
->psz_filename
, psz_error
);
1231 #elif defined(HAVE_DL_DLOPEN)
1232 msg_Warn( p_module
, "cannot find symbol \"%s\" in file `%s' (%s)",
1233 psz_name
, p_module
->psz_filename
, dlerror() );
1234 #elif defined(HAVE_DL_SHL_LOAD)
1235 msg_Warn( p_module
, "cannot find symbol \"%s\" in file `%s' (%s)",
1236 psz_name
, p_module
->psz_filename
, strerror(errno
) );
1238 # error "Something is wrong in modules.c"
1243 /* We can now try to call the symbol */
1244 if( pf_symbol( p_module
) != 0 )
1246 /* With a well-written module we shouldn't have to print an
1247 * additional error message here, but just make sure. */
1248 msg_Err( p_module
, "failed calling symbol \"%s\" in file `%s'",
1249 psz_name
, p_module
->psz_filename
);
1253 /* Everything worked fine, we can return */
1257 /*****************************************************************************
1258 * LoadModule: loads a dynamic library
1259 *****************************************************************************
1260 * This function loads a dynamically linked library using a system dependant
1261 * method. Will return 0 on success as well as the module handle.
1262 *****************************************************************************/
1263 static int LoadModule( vlc_object_t
*p_this
, char *psz_file
,
1264 module_handle_t
*p_handle
)
1266 module_handle_t handle
;
1268 #if defined(HAVE_DL_DYLD)
1269 NSObjectFileImage image
;
1270 NSObjectFileImageReturnCode ret
;
1272 ret
= NSCreateObjectFileImageFromFile( psz_file
, &image
);
1274 if( ret
!= NSObjectFileImageSuccess
)
1276 msg_Warn( p_this
, "cannot create image from `%s'", psz_file
);
1280 /* Open the dynamic module */
1281 handle
= NSLinkModule( image
, psz_file
,
1282 NSLINKMODULE_OPTION_RETURN_ON_ERROR
);
1286 NSLinkEditErrors errors
;
1287 const char *psz_file
, *psz_err
;
1289 NSLinkEditError( &errors
, &i_errnum
, &psz_file
, &psz_err
);
1290 msg_Warn( p_this
, "cannot link module `%s' (%s)", psz_file
, psz_err
);
1291 NSDestroyObjectFileImage( image
);
1295 /* Destroy our image, we won't need it */
1296 NSDestroyObjectFileImage( image
);
1298 #elif defined(HAVE_DL_BEOS)
1299 handle
= load_add_on( psz_file
);
1302 msg_Warn( p_this
, "cannot load module `%s'", psz_file
);
1306 #elif defined(HAVE_DL_WINDOWS)
1309 wchar_t psz_wfile
[MAX_PATH
];
1310 MultiByteToWideChar( CP_ACP
, 0, psz_file
, -1, psz_wfile
, MAX_PATH
);
1311 handle
= LoadLibrary( psz_wfile
);
1314 handle
= LoadLibrary( psz_file
);
1316 if( handle
== NULL
)
1318 char *psz_err
= GetWindowsError();
1319 msg_Warn( p_this
, "cannot load module `%s' (%s)", psz_file
, psz_err
);
1324 #elif defined(HAVE_DL_DLOPEN) && defined(RTLD_NOW)
1325 /* static is OK, we are called atomically */
1326 static vlc_bool_t b_kde
= VLC_FALSE
;
1328 # if defined(SYS_LINUX)
1329 /* XXX HACK #1 - we should NOT open modules with RTLD_GLOBAL, or we
1330 * are going to get namespace collisions when two modules have common
1331 * public symbols, but ALSA is being a pest here. */
1332 if( strstr( psz_file
, "alsa_plugin" ) )
1334 handle
= dlopen( psz_file
, RTLD_NOW
| RTLD_GLOBAL
);
1335 if( handle
== NULL
)
1337 msg_Warn( p_this
, "cannot load module `%s' (%s)",
1338 psz_file
, dlerror() );
1343 /* XXX HACK #2 - the ugly KDE workaround. It seems that libkdewhatever
1344 * causes dlopen() to segfault if libstdc++ is not loaded in the caller,
1345 * so we just load libstdc++. Bwahahaha! ph34r! -- Sam. */
1346 /* Update: FYI, this is Debian bug #180505, and seems to be fixed. */
1347 if( !b_kde
&& !strstr( psz_file
, "kde" ) )
1349 dlopen( "libstdc++.so.6", RTLD_NOW
)
1350 || dlopen( "libstdc++.so.5", RTLD_NOW
)
1351 || dlopen( "libstdc++.so.4", RTLD_NOW
)
1352 || dlopen( "libstdc++.so.3", RTLD_NOW
);
1356 handle
= dlopen( psz_file
, RTLD_NOW
);
1357 if( handle
== NULL
)
1359 msg_Warn( p_this
, "cannot load module `%s' (%s)",
1360 psz_file
, dlerror() );
1364 #elif defined(HAVE_DL_DLOPEN)
1365 # if defined(DL_LAZY)
1366 handle
= dlopen( psz_file
, DL_LAZY
);
1368 handle
= dlopen( psz_file
, 0 );
1370 if( handle
== NULL
)
1372 msg_Warn( p_this
, "cannot load module `%s' (%s)",
1373 psz_file
, dlerror() );
1377 #elif defined(HAVE_DL_SHL_LOAD)
1378 handle
= shl_load( psz_file
, BIND_IMMEDIATE
| BIND_NONFATAL
, NULL
);
1379 if( handle
== NULL
)
1381 msg_Warn( p_this
, "cannot load module `%s' (%s)",
1382 psz_file
, strerror(errno
) );
1387 # error "Something is wrong in modules.c"
1395 /*****************************************************************************
1396 * CloseModule: unload a dynamic library
1397 *****************************************************************************
1398 * This function unloads a previously opened dynamically linked library
1399 * using a system dependant method. No return value is taken in consideration,
1400 * since some libraries sometimes refuse to close properly.
1401 *****************************************************************************/
1402 static void CloseModule( module_handle_t handle
)
1404 #if defined(HAVE_DL_DYLD)
1405 NSUnLinkModule( handle
, FALSE
);
1407 #elif defined(HAVE_DL_BEOS)
1408 unload_add_on( handle
);
1410 #elif defined(HAVE_DL_WINDOWS)
1411 FreeLibrary( handle
);
1413 #elif defined(HAVE_DL_DLOPEN)
1416 #elif defined(HAVE_DL_SHL_LOAD)
1417 shl_unload( handle
);
1423 /*****************************************************************************
1424 * GetSymbol: get a symbol from a dynamic library
1425 *****************************************************************************
1426 * This function queries a loaded library for a symbol specified in a
1427 * string, and returns a pointer to it. We don't check for dlerror() or
1428 * similar functions, since we want a non-NULL symbol anyway.
1429 *****************************************************************************/
1430 static void * _module_getsymbol( module_handle_t
, const char * );
1432 static void * GetSymbol( module_handle_t handle
, const char * psz_function
)
1434 void * p_symbol
= _module_getsymbol( handle
, psz_function
);
1436 /* MacOS X dl library expects symbols to begin with "_". So do
1437 * some other operating systems. That's really lame, but hey, what
1439 if( p_symbol
== NULL
)
1441 char *psz_call
= malloc( strlen( psz_function
) + 2 );
1443 strcpy( psz_call
+ 1, psz_function
);
1444 psz_call
[ 0 ] = '_';
1445 p_symbol
= _module_getsymbol( handle
, psz_call
);
1452 static void * _module_getsymbol( module_handle_t handle
,
1453 const char * psz_function
)
1455 #if defined(HAVE_DL_DYLD)
1456 NSSymbol sym
= NSLookupSymbolInModule( handle
, psz_function
);
1457 return NSAddressOfSymbol( sym
);
1459 #elif defined(HAVE_DL_BEOS)
1461 if( B_OK
== get_image_symbol( handle
, psz_function
,
1462 B_SYMBOL_TYPE_TEXT
, &p_symbol
) )
1471 #elif defined(HAVE_DL_WINDOWS) && defined(UNDER_CE)
1472 wchar_t psz_real
[256];
1473 MultiByteToWideChar( CP_ACP
, 0, psz_function
, -1, psz_real
, 256 );
1475 return (void *)GetProcAddress( handle
, psz_real
);
1477 #elif defined(HAVE_DL_WINDOWS) && defined(WIN32)
1478 return (void *)GetProcAddress( handle
, (char *)psz_function
);
1480 #elif defined(HAVE_DL_DLOPEN)
1481 return dlsym( handle
, psz_function
);
1483 #elif defined(HAVE_DL_SHL_LOAD)
1485 shl_findsym( &handle
, psz_function
, TYPE_UNDEFINED
, &p_sym
);
1491 #if defined(HAVE_DL_WINDOWS)
1492 static char * GetWindowsError( void )
1494 #if defined(UNDER_CE)
1495 wchar_t psz_tmp
[256];
1496 char * psz_buffer
= malloc( 256 );
1498 char * psz_tmp
= malloc( 256 );
1500 int i
= 0, i_error
= GetLastError();
1502 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
,
1503 NULL
, i_error
, MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
1504 (LPTSTR
) psz_tmp
, 256, NULL
);
1506 /* Go to the end of the string */
1507 #if defined(UNDER_CE)
1508 while( psz_tmp
[i
] && psz_tmp
[i
] != L
'\r' && psz_tmp
[i
] != L
'\n' )
1510 while( psz_tmp
[i
] && psz_tmp
[i
] != '\r' && psz_tmp
[i
] != '\n' )
1518 #if defined(UNDER_CE)
1519 swprintf( psz_tmp
+ i
, L
" (error %i)", i_error
);
1520 psz_tmp
[ 255 ] = L
'\0';
1522 snprintf( psz_tmp
+ i
, 256 - i
, " (error %i)", i_error
);
1523 psz_tmp
[ 255 ] = '\0';
1527 #if defined(UNDER_CE)
1528 WideCharToMultiByte( CP_ACP
, WC_DEFAULTCHAR
, psz_tmp
, -1,
1529 psz_buffer
, 256, NULL
, NULL
);
1535 #endif /* HAVE_DL_WINDOWS */
1537 /*****************************************************************************
1538 * LoadPluginsCache: loads the plugins cache file
1539 *****************************************************************************
1540 * This function will load the plugin cache if present and valid. This cache
1541 * will in turn be queried by AllocateAllPlugins() to see if it needs to
1542 * actually load the dynamically loadable module.
1543 * This allows us to only fully load plugins when they are actually used.
1544 *****************************************************************************/
1545 static void CacheLoad( vlc_object_t
*p_this
)
1547 char *psz_filename
, *psz_homedir
;
1549 int i
, j
, i_size
, i_read
;
1550 char p_cachestring
[sizeof(PLUGINSCACHE_DIR COPYRIGHT_MESSAGE
)];
1552 module_cache_t
**pp_cache
= 0;
1553 int32_t i_file_size
;
1555 psz_homedir
= p_this
->p_vlc
->psz_homedir
;
1558 msg_Err( p_this
, "psz_homedir is null" );
1562 i_size
= asprintf( &psz_filename
, "%s/%s/%s/%s", psz_homedir
, CONFIG_DIR
,
1563 PLUGINSCACHE_DIR
, CacheName() );
1566 msg_Err( p_this
, "out of memory" );
1570 if( p_this
->p_libvlc
->p_module_bank
->b_cache_delete
)
1572 #if !defined( UNDER_CE )
1573 unlink( psz_filename
);
1575 wchar_t psz_wf
[MAX_PATH
];
1576 MultiByteToWideChar( CP_ACP
, 0, psz_filename
, -1, psz_wf
, MAX_PATH
);
1577 DeleteFile( psz_wf
);
1579 msg_Dbg( p_this
, "removing plugins cache file %s", psz_filename
);
1583 msg_Dbg( p_this
, "loading plugins cache file %s", psz_filename
);
1585 file
= fopen( psz_filename
, "rb" );
1588 msg_Warn( p_this
, "could not open plugins cache file %s for reading",
1590 free( psz_filename
);
1593 free( psz_filename
);
1595 /* Check the file size */
1596 i_read
= fread( &i_file_size
, sizeof(char), sizeof(i_file_size
), file
);
1597 if( i_read
!= sizeof(i_file_size
) )
1599 msg_Warn( p_this
, "This doesn't look like a valid plugins cache "
1605 fseek( file
, 0, SEEK_END
);
1606 if( ftell( file
) != i_file_size
)
1608 msg_Warn( p_this
, "This doesn't look like a valid plugins cache "
1609 "(corrupted size)" );
1613 fseek( file
, sizeof(i_file_size
), SEEK_SET
);
1615 /* Check the file is a plugins cache */
1616 i_size
= sizeof(PLUGINSCACHE_DIR COPYRIGHT_MESSAGE
) - 1;
1617 i_read
= fread( p_cachestring
, sizeof(char), i_size
, file
);
1618 if( i_read
!= i_size
||
1619 memcmp( p_cachestring
, PLUGINSCACHE_DIR COPYRIGHT_MESSAGE
, i_size
) )
1621 msg_Warn( p_this
, "This doesn't look like a valid plugins cache" );
1626 p_this
->p_libvlc
->p_module_bank
->i_loaded_cache
= 0;
1627 fread( &i_cache
, sizeof(char), sizeof(i_cache
), file
);
1628 pp_cache
= p_this
->p_libvlc
->p_module_bank
->pp_loaded_cache
=
1629 malloc( i_cache
* sizeof(void *) );
1631 #define LOAD_IMMEDIATE(a) \
1632 if( fread( &a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error
1633 #define LOAD_STRING(a) \
1634 { if( fread( &i_size, sizeof(char), sizeof(i_size), file ) \
1635 != sizeof(i_size) ) goto error; \
1637 a = malloc( i_size ); \
1638 if( fread( a, sizeof(char), i_size, file ) != (size_t)i_size ) \
1644 for( i
= 0; i
< i_cache
; i
++ )
1649 pp_cache
[i
] = malloc( sizeof(module_cache_t
) );
1650 p_this
->p_libvlc
->p_module_bank
->i_loaded_cache
++;
1652 /* Load common info */
1653 LOAD_STRING( pp_cache
[i
]->psz_file
);
1654 LOAD_IMMEDIATE( pp_cache
[i
]->i_time
);
1655 LOAD_IMMEDIATE( pp_cache
[i
]->i_size
);
1656 LOAD_IMMEDIATE( pp_cache
[i
]->b_junk
);
1658 if( pp_cache
[i
]->b_junk
) continue;
1660 pp_cache
[i
]->p_module
= vlc_object_create( p_this
, VLC_OBJECT_MODULE
);
1662 /* Load additional infos */
1663 LOAD_STRING( pp_cache
[i
]->p_module
->psz_object_name
);
1664 LOAD_STRING( pp_cache
[i
]->p_module
->psz_shortname
);
1665 LOAD_STRING( pp_cache
[i
]->p_module
->psz_longname
);
1666 LOAD_STRING( pp_cache
[i
]->p_module
->psz_program
);
1667 for( j
= 0; j
< MODULE_SHORTCUT_MAX
; j
++ )
1669 LOAD_STRING( pp_cache
[i
]->p_module
->pp_shortcuts
[j
] ); // FIX
1671 LOAD_STRING( pp_cache
[i
]->p_module
->psz_capability
);
1672 LOAD_IMMEDIATE( pp_cache
[i
]->p_module
->i_score
);
1673 LOAD_IMMEDIATE( pp_cache
[i
]->p_module
->i_cpu
);
1674 LOAD_IMMEDIATE( pp_cache
[i
]->p_module
->b_unloadable
);
1675 LOAD_IMMEDIATE( pp_cache
[i
]->p_module
->b_reentrant
);
1676 LOAD_IMMEDIATE( pp_cache
[i
]->p_module
->b_submodule
);
1679 if( CacheLoadConfig( pp_cache
[i
]->p_module
, file
) != VLC_SUCCESS
)
1682 LOAD_STRING( pp_cache
[i
]->p_module
->psz_filename
);
1684 LOAD_IMMEDIATE( i_submodules
);
1686 while( i_submodules
-- )
1688 module_t
*p_module
= vlc_object_create( p_this
, VLC_OBJECT_MODULE
);
1689 vlc_object_attach( p_module
, pp_cache
[i
]->p_module
);
1690 p_module
->b_submodule
= VLC_TRUE
;
1692 LOAD_STRING( p_module
->psz_object_name
);
1693 LOAD_STRING( p_module
->psz_shortname
);
1694 LOAD_STRING( p_module
->psz_longname
);
1695 LOAD_STRING( p_module
->psz_program
);
1696 for( j
= 0; j
< MODULE_SHORTCUT_MAX
; j
++ )
1698 LOAD_STRING( p_module
->pp_shortcuts
[j
] ); // FIX
1700 LOAD_STRING( p_module
->psz_capability
);
1701 LOAD_IMMEDIATE( p_module
->i_score
);
1702 LOAD_IMMEDIATE( p_module
->i_cpu
);
1703 LOAD_IMMEDIATE( p_module
->b_unloadable
);
1704 LOAD_IMMEDIATE( p_module
->b_reentrant
);
1713 msg_Warn( p_this
, "plugins cache not loaded (corrupted)" );
1716 p_this
->p_libvlc
->p_module_bank
->i_loaded_cache
= 0;
1722 int CacheLoadConfig( module_t
*p_module
, FILE *file
)
1727 /* Calculate the structure length */
1728 LOAD_IMMEDIATE( p_module
->i_config_items
);
1729 LOAD_IMMEDIATE( p_module
->i_bool_items
);
1731 LOAD_IMMEDIATE( i_lines
);
1733 /* Allocate memory */
1734 p_module
->p_config
=
1735 (module_config_t
*)malloc( sizeof(module_config_t
) * (i_lines
+ 1));
1736 if( p_module
->p_config
== NULL
)
1738 msg_Err( p_module
, "config error: can't duplicate p_config" );
1742 /* Do the duplication job */
1743 for( i
= 0; i
< i_lines
; i
++ )
1745 LOAD_IMMEDIATE( p_module
->p_config
[i
] );
1747 LOAD_STRING( p_module
->p_config
[i
].psz_type
);
1748 LOAD_STRING( p_module
->p_config
[i
].psz_name
);
1749 LOAD_STRING( p_module
->p_config
[i
].psz_text
);
1750 LOAD_STRING( p_module
->p_config
[i
].psz_longtext
);
1751 LOAD_STRING( p_module
->p_config
[i
].psz_value_orig
);
1753 p_module
->p_config
[i
].psz_value
=
1754 p_module
->p_config
[i
].psz_value_orig
?
1755 strdup( p_module
->p_config
[i
].psz_value_orig
) : 0;
1756 p_module
->p_config
[i
].i_value
= p_module
->p_config
[i
].i_value_orig
;
1757 p_module
->p_config
[i
].f_value
= p_module
->p_config
[i
].f_value_orig
;
1759 p_module
->p_config
[i
].p_lock
= &p_module
->object_lock
;
1761 if( p_module
->p_config
[i
].i_list
)
1763 if( p_module
->p_config
[i
].ppsz_list
)
1765 p_module
->p_config
[i
].ppsz_list
=
1766 malloc( (p_module
->p_config
[i
].i_list
+1) * sizeof(char *));
1767 if( p_module
->p_config
[i
].ppsz_list
)
1769 for( j
= 0; j
< p_module
->p_config
[i
].i_list
; j
++ )
1770 LOAD_STRING( p_module
->p_config
[i
].ppsz_list
[j
] );
1771 p_module
->p_config
[i
].ppsz_list
[j
] = NULL
;
1774 if( p_module
->p_config
[i
].ppsz_list_text
)
1776 p_module
->p_config
[i
].ppsz_list_text
=
1777 malloc( (p_module
->p_config
[i
].i_list
+1) * sizeof(char *));
1778 if( p_module
->p_config
[i
].ppsz_list_text
)
1780 for( j
= 0; j
< p_module
->p_config
[i
].i_list
; j
++ )
1781 LOAD_STRING( p_module
->p_config
[i
].ppsz_list_text
[j
] );
1782 p_module
->p_config
[i
].ppsz_list_text
[j
] = NULL
;
1785 if( p_module
->p_config
[i
].pi_list
)
1787 p_module
->p_config
[i
].pi_list
=
1788 malloc( (p_module
->p_config
[i
].i_list
+ 1) * sizeof(int) );
1789 if( p_module
->p_config
[i
].pi_list
)
1791 for( j
= 0; j
< p_module
->p_config
[i
].i_list
; j
++ )
1792 LOAD_IMMEDIATE( p_module
->p_config
[i
].pi_list
[j
] );
1797 if( p_module
->p_config
[i
].i_action
)
1799 p_module
->p_config
[i
].ppf_action
=
1800 malloc( p_module
->p_config
[i
].i_action
* sizeof(void *) );
1801 p_module
->p_config
[i
].ppsz_action_text
=
1802 malloc( p_module
->p_config
[i
].i_action
* sizeof(char *) );
1804 for( j
= 0; j
< p_module
->p_config
[i
].i_action
; j
++ )
1806 p_module
->p_config
[i
].ppf_action
[j
] = 0;
1807 LOAD_STRING( p_module
->p_config
[i
].ppsz_action_text
[j
] );
1811 LOAD_IMMEDIATE( p_module
->p_config
[i
].pf_callback
);
1814 p_module
->p_config
[i
].i_type
= CONFIG_HINT_END
;
1820 return VLC_EGENERIC
;
1823 /*****************************************************************************
1824 * SavePluginsCache: saves the plugins cache to a file
1825 *****************************************************************************/
1826 static void CacheSave( vlc_object_t
*p_this
)
1828 static char const psz_tag
[] =
1829 "Signature: 8a477f597d28d172789f06886806bc55\r\n"
1830 "# This file is a cache directory tag created by VLC.\r\n"
1831 "# For information about cache directory tags, see:\r\n"
1832 "# http://www.brynosaurus.com/cachedir/\r\n";
1834 char *psz_filename
, *psz_homedir
;
1837 module_cache_t
**pp_cache
;
1838 int32_t i_file_size
= 0;
1840 psz_homedir
= p_this
->p_vlc
->psz_homedir
;
1843 msg_Err( p_this
, "psz_homedir is null" );
1847 (char *)malloc( sizeof("/" CONFIG_DIR
"/" PLUGINSCACHE_DIR
"/" ) +
1848 strlen(psz_homedir
) + strlen(CacheName()) );
1852 msg_Err( p_this
, "out of memory" );
1856 sprintf( psz_filename
, "%s/%s", psz_homedir
, CONFIG_DIR
);
1858 config_CreateDir( p_this
, psz_filename
);
1860 strcat( psz_filename
, "/" PLUGINSCACHE_DIR
);
1862 config_CreateDir( p_this
, psz_filename
);
1864 strcat( psz_filename
, "/CACHEDIR.TAG" );
1866 file
= fopen( psz_filename
, "wb" );
1869 fwrite( psz_tag
, 1, strlen(psz_tag
), file
);
1873 sprintf( psz_filename
, "%s/%s/%s/%s", psz_homedir
, CONFIG_DIR
,
1874 PLUGINSCACHE_DIR
, CacheName() );
1876 msg_Dbg( p_this
, "saving plugins cache file %s", psz_filename
);
1878 file
= fopen( psz_filename
, "wb" );
1881 msg_Warn( p_this
, "could not open plugins cache file %s for writing",
1883 free( psz_filename
);
1886 free( psz_filename
);
1888 /* Empty space for file size */
1889 fwrite( &i_file_size
, sizeof(char), sizeof(i_file_size
), file
);
1891 /* Contains version number */
1892 fprintf( file
, "%s", PLUGINSCACHE_DIR COPYRIGHT_MESSAGE
);
1894 i_cache
= p_this
->p_libvlc
->p_module_bank
->i_cache
;
1895 pp_cache
= p_this
->p_libvlc
->p_module_bank
->pp_cache
;
1897 fwrite( &i_cache
, sizeof(char), sizeof(i_cache
), file
);
1899 #define SAVE_IMMEDIATE(a) \
1900 fwrite( &a, sizeof(char), sizeof(a), file )
1901 #define SAVE_STRING(a) \
1902 { i_size = a ? strlen( a ) + 1 : 0; \
1903 fwrite( &i_size, sizeof(char), sizeof(i_size), file ); \
1904 if( a ) fwrite( a, sizeof(char), i_size, file ); \
1907 for( i
= 0; i
< i_cache
; i
++ )
1910 int32_t i_submodule
;
1912 /* Save common info */
1913 SAVE_STRING( pp_cache
[i
]->psz_file
);
1914 SAVE_IMMEDIATE( pp_cache
[i
]->i_time
);
1915 SAVE_IMMEDIATE( pp_cache
[i
]->i_size
);
1916 SAVE_IMMEDIATE( pp_cache
[i
]->b_junk
);
1918 if( pp_cache
[i
]->b_junk
) continue;
1920 /* Save additional infos */
1921 SAVE_STRING( pp_cache
[i
]->p_module
->psz_object_name
);
1922 SAVE_STRING( pp_cache
[i
]->p_module
->psz_shortname
);
1923 SAVE_STRING( pp_cache
[i
]->p_module
->psz_longname
);
1924 SAVE_STRING( pp_cache
[i
]->p_module
->psz_program
);
1925 for( j
= 0; j
< MODULE_SHORTCUT_MAX
; j
++ )
1927 SAVE_STRING( pp_cache
[i
]->p_module
->pp_shortcuts
[j
] ); // FIX
1929 SAVE_STRING( pp_cache
[i
]->p_module
->psz_capability
);
1930 SAVE_IMMEDIATE( pp_cache
[i
]->p_module
->i_score
);
1931 SAVE_IMMEDIATE( pp_cache
[i
]->p_module
->i_cpu
);
1932 SAVE_IMMEDIATE( pp_cache
[i
]->p_module
->b_unloadable
);
1933 SAVE_IMMEDIATE( pp_cache
[i
]->p_module
->b_reentrant
);
1934 SAVE_IMMEDIATE( pp_cache
[i
]->p_module
->b_submodule
);
1937 CacheSaveConfig( pp_cache
[i
]->p_module
, file
);
1939 SAVE_STRING( pp_cache
[i
]->p_module
->psz_filename
);
1941 i_submodule
= pp_cache
[i
]->p_module
->i_children
;
1942 SAVE_IMMEDIATE( i_submodule
);
1943 for( i_submodule
= 0; i_submodule
< pp_cache
[i
]->p_module
->i_children
;
1946 module_t
*p_module
=
1947 (module_t
*)pp_cache
[i
]->p_module
->pp_children
[i_submodule
];
1949 SAVE_STRING( p_module
->psz_object_name
);
1950 SAVE_STRING( p_module
->psz_shortname
);
1951 SAVE_STRING( p_module
->psz_longname
);
1952 SAVE_STRING( p_module
->psz_program
);
1953 for( j
= 0; j
< MODULE_SHORTCUT_MAX
; j
++ )
1955 SAVE_STRING( p_module
->pp_shortcuts
[j
] ); // FIX
1957 SAVE_STRING( p_module
->psz_capability
);
1958 SAVE_IMMEDIATE( p_module
->i_score
);
1959 SAVE_IMMEDIATE( p_module
->i_cpu
);
1960 SAVE_IMMEDIATE( p_module
->b_unloadable
);
1961 SAVE_IMMEDIATE( p_module
->b_reentrant
);
1965 /* Fill-up file size */
1966 i_file_size
= ftell( file
);
1967 fseek( file
, 0, SEEK_SET
);
1968 fwrite( &i_file_size
, sizeof(char), sizeof(i_file_size
), file
);
1975 void CacheSaveConfig( module_t
*p_module
, FILE *file
)
1977 int i
, j
, i_lines
= 0;
1978 module_config_t
*p_item
;
1981 SAVE_IMMEDIATE( p_module
->i_config_items
);
1982 SAVE_IMMEDIATE( p_module
->i_bool_items
);
1984 for( p_item
= p_module
->p_config
; p_item
->i_type
!= CONFIG_HINT_END
;
1985 p_item
++ ) i_lines
++;
1987 SAVE_IMMEDIATE( i_lines
);
1989 for( i
= 0; i
< i_lines
; i
++ )
1991 SAVE_IMMEDIATE( p_module
->p_config
[i
] );
1993 SAVE_STRING( p_module
->p_config
[i
].psz_type
);
1994 SAVE_STRING( p_module
->p_config
[i
].psz_name
);
1995 SAVE_STRING( p_module
->p_config
[i
].psz_text
);
1996 SAVE_STRING( p_module
->p_config
[i
].psz_longtext
);
1997 SAVE_STRING( p_module
->p_config
[i
].psz_value_orig
);
1999 if( p_module
->p_config
[i
].i_list
)
2001 if( p_module
->p_config
[i
].ppsz_list
)
2003 for( j
= 0; j
< p_module
->p_config
[i
].i_list
; j
++ )
2004 SAVE_STRING( p_module
->p_config
[i
].ppsz_list
[j
] );
2007 if( p_module
->p_config
[i
].ppsz_list_text
)
2009 for( j
= 0; j
< p_module
->p_config
[i
].i_list
; j
++ )
2010 SAVE_STRING( p_module
->p_config
[i
].ppsz_list_text
[j
] );
2012 if( p_module
->p_config
[i
].pi_list
)
2014 for( j
= 0; j
< p_module
->p_config
[i
].i_list
; j
++ )
2015 SAVE_IMMEDIATE( p_module
->p_config
[i
].pi_list
[j
] );
2019 for( j
= 0; j
< p_module
->p_config
[i
].i_action
; j
++ )
2020 SAVE_STRING( p_module
->p_config
[i
].ppsz_action_text
[j
] );
2022 SAVE_IMMEDIATE( p_module
->p_config
[i
].pf_callback
);
2026 /*****************************************************************************
2027 * CacheName: Return the cache file name for this platform.
2028 *****************************************************************************/
2029 static char *CacheName( void )
2031 static char psz_cachename
[32];
2032 static vlc_bool_t b_initialised
= VLC_FALSE
;
2034 if( !b_initialised
)
2036 /* Code int size, pointer size and endianness in the filename */
2037 int32_t x
= 0xbe00001e;
2038 sprintf( psz_cachename
, "plugins-%.2x%.2x%.2x.dat", sizeof(int),
2039 sizeof(void *), (unsigned int)((unsigned char *)&x
)[0] );
2040 b_initialised
= VLC_TRUE
;
2043 return psz_cachename
;
2046 /*****************************************************************************
2047 * CacheMerge: Merge a cache module descriptor with a full module descriptor.
2048 *****************************************************************************/
2049 static void CacheMerge( vlc_object_t
*p_this
, module_t
*p_cache
,
2050 module_t
*p_module
)
2054 p_cache
->pf_activate
= p_module
->pf_activate
;
2055 p_cache
->pf_deactivate
= p_module
->pf_deactivate
;
2056 p_cache
->p_symbols
= p_module
->p_symbols
;
2057 p_cache
->handle
= p_module
->handle
;
2059 for( i_submodule
= 0; i_submodule
< p_module
->i_children
; i_submodule
++ )
2061 module_t
*p_child
= (module_t
*)p_module
->pp_children
[i_submodule
];
2062 module_t
*p_cchild
= (module_t
*)p_cache
->pp_children
[i_submodule
];
2063 p_cchild
->pf_activate
= p_child
->pf_activate
;
2064 p_cchild
->pf_deactivate
= p_child
->pf_deactivate
;
2065 p_cchild
->p_symbols
= p_child
->p_symbols
;
2068 p_cache
->b_loaded
= VLC_TRUE
;
2069 p_module
->b_loaded
= VLC_FALSE
;
2072 /*****************************************************************************
2073 * FindPluginCache: finds the cache entry corresponding to a file
2074 *****************************************************************************/
2075 static module_cache_t
*CacheFind( vlc_object_t
*p_this
, char *psz_file
,
2076 int64_t i_time
, int64_t i_size
)
2078 module_cache_t
**pp_cache
;
2081 pp_cache
= p_this
->p_libvlc
->p_module_bank
->pp_loaded_cache
;
2082 i_cache
= p_this
->p_libvlc
->p_module_bank
->i_loaded_cache
;
2084 for( i
= 0; i
< i_cache
; i
++ )
2086 if( !strcmp( pp_cache
[i
]->psz_file
, psz_file
) &&
2087 pp_cache
[i
]->i_time
== i_time
&&
2088 pp_cache
[i
]->i_size
== i_size
) return pp_cache
[i
];
2094 #endif /* HAVE_DYNAMIC_PLUGINS */