]> git.sesse.net Git - vlc/blob - modules/misc/lua/demux.c
give playlist to vlclua_playlist_add_internal instead of NULL, core doesn't like
[vlc] / modules / misc / lua / demux.c
1 /*****************************************************************************
2  * demux.c :  Lua playlist demux module
3  *****************************************************************************
4  * Copyright (C) 2007-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Cellerier <dionoea at videolan tod org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_demux.h>
33 #include <vlc_url.h>
34 #include <vlc_strings.h>
35 #include <vlc_charset.h>
36
37 #include <errno.h>                                                 /* ENOMEM */
38 #ifdef HAVE_SYS_STAT_H
39 #   include <sys/stat.h>
40 #endif
41
42 #include "vlc.h"
43 #include "libs.h"
44
45
46 /*****************************************************************************
47  * Local prototypes
48  *****************************************************************************/
49 static int Demux( demux_t *p_demux );
50 static int Control( demux_t *p_demux, int i_query, va_list args );
51
52 /*****************************************************************************
53  * Demux specific functions
54  *****************************************************************************/
55 struct demux_sys_t
56 {
57     lua_State *L;
58     char *psz_filename;
59 };
60
61 static int vlclua_demux_peek( lua_State *L )
62 {
63     demux_t *p_demux = (demux_t *)vlclua_get_this( L );
64     int n = luaL_checkint( L, 1 );
65     const uint8_t *p_peek;
66     int i_peek = stream_Peek( p_demux->s, &p_peek, n );
67     lua_pushlstring( L, (const char *)p_peek, i_peek );
68     return 1;
69 }
70
71 static int vlclua_demux_read( lua_State *L )
72 {
73     demux_t *p_demux = (demux_t *)vlclua_get_this( L );
74     uint8_t *p_read;
75     int n = luaL_checkint( L, 1 );
76     int i_read = stream_Read( p_demux->s, &p_read, n );
77     lua_pushlstring( L, (const char *)p_read, i_read );
78     return 1;
79 }
80
81 static int vlclua_demux_readline( lua_State *L )
82 {
83     demux_t *p_demux = (demux_t *)vlclua_get_this( L );
84     char *psz_line = stream_ReadLine( p_demux->s );
85     if( psz_line )
86     {
87         lua_pushstring( L, psz_line );
88         free( psz_line );
89     }
90     else
91     {
92         lua_pushnil( L );
93     }
94     return 1;
95 }
96
97 /*****************************************************************************
98  *
99  *****************************************************************************/
100 /* Functions to register */
101 static luaL_Reg p_reg[] =
102 {
103     { "peek", vlclua_demux_peek },
104     { NULL, NULL }
105 };
106
107 /* Functions to register for parse() function call only */
108 static luaL_Reg p_reg_parse[] =
109 {
110     { "read", vlclua_demux_read },
111     { "readline", vlclua_demux_readline },
112     { NULL, NULL }
113 };
114
115 /*****************************************************************************
116  * Called through lua_scripts_batch_execute to call 'probe' on
117  * the script pointed by psz_filename.
118  *****************************************************************************/
119 static int probe_luascript( vlc_object_t *p_this, const char * psz_filename,
120                             lua_State * L, void * user_data )
121 {
122     VLC_UNUSED(user_data);
123     demux_t * p_demux = (demux_t *)p_this;
124
125     p_demux->p_sys->psz_filename = strdup(psz_filename);
126
127     /* In lua, setting a variable's value to nil is equivalent to deleting it */
128     lua_pushnil( L );
129     lua_pushnil( L );
130     lua_setglobal( L, "probe" );
131     lua_setglobal( L, "parse" );
132
133     /* Load and run the script(s) */
134     if( luaL_dofile( L, psz_filename ) )
135     {
136         msg_Warn( p_demux, "Error loading script %s: %s", psz_filename,
137                   lua_tostring( L, lua_gettop( L ) ) );
138         lua_pop( L, 1 );
139         return VLC_EGENERIC;
140     }
141
142     lua_getglobal( L, "probe" );
143
144     if( !lua_isfunction( L, -1 ) )
145     {
146         msg_Warn( p_demux, "Error while runing script %s, "
147                   "function probe() not found", psz_filename );
148         lua_pop( L, 1 );
149         return VLC_EGENERIC;
150     }
151
152     if( lua_pcall( L, 0, 1, 0 ) )
153     {
154         msg_Warn( p_demux, "Error while runing script %s, "
155                   "function probe(): %s", psz_filename,
156                   lua_tostring( L, lua_gettop( L ) ) );
157         lua_pop( L, 1 );
158         return VLC_EGENERIC;
159     }
160
161     if( lua_gettop( L ) )
162     {
163         int i_ret = VLC_EGENERIC;
164         if( lua_toboolean( L, 1 ) )
165         {
166             msg_Dbg( p_demux, "Lua playlist script %s's "
167                      "probe() function was successful", psz_filename );
168             i_ret = VLC_SUCCESS;
169         }
170         lua_pop( L, 1 );
171
172         return i_ret;
173     }
174     return VLC_EGENERIC;
175 }
176
177 /*****************************************************************************
178  * Import_LuaPlaylist: main import function
179  *****************************************************************************/
180 int Import_LuaPlaylist( vlc_object_t *p_this )
181 {
182     demux_t *p_demux = (demux_t *)p_this;
183     lua_State *L;
184     int ret;
185
186     p_demux->p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) );
187     if( !p_demux->p_sys )
188     {
189         return VLC_ENOMEM;
190     }
191
192     p_demux->p_sys->psz_filename = NULL;
193
194     p_demux->pf_control = Control;
195     p_demux->pf_demux = Demux;
196
197     /* Initialise Lua state structure */
198     L = luaL_newstate();
199     if( !L )
200     {
201         msg_Err( p_demux, "Could not create new Lua State" );
202         free( p_demux->p_sys );
203         return VLC_EGENERIC;
204     }
205     p_demux->p_sys->L = L;
206
207     /* Load Lua libraries */
208     luaL_openlibs( L ); /* FIXME: Don't open all the libs? */
209
210     luaL_register( L, "vlc", p_reg );
211     luaopen_msg( L );
212     luaopen_strings( L );
213     lua_pushlightuserdata( L, p_demux );
214     lua_setfield( L, -2, "private" );
215     lua_pushstring( L, p_demux->psz_path );
216     lua_setfield( L, -2, "path" );
217     lua_pushstring( L, p_demux->psz_access );
218     lua_setfield( L, -2, "access" );
219
220     lua_pop( L, 1 );
221
222     ret = vlclua_scripts_batch_execute( p_this, "playlist",
223                                         &probe_luascript, L, NULL );
224     if( ret )
225         Close_LuaPlaylist( p_this );
226     return ret;
227 }
228
229
230 /*****************************************************************************
231  * Deactivate: frees unused data
232  *****************************************************************************/
233 void Close_LuaPlaylist( vlc_object_t *p_this )
234 {
235     demux_t *p_demux = (demux_t *)p_this;
236     lua_close( p_demux->p_sys->L );
237     free( p_demux->p_sys->psz_filename );
238     free( p_demux->p_sys );
239 }
240
241 static int Demux( demux_t *p_demux )
242 {
243     lua_State *L = p_demux->p_sys->L;
244     char *psz_filename = p_demux->p_sys->psz_filename;
245
246     input_thread_t *p_input_thread = (input_thread_t *)
247         vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
248     input_item_t *p_current_input = input_GetItem( p_input_thread );
249     playlist_t *p_playlist = pl_Yield( p_demux );
250
251     luaL_register( L, "vlc", p_reg_parse );
252
253     lua_getglobal( L, "parse" );
254
255     if( !lua_isfunction( L, -1 ) )
256     {
257         msg_Warn( p_demux, "Error while runing script %s, "
258                   "function parse() not found", psz_filename );
259         Close_LuaPlaylist( VLC_OBJECT( p_demux ) );
260         return VLC_EGENERIC;
261     }
262
263     if( lua_pcall( L, 0, 1, 0 ) )
264     {
265         msg_Warn( p_demux, "Error while runing script %s, "
266                   "function parse(): %s", psz_filename,
267                   lua_tostring( L, lua_gettop( L ) ) );
268         Close_LuaPlaylist( VLC_OBJECT( p_demux ) );
269         return VLC_EGENERIC;
270     }
271
272     if( lua_gettop( L ) )
273         vlclua_playlist_add_internal( p_demux, L, p_playlist,
274                                       p_current_input, 0 );
275     else
276         msg_Err( p_demux, "Script went completely foobar" );
277
278     vlc_object_release( p_input_thread );
279     pl_Release( p_playlist );
280
281     return -1; /* Needed for correct operation of go back */
282 }
283
284 static int Control( demux_t *p_demux, int i_query, va_list args )
285 {
286     VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args);
287     return VLC_EGENERIC;
288 }