1 /*****************************************************************************
2 * b4s.c : B4S playlist format import
3 *****************************************************************************
4 * Copyright (C) 2005-2009 VLC authors and VideoLAN
7 * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_access.h>
35 #include <vlc_strings.h>
39 /*****************************************************************************
41 *****************************************************************************/
42 static int ReadDir( stream_t
*, input_item_node_t
*);
43 static bool IsWhitespace( const char *psz_string
);
45 /*****************************************************************************
46 * Import_B4S: main import function
47 *****************************************************************************/
48 int Import_B4S( vlc_object_t
*p_this
)
50 stream_t
*demux
= (stream_t
*)p_this
;
53 if( !stream_HasExtension( demux
, ".b4s" ) )
56 demux
->pf_readdir
= ReadDir
;
57 demux
->pf_control
= access_vaDirectoryControlHelper
;
62 static int ReadDir( stream_t
*p_demux
, input_item_node_t
*p_subitems
)
66 xml_reader_t
*p_xml_reader
= NULL
;
67 char *psz_elname
= NULL
;
69 input_item_t
*p_input
;
70 char *psz_mrl
= NULL
, *psz_title
= NULL
, *psz_genre
= NULL
;
71 char *psz_now
= NULL
, *psz_listeners
= NULL
, *psz_bitrate
= NULL
;
73 input_item_t
*p_current_input
= GetCurrentItem(p_demux
);
75 free( vlc_stream_ReadLine( p_demux
->p_source
) );
77 p_xml_reader
= xml_ReaderCreate( p_demux
, p_demux
->p_source
);
83 if( xml_ReaderNextNode( p_xml_reader
, &node
) != XML_READER_STARTELEM
)
85 msg_Err( p_demux
, "invalid file (no root node)" );
89 if( strcmp( node
, "WinampXML" ) )
91 msg_Err( p_demux
, "invalid root node: %s", node
);
95 /* root node should not have any attributes, and should only
96 * contain the "playlist node */
98 /* Skip until 1st child node */
99 while( (i_ret
= xml_ReaderNextNode( p_xml_reader
, &node
)) != XML_READER_STARTELEM
)
102 msg_Err( p_demux
, "invalid file (no child node)" );
106 if( strcmp( node
, "playlist" ) )
108 msg_Err( p_demux
, "invalid child node %s", node
);
112 // Read the attributes
113 const char *attr
, *value
;
114 while( (attr
= xml_ReaderNextAttr( p_xml_reader
, &value
)) != NULL
)
116 if( !strcmp( attr
, "num_entries" ) )
117 msg_Dbg( p_demux
, "playlist has %d entries", atoi(value
) );
118 else if( !strcmp( attr
, "label" ) )
119 input_item_SetName( p_current_input
, value
);
121 msg_Warn( p_demux
, "stray attribute %s with value %s in element"
122 " <playlist>", attr
, value
);
125 while( (i_ret
= xml_ReaderNextNode( p_xml_reader
, &node
)) > 0 )
130 case XML_READER_STARTELEM
:
132 // Read the element name
134 psz_elname
= strdup( node
);
135 if( unlikely(!psz_elname
) )
138 // Read the attributes
139 while( (attr
= xml_ReaderNextAttr( p_xml_reader
, &value
)) )
141 if( !strcmp( psz_elname
, "entry" ) &&
142 !strcmp( attr
, "Playstring" ) )
145 psz_mrl
= strdup( value
);
149 msg_Warn( p_demux
, "unexpected attribute %s in <%s>",
156 case XML_READER_TEXT
:
160 if( psz_elname
== NULL
)
162 if( IsWhitespace( node
) )
164 if( !strcmp( psz_elname
, "Name" ) )
166 else if( !strcmp( psz_elname
, "Genre" ) )
168 else if( !strcmp( psz_elname
, "Nowplaying" ) )
170 else if( !strcmp( psz_elname
, "Listeners" ) )
172 else if( !strcmp( psz_elname
, "Bitrate" ) )
176 msg_Warn( p_demux
, "unexpected text in element <%s>",
186 case XML_READER_ENDELEM
:
188 // Read the element name
189 if( !strcmp( node
, "entry" ) )
191 vlc_xml_decode( psz_mrl
);
192 p_input
= input_item_New( psz_mrl
, psz_title
);
194 input_item_SetNowPlaying( p_input
, psz_now
);
196 input_item_SetGenre( p_input
, psz_genre
);
198 msg_Err( p_demux
, "Unsupported meta listeners" );
200 msg_Err( p_demux
, "Unsupported meta bitrate" );
202 input_item_node_AppendItem( p_subitems
, p_input
);
203 input_item_Release( p_input
);
204 FREENULL( psz_title
);
206 FREENULL( psz_genre
);
207 FREENULL( psz_bitrate
);
208 FREENULL( psz_listeners
);
211 FREENULL( psz_elname
);
219 msg_Warn( p_demux
, "error while parsing data" );
220 i_ret
= 0; /* Needed for correct operation of go back */
227 xml_ReaderDelete( p_xml_reader
);
231 static bool IsWhitespace( const char *psz_string
)
233 psz_string
+= strspn( psz_string
, " \t\r\n" );