Commit b37280cb authored by sigmunau's avatar sigmunau

new b4s demuxer for winamp b4s playlists. Uses xml parser modules. Only

works with xtag for now due to lack of a DTD
parent 437c2140
......@@ -2,4 +2,5 @@ SOURCES_playlist = playlist.c \
playlist.h \
old.c \
m3u.c \
b4s.c \
pls.c
/*****************************************************************************
* b4s.c : B4S playlist format import
*****************************************************************************
* Copyright (C) 2004 VideoLAN
* $Id: m3u.c 10101 2005-03-02 16:47:31Z robux4 $
*
* Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
#include <vlc/vlc.h>
#include <vlc/input.h>
#include <vlc/intf.h>
#include <errno.h> /* ENOMEM */
#include "playlist.h"
#include "vlc_xml.h"
struct demux_sys_t
{
char *psz_prefix;
playlist_t *p_playlist;
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 int IsWhitespace( char *psz_string );
/*****************************************************************************
* Import_B4S: main import function
*****************************************************************************/
int Import_B4S( vlc_object_t *p_this )
{
demux_t *p_demux = (demux_t *)p_this;
char *psz_ext;
psz_ext = strrchr ( p_demux->psz_path, '.' );
if( ( psz_ext && !strcasecmp( psz_ext, ".b4s") ) ||
( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "b4s") ) )
{
;
}
else
{
return VLC_EGENERIC;
}
msg_Dbg( p_demux, "using b4s playlist import");
p_demux->pf_control = Control;
p_demux->pf_demux = Demux;
p_demux->p_sys = malloc( sizeof(demux_sys_t) );
if( p_demux->p_sys == NULL )
{
msg_Err( p_demux, "Out of memory" );
return VLC_ENOMEM;
}
p_demux->p_sys->psz_prefix = FindPrefix( p_demux );
return VLC_SUCCESS;
}
/*****************************************************************************
* 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( p_sys->psz_prefix ) free( p_sys->psz_prefix );
if( p_sys->p_playlist ) vlc_object_release( p_sys->p_playlist );
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 );
}
static int Demux( demux_t *p_demux )
{
playlist_t *p_playlist;
int i_ret;
playlist_item_t *p_item, *p_current;
vlc_bool_t b_play;
xml_t *p_xml;
xml_reader_t *p_xml_reader;
char *psz_elname = NULL;
int i_type;
char *psz_mrl = NULL, *psz_name = NULL, *psz_genre = NULL;
char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL;
demux_sys_t *p_sys = p_demux->p_sys;
p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,
FIND_PARENT );
if( !p_playlist )
{
msg_Err( p_demux, "can't find playlist" );
return -1;
}
p_sys->p_playlist = p_playlist;
b_play = FindItem( p_demux, p_playlist, &p_current );
playlist_ItemToNode( p_playlist, p_current );
p_current->input.i_type = ITEM_TYPE_PLAYLIST;
p_xml = xml_Create( p_demux );
if( !p_xml ) return -1;
p_sys->p_xml = p_xml;
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;
/* xml */
/* check root node */
i_ret = xml_ReaderRead( p_xml_reader );
if( i_ret != 1 ||
xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ||
( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
strcmp( psz_elname, "WinampXML" ) )
{
msg_Err( p_demux, "invalid file %i,%s", xml_ReaderNodeType( p_xml_reader ), psz_elname );
if( psz_elname ) free( psz_elname );
return -1;
}
free( psz_elname );
/* root node should not have any attributes, and should only
* contain the "playlist node */
i_ret = xml_ReaderRead( p_xml_reader );
if( i_ret == 1 && xml_ReaderNodeType( p_xml_reader ) == XML_READER_TEXT )
{
i_ret = xml_ReaderRead( p_xml_reader );
}
if( i_ret != 1 ||
xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ||
( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
strcmp( psz_elname, "playlist" ) )
{
msg_Err( p_demux, "invalid file %i,%s", xml_ReaderNodeType( p_xml_reader ), psz_elname );
msg_Err( p_demux, "invalid file" );
if( psz_elname ) free( psz_elname );
return -1;
}
// Read the attributes
while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
{
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" ) )
{
playlist_ItemSetName( p_current, psz_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 );
}
i_ret = xml_ReaderRead( p_xml_reader );
while( i_ret == 1 )
{
// Get the node type
i_type = xml_ReaderNodeType( p_xml_reader );
switch( i_type )
{
// 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;
// Read the attributes
while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
{
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" ) )
{
psz_mrl = strdup( psz_value );
}
else
{
msg_Warn( p_demux, "unexpected attribure %s in element %s",
psz_name, 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 );
break;
}
if( !strcmp( psz_elname, "Name" ) )
{
psz_name = strdup( psz_text );
}
else if( !strcmp( psz_elname, "Genre" ) )
{
psz_genre = strdup( psz_text );
}
else if( !strcmp( psz_elname, "Nowplaying" ) )
{
psz_now = strdup( psz_text );
}
else if( !strcmp( psz_elname, "Listeners" ) )
{
psz_listeners = strdup( psz_text );
}
else if( !strcmp( psz_elname, "Bitrate" ) )
{
psz_bitrate = strdup( psz_text );
}
else if( !strcmp( psz_elname, "" ) )
{
;
}
else
{
msg_Warn( p_demux, "unexpected text in element '%s'",
psz_elname );
}
free( psz_text );
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" ) )
{
p_item = playlist_ItemNew( p_playlist, psz_mrl, psz_name );
if( psz_now )
{
vlc_input_item_AddInfo( &(p_item->input),
_("Meta-information"),
_( VLC_META_NOW_PLAYING ),
"%s",
psz_now );
}
if( psz_genre )
{
vlc_input_item_AddInfo( &p_item->input,
_("Meta-information"),
_( VLC_META_GENRE ),
"%s",
psz_genre );
}
if( psz_listeners )
{
vlc_input_item_AddInfo( &p_item->input,
_("Meta-information"),
_( "Listeners" ),
"%s",
psz_listeners );
}
if( psz_bitrate )
{
vlc_input_item_AddInfo( &p_item->input,
_("Meta-information"),
_( "Bitrate" ),
"%s",
psz_bitrate );
}
playlist_NodeAddItem( p_playlist, p_item,
p_current->pp_parents[0]->i_view,
p_current, PLAYLIST_APPEND,
PLAYLIST_END );
/* We need to declare the parents of the node as the
* * same of the parent's ones */
playlist_CopyParents( p_current, p_item );
vlc_input_item_CopyOptions( &p_current->input,
&p_item->input );
#define FREE(a) if( a ) free( a ); a = NULL;
FREE( psz_name );
FREE( psz_mrl );
FREE( psz_genre );
FREE( psz_bitrate );
FREE( psz_listeners );
FREE( psz_now );
#undef FREE
}
free( psz_elname );
psz_elname = strdup("");
break;
}
}
i_ret = xml_ReaderRead( p_xml_reader );
}
if( i_ret != 0 ) return -1;
/* end */
/* Go back and play the playlist */
if( b_play )
{
playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
p_playlist->status.i_view,
p_playlist->status.p_item, NULL );
}
vlc_object_release( p_playlist );
p_sys->p_playlist = NULL;
return VLC_SUCCESS;
}
static int Control( demux_t *p_demux, int i_query, va_list args )
{
return VLC_EGENERIC;
}
static int IsWhitespace( char *psz_string )
{
while( *psz_string )
{
if( *psz_string != ' ' && *psz_string != '\t' && *psz_string != '\r' &&
*psz_string != '\n' )
{
return VLC_FALSE;
}
psz_string++;
}
return VLC_TRUE;
}
......@@ -40,26 +40,31 @@ vlc_module_begin();
set_description( _("Old playlist open") );
add_shortcut( "old-open" );
set_capability( "demux2" , 10 );
set_callbacks( Import_Old , NULL );
set_capability( "demux2", 10 );
set_callbacks( Import_Old, NULL );
#if 0
add_submodule();
set_description( _("Native playlist import") );
add_shortcut( "playlist" );
add_shortcut( "native-open" );
set_capability( "demux2" , 10 );
set_callbacks( Import_Native , Close_Native );
set_capability( "demux2", 10 );
set_callbacks( Import_Native, Close_Native );
#endif
add_submodule();
set_description( _("M3U playlist import") );
add_shortcut( "m3u-open" );
set_capability( "demux2" , 10 );
set_callbacks( Import_M3U , Close_M3U );
set_capability( "demux2", 10 );
set_callbacks( Import_M3U, Close_M3U );
add_submodule();
set_description( _("PLS playlist import") );
add_shortcut( "pls-open" );
set_capability( "demux2" , 10 );
set_callbacks( Import_PLS , Close_PLS );
set_capability( "demux2", 10 );
set_callbacks( Import_PLS, Close_PLS );
add_submodule();
set_description( _("B4S playlist import") );
add_shortcut( "b4s-open" );
set_capability( "demux2", 10 );
set_callbacks( Import_B4S, Close_B4S );
vlc_module_end();
......
......@@ -27,11 +27,15 @@ char *FindPrefix( demux_t * );
vlc_bool_t FindItem( demux_t *, playlist_t *, playlist_item_t **);
int Import_Old ( vlc_object_t * );
int Import_M3U ( vlc_object_t * );
int Import_Native ( vlc_object_t * );
int Close_Native ( vlc_object_t * );
int Import_M3U ( vlc_object_t * );
void Close_M3U ( vlc_object_t * );
int Import_PLS ( vlc_object_t * );
void Close_PLS ( vlc_object_t * );
int Import_B4S ( vlc_object_t * );
void Close_B4S ( vlc_object_t * );
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment