1 /*****************************************************************************
2 * sd.c: Services discovery related functions
3 *****************************************************************************
4 * Copyright (C) 2007-2008 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea at videolan tod org>
8 * Fabio Ritrovato <sephiroth87 at videolan dot org>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
36 #include <vlc_common.h>
37 #include <vlc_services_discovery.h>
38 #include <vlc_playlist.h>
39 #include <vlc_charset.h>
41 #include <lua.h> /* Low level lua C API */
42 #include <lauxlib.h> /* Higher level C API */
43 #include <lualib.h> /* Lua libs */
49 /*****************************************************************************
51 *****************************************************************************/
52 static int vlclua_node_add_subitem( lua_State * );
53 static int vlclua_node_add_node( lua_State * );
55 static const luaL_Reg vlclua_node_reg[] = {
56 { "add_subitem", vlclua_node_add_subitem },
57 { "add_node", vlclua_node_add_node },
61 static int vlclua_sd_get_services_names( lua_State *L )
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 );
69 char **ppsz_longname = ppsz_longnames;
70 char **ppsz_name = ppsz_names;
73 for( ; *ppsz_name; ppsz_name++,ppsz_longname++ )
75 lua_pushstring( L, *ppsz_longname );
76 lua_setfield( L, -2, *ppsz_name );
78 free( *ppsz_longname );
81 free( ppsz_longnames );
85 static int vlclua_sd_add( lua_State *L )
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 );
93 static int vlclua_sd_remove( lua_State *L )
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 );
101 static int vlclua_sd_is_loaded( lua_State *L )
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 ));
109 static int vlclua_sd_add_node( lua_State *L )
111 services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
112 if( lua_istable( L, -1 ) )
114 lua_getfield( L, -1, "title" );
115 if( lua_isstring( L, -1 ) )
117 char *name = strdup( lua_tostring( L, -1 ) );
119 input_item_t *p_input = input_item_NewWithType( VLC_OBJECT( p_sd ),
122 -1, ITEM_TYPE_NODE );
125 lua_getfield( L, -1, "arturl" );
126 if( lua_isstring( L, -1 ) && strcmp( lua_tostring( L, -1 ), "" ) )
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 );
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 * ) );
139 if( luaL_newmetatable( L, "node" ) )
142 luaL_register( L, NULL, vlclua_node_reg );
143 lua_setfield( L, -2, "__index" );
145 lua_setmetatable( L, -2 );
150 msg_Err( p_sd, "vlc.sd.add_node: the \"title\" parameter can't be empty" );
153 msg_Err( p_sd, "Error parsing add_node arguments" );
157 static int vlclua_sd_add_item( lua_State *L )
159 services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
160 if( lua_istable( L, -1 ) )
162 lua_getfield( L, -1, "path" );
163 if( lua_isstring( L, -1 ) )
165 char **ppsz_options = NULL;
167 char *psz_path = strdup( lua_tostring( 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,
172 (const char **)ppsz_options,
173 VLC_INPUT_OPTION_TRUSTED, -1 );
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)." );
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 * ) );
190 if( luaL_newmetatable( L, "input_item_t" ) )
192 lua_pushliteral( L, "none of your business" );
193 lua_setfield( L, -2, "__metatable" );
195 lua_setmetatable( L, -2 );
196 vlc_gc_decref( p_input );
199 while( i_options > 0 )
200 free( ppsz_options[--i_options] );
201 free( ppsz_options );
204 msg_Err( p_sd, "vlc.sd.add_item: the \"path\" parameter can't be empty" );
207 msg_Err( p_sd, "Error parsing add_item arguments" );
211 static int vlclua_sd_remove_item( lua_State *L )
213 services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
214 if( !lua_isnil( L, 1 ) )
216 input_item_t **pp_input = luaL_checkudata( L, 1, "input_item_t" );
218 services_discovery_RemoveItem( p_sd, *pp_input );
219 /* Make sure we won't try to remove it again */
225 static int vlclua_node_add_subitem( lua_State *L )
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" );
231 if( lua_istable( L, -1 ) )
233 lua_getfield( L, -1, "path" );
234 if( lua_isstring( L, -1 ) )
236 char **ppsz_options = NULL;
238 char *psz_path = strdup( lua_tostring( 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,
244 (const char **)ppsz_options,
245 VLC_INPUT_OPTION_TRUSTED, -1 );
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)." );
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 * ) );
262 if( luaL_newmetatable( L, "input_item_t" ) )
264 lua_pushliteral( L, "none of your business" );
265 lua_setfield( L, -2, "__metatable" );
267 lua_setmetatable( L, -2 );
268 vlc_gc_decref( p_input );
271 while( i_options > 0 )
272 free( ppsz_options[--i_options] );
273 free( ppsz_options );
276 msg_Err( p_sd, "node:add_subitem: the \"path\" parameter can't be empty" );
279 msg_Err( p_sd, "Error parsing add_subitem arguments" );
284 static int vlclua_node_add_node( lua_State *L )
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" );
290 if( lua_istable( L, -1 ) )
292 lua_getfield( L, -1, "title" );
293 if( lua_isstring( L, -1 ) )
295 char *name = strdup( lua_tostring( 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 ),
301 -1, ITEM_TYPE_NODE );
304 lua_getfield( L, -1, "arturl" );
305 if( lua_isstring( L, -1 ) && strcmp( lua_tostring( L, -1 ), "" ) )
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 );
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 * ) );
318 if( luaL_newmetatable( L, "node" ) )
321 luaL_register( L, NULL, vlclua_node_reg );
322 lua_setfield( L, -2, "__index" );
324 lua_setmetatable( L, -2 );
329 msg_Err( p_sd, "node:add_node: the \"title\" parameter can't be empty" );
332 msg_Err( p_sd, "Error parsing add_node arguments" );
337 /*****************************************************************************
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 },
351 void luaopen_sd( lua_State *L )
354 luaL_register( L, NULL, vlclua_sd_reg );
355 lua_setfield( L, -2, "sd" );