]> git.sesse.net Git - vlc/blobdiff - modules/misc/lua/libs/misc.c
lua: implement timers in vlc.misc
[vlc] / modules / misc / lua / libs / misc.c
index c496262b16517f1b3dddc876c2541184823520bb..2d7bbc92277d398a31ec226f038bd765d3a23a24 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Authors: Antoine Cellerier <dionoea at videolan tod org>
  *          Pierre d'Herbemont <pdherbemont # videolan.org>
+ *          RĂ©mi Duraffort <ivoire # videolan tod org>
  *
  * 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,7 +37,6 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_meta.h>
-#include <vlc_charset.h>
 #include <vlc_aout.h>
 #include <vlc_interface.h>
 #include <vlc_keys.h>
 /*****************************************************************************
  * 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 );
 }
 
 /*****************************************************************************
@@ -85,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;
 }
 
@@ -156,15 +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( vlclua_get_this( L ), psz_dirname, ppsz_dir_list )
+    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 );
@@ -178,8 +204,7 @@ 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 );
@@ -205,8 +230,8 @@ 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, p_intf->p_sys->exiting );
+    intf_sys_t *p_sys = vlclua_get_intf( L );
+    lua_pushboolean( L, p_sys->exiting );
     return 1;
 }
 
@@ -219,6 +244,91 @@ static int vlclua_action_id( lua_State *L )
     return 1;
 }
 
+/*****************************************************************************
+ * Timer functions
+ *****************************************************************************/
+static int vlclua_timer_schedule( lua_State *L );
+
+static const luaL_Reg vlclua_timer_reg[] = {
+    { "schedule",   vlclua_timer_schedule },
+    { 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 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 );
+        fprintf( stderr, "Error while running the timer callback: %s\n", 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;
+}
+
 /*****************************************************************************
  *
  *****************************************************************************/
@@ -244,6 +354,8 @@ static const luaL_Reg vlclua_misc_reg[] = {
     { "should_die", vlclua_intf_should_die },
     { "quit", vlclua_quit },
 
+    { "timer", vlclua_timer_create },
+
     { NULL, NULL }
 };