]> git.sesse.net Git - vlc/blob - modules/misc/lua/libs/sd.c
luasd: new SD related script functions
[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 <exsephiroth87 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
40 #include <lua.h>        /* Low level lua C API */
41 #include <lauxlib.h>    /* Higher level C API */
42 #include <lualib.h>     /* Lua libs */
43
44 #include "../vlc.h"
45 #include "../libs.h"
46 #include "playlist.h"
47
48 /*****************************************************************************
49  *
50  *****************************************************************************/
51 static int vlclua_node_add_subitem( lua_State * );
52 static int vlclua_node_add_node( lua_State * );
53
54 static const luaL_Reg vlclua_node_reg[] = {
55     { "add_subitem", vlclua_node_add_subitem },
56     { "add_node", vlclua_node_add_node },
57     { NULL, NULL }
58 };
59
60 static int vlclua_sd_get_services_names( lua_State *L )
61 {
62     playlist_t *p_playlist = vlclua_get_playlist_internal( L );
63     char **ppsz_longnames;
64     char **ppsz_names = vlc_sd_GetNames( p_playlist, &ppsz_longnames );
65     vlclua_release_playlist_internal( p_playlist );
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     vlclua_release_playlist_internal( p_playlist );
91     return vlclua_push_ret( L, i_ret );
92 }
93
94 static int vlclua_sd_remove( lua_State *L )
95 {
96     const char *psz_sd = luaL_checkstring( L, 1 );
97     playlist_t *p_playlist = vlclua_get_playlist_internal( L );
98     int i_ret = playlist_ServicesDiscoveryRemove( p_playlist, psz_sd );
99     vlclua_release_playlist_internal( p_playlist );
100     return vlclua_push_ret( L, i_ret );
101 }
102
103 static int vlclua_sd_is_loaded( lua_State *L )
104 {
105     const char *psz_sd = luaL_checkstring( L, 1 );
106     playlist_t *p_playlist = vlclua_get_playlist_internal( L );
107     lua_pushboolean( L, playlist_IsServicesDiscoveryLoaded( p_playlist, psz_sd ));
108     vlclua_release_playlist_internal( p_playlist );
109     return 1;
110 }
111
112 static int vlclua_sd_add_node( lua_State *L )
113 {
114     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
115     if( lua_istable( L, -1 ) )
116     {
117         lua_getfield( L, -1, "title" );
118         if( lua_isstring( L, -1 ) )
119         {
120             input_item_t *p_input = input_item_New( p_sd, "vlc://nop",
121                                                     strdup( lua_tostring( L, -1 ) ) );
122             lua_pop( L, 1 );
123             lua_getfield( L, -1, "arturl" );
124             if( lua_isstring( L, -1 ) )
125             {
126                 char *psz_value = strdup( lua_tostring( L, -1 ) );
127                 EnsureUTF8( psz_value );
128                 msg_Dbg( p_sd, "ArtURL: %s", psz_value );
129                 input_item_SetArtURL( p_input, psz_value );
130                 free( psz_value );
131             }
132             services_discovery_AddItem( p_sd, p_input, NULL );
133             input_item_t **udata = (input_item_t **)
134                                    lua_newuserdata( L, sizeof( input_item_t * ) );
135             *udata = p_input;
136             if( luaL_newmetatable( L, "node" ) )
137             {
138                 lua_newtable( L );
139                 luaL_register( L, NULL, vlclua_node_reg );
140                 lua_setfield( L, -2, "__index" );
141             }
142             lua_setmetatable( L, -2 );
143         }
144         else
145             msg_Err( p_sd, "vlc.sd.add_node: the \"title\" parameter can't be empty" );
146     }
147     else
148         msg_Err( p_sd, "Error parsing add_node arguments" );
149     return 1;
150 }
151
152 static int vlclua_sd_add_item( lua_State *L )
153 {
154     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
155     if( lua_istable( L, -1 ) )
156     {
157         lua_getfield( L, -1, "url" );
158         if( lua_isstring( L, -1 ) )
159         {
160             input_item_t *p_input = input_item_New( p_sd,
161                                                     strdup( lua_tostring( L, -1 ) ),
162                                                     strdup( lua_tostring( L, -1 ) ) );
163             lua_pop( L, 1 );
164             vlclua_read_meta_data( p_sd, L, p_input );
165             /* This one is to be tested... */
166             vlclua_read_custom_meta_data( p_sd, L, p_input );
167             lua_getfield( L, -1, "duration" );
168             if( lua_isnumber( L, -1 ) )
169                input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) );
170             else if( !lua_isnil( L, -1 ) )
171                 msg_Warn( p_sd, "Item duration should be a number (in seconds)." );
172             lua_pop( L, 1 );
173             services_discovery_AddItem( p_sd, p_input, NULL );
174             input_item_t **udata = (input_item_t **)
175                                    lua_newuserdata( L, sizeof( input_item_t * ) );
176             *udata = p_input;
177             if( luaL_newmetatable( L, "input_item_t" ) )
178             {
179                 lua_pushstring( L, "none of your business" );
180                 lua_setfield( L, -2, "__metatable" );
181             }
182             lua_setmetatable( L, -2 );
183         }
184         else
185             msg_Err( p_sd, "vlc.sd.add_item: the \"url\" parameter can't be empty" );
186     }
187     else
188         msg_Err( p_sd, "Error parsing add_item arguments" );
189     return 1;
190 }
191
192 static int vlclua_sd_remove_item( lua_State *L )
193 {
194     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
195     if( !lua_isnil( L, -1 ) )
196     {
197         input_item_t **pp_input = luaL_checkudata( L, -1, "input_item_t" );
198         if( *pp_input )
199             services_discovery_RemoveItem( p_sd, *pp_input );
200     }
201     return 1;
202 }
203
204 static int vlclua_node_add_subitem( lua_State *L )
205 {
206     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
207     input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" );
208     if( *pp_node )
209     {
210         if( lua_istable( L, -1 ) )
211         {
212             lua_getfield( L, -1, "url" );
213             if( lua_isstring( L, -1 ) )
214             {
215                 input_item_node_t *p_input_node = input_item_node_Create( *pp_node );
216                 input_item_t *p_input = input_item_New( p_sd,
217                                                         strdup( lua_tostring( L, -1 ) ),
218                                                         strdup( lua_tostring( L, -1 ) ) );
219                 lua_pop( L, 1 );
220                 vlclua_read_meta_data( p_sd, L, p_input );
221                 /* This one is to be tested... */
222                 vlclua_read_custom_meta_data( p_sd, L, p_input );
223                 lua_getfield( L, -1, "duration" );
224                 if( lua_isnumber( L, -1 ) )
225                     input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) );
226                 else if( !lua_isnil( L, -1 ) )
227                     msg_Warn( p_sd, "Item duration should be a number (in seconds)." );
228                 lua_pop( L, 1 );
229                 input_item_node_AppendItem( p_input_node, p_input );
230                 input_item_node_PostAndDelete( p_input_node );
231                 input_item_t **udata = (input_item_t **)
232                                        lua_newuserdata( L, sizeof( input_item_t * ) );
233                 *udata = p_input;
234                 if( luaL_newmetatable( L, "input_item_t" ) )
235                 {
236                     lua_pushstring( L, "none of your business" );
237                     lua_setfield( L, -2, "__metatable" );
238                 }
239                 lua_setmetatable( L, -2 );
240             }
241             else
242                 msg_Err( p_sd, "node:add_subitem: the \"url\" parameter can't be empty" );
243         }
244         else
245             msg_Err( p_sd, "Error parsing add_subitem arguments" );
246     }
247     return 1;
248 }
249
250 static int vlclua_node_add_node( lua_State *L )
251 {
252     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
253     input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" );
254     if( *pp_node )
255     {
256         if( lua_istable( L, -1 ) )
257         {
258             lua_getfield( L, -1, "title" );
259             if( lua_isstring( L, -1 ) )
260             {
261                 input_item_node_t *p_input_node = input_item_node_Create( *pp_node );
262                 input_item_t *p_input = input_item_New( p_sd,
263                                                         "vlc://nop",
264                                                         strdup( lua_tostring( L, -1 ) ) );
265                 lua_pop( L, 1 );
266                 lua_getfield( L, -1, "arturl" );
267                 if( lua_isstring( L, -1 ) )
268                 {
269                     char *psz_value = strdup( lua_tostring( L, -1 ) );
270                     EnsureUTF8( psz_value );
271                     msg_Dbg( p_sd, "ArtURL: %s", psz_value );
272                     input_item_SetArtURL( p_input, psz_value );
273                     free( psz_value );
274                 }
275                 input_item_node_AppendItem( p_input_node, p_input );
276                 input_item_node_PostAndDelete( p_input_node );
277                 input_item_t **udata = (input_item_t **)
278                                        lua_newuserdata( L, sizeof( input_item_t * ) );
279                 *udata = p_input;
280                 if( luaL_newmetatable( L, "node" ) )
281                 {
282                     lua_newtable( L );
283                     luaL_register( L, NULL, vlclua_node_reg );
284                     lua_setfield( L, -2, "__index" );
285                 }
286                 lua_setmetatable( L, -2 );
287             }
288             else
289                 msg_Err( p_sd, "node:add_node: the \"title\" parameter can't be empty" );
290         }
291         else
292             msg_Err( p_sd, "Error parsing add_node arguments" );
293     }
294     return 1;
295 }
296
297 /*****************************************************************************
298  *
299  *****************************************************************************/
300 static const luaL_Reg vlclua_sd_reg[] = {
301     { "get_services_names", vlclua_sd_get_services_names },
302     { "add", vlclua_sd_add },
303     { "remove", vlclua_sd_remove },
304     { "is_loaded", vlclua_sd_is_loaded },
305     { "add_node", vlclua_sd_add_node },
306     { "add_item", vlclua_sd_add_item },
307     { "remove_item", vlclua_sd_remove_item },
308     { NULL, NULL }
309 };
310
311 void luaopen_sd( lua_State *L )
312 {
313     lua_newtable( L );
314     luaL_register( L, NULL, vlclua_sd_reg );
315     lua_setfield( L, -2, "sd" );
316 }