]> git.sesse.net Git - vlc/blob - modules/lua/libs/variables.c
lua: remove add_callback and del_callback
[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->pi_types[i],
89                                p_list->p_values[i], true ) )
90              lua_pushnil( L );
91         lua_settable( L, -3 );
92     }
93     return 1;
94 }
95
96 static int vlclua_tovalue( lua_State *L, int i_type, vlc_value_t *val )
97 {
98     switch( i_type & VLC_VAR_CLASS )
99     {
100         case VLC_VAR_VOID:
101             break;
102         case VLC_VAR_BOOL:
103             val->b_bool = luaL_checkboolean( L, -1 );
104             break;
105         case VLC_VAR_INTEGER:
106             val->i_int = luaL_checkint( L, -1 );
107             break;
108         case VLC_VAR_STRING:
109             val->psz_string = (char*)luaL_checkstring( L, -1 ); /* XXX: Beware, this only stays valid as long as (L,-1) stays in the stack */
110             break;
111         case VLC_VAR_FLOAT:
112             val->f_float = luaL_checknumber( L, -1 );
113             break;
114         case VLC_VAR_TIME:
115             {
116                 double f = luaL_checknumber( L, -1 );
117                 val->i_time = (int64_t)(f*1000000.);
118             }
119             break;
120         case VLC_VAR_ADDRESS:
121             vlclua_error( L );
122             break;
123         default:
124             vlclua_error( L );
125     }
126     return 1;
127 }
128
129 static int vlclua_var_inherit( lua_State *L )
130 {
131     vlc_value_t val;
132     vlc_object_t *p_obj;
133     if( lua_type( L, 1 ) == LUA_TNIL )
134         p_obj = vlclua_get_this( L );
135     else
136     {
137         vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
138         p_obj = *pp_obj;
139     }
140     const char *psz_var = luaL_checkstring( L, 2 );
141
142     int i_type = config_GetType( p_obj, psz_var );
143     if( var_Inherit( p_obj, psz_var, i_type, &val ) != VLC_SUCCESS )
144         return 0;
145
146     lua_pop( L, 2 );
147     return vlclua_pushvalue( L, i_type, val, true );
148 }
149
150 static int vlclua_var_get( lua_State *L )
151 {
152     vlc_value_t val;
153     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
154     const char *psz_var = luaL_checkstring( L, 2 );
155
156     int i_type = var_Type( *pp_obj, psz_var );
157     if( var_Get( *pp_obj, psz_var, &val ) != VLC_SUCCESS )
158         return 0;
159
160     lua_pop( L, 2 );
161     return vlclua_pushvalue( L, i_type, val, true );
162 }
163
164 static int vlclua_var_set( lua_State *L )
165 {
166     vlc_value_t val;
167     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
168     const char *psz_var = luaL_checkstring( L, 2 );
169
170     int i_type = var_Type( *pp_obj, psz_var );
171     vlclua_tovalue( L, i_type, &val );
172
173     int i_ret = var_Set( *pp_obj, psz_var, val );
174
175     lua_pop( L, 3 );
176     return vlclua_push_ret( L, i_ret );
177 }
178
179 static int vlclua_var_create( lua_State *L )
180 {
181     int i_type, i_ret;
182     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
183     const char *psz_var = luaL_checkstring( L, 2 );
184
185     switch( lua_type( L, 3 ) )
186     {
187         case LUA_TNUMBER:
188             i_type = VLC_VAR_FLOAT;
189             break;
190         case LUA_TBOOLEAN:
191             i_type = VLC_VAR_BOOL;
192             break;
193         case LUA_TSTRING:
194             i_type = VLC_VAR_STRING;
195             break;
196         case LUA_TNIL:
197             i_type = VLC_VAR_VOID;
198             break;
199         default:
200             return 0;
201     }
202
203     if( ( i_ret = var_Create( *pp_obj, psz_var, i_type ) ) != VLC_SUCCESS )
204         return vlclua_push_ret( L, i_ret );
205
206     // Special case for void variables
207     if( i_type == VLC_VAR_VOID )
208         return 0;
209
210     vlc_value_t val;
211     vlclua_tovalue( L, i_type, &val );
212     return vlclua_push_ret( L, var_Set( *pp_obj, psz_var, val ) );
213 }
214
215 static int vlclua_var_get_list( lua_State *L )
216 {
217     vlc_value_t val;
218     vlc_value_t text;
219     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
220     const char *psz_var = luaL_checkstring( L, 2 );
221
222     int i_ret = var_Change( *pp_obj, psz_var, VLC_VAR_GETLIST, &val, &text );
223     if( i_ret < 0 )
224         return vlclua_push_ret( L, i_ret );
225
226     vlclua_pushlist( L, val.p_list );
227     vlclua_pushlist( L, text.p_list );
228
229     var_FreeList( &val, &text );
230     return 2;
231 }
232
233 static int vlclua_command( lua_State *L )
234 {
235     vlc_object_t * p_this = vlclua_get_this( L );
236     char *psz_msg;
237
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 );
242     lua_pop( L, 3 );
243
244     if( psz_msg )
245     {
246         lua_pushstring( L, psz_msg );
247         free( psz_msg );
248     }
249     else
250     {
251         lua_pushliteral( L, "" );
252     }
253     return vlclua_push_ret( L, ret ) + 1;
254 }
255
256 static int vlclua_libvlc_command( lua_State *L )
257 {
258     vlc_object_t * p_this = vlclua_get_this( L );
259     vlc_value_t val_arg;
260
261     const char *psz_cmd = luaL_checkstring( L, 1 );
262     val_arg.psz_string = (char*)luaL_optstring( L, 2, "" );
263
264     int i_type = var_Type( p_this->p_libvlc, psz_cmd );
265     if( ! (i_type & VLC_VAR_ISCOMMAND) )
266     {
267         return luaL_error( L, "libvlc's \"%s\" is not a command",
268                            psz_cmd );
269     }
270
271     int i_ret = var_Set( p_this->p_libvlc, psz_cmd, val_arg );
272     lua_pop( L, 2 );
273
274     return vlclua_push_ret( L, i_ret );
275 }
276
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 )
280 {
281     bool b_bool;
282     if( lua_gettop( L ) > 1 ) return vlclua_error( L );
283
284     if( lua_gettop( L ) == 0 )
285     {
286         b_bool = var_ToggleBool( p_obj, psz_name );
287         goto end;
288     }
289
290     /* lua_gettop( L ) == 1 */
291     const char *s = luaL_checkstring( L, -1 );
292     lua_pop( L, 1 );
293
294     if( s && !strcmp(s, "on") )
295         b_bool = true;
296     else if( s && !strcmp(s, "off") )
297         b_bool = false;
298     else
299     {
300         b_bool = var_GetBool( p_obj, psz_name );
301         goto end;
302     }
303
304     if( b_bool != var_GetBool( p_obj, psz_name ) )
305         var_SetBool( p_obj, psz_name, b_bool );
306
307 end:
308     lua_pushboolean( L, b_bool );
309     return 1;
310 }
311
312 static inline const void *luaL_checklightuserdata( lua_State *L, int narg )
313 {
314     luaL_checktype( L, narg, LUA_TLIGHTUSERDATA ); /* can raise an error */
315     return lua_topointer( L, narg );
316 }
317
318 static int vlclua_trigger_callback( lua_State *L )
319 {
320     vlc_object_t **pp_obj = luaL_checkudata( L, 1, "vlc_object" );
321     const char *psz_var = luaL_checkstring( L, 2 );
322
323     return vlclua_push_ret( L, var_TriggerCallback( *pp_obj, psz_var ) );
324 }
325
326 static int vlclua_inc_integer( lua_State *L )
327 {
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 );
331
332     lua_pushinteger( L, i_val );
333     return 1;
334 }
335
336 static int vlclua_dec_integer( lua_State *L )
337 {
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 );
341
342     lua_pushinteger( L, i_val );
343     return 1;
344 }
345
346 static int vlclua_countchoices( lua_State *L )
347 {
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 );
351
352     lua_pushinteger( L, i_count );
353     return 1;
354 }
355
356 static int vlclua_togglebool( lua_State *L )
357 {
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 );
361
362     lua_pushboolean( L, b_val );
363     return 1;
364 }
365
366 /*****************************************************************************
367  *
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 },
382     { NULL, NULL }
383 };
384
385 void luaopen_variables( lua_State *L )
386 {
387     lua_newtable( L );
388     luaL_register( L, NULL, vlclua_var_reg );
389     lua_setfield( L, -2, "var" );
390 }