]> git.sesse.net Git - vlc/blob - modules/misc/lua/libs/sd.c
lua: remove "bla ? true : false"
[vlc] / modules / misc / lua / libs / sd.c
1 /*****************************************************************************
2  * sd.c: Services discovery related functions
3  *****************************************************************************
4  * Copyright (C) 2007-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Cellerier <dionoea at videolan tod org>
8  *          Fabio Ritrovato <sephiroth87 at videolan dot org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifndef  _GNU_SOURCE
29 #   define  _GNU_SOURCE
30 #endif
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <vlc_common.h>
37 #include <vlc_services_discovery.h>
38 #include <vlc_playlist.h>
39 #include <vlc_charset.h>
40
41 #include <lua.h>        /* Low level lua C API */
42 #include <lauxlib.h>    /* Higher level C API */
43 #include <lualib.h>     /* Lua libs */
44
45 #include "../vlc.h"
46 #include "../libs.h"
47 #include "playlist.h"
48
49 /*****************************************************************************
50  *
51  *****************************************************************************/
52 static int vlclua_node_add_subitem( lua_State * );
53 static int vlclua_node_add_node( lua_State * );
54
55 static const luaL_Reg vlclua_node_reg[] = {
56     { "add_subitem", vlclua_node_add_subitem },
57     { "add_node", vlclua_node_add_node },
58     { NULL, NULL }
59 };
60
61 static int vlclua_sd_get_services_names( lua_State *L )
62 {
63     playlist_t *p_playlist = vlclua_get_playlist_internal( L );
64     char **ppsz_longnames;
65     char **ppsz_names = vlc_sd_GetNames( p_playlist, &ppsz_longnames, NULL );
66     if( !ppsz_names )
67         return 0;
68
69     char **ppsz_longname = ppsz_longnames;
70     char **ppsz_name = ppsz_names;
71     lua_settop( L, 0 );
72     lua_newtable( L );
73     for( ; *ppsz_name; ppsz_name++,ppsz_longname++ )
74     {
75         lua_pushstring( L, *ppsz_longname );
76         lua_setfield( L, -2, *ppsz_name );
77         free( *ppsz_name );
78         free( *ppsz_longname );
79     }
80     free( ppsz_names );
81     free( ppsz_longnames );
82     return 1;
83 }
84
85 static int vlclua_sd_add( lua_State *L )
86 {
87     const char *psz_sd = luaL_checkstring( L, 1 );
88     playlist_t *p_playlist = vlclua_get_playlist_internal( L );
89     int i_ret = playlist_ServicesDiscoveryAdd( p_playlist, psz_sd );
90     return vlclua_push_ret( L, i_ret );
91 }
92
93 static int vlclua_sd_remove( lua_State *L )
94 {
95     const char *psz_sd = luaL_checkstring( L, 1 );
96     playlist_t *p_playlist = vlclua_get_playlist_internal( L );
97     int i_ret = playlist_ServicesDiscoveryRemove( p_playlist, psz_sd );
98     return vlclua_push_ret( L, i_ret );
99 }
100
101 static int vlclua_sd_is_loaded( lua_State *L )
102 {
103     const char *psz_sd = luaL_checkstring( L, 1 );
104     playlist_t *p_playlist = vlclua_get_playlist_internal( L );
105     lua_pushboolean( L, playlist_IsServicesDiscoveryLoaded( p_playlist, psz_sd ));
106     return 1;
107 }
108
109 static int vlclua_sd_add_node( lua_State *L )
110 {
111     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
112     if( lua_istable( L, -1 ) )
113     {
114         lua_getfield( L, -1, "title" );
115         if( lua_isstring( L, -1 ) )
116         {
117             char *name = strdup( lua_tostring( L, -1 ) );
118             lua_pop( L, 1 );
119             input_item_t *p_input = input_item_NewWithType( VLC_OBJECT( p_sd ),
120                                                             "vlc://nop",
121                                                             name, 0, NULL, 0,
122                                                             -1, ITEM_TYPE_NODE );
123             if( p_input )
124             {
125                 lua_getfield( L, -1, "arturl" );
126                 if( lua_isstring( L, -1 ) && strcmp( lua_tostring( L, -1 ), "" ) )
127                 {
128                     char *psz_value = strdup( lua_tostring( L, -1 ) );
129                     EnsureUTF8( psz_value );
130                     msg_Dbg( p_sd, "ArtURL: %s", psz_value );
131                     /** @todo Ask for art download if not local file */
132                     input_item_SetArtURL( p_input, psz_value );
133                     free( psz_value );
134                 }
135                 services_discovery_AddItem( p_sd, p_input, NULL );
136                 input_item_t **udata = (input_item_t **)
137                                        lua_newuserdata( L, sizeof( input_item_t * ) );
138                 *udata = p_input;
139                 if( luaL_newmetatable( L, "node" ) )
140                 {
141                     lua_newtable( L );
142                     luaL_register( L, NULL, vlclua_node_reg );
143                     lua_setfield( L, -2, "__index" );
144                 }
145                 lua_setmetatable( L, -2 );
146             }
147             free( name );
148         }
149         else
150             msg_Err( p_sd, "vlc.sd.add_node: the \"title\" parameter can't be empty" );
151     }
152     else
153         msg_Err( p_sd, "Error parsing add_node arguments" );
154     return 1;
155 }
156
157 static int vlclua_sd_add_item( lua_State *L )
158 {
159     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
160     if( lua_istable( L, -1 ) )
161     {
162         lua_getfield( L, -1, "path" );
163         if( lua_isstring( L, -1 ) )
164         {
165             char **ppsz_options = NULL;
166             int i_options = 0;
167             char *psz_path = strdup( lua_tostring( L, -1 ) );
168             lua_pop( L, 1 );
169             vlclua_read_options( p_sd, L, &i_options, &ppsz_options );
170             input_item_t *p_input = input_item_NewExt( p_sd, psz_path, psz_path,
171                                                        i_options,
172                                                        (const char **)ppsz_options,
173                                                        VLC_INPUT_OPTION_TRUSTED, -1 );
174             if( p_input )
175             {
176                 vlclua_read_meta_data( p_sd, L, p_input );
177                 /* This one is to be tested... */
178                 vlclua_read_custom_meta_data( p_sd, L, p_input );
179                 /* The duration is given in seconds, convert to microseconds */
180                 lua_getfield( L, -1, "duration" );
181                 if( lua_isnumber( L, -1 ) )
182                    input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) );
183                 else if( !lua_isnil( L, -1 ) )
184                     msg_Warn( p_sd, "Item duration should be a number (in seconds)." );
185                 lua_pop( L, 1 );
186                 services_discovery_AddItem( p_sd, p_input, NULL );
187                 input_item_t **udata = (input_item_t **)
188                                        lua_newuserdata( L, sizeof( input_item_t * ) );
189                 *udata = p_input;
190                 if( luaL_newmetatable( L, "input_item_t" ) )
191                 {
192                     lua_pushliteral( L, "none of your business" );
193                     lua_setfield( L, -2, "__metatable" );
194                 }
195                 lua_setmetatable( L, -2 );
196                 vlc_gc_decref( p_input );
197             }
198             free( psz_path );
199             while( i_options > 0 )
200                 free( ppsz_options[--i_options] );
201             free( ppsz_options );
202         }
203         else
204             msg_Err( p_sd, "vlc.sd.add_item: the \"path\" parameter can't be empty" );
205     }
206     else
207         msg_Err( p_sd, "Error parsing add_item arguments" );
208     return 1;
209 }
210
211 static int vlclua_sd_remove_item( lua_State *L )
212 {
213     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
214     if( !lua_isnil( L, 1 ) )
215     {
216         input_item_t **pp_input = luaL_checkudata( L, 1, "input_item_t" );
217         if( *pp_input )
218             services_discovery_RemoveItem( p_sd, *pp_input );
219         /* Make sure we won't try to remove it again */
220         *pp_input = NULL;
221     }
222     return 1;
223 }
224
225 static int vlclua_node_add_subitem( lua_State *L )
226 {
227     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
228     input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" );
229     if( *pp_node )
230     {
231         if( lua_istable( L, -1 ) )
232         {
233             lua_getfield( L, -1, "path" );
234             if( lua_isstring( L, -1 ) )
235             {
236                 char **ppsz_options = NULL;
237                 int i_options = 0;
238                 char *psz_path = strdup( lua_tostring( L, -1 ) );
239                 lua_pop( L, 1 );
240                 vlclua_read_options( p_sd, L, &i_options, &ppsz_options );
241                 input_item_node_t *p_input_node = input_item_node_Create( *pp_node );
242                 input_item_t *p_input = input_item_NewExt( p_sd, psz_path,
243                                                            psz_path, i_options,
244                                                            (const char **)ppsz_options,
245                                                            VLC_INPUT_OPTION_TRUSTED, -1 );
246                 if( p_input )
247                 {
248                     vlclua_read_meta_data( p_sd, L, p_input );
249                     /* This one is to be tested... */
250                     vlclua_read_custom_meta_data( p_sd, L, p_input );
251                     lua_getfield( L, -1, "duration" );
252                     if( lua_isnumber( L, -1 ) )
253                         input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) );
254                     else if( !lua_isnil( L, -1 ) )
255                         msg_Warn( p_sd, "Item duration should be a number (in seconds)." );
256                     lua_pop( L, 1 );
257                     input_item_node_AppendItem( p_input_node, p_input );
258                     input_item_node_PostAndDelete( p_input_node );
259                     input_item_t **udata = (input_item_t **)
260                                            lua_newuserdata( L, sizeof( input_item_t * ) );
261                     *udata = p_input;
262                     if( luaL_newmetatable( L, "input_item_t" ) )
263                     {
264                         lua_pushliteral( L, "none of your business" );
265                         lua_setfield( L, -2, "__metatable" );
266                     }
267                     lua_setmetatable( L, -2 );
268                     vlc_gc_decref( p_input );
269                 }
270                 free( psz_path );
271                 while( i_options > 0 )
272                     free( ppsz_options[--i_options] );
273                 free( ppsz_options );
274             }
275             else
276                 msg_Err( p_sd, "node:add_subitem: the \"path\" parameter can't be empty" );
277         }
278         else
279             msg_Err( p_sd, "Error parsing add_subitem arguments" );
280     }
281     return 1;
282 }
283
284 static int vlclua_node_add_node( lua_State *L )
285 {
286     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
287     input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" );
288     if( *pp_node )
289     {
290         if( lua_istable( L, -1 ) )
291         {
292             lua_getfield( L, -1, "title" );
293             if( lua_isstring( L, -1 ) )
294             {
295                 char *name = strdup( lua_tostring( L, -1 ) );
296                 lua_pop( L, 1 );
297                 input_item_node_t *p_input_node = input_item_node_Create( *pp_node );
298                 input_item_t *p_input = input_item_NewWithType( VLC_OBJECT( p_sd ),
299                                                                 "vlc://nop",
300                                                                 name, 0, NULL, 0,
301                                                                 -1, ITEM_TYPE_NODE );
302                 if( p_input )
303                 {
304                     lua_getfield( L, -1, "arturl" );
305                     if( lua_isstring( L, -1 ) && strcmp( lua_tostring( L, -1 ), "" ) )
306                     {
307                         char *psz_value = strdup( lua_tostring( L, -1 ) );
308                         EnsureUTF8( psz_value );
309                         msg_Dbg( p_sd, "ArtURL: %s", psz_value );
310                         input_item_SetArtURL( p_input, psz_value );
311                         free( psz_value );
312                     }
313                     input_item_node_AppendItem( p_input_node, p_input );
314                     input_item_node_PostAndDelete( p_input_node );
315                     input_item_t **udata = (input_item_t **)
316                                            lua_newuserdata( L, sizeof( input_item_t * ) );
317                     *udata = p_input;
318                     if( luaL_newmetatable( L, "node" ) )
319                     {
320                         lua_newtable( L );
321                         luaL_register( L, NULL, vlclua_node_reg );
322                         lua_setfield( L, -2, "__index" );
323                     }
324                     lua_setmetatable( L, -2 );
325                 }
326                 free( name );
327             }
328             else
329                 msg_Err( p_sd, "node:add_node: the \"title\" parameter can't be empty" );
330         }
331         else
332             msg_Err( p_sd, "Error parsing add_node arguments" );
333     }
334     return 1;
335 }
336
337 /*****************************************************************************
338  *
339  *****************************************************************************/
340 static const luaL_Reg vlclua_sd_reg[] = {
341     { "get_services_names", vlclua_sd_get_services_names },
342     { "add", vlclua_sd_add },
343     { "remove", vlclua_sd_remove },
344     { "is_loaded", vlclua_sd_is_loaded },
345     { "add_node", vlclua_sd_add_node },
346     { "add_item", vlclua_sd_add_item },
347     { "remove_item", vlclua_sd_remove_item },
348     { NULL, NULL }
349 };
350
351 void luaopen_sd( lua_State *L )
352 {
353     lua_newtable( L );
354     luaL_register( L, NULL, vlclua_sd_reg );
355     lua_setfield( L, -2, "sd" );
356 }