/*****************************************************************************
* b4s.c : B4S playlist format import
*****************************************************************************
- * Copyright (C) 2005 the VideoLAN team
+ * Copyright (C) 2005-2009 the VideoLAN team
* $Id$
*
* Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
#include <vlc_common.h>
#include <vlc_demux.h>
-#include <vlc_interface.h>
+#include <vlc_xml.h>
#include "playlist.h"
-#include "vlc_xml.h"
-
-struct demux_sys_t
-{
- char *psz_prefix;
- xml_t *p_xml;
- xml_reader_t *p_xml_reader;
-};
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Demux( demux_t *p_demux);
-static int Control( demux_t *p_demux, int i_query, va_list args );
-//static char *GetNextToken(char *psz_cur_string);
-static int IsWhitespace( char *psz_string );
+static bool IsWhitespace( const char *psz_string );
/*****************************************************************************
* Import_B4S: main import function
*****************************************************************************/
int Import_B4S( vlc_object_t *p_this )
{
- DEMUX_BY_EXTENSION_OR_FORCED_MSG( ".b4s", "b4s-open",
- "using B4S playlist reader" );
- p_demux->p_sys->psz_prefix = FindPrefix( p_demux );
- p_demux->p_sys->p_xml = NULL;
- p_demux->p_sys->p_xml_reader = NULL;
- return VLC_SUCCESS;
-}
+ demux_t *demux = (demux_t *)p_this;
-/*****************************************************************************
- * Deactivate: frees unused data
- *****************************************************************************/
-void Close_B4S( vlc_object_t *p_this )
-{
- demux_t *p_demux = (demux_t *)p_this;
- demux_sys_t *p_sys = p_demux->p_sys;
+ if( !demux_IsPathExtension( demux, ".b4s" )
+ && !demux_IsForced( demux, "b4s-open" ) )
+ return VLC_EGENERIC;
+
+ demux->pf_demux = Demux;
+ demux->pf_control = Control;
- free( p_sys->psz_prefix );
- if( p_sys->p_xml_reader ) xml_ReaderDelete( p_sys->p_xml, p_sys->p_xml_reader );
- if( p_sys->p_xml ) xml_Delete( p_sys->p_xml );
- free( p_sys );
+ return VLC_SUCCESS;
}
static int Demux( demux_t *p_demux )
{
- demux_sys_t *p_sys = p_demux->p_sys;
- int i_ret;
+ int i_ret = -1;
- xml_t *p_xml;
- xml_reader_t *p_xml_reader;
+ xml_reader_t *p_xml_reader = NULL;
char *psz_elname = NULL;
- int i_type;
+ const char *node;
input_item_t *p_input;
- char *psz_mrl = NULL, *psz_name = NULL, *psz_genre = NULL;
+ char *psz_mrl = NULL, *psz_title = NULL, *psz_genre = NULL;
char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL;
+ input_item_node_t *p_subitems = NULL;
- INIT_PLAYLIST_STUFF;
-
- p_xml = p_sys->p_xml = xml_Create( p_demux );
- if( !p_xml ) return -1;
+ input_item_t *p_current_input = GetCurrentItem(p_demux);
- psz_elname = stream_ReadLine( p_demux->s );
- free( psz_elname );
- psz_elname = 0;
+ free( stream_ReadLine( p_demux->s ) );
- p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s );
- if( !p_xml_reader ) return -1;
- p_sys->p_xml_reader = p_xml_reader;
+ p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s );
+ if( !p_xml_reader )
+ return -1;
/* xml */
/* check root node */
- if( xml_ReaderRead( p_xml_reader ) != 1 )
+ if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM )
{
msg_Err( p_demux, "invalid file (no root node)" );
- vlc_object_release( p_playlist );
- return -1;
+ goto end;
}
- if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ||
- ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
- strcmp( psz_elname, "WinampXML" ) )
+ if( strcmp( node, "WinampXML" ) )
{
- msg_Err( p_demux, "invalid root node %i, %s",
- xml_ReaderNodeType( p_xml_reader ), psz_elname );
- free( psz_elname );
- vlc_object_release( p_playlist );
- return -1;
+ msg_Err( p_demux, "invalid root node: %s", node );
+ goto end;
}
- free( psz_elname );
/* root node should not have any attributes, and should only
* contain the "playlist node */
/* Skip until 1st child node */
- while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 &&
- xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM );
- if( i_ret != 1 )
- {
- msg_Err( p_demux, "invalid file (no child node)" );
- return -1;
- }
+ while( (i_ret = xml_ReaderNextNode( p_xml_reader, &node )) != XML_READER_STARTELEM )
+ if( i_ret <= 0 )
+ {
+ msg_Err( p_demux, "invalid file (no child node)" );
+ goto end;
+ }
- if( ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
- strcmp( psz_elname, "playlist" ) )
+ if( strcmp( node, "playlist" ) )
{
- msg_Err( p_demux, "invalid child node %s", psz_elname );
- free( psz_elname );
- return -1;
+ msg_Err( p_demux, "invalid child node %s", node );
+ goto end;
}
- free( psz_elname ); psz_elname = 0;
// Read the attributes
- while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
+ const char *attr, *value;
+ while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL )
{
- char *psz_name = xml_ReaderName( p_xml_reader );
- char *psz_value = xml_ReaderValue( p_xml_reader );
- if( !psz_name || !psz_value ) return -1;
- if( !strcmp( psz_name, "num_entries" ) )
- {
- msg_Dbg( p_demux, "playlist has %d entries", atoi(psz_value) );
- }
- else if( !strcmp( psz_name, "label" ) )
- {
- input_item_SetName( p_current_input, psz_value );
- }
+ if( !strcmp( attr, "num_entries" ) )
+ msg_Dbg( p_demux, "playlist has %d entries", atoi(value) );
+ else if( !strcmp( attr, "label" ) )
+ input_item_SetName( p_current_input, value );
else
- {
msg_Warn( p_demux, "stray attribute %s with value %s in element"
- " 'playlist'", psz_name, psz_value );
- }
- free( psz_name );
- free( psz_value );
+ " <playlist>", attr, value );
}
- while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 )
+ p_subitems = input_item_node_Create( p_current_input );
+
+ while( (i_ret = xml_ReaderNextNode( p_xml_reader, &node )) > 0 )
{
// Get the node type
- i_type = xml_ReaderNodeType( p_xml_reader );
- switch( i_type )
+ switch( i_ret )
{
- // Error
- case -1:
- return -1;
- break;
-
case XML_READER_STARTELEM:
{
// Read the element name
free( psz_elname );
- psz_elname = xml_ReaderName( p_xml_reader );
- if( !psz_elname ) return -1;
-
+ psz_elname = strdup( node );
+ if( unlikely(!psz_elname) )
+ goto end;
// Read the attributes
- while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
+ while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) )
{
- char *psz_name = xml_ReaderName( p_xml_reader );
- char *psz_value = xml_ReaderValue( p_xml_reader );
- if( !psz_name || !psz_value ) return -1;
if( !strcmp( psz_elname, "entry" ) &&
- !strcmp( psz_name, "Playstring" ) )
+ !strcmp( attr, "Playstring" ) )
{
- psz_mrl = strdup( psz_value );
+ free( psz_mrl );
+ psz_mrl = strdup( value );
}
else
{
- msg_Warn( p_demux, "unexpected attribure %s in element %s",
- psz_name, psz_elname );
+ msg_Warn( p_demux, "unexpected attribute %s in <%s>",
+ attr, psz_elname );
}
- free( psz_name );
- free( psz_value );
}
break;
}
+
case XML_READER_TEXT:
{
- char *psz_text = xml_ReaderValue( p_xml_reader );
- if( IsWhitespace( psz_text ) )
- {
- free( psz_text );
+ char **p;
+
+ if( psz_elname == NULL )
+ break;
+ if( IsWhitespace( node ) )
break;
- }
if( !strcmp( psz_elname, "Name" ) )
- {
- psz_name = strdup( psz_text );
- }
+ p = &psz_title;
else if( !strcmp( psz_elname, "Genre" ) )
- {
- psz_genre = strdup( psz_text );
- }
+ p = &psz_genre;
else if( !strcmp( psz_elname, "Nowplaying" ) )
- {
- psz_now = strdup( psz_text );
- }
+ p = &psz_now;
else if( !strcmp( psz_elname, "Listeners" ) )
- {
- psz_listeners = strdup( psz_text );
- }
+ p = &psz_listeners;
else if( !strcmp( psz_elname, "Bitrate" ) )
- {
- psz_bitrate = strdup( psz_text );
- }
- else if( !strcmp( psz_elname, "" ) )
- {
- ;
- }
+ p = &psz_bitrate;
else
{
- msg_Warn( p_demux, "unexpected text in element '%s'",
+ msg_Warn( p_demux, "unexpected text in element <%s>",
psz_elname );
+ break;
}
- free( psz_text );
+ free( *p );
+ *p = strdup( node );
break;
}
+
// End element
case XML_READER_ENDELEM:
{
// Read the element name
- free( psz_elname );
- psz_elname = xml_ReaderName( p_xml_reader );
- if( !psz_elname ) return -1;
- if( !strcmp( psz_elname, "entry" ) )
+ if( !strcmp( node, "entry" ) )
{
- p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name,
- 0, NULL, -1 );
+ p_input = input_item_New( psz_mrl, psz_title );
if( psz_now )
input_item_SetNowPlaying( p_input, psz_now );
if( psz_genre )
input_item_SetGenre( p_input, psz_genre );
if( psz_listeners )
- msg_Err( p_playlist, "Unsupported meta listeners" );
+ msg_Err( p_demux, "Unsupported meta listeners" );
if( psz_bitrate )
- msg_Err( p_playlist, "Unsupported meta bitrate" );
+ msg_Err( p_demux, "Unsupported meta bitrate" );
- input_ItemAddSubItem( p_current_input, p_input );
+ input_item_node_AppendItem( p_subitems, p_input );
vlc_gc_decref( p_input );
- FREENULL( psz_name );
+ FREENULL( psz_title );
FREENULL( psz_mrl );
FREENULL( psz_genre );
FREENULL( psz_bitrate );
FREENULL( psz_listeners );
FREENULL( psz_now );
}
- free( psz_elname );
- psz_elname = strdup("");
-
+ FREENULL( psz_elname );
break;
}
}
}
- if( i_ret != 0 )
+ if( i_ret < 0 )
{
msg_Warn( p_demux, "error while parsing data" );
+ i_ret = 0; /* Needed for correct operation of go back */
}
- HANDLE_PLAY_AND_RELEASE;
- return 0; /* Needed for correct operation of go back */
-}
+end:
+ free( psz_elname );
-static int Control( demux_t *p_demux, int i_query, va_list args )
-{
- VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args);
- return VLC_EGENERIC;
-}
+ if( p_subitems )
+ input_item_node_PostAndDelete( p_subitems );
-#if 0
-/**
- * Get a in-string pointer to the start of the next token from a
- * string terminating the pointer returned by a previous call.
- *
- * \param psz_cur_string The string to search for the token from
- * \return a pointer to withing psz_cur_string, or NULL if no token
- * was found
- * \note The returned pointer may contain more than one
- * token, Run GetNextToken once more to terminate the token properly
- */
-static char *GetNextToken(char *psz_cur_string) {
- while (*psz_cur_string && !isspace(*psz_cur_string))
- psz_cur_string++;
- if (!*psz_cur_string)
- return NULL;
- *psz_cur_string++ = '\0';
- while (*psz_cur_string && isspace(*psz_cur_string))
- psz_cur_string++;
- return psz_cur_string;
+ vlc_gc_decref( p_current_input );
+ if( p_xml_reader )
+ xml_ReaderDelete( p_xml_reader );
+ return i_ret;
}
-#endif
-static int IsWhitespace( char *psz_string )
+static bool IsWhitespace( const char *psz_string )
{
- while( *psz_string )
- {
- if( *psz_string != ' ' && *psz_string != '\t' && *psz_string != '\r' &&
- *psz_string != '\n' )
- {
- return false;
- }
- psz_string++;
- }
- return true;
+ psz_string += strspn( psz_string, " \t\r\n" );
+ return !*psz_string;
}