X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Flua%2Flibs%2Fmisc.c;h=ba012682832e1acc4e1ee5d14599dd0b053715c1;hb=HEAD;hp=8a21cceeebc5d2b465b56a7d9acde6a8187209ad;hpb=b935abee4d16231e34ab6a2b092fcc1e757483c5;p=vlc diff --git a/modules/misc/lua/libs/misc.c b/modules/misc/lua/libs/misc.c index 8a21cceeeb..ba01268283 100644 --- a/modules/misc/lua/libs/misc.c +++ b/modules/misc/lua/libs/misc.c @@ -6,6 +6,7 @@ * * Authors: Antoine Cellerier * Pierre d'Herbemont + * Rémi Duraffort * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,9 +37,9 @@ #include #include #include -#include #include #include +#include #include /* Low level lua C API */ #include /* Higher level C API */ @@ -50,14 +51,41 @@ /***************************************************************************** * Internal lua<->vlc utils *****************************************************************************/ +static void vlclua_set_object( lua_State *L, void *id, void *value ) +{ + lua_pushlightuserdata( L, id ); + lua_pushlightuserdata( L, value ); + lua_rawset( L, LUA_REGISTRYINDEX ); +} + +static void *vlclua_get_object( lua_State *L, void *id ) +{ + lua_pushlightuserdata( L, id ); + lua_rawget( L, LUA_REGISTRYINDEX ); + const void *p = lua_topointer( L, -1 ); + lua_pop( L, 1 ); + return (void *)p; +} + +#undef vlclua_set_this +void vlclua_set_this( lua_State *L, vlc_object_t *p_this ) +{ + vlclua_set_object( L, vlclua_set_this, p_this ); +} + vlc_object_t * vlclua_get_this( lua_State *L ) { - vlc_object_t * p_this; - lua_getglobal( L, "vlc" ); - lua_getfield( L, -1, "private" ); - p_this = (vlc_object_t*)lua_topointer( L, lua_gettop( L ) ); - lua_pop( L, 2 ); - return p_this; + return vlclua_get_object( L, vlclua_set_this ); +} + +void vlclua_set_intf( lua_State *L, intf_sys_t *p_intf ) +{ + vlclua_set_object( L, vlclua_set_intf, p_intf ); +} + +static intf_sys_t * vlclua_get_intf( lua_State *L ) +{ + return vlclua_get_object( L, vlclua_set_intf ); } /***************************************************************************** @@ -84,7 +112,7 @@ static int vlclua_version( lua_State *L ) *****************************************************************************/ static int vlclua_copyright( lua_State *L ) { - lua_pushstring( L, COPYRIGHT_MESSAGE ); + lua_pushliteral( L, COPYRIGHT_MESSAGE ); return 1; } @@ -105,7 +133,7 @@ static int vlclua_quit( lua_State *L ) vlc_object_t *p_this = vlclua_get_this( L ); /* The rc.c code also stops the playlist ... not sure if this is needed * though. */ - vlc_object_kill( p_this->p_libvlc ); + libvlc_Quit( p_this->p_libvlc ); return 0; } @@ -114,25 +142,31 @@ static int vlclua_quit( lua_State *L ) *****************************************************************************/ static int vlclua_datadir( lua_State *L ) { - lua_pushstring( L, config_GetDataDir() ); + char *psz_data = config_GetDataDir( vlclua_get_this( L ) ); + lua_pushstring( L, psz_data ); + free( psz_data ); return 1; } static int vlclua_userdatadir( lua_State *L ) { - lua_pushstring( L, config_GetUserDataDir() ); + char *dir = config_GetUserDir( VLC_DATA_DIR ); + lua_pushstring( L, dir ); + free( dir ); return 1; } static int vlclua_homedir( lua_State *L ) { - lua_pushstring( L, config_GetHomeDir() ); + char *home = config_GetUserDir( VLC_HOME_DIR ); + lua_pushstring( L, home ); + free( home ); return 1; } static int vlclua_configdir( lua_State *L ) { - char *dir = config_GetUserConfDir(); + char *dir = config_GetUserDir( VLC_CONFIG_DIR ); lua_pushstring( L, dir ); free( dir ); return 1; @@ -140,7 +174,7 @@ static int vlclua_configdir( lua_State *L ) static int vlclua_cachedir( lua_State *L ) { - char *dir = config_GetCacheDir(); + char *dir = config_GetUserDir( VLC_CACHE_DIR ); lua_pushstring( L, dir ); free( dir ); return 1; @@ -149,14 +183,14 @@ static int vlclua_cachedir( lua_State *L ) static int vlclua_datadir_list( lua_State *L ) { const char *psz_dirname = luaL_checkstring( L, 1 ); - char *ppsz_dir_list[] = { NULL, NULL, NULL, NULL }; - char **ppsz_dir = ppsz_dir_list; + char **ppsz_dir_list = NULL; int i = 1; - if( vlclua_dir_list( psz_dirname, ppsz_dir_list ) != VLC_SUCCESS ) + if( vlclua_dir_list( vlclua_get_this( L ), psz_dirname, &ppsz_dir_list ) + != VLC_SUCCESS ) return 0; lua_newtable( L ); - for( ; *ppsz_dir; ppsz_dir++ ) + for( char **ppsz_dir = ppsz_dir_list; *ppsz_dir; ppsz_dir++ ) { lua_pushstring( L, *ppsz_dir ); lua_rawseti( L, -2, i ); @@ -170,13 +204,13 @@ static int vlclua_datadir_list( lua_State *L ) *****************************************************************************/ static int vlclua_lock_and_wait( lua_State *L ) { - intf_thread_t *p_intf = (intf_thread_t *)vlclua_get_this( L ); - intf_sys_t *p_sys = p_intf->p_sys; + intf_sys_t *p_sys = vlclua_get_intf( L ); vlc_mutex_lock( &p_sys->lock ); + mutex_cleanup_push( &p_sys->lock ); while( !p_sys->exiting ) vlc_cond_wait( &p_sys->wait, &p_sys->lock ); - vlc_mutex_unlock( &p_sys->lock ); + vlc_cleanup_run(); lua_pushboolean( L, 1 ); return 1; } @@ -196,8 +230,114 @@ static int vlclua_mwait( lua_State *L ) static int vlclua_intf_should_die( lua_State *L ) { - intf_thread_t *p_intf = (intf_thread_t*)vlclua_get_this( L ); - lua_pushboolean( L, !vlc_object_alive( p_intf ) ); + intf_sys_t *p_sys = vlclua_get_intf( L ); + lua_pushboolean( L, p_sys->exiting ); + return 1; +} + +static int vlclua_action_id( lua_State *L ) +{ + vlc_key_t i_key = vlc_GetActionId( luaL_checkstring( L, 1 ) ); + if (i_key == 0) + return 0; + lua_pushnumber( L, i_key ); + return 1; +} + +/***************************************************************************** + * Timer functions + *****************************************************************************/ +static int vlclua_timer_schedule( lua_State *L ); +static int vlclua_timer_getoverrun( lua_State *L); + +static const luaL_Reg vlclua_timer_reg[] = { + { "schedule", vlclua_timer_schedule }, + { "getoverrun", vlclua_timer_getoverrun }, + { NULL, NULL } +}; + +typedef struct +{ + lua_State *L; + vlc_timer_t timer; + char *psz_callback; +} vlclua_timer_t; + +static int vlclua_timer_schedule( lua_State *L ) +{ + vlclua_timer_t **pp_timer = (vlclua_timer_t**)luaL_checkudata( L, 1, "timer" ); + if( !pp_timer || !*pp_timer ) + luaL_error( L, "Can't get pointer to timer" ); + + bool b_relative = luaL_checkboolean( L, 2 ); + mtime_t i_value = luaL_checkinteger( L, 3 ); + mtime_t i_interval = luaL_checkinteger( L, 4 ); + + vlc_timer_schedule( (*pp_timer)->timer, b_relative, i_value, i_interval ); + return 0; +} + +static int vlclua_timer_getoverrun( lua_State *L ) +{ + vlclua_timer_t **pp_timer = (vlclua_timer_t**)luaL_checkudata(L, 1, "timer" ); + if( !pp_timer || !*pp_timer ) + luaL_error( L, "Can't get pointer to timer" ); + + lua_pushinteger( L, vlc_timer_getoverrun( (*pp_timer)->timer ) ); + return 1; +} + +static void vlclua_timer_callback( void *data ) +{ + vlclua_timer_t *p_timer = (vlclua_timer_t*)data; + lua_State *L = p_timer->L; + + lua_getglobal( L, p_timer->psz_callback ); + if( lua_pcall( L, 0, 0, 0 ) ) + { + const char *psz_err = lua_tostring( L, -1 ); + msg_Err( vlclua_get_this( L ), "Error while running the timer callback: '%s'", psz_err ); + lua_settop( L, 0 ); + } +} + +static int vlclua_timer_delete( lua_State *L ) +{ + vlclua_timer_t **pp_timer = (vlclua_timer_t**)luaL_checkudata( L, 1, "timer" ); + if( !pp_timer || !*pp_timer ) + luaL_error( L, "Can't get pointer to timer" ); + + vlc_timer_destroy( (*pp_timer)->timer ); + free( (*pp_timer)->psz_callback ); + return 0; +} + +static int vlclua_timer_create( lua_State *L ) +{ + vlclua_timer_t *p_timer = malloc( sizeof( vlclua_timer_t ) ); + if( !lua_isstring( L, 1 ) ) + return luaL_error( L, "timer(function_name)" ); + + if( vlc_timer_create( &p_timer->timer, vlclua_timer_callback, p_timer ) ) + return luaL_error( L, "Cannot initialize the timer" ); + + p_timer->L = L; + p_timer->psz_callback = strdup( luaL_checkstring( L, 1 ) ); + + vlclua_timer_t **pp_timer = lua_newuserdata( L, sizeof( vlclua_timer_t* ) ); + *pp_timer = p_timer; + + /* Create the object */ + if( luaL_newmetatable( L, "timer" ) ) + { + lua_newtable( L ); + luaL_register( L, NULL, vlclua_timer_reg ); + lua_setfield( L, -2, "__index" ); + lua_pushcfunction( L, vlclua_timer_delete ); + lua_setfield( L, -2, "__gc" ); + } + lua_setmetatable( L, -2 ); + return 1; } @@ -216,6 +356,8 @@ static const luaL_Reg vlclua_misc_reg[] = { { "cachedir", vlclua_cachedir }, { "datadir_list", vlclua_datadir_list }, + { "action_id", vlclua_action_id }, + { "mdate", vlclua_mdate }, { "mwait", vlclua_mwait }, @@ -224,6 +366,8 @@ static const luaL_Reg vlclua_misc_reg[] = { { "should_die", vlclua_intf_should_die }, { "quit", vlclua_quit }, + { "timer", vlclua_timer_create }, + { NULL, NULL } };