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_command( lua_State *L )
235 vlc_object_t * p_this = vlclua_get_this( L );
238 const char *psz_name = luaL_checkstring( L, 1 );
239 const char *psz_cmd = luaL_checkstring( L, 2 );
240 const char *psz_arg = luaL_checkstring( L, 3 );
241 int ret = var_Command( p_this, psz_name, psz_cmd, psz_arg, &psz_msg );
246 lua_pushstring( L, psz_msg );
251 lua_pushliteral( L, "" );
253 return vlclua_push_ret( L, ret ) + 1;
256 static int vlclua_libvlc_command( lua_State *L )
258 vlc_object_t * p_this = vlclua_get_this( L );
261 const char *psz_cmd = luaL_checkstring( L, 1 );
262 val_arg.psz_string = (char*)luaL_optstring( L, 2, "" );
264 int i_type = var_Type( p_this->p_libvlc, psz_cmd );
265 if( ! (i_type & VLC_VAR_ISCOMMAND) )
267 return luaL_error( L, "libvlc's \"%s\" is not a command",
271 int i_ret = var_Set( p_this->p_libvlc, psz_cmd, val_arg );
274 return vlclua_push_ret( L, i_ret );
277 #undef vlclua_var_toggle_or_set
278 int vlclua_var_toggle_or_set( lua_State *L, vlc_object_t *p_obj,
279 const char *psz_name )
282 if( lua_gettop( L ) > 1 ) return vlclua_error( L );
284 if( lua_gettop( L ) == 0 )
286 b_bool = var_ToggleBool( p_obj, psz_name );
290 /* lua_gettop( L ) == 1 */
291 const char *s = luaL_checkstring( L, -1 );
294 if( s && !strcmp(s, "on") )
296 else if( s && !strcmp(s, "off") )
300 b_bool = var_GetBool( p_obj, psz_name );
304 if( b_bool != var_GetBool( p_obj, psz_name ) )
305 var_SetBool( p_obj, psz_name, b_bool );
308 lua_pushboolean( L, b_bool );
312 static inline const void *luaL_checklightuserdata( lua_State *L, int narg )
314 luaL_checktype( L, narg, LUA_TLIGHTUSERDATA ); /* can raise an error */
315 return lua_topointer( L, narg );
318 static int vlclua_trigger_callback( lua_State *L )
320 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
321 const char *psz_var = luaL_checkstring( L, 2 );
323 return vlclua_push_ret( L, var_TriggerCallback( *pp_obj, psz_var ) );
326 static int vlclua_inc_integer( lua_State *L )
328 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
329 const char *psz_var = luaL_checkstring( L, 2 );
330 int64_t i_val = var_IncInteger( *pp_obj, psz_var );
332 lua_pushinteger( L, i_val );
336 static int vlclua_dec_integer( lua_State *L )
338 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
339 const char *psz_var = luaL_checkstring( L, 2 );
340 int64_t i_val = var_DecInteger( *pp_obj, psz_var );
342 lua_pushinteger( L, i_val );
346 static int vlclua_countchoices( lua_State *L )
348 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
349 const char *psz_var = luaL_checkstring( L, 2 );
350 int i_count = var_CountChoices( *pp_obj, psz_var );
352 lua_pushinteger( L, i_count );
356 static int vlclua_togglebool( lua_State *L )
358 vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
359 const char *psz_var = luaL_checkstring( L, 2 );
360 bool b_val = var_ToggleBool( *pp_obj, psz_var );
362 lua_pushboolean( L, b_val );
366 /*****************************************************************************
368 *****************************************************************************/
369 static const luaL_Reg vlclua_var_reg[] = {
370 { "inherit", vlclua_var_inherit },
371 { "get", vlclua_var_get },
372 { "get_list", vlclua_var_get_list },
373 { "set", vlclua_var_set },
374 { "create", vlclua_var_create },
375 { "trigger_callback", vlclua_trigger_callback },
376 { "command", vlclua_command },
377 { "libvlc_command", vlclua_libvlc_command },
378 { "inc_integer", vlclua_inc_integer },
379 { "dec_integer", vlclua_dec_integer },
380 { "count_choices", vlclua_countchoices },
381 { "toggle_bool", vlclua_togglebool },
385 void luaopen_variables( lua_State *L )
388 luaL_register( L, NULL, vlclua_var_reg );
389 lua_setfield( L, -2, "var" );