]> git.sesse.net Git - vlc/blobdiff - modules/demux/m3u.c
* src/misc/messages.c: forget a defined(SYS_BEOS) in my last commit
[vlc] / modules / demux / m3u.c
index f4eed26ad5d72e765e51bb8808f87e80208935c9..6c320580c41e081de57a45b081f69c034da53e41 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
- * m3u.c: a meta demux to parse m3u and asx playlists
+ * m3u.c: a meta demux to parse pls, m3u and asx playlists
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: m3u.c,v 1.11 2003/01/16 21:14:23 babal Exp $
+ * $Id: m3u.c,v 1.18 2003/04/06 20:08:11 sigmunau Exp $
  *
  * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
  *          Gildas Bazin <gbazin@netcourrier.com>
  *****************************************************************************/
 #define MAX_LINE 1024
 
+#define TYPE_UNKNOWN 0
 #define TYPE_M3U 1
 #define TYPE_ASX 2
 #define TYPE_HTML 3
+#define TYPE_PLS 4
 
 struct demux_sys_t
 {
@@ -60,12 +62,13 @@ static int  Demux ( input_thread_t * );
  * Module descriptor
  *****************************************************************************/
 vlc_module_begin();
-    set_description( "m3u/asx metademux" );
-    set_capability( "demux", 10 );
+    set_description( _("playlist metademux") );
+    set_capability( "demux", 180 );
     set_callbacks( Activate, Deactivate );
     add_shortcut( "m3u" );
     add_shortcut( "asx" );
     add_shortcut( "html" );
+    add_shortcut( "pls" );
 vlc_module_end();
 
 /*****************************************************************************
@@ -76,7 +79,8 @@ static int Activate( vlc_object_t * p_this )
     input_thread_t *p_input = (input_thread_t *)p_this;
     char           *psz_ext;
     demux_sys_t    *p_m3u;
-    int            i_type = 0;
+    int             i_type = 0;
+    int             i_type2 = 0;
 
     /* Initialize access plug-in structures. */
     if( p_input->i_mtu == 0 )
@@ -88,35 +92,42 @@ static int Activate( vlc_object_t * p_this )
     p_input->pf_demux = Demux;
     p_input->pf_rewind = NULL;
 
-    /* Check for m3u/asx file extension */
+    /* Check for m3u/asx file extension or if the demux has been forced */
     psz_ext = strrchr ( p_input->psz_name, '.' );
-    if( !strcasecmp( psz_ext, ".m3u") ||
-        ( p_input->psz_demux && !strncmp(p_input->psz_demux, "m3u", 3) ) )
+
+    if( ( psz_ext && !strcasecmp( psz_ext, ".m3u") ) ||
+        ( p_input->psz_demux && !strcmp(p_input->psz_demux, "m3u") ) )
     {
         i_type = TYPE_M3U;
     }
-    else if( !strcasecmp( psz_ext, ".asx") ||
-             ( p_input->psz_demux && !strncmp(p_input->psz_demux, "asx", 3) ) )
+    else if( ( psz_ext && !strcasecmp( psz_ext, ".asx") ) ||
+             ( p_input->psz_demux && !strcmp(p_input->psz_demux, "asx") ) )
     {
         i_type = TYPE_ASX;
     }
-    else if( !strcasecmp( psz_ext, ".html") ||
-             ( p_input->psz_demux && !strncmp(p_input->psz_demux, "html", 4) ) )
+    else if( ( psz_ext && !strcasecmp( psz_ext, ".html") ) ||
+             ( p_input->psz_demux && !strcmp(p_input->psz_demux, "html") ) )
     {
         i_type = TYPE_HTML;
     }
+    else if( ( psz_ext && !strcasecmp( psz_ext, ".pls") ) ||
+             ( p_input->psz_demux && !strcmp(p_input->psz_demux, "pls") ) )
+    {
+        i_type = TYPE_PLS;
+    }
 
     /* we had no luck looking at the file extention, so we have a look
      * at the content. This is useful for .asp, .php and similar files
      * that are actually html. Also useful for som asx files that have
      * another extention */
-    if( !i_type )
+    if( i_type != TYPE_M3U )
     {
         byte_t *p_peek;
         int i_size = input_Peek( p_input, &p_peek, MAX_LINE );
-        i_size -= sizeof("<html>") - 1;
+        i_size -= sizeof("[playlist]") - 1;
         if ( i_size > 0 ) {
             while ( i_size
+                    && strncasecmp( p_peek, "[playlist]", sizeof("[playlist]") - 1 )
                     && strncasecmp( p_peek, "<html>", sizeof("<html>") - 1 )
                     && strncasecmp( p_peek, "<asx", sizeof("<asx") - 1 ) )
             {
@@ -125,18 +136,35 @@ static int Activate( vlc_object_t * p_this )
             }
             if ( !i_size )
             {
-                return -1;
+                ;
+            }
+            else if ( !strncasecmp( p_peek, "[playlist]", sizeof("[playlist]") -1 ) )
+            {
+                i_type2 = TYPE_PLS;
             }
             else if ( !strncasecmp( p_peek, "<html>", sizeof("<html>") -1 ) )
             {
-                i_type = TYPE_HTML;
+                i_type2 = TYPE_HTML;
             }
             else if ( !strncasecmp( p_peek, "<asx", sizeof("<asx") -1 ) )
             {
-                i_type = TYPE_ASX;
+                i_type2 = TYPE_ASX;
             }
         }
     }
+    if ( !i_type && !i_type2 )
+    {
+        return -1;
+    }
+    if ( i_type  && !i_type2 )
+    {
+        i_type = TYPE_M3U;
+    }
+    else
+    {
+        i_type = i_type2;
+    }
+
     /* Allocate p_m3u */
     if( !( p_m3u = malloc( sizeof( demux_sys_t ) ) ) )
     {
@@ -162,15 +190,13 @@ static void Deactivate( vlc_object_t *p_this )
 }
 
 /*****************************************************************************
- * Demux: reads and demuxes data packets
- *****************************************************************************
- * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ * ProcessLine: read a "line" from the file and add any entries found
+ * to the playlist. Return number of items added ( 0 or 1 )
  *****************************************************************************/
-static void ProcessLine ( input_thread_t *p_input , demux_sys_t *p_m3u
-        , playlist_t *p_playlist , char psz_line[MAX_LINE] )
+static int ProcessLine ( input_thread_t *p_input , demux_sys_t *p_m3u
+        , playlist_t *p_playlist , char psz_line[MAX_LINE], int i_position )
 {
     char          *psz_bol, *psz_name;
-
     psz_bol = psz_line;
 
     /* Remove unnecessary tabs or spaces at the beginning of line */
@@ -183,7 +209,23 @@ static void ProcessLine ( input_thread_t *p_input , demux_sys_t *p_m3u
         /* Check for comment line */
         if( *psz_bol == '#' )
             /*line is comment or extended info, ignored for now */
-            return;
+            return 0;
+    }
+    else if ( p_m3u->i_type == TYPE_PLS )
+    {
+        /* We are dealing with .pls files from shoutcast
+         * We are looking for lines like "File1=http://..." */
+        if( !strncasecmp( psz_bol, "File", sizeof("File") - 1 ) )
+        {
+            psz_bol += sizeof("File") - 1;
+            psz_bol = strchr( psz_bol, '=' );
+            if ( !psz_bol ) return 0;
+            psz_bol++;
+        }
+        else
+        {
+            return 0;
+        }
     }
     else if ( p_m3u->i_type == TYPE_ASX )
     {
@@ -196,32 +238,36 @@ static void ProcessLine ( input_thread_t *p_input , demux_sys_t *p_m3u
                strncasecmp( psz_bol, "ref", sizeof("ref") - 1 ) )
             psz_bol++;
 
-        if( !*psz_bol ) return;
+        if( !*psz_bol ) return 0;
 
         while( *psz_bol &&
                strncasecmp( psz_bol, "href", sizeof("href") - 1 ) )
             psz_bol++;
 
-        if( !*psz_bol ) return;
+        if( !*psz_bol ) return 0;
 
         while( *psz_bol &&
                strncasecmp( psz_bol, "mms://",
                             sizeof("mms://") - 1 ) &&
+               strncasecmp( psz_bol, "mmsu://",
+                            sizeof("mmsu://") - 1 ) &&
+               strncasecmp( psz_bol, "mmst://",
+                            sizeof("mmst://") - 1 ) &&
                strncasecmp( psz_bol, "http://",
                             sizeof("http://") - 1 ) &&
                strncasecmp( psz_bol, "file://",
                             sizeof("file://") - 1 ) )
             psz_bol++;
 
-        if( !*psz_bol ) return;
+        if( !*psz_bol ) return 0;
 
         psz_eol = strchr( psz_bol, '"');
         if( !psz_eol )
-          return;
+          return 0;
 
         *psz_eol = '\0';
     }
-    else
+    else if ( p_m3u->i_type == TYPE_HTML )
     {
         /* We are dealing with a html file with embedded
          * video.  We are looking for "<param name="filename"
@@ -232,31 +278,36 @@ static void ProcessLine ( input_thread_t *p_input , demux_sys_t *p_m3u
                strncasecmp( psz_bol, "param", sizeof("param") - 1 ) )
             psz_bol++;
 
-        if( !*psz_bol ) return;
+        if( !*psz_bol ) return 0;
 
         while( *psz_bol &&
                strncasecmp( psz_bol, "filename", sizeof("filename") - 1 ) )
             psz_bol++;
 
-        if( !*psz_bol ) return;
+        if( !*psz_bol ) return 0;
 
         while( *psz_bol &&
                strncasecmp( psz_bol, "http://",
                             sizeof("http://") - 1 ) )
             psz_bol++;
 
-        if( !*psz_bol ) return;
+        if( !*psz_bol ) return 0;
 
         psz_eol = strchr( psz_bol, '"');
         if( !psz_eol )
-          return;
+          return 0;
 
         *psz_eol = '\0';
 
     }
+    else
+    {
+        msg_Warn( p_input, "unknown file type" );
+        return 0;
+    }
 
     /* empty line */
-    if ( !*psz_bol ) return;
+    if ( !*psz_bol ) return 0;
 
     /*
      * From now on, we know we've got a meaningful line
@@ -332,17 +383,24 @@ static void ProcessLine ( input_thread_t *p_input , demux_sys_t *p_m3u
     }
 
     playlist_Add( p_playlist, psz_name,
-                  PLAYLIST_APPEND, PLAYLIST_END );
+                  PLAYLIST_INSERT, i_position );
 
     free( psz_name );
+    return 1;
 }
 
+/*****************************************************************************
+ * Demux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
 static int Demux ( input_thread_t *p_input )
 {
     data_packet_t *p_data;
     char          *p_buf, psz_line[MAX_LINE], eol_tok;
     int           i_size, i_bufpos, i_linepos = 0;
     playlist_t    *p_playlist;
+    int           i_position;
     vlc_bool_t    b_discard = VLC_FALSE;
 
     demux_sys_t   *p_m3u = (demux_sys_t *)p_input->p_demux_data;
@@ -356,6 +414,7 @@ static int Demux ( input_thread_t *p_input )
     }
 
     p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
+    i_position = p_playlist->i_index + 1;
 
     /* Depending on wether we are dealing with an m3u/asf file, the end of
      * line token will be different */
@@ -402,7 +461,8 @@ static int Demux ( input_thread_t *p_input )
 
             psz_line[i_linepos] = '\0';
             i_linepos = 0;
-            ProcessLine ( p_input, p_m3u , p_playlist , psz_line );
+            i_position += ProcessLine ( p_input, p_m3u , p_playlist ,
+                                        psz_line, i_position );
         }
 
         input_DeletePacket( p_input->p_method_data, p_data );
@@ -412,7 +472,8 @@ static int Demux ( input_thread_t *p_input )
     {
         psz_line[i_linepos] = '\0';
         i_linepos = 0;
-        ProcessLine ( p_input, p_m3u , p_playlist , psz_line );
+        i_position += ProcessLine ( p_input, p_m3u , p_playlist , psz_line,
+                                    i_position );
     }
 
     vlc_object_release( p_playlist );