]> git.sesse.net Git - vlc/blob - modules/lua/libs/variables.c
demux: asf: remove dead code (cid #1251046)
[vlc] / modules / lua / libs / variables.c
1 /*****************************************************************************
2  * variables.c: Generic lua<->vlc variables interface
3  *****************************************************************************
4  * Copyright (C) 2007-2010 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Cellerier <dionoea at videolan tod org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifndef  _GNU_SOURCE
28 #   define  _GNU_SOURCE
29 #endif
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <vlc_common.h>
36
37 #include "../vlc.h"
38 #include "../libs.h"
39 #include "variables.h"
40 #include "objects.h"
41
42 /*****************************************************************************
43  * Variables handling
44  *****************************************************************************/
45 static int vlclua_pushvalue( lua_State *L, int i_type, vlc_value_t val, bool b_error_void )
46 {
47     switch( i_type & VLC_VAR_CLASS )
48     {
49         case VLC_VAR_VOID:
50             if( b_error_void )
51                 vlclua_error( L );
52             else
53                 lua_pushnil( L );
54             break;
55         case VLC_VAR_BOOL:
56             lua_pushboolean( L, val.b_bool );
57             break;
58         case VLC_VAR_INTEGER:
59             lua_pushinteger( L, val.i_int );
60             break;
61         case VLC_VAR_STRING:
62             lua_pushstring( L, val.psz_string );
63             break;
64         case VLC_VAR_FLOAT:
65             lua_pushnumber( L, val.f_float );
66             break;
67         case VLC_VAR_TIME:
68             /* FIXME? (we're losing some precision, but does it really matter?) */
69             lua_pushnumber( L, ((double)val.i_time)/1000000. );
70             break;
71         case VLC_VAR_ADDRESS:
72             vlclua_error( L );
73             break;
74         default:
75             vlclua_error( L );
76     }
77     return 1;
78 }
79
80 static int vlclua_pushlist( lua_State *L, vlc_list_t *p_list )
81 {
82     int i_count = p_list->i_count;
83
84     lua_createtable( L, i_count, 0 );
85     for( int i = 0; i < i_count; i++ )
86     {
87         lua_pushinteger( L, i+1 );
88         if( !vlclua_pushvalue( L, p_list->i_type, p_list->p_values[i], true ) )
89              lua_pushnil( L );
90         lua_settable( L, -3 );
91     }
92     return 1;
93 }
94
95 static int vlclua_tovalue( lua_State *L, int i_type, vlc_value_t *val )
96 {
97     switch( i_type & VLC_VAR_CLASS )
98     {
99         case VLC_VAR_VOID:
100             break;
101         case VLC_VAR_BOOL:
102             val->b_bool = luaL_checkboolean( L, -1 );
103             break;
104         case VLC_VAR_INTEGER:
105             val->i_int = luaL_checkint( L, -1 );
106             break;
107         case VLC_VAR_STRING:
108             val->psz_string = (char*)luaL_checkstring( L, -1 ); /* XXX: Beware, this only stays valid as long as (L,-1) stays in the stack */
109             break;
110         case VLC_VAR_FLOAT:
111             val->f_float = luaL_checknumber( L, -1 );
112             break;
113         case VLC_VAR_TIME:
114             {
115                 double f = luaL_checknumber( L, -1 );
116                 val->i_time = (int64_t)(f*1000000.);
117             }
118             break;
119         case VLC_VAR_ADDRESS:
120             vlclua_error( L );
121             break;
122         default:
123             vlclua_error( L );
124     }
125     return 1;
126 }
127
128 static int vlclua_var_inherit( lua_State *L )
129 {
130     vlc_value_t val;
131     vlc_object_t *p_obj;
132     if( lua_type( L, 1 ) == LUA_TNIL )
133         p_obj = vlclua_get_this( L );
134     else
135     {
136         vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
137         p_obj = *pp_obj;
138     }
139     const char *psz_var = luaL_checkstring( L, 2 );
140
141     int i_type = config_GetType( p_obj, psz_var );
142     if( var_Inherit( p_obj, psz_var, i_type, &val ) != VLC_SUCCESS )
143         return 0;
144
145     lua_pop( L, 2 );
146     return vlclua_pushvalue( L, i_type, val, true );
147 }
148
149 static int vlclua_var_get( lua_State *L )
150 {
151     vlc_value_t val;
152     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
153     const char *psz_var = luaL_checkstring( L, 2 );
154
155     int i_type = var_Type( *pp_obj, psz_var );
156     if( var_Get( *pp_obj, psz_var, &val ) != VLC_SUCCESS )
157         return 0;
158
159     lua_pop( L, 2 );
160     return vlclua_pushvalue( L, i_type, val, true );
161 }
162
163 static int vlclua_var_set( lua_State *L )
164 {
165     vlc_value_t val;
166     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
167     const char *psz_var = luaL_checkstring( L, 2 );
168
169     int i_type = var_Type( *pp_obj, psz_var );
170     vlclua_tovalue( L, i_type, &val );
171
172     int i_ret = var_Set( *pp_obj, psz_var, val );
173
174     lua_pop( L, 3 );
175     return vlclua_push_ret( L, i_ret );
176 }
177
178 static int vlclua_var_create( lua_State *L )
179 {
180     int i_type, i_ret;
181     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
182     const char *psz_var = luaL_checkstring( L, 2 );
183
184     switch( lua_type( L, 3 ) )
185     {
186         case LUA_TNUMBER:
187             i_type = VLC_VAR_FLOAT;
188             break;
189         case LUA_TBOOLEAN:
190             i_type = VLC_VAR_BOOL;
191             break;
192         case LUA_TSTRING:
193             i_type = VLC_VAR_STRING;
194             break;
195         case LUA_TNIL:
196             i_type = VLC_VAR_VOID;
197             break;
198         default:
199             return 0;
200     }
201
202     if( ( i_ret = var_Create( *pp_obj, psz_var, i_type ) ) != VLC_SUCCESS )
203         return vlclua_push_ret( L, i_ret );
204
205     // Special case for void variables
206     if( i_type == VLC_VAR_VOID )
207         return 0;
208
209     vlc_value_t val;
210     vlclua_tovalue( L, i_type, &val );
211     return vlclua_push_ret( L, var_Set( *pp_obj, psz_var, val ) );
212 }
213
214 static int vlclua_var_get_list( lua_State *L )
215 {
216     vlc_value_t val;
217     vlc_value_t text;
218     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
219     const char *psz_var = luaL_checkstring( L, 2 );
220
221     int i_ret = var_Change( *pp_obj, psz_var, VLC_VAR_GETCHOICES, &val, &text );
222     if( i_ret < 0 )
223         return vlclua_push_ret( L, i_ret );
224
225     vlclua_pushlist( L, val.p_list );
226     vlclua_pushlist( L, text.p_list );
227
228     var_FreeList( &val, &text );
229     return 2;
230 }
231
232 static int vlclua_libvlc_command( lua_State *L )
233 {
234     vlc_object_t * p_this = vlclua_get_this( L );
235     vlc_value_t val_arg;
236
237     const char *psz_cmd = luaL_checkstring( L, 1 );
238     val_arg.psz_string = (char*)luaL_optstring( L, 2, "" );
239
240     int i_type = var_Type( p_this->p_libvlc, psz_cmd );
241     if( ! (i_type & VLC_VAR_ISCOMMAND) )
242     {
243         return luaL_error( L, "libvlc's \"%s\" is not a command",
244                            psz_cmd );
245     }
246
247     int i_ret = var_Set( p_this->p_libvlc, psz_cmd, val_arg );
248     lua_pop( L, 2 );
249
250     return vlclua_push_ret( L, i_ret );
251 }
252
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 )
256 {
257     bool b_bool;
258     if( lua_gettop( L ) > 1 ) return vlclua_error( L );
259
260     if( lua_gettop( L ) == 0 )
261     {
262         b_bool = var_ToggleBool( p_obj, psz_name );
263         goto end;
264     }
265
266     /* lua_gettop( L ) == 1 */
267     const char *s = luaL_checkstring( L, -1 );
268     lua_pop( L, 1 );
269
270     if( s && !strcmp(s, "on") )
271         b_bool = true;
272     else if( s && !strcmp(s, "off") )
273         b_bool = false;
274     else
275     {
276         b_bool = var_GetBool( p_obj, psz_name );
277         goto end;
278     }
279
280     if( b_bool != var_GetBool( p_obj, psz_name ) )
281         var_SetBool( p_obj, psz_name, b_bool );
282
283 end:
284     lua_pushboolean( L, b_bool );
285     return 1;
286 }
287
288 static inline const void *luaL_checklightuserdata( lua_State *L, int narg )
289 {
290     luaL_checktype( L, narg, LUA_TLIGHTUSERDATA ); /* can raise an error */
291     return lua_topointer( L, narg );
292 }
293
294 static int vlclua_trigger_callback( lua_State *L )
295 {
296     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
297     const char *psz_var = luaL_checkstring( L, 2 );
298
299     return vlclua_push_ret( L, var_TriggerCallback( *pp_obj, psz_var ) );
300 }
301
302 static int vlclua_inc_integer( lua_State *L )
303 {
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 );
307
308     lua_pushinteger( L, i_val );
309     return 1;
310 }
311
312 static int vlclua_dec_integer( lua_State *L )
313 {
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 );
317
318     lua_pushinteger( L, i_val );
319     return 1;
320 }
321
322 static int vlclua_countchoices( lua_State *L )
323 {
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 );
327
328     lua_pushinteger( L, i_count );
329     return 1;
330 }
331
332 static int vlclua_togglebool( lua_State *L )
333 {
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 );
337
338     lua_pushboolean( L, b_val );
339     return 1;
340 }
341
342 /*****************************************************************************
343  *
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 },
357     { NULL, NULL }
358 };
359
360 void luaopen_variables( lua_State *L )
361 {
362     lua_newtable( L );
363     luaL_register( L, NULL, vlclua_var_reg );
364     lua_setfield( L, -2, "var" );
365 }