]> git.sesse.net Git - vlc/blob - modules/demux/playlist/qtl.c
Preparse playlist items that don't have enough meta
[vlc] / modules / demux / playlist / qtl.c
1 /*****************************************************************************
2  * qtl.c: QuickTime Media Link Importer
3  *****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Cellerier <dionoea -@t- videolan -Dot- 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 See
26 http://developer.apple.com/documentation/QuickTime/QT6WhatsNew/Chap1/chapter_1_section_54.html
27 and
28 http://developer.apple.com/documentation/QuickTime/WhatsNewQT5/QT5NewChapt1/chapter_1_section_39.html
29
30 autoplay - true/false
31 controller - true/false
32 fullscreen - normal/double/half/current/full
33 href - url
34 kioskmode - true/false
35 loop - true/false/palindrome
36 movieid - integer
37 moviename - string
38 playeveryframe - true/false
39 qtnext - url
40 quitwhendone - true/false
41 src - url (required)
42 type - mime type
43 volume - 0 (mute) - 100 (max)
44
45 */
46
47 /*****************************************************************************
48  * Preamble
49  *****************************************************************************/
50 #include <ctype.h>                                              /* isspace() */
51
52 #include <vlc/vlc.h>
53 #include <vlc/input.h>
54 #include <vlc/intf.h>
55
56 #include "playlist.h"
57 #include "vlc_xml.h"
58
59 struct demux_sys_t
60 {
61     playlist_t *p_playlist;
62     playlist_item_t *p_current;
63     playlist_item_t *p_item_in_category;
64
65     xml_t *p_xml;
66     xml_reader_t *p_xml_reader;
67 };
68
69 typedef enum { FULLSCREEN_NORMAL,
70                FULLSCREEN_DOUBLE,
71                FULLSCREEN_HALF,
72                FULLSCREEN_CURRENT,
73                FULLSCREEN_FULL } qtl_fullscreen_t;
74 char* ppsz_fullscreen[] = { "normal", "double", "half", "current", "full" };
75 typedef enum { LOOP_TRUE,
76                LOOP_FALSE,
77                LOOP_PALINDROME } qtl_loop_t;
78 char* ppsz_loop[] = { "true", "false", "palindrome" };
79
80 /*****************************************************************************
81  * Local prototypes
82  *****************************************************************************/
83 static int Demux( demux_t *p_demux);
84 static int Control( demux_t *p_demux, int i_query, va_list args );
85
86 /*****************************************************************************
87  * Import_QTL: main import function
88  *****************************************************************************/
89 int E_(Import_QTL)( vlc_object_t *p_this )
90 {
91     DEMUX_BY_EXTENSION_MSG( ".qtl", "using QuickTime Media Link reader" );
92     p_demux->p_sys->p_playlist = NULL;
93     p_demux->p_sys->p_xml = NULL;
94     p_demux->p_sys->p_xml_reader = NULL;
95     return VLC_SUCCESS;
96 }
97
98 /*****************************************************************************
99  * Deactivate: frees unused data
100  *****************************************************************************/
101 void E_(Close_QTL)( vlc_object_t *p_this )
102 {
103     demux_t *p_demux = (demux_t *)p_this;
104     demux_sys_t *p_sys = p_demux->p_sys;
105
106     if( p_sys->p_playlist )
107         vlc_object_release( p_sys->p_playlist );
108     if( p_sys->p_xml_reader )
109         xml_ReaderDelete( p_sys->p_xml, p_sys->p_xml_reader );
110     if( p_sys->p_xml )
111         xml_Delete( p_sys->p_xml );
112     free( p_sys );
113 }
114
115 static int Demux( demux_t *p_demux )
116 {
117     demux_sys_t *p_sys = p_demux->p_sys;
118     xml_t *p_xml;
119     xml_reader_t *p_xml_reader;
120     char *psz_eltname = NULL;
121     input_item_t *p_input;
122
123     /* List of all possible attributes. The only required one is "src" */
124     vlc_bool_t b_autoplay = VLC_FALSE;
125     vlc_bool_t b_controler = VLC_TRUE;
126     qtl_fullscreen_t fullscreen = VLC_FALSE;
127     char *psz_href = NULL;
128     vlc_bool_t b_kioskmode = VLC_FALSE;
129     qtl_loop_t loop = LOOP_FALSE;
130     int i_movieid = -1;
131     char *psz_moviename = NULL;
132     vlc_bool_t b_playeveryframe = VLC_FALSE;
133     char *psz_qtnext = NULL;
134     vlc_bool_t b_quitwhendone = VLC_FALSE;
135     char *psz_src = NULL;
136     char *psz_mimetype = NULL;
137     int i_volume = 100;
138
139     INIT_PLAYLIST_STUFF;
140
141     p_sys->p_playlist = p_playlist;
142     p_sys->p_current = p_current;
143     p_sys->p_item_in_category = p_item_in_category;
144
145     p_xml = p_sys->p_xml = xml_Create( p_demux );
146     if( !p_xml ) return -1;
147
148     p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s );
149     if( !p_xml_reader ) return -1;
150     p_sys->p_xml_reader = p_xml_reader;
151
152     /* check root node */
153     if( xml_ReaderRead( p_xml_reader ) != 1 )
154     {
155         msg_Err( p_demux, "invalid file (no root node)" );
156         return -1;
157     }
158
159     if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ||
160         ( psz_eltname = xml_ReaderName( p_xml_reader ) ) == NULL ||
161         strcmp( psz_eltname, "embed" ) )
162     {
163         msg_Err( p_demux, "invalid root node %i, %s",
164                  xml_ReaderNodeType( p_xml_reader ), psz_eltname );
165         FREE( psz_eltname );
166
167         /* second line has <?quicktime tag ... so we try to skip it */
168         msg_Dbg( p_demux, "trying to read one more node" );
169         xml_ReaderRead( p_xml_reader );
170         if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ||
171             ( psz_eltname = xml_ReaderName( p_xml_reader ) ) == NULL ||
172             strcmp( psz_eltname, "embed" ) )
173         {
174             msg_Err( p_demux, "invalid root node %i, %s",
175                      xml_ReaderNodeType( p_xml_reader ), psz_eltname );
176             FREE( psz_eltname );
177             return -1;
178         }
179     }
180     FREE( psz_eltname );
181
182     while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS )
183     {
184         char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader );
185         char *psz_attrvalue = xml_ReaderValue( p_sys->p_xml_reader );
186
187         if( !psz_attrname || !psz_attrvalue )
188         {
189             FREE( psz_attrname );
190             FREE( psz_attrvalue );
191             return -1;
192         }
193
194         if( !strcmp( psz_attrname, "autoplay" ) )
195         {
196             if( !strcmp( psz_attrvalue, "true" ) )
197             {
198                 b_autoplay = VLC_TRUE;
199             }
200             else
201             {
202                 b_autoplay = VLC_FALSE;
203             }
204         }
205         else if( !strcmp( psz_attrname, "controler" ) )
206         {
207             if( !strcmp( psz_attrvalue, "false" ) )
208             {
209                 b_controler = VLC_FALSE;
210             }
211             else
212             {
213                 b_controler = VLC_TRUE;
214             }
215         }
216         else if( !strcmp( psz_attrname, "fullscreen" ) )
217         {
218             if( !strcmp( psz_attrvalue, "double" ) )
219             {
220                 fullscreen = FULLSCREEN_DOUBLE;
221             }
222             else if( !strcmp( psz_attrvalue, "half" ) )
223             {
224                 fullscreen = FULLSCREEN_HALF;
225             }
226             else if( !strcmp( psz_attrvalue, "current" ) )
227             {
228                 fullscreen = FULLSCREEN_CURRENT;
229             }
230             else if( !strcmp( psz_attrvalue, "full" ) )
231             {
232                 fullscreen = FULLSCREEN_FULL;
233             }
234             else
235             {
236                 fullscreen = FULLSCREEN_NORMAL;
237             }
238         }
239         else if( !strcmp( psz_attrname, "href" ) )
240         {
241             psz_href = psz_attrvalue;
242             psz_attrvalue = NULL;
243         }
244         else if( !strcmp( psz_attrname, "kioskmode" ) )
245         {
246             if( !strcmp( psz_attrvalue, "true" ) )
247             {
248                 b_kioskmode = VLC_TRUE;
249             }
250             else
251             {
252                 b_kioskmode = VLC_FALSE;
253             }
254         }
255         else if( !strcmp( psz_attrname, "loop" ) )
256         {
257             if( !strcmp( psz_attrvalue, "true" ) )
258             {
259                 loop = LOOP_TRUE;
260             }
261             else if( !strcmp( psz_attrvalue, "palindrome" ) )
262             {
263                 loop = LOOP_PALINDROME;
264             }
265             else
266             {
267                 loop = LOOP_FALSE;
268             }
269         }
270         else if( !strcmp( psz_attrname, "movieid" ) )
271         {
272             i_movieid = atoi( psz_attrvalue );
273         }
274         else if( !strcmp( psz_attrname, "moviename" ) )
275         {
276             psz_moviename = psz_attrvalue;
277             psz_attrvalue = NULL;
278         }
279         else if( !strcmp( psz_attrname, "playeveryframe" ) )
280         {
281             if( !strcmp( psz_attrvalue, "true" ) )
282             {
283                 b_playeveryframe = VLC_TRUE;
284             }
285             else
286             {
287                 b_playeveryframe = VLC_FALSE;
288             }
289         }
290         else if( !strcmp( psz_attrname, "qtnext" ) )
291         {
292             psz_qtnext = psz_attrvalue;
293             psz_attrvalue = NULL;
294         }
295         else if( !strcmp( psz_attrname, "quitwhendone" ) )
296         {
297             if( !strcmp( psz_attrvalue, "true" ) )
298             {
299                 b_quitwhendone = VLC_TRUE;
300             }
301             else
302             {
303                 b_quitwhendone = VLC_FALSE;
304             }
305         }
306         else if( !strcmp( psz_attrname, "src" ) )
307         {
308             psz_src = psz_attrvalue;
309             psz_attrvalue = NULL;
310         }
311         else if( !strcmp( psz_attrname, "mimetype" ) )
312         {
313             psz_mimetype = psz_attrvalue;
314             psz_attrvalue = NULL;
315         }
316         else if( !strcmp( psz_attrname, "volume" ) )
317         {
318             i_volume = atoi( psz_attrvalue );
319         }
320         else
321         {
322             msg_Dbg( p_demux, "Attribute %s with value %s isn't valid",
323                      psz_attrname, psz_attrvalue );
324         }
325         FREE( psz_attrname );
326         FREE( psz_attrvalue );
327     }
328
329     msg_Dbg( p_demux, "autoplay: %s (unused by VLC)",
330              b_autoplay==VLC_TRUE ? "true": "false" );
331     msg_Dbg( p_demux, "controler: %s (unused by VLC)",
332              b_controler==VLC_TRUE?"true": "false" );
333     msg_Dbg( p_demux, "fullscreen: %s (unused by VLC)",
334              ppsz_fullscreen[fullscreen] );
335     msg_Dbg( p_demux, "href: %s", psz_href );
336     msg_Dbg( p_demux, "kioskmode: %s (unused by VLC)",
337              b_kioskmode==VLC_TRUE?"true":"false" );
338     msg_Dbg( p_demux, "loop: %s (unused by VLC)", ppsz_loop[loop] );
339     msg_Dbg( p_demux, "movieid: %d (unused by VLC)", i_movieid );
340     msg_Dbg( p_demux, "moviename: %s", psz_moviename );
341     msg_Dbg( p_demux, "playeverframe: %s (unused by VLC)",
342              b_playeveryframe==VLC_TRUE?"true":"false" );
343     msg_Dbg( p_demux, "qtnext: %s", psz_qtnext );
344     msg_Dbg( p_demux, "quitwhendone: %s (unused by VLC)",
345              b_quitwhendone==VLC_TRUE?"true":"false" );
346     msg_Dbg( p_demux, "src: %s", psz_src );
347     msg_Dbg( p_demux, "mimetype: %s", psz_mimetype );
348     msg_Dbg( p_demux, "volume: %d (unused by VLC)", i_volume );
349
350
351     if( !psz_src )
352     {
353         msg_Err( p_demux, "Mandatory attribute 'src' not found" );
354     }
355     else
356     {
357         p_input = input_ItemNewExt( p_sys->p_playlist,
358                                 psz_src, psz_moviename, 0, NULL, -1 );
359 #define SADD_INFO( type, field ) if( field ) { input_ItemAddInfo( \
360                     p_input, "QuickTime Media Link", _(type), "%s", field ) ; }
361         SADD_INFO( "href", psz_href );
362         SADD_INFO( "mime type", psz_mimetype );
363         playlist_BothAddInput( p_sys->p_playlist, p_input,
364                                p_sys->p_item_in_category,
365                                PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
366                                PLAYLIST_END );
367         if( psz_qtnext )
368         {
369             p_input = input_ItemNewExt( p_sys->p_playlist,
370                                         psz_qtnext, NULL, 0, NULL, -1 );
371             playlist_BothAddInput( p_sys->p_playlist, p_input,
372                                    p_sys->p_item_in_category,
373                                    PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
374                                    PLAYLIST_END );
375         }
376     }
377
378     HANDLE_PLAY_AND_RELEASE;
379
380     p_sys->p_playlist = NULL;
381
382     FREE( psz_href );
383     FREE( psz_moviename );
384     FREE( psz_qtnext );
385     FREE( psz_src );
386     FREE( psz_mimetype );
387
388     return -1; /* Needed for correct operation of go back */
389 }
390
391 static int Control( demux_t *p_demux, int i_query, va_list args )
392 {
393     return VLC_EGENERIC;
394 }