/***************************************************************************** * Run a lua entry point function *****************************************************************************/ static int run( vlc_object_t *p_this, const char * psz_filename, lua_State * L, const char *luafunction, const luabatch_context_t *p_context ) { /* Ugly hack to delete previous versions of the fetchart() * functions. */ lua_pushnil( L ); lua_setglobal( L, luafunction ); /* Load and run the script(s) */ if( vlclua_dofile( p_this, L, psz_filename ) ) { msg_Warn( p_this, "Error loading script %s: %s", psz_filename, lua_tostring( L, lua_gettop( L ) ) ); goto error; } meta_fetcher_scope_t e_scope = FETCHER_SCOPE_NETWORK; /* default to restricted one */ lua_getglobal( L, "descriptor" ); if( lua_isfunction( L, lua_gettop( L ) ) && !lua_pcall( L, 0, 1, 0 ) ) { lua_getfield( L, -1, "scope" ); char *psz_scope = luaL_strdupornull( L, -1 ); if ( psz_scope && !strcmp( psz_scope, "local" ) ) e_scope = FETCHER_SCOPE_LOCAL; free( psz_scope ); lua_pop( L, 1 ); } lua_pop( L, 1 ); if ( p_context && p_context->pf_validator && !p_context->pf_validator( p_context, e_scope ) ) { msg_Dbg( p_this, "skipping script (unmatched scope) %s", psz_filename ); goto error; } lua_getglobal( L, luafunction ); if( !lua_isfunction( L, lua_gettop( L ) ) ) { msg_Warn( p_this, "Error while running script %s, " "function %s() not found", psz_filename, luafunction ); goto error; } if( lua_pcall( L, 0, 1, 0 ) ) { msg_Warn( p_this, "Error while running script %s, " "function %s(): %s", psz_filename, luafunction, lua_tostring( L, lua_gettop( L ) ) ); goto error; } return VLC_SUCCESS; error: lua_pop( L, 1 ); return VLC_EGENERIC; }
int vlclua_probe_sd( vlc_object_t *obj, const char *name ) { vlc_probe_t *probe = (vlc_probe_t *)obj; char *filename = vlclua_find_file( "sd", name ); if( filename == NULL ) { // File suddenly disappeared - maybe a race condition, no problem msg_Err( probe, "Couldn't probe lua services discovery script \"%s\".", name ); return VLC_PROBE_CONTINUE; } lua_State *L = luaL_newstate(); if( !L ) { msg_Err( probe, "Could not create new Lua State" ); free( filename ); return VLC_ENOMEM; } luaL_openlibs( L ); if( vlclua_add_modules_path( L, filename ) ) { msg_Err( probe, "Error while setting the module search path for %s", filename ); lua_close( L ); free( filename ); return VLC_ENOMEM; } if( vlclua_dofile( obj, L, filename ) ) { msg_Err( probe, "Error loading script %s: %s", filename, lua_tostring( L, -1 ) ); lua_close( L ); free( filename ); return VLC_PROBE_CONTINUE; } const char *description = vlclua_sd_description( obj, L, filename ); if( description == NULL ) description = name; int r = VLC_ENOMEM; char *name_esc = config_StringEscape( name ); char *chain; if( asprintf( &chain, "lua{sd='%s'}", name_esc ) != -1 ) { r = vlc_sd_probe_Add( probe, chain, description, SD_CAT_INTERNET ); free( chain ); } free( name_esc ); lua_close( L ); free( filename ); return r; }
static void *Run( void *data ) { intf_thread_t *p_intf = data; intf_sys_t *p_sys = p_intf->p_sys; lua_State *L = p_sys->L; if( vlclua_dofile( VLC_OBJECT(p_intf), L, p_sys->psz_filename ) ) { msg_Err( p_intf, "Error loading script %s: %s", p_sys->psz_filename, lua_tostring( L, lua_gettop( L ) ) ); lua_pop( L, 1 ); } return NULL; }
/***************************************************************************** * FillDescriptor: call the descriptor function and fill the structure ****************************************************************************/ static int FillDescriptor( services_discovery_t *p_sd, services_discovery_descriptor_t *p_desc ) { services_discovery_sys_t *p_sys = p_sd->p_sys; int i_ret = VLC_EGENERIC; /* Create a new lua thread */ lua_State *L = luaL_newstate(); if( vlclua_dofile( VLC_OBJECT(p_sd), L, p_sys->psz_filename ) ) { msg_Err( p_sd, "Error loading script %s: %s", p_sys->psz_filename, lua_tostring( L, -1 ) ); goto end; } /* Call the "descriptor" function */ lua_getglobal( L, "descriptor" ); if( !lua_isfunction( L, -1 ) || lua_pcall( L, 0, 1, 0 ) ) { msg_Warn( p_sd, "Error getting the descriptor in '%s': %s", p_sys->psz_filename, lua_tostring( L, -1 ) ); goto end; } /* Get the different fields of the returned table */ lua_getfield( L, -1, "short_description" ); p_desc->psz_short_desc = luaL_strdupornull( L, -1 ); lua_pop( L, 1 ); lua_getfield( L, -1, "icon" ); p_desc->psz_icon_url = luaL_strdupornull( L, -1 ); lua_pop( L, 1 ); lua_getfield( L, -1, "url" ); p_desc->psz_url = luaL_strdupornull( L, -1 ); lua_pop( L, 1 ); lua_getfield( L, -1, "capabilities" ); p_desc->i_capabilities = 0; if( lua_istable( L, -1 ) ) { /* List all table entries */ lua_pushnil( L ); while( lua_next( L, -2 ) != 0 ) { /* Key is at index -2 and value at index -1 */ const char *psz_cap = luaL_checkstring( L, -1 ); int i_cap = 0; const char *psz_iter; for( psz_iter = *ppsz_capabilities; psz_iter; psz_iter = ppsz_capabilities[ ++i_cap ] ) { if( !strcmp( psz_iter, psz_cap ) ) { p_desc->i_capabilities |= 1 << i_cap; break; } } lua_pop( L, 1 ); if( !psz_iter ) msg_Warn( p_sd, "Services discovery capability '%s' unknown in " "script '%s'", psz_cap, p_sys->psz_filename ); } } lua_pop( L, 1 ); i_ret = VLC_SUCCESS; end: lua_close( L ); return i_ret; }
/***************************************************************************** * Open: initialize and create stuff *****************************************************************************/ int Open_LuaSD( vlc_object_t *p_this ) { services_discovery_t *p_sd = ( services_discovery_t * )p_this; services_discovery_sys_t *p_sys; lua_State *L = NULL; char *psz_name; if( !( p_sys = malloc( sizeof( services_discovery_sys_t ) ) ) ) return VLC_ENOMEM; if( !strcmp( p_sd->psz_name, "lua" ) || !strcmp( p_sd->psz_name, "luasd" ) ) { // We want to load the module name "lua" // This module can be used to load lua script not registered // as builtin lua SD modules. config_ChainParse( p_sd, "lua-", ppsz_sd_options, p_sd->p_cfg ); psz_name = var_GetString( p_sd, "lua-sd" ); } else { // We are loading a builtin lua sd module. psz_name = strdup(p_sd->psz_name); } p_sd->p_sys = p_sys; p_sd->pf_control = Control; p_sys->psz_filename = vlclua_find_file( "sd", psz_name ); if( !p_sys->psz_filename ) { msg_Err( p_sd, "Couldn't find lua services discovery script \"%s\".", psz_name ); free( psz_name ); goto error; } free( psz_name ); L = luaL_newstate(); if( !L ) { msg_Err( p_sd, "Could not create new Lua State" ); goto error; } vlclua_set_this( L, p_sd ); luaL_openlibs( L ); luaL_register_namespace( L, "vlc", p_reg ); luaopen_input( L ); luaopen_msg( L ); luaopen_object( L ); luaopen_sd_sd( L ); luaopen_strings( L ); luaopen_variables( L ); luaopen_stream( L ); luaopen_gettext( L ); luaopen_xml( L ); lua_pop( L, 1 ); if( vlclua_add_modules_path( L, p_sys->psz_filename ) ) { msg_Warn( p_sd, "Error while setting the module search path for %s", p_sys->psz_filename ); goto error; } if( vlclua_dofile( VLC_OBJECT(p_sd), L, p_sys->psz_filename ) ) { msg_Err( p_sd, "Error loading script %s: %s", p_sys->psz_filename, lua_tostring( L, lua_gettop( L ) ) ); lua_pop( L, 1 ); goto error; } // No strdup(), just don't remove the string from the lua stack p_sd->description = vlclua_sd_description( VLC_OBJECT(p_sd), L, p_sys->psz_filename ); if( p_sd->description == NULL ) p_sd->description = p_sd->psz_name; p_sys->L = L; vlc_mutex_init( &p_sys->lock ); vlc_cond_init( &p_sys->cond ); TAB_INIT( p_sys->i_query, p_sys->ppsz_query ); if( vlc_clone( &p_sys->thread, Run, p_sd, VLC_THREAD_PRIORITY_LOW ) ) { TAB_CLEAN( p_sys->i_query, p_sys->ppsz_query ); vlc_cond_destroy( &p_sys->cond ); vlc_mutex_destroy( &p_sys->lock ); goto error; } return VLC_SUCCESS; error: if( L ) lua_close( L ); free( p_sys->psz_filename ); free( p_sys ); return VLC_EGENERIC; }
static int vlc_sd_probe_Open( vlc_object_t *obj ) { vlc_probe_t *probe = (vlc_probe_t *)obj; char **ppsz_filelist = NULL; char **ppsz_fileend = NULL; char **ppsz_file; char *psz_name; char **ppsz_dir_list = NULL; char **ppsz_dir; lua_State *L = NULL; vlclua_dir_list( "sd", &ppsz_dir_list ); for( ppsz_dir = ppsz_dir_list; *ppsz_dir; ppsz_dir++ ) { int i_files; if( ppsz_filelist ) { for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; ppsz_file++ ) free( *ppsz_file ); free( ppsz_filelist ); ppsz_filelist = NULL; } i_files = vlc_scandir( *ppsz_dir, &ppsz_filelist, file_select, file_compare ); if( i_files < 1 ) continue; ppsz_fileend = ppsz_filelist + i_files; for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; ppsz_file++ ) { char *psz_filename; if( asprintf( &psz_filename, "%s" DIR_SEP "%s", *ppsz_dir, *ppsz_file ) < 0 ) { goto error; } L = luaL_newstate(); if( !L ) { msg_Err( probe, "Could not create new Lua State" ); free( psz_filename ); goto error; } luaL_openlibs( L ); if( vlclua_add_modules_path( L, psz_filename ) ) { msg_Err( probe, "Error while setting the module search path for %s", psz_filename ); free( psz_filename ); goto error; } if( vlclua_dofile( VLC_OBJECT(probe), L, psz_filename ) ) { msg_Err( probe, "Error loading script %s: %s", psz_filename, lua_tostring( L, lua_gettop( L ) ) ); lua_pop( L, 1 ); free( psz_filename ); lua_close( L ); continue; } char *psz_longname; char *temp = strchr( *ppsz_file, '.' ); if( temp ) *temp = '\0'; lua_getglobal( L, "descriptor" ); if( !lua_isfunction( L, lua_gettop( L ) ) || lua_pcall( L, 0, 1, 0 ) ) { msg_Warn( probe, "No 'descriptor' function in '%s'", psz_filename ); lua_pop( L, 1 ); if( !( psz_longname = strdup( *ppsz_file ) ) ) { free( psz_filename ); goto error; } } else { lua_getfield( L, -1, "title" ); if( !lua_isstring( L, -1 ) || !( psz_longname = strdup( lua_tostring( L, -1 ) ) ) ) { free( psz_filename ); goto error; } } char *psz_file_esc = config_StringEscape( *ppsz_file ); char *psz_longname_esc = config_StringEscape( psz_longname ); if( asprintf( &psz_name, "lua{sd='%s',longname='%s'}", psz_file_esc, psz_longname_esc ) < 0 ) { free( psz_file_esc ); free( psz_longname_esc ); free( psz_filename ); free( psz_longname ); goto error; } free( psz_file_esc ); free( psz_longname_esc ); vlc_sd_probe_Add( probe, psz_name, psz_longname, SD_CAT_INTERNET ); free( psz_name ); free( psz_longname ); free( psz_filename ); lua_close( L ); } } if( ppsz_filelist ) { for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; ppsz_file++ ) free( *ppsz_file ); free( ppsz_filelist ); } vlclua_dir_list_free( ppsz_dir_list ); return VLC_PROBE_CONTINUE; error: if( ppsz_filelist ) { for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; ppsz_file++ ) free( *ppsz_file ); free( ppsz_filelist ); } if( L ) lua_close( L ); vlclua_dir_list_free( ppsz_dir_list ); return VLC_ENOMEM; }
/***************************************************************************** * Called through lua_scripts_batch_execute to call 'probe' on * the script pointed by psz_filename. *****************************************************************************/ static int probe_luascript( vlc_object_t *p_this, const char * psz_filename, const luabatch_context_t *p_context ) { VLC_UNUSED(p_context); demux_t * p_demux = (demux_t *)p_this; p_demux->p_sys->psz_filename = strdup(psz_filename); /* Initialise Lua state structure */ lua_State *L = luaL_newstate(); if( !L ) { msg_Err( p_demux, "Could not create new Lua State" ); goto error; } p_demux->p_sys->L = L; /* Load Lua libraries */ luaL_openlibs( L ); /* FIXME: Don't open all the libs? */ vlclua_set_this( L, p_demux ); luaL_register_namespace( L, "vlc", p_reg ); luaopen_msg( L ); luaopen_strings( L ); luaopen_stream( L ); luaopen_variables( L ); luaopen_xml( L ); lua_pushstring( L, p_demux->psz_location ); lua_setfield( L, -2, "path" ); lua_pushstring( L, p_demux->psz_access ); lua_setfield( L, -2, "access" ); lua_pop( L, 1 ); /* Setup the module search path */ if( vlclua_add_modules_path( L, psz_filename ) ) { msg_Warn( p_demux, "Error while setting the module search path for %s", psz_filename ); goto error; } /* Load and run the script(s) */ if( vlclua_dofile( VLC_OBJECT(p_demux), L, psz_filename ) ) { msg_Warn( p_demux, "Error loading script %s: %s", psz_filename, lua_tostring( L, lua_gettop( L ) ) ); goto error; } lua_getglobal( L, "probe" ); if( !lua_isfunction( L, -1 ) ) { msg_Warn( p_demux, "Error while running script %s, " "function probe() not found", psz_filename ); goto error; } if( lua_pcall( L, 0, 1, 0 ) ) { msg_Warn( p_demux, "Error while running script %s, " "function probe(): %s", psz_filename, lua_tostring( L, lua_gettop( L ) ) ); goto error; } if( lua_gettop( L ) ) { if( lua_toboolean( L, 1 ) ) { msg_Dbg( p_demux, "Lua playlist script %s's " "probe() function was successful", psz_filename ); lua_pop( L, 1 ); return VLC_SUCCESS; } } error: lua_pop( L, 1 ); lua_close( p_demux->p_sys->L ); p_demux->p_sys->L = NULL; FREENULL( p_demux->p_sys->psz_filename ); return VLC_EGENERIC; }
/***************************************************************************** * Called through lua_scripts_batch_execute to call 'probe' on * the script pointed by psz_filename. *****************************************************************************/ static int probe_luascript(vlc_object_t *obj, const char *filename, const luabatch_context_t *ctx) { stream_t *s = (stream_t *)obj; struct vlclua_playlist *sys = s->p_sys; /* Initialise Lua state structure */ lua_State *L = luaL_newstate(); if( !L ) return VLC_ENOMEM; sys->L = L; /* Load Lua libraries */ luaL_openlibs( L ); /* FIXME: Don't open all the libs? */ vlclua_set_this(L, s); luaL_register_namespace( L, "vlc", p_reg ); luaopen_msg( L ); luaopen_strings( L ); luaopen_stream( L ); luaopen_variables( L ); luaopen_xml( L ); if (sys->path != NULL) lua_pushstring(L, sys->path); else lua_pushnil(L); lua_setfield( L, -2, "path" ); if (sys->access != NULL) lua_pushstring(L, sys->access); else lua_pushnil(L); lua_setfield( L, -2, "access" ); lua_pop( L, 1 ); /* Setup the module search path */ if (vlclua_add_modules_path(L, filename)) { msg_Warn(s, "error setting the module search path for %s", filename); goto error; } /* Load and run the script(s) */ if (vlclua_dofile(VLC_OBJECT(s), L, filename)) { msg_Warn(s, "error loading script %s: %s", filename, lua_tostring(L, lua_gettop(L))); goto error; } lua_getglobal( L, "probe" ); if( !lua_isfunction( L, -1 ) ) { msg_Warn(s, "error running script %s: function %s(): %s", filename, "probe", "not found"); goto error; } if( lua_pcall( L, 0, 1, 0 ) ) { msg_Warn(s, "error running script %s: function %s(): %s", filename, "probe", lua_tostring(L, lua_gettop(L))); goto error; } if( lua_gettop( L ) ) { if( lua_toboolean( L, 1 ) ) { msg_Dbg(s, "Lua playlist script %s's " "probe() function was successful", filename ); lua_pop( L, 1 ); sys->filename = strdup(filename); return VLC_SUCCESS; } } (void) ctx; error: lua_pop( L, 1 ); lua_close(sys->L); return VLC_EGENERIC; }