X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmodules%2Fmodules.c;h=15feab162a7f0218125c9fea26adff7dee695acf;hb=d6aa3d36b8570833583b763b187979399b8c6b2a;hp=52662a2c200e162de8f478eb7ef1fa51ca2521ee;hpb=40a2f546e1dca36312916b391f64f96a438f0a37;p=vlc diff --git a/src/modules/modules.c b/src/modules/modules.c index 52662a2c20..15feab162a 100644 --- a/src/modules/modules.c +++ b/src/modules/modules.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "libvlc.h" #include /* free(), strtol() */ @@ -42,46 +43,21 @@ # include #endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif +#include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif - -#if !defined(HAVE_DYNAMIC_PLUGINS) - /* no support for plugins */ -#elif defined(HAVE_DL_DYLD) -# if defined(HAVE_MACH_O_DYLD_H) -# include -# endif -#elif defined(HAVE_DL_BEOS) -# if defined(HAVE_IMAGE_H) -# include -# endif -#elif defined(HAVE_DL_WINDOWS) -# include -#elif defined(HAVE_DL_DLOPEN) -# if defined(HAVE_DLFCN_H) /* Linux, BSD, Hurd */ -# include -# endif -# if defined(HAVE_SYS_DL_H) -# include -# endif -#elif defined(HAVE_DL_SHL_LOAD) -# if defined(HAVE_DL_H) -# include -# endif +#ifdef ENABLE_NLS +# include #endif #include "config/configuration.h" -#include "vlc_charset.h" +#include #include "vlc_arrays.h" -#include #include "modules/modules.h" @@ -108,6 +84,7 @@ static void DupModule ( module_t * ); static void UndupModule ( module_t * ); #endif +#undef module_InitBank /** * Init bank * @@ -116,7 +93,7 @@ static void UndupModule ( module_t * ); * \param p_this vlc object structure * \return nothing */ -void __module_InitBank( vlc_object_t *p_this ) +void module_InitBank( vlc_object_t *p_this ) { module_bank_t *p_bank = NULL; @@ -140,6 +117,8 @@ void __module_InitBank( vlc_object_t *p_this ) * options of main will be available in the module bank structure just * as for every other module. */ AllocateBuiltinModule( p_this, vlc_entry__main ); + vlc_rwlock_init (&config_lock); + config_SortConfig (); } else p_module_bank->i_usage++; @@ -168,7 +147,7 @@ void module_EndBank( vlc_object_t *p_this, bool b_plugins ) assert (p_bank != NULL); /* Save the configuration */ - if( !config_GetInt( p_this, "ignore-config" ) ) + if( !var_InheritBool( p_this, "ignore-config" ) ) config_AutoSaveConfigFile( p_this ); /* If plugins were _not_ loaded, then the caller still has the bank lock @@ -183,12 +162,13 @@ void module_EndBank( vlc_object_t *p_this, bool b_plugins ) vlc_mutex_unlock( &module_lock ); return; } + + config_UnsortConfig (); + vlc_rwlock_destroy (&config_lock); p_module_bank = NULL; vlc_mutex_unlock( &module_lock ); #ifdef HAVE_DYNAMIC_PLUGINS - if( p_bank->b_cache ) - CacheSave( p_this, p_bank ); while( p_bank->i_loaded_cache-- ) { if( p_bank->pp_loaded_cache[p_bank->i_loaded_cache] ) @@ -222,7 +202,7 @@ void module_EndBank( vlc_object_t *p_this, bool b_plugins ) * \param p_this vlc object structure * \return nothing */ -void module_LoadPlugins( vlc_object_t * p_this, bool b_cache_delete ) +void module_LoadPlugins( vlc_object_t * p_this ) { module_bank_t *p_bank = p_module_bank; @@ -233,14 +213,13 @@ void module_LoadPlugins( vlc_object_t * p_this, bool b_cache_delete ) if( p_bank->i_usage == 1 ) { msg_Dbg( p_this, "checking plugin modules" ); - p_module_bank->b_cache = config_GetInt( p_this, "plugins-cache" ) > 0; + p_module_bank->b_cache = var_InheritBool( p_this, "plugins-cache" ); - if( p_module_bank->b_cache || b_cache_delete ) - CacheLoad( p_this, p_module_bank, b_cache_delete ); AllocateAllPlugins( p_this, p_module_bank ); + config_UnsortConfig (); + config_SortConfig (); } #endif - p_module_bank->b_plugins = true; vlc_mutex_unlock( &module_lock ); } @@ -315,6 +294,24 @@ int module_get_score( const module_t *m ) return m->i_score; } +/** + * Translate a string using the module's text domain + * + * \param m the module + * \param str the American English ASCII string to localize + * \return the gettext-translated string + */ +const char *module_gettext (const module_t *m, const char *str) +{ +#ifdef ENABLE_NLS + const char *domain = m->domain ? m->domain : PACKAGE_NAME; + return dgettext (domain, str); +#else + (void)m; + return str; +#endif +} + module_t *module_hold (module_t *m) { vlc_hold (&m->vlc_gc_data); @@ -326,6 +323,19 @@ void module_release (module_t *m) vlc_release (&m->vlc_gc_data); } +#undef module_start +int module_start (vlc_object_t *obj, module_t *m) +{ + return m->pf_activate ? (m->pf_activate (obj)) : VLC_SUCCESS; +} + +#undef module_stop +void module_stop (vlc_object_t *obj, module_t *m) +{ + if (m->pf_deactivate) + m->pf_deactivate (obj); +} + /** * Frees the flat list of VLC modules. * @param list list obtained by module_list_get() @@ -392,6 +402,7 @@ static int modulecmp (const void *a, const void *b) return lb->i_score - la->i_score; } +#undef module_need /** * module Need * @@ -404,8 +415,8 @@ static int modulecmp (const void *a, const void *b) * but the same capability * \return the module or NULL in case of a failure */ -module_t * __module_need( vlc_object_t *p_this, const char *psz_capability, - const char *psz_name, bool b_strict ) +module_t * module_need( vlc_object_t *p_this, const char *psz_capability, + const char *psz_name, bool b_strict ) { stats_TimerStart( p_this, "module_need()", STATS_TIMER_MODULE_NEED ); @@ -437,16 +448,13 @@ module_t * __module_need( vlc_object_t *p_this, const char *psz_capability, } i_shortcuts++; - psz_shortcuts = psz_last_shortcut = strdup( psz_name ); + psz_parser = psz_shortcuts = psz_last_shortcut = strdup( psz_name ); - for( psz_parser = psz_shortcuts; *psz_parser; psz_parser++ ) + while( ( psz_parser = strchr( psz_parser, ',' ) ) ) { - if( *psz_parser == ',' ) - { - *psz_parser = '\0'; - i_shortcuts++; - psz_last_shortcut = psz_parser + 1; - } + *psz_parser = '\0'; + i_shortcuts++; + psz_last_shortcut = ++psz_parser; } /* Check if the user wants to override the "strict" mode */ @@ -469,7 +477,6 @@ module_t * __module_need( vlc_object_t *p_this, const char *psz_capability, size_t count; module_t **p_all = module_list_get (&count); p_list = malloc( count * sizeof( module_list_t ) ); - unsigned i_cpu = vlc_CPU(); /* Parse the module list for capabilities and probe each of them */ count = 0; @@ -480,9 +487,6 @@ module_t * __module_need( vlc_object_t *p_this, const char *psz_capability, /* Test that this module can do what we need */ if( !module_provides( p_module, psz_capability ) ) continue; - /* Test if we have the required CPU */ - if( (p_module->i_cpu & i_cpu) != p_module->i_cpu ) - continue; /* If we required a shortcut, check this plugin provides it. */ if( i_shortcuts > 0 ) @@ -491,7 +495,7 @@ module_t * __module_need( vlc_object_t *p_this, const char *psz_capability, for( unsigned i_short = i_shortcuts; i_short > 0; i_short-- ) { - for( unsigned i = 0; p_module->pp_shortcuts[i]; i++ ) + for( unsigned i = 0; i < p_module->i_shortcuts; i++ ) { char *c; if( ( c = strchr( name, '@' ) ) @@ -564,10 +568,7 @@ found_shortcut: p_this->b_force = p_list[i].b_force; - int ret = VLC_SUCCESS; - if( p_cand->pf_activate ) - ret = p_cand->pf_activate( p_this ); - switch( ret ) + switch( module_start( p_this, p_cand ) ) { case VLC_SUCCESS: /* good module! */ @@ -600,30 +601,11 @@ found_shortcut: : p_module->psz_object_name ); } else if( count == 0 ) - { - if( !strcmp( psz_capability, "access_demux" ) - || !strcmp( psz_capability, "stream_filter" ) - || !strcmp( psz_capability, "vout_window" ) ) - { - msg_Dbg( p_this, "no %s module matched \"%s\"", - psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); - } - else - { - msg_Err( p_this, "no %s module matched \"%s\"", + msg_Dbg( p_this, "no %s module matched \"%s\"", psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); - - msg_StackSet( VLC_EGENERIC, "no %s module matched \"%s\"", - psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); - } - } - else if( psz_name != NULL && *psz_name ) - { - msg_Warn( p_this, "no %s module matching \"%s\" could be loaded", - psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); - } else - msg_StackSet( VLC_EGENERIC, "no suitable %s module", psz_capability ); + msg_Dbg( p_this, "no %s module matching \"%s\" could be loaded", + psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); free( psz_shortcuts ); free( psz_var ); @@ -636,6 +618,7 @@ found_shortcut: return p_module; } +#undef module_unneed /** * Module unneed * @@ -645,16 +628,10 @@ found_shortcut: * \param p_module the module structure * \return nothing */ -void __module_unneed( vlc_object_t * p_this, module_t * p_module ) +void module_unneed( vlc_object_t * p_this, module_t * p_module ) { - /* Use the close method */ - if( p_module->pf_deactivate ) - { - p_module->pf_deactivate( p_this ); - } - msg_Dbg( p_this, "removing module \"%s\"", p_module->psz_object_name ); - + module_stop( p_this, p_module ); module_release( p_module ); } @@ -719,9 +696,7 @@ module_t *module_find_by_shortcut (const char *psz_shortcut) for (size_t i = 0; (module = list[i]) != NULL; i++) { - for (size_t j = 0; - (module->pp_shortcuts[j] != NULL) && (j < MODULE_SHORTCUT_MAX); - j++) + for (size_t j = 0; j < module->i_shortcuts; j++) { if (!strcmp (module->pp_shortcuts[j], psz_shortcut)) { @@ -758,7 +733,6 @@ module_config_t *module_config_get( const module_t *module, unsigned *restrict p { const module_config_t *item = module->p_config + i; if( item->b_internal /* internal option */ - || item->b_unsaveable /* non-modifiable option */ || item->b_removed /* removed option */ ) continue; @@ -844,20 +818,17 @@ static void AllocateAllPlugins( vlc_object_t *p_this, module_bank_t *p_bank ) int count,i; char * path; vlc_array_t *arraypaths = vlc_array_new(); + const bool b_reset = var_InheritBool( p_this, "reset-plugins-cache" ); /* Contruct the special search path for system that have a relocatable - * executable. Set it to /modules and /plugins. */ + * executable. Set it to /plugins. */ + assert( vlcpath ); - if( vlcpath && asprintf( &path, "%s" DIR_SEP "modules", vlcpath ) != -1 ) - vlc_array_append( arraypaths, path ); - if( vlcpath && asprintf( &path, "%s" DIR_SEP "plugins", vlcpath ) != -1 ) + if( asprintf( &path, "%s" DIR_SEP "plugins", vlcpath ) != -1 ) vlc_array_append( arraypaths, path ); -#ifndef WIN32 - vlc_array_append( arraypaths, strdup( PLUGIN_PATH ) ); -#endif /* If the user provided a plugin path, we add it to the list */ - char *userpaths = config_GetPsz( p_this, "plugin-path" ); + char *userpaths = var_InheritString( p_this, "plugin-path" ); char *paths_iter; for( paths_iter = userpaths; paths_iter; ) @@ -874,11 +845,20 @@ static void AllocateAllPlugins( vlc_object_t *p_this, module_bank_t *p_bank ) if( !path ) continue; + size_t offset = p_module_bank->i_cache; + if( b_reset ) + CacheDelete( p_this, path ); + else + CacheLoad( p_this, p_module_bank, path ); + msg_Dbg( p_this, "recursively browsing `%s'", path ); /* Don't go deeper than 5 subdirectories */ AllocatePluginDir( p_this, p_bank, path, 5 ); + + CacheSave( p_this, path, p_module_bank->pp_cache + offset, + p_module_bank->i_cache - offset ); free( path ); } @@ -895,21 +875,23 @@ static void AllocatePluginDir( vlc_object_t *p_this, module_bank_t *p_bank, if( i_maxdepth == 0 ) return; - DIR *dh = utf8_opendir (psz_dir); + DIR *dh = vlc_opendir (psz_dir); if (dh == NULL) return; /* Parse the directory and try to load all files it contains. */ for (;;) { - char *file = utf8_readdir (dh), *path; + char *file = vlc_readdir (dh), *path; struct stat st; if (file == NULL) break; /* Skip ".", ".." */ - if (!strcmp (file, ".") || !strcmp (file, "..")) + if (!strcmp (file, ".") || !strcmp (file, "..") + /* Skip directories for unsupported optimizations */ + || !vlc_CPU_CheckPluginDir (file)) { free (file); continue; @@ -917,7 +899,7 @@ static void AllocatePluginDir( vlc_object_t *p_this, module_bank_t *p_bank, const int pathlen = asprintf (&path, "%s"DIR_SEP"%s", psz_dir, file); free (file); - if (pathlen == -1 || utf8_stat (path, &st)) + if (pathlen == -1 || vlc_stat (path, &st)) continue; if (S_ISDIR (st.st_mode)) @@ -925,10 +907,11 @@ static void AllocatePluginDir( vlc_object_t *p_this, module_bank_t *p_bank, AllocatePluginDir (p_this, p_bank, path, i_maxdepth - 1); else if (S_ISREG (st.st_mode) - && ((size_t)pathlen >= strlen (LIBEXT)) - && !strncasecmp (path + pathlen - strlen (LIBEXT), LIBEXT, - strlen (LIBEXT))) - /* ^^ We only load files ending with LIBEXT */ + && strncmp (path, "lib", 3) + && ((size_t)pathlen >= sizeof ("_plugin"LIBEXT)) + && !strncasecmp (path + pathlen - strlen ("_plugin"LIBEXT), + "_plugin"LIBEXT, strlen ("_plugni"LIBEXT))) + /* ^^ We only load files matching "lib*_plugin"LIBEXT */ AllocatePluginFile (p_this, p_bank, path, st.st_mtime, st.st_size); free (path); @@ -959,16 +942,16 @@ static int AllocatePluginFile( vlc_object_t * p_this, module_bank_t *p_bank, p_module = AllocatePlugin( p_this, psz_file ); } else - /* If junk dll, don't try to load it */ - if( p_cache_entry->b_junk ) - return -1; - else { module_config_t *p_item = NULL, *p_end = NULL; p_module = p_cache_entry->p_module; p_module->b_loaded = false; + /* If plugin-path contains duplicate entries... */ + if( p_module->next != NULL ) + return 0; /* already taken care of that one */ + /* For now we force loading if the module's config contains * callbacks or actions. * Could be optimized by adding an API call.*/ @@ -981,13 +964,14 @@ static int AllocatePluginFile( vlc_object_t * p_this, module_bank_t *p_bank, break; } } - if( p_module == p_cache_entry->p_module ) - p_cache_entry->b_used = true; } if( p_module == NULL ) return -1; + /* We have not already scanned and inserted this module */ + assert( p_module->next == NULL ); + /* Everything worked fine ! * The module is ready to be added to the list. */ p_module->b_builtin = false; @@ -996,6 +980,7 @@ static int AllocatePluginFile( vlc_object_t * p_this, module_bank_t *p_bank, p_module->psz_object_name, p_module->psz_longname ); */ p_module->next = p_bank->head; p_bank->head = p_module; + assert( p_module->next != NULL ); /* Insertion done */ if( !p_module_bank->b_cache ) return 0; @@ -1012,8 +997,6 @@ static int AllocatePluginFile( vlc_object_t * p_this, module_bank_t *p_bank, pp_cache[p_bank->i_cache]->psz_file = strdup( psz_file ); pp_cache[p_bank->i_cache]->i_time = i_file_time; pp_cache[p_bank->i_cache]->i_size = i_file_size; - pp_cache[p_bank->i_cache]->b_junk = p_module ? 0 : 1; - pp_cache[p_bank->i_cache]->b_used = true; pp_cache[p_bank->i_cache]->p_module = p_module; p_bank->pp_cache = pp_cache; p_bank->i_cache++; @@ -1074,12 +1057,9 @@ static module_t * AllocatePlugin( vlc_object_t * p_this, const char *psz_file ) *****************************************************************************/ static void DupModule( module_t *p_module ) { - char **pp_shortcut; - - for( pp_shortcut = p_module->pp_shortcuts ; *pp_shortcut ; pp_shortcut++ ) - { - *pp_shortcut = strdup( *pp_shortcut ); - } + char **pp_shortcuts = p_module->pp_shortcuts; + for( unsigned i = 0; i < p_module->i_shortcuts; i++ ) + pp_shortcuts[i] = strdup( p_module->pp_shortcuts[i] ); /* We strdup() these entries so that they are still valid when the * module is unloaded. */ @@ -1089,6 +1069,7 @@ static void DupModule( module_t *p_module ) p_module->psz_longname = strdup( p_module->psz_longname ); p_module->psz_help = p_module->psz_help ? strdup( p_module->psz_help ) : NULL; + p_module->domain = p_module->domain ? strdup( p_module->domain ) : NULL; for (module_t *subm = p_module->submodule; subm; subm = subm->next) DupModule (subm); @@ -1101,20 +1082,19 @@ static void DupModule( module_t *p_module ) *****************************************************************************/ static void UndupModule( module_t *p_module ) { - char **pp_shortcut; + char **pp_shortcuts = p_module->pp_shortcuts; for (module_t *subm = p_module->submodule; subm; subm = subm->next) UndupModule (subm); - for( pp_shortcut = p_module->pp_shortcuts ; *pp_shortcut ; pp_shortcut++ ) - { - free( *pp_shortcut ); - } + for( unsigned i = 0; i < p_module->i_shortcuts; i++ ) + free( pp_shortcuts[i] ); free( p_module->psz_capability ); FREENULL( p_module->psz_shortname ); free( p_module->psz_longname ); FREENULL( p_module->psz_help ); + free( p_module->domain ); } #endif /* HAVE_DYNAMIC_PLUGINS */