1 /*****************************************************************************
2 * luaplaylist.c : Lua playlist demux module
3 *****************************************************************************
4 * Copyright (C) 2007 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea at videolan tod org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
28 #include <vlc_demux.h>
30 #include <vlc_strings.h>
31 #include <vlc_charset.h>
33 #include <errno.h> /* ENOMEM */
34 #ifdef HAVE_SYS_STAT_H
35 # include <sys/stat.h>
41 /*****************************************************************************
43 *****************************************************************************/
44 static int Demux( demux_t *p_demux );
45 static int Control( demux_t *p_demux, int i_query, va_list args );
47 /*****************************************************************************
49 *****************************************************************************/
56 /*****************************************************************************
58 *****************************************************************************/
60 static int vlclua_demux_peek( lua_State *p_state )
62 demux_t *p_demux = (demux_t *)vlclua_get_this( p_state );
63 int i = lua_gettop( p_state );
68 n = lua_tonumber( p_state, 1 );
69 lua_pop( p_state, i );
70 i_peek = stream_Peek( p_demux->s, &p_peek, n );
71 lua_pushlstring( p_state, (const char *)p_peek, i_peek );
75 static int vlclua_demux_read( lua_State *p_state )
77 demux_t *p_demux = (demux_t *)vlclua_get_this( p_state );
78 int i = lua_gettop( p_state );
83 n = lua_tonumber( p_state, 1 );
84 lua_pop( p_state, i );
85 i_read = stream_Read( p_demux->s, &p_read, n );
86 lua_pushlstring( p_state, (const char *)p_read, i_read );
90 static int vlclua_demux_readline( lua_State *p_state )
92 demux_t *p_demux = (demux_t *)vlclua_get_this( p_state );
93 char *psz_line = stream_ReadLine( p_demux->s );
96 lua_pushstring( p_state, psz_line );
101 lua_pushnil( p_state );
107 /* Functions to register */
108 static luaL_Reg p_reg[] =
110 { "peek", vlclua_demux_peek },
111 { "decode_uri", vlclua_decode_uri },
112 { "resolve_xml_special_chars", vlclua_resolve_xml_special_chars },
113 { "msg_dbg", vlclua_msg_dbg },
114 { "msg_warn", vlclua_msg_warn },
115 { "msg_err", vlclua_msg_err },
116 { "msg_info", vlclua_msg_info },
120 /* Functions to register for parse() function call only */
121 static luaL_Reg p_reg_parse[] =
123 { "read", vlclua_demux_read },
124 { "readline", vlclua_demux_readline },
128 /*****************************************************************************
129 * Called through lua_scripts_batch_execute to call 'probe' on
130 * the script pointed by psz_filename.
131 *****************************************************************************/
132 static int probe_luascript( vlc_object_t *p_this, const char * psz_filename,
133 lua_State * p_state, void * user_data )
135 demux_t * p_demux = (demux_t *)p_this;
137 p_demux->p_sys->psz_filename = strdup(psz_filename);
139 /* Ugly hack to delete previous versions of the probe() and parse()
141 lua_pushnil( p_state );
142 lua_pushnil( p_state );
143 lua_setglobal( p_state, "probe" );
144 lua_setglobal( p_state, "parse" );
146 /* Load and run the script(s) */
147 if( luaL_dofile( p_state, psz_filename ) )
149 msg_Warn( p_demux, "Error loading script %s: %s", psz_filename,
150 lua_tostring( p_state, lua_gettop( p_state ) ) );
151 lua_pop( p_state, 1 );
155 lua_getglobal( p_state, "probe" );
157 if( !lua_isfunction( p_state, lua_gettop( p_state ) ) )
159 msg_Warn( p_demux, "Error while runing script %s, "
160 "function probe() not found", psz_filename );
161 lua_pop( p_state, 1 );
165 if( lua_pcall( p_state, 0, 1, 0 ) )
167 msg_Warn( p_demux, "Error while runing script %s, "
168 "function probe(): %s", psz_filename,
169 lua_tostring( p_state, lua_gettop( p_state ) ) );
170 lua_pop( p_state, 1 );
174 if( lua_gettop( p_state ) )
176 int i_ret = VLC_EGENERIC;
177 if( lua_toboolean( p_state, 1 ) )
179 msg_Dbg( p_demux, "Lua playlist script %s's "
180 "probe() function was successful", psz_filename );
183 lua_pop( p_state, 1 );
190 /*****************************************************************************
191 * Import_LuaPlaylist: main import function
192 *****************************************************************************/
193 int E_(Import_LuaPlaylist)( vlc_object_t *p_this )
195 demux_t *p_demux = (demux_t *)p_this;
198 p_demux->p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) );
199 if( !p_demux->p_sys )
204 p_demux->p_sys->psz_filename = NULL;
206 p_demux->pf_control = Control;
207 p_demux->pf_demux = Demux;
209 /* Initialise Lua state structure */
210 p_state = luaL_newstate();
213 msg_Err( p_demux, "Could not create new Lua State" );
214 free( p_demux->p_sys );
217 p_demux->p_sys->p_state = p_state;
219 /* Load Lua libraries */
220 luaL_openlibs( p_state ); /* FIXME: Don't open all the libs? */
222 luaL_register( p_state, "vlc", p_reg );
223 lua_pushlightuserdata( p_state, p_demux );
224 lua_setfield( p_state, lua_gettop( p_state ) - 1, "private" );
225 lua_pushstring( p_state, p_demux->psz_path );
226 lua_setfield( p_state, lua_gettop( p_state ) - 1, "path" );
227 lua_pushstring( p_state, p_demux->psz_access );
228 lua_setfield( p_state, lua_gettop( p_state ) - 1, "access" );
230 lua_pop( p_state, 1 );
232 return vlclua_scripts_batch_execute( p_this, "luaplaylist", &probe_luascript,
238 /*****************************************************************************
239 * Deactivate: frees unused data
240 *****************************************************************************/
241 void E_(Close_LuaPlaylist)( vlc_object_t *p_this )
243 demux_t *p_demux = (demux_t *)p_this;
244 lua_close( p_demux->p_sys->p_state );
245 free( p_demux->p_sys->psz_filename );
246 free( p_demux->p_sys );
249 static inline void read_options( demux_t *p_demux, lua_State *p_state,
250 int o, int t, int *pi_options,
251 char ***pppsz_options )
253 lua_getfield( p_state, o, "options" );
254 if( lua_istable( p_state, t ) )
256 lua_pushnil( p_state );
257 while( lua_next( p_state, t ) )
259 if( lua_isstring( p_state, t+2 ) )
261 char *psz_option = strdup( lua_tostring( p_state, t+2 ) );
262 msg_Dbg( p_demux, "Option: %s", psz_option );
263 INSERT_ELEM( *pppsz_options, *pi_options, *pi_options,
268 msg_Warn( p_demux, "Option should be a string" );
270 lua_pop( p_state, 1 ); /* pop option */
273 lua_pop( p_state, 1 ); /* pop "options" */
277 static int Demux( demux_t *p_demux )
279 input_item_t *p_input;
280 lua_State *p_state = p_demux->p_sys->p_state;
281 char *psz_filename = p_demux->p_sys->psz_filename;
284 playlist_t *p_playlist = pl_Yield( p_demux );
285 input_thread_t *p_input_thread = (input_thread_t *)vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
286 input_item_t *p_current_input = input_GetItem( p_input_thread );
288 luaL_register( p_state, "vlc", p_reg_parse );
290 lua_getglobal( p_state, "parse" );
292 if( !lua_isfunction( p_state, lua_gettop( p_state ) ) )
294 msg_Warn( p_demux, "Error while runing script %s, "
295 "function parse() not found", psz_filename );
296 E_(Close_LuaPlaylist)( VLC_OBJECT( p_demux ) );
300 if( lua_pcall( p_state, 0, 1, 0 ) )
302 msg_Warn( p_demux, "Error while runing script %s, "
303 "function parse(): %s", psz_filename,
304 lua_tostring( p_state, lua_gettop( p_state ) ) );
305 E_(Close_LuaPlaylist)( VLC_OBJECT( p_demux ) );
309 /* Check that the Lua stack is big enough and grow it if needed.
310 * Should be ok since LUA_MINSTACK is 20 but we never know. */
311 lua_checkstack( p_state, 8 );
313 if( ( t = lua_gettop( p_state ) ) )
316 if( lua_istable( p_state, t ) )
318 lua_pushnil( p_state );
319 while( lua_next( p_state, t ) )
321 if( lua_istable( p_state, t+2 ) )
323 lua_getfield( p_state, t+2, "path" );
324 if( lua_isstring( p_state, t+3 ) )
326 const char *psz_path = NULL;
327 const char *psz_name = NULL;
328 char **ppsz_options = NULL;
330 mtime_t i_duration = -1;
332 /* Read path and name */
333 psz_path = lua_tostring( p_state, t+3 );
334 msg_Dbg( p_demux, "Path: %s", psz_path );
335 lua_getfield( p_state, t+2, "name" );
336 if( lua_isstring( p_state, t+4 ) )
338 psz_name = lua_tostring( p_state, t+4 );
339 msg_Dbg( p_demux, "Name: %s", psz_name );
347 lua_getfield( p_state, t+2, "duration" );
348 if( lua_isnumber( p_state, t+5 ) )
350 i_duration = (mtime_t)lua_tointeger( p_state, t+5 );
351 i_duration *= 1000000;
353 lua_pop( p_state, 1 ); /* pop "duration" */
356 read_options( p_demux, p_state, t+2, t+5,
357 &i_options, &ppsz_options );
359 /* Create input item */
360 p_input = input_ItemNewExt( p_playlist, psz_path,
362 (const char **)ppsz_options,
364 lua_pop( p_state, 1 ); /* pop "name" */
367 vlclua_read_meta_data( VLC_OBJECT(p_demux), p_state, t+2, t+4, p_input );
369 /* Read custom meta data */
370 vlclua_read_custom_meta_data( VLC_OBJECT(p_demux), p_state, t+2, t+4,
373 /* Append item to playlist */
374 input_ItemAddSubItem( p_current_input, p_input );
376 while( i_options > 0 )
377 free( ppsz_options[--i_options] );
378 free( ppsz_options );
383 "Playlist item's path should be a string" );
385 lua_pop( p_state, 1 ); /* pop "path" */
389 msg_Warn( p_demux, "Playlist item should be a table" );
391 lua_pop( p_state, 1 ); /* pop the value, keep the key for
392 * the next lua_next() call */
397 msg_Warn( p_demux, "Script didn't return a table" );
402 msg_Err( p_demux, "Script went completely foobar" );
405 vlc_object_release( p_input_thread );
406 vlc_object_release( p_playlist );
408 return -1; /* Needed for correct operation of go back */
411 static int Control( demux_t *p_demux, int i_query, va_list args )