]> git.sesse.net Git - vlc/blob - modules/demux/playlist/b4s.c
RTP: Initialize ref_ts to zero
[vlc] / modules / demux / playlist / b4s.c
1 /*****************************************************************************
2  * b4s.c : B4S playlist format import
3  *****************************************************************************
4  * Copyright (C) 2005-2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Sigmund Augdal Helberg <dnumgis@videolan.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
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_demux.h>
34 #include <vlc_xml.h>
35
36 #include "playlist.h"
37
38 struct demux_sys_t
39 {
40     char *psz_prefix;
41 };
42
43 /*****************************************************************************
44  * Local prototypes
45  *****************************************************************************/
46 static int Demux( demux_t *p_demux);
47 static int Control( demux_t *p_demux, int i_query, va_list args );
48 static int IsWhitespace( char *psz_string );
49
50 /*****************************************************************************
51  * Import_B4S: main import function
52  *****************************************************************************/
53 int Import_B4S( vlc_object_t *p_this )
54 {
55     DEMUX_BY_EXTENSION_OR_FORCED_MSG( ".b4s", "b4s-open",
56                                       "using B4S playlist reader" );
57     p_demux->p_sys->psz_prefix = FindPrefix( p_demux );
58     return VLC_SUCCESS;
59 }
60
61 /*****************************************************************************
62  * Deactivate: frees unused data
63  *****************************************************************************/
64 void Close_B4S( vlc_object_t *p_this )
65 {
66     demux_t *p_demux = (demux_t *)p_this;
67     demux_sys_t *p_sys = p_demux->p_sys;
68
69     free( p_sys->psz_prefix );
70     free( p_sys );
71 }
72
73 static int Demux( demux_t *p_demux )
74 {
75     int i_ret = -1;
76
77     xml_t *p_xml;
78     xml_reader_t *p_xml_reader = NULL;
79     char *psz_elname = NULL;
80     input_item_t *p_input;
81     char *psz_mrl = NULL, *psz_title = NULL, *psz_genre = NULL;
82     char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL;
83
84     input_item_t *p_current_input = GetCurrentItem(p_demux);
85
86     p_xml = xml_Create( p_demux );
87     if( !p_xml )
88         goto end;
89
90     psz_elname = stream_ReadLine( p_demux->s );
91     free( psz_elname );
92     psz_elname = NULL;
93
94     p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s );
95     if( !p_xml_reader )
96         goto end;
97
98     /* xml */
99     /* check root node */
100     if( xml_ReaderRead( p_xml_reader ) != 1 )
101     {
102         msg_Err( p_demux, "invalid file (no root node)" );
103         goto end;
104     }
105
106     if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ||
107         ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
108         strcmp( psz_elname, "WinampXML" ) )
109     {
110         msg_Err( p_demux, "invalid root node %i, %s",
111                  xml_ReaderNodeType( p_xml_reader ), psz_elname );
112         goto end;
113     }
114     FREENULL( psz_elname );
115
116     /* root node should not have any attributes, and should only
117      * contain the "playlist node */
118
119     /* Skip until 1st child node */
120     while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 &&
121            xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM );
122     if( i_ret != 1 )
123     {
124         msg_Err( p_demux, "invalid file (no child node)" );
125         goto end;
126     }
127
128     if( ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
129         strcmp( psz_elname, "playlist" ) )
130     {
131         msg_Err( p_demux, "invalid child node %s", psz_elname );
132         goto end;
133     }
134     FREENULL( psz_elname );
135
136     // Read the attributes
137     while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
138     {
139         char *psz_name = xml_ReaderName( p_xml_reader );
140         char *psz_value = xml_ReaderValue( p_xml_reader );
141         if( !psz_name || !psz_value )
142         {
143             free( psz_name );
144             free( psz_value );
145             goto end;
146         }
147         if( !strcmp( psz_name, "num_entries" ) )
148         {
149             msg_Dbg( p_demux, "playlist has %d entries", atoi(psz_value) );
150         }
151         else if( !strcmp( psz_name, "label" ) )
152         {
153             input_item_SetName( p_current_input, psz_value );
154         }
155         else
156         {
157             msg_Warn( p_demux, "stray attribute %s with value %s in element"
158                       " 'playlist'", psz_name, psz_value );
159         }
160         free( psz_name );
161         free( psz_value );
162     }
163
164     while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 )
165     {
166         // Get the node type
167         switch( xml_ReaderNodeType( p_xml_reader ) )
168         {
169             // Error
170             case -1:
171                 goto end;
172
173             case XML_READER_STARTELEM:
174             {
175                 // Read the element name
176                 free( psz_elname );
177                 psz_elname = xml_ReaderName( p_xml_reader );
178                 if( !psz_elname )
179                     goto end;
180
181                 // Read the attributes
182                 while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
183                 {
184                     char *psz_name = xml_ReaderName( p_xml_reader );
185                     char *psz_value = xml_ReaderValue( p_xml_reader );
186                     if( !psz_name || !psz_value )
187                     {
188                         free( psz_name );
189                         free( psz_value );
190                         goto end;
191                     }
192                     if( !strcmp( psz_elname, "entry" ) &&
193                         !strcmp( psz_name, "Playstring" ) )
194                     {
195                         psz_mrl = psz_value;
196                     }
197                     else
198                     {
199                         msg_Warn( p_demux, "unexpected attribure %s in element %s",
200                                   psz_name, psz_elname );
201                         free( psz_value );
202                     }
203                     free( psz_name );
204                 }
205                 break;
206             }
207             case XML_READER_TEXT:
208             {
209                 char *psz_text = xml_ReaderValue( p_xml_reader );
210                 if( IsWhitespace( psz_text ) )
211                 {
212                     free( psz_text );
213                     break;
214                 }
215                 if( !strcmp( psz_elname, "Name" ) )
216                 {
217                     psz_title = psz_text;
218                 }
219                 else if( !strcmp( psz_elname, "Genre" ) )
220                 {
221                     psz_genre = psz_text;
222                 }
223                 else if( !strcmp( psz_elname, "Nowplaying" ) )
224                 {
225                     psz_now = psz_text;
226                 }
227                 else if( !strcmp( psz_elname, "Listeners" ) )
228                 {
229                     psz_listeners = psz_text;
230                 }
231                 else if( !strcmp( psz_elname, "Bitrate" ) )
232                 {
233                     psz_bitrate = psz_text;
234                 }
235                 else if( !strcmp( psz_elname, "" ) )
236                 {
237                     free( psz_text );
238                 }
239                 else
240                 {
241                     msg_Warn( p_demux, "unexpected text in element '%s'",
242                               psz_elname );
243                     free( psz_text );
244                 }
245                 break;
246             }
247             // End element
248             case XML_READER_ENDELEM:
249             {
250                 // Read the element name
251                 free( psz_elname );
252                 psz_elname = xml_ReaderName( p_xml_reader );
253                 if( !psz_elname )
254                     goto end;
255                 if( !strcmp( psz_elname, "entry" ) )
256                 {
257                     p_input = input_item_New( p_demux, psz_mrl, psz_title );
258                     if( psz_now )
259                         input_item_SetNowPlaying( p_input, psz_now );
260                     if( psz_genre )
261                         input_item_SetGenre( p_input, psz_genre );
262                     if( psz_listeners )
263                         msg_Err( p_demux, "Unsupported meta listeners" );
264                     if( psz_bitrate )
265                         msg_Err( p_demux, "Unsupported meta bitrate" );
266
267                     input_item_AddSubItem( p_current_input, p_input );
268                     vlc_gc_decref( p_input );
269                     FREENULL( psz_title );
270                     FREENULL( psz_mrl );
271                     FREENULL( psz_genre );
272                     FREENULL( psz_bitrate );
273                     FREENULL( psz_listeners );
274                     FREENULL( psz_now );
275                 }
276                 free( psz_elname );
277                 psz_elname = strdup( "" );
278
279                 break;
280             }
281         }
282     }
283
284     if( i_ret != 0 )
285     {
286         msg_Warn( p_demux, "error while parsing data" );
287         i_ret = 0; /* Needed for correct operation of go back */
288     }
289
290 end:
291     free( psz_elname );
292
293     vlc_gc_decref( p_current_input );
294     if( p_xml_reader )
295         xml_ReaderDelete( p_xml, p_xml_reader );
296     if( p_xml )
297         xml_Delete( p_xml );
298     return i_ret;
299 }
300
301 static int Control( demux_t *p_demux, int i_query, va_list args )
302 {
303     VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args);
304     return VLC_EGENERIC;
305 }
306
307 static int IsWhitespace( char *psz_string )
308 {
309     while( *psz_string )
310     {
311         if( *psz_string != ' ' && *psz_string != '\t' && *psz_string != '\r' &&
312             *psz_string != '\n' )
313         {
314             return false;
315         }
316         psz_string++;
317     }
318     return true;
319 }