]> git.sesse.net Git - vlc/commitdiff
new b4s demuxer for winamp b4s playlists. Uses xml parser modules. Only
authorSigmund Augdal Helberg <sigmunau@videolan.org>
Sat, 2 Apr 2005 13:58:03 +0000 (13:58 +0000)
committerSigmund Augdal Helberg <sigmunau@videolan.org>
Sat, 2 Apr 2005 13:58:03 +0000 (13:58 +0000)
works with xtag for now due to lack of a DTD

modules/demux/playlist/Modules.am
modules/demux/playlist/b4s.c [new file with mode: 0644]
modules/demux/playlist/playlist.c
modules/demux/playlist/playlist.h

index a1b87db3a71f6cd89e54ecbc8e74711328083245..fd7f9684779a8f293228bebe88dc434fb3c6a892 100644 (file)
@@ -2,4 +2,5 @@ SOURCES_playlist = playlist.c \
                   playlist.h \
                   old.c \
                   m3u.c \
+                   b4s.c \
                   pls.c
diff --git a/modules/demux/playlist/b4s.c b/modules/demux/playlist/b4s.c
new file mode 100644 (file)
index 0000000..9083def
--- /dev/null
@@ -0,0 +1,382 @@
+/*****************************************************************************
+ * 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;
+}
index 4ce3e188d4e7baf7b9bca2ff7f2199e3a5b13488..900fc88cc6a670663356e83feaa3cf81581c9e30 100644 (file)
@@ -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();
 
 
index 9bc6e11237cb69d09715bc6e22f3c3dd863c33e8..4e661cb1272876c4c32019126d5cfb1c8588907f 100644 (file)
@@ -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 * );