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
);
124 lua_getfield( L
, -1, "arturl" );
125 if( lua_isstring( L
, -1 ) )
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
);
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
* ) );
138 if( luaL_newmetatable( L
, "node" ) )
141 luaL_register( L
, NULL
, vlclua_node_reg
);
142 lua_setfield( L
, -2, "__index" );
144 lua_setmetatable( L
, -2 );
147 msg_Err( p_sd
, "vlc.sd.add_node: the \"title\" parameter can't be empty" );
150 msg_Err( p_sd
, "Error parsing add_node arguments" );
154 static int vlclua_sd_add_item( lua_State
*L
)
156 services_discovery_t
*p_sd
= (services_discovery_t
*)vlclua_get_this( L
);
157 if( lua_istable( L
, -1 ) )
159 lua_getfield( L
, -1, "url" );
160 if( lua_isstring( L
, -1 ) )
162 char **ppsz_options
= NULL
;
164 char *psz_url
= strdup( lua_tostring( 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_url
, psz_url
,
169 (const char **)ppsz_options
,
170 VLC_INPUT_OPTION_TRUSTED
, -1 );
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)." );
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
* ) );
186 if( luaL_newmetatable( L
, "input_item_t" ) )
188 lua_pushstring( L
, "none of your business" );
189 lua_setfield( L
, -2, "__metatable" );
191 lua_setmetatable( L
, -2 );
194 msg_Err( p_sd
, "vlc.sd.add_item: the \"url\" parameter can't be empty" );
197 msg_Err( p_sd
, "Error parsing add_item arguments" );
201 static int vlclua_sd_remove_item( lua_State
*L
)
203 services_discovery_t
*p_sd
= (services_discovery_t
*)vlclua_get_this( L
);
204 if( !lua_isnil( L
, -1 ) )
206 input_item_t
**pp_input
= luaL_checkudata( L
, -1, "input_item_t" );
208 services_discovery_RemoveItem( p_sd
, *pp_input
);
209 /* Make sure we won't try to remove it again */
215 static int vlclua_node_add_subitem( lua_State
*L
)
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" );
221 if( lua_istable( L
, -1 ) )
223 lua_getfield( L
, -1, "url" );
224 if( lua_isstring( L
, -1 ) )
226 char **ppsz_options
= NULL
;
228 char *url
= strdup( lua_tostring( 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
, url
, url
,
234 (const char **)ppsz_options
,
235 VLC_INPUT_OPTION_TRUSTED
, -1 );
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)." );
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
* ) );
251 if( luaL_newmetatable( L
, "input_item_t" ) )
253 lua_pushstring( L
, "none of your business" );
254 lua_setfield( L
, -2, "__metatable" );
256 lua_setmetatable( L
, -2 );
259 msg_Err( p_sd
, "node:add_subitem: the \"url\" parameter can't be empty" );
262 msg_Err( p_sd
, "Error parsing add_subitem arguments" );
267 static int vlclua_node_add_node( lua_State
*L
)
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" );
273 if( lua_istable( L
, -1 ) )
275 lua_getfield( L
, -1, "title" );
276 if( lua_isstring( L
, -1 ) )
278 char *name
= strdup( lua_tostring( 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
),
284 -1, ITEM_TYPE_NODE
);
286 lua_getfield( L
, -1, "arturl" );
287 if( lua_isstring( L
, -1 ) )
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
);
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
* ) );
300 if( luaL_newmetatable( L
, "node" ) )
303 luaL_register( L
, NULL
, vlclua_node_reg
);
304 lua_setfield( L
, -2, "__index" );
306 lua_setmetatable( L
, -2 );
309 msg_Err( p_sd
, "node:add_node: the \"title\" parameter can't be empty" );
312 msg_Err( p_sd
, "Error parsing add_node arguments" );
317 /*****************************************************************************
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
},
331 void luaopen_sd( lua_State
*L
)
334 luaL_register( L
, NULL
, vlclua_sd_reg
);
335 lua_setfield( L
, -2, "sd" );