1 /*****************************************************************************
2 * variables.c: Generic lua<->vlc variables interface
3 *****************************************************************************
4 * Copyright (C) 2007-2010 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea at videolan tod org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
35 #include <vlc_common.h>
39 #include "variables.h"
42 /*****************************************************************************
44 *****************************************************************************/
45 static int vlclua_pushvalue( lua_State *L, int i_type, vlc_value_t val, bool b_error_void )
47 switch( i_type & VLC_VAR_CLASS )
56 lua_pushboolean( L, val.b_bool );
59 lua_pushinteger( L, val.i_int );
62 lua_pushstring( L, val.psz_string );
65 lua_pushnumber( L, val.f_float );
68 /* FIXME? (we're losing some precision, but does it really matter?) */
69 lua_pushnumber( L, ((double)val.i_time)/1000000. );
80 static int vlclua_pushlist( lua_State *L, vlc_list_t *p_list )
82 int i_count = p_list->i_count;
84 lua_createtable( L, i_count, 0 );
85 for( int i = 0; i < i_count; i++ )
87 lua_pushinteger( L, i+1 );
88 if( !vlclua_pushvalue( L, p_list->pi_types[i],
89 p_list->p_values[i], true ) )
91 lua_settable( L, -3 );
96 static int vlclua_tovalue( lua_State *L, int i_type, vlc_value_t *val )
98 switch( i_type & VLC_VAR_CLASS )
103 val->b_bool = luaL_checkboolean( L, -1 );
105 case VLC_VAR_INTEGER:
106 val->i_int = luaL_checkint( L, -1 );
109 val->psz_string = (char*)luaL_checkstring( L, -1 ); /* XXX: Beware, this only stays valid as long as (L,-1) stays in the stack */
112 val->f_float = luaL_checknumber( L, -1 );
116 double f = luaL_checknumber( L, -1 );
117 val->i_time = (int64_t)(f*1000000.);
120 case VLC_VAR_ADDRESS:
129 static int vlclua_var_inherit( lua_State *L )
133 if( lua_type( L, 1 ) == LUA_TNIL )
134 p_obj = vlclua_get_this( L );
137 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
140 const char *psz_var = luaL_checkstring( L, 2 );
142 int i_type = config_GetType( p_obj, psz_var );
143 if( var_Inherit( p_obj, psz_var, i_type, &val ) != VLC_SUCCESS )
147 return vlclua_pushvalue( L, i_type, val, true );
150 static int vlclua_var_get( lua_State *L )
153 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
154 const char *psz_var = luaL_checkstring( L, 2 );
156 int i_type = var_Type( *pp_obj, psz_var );
157 if( var_Get( *pp_obj, psz_var, &val ) != VLC_SUCCESS )
161 return vlclua_pushvalue( L, i_type, val, true );
164 static int vlclua_var_set( lua_State *L )
167 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
168 const char *psz_var = luaL_checkstring( L, 2 );
170 int i_type = var_Type( *pp_obj, psz_var );
171 vlclua_tovalue( L, i_type, &val );
173 int i_ret = var_Set( *pp_obj, psz_var, val );
176 return vlclua_push_ret( L, i_ret );
179 static int vlclua_var_create( lua_State *L )
182 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
183 const char *psz_var = luaL_checkstring( L, 2 );
185 switch( lua_type( L, 3 ) )
188 i_type = VLC_VAR_FLOAT;
191 i_type = VLC_VAR_BOOL;
194 i_type = VLC_VAR_STRING;
197 i_type = VLC_VAR_VOID;
203 if( ( i_ret = var_Create( *pp_obj, psz_var, i_type ) ) != VLC_SUCCESS )
204 return vlclua_push_ret( L, i_ret );
206 // Special case for void variables
207 if( i_type == VLC_VAR_VOID )
211 vlclua_tovalue( L, i_type, &val );
212 return vlclua_push_ret( L, var_Set( *pp_obj, psz_var, val ) );
215 static int vlclua_var_get_list( lua_State *L )
219 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
220 const char *psz_var = luaL_checkstring( L, 2 );
222 int i_ret = var_Change( *pp_obj, psz_var, VLC_VAR_GETLIST, &val, &text );
224 return vlclua_push_ret( L, i_ret );
226 vlclua_pushlist( L, val.p_list );
227 vlclua_pushlist( L, text.p_list );
229 var_FreeList( &val, &text );
233 static int vlclua_libvlc_command( lua_State *L )
235 vlc_object_t * p_this = vlclua_get_this( L );
238 const char *psz_cmd = luaL_checkstring( L, 1 );
239 val_arg.psz_string = (char*)luaL_optstring( L, 2, "" );
241 int i_type = var_Type( p_this->p_libvlc, psz_cmd );
242 if( ! (i_type & VLC_VAR_ISCOMMAND) )
244 return luaL_error( L, "libvlc's \"%s\" is not a command",
248 int i_ret = var_Set( p_this->p_libvlc, psz_cmd, val_arg );
251 return vlclua_push_ret( L, i_ret );
254 #undef vlclua_var_toggle_or_set
255 int vlclua_var_toggle_or_set( lua_State *L, vlc_object_t *p_obj,
256 const char *psz_name )
259 if( lua_gettop( L ) > 1 ) return vlclua_error( L );
261 if( lua_gettop( L ) == 0 )
263 b_bool = var_ToggleBool( p_obj, psz_name );
267 /* lua_gettop( L ) == 1 */
268 const char *s = luaL_checkstring( L, -1 );
271 if( s && !strcmp(s, "on") )
273 else if( s && !strcmp(s, "off") )
277 b_bool = var_GetBool( p_obj, psz_name );
281 if( b_bool != var_GetBool( p_obj, psz_name ) )
282 var_SetBool( p_obj, psz_name, b_bool );
285 lua_pushboolean( L, b_bool );
289 static inline const void *luaL_checklightuserdata( lua_State *L, int narg )
291 luaL_checktype( L, narg, LUA_TLIGHTUSERDATA ); /* can raise an error */
292 return lua_topointer( L, narg );
295 static int vlclua_trigger_callback( lua_State *L )
297 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
298 const char *psz_var = luaL_checkstring( L, 2 );
300 return vlclua_push_ret( L, var_TriggerCallback( *pp_obj, psz_var ) );
303 static int vlclua_inc_integer( lua_State *L )
305 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
306 const char *psz_var = luaL_checkstring( L, 2 );
307 int64_t i_val = var_IncInteger( *pp_obj, psz_var );
309 lua_pushinteger( L, i_val );
313 static int vlclua_dec_integer( lua_State *L )
315 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
316 const char *psz_var = luaL_checkstring( L, 2 );
317 int64_t i_val = var_DecInteger( *pp_obj, psz_var );
319 lua_pushinteger( L, i_val );
323 static int vlclua_countchoices( lua_State *L )
325 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
326 const char *psz_var = luaL_checkstring( L, 2 );
327 int i_count = var_CountChoices( *pp_obj, psz_var );
329 lua_pushinteger( L, i_count );
333 static int vlclua_togglebool( lua_State *L )
335 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
336 const char *psz_var = luaL_checkstring( L, 2 );
337 bool b_val = var_ToggleBool( *pp_obj, psz_var );
339 lua_pushboolean( L, b_val );
343 /*****************************************************************************
345 *****************************************************************************/
346 static const luaL_Reg vlclua_var_reg[] = {
347 { "inherit", vlclua_var_inherit },
348 { "get", vlclua_var_get },
349 { "get_list", vlclua_var_get_list },
350 { "set", vlclua_var_set },
351 { "create", vlclua_var_create },
352 { "trigger_callback", vlclua_trigger_callback },
353 { "libvlc_command", vlclua_libvlc_command },
354 { "inc_integer", vlclua_inc_integer },
355 { "dec_integer", vlclua_dec_integer },
356 { "count_choices", vlclua_countchoices },
357 { "toggle_bool", vlclua_togglebool },
361 void luaopen_variables( lua_State *L )
364 luaL_register( L, NULL, vlclua_var_reg );
365 lua_setfield( L, -2, "var" );