X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Flua%2Fextension.c;h=2a529b85a5e6415f9c94e096946125652dc6931c;hb=63ffc8e1218d553842ba80e577b6110bd2d4e48d;hp=16c363f6e8cce1939d0d611b9e44ab82c92fc35c;hpb=eeda6528dd9bf2fbb7bc5a61bb5744a59e913847;p=vlc diff --git a/modules/misc/lua/extension.c b/modules/misc/lua/extension.c index 16c363f6e8..2a529b85a5 100644 --- a/modules/misc/lua/extension.c +++ b/modules/misc/lua/extension.c @@ -56,7 +56,7 @@ const char* const ppsz_capabilities[] = { static int ScanExtensions( extensions_manager_t *p_this ); static int ScanLuaCallback( vlc_object_t *p_this, const char *psz_script, - void *pb_continue ); + void *dummy ); static int Control( extensions_manager_t *, int, va_list ); static int GetMenuEntries( extensions_manager_t *p_mgr, extension_t *p_ext, char ***pppsz_titles, uint16_t **ppi_ids ); @@ -181,12 +181,11 @@ void Close_Extension( vlc_object_t *p_this ) **/ static int ScanExtensions( extensions_manager_t *p_mgr ) { - bool b_true = true; int i_ret = vlclua_scripts_batch_execute( VLC_OBJECT( p_mgr ), "extensions", &ScanLuaCallback, - &b_true ); + NULL ); if( !i_ret ) return VLC_EGENERIC; @@ -194,16 +193,29 @@ static int ScanExtensions( extensions_manager_t *p_mgr ) return VLC_SUCCESS; } +/** + * Dummy Lua function: does nothing + * @note This function can be used to replace "require" while scanning for + * extensions + * Even the built-in libraries are not loaded when calling descriptor() + **/ +static int vlclua_dummy_require( lua_State *L ) +{ + (void) L; + return 0; +} + /** * Batch scan all Lua files in folder "extensions": callback * @param p_this This extensions_manager_t object * @param psz_script Name of the script to run * @param L Lua State, common to all scripts here - * @param pb_continue bool* that indicates whether to continue batch or not + * @param dummy: unused **/ int ScanLuaCallback( vlc_object_t *p_this, const char *psz_script, - void *pb_continue ) + void *dummy ) { + VLC_UNUSED(dummy); extensions_manager_t *p_mgr = ( extensions_manager_t* ) p_this; bool b_ok = false; @@ -236,8 +248,11 @@ int ScanLuaCallback( vlc_object_t *p_this, const char *psz_script, vlc_mutex_init( &p_ext->p_sys->running_lock ); vlc_cond_init( &p_ext->p_sys->wait ); - /* Load and run the script(s) */ + /* Prepare Lua state */ lua_State *L = luaL_newstate(); + lua_register( L, "require", &vlclua_dummy_require ); + + /* Let's run it */ if( luaL_dofile( L, psz_script ) ) { msg_Warn( p_mgr, "Error loading script %s: %s", psz_script, @@ -251,14 +266,14 @@ int ScanLuaCallback( vlc_object_t *p_this, const char *psz_script, if( !lua_isfunction( L, -1 ) ) { - msg_Warn( p_mgr, "Error while runing script %s, " + msg_Warn( p_mgr, "Error while running script %s, " "function descriptor() not found", psz_script ); goto exit; } if( lua_pcall( L, 0, 1, 0 ) ) { - msg_Warn( p_mgr, "Error while runing script %s, " + msg_Warn( p_mgr, "Error while running script %s, " "function descriptor(): %s", psz_script, lua_tostring( L, lua_gettop( L ) ) ); goto exit; @@ -327,61 +342,31 @@ int ScanLuaCallback( vlc_object_t *p_this, const char *psz_script, /* Get author */ lua_getfield( L, -1, "author" ); if( lua_isstring( L, -1 ) ) - { - p_ext->psz_author = strdup( luaL_checkstring( L, -1 ) ); - } - else - { - p_ext->psz_author = NULL; - } + p_ext->psz_author = strdup( luaL_optstring( L, -1, NULL ) ); lua_pop( L, 1 ); /* Get description */ lua_getfield( L, -1, "description" ); if( lua_isstring( L, -1 ) ) - { - p_ext->psz_description = strdup( luaL_checkstring( L, -1 ) ); - } - else - { - p_ext->psz_description = NULL; - } + p_ext->psz_description = strdup( luaL_optstring( L, -1, NULL ) ); lua_pop( L, 1 ); /* Get short description */ lua_getfield( L, -1, "shortdesc" ); if( lua_isstring( L, -1 ) ) - { - p_ext->psz_shortdescription = strdup( luaL_checkstring( L, -1 ) ); - } - else - { - p_ext->psz_shortdescription = NULL; - } + p_ext->psz_shortdescription = strdup( luaL_optstring( L, -1, NULL ) ); lua_pop( L, 1 ); /* Get URL */ lua_getfield( L, -1, "url" ); if( lua_isstring( L, -1 ) ) - { - p_ext->psz_url = strdup( luaL_checkstring( L, -1 ) ); - } - else - { - p_ext->psz_url = NULL; - } + p_ext->psz_url = strdup( luaL_optstring( L, -1, NULL ) ); lua_pop( L, 1 ); /* Get version */ lua_getfield( L, -1, "version" ); if( lua_isstring( L, -1 ) ) - { - p_ext->psz_version = strdup( luaL_checkstring( L, -1 ) ); - } - else - { - p_ext->psz_version = NULL; - } + p_ext->psz_version = strdup( luaL_optstring( L, -1, NULL ) ); lua_pop( L, 1 ); } else @@ -426,7 +411,7 @@ exit: vlc_mutex_unlock( &p_mgr->lock ); /* Continue batch execution */ - return pb_continue ? ( (* (bool*)pb_continue) ? -1 : 0 ) : -1; + return VLC_EGENERIC; } static int Control( extensions_manager_t *p_mgr, int i_control, va_list args ) @@ -593,7 +578,10 @@ int lua_ExtensionWidgetClick( extensions_manager_t *p_mgr, if( !p_ext->p_sys->L ) return VLC_SUCCESS; - return lua_ExecuteFunction( p_mgr, p_ext, (const char*) p_widget->p_sys, LUA_END ); + lua_State *L = GetLuaState( p_mgr, p_ext ); + lua_pushlightuserdata( L, p_widget ); + lua_gettable( L, LUA_REGISTRYINDEX ); + return lua_ExecuteFunction( p_mgr, p_ext, NULL, LUA_END ); } @@ -602,7 +590,7 @@ int lua_ExtensionWidgetClick( extensions_manager_t *p_mgr, * @param p_mgr * @param p_ext * @param pppsz_titles Pointer to NULL. All strings must be freed by the caller - * @param ppi_ids Pointer to NULL. Must be feed by the caller. + * @param ppi_ids Pointer to NULL. Must be freed by the caller. * @note This function is allowed to run in the UI thread. This means * that it MUST respond very fast. * @todo Remove the menu() hook and provide a new function vlc.set_menu() @@ -638,14 +626,14 @@ static int GetMenuEntries( extensions_manager_t *p_mgr, extension_t *p_ext, if( !lua_isfunction( L, -1 ) ) { - msg_Warn( p_mgr, "Error while runing script %s, " + msg_Warn( p_mgr, "Error while running script %s, " "function menu() not found", p_ext->psz_name ); goto exit; } if( lua_pcall( L, 0, 1, 0 ) ) { - msg_Warn( p_mgr, "Error while runing script %s, " + msg_Warn( p_mgr, "Error while running script %s, " "function menu(): %s", p_ext->psz_name, lua_tostring( L, lua_gettop( L ) ) ); goto exit; @@ -719,16 +707,13 @@ static lua_State* GetLuaState( extensions_manager_t *p_mgr, msg_Err( p_mgr, "Could not create new Lua State" ); return NULL; } + vlclua_set_this( L, p_mgr ); + vlclua_extension_set( L, p_ext ); + luaL_openlibs( L ); luaL_register( L, "vlc", p_reg ); luaopen_msg( L ); - lua_pushlightuserdata( L, p_mgr ); - lua_setfield( L, -2, "private" ); - - lua_pushlightuserdata( L, p_ext ); - lua_setfield( L, -2, "extension" ); - if( p_ext ) { /* Load more libraries */ @@ -736,6 +721,7 @@ static lua_State* GetLuaState( extensions_manager_t *p_mgr, luaopen_config( L ); luaopen_dialog( L, p_ext ); luaopen_input( L ); + luaopen_md5( L ); luaopen_msg( L ); luaopen_misc( L ); luaopen_net( L ); @@ -775,13 +761,6 @@ static lua_State* GetLuaState( extensions_manager_t *p_mgr, p_ext->p_sys->L = L; } } -#ifndef NDEBUG - else - { - msg_Dbg( p_mgr, "Reusing old Lua state for extension '%s'", - p_ext->psz_name ); - } -#endif return L; } @@ -798,6 +777,9 @@ int lua_ExecuteFunction( extensions_manager_t *p_mgr, extension_t *p_ext, /** * Execute a function in a Lua script + * @param psz_function Name of global function to execute. If NULL, assume + * that the function object is already on top of the + * stack. * @return < 0 in case of failure, >= 0 in case of success * @note It's better to call this function from a dedicated thread * (see extension_thread.c) @@ -811,11 +793,12 @@ int lua_ExecuteFunctionVa( extensions_manager_t *p_mgr, extension_t *p_ext, assert( p_ext != NULL ); lua_State *L = GetLuaState( p_mgr, p_ext ); - lua_getglobal( L, psz_function ); + if( psz_function ) + lua_getglobal( L, psz_function ); if( !lua_isfunction( L, -1 ) ) { - msg_Warn( p_mgr, "Error while runing script %s, " + msg_Warn( p_mgr, "Error while running script %s, " "function %s() not found", p_ext->psz_name, psz_function ); goto exit; } @@ -841,7 +824,7 @@ int lua_ExecuteFunctionVa( extensions_manager_t *p_mgr, extension_t *p_ext, } if( lua_pcall( L, i_args, 1, 0 ) ) { - msg_Warn( p_mgr, "Error while runing script %s, " + msg_Warn( p_mgr, "Error while running script %s, " "function %s(): %s", p_ext->psz_name, psz_function, lua_tostring( L, lua_gettop( L ) ) ); goto exit; @@ -872,7 +855,7 @@ int lua_ExtensionTriggerMenu( extensions_manager_t *p_mgr, lua_getglobal( L, "trigger_menu" ); if( !lua_isfunction( L, -1 ) ) { - msg_Warn( p_mgr, "Error while runing script %s, " + msg_Warn( p_mgr, "Error while running script %s, " "function trigger_menu() not found", p_ext->psz_name ); return VLC_EGENERIC; } @@ -882,7 +865,7 @@ int lua_ExtensionTriggerMenu( extensions_manager_t *p_mgr, if( lua_pcall( L, 1, 1, 0 ) != 0 ) { - msg_Warn( p_mgr, "Error while runing script %s, " + msg_Warn( p_mgr, "Error while running script %s, " "function trigger_menu(): %s", p_ext->psz_name, lua_tostring( L, lua_gettop( L ) ) ); return VLC_EGENERIC; @@ -916,17 +899,27 @@ static int TriggerExtension( extensions_manager_t *p_mgr, return i_ret; } +/** Set extension associated to the current script + * @param L current lua_State + * @param p_ext the extension + */ +void vlclua_extension_set( lua_State *L, extension_t *p_ext ) +{ + lua_pushlightuserdata( L, vlclua_extension_set ); + lua_pushlightuserdata( L, p_ext ); + lua_rawset( L, LUA_REGISTRYINDEX ); +} + /** Retrieve extension associated to the current script * @param L current lua_State - * @return Lua userdata "vlc.extension" + * @return Extension pointer **/ extension_t *vlclua_extension_get( lua_State *L ) { - extension_t *p_ext = NULL; - lua_getglobal( L, "vlc" ); - lua_getfield( L, -1, "extension" ); - p_ext = (extension_t*) lua_topointer( L, lua_gettop( L ) ); - lua_pop( L, 2 ); + lua_pushlightuserdata( L, vlclua_extension_set ); + lua_rawget( L, LUA_REGISTRYINDEX ); + extension_t *p_ext = (extension_t*) lua_topointer( L, -1 ); + lua_pop( L, 1 ); return p_ext; } @@ -973,7 +966,7 @@ static int vlclua_extension_dialog_callback( vlc_object_t *p_this, { case EXTENSION_EVENT_CLICK: assert( p_widget != NULL ); - PushCommand( p_ext, CMD_CLICK, p_widget ); + PushCommandUnique( p_ext, CMD_CLICK, p_widget ); break; case EXTENSION_EVENT_CLOSE: PushCommandUnique( p_ext, CMD_CLOSE );