00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifdef _FILE_OFFSET_BITS
00030 #undef _FILE_OFFSET_BITS
00031 #endif
00032
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036
00037 #include <vlc/vlc.h>
00038 #include <vlc/input.h>
00039
00040 #ifdef HAVE_DIRENT_H
00041 # include <dirent.h>
00042 #endif
00043
00044 #ifdef HAVE_SYS_TYPES_H
00045 # include <sys/types.h>
00046 #endif
00047 #ifdef HAVE_SYS_STAT_H
00048 # include <sys/stat.h>
00049 #endif
00050 #ifdef HAVE_UNISTD_H
00051 # include <unistd.h>
00052 #endif
00053
00054 #if !defined(HAVE_DYNAMIC_PLUGINS)
00055
00056 #elif defined(HAVE_DL_DYLD)
00057 # if defined(HAVE_MACH_O_DYLD_H)
00058 # include <mach-o/dyld.h>
00059 # endif
00060 #elif defined(HAVE_DL_BEOS)
00061 # if defined(HAVE_IMAGE_H)
00062 # include <image.h>
00063 # endif
00064 #elif defined(HAVE_DL_WINDOWS)
00065 # include <windows.h>
00066 #elif defined(HAVE_DL_DLOPEN)
00067 # if defined(HAVE_DLFCN_H)
00068 # include <dlfcn.h>
00069 # endif
00070 # if defined(HAVE_SYS_DL_H)
00071 # include <sys/dl.h>
00072 # endif
00073 #elif defined(HAVE_DL_SHL_LOAD)
00074 # if defined(HAVE_DL_H)
00075 # include <dl.h>
00076 # endif
00077 #endif
00078
00079 #include "vlc_error.h"
00080
00081 #include "vlc_interface.h"
00082 #include "intf_eject.h"
00083
00084 #include "vlc_playlist.h"
00085
00086 #include "vlc_video.h"
00087 #include "video_output.h"
00088 #include "vout_synchro.h"
00089 #include "vlc_spu.h"
00090
00091 #include "audio_output.h"
00092 #include "aout_internal.h"
00093
00094 #include "stream_output.h"
00095 #include "vlc_httpd.h"
00096 #include "vlc_acl.h"
00097 #include "vlc_tls.h"
00098 #include "vlc_md5.h"
00099 #include "vlc_xml.h"
00100
00101 #include "iso_lang.h"
00102 #include "charset.h"
00103
00104 #include "vlc_block.h"
00105
00106 #include "vlc_vlm.h"
00107
00108 #include "vlc_image.h"
00109 #include "vlc_osd.h"
00110
00111 #if defined( _MSC_VER ) && defined( UNDER_CE )
00112 # include "modules_builtin_evc.h"
00113 #elif defined( _MSC_VER )
00114 # include "modules_builtin_msvc.h"
00115 #else
00116 # include "modules_builtin.h"
00117 #endif
00118 #include "network.h"
00119
00120 #if defined( WIN32 ) || defined( UNDER_CE )
00121
00122 # define LoadModule(a,b,c) LoadVlcModule(a,b,c)
00123 #endif
00124
00125
00126
00127
00128 #ifdef HAVE_DYNAMIC_PLUGINS
00129 static void AllocateAllPlugins ( vlc_object_t * );
00130 static void AllocatePluginDir ( vlc_object_t *, const char *, int );
00131 static int AllocatePluginFile ( vlc_object_t *, char *, int64_t, int64_t );
00132 static module_t * AllocatePlugin( vlc_object_t *, char * );
00133 #endif
00134 static int AllocateBuiltinModule( vlc_object_t *, int ( * ) ( module_t * ) );
00135 static int DeleteModule ( module_t * );
00136 #ifdef HAVE_DYNAMIC_PLUGINS
00137 static void DupModule ( module_t * );
00138 static void UndupModule ( module_t * );
00139 static int CallEntry ( module_t * );
00140 static int LoadModule ( vlc_object_t *, char *, module_handle_t * );
00141 static void CloseModule ( module_handle_t );
00142 static void * GetSymbol ( module_handle_t, const char * );
00143 static void CacheLoad ( vlc_object_t * );
00144 static int CacheLoadConfig ( module_t *, FILE * );
00145 static void CacheSave ( vlc_object_t * );
00146 static void CacheSaveConfig ( module_t *, FILE * );
00147 static char * CacheName ( void );
00148 static void CacheMerge ( vlc_object_t *, module_t *, module_t * );
00149 static module_cache_t * CacheFind( vlc_object_t *, char *, int64_t, int64_t );
00150
00151 #if defined(HAVE_DL_WINDOWS)
00152 static char * GetWindowsError ( void );
00153 #endif
00154 #endif
00155
00156
00157
00158
00159 #define CACHE_SUBVERSION_NUM 1
00160
00161
00162
00163
00164
00165
00166
00167 void __module_InitBank( vlc_object_t *p_this )
00168 {
00169 module_bank_t *p_bank;
00170 vlc_value_t lockval;
00171
00172 var_Create( p_this->p_libvlc, "libvlc", VLC_VAR_MUTEX );
00173 var_Get( p_this->p_libvlc, "libvlc", &lockval );
00174 vlc_mutex_lock( lockval.p_address );
00175 if( p_this->p_libvlc->p_module_bank )
00176 {
00177 p_this->p_libvlc->p_module_bank->i_usage++;
00178 vlc_mutex_unlock( lockval.p_address );
00179 var_Destroy( p_this->p_libvlc, "libvlc" );
00180 return;
00181 }
00182 vlc_mutex_unlock( lockval.p_address );
00183 var_Destroy( p_this->p_libvlc, "libvlc" );
00184
00185 p_bank = vlc_object_create( p_this, sizeof(module_bank_t) );
00186 p_bank->psz_object_name = "module bank";
00187 p_bank->i_usage = 1;
00188 p_bank->i_cache = p_bank->i_loaded_cache = 0;
00189 p_bank->pp_cache = p_bank->pp_loaded_cache = 0;
00190 p_bank->b_cache = p_bank->b_cache_dirty =
00191 p_bank->b_cache_delete = VLC_FALSE;
00192
00193
00194
00195
00196 #if defined (HAVE_DYNAMIC_PLUGINS) && !defined (HAVE_SHARED_LIBVLC)
00197 STORE_SYMBOLS( &p_bank->symbols );
00198 #endif
00199
00200
00201 p_this->p_libvlc->p_module_bank = p_bank;
00202 vlc_object_attach( p_bank, p_this->p_libvlc );
00203
00204 module_LoadMain( p_this );
00205
00206 return;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 void __module_ResetBank( vlc_object_t *p_this )
00216 {
00217 msg_Err( p_this, "FIXME: module_ResetBank unimplemented" );
00218 return;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227 void __module_EndBank( vlc_object_t *p_this )
00228 {
00229 module_t * p_next;
00230 vlc_value_t lockval;
00231
00232 var_Create( p_this->p_libvlc, "libvlc", VLC_VAR_MUTEX );
00233 var_Get( p_this->p_libvlc, "libvlc", &lockval );
00234 vlc_mutex_lock( lockval.p_address );
00235 if( !p_this->p_libvlc->p_module_bank )
00236 {
00237 vlc_mutex_unlock( lockval.p_address );
00238 var_Destroy( p_this->p_libvlc, "libvlc" );
00239 return;
00240 }
00241 if( --p_this->p_libvlc->p_module_bank->i_usage )
00242 {
00243 vlc_mutex_unlock( lockval.p_address );
00244 var_Destroy( p_this->p_libvlc, "libvlc" );
00245 return;
00246 }
00247 vlc_mutex_unlock( lockval.p_address );
00248 var_Destroy( p_this->p_libvlc, "libvlc" );
00249
00250 config_AutoSaveConfigFile( p_this );
00251
00252 #ifdef HAVE_DYNAMIC_PLUGINS
00253 #define p_bank p_this->p_libvlc->p_module_bank
00254 if( p_bank->b_cache ) CacheSave( p_this );
00255 while( p_bank->i_loaded_cache-- )
00256 {
00257 free( p_bank->pp_loaded_cache[p_bank->i_loaded_cache]->psz_file );
00258 free( p_bank->pp_loaded_cache[p_bank->i_loaded_cache] );
00259 }
00260 if( p_bank->pp_loaded_cache )
00261 free( p_bank->pp_loaded_cache );
00262
00263 while( p_bank->i_cache-- )
00264 {
00265 free( p_bank->pp_cache[p_bank->i_cache]->psz_file );
00266 free( p_bank->pp_cache[p_bank->i_cache] );
00267 }
00268 if( p_bank->pp_cache )
00269 free( p_bank->pp_cache );
00270 #undef p_bank
00271 #endif
00272
00273 vlc_object_detach( p_this->p_libvlc->p_module_bank );
00274
00275 while( p_this->p_libvlc->p_module_bank->i_children )
00276 {
00277 p_next = (module_t *)p_this->p_libvlc->p_module_bank->pp_children[0];
00278
00279 if( DeleteModule( p_next ) )
00280 {
00281
00282 msg_Err( p_this, "module \"%s\" can't be removed, trying harder",
00283 p_next->psz_object_name );
00284
00285
00286 vlc_object_detach( p_next );
00287 vlc_object_destroy( p_next );
00288 }
00289 }
00290
00291 vlc_object_destroy( p_this->p_libvlc->p_module_bank );
00292 p_this->p_libvlc->p_module_bank = NULL;
00293
00294 return;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 void __module_LoadMain( vlc_object_t *p_this )
00306 {
00307 vlc_value_t lockval;
00308
00309 var_Create( p_this->p_libvlc, "libvlc", VLC_VAR_MUTEX );
00310 var_Get( p_this->p_libvlc, "libvlc", &lockval );
00311 vlc_mutex_lock( lockval.p_address );
00312 if( p_this->p_libvlc->p_module_bank->b_main )
00313 {
00314 vlc_mutex_unlock( lockval.p_address );
00315 var_Destroy( p_this->p_libvlc, "libvlc" );
00316 return;
00317 }
00318 p_this->p_libvlc->p_module_bank->b_main = VLC_TRUE;
00319 vlc_mutex_unlock( lockval.p_address );
00320 var_Destroy( p_this->p_libvlc, "libvlc" );
00321
00322 AllocateBuiltinModule( p_this, vlc_entry__main );
00323 }
00324
00325
00326
00327
00328
00329
00330 void __module_LoadBuiltins( vlc_object_t * p_this )
00331 {
00332 vlc_value_t lockval;
00333
00334 var_Create( p_this->p_libvlc, "libvlc", VLC_VAR_MUTEX );
00335 var_Get( p_this->p_libvlc, "libvlc", &lockval );
00336 vlc_mutex_lock( lockval.p_address );
00337 if( p_this->p_libvlc->p_module_bank->b_builtins )
00338 {
00339 vlc_mutex_unlock( lockval.p_address );
00340 var_Destroy( p_this->p_libvlc, "libvlc" );
00341 return;
00342 }
00343 p_this->p_libvlc->p_module_bank->b_builtins = VLC_TRUE;
00344 vlc_mutex_unlock( lockval.p_address );
00345 var_Destroy( p_this->p_libvlc, "libvlc" );
00346
00347 msg_Dbg( p_this, "checking builtin modules" );
00348 ALLOCATE_ALL_BUILTINS();
00349 }
00350
00351
00352
00353
00354
00355
00356 void __module_LoadPlugins( vlc_object_t * p_this )
00357 {
00358 #ifdef HAVE_DYNAMIC_PLUGINS
00359 vlc_value_t lockval;
00360
00361 var_Create( p_this->p_libvlc, "libvlc", VLC_VAR_MUTEX );
00362 var_Get( p_this->p_libvlc, "libvlc", &lockval );
00363 vlc_mutex_lock( lockval.p_address );
00364 if( p_this->p_libvlc->p_module_bank->b_plugins )
00365 {
00366 vlc_mutex_unlock( lockval.p_address );
00367 var_Destroy( p_this->p_libvlc, "libvlc" );
00368 return;
00369 }
00370 p_this->p_libvlc->p_module_bank->b_plugins = VLC_TRUE;
00371 vlc_mutex_unlock( lockval.p_address );
00372 var_Destroy( p_this->p_libvlc, "libvlc" );
00373
00374 msg_Dbg( p_this, "checking plugin modules" );
00375
00376 if( config_GetInt( p_this, "plugins-cache" ) )
00377 p_this->p_libvlc->p_module_bank->b_cache = VLC_TRUE;
00378
00379 if( p_this->p_libvlc->p_module_bank->b_cache ||
00380 p_this->p_libvlc->p_module_bank->b_cache_delete ) CacheLoad( p_this );
00381
00382 AllocateAllPlugins( p_this );
00383 #endif
00384 }
00385
00386
00387
00388
00389
00390
00391 module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
00392 const char *psz_name, vlc_bool_t b_strict )
00393 {
00394 typedef struct module_list_t module_list_t;
00395
00396 struct module_list_t
00397 {
00398 module_t *p_module;
00399 int i_score;
00400 vlc_bool_t b_force;
00401 module_list_t *p_next;
00402 };
00403
00404 module_list_t *p_list, *p_first, *p_tmp;
00405 vlc_list_t *p_all;
00406
00407 int i_which_module, i_index = 0;
00408 vlc_bool_t b_intf = VLC_FALSE;
00409
00410 module_t *p_module;
00411
00412 int i_shortcuts = 0;
00413 char *psz_shortcuts = NULL, *psz_var = NULL;
00414 vlc_bool_t b_force_backup = p_this->b_force;
00415
00416
00417
00418 if( psz_name && psz_name[0] == '$' )
00419 {
00420 vlc_value_t val;
00421 var_Create( p_this, psz_name + 1, VLC_VAR_MODULE | VLC_VAR_DOINHERIT );
00422 var_Get( p_this, psz_name + 1, &val );
00423 psz_var = val.psz_string;
00424 psz_name = psz_var;
00425 }
00426
00427
00428 if( psz_name && *psz_name )
00429 {
00430 char *psz_parser, *psz_last_shortcut;
00431
00432
00433 if( !strcmp( psz_name, "none" ) )
00434 {
00435 if( psz_var ) free( psz_var );
00436 return NULL;
00437 }
00438
00439 i_shortcuts++;
00440 psz_shortcuts = psz_last_shortcut = strdup( psz_name );
00441
00442 for( psz_parser = psz_shortcuts; *psz_parser; psz_parser++ )
00443 {
00444 if( *psz_parser == ',' )
00445 {
00446 *psz_parser = '\0';
00447 i_shortcuts++;
00448 psz_last_shortcut = psz_parser + 1;
00449 }
00450 }
00451
00452
00453 if( psz_last_shortcut )
00454 {
00455 if( !strcmp(psz_last_shortcut, "none") )
00456 {
00457 b_strict = VLC_TRUE;
00458 i_shortcuts--;
00459 }
00460 else if( !strcmp(psz_last_shortcut, "any") )
00461 {
00462 b_strict = VLC_FALSE;
00463 i_shortcuts--;
00464 }
00465 }
00466 }
00467
00468
00469 p_all = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
00470 p_list = malloc( p_all->i_count * sizeof( module_list_t ) );
00471 p_first = NULL;
00472
00473
00474 for( i_which_module = 0; i_which_module < p_all->i_count; i_which_module++ )
00475 {
00476 int i_shortcut_bonus = 0;
00477
00478 p_module = (module_t *)p_all->p_values[i_which_module].p_object;
00479
00480
00481 if( strcmp( p_module->psz_capability, psz_capability ) )
00482 {
00483
00484
00485 continue;
00486 }
00487
00488
00489 if( (p_module->i_cpu & p_this->p_libvlc->i_cpu) != p_module->i_cpu )
00490 {
00491 continue;
00492 }
00493
00494
00495 if( i_shortcuts > 0 )
00496 {
00497 vlc_bool_t b_trash;
00498 int i_dummy, i_short = i_shortcuts;
00499 char *psz_name = psz_shortcuts;
00500
00501
00502
00503 b_trash = p_module->i_score <= 0;
00504
00505 while( i_short > 0 )
00506 {
00507 for( i_dummy = 0; p_module->pp_shortcuts[i_dummy]; i_dummy++ )
00508 {
00509 if( !strcasecmp( psz_name,
00510 p_module->pp_shortcuts[i_dummy] ) )
00511 {
00512
00513 b_trash = VLC_FALSE;
00514 i_shortcut_bonus = i_short * 10000;
00515 break;
00516 }
00517 }
00518
00519 if( i_shortcut_bonus )
00520 {
00521
00522 break;
00523 }
00524
00525
00526 while( *psz_name )
00527 {
00528 psz_name++;
00529 }
00530 psz_name++;
00531 i_short--;
00532 }
00533
00534
00535
00536
00537 if( i_short == 0 && b_strict )
00538 {
00539 b_trash = VLC_TRUE;
00540 }
00541
00542 if( b_trash )
00543 {
00544 continue;
00545 }
00546 }
00547
00548 else if( p_module->i_score <= 0 )
00549 {
00550 continue;
00551 }
00552
00553
00554 if( !i_shortcuts && p_module->psz_program
00555 && !strcmp( psz_capability, "interface" )
00556 && !strcmp( p_module->psz_program,
00557 p_this->p_vlc->psz_object_name ) )
00558 {
00559 if( !b_intf )
00560 {
00561
00562 i_index = 0;
00563 b_intf = VLC_TRUE;
00564 }
00565 }
00566 else if( b_intf )
00567 {
00568
00569 continue;
00570 }
00571
00572
00573 p_list[ i_index ].p_module = p_module;
00574 p_list[ i_index ].i_score = p_module->i_score + i_shortcut_bonus;
00575 p_list[ i_index ].b_force = !!i_shortcut_bonus;
00576
00577
00578 if( i_index == 0 )
00579 {
00580 p_list[ 0 ].p_next = NULL;
00581 p_first = p_list;
00582 }
00583 else
00584 {
00585
00586
00587
00588 module_list_t *p_newlist = p_first;
00589
00590 if( p_first->i_score < p_list[ i_index ].i_score )
00591 {
00592 p_list[ i_index ].p_next = p_first;
00593 p_first = &p_list[ i_index ];
00594 }
00595 else
00596 {
00597 while( p_newlist->p_next != NULL &&
00598 p_newlist->p_next->i_score >= p_list[ i_index ].i_score )
00599 {
00600 p_newlist = p_newlist->p_next;
00601 }
00602
00603 p_list[ i_index ].p_next = p_newlist->p_next;
00604 p_newlist->p_next = &p_list[ i_index ];
00605 }
00606 }
00607
00608 i_index++;
00609 }
00610
00611 msg_Dbg( p_this, "looking for %s module: %i candidate%s", psz_capability,
00612 i_index, i_index == 1 ? "" : "s" );
00613
00614
00615 p_tmp = p_first;
00616 while( p_tmp != NULL )
00617 {
00618 vlc_object_yield( p_tmp->p_module );
00619 p_tmp = p_tmp->p_next;
00620 }
00621
00622
00623 vlc_list_release( p_all );
00624
00625
00626 p_tmp = p_first;
00627 while( p_tmp != NULL )
00628 {
00629 #ifdef HAVE_DYNAMIC_PLUGINS
00630
00631 module_t *p_module = p_tmp->p_module->b_submodule ?
00632 (module_t *)p_tmp->p_module->p_parent : p_tmp->p_module;
00633 if( !p_module->b_builtin && !p_module->b_loaded )
00634 {
00635 module_t *p_new_module =
00636 AllocatePlugin( p_this, p_module->psz_filename );
00637 if( p_new_module )
00638 {
00639 CacheMerge( p_this, p_module, p_new_module );
00640 vlc_object_attach( p_new_module, p_module );
00641 DeleteModule( p_new_module );
00642 }
00643 }
00644 #endif
00645
00646 p_this->b_force = p_tmp->b_force;
00647 if( p_tmp->p_module->pf_activate
00648 && p_tmp->p_module->pf_activate( p_this ) == VLC_SUCCESS )
00649 {
00650 break;
00651 }
00652
00653 vlc_object_release( p_tmp->p_module );
00654 p_tmp = p_tmp->p_next;
00655 }
00656
00657
00658 if( p_tmp != NULL )
00659 {
00660 p_module = p_tmp->p_module;
00661 p_tmp = p_tmp->p_next;
00662 }
00663 else
00664 {
00665 p_module = NULL;
00666 }
00667
00668
00669 while( p_tmp != NULL )
00670 {
00671 vlc_object_release( p_tmp->p_module );
00672 p_tmp = p_tmp->p_next;
00673 }
00674
00675 free( p_list );
00676 p_this->b_force = b_force_backup;
00677
00678 if( p_module != NULL )
00679 {
00680 msg_Dbg( p_module, "using %s module \"%s\"",
00681 psz_capability, p_module->psz_object_name );
00682 }
00683 else if( p_first == NULL )
00684 {
00685 if( !strcmp( psz_capability, "access_demux" ) )
00686 {
00687 msg_Warn( p_this, "no %s module matched \"%s\"",
00688 psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
00689 }
00690 else
00691 {
00692 msg_Err( p_this, "no %s module matched \"%s\"",
00693 psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
00694 }
00695 }
00696 else if( psz_name != NULL && *psz_name )
00697 {
00698 msg_Warn( p_this, "no %s module matching \"%s\" could be loaded",
00699 psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
00700 }
00701
00702 if( psz_shortcuts )
00703 {
00704 free( psz_shortcuts );
00705 }
00706
00707 if( psz_var )
00708 {
00709 free( psz_var );
00710 }
00711
00712
00713 return p_module;
00714 }
00715
00716
00717
00718
00719
00720
00721
00722 void __module_Unneed( vlc_object_t * p_this, module_t * p_module )
00723 {
00724
00725 if( p_module->pf_deactivate )
00726 {
00727 p_module->pf_deactivate( p_this );
00728 }
00729
00730 msg_Dbg( p_module, "unlocking module \"%s\"", p_module->psz_object_name );
00731
00732 vlc_object_release( p_module );
00733
00734 return;
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744 #ifdef HAVE_DYNAMIC_PLUGINS
00745 static void AllocateAllPlugins( vlc_object_t *p_this )
00746 {
00747
00748 #if defined( WIN32 ) || defined( UNDER_CE )
00749 char *path[] = { "modules", "", "plugins", 0, 0 };
00750 #else
00751 char *path[] = { "modules", PLUGIN_PATH, "plugins", 0, 0 };
00752 #endif
00753
00754 char **ppsz_path = path;
00755 char *psz_fullpath;
00756
00757
00758 path[ sizeof(path)/sizeof(char*) - 2 ] =
00759 config_GetPsz( p_this, "plugin-path" );
00760
00761 for( ; *ppsz_path != NULL ; ppsz_path++ )
00762 {
00763 if( !(*ppsz_path)[0] ) continue;
00764
00765 #if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
00766
00767
00768 #ifdef WIN32
00769 if( (*ppsz_path)[0] != '\\' && (*ppsz_path)[0] != '/' &&
00770 (*ppsz_path)[1] != ':' )
00771 #else
00772 if( (*ppsz_path)[0] != '/' )
00773 #endif
00774 {
00775 int i_dirlen = strlen( *ppsz_path );
00776 i_dirlen += strlen( p_this->p_libvlc->psz_vlcpath ) + 2;
00777
00778 psz_fullpath = malloc( i_dirlen );
00779 if( psz_fullpath == NULL )
00780 {
00781 continue;
00782 }
00783 #ifdef WIN32
00784 sprintf( psz_fullpath, "%s\\%s",
00785 p_this->p_libvlc->psz_vlcpath, *ppsz_path );
00786 #else
00787 sprintf( psz_fullpath, "%s/%s",
00788 p_this->p_libvlc->psz_vlcpath, *ppsz_path );
00789 #endif
00790 }
00791 else
00792 #endif
00793 {
00794 psz_fullpath = strdup( *ppsz_path );
00795 }
00796
00797 msg_Dbg( p_this, "recursively browsing `%s'", psz_fullpath );
00798
00799
00800 AllocatePluginDir( p_this, psz_fullpath, 5 );
00801
00802 free( psz_fullpath );
00803 }
00804
00805
00806 if( path[ sizeof(path)/sizeof(char*) - 2 ] )
00807 free( path[ sizeof(path)/sizeof(char*) - 2 ] );
00808 path[ sizeof(path)/sizeof(char*) - 2 ] = NULL;
00809 }
00810
00811
00812
00813
00814 static void AllocatePluginDir( vlc_object_t *p_this, const char *psz_dir,
00815 int i_maxdepth )
00816 {
00817 #if defined( UNDER_CE ) || defined( _MSC_VER )
00818 #ifdef UNDER_CE
00819 wchar_t psz_wpath[MAX_PATH + 256];
00820 wchar_t psz_wdir[MAX_PATH];
00821 #endif
00822 char psz_path[MAX_PATH + 256];
00823 WIN32_FIND_DATA finddata;
00824 HANDLE handle;
00825 int rc;
00826 #else
00827 int i_dirlen;
00828 DIR * dir;
00829 struct dirent * file;
00830 #endif
00831 char * psz_file;
00832
00833 if( p_this->p_vlc->b_die || i_maxdepth < 0 )
00834 {
00835 return;
00836 }
00837
00838 #if defined( UNDER_CE ) || defined( _MSC_VER )
00839 #ifdef UNDER_CE
00840 MultiByteToWideChar( CP_ACP, 0, psz_dir, -1, psz_wdir, MAX_PATH );
00841
00842 rc = GetFileAttributes( psz_wdir );
00843 if( rc<0 || !(rc&FILE_ATTRIBUTE_DIRECTORY) ) return;
00844
00845
00846 swprintf( psz_wpath, L"%ls\\*", psz_wdir );
00847 #else
00848 rc = GetFileAttributes( psz_dir );
00849 if( rc<0 || !(rc&FILE_ATTRIBUTE_DIRECTORY) ) return;
00850 #endif
00851
00852
00853 sprintf( psz_path, "%s\\*", psz_dir );
00854
00855 #ifdef UNDER_CE
00856 handle = FindFirstFile( psz_wpath, &finddata );
00857 #else
00858 handle = FindFirstFile( psz_path, &finddata );
00859 #endif
00860 if( handle == INVALID_HANDLE_VALUE )
00861 {
00862
00863 return;
00864 }
00865
00866
00867 do
00868 {
00869 #ifdef UNDER_CE
00870 unsigned int i_len = wcslen( finddata.cFileName );
00871 swprintf( psz_wpath, L"%ls\\%ls", psz_wdir, finddata.cFileName );
00872 sprintf( psz_path, "%s\\%ls", psz_dir, finddata.cFileName );
00873 #else
00874 unsigned int i_len = strlen( finddata.cFileName );
00875 sprintf( psz_path, "%s\\%s", psz_dir, finddata.cFileName );
00876 #endif
00877
00878
00879 if( !*finddata.cFileName || *finddata.cFileName == '.' )
00880 {
00881 if( !FindNextFile( handle, &finddata ) ) break;
00882 continue;
00883 }
00884
00885 #ifdef UNDER_CE
00886 if( GetFileAttributes( psz_wpath ) & FILE_ATTRIBUTE_DIRECTORY )
00887 #else
00888 if( GetFileAttributes( psz_path ) & FILE_ATTRIBUTE_DIRECTORY )
00889 #endif
00890 {
00891 AllocatePluginDir( p_this, psz_path, i_maxdepth - 1 );
00892 }
00893 else if( i_len > strlen( LIBEXT )
00894
00895 && !strncasecmp( psz_path + strlen( psz_path)
00896 - strlen( LIBEXT ),
00897 LIBEXT, strlen( LIBEXT ) ) )
00898 {
00899 WIN32_FILE_ATTRIBUTE_DATA attrbuf;
00900 int64_t i_time = 0, i_size = 0;
00901
00902 #ifdef UNDER_CE
00903 if( GetFileAttributesEx( psz_wpath, GetFileExInfoStandard,
00904 &attrbuf ) )
00905 #else
00906 if( GetFileAttributesEx( psz_path, GetFileExInfoStandard,
00907 &attrbuf ) )
00908 #endif
00909 {
00910 i_time = attrbuf.ftLastWriteTime.dwHighDateTime;
00911 i_time <<= 32;
00912 i_time |= attrbuf.ftLastWriteTime.dwLowDateTime;
00913 i_size = attrbuf.nFileSizeHigh;
00914 i_size <<= 32;
00915 i_size |= attrbuf.nFileSizeLow;
00916 }
00917 psz_file = psz_path;
00918
00919 AllocatePluginFile( p_this, psz_file, i_time, i_size );
00920 }
00921 }
00922 while( !p_this->p_vlc->b_die && FindNextFile( handle, &finddata ) );
00923
00924
00925 FindClose( handle );
00926
00927 #else
00928 dir = opendir( psz_dir );
00929 if( !dir )
00930 {
00931 return;
00932 }
00933
00934 i_dirlen = strlen( psz_dir );
00935
00936
00937 while( !p_this->p_vlc->b_die && (file = readdir( dir )) )
00938 {
00939 struct stat statbuf;
00940 unsigned int i_len;
00941 int i_stat;
00942
00943
00944 if( !*file->d_name || *file->d_name == '.' )
00945 {
00946 continue;
00947 }
00948
00949 i_len = strlen( file->d_name );
00950 psz_file = malloc( i_dirlen + 1 + i_len + 1 );
00951 #ifdef WIN32
00952 sprintf( psz_file, "%s\\%s", psz_dir, file->d_name );
00953 #else
00954 sprintf( psz_file, "%s/%s", psz_dir, file->d_name );
00955 #endif
00956
00957 i_stat = stat( psz_file, &statbuf );
00958 if( !i_stat && statbuf.st_mode & S_IFDIR )
00959 {
00960 AllocatePluginDir( p_this, psz_file, i_maxdepth - 1 );
00961 }
00962 else if( i_len > strlen( LIBEXT )
00963
00964 && !strncasecmp( file->d_name + i_len - strlen( LIBEXT ),
00965 LIBEXT, strlen( LIBEXT ) ) )
00966 {
00967 int64_t i_time = 0, i_size = 0;
00968
00969 if( !i_stat )
00970 {
00971 i_time = statbuf.st_mtime;
00972 i_size = statbuf.st_size;
00973 }
00974
00975 AllocatePluginFile( p_this, psz_file, i_time, i_size );
00976 }
00977
00978 free( psz_file );
00979 }
00980
00981
00982 closedir( dir );
00983
00984 #endif
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994 static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
00995 int64_t i_file_time, int64_t i_file_size )
00996 {
00997 module_t * p_module;
00998 module_cache_t *p_cache_entry = NULL;
00999
01000
01001
01002
01003 p_cache_entry =
01004 CacheFind( p_this, psz_file, i_file_time, i_file_size );
01005
01006 if( !p_cache_entry )
01007 {
01008 p_module = AllocatePlugin( p_this, psz_file );
01009 }
01010 else
01011 {
01012
01013 if( p_cache_entry->b_junk )
01014 {
01015 p_module = NULL;
01016 }
01017 else
01018 {
01019 module_config_t *p_item;
01020
01021 p_module = p_cache_entry->p_module;
01022 p_module->b_loaded = VLC_FALSE;
01023
01024
01025
01026
01027 for( p_item = p_module->p_config;
01028 p_item->i_type != CONFIG_HINT_END; p_item++ )
01029 {
01030 if( p_item->pf_callback || p_item->i_action )
01031 p_module = AllocatePlugin( p_this, psz_file );
01032 }
01033 }
01034 }
01035
01036 if( p_module )
01037 {
01038
01039
01040 p_module->b_builtin = VLC_FALSE;
01041
01042
01043
01044
01045 vlc_object_attach( p_module, p_this->p_libvlc->p_module_bank );
01046 }
01047
01048 if( !p_this->p_libvlc->p_module_bank->b_cache ) return 0;
01049
01050
01051 #define p_bank p_this->p_libvlc->p_module_bank
01052 p_bank->pp_cache =
01053 realloc( p_bank->pp_cache, (p_bank->i_cache + 1) * sizeof(void *) );
01054 p_bank->pp_cache[p_bank->i_cache] = malloc( sizeof(module_cache_t) );
01055 p_bank->pp_cache[p_bank->i_cache]->psz_file = strdup( psz_file );
01056 p_bank->pp_cache[p_bank->i_cache]->i_time = i_file_time;
01057 p_bank->pp_cache[p_bank->i_cache]->i_size = i_file_size;
01058 p_bank->pp_cache[p_bank->i_cache]->b_junk = p_module ? 0 : 1;
01059 p_bank->pp_cache[p_bank->i_cache]->p_module = p_module;
01060 p_bank->i_cache++;
01061
01062 return p_module ? 0 : -1;
01063 }
01064
01065
01066
01067
01068
01069
01070
01071
01072 static module_t * AllocatePlugin( vlc_object_t * p_this, char * psz_file )
01073 {
01074 module_t * p_module;
01075 module_handle_t handle;
01076
01077 if( LoadModule( p_this, psz_file, &handle ) ) return NULL;
01078
01079
01080
01081 p_module = vlc_object_create( p_this, VLC_OBJECT_MODULE );
01082 if( p_module == NULL )
01083 {
01084 msg_Err( p_this, "out of memory" );
01085 CloseModule( handle );
01086 return NULL;
01087 }
01088
01089
01090 p_module->psz_filename = psz_file;
01091 p_module->handle = handle;
01092 #ifndef HAVE_SHARED_LIBVLC
01093 p_module->p_symbols = &p_this->p_libvlc->p_module_bank->symbols;
01094 #endif
01095 p_module->b_loaded = VLC_TRUE;
01096
01097
01098 if( CallEntry( p_module ) != 0 )
01099 {
01100
01101 vlc_object_destroy( p_module );
01102 CloseModule( handle );
01103 return NULL;
01104 }
01105
01106 DupModule( p_module );
01107 p_module->psz_filename = strdup( p_module->psz_filename );
01108
01109
01110 p_module->b_builtin = VLC_FALSE;
01111
01112 return p_module;
01113 }
01114
01115
01116
01117
01118
01119
01120
01121 static void DupModule( module_t *p_module )
01122 {
01123 char **pp_shortcut;
01124 int i_submodule;
01125
01126 for( pp_shortcut = p_module->pp_shortcuts ; *pp_shortcut ; pp_shortcut++ )
01127 {
01128 *pp_shortcut = strdup( *pp_shortcut );
01129 }
01130
01131
01132
01133 p_module->psz_object_name = strdup( p_module->psz_object_name );
01134 p_module->psz_capability = strdup( p_module->psz_capability );
01135 p_module->psz_shortname = p_module->psz_shortname ?
01136 strdup( p_module->psz_shortname ) : NULL;
01137 p_module->psz_longname = strdup( p_module->psz_longname );
01138
01139 if( p_module->psz_program != NULL )
01140 {
01141 p_module->psz_program = strdup( p_module->psz_program );
01142 }
01143
01144 for( i_submodule = 0; i_submodule < p_module->i_children; i_submodule++ )
01145 {
01146 DupModule( (module_t*)p_module->pp_children[ i_submodule ] );
01147 }
01148 }
01149
01150
01151
01152
01153
01154
01155 static void UndupModule( module_t *p_module )
01156 {
01157 char **pp_shortcut;
01158 int i_submodule;
01159
01160 for( i_submodule = 0; i_submodule < p_module->i_children; i_submodule++ )
01161 {
01162 UndupModule( (module_t*)p_module->pp_children[ i_submodule ] );
01163 }
01164
01165 for( pp_shortcut = p_module->pp_shortcuts ; *pp_shortcut ; pp_shortcut++ )
01166 {
01167 free( *pp_shortcut );
01168 }
01169
01170 free( p_module->psz_object_name );
01171 free( p_module->psz_capability );
01172 if( p_module->psz_shortname ) free( p_module->psz_shortname );
01173 free( p_module->psz_longname );
01174
01175 if( p_module->psz_program != NULL )
01176 {
01177 free( p_module->psz_program );
01178 }
01179 }
01180
01181 #endif
01182
01183
01184
01185
01186
01187
01188
01189
01190 static int AllocateBuiltinModule( vlc_object_t * p_this,
01191 int ( *pf_entry ) ( module_t * ) )
01192 {
01193 module_t * p_module;
01194
01195
01196
01197 p_module = vlc_object_create( p_this, VLC_OBJECT_MODULE );
01198 if( p_module == NULL )
01199 {
01200 msg_Err( p_this, "out of memory" );
01201 return -1;
01202 }
01203
01204
01205 if( pf_entry( p_module ) != 0 )
01206 {
01207
01208
01209 msg_Err( p_this, "failed calling entry point in builtin module" );
01210 vlc_object_destroy( p_module );
01211 return -1;
01212 }
01213
01214
01215 p_module->b_builtin = VLC_TRUE;
01216
01217
01218
01219
01220 vlc_object_attach( p_module, p_this->p_libvlc->p_module_bank );
01221
01222 return 0;
01223 }
01224
01225
01226
01227
01228
01229
01230 static int DeleteModule( module_t * p_module )
01231 {
01232 vlc_object_detach( p_module );
01233
01234
01235 #ifdef HAVE_DYNAMIC_PLUGINS
01236 if( !p_module->b_builtin )
01237 {
01238 if( p_module->b_loaded && p_module->b_unloadable )
01239 {
01240 CloseModule( p_module->handle );
01241 }
01242 UndupModule( p_module );
01243 free( p_module->psz_filename );
01244 }
01245 #endif
01246
01247
01248 while( p_module->i_children )
01249 {
01250 vlc_object_t *p_this = p_module->pp_children[0];
01251 vlc_object_detach( p_this );
01252 vlc_object_destroy( p_this );
01253 }
01254
01255 config_Free( p_module );
01256 vlc_object_destroy( p_module );
01257
01258 return 0;
01259 }
01260
01261 #ifdef HAVE_DYNAMIC_PLUGINS
01262
01263
01264
01265
01266
01267
01268
01269 static int CallEntry( module_t * p_module )
01270 {
01271 static char *psz_name = "vlc_entry" MODULE_SUFFIX;
01272 int (* pf_symbol) ( module_t * p_module );
01273
01274
01275 pf_symbol = (int (*)(module_t *)) GetSymbol( p_module->handle, psz_name );
01276
01277 if( pf_symbol == NULL )
01278 {
01279 #if defined(HAVE_DL_DYLD) || defined(HAVE_DL_BEOS)
01280 msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s'",
01281 psz_name, p_module->psz_filename );
01282 #elif defined(HAVE_DL_WINDOWS)
01283 char *psz_error = GetWindowsError();
01284 msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s' (%s)",
01285 psz_name, p_module->psz_filename, psz_error );
01286 free( psz_error );
01287 #elif defined(HAVE_DL_DLOPEN)
01288 msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s' (%s)",
01289 psz_name, p_module->psz_filename, dlerror() );
01290 #elif defined(HAVE_DL_SHL_LOAD)
01291 msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s' (%s)",
01292 psz_name, p_module->psz_filename, strerror(errno) );
01293 #else
01294 # error "Something is wrong in modules.c"
01295 #endif
01296 return -1;
01297 }
01298
01299
01300 if( pf_symbol( p_module ) != 0 )
01301 {
01302
01303
01304 msg_Err( p_module, "failed calling symbol \"%s\" in file `%s'",
01305 psz_name, p_module->psz_filename );
01306 return -1;
01307 }
01308
01309
01310 return 0;
01311 }
01312
01313
01314
01315
01316
01317
01318
01319 static int LoadModule( vlc_object_t *p_this, char *psz_file,
01320 module_handle_t *p_handle )
01321 {
01322 module_handle_t handle;
01323
01324 #if defined(HAVE_DL_DYLD)
01325 NSObjectFileImage image;
01326 NSObjectFileImageReturnCode ret;
01327
01328 ret = NSCreateObjectFileImageFromFile( psz_file, &image );
01329
01330 if( ret != NSObjectFileImageSuccess )
01331 {
01332 msg_Warn( p_this, "cannot create image from `%s'", psz_file );
01333 return -1;
01334 }
01335
01336
01337 handle = NSLinkModule( image, psz_file,
01338 NSLINKMODULE_OPTION_RETURN_ON_ERROR );
01339
01340 if( !handle )
01341 {
01342 NSLinkEditErrors errors;
01343 const char *psz_file, *psz_err;
01344 int i_errnum;
01345 NSLinkEditError( &errors, &i_errnum, &psz_file, &psz_err );
01346 msg_Warn( p_this, "cannot link module `%s' (%s)", psz_file, psz_err );
01347 NSDestroyObjectFileImage( image );
01348 return -1;
01349 }
01350
01351
01352 NSDestroyObjectFileImage( image );
01353
01354 #elif defined(HAVE_DL_BEOS)
01355 handle = load_add_on( psz_file );
01356 if( handle < 0 )
01357 {
01358 msg_Warn( p_this, "cannot load module `%s'", psz_file );
01359 return -1;
01360 }
01361
01362 #elif defined(HAVE_DL_WINDOWS)
01363 #ifdef UNDER_CE
01364 {
01365 wchar_t psz_wfile[MAX_PATH];
01366 MultiByteToWideChar( CP_ACP, 0, psz_file, -1, psz_wfile, MAX_PATH );
01367 handle = LoadLibrary( psz_wfile );
01368 }
01369 #else
01370 handle = LoadLibrary( psz_file );
01371 #endif
01372 if( handle == NULL )
01373 {
01374 char *psz_err = GetWindowsError();
01375 msg_Warn( p_this, "cannot load module `%s' (%s)", psz_file, psz_err );
01376 free( psz_err );
01377 return -1;
01378 }
01379
01380 #elif defined(HAVE_DL_DLOPEN) && defined(RTLD_NOW)
01381
01382
01383 # if defined(SYS_LINUX)
01384
01385
01386
01387 if( strstr( psz_file, "alsa_plugin" ) )
01388 {
01389 handle = dlopen( psz_file, RTLD_NOW | RTLD_GLOBAL );
01390 if( handle == NULL )
01391 {
01392 msg_Warn( p_this, "cannot load module `%s' (%s)",
01393 psz_file, dlerror() );
01394 return -1;
01395 }
01396 }
01397 # endif
01398
01399 handle = dlopen( psz_file, RTLD_NOW );
01400 if( handle == NULL )
01401 {
01402 msg_Warn( p_this, "cannot load module `%s' (%s)",
01403 psz_file, dlerror() );
01404 return -1;
01405 }
01406
01407 #elif defined(HAVE_DL_DLOPEN)
01408 # if defined(DL_LAZY)
01409 handle = dlopen( psz_file, DL_LAZY );
01410 # else
01411 handle = dlopen( psz_file, 0 );
01412 # endif
01413 if( handle == NULL )
01414 {
01415 msg_Warn( p_this, "cannot load module `%s' (%s)",
01416 psz_file, dlerror() );
01417 return -1;
01418 }
01419
01420 #elif defined(HAVE_DL_SHL_LOAD)
01421 handle = shl_load( psz_file, BIND_IMMEDIATE | BIND_NONFATAL, NULL );
01422 if( handle == NULL )
01423 {
01424 msg_Warn( p_this, "cannot load module `%s' (%s)",
01425 psz_file, strerror(errno) );
01426 return -1;
01427 }
01428
01429 #else
01430 # error "Something is wrong in modules.c"
01431
01432 #endif
01433
01434 *p_handle = handle;
01435 return 0;
01436 }
01437
01438
01439
01440
01441
01442
01443
01444
01445 static void CloseModule( module_handle_t handle )
01446 {
01447 #if defined(HAVE_DL_DYLD)
01448 NSUnLinkModule( handle, FALSE );
01449
01450 #elif defined(HAVE_DL_BEOS)
01451 unload_add_on( handle );
01452
01453 #elif defined(HAVE_DL_WINDOWS)
01454 FreeLibrary( handle );
01455
01456 #elif defined(HAVE_DL_DLOPEN)
01457 dlclose( handle );
01458
01459 #elif defined(HAVE_DL_SHL_LOAD)
01460 shl_unload( handle );
01461
01462 #endif
01463 return;
01464 }
01465
01466
01467
01468
01469
01470
01471
01472
01473 static void * _module_getsymbol( module_handle_t, const char * );
01474
01475 static void * GetSymbol( module_handle_t handle, const char * psz_function )
01476 {
01477 void * p_symbol = _module_getsymbol( handle, psz_function );
01478
01479
01480
01481
01482 if( p_symbol == NULL )
01483 {
01484 char *psz_call = malloc( strlen( psz_function ) + 2 );
01485
01486 strcpy( psz_call + 1, psz_function );
01487 psz_call[ 0 ] = '_';
01488 p_symbol = _module_getsymbol( handle, psz_call );
01489 free( psz_call );
01490 }
01491
01492 return p_symbol;
01493 }
01494
01495 static void * _module_getsymbol( module_handle_t handle,
01496 const char * psz_function )
01497 {
01498 #if defined(HAVE_DL_DYLD)
01499 NSSymbol sym = NSLookupSymbolInModule( handle, psz_function );
01500 return NSAddressOfSymbol( sym );
01501
01502 #elif defined(HAVE_DL_BEOS)
01503 void * p_symbol;
01504 if( B_OK == get_image_symbol( handle, psz_function,
01505 B_SYMBOL_TYPE_TEXT, &p_symbol ) )
01506 {
01507 return p_symbol;
01508 }
01509 else
01510 {
01511 return NULL;
01512 }
01513
01514 #elif defined(HAVE_DL_WINDOWS) && defined(UNDER_CE)
01515 wchar_t psz_real[256];
01516 MultiByteToWideChar( CP_ACP, 0, psz_function, -1, psz_real, 256 );
01517
01518 return (void *)GetProcAddress( handle, psz_real );
01519
01520 #elif defined(HAVE_DL_WINDOWS) && defined(WIN32)
01521 return (void *)GetProcAddress( handle, (char *)psz_function );
01522
01523 #elif defined(HAVE_DL_DLOPEN)
01524 return dlsym( handle, psz_function );
01525
01526 #elif defined(HAVE_DL_SHL_LOAD)
01527 void *p_sym;
01528 shl_findsym( &handle, psz_function, TYPE_UNDEFINED, &p_sym );
01529 return p_sym;
01530
01531 #endif
01532 }
01533
01534 #if defined(HAVE_DL_WINDOWS)
01535 static char * GetWindowsError( void )
01536 {
01537 #if defined(UNDER_CE)
01538 wchar_t psz_tmp[MAX_PATH];
01539 char * psz_buffer = malloc( MAX_PATH );
01540 #else
01541 char * psz_tmp = malloc( MAX_PATH );
01542 #endif
01543 int i = 0, i_error = GetLastError();
01544
01545 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
01546 NULL, i_error, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
01547 (LPTSTR)psz_tmp, MAX_PATH, NULL );
01548
01549
01550 while( psz_tmp[i] && psz_tmp[i] != _T('\r') && psz_tmp[i] != _T('\n') )
01551 {
01552 i++;
01553 }
01554
01555 if( psz_tmp[i] )
01556 {
01557 #if defined(UNDER_CE)
01558 swprintf( psz_tmp + i, L" (error %i)", i_error );
01559 psz_tmp[ 255 ] = L'\0';
01560 #else
01561 snprintf( psz_tmp + i, 256 - i, " (error %i)", i_error );
01562 psz_tmp[ 255 ] = '\0';
01563 #endif
01564 }
01565
01566 #if defined(UNDER_CE)
01567 wcstombs( psz_buffer, psz_tmp, MAX_PATH );
01568 return psz_buffer;
01569 #else
01570 return psz_tmp;
01571 #endif
01572 }
01573 #endif
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583 static void CacheLoad( vlc_object_t *p_this )
01584 {
01585 char *psz_filename, *psz_homedir;
01586 FILE *file;
01587 int i, j, i_size, i_read;
01588 char p_cachestring[sizeof(PLUGINSCACHE_DIR COPYRIGHT_MESSAGE)];
01589 char p_cachelang[6], p_lang[6];
01590 int i_cache;
01591 module_cache_t **pp_cache = 0;
01592 int32_t i_file_size, i_marker;
01593
01594 psz_homedir = p_this->p_vlc->psz_homedir;
01595 if( !psz_homedir )
01596 {
01597 msg_Err( p_this, "psz_homedir is null" );
01598 return;
01599 }
01600
01601 i_size = asprintf( &psz_filename, "%s/%s/%s/%s", psz_homedir, CONFIG_DIR,
01602 PLUGINSCACHE_DIR, CacheName() );
01603 if( i_size <= 0 )
01604 {
01605 msg_Err( p_this, "out of memory" );
01606 return;
01607 }
01608
01609 if( p_this->p_libvlc->p_module_bank->b_cache_delete )
01610 {
01611 #if !defined( UNDER_CE )
01612 unlink( psz_filename );
01613 #else
01614 wchar_t psz_wf[MAX_PATH];
01615 MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_wf, MAX_PATH );
01616 DeleteFile( psz_wf );
01617 #endif
01618 msg_Dbg( p_this, "removing plugins cache file %s", psz_filename );
01619 free( psz_filename );
01620 return;
01621 }
01622
01623 msg_Dbg( p_this, "loading plugins cache file %s", psz_filename );
01624
01625 file = fopen( psz_filename, "rb" );
01626 if( !file )
01627 {
01628 msg_Warn( p_this, "could not open plugins cache file %s for reading",
01629 psz_filename );
01630 free( psz_filename );
01631 return;
01632 }
01633 free( psz_filename );
01634
01635
01636 i_read = fread( &i_file_size, sizeof(char), sizeof(i_file_size), file );
01637 if( i_read != sizeof(i_file_size) )
01638 {
01639 msg_Warn( p_this, "This doesn't look like a valid plugins cache "
01640 "(too short)" );
01641 fclose( file );
01642 return;
01643 }
01644
01645 fseek( file, 0, SEEK_END );
01646 if( ftell( file ) != i_file_size )
01647 {
01648 msg_Warn( p_this, "This doesn't look like a valid plugins cache "
01649 "(corrupted size)" );
01650 fclose( file );
01651 return;
01652 }
01653 fseek( file, sizeof(i_file_size), SEEK_SET );
01654
01655
01656 i_size = sizeof(PLUGINSCACHE_DIR COPYRIGHT_MESSAGE) - 1;
01657 i_read = fread( p_cachestring, sizeof(char), i_size, file );
01658 if( i_read != i_size ||
01659 memcmp( p_cachestring, PLUGINSCACHE_DIR COPYRIGHT_MESSAGE, i_size ) )
01660 {
01661 msg_Warn( p_this, "This doesn't look like a valid plugins cache" );
01662 fclose( file );
01663 return;
01664 }
01665
01666
01667 i_read = fread( &i_marker, sizeof(char), sizeof(i_marker), file );
01668 if( i_read != sizeof(i_marker) || i_marker != CACHE_SUBVERSION_NUM )
01669 {
01670 msg_Warn( p_this, "This doesn't look like a valid plugins cache "
01671 "(corrupted header)" );
01672 fclose( file );
01673 return;
01674 }
01675
01676
01677 sprintf( p_lang, "%5.5s", _("C") ); i_size = 5;
01678 i_read = fread( p_cachelang, sizeof(char), i_size, file );
01679 if( i_read != i_size || memcmp( p_cachelang, p_lang, i_size ) )
01680 {
01681 msg_Warn( p_this, "This doesn't look like a valid plugins cache "
01682 "(language changed)" );
01683 fclose( file );
01684 return;
01685 }
01686
01687
01688 i_read = fread( &i_marker, sizeof(char), sizeof(i_marker), file );
01689 if( i_read != sizeof(i_marker) ||
01690 i_marker != ftell( file ) - (int)sizeof(i_marker) )
01691 {
01692 msg_Warn( p_this, "This doesn't look like a valid plugins cache "
01693 "(corrupted header)" );
01694 fclose( file );
01695 return;
01696 }
01697
01698 p_this->p_libvlc->p_module_bank->i_loaded_cache = 0;
01699 fread( &i_cache, sizeof(char), sizeof(i_cache), file );
01700 if( i_cache )
01701 pp_cache = p_this->p_libvlc->p_module_bank->pp_loaded_cache =
01702 malloc( i_cache * sizeof(void *) );
01703
01704 #define LOAD_IMMEDIATE(a) \
01705 if( fread( &a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error
01706 #define LOAD_STRING(a) \
01707 { if( fread( &i_size, sizeof(char), sizeof(i_size), file ) \
01708 != sizeof(i_size) ) goto error; \
01709 if( i_size && i_size < 16384 ) { \
01710 a = malloc( i_size ); \
01711 if( fread( a, sizeof(char), i_size, file ) != (size_t)i_size ) \
01712 goto error; \
01713 if( a[i_size-1] ) { \
01714 free( a ); a = 0; \
01715 goto error; } \
01716 } else a = 0; \
01717 } while(0)
01718
01719
01720 for( i = 0; i < i_cache; i++ )
01721 {
01722 int16_t i_size;
01723 int i_submodules;
01724
01725 pp_cache[i] = malloc( sizeof(module_cache_t) );
01726 p_this->p_libvlc->p_module_bank->i_loaded_cache++;
01727
01728
01729 LOAD_STRING( pp_cache[i]->psz_file );
01730 LOAD_IMMEDIATE( pp_cache[i]->i_time );
01731 LOAD_IMMEDIATE( pp_cache[i]->i_size );
01732 LOAD_IMMEDIATE( pp_cache[i]->b_junk );
01733
01734 if( pp_cache[i]->b_junk ) continue;
01735
01736 pp_cache[i]->p_module = vlc_object_create( p_this, VLC_OBJECT_MODULE );
01737
01738
01739 LOAD_STRING( pp_cache[i]->p_module->psz_object_name );
01740 LOAD_STRING( pp_cache[i]->p_module->psz_shortname );
01741 LOAD_STRING( pp_cache[i]->p_module->psz_longname );
01742 LOAD_STRING( pp_cache[i]->p_module->psz_program );
01743 for( j = 0; j < MODULE_SHORTCUT_MAX; j++ )
01744 {
01745 LOAD_STRING( pp_cache[i]->p_module->pp_shortcuts[j] );
01746 }
01747 LOAD_STRING( pp_cache[i]->p_module->psz_capability );
01748 LOAD_IMMEDIATE( pp_cache[i]->p_module->i_score );
01749 LOAD_IMMEDIATE( pp_cache[i]->p_module->i_cpu );
01750 LOAD_IMMEDIATE( pp_cache[i]->p_module->b_unloadable );
01751 LOAD_IMMEDIATE( pp_cache[i]->p_module->b_reentrant );
01752 LOAD_IMMEDIATE( pp_cache[i]->p_module->b_submodule );
01753
01754
01755 if( CacheLoadConfig( pp_cache[i]->p_module, file ) != VLC_SUCCESS )
01756 goto error;
01757
01758 LOAD_STRING( pp_cache[i]->p_module->psz_filename );
01759
01760 LOAD_IMMEDIATE( i_submodules );
01761
01762 while( i_submodules-- )
01763 {
01764 module_t *p_module = vlc_object_create( p_this, VLC_OBJECT_MODULE);
01765 vlc_object_attach( p_module, pp_cache[i]->p_module );
01766 p_module->b_submodule = VLC_TRUE;
01767
01768 LOAD_STRING( p_module->psz_object_name );
01769 LOAD_STRING( p_module->psz_shortname );
01770 LOAD_STRING( p_module->psz_longname );
01771 LOAD_STRING( p_module->psz_program );
01772 for( j = 0; j < MODULE_SHORTCUT_MAX; j++ )
01773 {
01774 LOAD_STRING( p_module->pp_shortcuts[j] );
01775 }
01776 LOAD_STRING( p_module->psz_capability );
01777 LOAD_IMMEDIATE( p_module->i_score );
01778 LOAD_IMMEDIATE( p_module->i_cpu );
01779 LOAD_IMMEDIATE( p_module->b_unloadable );
01780 LOAD_IMMEDIATE( p_module->b_reentrant );
01781 }
01782 }
01783
01784 fclose( file );
01785 return;
01786
01787 error:
01788
01789 msg_Warn( p_this, "plugins cache not loaded (corrupted)" );
01790
01791
01792 p_this->p_libvlc->p_module_bank->i_loaded_cache = 0;
01793
01794 fclose( file );
01795 return;
01796 }
01797
01798 int CacheLoadConfig( module_t *p_module, FILE *file )
01799 {
01800 int i, j, i_lines;
01801 int16_t i_size;
01802
01803
01804 LOAD_IMMEDIATE( p_module->i_config_items );
01805 LOAD_IMMEDIATE( p_module->i_bool_items );
01806
01807 LOAD_IMMEDIATE( i_lines );
01808
01809
01810 p_module->p_config =
01811 (module_config_t *)malloc( sizeof(module_config_t) * (i_lines + 1));
01812 if( p_module->p_config == NULL )
01813 {
01814 msg_Err( p_module, "config error: can't duplicate p_config" );
01815 return VLC_ENOMEM;
01816 }
01817
01818
01819 for( i = 0; i < i_lines ; i++ )
01820 {
01821 LOAD_IMMEDIATE( p_module->p_config[i] );
01822
01823 LOAD_STRING( p_module->p_config[i].psz_type );
01824 LOAD_STRING( p_module->p_config[i].psz_name );
01825 LOAD_STRING( p_module->p_config[i].psz_text );
01826 LOAD_STRING( p_module->p_config[i].psz_longtext );
01827 LOAD_STRING( p_module->p_config[i].psz_current );
01828 LOAD_STRING( p_module->p_config[i].psz_value_orig );
01829
01830 p_module->p_config[i].psz_value =
01831 p_module->p_config[i].psz_value_orig ?
01832 strdup( p_module->p_config[i].psz_value_orig ) : 0;
01833 p_module->p_config[i].i_value = p_module->p_config[i].i_value_orig;
01834 p_module->p_config[i].f_value = p_module->p_config[i].f_value_orig;
01835 p_module->p_config[i].i_value_saved = p_module->p_config[i].i_value;
01836 p_module->p_config[i].f_value_saved = p_module->p_config[i].f_value;
01837 p_module->p_config[i].psz_value_saved = 0;
01838 p_module->p_config[i].b_dirty = VLC_FALSE;
01839
01840 p_module->p_config[i].p_lock = &p_module->object_lock;
01841
01842 if( p_module->p_config[i].i_list )
01843 {
01844 if( p_module->p_config[i].ppsz_list )
01845 {
01846 p_module->p_config[i].ppsz_list =
01847 malloc( (p_module->p_config[i].i_list+1) * sizeof(char *));
01848 if( p_module->p_config[i].ppsz_list )
01849 {
01850 for( j = 0; j < p_module->p_config[i].i_list; j++ )
01851 LOAD_STRING( p_module->p_config[i].ppsz_list[j] );
01852 p_module->p_config[i].ppsz_list[j] = NULL;
01853 }
01854 }
01855 if( p_module->p_config[i].ppsz_list_text )
01856 {
01857 p_module->p_config[i].ppsz_list_text =
01858 malloc( (p_module->p_config[i].i_list+1) * sizeof(char *));
01859 if( p_module->p_config[i].ppsz_list_text )
01860 {
01861 for( j = 0; j < p_module->p_config[i].i_list; j++ )
01862 LOAD_STRING( p_module->p_config[i].ppsz_list_text[j] );
01863 p_module->p_config[i].ppsz_list_text[j] = NULL;
01864 }
01865 }
01866 if( p_module->p_config[i].pi_list )
01867 {
01868 p_module->p_config[i].pi_list =
01869 malloc( (p_module->p_config[i].i_list + 1) * sizeof(int) );
01870 if( p_module->p_config[i].pi_list )
01871 {
01872 for( j = 0; j < p_module->p_config[i].i_list; j++ )
01873 LOAD_IMMEDIATE( p_module->p_config[i].pi_list[j] );
01874 }
01875 }
01876 }
01877
01878 if( p_module->p_config[i].i_action )
01879 {
01880 p_module->p_config[i].ppf_action =
01881 malloc( p_module->p_config[i].i_action * sizeof(void *) );
01882 p_module->p_config[i].ppsz_action_text =
01883 malloc( p_module->p_config[i].i_action * sizeof(char *) );
01884
01885 for( j = 0; j < p_module->p_config[i].i_action; j++ )
01886 {
01887 p_module->p_config[i].ppf_action[j] = 0;
01888 LOAD_STRING( p_module->p_config[i].ppsz_action_text[j] );
01889 }
01890 }
01891
01892 LOAD_IMMEDIATE( p_module->p_config[i].pf_callback );
01893 }
01894
01895 p_module->p_config[i].i_type = CONFIG_HINT_END;
01896
01897 return VLC_SUCCESS;
01898
01899 error:
01900
01901 return VLC_EGENERIC;
01902 }
01903
01904
01905
01906
01907 static void CacheSave( vlc_object_t *p_this )
01908 {
01909 static char const psz_tag[] =
01910 "Signature: 8a477f597d28d172789f06886806bc55\r\n"
01911 "# This file is a cache directory tag created by VLC.\r\n"
01912 "# For information about cache directory tags, see:\r\n"
01913 "# http://www.brynosaurus.com/cachedir/\r\n";
01914
01915 char *psz_filename, *psz_homedir;
01916 FILE *file;
01917 int i, j, i_cache;
01918 module_cache_t **pp_cache;
01919 int32_t i_file_size = 0;
01920
01921 psz_homedir = p_this->p_vlc->psz_homedir;
01922 if( !psz_homedir )
01923 {
01924 msg_Err( p_this, "psz_homedir is null" );
01925 return;
01926 }
01927 psz_filename =
01928 (char *)malloc( sizeof("/" CONFIG_DIR "/" PLUGINSCACHE_DIR "/" ) +
01929 strlen(psz_homedir) + strlen(CacheName()) );
01930
01931 if( !psz_filename )
01932 {
01933 msg_Err( p_this, "out of memory" );
01934 return;
01935 }
01936
01937 sprintf( psz_filename, "%s/%s", psz_homedir, CONFIG_DIR );
01938
01939 config_CreateDir( p_this, psz_filename );
01940
01941 strcat( psz_filename, "/" PLUGINSCACHE_DIR );
01942
01943 config_CreateDir( p_this, psz_filename );
01944
01945 strcat( psz_filename, "/CACHEDIR.TAG" );
01946
01947 file = fopen( psz_filename, "wb" );
01948 if( file )
01949 {
01950 fwrite( psz_tag, 1, strlen(psz_tag), file );
01951 fclose( file );
01952 }
01953
01954 sprintf( psz_filename, "%s/%s/%s/%s", psz_homedir, CONFIG_DIR,
01955 PLUGINSCACHE_DIR, CacheName() );
01956
01957 msg_Dbg( p_this, "saving plugins cache file %s", psz_filename );
01958
01959 file = fopen( psz_filename, "wb" );
01960 if( !file )
01961 {
01962 msg_Warn( p_this, "could not open plugins cache file %s for writing",
01963 psz_filename );
01964 free( psz_filename );
01965 return;
01966 }
01967 free( psz_filename );
01968
01969
01970 fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file );
01971
01972
01973 fprintf( file, "%s", PLUGINSCACHE_DIR COPYRIGHT_MESSAGE );
01974
01975
01976
01977 i_file_size = CACHE_SUBVERSION_NUM;
01978 fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file );
01979
01980
01981 fprintf( file, "%5.5s", _("C") );
01982
01983
01984 i_file_size = ftell( file );
01985 fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file );
01986
01987 i_cache = p_this->p_libvlc->p_module_bank->i_cache;
01988 pp_cache = p_this->p_libvlc->p_module_bank->pp_cache;
01989
01990 fwrite( &i_cache, sizeof(char), sizeof(i_cache), file );
01991
01992 #define SAVE_IMMEDIATE(a) \
01993 fwrite( &a, sizeof(char), sizeof(a), file )
01994 #define SAVE_STRING(a) \
01995 { i_size = a ? strlen( a ) + 1 : 0; \
01996 fwrite( &i_size, sizeof(char), sizeof(i_size), file ); \
01997 if( a ) fwrite( a, sizeof(char), i_size, file ); \
01998 } while(0)
01999
02000 for( i = 0; i < i_cache; i++ )
02001 {
02002 int16_t i_size;
02003 int32_t i_submodule;
02004
02005
02006 SAVE_STRING( pp_cache[i]->psz_file );
02007 SAVE_IMMEDIATE( pp_cache[i]->i_time );
02008 SAVE_IMMEDIATE( pp_cache[i]->i_size );
02009 SAVE_IMMEDIATE( pp_cache[i]->b_junk );
02010
02011 if( pp_cache[i]->b_junk ) continue;
02012
02013
02014 SAVE_STRING( pp_cache[i]->p_module->psz_object_name );
02015 SAVE_STRING( pp_cache[i]->p_module->psz_shortname );
02016 SAVE_STRING( pp_cache[i]->p_module->psz_longname );
02017 SAVE_STRING( pp_cache[i]->p_module->psz_program );
02018 for( j = 0; j < MODULE_SHORTCUT_MAX; j++ )
02019 {
02020 SAVE_STRING( pp_cache[i]->p_module->pp_shortcuts[j] );
02021 }
02022 SAVE_STRING( pp_cache[i]->p_module->psz_capability );
02023 SAVE_IMMEDIATE( pp_cache[i]->p_module->i_score );
02024 SAVE_IMMEDIATE( pp_cache[i]->p_module->i_cpu );
02025 SAVE_IMMEDIATE( pp_cache[i]->p_module->b_unloadable );
02026 SAVE_IMMEDIATE( pp_cache[i]->p_module->b_reentrant );
02027 SAVE_IMMEDIATE( pp_cache[i]->p_module->b_submodule );
02028
02029
02030 CacheSaveConfig( pp_cache[i]->p_module, file );
02031
02032 SAVE_STRING( pp_cache[i]->p_module->psz_filename );
02033
02034 i_submodule = pp_cache[i]->p_module->i_children;
02035 SAVE_IMMEDIATE( i_submodule );
02036 for( i_submodule = 0; i_submodule < pp_cache[i]->p_module->i_children;
02037 i_submodule++ )
02038 {
02039 module_t *p_module =
02040 (module_t *)pp_cache[i]->p_module->pp_children[i_submodule];
02041
02042 SAVE_STRING( p_module->psz_object_name );
02043 SAVE_STRING( p_module->psz_shortname );
02044 SAVE_STRING( p_module->psz_longname );
02045 SAVE_STRING( p_module->psz_program );
02046 for( j = 0; j < MODULE_SHORTCUT_MAX; j++ )
02047 {
02048 SAVE_STRING( p_module->pp_shortcuts[j] );
02049 }
02050 SAVE_STRING( p_module->psz_capability );
02051 SAVE_IMMEDIATE( p_module->i_score );
02052 SAVE_IMMEDIATE( p_module->i_cpu );
02053 SAVE_IMMEDIATE( p_module->b_unloadable );
02054 SAVE_IMMEDIATE( p_module->b_reentrant );
02055 }
02056 }
02057
02058
02059 i_file_size = ftell( file );
02060 fseek( file, 0, SEEK_SET );
02061 fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file );
02062
02063 fclose( file );
02064
02065 return;
02066 }
02067
02068 void CacheSaveConfig( module_t *p_module, FILE *file )
02069 {
02070 int i, j, i_lines = 0;
02071 module_config_t *p_item;
02072 int16_t i_size;
02073
02074 SAVE_IMMEDIATE( p_module->i_config_items );
02075 SAVE_IMMEDIATE( p_module->i_bool_items );
02076
02077 for( p_item = p_module->p_config; p_item->i_type != CONFIG_HINT_END;
02078 p_item++ ) i_lines++;
02079
02080 SAVE_IMMEDIATE( i_lines );
02081
02082 for( i = 0; i < i_lines ; i++ )
02083 {
02084 SAVE_IMMEDIATE( p_module->p_config[i] );
02085
02086 SAVE_STRING( p_module->p_config[i].psz_type );
02087 SAVE_STRING( p_module->p_config[i].psz_name );
02088 SAVE_STRING( p_module->p_config[i].psz_text );
02089 SAVE_STRING( p_module->p_config[i].psz_longtext );
02090 SAVE_STRING( p_module->p_config[i].psz_current );
02091 SAVE_STRING( p_module->p_config[i].psz_value_orig );
02092
02093 if( p_module->p_config[i].i_list )
02094 {
02095 if( p_module->p_config[i].ppsz_list )
02096 {
02097 for( j = 0; j < p_module->p_config[i].i_list; j++ )
02098 SAVE_STRING( p_module->p_config[i].ppsz_list[j] );
02099 }
02100
02101 if( p_module->p_config[i].ppsz_list_text )
02102 {
02103 for( j = 0; j < p_module->p_config[i].i_list; j++ )
02104 SAVE_STRING( p_module->p_config[i].ppsz_list_text[j] );
02105 }
02106 if( p_module->p_config[i].pi_list )
02107 {
02108 for( j = 0; j < p_module->p_config[i].i_list; j++ )
02109 SAVE_IMMEDIATE( p_module->p_config[i].pi_list[j] );
02110 }
02111 }
02112
02113 for( j = 0; j < p_module->p_config[i].i_action; j++ )
02114 SAVE_STRING( p_module->p_config[i].ppsz_action_text[j] );
02115
02116 SAVE_IMMEDIATE( p_module->p_config[i].pf_callback );
02117 }
02118 }
02119
02120
02121
02122
02123 static char *CacheName( void )
02124 {
02125 static char psz_cachename[32];
02126 static vlc_bool_t b_initialised = VLC_FALSE;
02127
02128 if( !b_initialised )
02129 {
02130
02131 int32_t x = 0xbe00001e;
02132 sprintf( psz_cachename, "plugins-%.2x%.2x%.2x.dat", sizeof(int),
02133 sizeof(void *), (unsigned int)((unsigned char *)&x)[0] );
02134 b_initialised = VLC_TRUE;
02135 }
02136
02137 return psz_cachename;
02138 }
02139
02140
02141
02142
02143 static void CacheMerge( vlc_object_t *p_this, module_t *p_cache,
02144 module_t *p_module )
02145 {
02146 int i_submodule;
02147
02148 p_cache->pf_activate = p_module->pf_activate;
02149 p_cache->pf_deactivate = p_module->pf_deactivate;
02150 #ifndef HAVE_SHARED_LIBVLC
02151 p_cache->p_symbols = p_module->p_symbols;
02152 #endif
02153 p_cache->handle = p_module->handle;
02154
02155 for( i_submodule = 0; i_submodule < p_module->i_children; i_submodule++ )
02156 {
02157 module_t *p_child = (module_t*)p_module->pp_children[i_submodule];
02158 module_t *p_cchild = (module_t*)p_cache->pp_children[i_submodule];
02159 p_cchild->pf_activate = p_child->pf_activate;
02160 p_cchild->pf_deactivate = p_child->pf_deactivate;
02161 #ifndef HAVE_SHARED_LIBVLC
02162 p_cchild->p_symbols = p_child->p_symbols;
02163 #endif
02164 }
02165
02166 p_cache->b_loaded = VLC_TRUE;
02167 p_module->b_loaded = VLC_FALSE;
02168 }
02169
02170
02171
02172
02173 static module_cache_t *CacheFind( vlc_object_t *p_this, char *psz_file,
02174 int64_t i_time, int64_t i_size )
02175 {
02176 module_cache_t **pp_cache;
02177 int i_cache, i;
02178
02179 pp_cache = p_this->p_libvlc->p_module_bank->pp_loaded_cache;
02180 i_cache = p_this->p_libvlc->p_module_bank->i_loaded_cache;
02181
02182 for( i = 0; i < i_cache; i++ )
02183 {
02184 if( !strcmp( pp_cache[i]->psz_file, psz_file ) &&
02185 pp_cache[i]->i_time == i_time &&
02186 pp_cache[i]->i_size == i_size ) return pp_cache[i];
02187 }
02188
02189 return NULL;
02190 }
02191
02192 #endif