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->i_type, p_list->p_values[i], true ) )
90 lua_settable( L, -3 );
95 static int vlclua_tovalue( lua_State *L, int i_type, vlc_value_t *val )
97 switch( i_type & VLC_VAR_CLASS )
102 val->b_bool = luaL_checkboolean( L, -1 );
104 case VLC_VAR_INTEGER:
105 val->i_int = luaL_checkint( L, -1 );
108 val->psz_string = (char*)luaL_checkstring( L, -1 ); /* XXX: Beware, this only stays valid as long as (L,-1) stays in the stack */
111 val->f_float = luaL_checknumber( L, -1 );
115 double f = luaL_checknumber( L, -1 );
116 val->i_time = (int64_t)(f*1000000.);
119 case VLC_VAR_ADDRESS:
128 static int vlclua_var_inherit( lua_State *L )
132 if( lua_type( L, 1 ) == LUA_TNIL )
133 p_obj = vlclua_get_this( L );
136 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
139 const char *psz_var = luaL_checkstring( L, 2 );
141 int i_type = config_GetType( p_obj, psz_var );
142 if( var_Inherit( p_obj, psz_var, i_type, &val ) != VLC_SUCCESS )
146 return vlclua_pushvalue( L, i_type, val, true );
149 static int vlclua_var_get( lua_State *L )
152 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
153 const char *psz_var = luaL_checkstring( L, 2 );
155 int i_type = var_Type( *pp_obj, psz_var );
156 if( var_Get( *pp_obj, psz_var, &val ) != VLC_SUCCESS )
160 return vlclua_pushvalue( L, i_type, val, true );
163 static int vlclua_var_set( lua_State *L )
166 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
167 const char *psz_var = luaL_checkstring( L, 2 );
169 int i_type = var_Type( *pp_obj, psz_var );
170 vlclua_tovalue( L, i_type, &val );
172 int i_ret = var_Set( *pp_obj, psz_var, val );
175 return vlclua_push_ret( L, i_ret );
178 static int vlclua_var_create( lua_State *L )
181 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
182 const char *psz_var = luaL_checkstring( L, 2 );
184 switch( lua_type( L, 3 ) )
187 i_type = VLC_VAR_FLOAT;
190 i_type = VLC_VAR_BOOL;
193 i_type = VLC_VAR_STRING;
196 i_type = VLC_VAR_VOID;
202 if( ( i_ret = var_Create( *pp_obj, psz_var, i_type ) ) != VLC_SUCCESS )
203 return vlclua_push_ret( L, i_ret );
205 // Special case for void variables
206 if( i_type == VLC_VAR_VOID )
210 vlclua_tovalue( L, i_type, &val );
211 return vlclua_push_ret( L, var_Set( *pp_obj, psz_var, val ) );
214 static int vlclua_var_get_list( lua_State *L )
218 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
219 const char *psz_var = luaL_checkstring( L, 2 );
221 int i_ret = var_Change( *pp_obj, psz_var, VLC_VAR_GETCHOICES, &val, &text );
223 return vlclua_push_ret( L, i_ret );
225 vlclua_pushlist( L, val.p_list );
226 vlclua_pushlist( L, text.p_list );
228 var_FreeList( &val, &text );
232 static int vlclua_libvlc_command( lua_State *L )
234 vlc_object_t * p_this = vlclua_get_this( L );
237 const char *psz_cmd = luaL_checkstring( L, 1 );
238 val_arg.psz_string = (char*)luaL_optstring( L, 2, "" );
240 int i_type = var_Type( p_this->p_libvlc, psz_cmd );
241 if( ! (i_type & VLC_VAR_ISCOMMAND) )
243 return luaL_error( L, "libvlc's \"%s\" is not a command",
247 int i_ret = var_Set( p_this->p_libvlc, psz_cmd, val_arg );
250 return vlclua_push_ret( L, i_ret );
253 #undef vlclua_var_toggle_or_set
254 int vlclua_var_toggle_or_set( lua_State *L, vlc_object_t *p_obj,
255 const char *psz_name )
258 if( lua_gettop( L ) > 1 ) return vlclua_error( L );
260 if( lua_gettop( L ) == 0 )
262 b_bool = var_ToggleBool( p_obj, psz_name );
266 /* lua_gettop( L ) == 1 */
267 const char *s = luaL_checkstring( L, -1 );
270 if( s && !strcmp(s, "on") )
272 else if( s && !strcmp(s, "off") )
276 b_bool = var_GetBool( p_obj, psz_name );
280 if( b_bool != var_GetBool( p_obj, psz_name ) )
281 var_SetBool( p_obj, psz_name, b_bool );
284 lua_pushboolean( L, b_bool );
288 static inline const void *luaL_checklightuserdata( lua_State *L, int narg )
290 luaL_checktype( L, narg, LUA_TLIGHTUSERDATA ); /* can raise an error */
291 return lua_topointer( L, narg );
294 static int vlclua_trigger_callback( lua_State *L )
296 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
297 const char *psz_var = luaL_checkstring( L, 2 );
299 return vlclua_push_ret( L, var_TriggerCallback( *pp_obj, psz_var ) );
302 static int vlclua_inc_integer( lua_State *L )
304 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
305 const char *psz_var = luaL_checkstring( L, 2 );
306 int64_t i_val = var_IncInteger( *pp_obj, psz_var );
308 lua_pushinteger( L, i_val );
312 static int vlclua_dec_integer( lua_State *L )
314 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
315 const char *psz_var = luaL_checkstring( L, 2 );
316 int64_t i_val = var_DecInteger( *pp_obj, psz_var );
318 lua_pushinteger( L, i_val );
322 static int vlclua_countchoices( lua_State *L )
324 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
325 const char *psz_var = luaL_checkstring( L, 2 );
326 int i_count = var_CountChoices( *pp_obj, psz_var );
328 lua_pushinteger( L, i_count );
332 static int vlclua_togglebool( lua_State *L )
334 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
335 const char *psz_var = luaL_checkstring( L, 2 );
336 bool b_val = var_ToggleBool( *pp_obj, psz_var );
338 lua_pushboolean( L, b_val );
342 /*****************************************************************************
344 *****************************************************************************/
345 static const luaL_Reg vlclua_var_reg[] = {
346 { "inherit", vlclua_var_inherit },
347 { "get", vlclua_var_get },
348 { "get_list", vlclua_var_get_list },
349 { "set", vlclua_var_set },
350 { "create", vlclua_var_create },
351 { "trigger_callback", vlclua_trigger_callback },
352 { "libvlc_command", vlclua_libvlc_command },
353 { "inc_integer", vlclua_inc_integer },
354 { "dec_integer", vlclua_dec_integer },
355 { "count_choices", vlclua_countchoices },
356 { "toggle_bool", vlclua_togglebool },
360 void luaopen_variables( lua_State *L )
363 luaL_register( L, NULL, vlclua_var_reg );
364 lua_setfield( L, -2, "var" );