]> git.sesse.net Git - vlc/blob - modules/misc/lua/libs/sd.c
Lua SD: use "path" instead of "url"
[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             free( name );
124             lua_getfield( L, -1, "arturl" );
125             if( lua_isstring( L, -1 ) )
126             {
127                 char *psz_value = strdup( lua_tostring( L, -1 ) );
128                 EnsureUTF8( psz_value );
129                 msg_Dbg( p_sd, "ArtURL: %s", psz_value );
130                 /** @todo Ask for art download if not local file */
131                 input_item_SetArtURL( p_input, psz_value );
132                 free( psz_value );
133             }
134             services_discovery_AddItem( p_sd, p_input, NULL );
135             input_item_t **udata = (input_item_t **)
136                                    lua_newuserdata( L, sizeof( input_item_t * ) );
137             *udata = p_input;
138             if( luaL_newmetatable( L, "node" ) )
139             {
140                 lua_newtable( L );
141                 luaL_register( L, NULL, vlclua_node_reg );
142                 lua_setfield( L, -2, "__index" );
143             }
144             lua_setmetatable( L, -2 );
145         }
146         else
147             msg_Err( p_sd, "vlc.sd.add_node: the \"title\" parameter can't be empty" );
148     }
149     else
150         msg_Err( p_sd, "Error parsing add_node arguments" );
151     return 1;
152 }
153
154 static int vlclua_sd_add_item( lua_State *L )
155 {
156     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
157     if( lua_istable( L, -1 ) )
158     {
159         lua_getfield( L, -1, "path" );
160         if( lua_isstring( L, -1 ) )
161         {
162             char **ppsz_options = NULL;
163             int i_options = 0;
164             char *psz_path = strdup( lua_tostring( L, -1 ) );
165             lua_pop( L, 1 );
166             vlclua_read_options( p_sd, L, &i_options, &ppsz_options );
167             input_item_t *p_input = input_item_NewExt( p_sd, psz_path, psz_path,
168                                                        i_options,
169                                                        (const char **)ppsz_options,
170                                                        VLC_INPUT_OPTION_TRUSTED, -1 );
171             free( psz_path );
172             vlclua_read_meta_data( p_sd, L, p_input );
173             /* This one is to be tested... */
174             vlclua_read_custom_meta_data( p_sd, L, p_input );
175             /* The duration is given in seconds, convert to microseconds */
176             lua_getfield( L, -1, "duration" );
177             if( lua_isnumber( L, -1 ) )
178                input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) );
179             else if( !lua_isnil( L, -1 ) )
180                 msg_Warn( p_sd, "Item duration should be a number (in seconds)." );
181             lua_pop( L, 1 );
182             services_discovery_AddItem( p_sd, p_input, NULL );
183             input_item_t **udata = (input_item_t **)
184                                    lua_newuserdata( L, sizeof( input_item_t * ) );
185             *udata = p_input;
186             if( luaL_newmetatable( L, "input_item_t" ) )
187             {
188                 lua_pushstring( L, "none of your business" );
189                 lua_setfield( L, -2, "__metatable" );
190             }
191             lua_setmetatable( L, -2 );
192         }
193         else
194             msg_Err( p_sd, "vlc.sd.add_item: the \"path\" parameter can't be empty" );
195     }
196     else
197         msg_Err( p_sd, "Error parsing add_item arguments" );
198     return 1;
199 }
200
201 static int vlclua_sd_remove_item( lua_State *L )
202 {
203     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
204     if( !lua_isnil( L, -1 ) )
205     {
206         input_item_t **pp_input = luaL_checkudata( L, -1, "input_item_t" );
207         if( *pp_input )
208             services_discovery_RemoveItem( p_sd, *pp_input );
209         /* Make sure we won't try to remove it again */
210         *pp_input = NULL;
211     }
212     return 1;
213 }
214
215 static int vlclua_node_add_subitem( lua_State *L )
216 {
217     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
218     input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" );
219     if( *pp_node )
220     {
221         if( lua_istable( L, -1 ) )
222         {
223             lua_getfield( L, -1, "path" );
224             if( lua_isstring( L, -1 ) )
225             {
226                 char **ppsz_options = NULL;
227                 int i_options = 0;
228                 char *psz_path = strdup( lua_tostring( L, -1 ) );
229                 lua_pop( L, 1 );
230                 vlclua_read_options( p_sd, L, &i_options, &ppsz_options );
231                 input_item_node_t *p_input_node = input_item_node_Create( *pp_node );
232                 input_item_t *p_input = input_item_NewExt( p_sd, psz_path,
233                                                            psz_path, i_options,
234                                                            (const char **)ppsz_options,
235                                                            VLC_INPUT_OPTION_TRUSTED, -1 );
236                 free( psz_path );
237                 vlclua_read_meta_data( p_sd, L, p_input );
238                 /* This one is to be tested... */
239                 vlclua_read_custom_meta_data( p_sd, L, p_input );
240                 lua_getfield( L, -1, "duration" );
241                 if( lua_isnumber( L, -1 ) )
242                     input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) );
243                 else if( !lua_isnil( L, -1 ) )
244                     msg_Warn( p_sd, "Item duration should be a number (in seconds)." );
245                 lua_pop( L, 1 );
246                 input_item_node_AppendItem( p_input_node, p_input );
247                 input_item_node_PostAndDelete( p_input_node );
248                 input_item_t **udata = (input_item_t **)
249                                        lua_newuserdata( L, sizeof( input_item_t * ) );
250                 *udata = p_input;
251                 if( luaL_newmetatable( L, "input_item_t" ) )
252                 {
253                     lua_pushstring( L, "none of your business" );
254                     lua_setfield( L, -2, "__metatable" );
255                 }
256                 lua_setmetatable( L, -2 );
257             }
258             else
259                 msg_Err( p_sd, "node:add_subitem: the \"path\" parameter can't be empty" );
260         }
261         else
262             msg_Err( p_sd, "Error parsing add_subitem arguments" );
263     }
264     return 1;
265 }
266
267 static int vlclua_node_add_node( lua_State *L )
268 {
269     services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
270     input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" );
271     if( *pp_node )
272     {
273         if( lua_istable( L, -1 ) )
274         {
275             lua_getfield( L, -1, "title" );
276             if( lua_isstring( L, -1 ) )
277             {
278                 char *name = strdup( lua_tostring( L, -1 ) );
279                 lua_pop( L, 1 );
280                 input_item_node_t *p_input_node = input_item_node_Create( *pp_node );
281                 input_item_t *p_input = input_item_NewWithType( VLC_OBJECT( p_sd ),
282                                                                 "vlc://nop",
283                                                                 name, 0, NULL, 0,
284                                                                 -1, ITEM_TYPE_NODE );
285                 free( name );
286                 lua_getfield( L, -1, "arturl" );
287                 if( lua_isstring( L, -1 ) )
288                 {
289                     char *psz_value = strdup( lua_tostring( L, -1 ) );
290                     EnsureUTF8( psz_value );
291                     msg_Dbg( p_sd, "ArtURL: %s", psz_value );
292                     input_item_SetArtURL( p_input, psz_value );
293                     free( psz_value );
294                 }
295                 input_item_node_AppendItem( p_input_node, p_input );
296                 input_item_node_PostAndDelete( p_input_node );
297                 input_item_t **udata = (input_item_t **)
298                                        lua_newuserdata( L, sizeof( input_item_t * ) );
299                 *udata = p_input;
300                 if( luaL_newmetatable( L, "node" ) )
301                 {
302                     lua_newtable( L );
303                     luaL_register( L, NULL, vlclua_node_reg );
304                     lua_setfield( L, -2, "__index" );
305                 }
306                 lua_setmetatable( L, -2 );
307             }
308             else
309                 msg_Err( p_sd, "node:add_node: the \"title\" parameter can't be empty" );
310         }
311         else
312             msg_Err( p_sd, "Error parsing add_node arguments" );
313     }
314     return 1;
315 }
316
317 /*****************************************************************************
318  *
319  *****************************************************************************/
320 static const luaL_Reg vlclua_sd_reg[] = {
321     { "get_services_names", vlclua_sd_get_services_names },
322     { "add", vlclua_sd_add },
323     { "remove", vlclua_sd_remove },
324     { "is_loaded", vlclua_sd_is_loaded },
325     { "add_node", vlclua_sd_add_node },
326     { "add_item", vlclua_sd_add_item },
327     { "remove_item", vlclua_sd_remove_item },
328     { NULL, NULL }
329 };
330
331 void luaopen_sd( lua_State *L )
332 {
333     lua_newtable( L );
334     luaL_register( L, NULL, vlclua_sd_reg );
335     lua_setfield( L, -2, "sd" );
336 }