Commit 0a85015c authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

playlist: Rewrite WPL module

It is now using our XML parser, and is licensed as LGPL
parent 9d73a00b
...@@ -220,6 +220,7 @@ libplaylist_plugin_la_SOURCES = \ ...@@ -220,6 +220,7 @@ libplaylist_plugin_la_SOURCES = \
demux/playlist/ram.c \ demux/playlist/ram.c \
demux/playlist/sgimb.c \ demux/playlist/sgimb.c \
demux/playlist/shoutcast.c \ demux/playlist/shoutcast.c \
demux/playlist/wpl.c \
demux/playlist/xspf.c \ demux/playlist/xspf.c \
demux/playlist/directory.c \ demux/playlist/directory.c \
demux/playlist/playlist.c demux/playlist/playlist.h demux/playlist/playlist.c demux/playlist/playlist.h
......
...@@ -135,6 +135,11 @@ vlc_module_begin () ...@@ -135,6 +135,11 @@ vlc_module_begin ()
add_shortcut( "playlist", "itml" ) add_shortcut( "playlist", "itml" )
set_capability( "demux", 10 ) set_capability( "demux", 10 )
set_callbacks( Import_iTML, Close_iTML ) set_callbacks( Import_iTML, Close_iTML )
add_submodule ()
set_description( N_("WPL playlist import") )
add_shortcut( "playlist", "wpl" )
set_capability( "demux", 10 )
set_callbacks( Import_WPL, Close_WPL )
add_submodule () add_submodule ()
set_description( N_("Directory import") ) set_description( N_("Directory import") )
add_shortcut( "playlist", "directory" ) add_shortcut( "playlist", "directory" )
......
/*****************************************************************************
* wpl.c : WPL playlist import
*****************************************************************************
* Copyright (C) 2015 VLC authors and VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_demux.h>
#include <vlc_xml.h>
#include "playlist.h"
struct demux_sys_t
{
xml_t* p_xml;
xml_reader_t* p_reader;
char* psz_prefix;
};
static void read_head( demux_t* p_demux, input_item_t* p_input )
{
demux_sys_t* p_sys = p_demux->p_sys;
const char* psz_name;
int i_type;
do
{
i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name );
if ( !strcasecmp( psz_name, "meta" ) )
{
char* psz_attribute_name = NULL;
char* psz_attribute_value = NULL;
while (!psz_attribute_name || !psz_attribute_value)
{
const char* psz_attr = NULL;
const char* psz_val = NULL;
psz_attr = xml_ReaderNextAttr( p_sys->p_reader, &psz_val );
if ( !psz_attr || !psz_val )
break;
if ( !strcasecmp( psz_attr, "name" ) )
psz_attribute_name = strdup( psz_val );
else if ( !strcasecmp( psz_attr, "content" ) )
psz_attribute_value = strdup( psz_val );
}
printf( "name: %s; value: %s\n", psz_attribute_name, psz_attribute_value );
if ( psz_attribute_name && psz_attribute_value )
{
if ( !strcasecmp( psz_attribute_name, "TotalDuration" ) )
input_item_SetDuration( p_input, atoll( psz_attribute_value ) );
else if ( !strcasecmp( psz_attribute_name, "Author" ) )
input_item_SetPublisher( p_input, psz_attribute_value );
else if ( !strcasecmp( psz_attribute_name, "Rating" ) )
input_item_SetRating( p_input, psz_attribute_value );
else if ( !strcasecmp( psz_attribute_name, "Genre" ) )
input_item_SetGenre( p_input, psz_attribute_value );
}
free( psz_attribute_name );
free( psz_attribute_value );
}
else if ( !strcasecmp( psz_name, "title" ) )
{
const char* psz_title;
int i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_title );
if ( i_type == XML_READER_TEXT && psz_title != NULL )
input_item_SetTitle( p_input, psz_title );
}
} while ( i_type != XML_READER_ENDELEM || strcasecmp( psz_name, "head" ) );
}
static void read_body( demux_t* p_demux, input_item_node_t* p_node )
{
demux_sys_t* p_sys = p_demux->p_sys;
const char* psz_name;
int i_type;
i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name );
if ( i_type != XML_READER_STARTELEM || strcasecmp( psz_name, "seq" ) )
{
msg_Err( p_demux, "Expected opening <seq> tag. Got <%s> with type %d", psz_name, i_type );
return;
}
do
{
i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name );
if ( !strcasecmp( psz_name, "media" ) )
{
const char* psz_attr = NULL;
const char* psz_val = NULL;
while ((psz_attr = xml_ReaderNextAttr( p_sys->p_reader, &psz_val )))
{
if ( !psz_val )
continue;
if (!strcasecmp( psz_attr, "src" ) )
{
char* mrl = ProcessMRL( psz_val, p_sys->psz_prefix );
if ( unlikely( !mrl ) )
return;
input_item_t* p_item = input_item_NewExt( mrl, NULL, 0, NULL, 0, -1 );
if ( likely( p_item ) )
{
input_item_node_AppendItem( p_node, p_item );
input_item_Release( p_item );
}
free( mrl );
}
}
}
} while ( i_type != XML_READER_ENDELEM || strcasecmp( psz_name, "seq" ) );
i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name );
if ( i_type != XML_READER_ENDELEM || strcasecmp( psz_name, "body" ) )
msg_Err( p_demux, "Expected closing <body> tag. Got: <%s> with type %d", psz_name, i_type );
}
static int Demux( demux_t* p_demux )
{
const char* psz_name;
int i_type;
demux_sys_t* p_sys = p_demux->p_sys;
input_item_t* p_input = GetCurrentItem( p_demux );
input_item_node_t* p_node = input_item_node_Create( p_input );
p_sys->psz_prefix = FindPrefix( p_demux );
do
{
i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name );
if ( i_type == XML_READER_STARTELEM && !strcasecmp( psz_name, "head" ) )
read_head( p_demux, p_input );
else if ( i_type == XML_READER_STARTELEM && !strcasecmp( psz_name, "body" ) )
read_body( p_demux, p_node );
} while (i_type != XML_READER_ENDELEM || strcasecmp( psz_name, "smil" ) );
input_item_node_PostAndDelete( p_node );
input_item_Release( p_input );
return 0;
}
void Close_WPL( vlc_object_t* p_this )
{
demux_t *p_demux = (demux_t*)p_this;
demux_sys_t* p_sys = p_demux->p_sys;
free( p_sys->psz_prefix );
if ( p_sys->p_reader )
xml_ReaderDelete( p_sys->p_reader );
if ( p_sys->p_xml )
xml_Delete( p_sys->p_xml );
free( p_sys );
}
int Import_WPL( vlc_object_t* p_this )
{
demux_t* p_demux = (demux_t*)p_this;
if( !demux_IsPathExtension( p_demux, ".wpl" ) &&
!demux_IsPathExtension( p_demux, ".zpl" ) )
return VLC_EGENERIC;
DEMUX_INIT_COMMON();
demux_sys_t* p_sys = p_demux->p_sys;
p_sys->p_xml = xml_Create( p_demux );
if ( !p_sys->p_xml )
{
msg_Err( p_demux, "Failed to create an XML parser" );
Close_WPL( p_this );
return VLC_EGENERIC;
}
p_sys->p_reader = xml_ReaderCreate( p_sys->p_xml, p_demux->s );
if ( !p_sys->p_reader )
{
msg_Err( p_demux, "Failed to create an XML reader" );
Close_WPL( p_this );
return VLC_EGENERIC;
}
const char* psz_name;
int type = xml_ReaderNextNode( p_sys->p_reader, &psz_name );
if ( type != XML_READER_STARTELEM || strcasecmp( psz_name, "smil" ) )
{
msg_Err( p_demux, "Invalid WPL playlist. Root element should have been <smil>" );
Close_WPL( p_this );
return VLC_EGENERIC;
}
msg_Dbg( p_demux, "Found valid WPL playlist" );
return VLC_SUCCESS;
}
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