[vlc-commits] playlist: Rewrite WPL module

Hugo Beauzée-Luyssen git at videolan.org
Fri Mar 13 15:22:59 CET 2015


vlc | branch: master | Hugo Beauzée-Luyssen <hugo at beauzee.fr> | Fri Mar 13 15:18:38 2015 +0100| [0a85015c3c86cecca354e9f1e4a2b96547b0567e] | committer: Hugo Beauzée-Luyssen

playlist: Rewrite WPL module

It is now using our XML parser, and is licensed as LGPL

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=0a85015c3c86cecca354e9f1e4a2b96547b0567e
---

 modules/demux/Makefile.am         |    1 +
 modules/demux/playlist/playlist.c |    5 +
 modules/demux/playlist/wpl.c      |  213 +++++++++++++++++++++++++++++++++++++
 3 files changed, 219 insertions(+)

diff --git a/modules/demux/Makefile.am b/modules/demux/Makefile.am
index b5d2d8a..78dc915 100644
--- a/modules/demux/Makefile.am
+++ b/modules/demux/Makefile.am
@@ -220,6 +220,7 @@ libplaylist_plugin_la_SOURCES = \
 	demux/playlist/ram.c \
 	demux/playlist/sgimb.c \
 	demux/playlist/shoutcast.c \
+	demux/playlist/wpl.c \
 	demux/playlist/xspf.c \
 	demux/playlist/directory.c \
 	demux/playlist/playlist.c demux/playlist/playlist.h
diff --git a/modules/demux/playlist/playlist.c b/modules/demux/playlist/playlist.c
index 92d30aa..07e47e1 100644
--- a/modules/demux/playlist/playlist.c
+++ b/modules/demux/playlist/playlist.c
@@ -136,6 +136,11 @@ vlc_module_begin ()
         set_capability( "demux", 10 )
         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 ()
         set_description( N_("Directory import") )
         add_shortcut( "playlist", "directory" )
         set_capability( "demux", 10 )
diff --git a/modules/demux/playlist/wpl.c b/modules/demux/playlist/wpl.c
new file mode 100644
index 0000000..e639799
--- /dev/null
+++ b/modules/demux/playlist/wpl.c
@@ -0,0 +1,213 @@
+/*****************************************************************************
+ * wpl.c : WPL playlist import
+ *****************************************************************************
+ * Copyright (C) 2015 VLC authors and VideoLAN
+ *
+ * Authors: Hugo Beauzée-Luyssen <hugo at 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;
+}
+



More information about the vlc-commits mailing list