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