📄 modules.c
字号:
path = vlc_array_item_at_index( arraypaths, i ); if( !path ) continue; msg_Dbg( p_this, "recursively browsing `%s'", path ); /* Don't go deeper than 5 subdirectories */ AllocatePluginDir( p_this, path, 5 ); free( path ); } vlc_array_destroy( arraypaths ); free( userpaths );}/***************************************************************************** * AllocatePluginDir: recursively parse a directory to look for plugins *****************************************************************************/static void AllocatePluginDir( vlc_object_t *p_this, const char *psz_dir, int i_maxdepth ){/* FIXME: Needs to be ported to wide char on ALL Windows builds */#ifdef WIN32# undef opendir# undef closedir# undef readdir#endif#if defined( UNDER_CE ) || defined( _MSC_VER )#ifdef UNDER_CE wchar_t psz_wpath[MAX_PATH + 256]; wchar_t psz_wdir[MAX_PATH];#endif char psz_path[MAX_PATH + 256]; WIN32_FIND_DATA finddata; HANDLE handle; int rc;#else int i_dirlen; DIR * dir; struct dirent * file;#endif char * psz_file; if( p_this->p_libvlc->b_die || i_maxdepth < 0 ) { return; }#if defined( UNDER_CE ) || defined( _MSC_VER )#ifdef UNDER_CE MultiByteToWideChar( CP_ACP, 0, psz_dir, -1, psz_wdir, MAX_PATH ); rc = GetFileAttributes( psz_wdir ); if( rc<0 || !(rc&FILE_ATTRIBUTE_DIRECTORY) ) return; /* Not a directory */ /* Parse all files in the directory */ swprintf( psz_wpath, L"%ls\\*", psz_wdir );#else rc = GetFileAttributes( psz_dir ); if( rc<0 || !(rc&FILE_ATTRIBUTE_DIRECTORY) ) return; /* Not a directory */#endif /* Parse all files in the directory */ sprintf( psz_path, "%s\\*", psz_dir );#ifdef UNDER_CE handle = FindFirstFile( psz_wpath, &finddata );#else handle = FindFirstFile( psz_path, &finddata );#endif if( handle == INVALID_HANDLE_VALUE ) { /* Empty directory */ return; } /* Parse the directory and try to load all files it contains. */ do {#ifdef UNDER_CE unsigned int i_len = wcslen( finddata.cFileName ); swprintf( psz_wpath, L"%ls\\%ls", psz_wdir, finddata.cFileName ); sprintf( psz_path, "%s\\%ls", psz_dir, finddata.cFileName );#else unsigned int i_len = strlen( finddata.cFileName ); sprintf( psz_path, "%s\\%s", psz_dir, finddata.cFileName );#endif /* Skip ".", ".." */ if( !*finddata.cFileName || !strcmp( finddata.cFileName, "." ) || !strcmp( finddata.cFileName, ".." ) ) { if( !FindNextFile( handle, &finddata ) ) break; continue; }#ifdef UNDER_CE if( GetFileAttributes( psz_wpath ) & FILE_ATTRIBUTE_DIRECTORY )#else if( GetFileAttributes( psz_path ) & FILE_ATTRIBUTE_DIRECTORY )#endif { AllocatePluginDir( p_this, psz_path, i_maxdepth - 1 ); } else if( i_len > strlen( LIBEXT ) /* We only load files ending with LIBEXT */ && !strncasecmp( psz_path + strlen( psz_path) - strlen( LIBEXT ), LIBEXT, strlen( LIBEXT ) ) ) { WIN32_FILE_ATTRIBUTE_DATA attrbuf; int64_t i_time = 0, i_size = 0;#ifdef UNDER_CE if( GetFileAttributesEx( psz_wpath, GetFileExInfoStandard, &attrbuf ) )#else if( GetFileAttributesEx( psz_path, GetFileExInfoStandard, &attrbuf ) )#endif { i_time = attrbuf.ftLastWriteTime.dwHighDateTime; i_time <<= 32; i_time |= attrbuf.ftLastWriteTime.dwLowDateTime; i_size = attrbuf.nFileSizeHigh; i_size <<= 32; i_size |= attrbuf.nFileSizeLow; } psz_file = psz_path; AllocatePluginFile( p_this, psz_file, i_time, i_size ); } } while( !p_this->p_libvlc->b_die && FindNextFile( handle, &finddata ) ); /* Close the directory */ FindClose( handle );#else dir = opendir( psz_dir ); if( !dir ) { return; } i_dirlen = strlen( psz_dir ); /* Parse the directory and try to load all files it contains. */ while( !p_this->p_libvlc->b_die && ( file = readdir( dir ) ) ) { struct stat statbuf; unsigned int i_len; int i_stat; /* Skip ".", ".." */ if( !*file->d_name || !strcmp( file->d_name, "." ) || !strcmp( file->d_name, ".." ) ) { continue; } i_len = strlen( file->d_name ); psz_file = malloc( i_dirlen + 1 + i_len + 1 ); sprintf( psz_file, "%s"DIR_SEP"%s", psz_dir, file->d_name ); i_stat = stat( psz_file, &statbuf ); if( !i_stat && statbuf.st_mode & S_IFDIR ) { AllocatePluginDir( p_this, psz_file, i_maxdepth - 1 ); } else if( i_len > strlen( LIBEXT ) /* We only load files ending with LIBEXT */ && !strncasecmp( file->d_name + i_len - strlen( LIBEXT ), LIBEXT, strlen( LIBEXT ) ) ) { int64_t i_time = 0, i_size = 0; if( !i_stat ) { i_time = statbuf.st_mtime; i_size = statbuf.st_size; } AllocatePluginFile( p_this, psz_file, i_time, i_size ); } free( psz_file ); } /* Close the directory */ closedir( dir );#endif}/***************************************************************************** * AllocatePluginFile: load a module into memory and initialize it. ***************************************************************************** * This function loads a dynamically loadable module and allocates a structure * for its information data. The module can then be handled by module_Need * and module_Unneed. It can be removed by DeleteModule. *****************************************************************************/static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file, int64_t i_file_time, int64_t i_file_size ){ module_t * p_module = NULL; module_cache_t *p_cache_entry = NULL; /* * Check our plugins cache first then load plugin if needed */ p_cache_entry = CacheFind( psz_file, i_file_time, i_file_size ); if( !p_cache_entry ) { p_module = AllocatePlugin( p_this, psz_file ); } else { /* If junk dll, don't try to load it */ if( p_cache_entry->b_junk ) { p_module = NULL; } else { module_config_t *p_item = NULL, *p_end = NULL; p_module = p_cache_entry->p_module; p_module->b_loaded = false; /* For now we force loading if the module's config contains * callbacks or actions. * Could be optimized by adding an API call.*/ for( p_item = p_module->p_config, p_end = p_item + p_module->confsize; p_item < p_end; p_item++ ) { if( p_item->pf_callback || p_item->i_action ) { p_module = AllocatePlugin( p_this, psz_file ); break; } } if( p_module == p_cache_entry->p_module ) p_cache_entry->b_used = true; } } if( p_module ) { libvlc_global_data_t *p_libvlc_global = vlc_global(); /* Everything worked fine ! * The module is ready to be added to the list. */ p_module->b_builtin = false; /* msg_Dbg( p_this, "plugin \"%s\", %s", p_module->psz_object_name, p_module->psz_longname ); */ vlc_object_attach( p_module, p_libvlc_global->p_module_bank ); if( !p_libvlc_global->p_module_bank->b_cache ) return 0;#define p_bank p_libvlc_global->p_module_bank /* Add entry to cache */ p_bank->pp_cache = realloc( p_bank->pp_cache, (p_bank->i_cache + 1) * sizeof(void *) ); p_bank->pp_cache[p_bank->i_cache] = malloc( sizeof(module_cache_t) ); if( !p_bank->pp_cache[p_bank->i_cache] ) return -1; p_bank->pp_cache[p_bank->i_cache]->psz_file = strdup( psz_file ); p_bank->pp_cache[p_bank->i_cache]->i_time = i_file_time; p_bank->pp_cache[p_bank->i_cache]->i_size = i_file_size; p_bank->pp_cache[p_bank->i_cache]->b_junk = p_module ? 0 : 1; p_bank->pp_cache[p_bank->i_cache]->b_used = true; p_bank->pp_cache[p_bank->i_cache]->p_module = p_module; p_bank->i_cache++;#undef p_bank } return p_module ? 0 : -1;}/***************************************************************************** * AllocatePlugin: load a module into memory and initialize it. ***************************************************************************** * This function loads a dynamically loadable module and allocates a structure * for its information data. The module can then be handled by module_Need * and module_Unneed. It can be removed by DeleteModule. *****************************************************************************/static module_t * AllocatePlugin( vlc_object_t * p_this, char * psz_file ){ module_t * p_module = NULL; module_handle_t handle; if( module_Load( p_this, psz_file, &handle ) ) return NULL; /* Now that we have successfully loaded the module, we can * allocate a structure for it */ p_module = vlc_module_create( p_this ); if( p_module == NULL ) { module_Unload( handle ); return NULL; } /* We need to fill these since they may be needed by module_Call() */ p_module->psz_filename = psz_file; p_module->handle = handle; p_module->b_loaded = true; /* Initialize the module: fill p_module, default config */ if( module_Call( p_module ) != 0 ) { /* We couldn't call module_init() */ vlc_object_release( p_module ); module_Unload( handle ); return NULL; } DupModule( p_module ); p_module->psz_filename = strdup( p_module->psz_filename ); /* Everything worked fine ! The module is ready to be added to the list. */ p_module->b_builtin = false; return p_module;}/***************************************************************************** * DupModule: make a plugin module standalone. ***************************************************************************** * This function duplicates all strings in the module, so that the dynamic * object can be unloaded. It acts recursively on submodules. *****************************************************************************/static void DupModule( module_t *p_module ){ char **pp_shortcut; int i_submodule; for( pp_shortcut = p_module->pp_shortcuts ; *pp_shortcut ; pp_shortcut++ ) { *pp_shortcut = strdup( *pp_shortcut ); } /* We strdup() these entries so that they are still valid when the * module is unloaded. */ p_module->psz_capability = strdup( p_module->psz_capability ); p_module->psz_shortname = p_module->psz_shortname ? strdup( p_module->psz_shortname ) : NULL; p_module->psz_longname = strdup( p_module->psz_longname ); p_module->psz_help = p_module->psz_help ? strdup( p_module->psz_help ) : NULL; for( i_submodule = 0; i_submodule < vlc_internals( p_module )->i_children; i_submodule++ ) { DupModule( (module_t*)vlc_internals( p_module )->pp_children[ i_submodule ] ); }}/***************************************************************************** * UndupModule: free a duplicated module. ***************************************************************************** * This function frees the allocations done in DupModule(). *****************************************************************************/static void UndupModule( module_t *p_module ){ char **pp_shortcut; int i_submodule; for( i_submodule = 0; i_submodule < vlc_internals( p_module )->i_children; i_submodule++ ) { UndupModule( (module_t*)vlc_internals( p_module )->pp_children[ i_submodule ] ); } for( pp_shortcut = p_module->pp_shortcuts ; *pp_shortcut ; pp_shortcut++ ) { free( *pp_shortcut ); } FREENULL( p_module->psz_object_name ); free( p_module->psz_capability ); free( p_module->psz_shortname ); free( p_module->psz_longname ); free( p_module->psz_help );}#endif /* HAVE_DYNAMIC_PLUGINS *//***************************************************************************** * AllocateBuiltinModule: initialize a builtin module. ***************************************************************************** * This function registers a builtin module and allocates a structure * for its information data. The module can then be handled by module_Need * and module_Unneed. It can be removed by DeleteModule. *****************************************************************************/static int AllocateBuiltinModule( vlc_object_t * p_this, int ( *pf_entry ) ( module_t * ) ){ module_t * p_module; /* Now that we have successfully loaded the module, we can * allocate a structure for it */ p_module = vlc_module_create( p_this ); if( p_module == NULL ) return -1; /* Initialize the module : fill p_module->psz_object_name, etc. */ if( pf_entry( p_module ) != 0 ) { /* With a well-written module we shouldn't have to print an * additional error message here, but just make sure. */ msg_Err( p_this, "failed calling entry point in builtin module" ); vlc_object_release( p_module ); return -1; } /* Everything worked fine ! The module is ready to be added to the list. */ p_module->b_builtin = true; /* msg_Dbg( p_this, "builtin \"%s\", %s", p_module->psz_object_name, p_module->psz_longname ); */ vlc_object_attach( p_module, vlc_global()->p_module_bank ); return 0;}/***************************************************************************** * DeleteModule: delete a module and its structure. ***************************************************************************** * This function can only be called if the module isn't being used. *****************************************************************************/static void DeleteModule( module_t * p_module, bool b_detach ){ assert( p_module ); if( b_detach ) vlc_object_detach( p_module ); /* We free the structures that we strdup()ed in Allocate*Module(). */#ifdef HAVE_DYNAMIC_PLUGINS if( !p_module->b_builtin ) { if( p_module->b_loaded && p_module->b_unloadable ) { module_Unload( p_module->handle ); } UndupModule( p_module ); free( p_module->psz_filename ); }#endif /* Free and detach the object's children */ while( vlc_internals( p_module )->i_children ) { vlc_object_t *p_this = vlc_internals( p_module )->pp_children[0]; vlc_object_detach( p_this ); vlc_object_release( p_this ); } config_Free( p_module ); vlc_object_release( p_module );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -