X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fplaylist%2Fm3u.c;h=3c45ad2acae01df2df1d80c35847211d2a67708c;hb=942cd8fe5d6d6c14198e275e64db635d21ce0ec9;hp=2fafb097e7e7b024c2deb972ed3df23760374026;hpb=ffdca9af740e111153ab385cf00e887c652e7b4c;p=vlc diff --git a/modules/demux/playlist/m3u.c b/modules/demux/playlist/m3u.c index 2fafb097e7..3c45ad2aca 100644 --- a/modules/demux/playlist/m3u.c +++ b/modules/demux/playlist/m3u.c @@ -1,11 +1,11 @@ /***************************************************************************** * m3u.c : M3U playlist format import ***************************************************************************** - * Copyright (C) 2004 VideoLAN - * $Id: m3u.c,v 1.3 2004/01/25 20:05:29 hartman Exp $ + * Copyright (C) 2004 the VideoLAN team + * $Id$ * - * Authors: Clément Stenac - * Authors: Sigmund Augdal + * Authors: Clément Stenac + * Sigmund Augdal Helberg * * 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 @@ -19,7 +19,7 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -28,7 +28,9 @@ #include /* malloc(), free() */ #include +#include #include +#include "charset.h" #include /* ENOMEM */ #include "playlist.h" @@ -43,50 +45,26 @@ struct demux_sys_t *****************************************************************************/ static int Demux( demux_t *p_demux); static int Control( demux_t *p_demux, int i_query, va_list args ); +static void parseEXTINF( char *psz_string, char **ppsz_artist, char **ppsz_name, int *pi_duration ); /***************************************************************************** * Import_M3U: main import function *****************************************************************************/ -int Import_M3U( vlc_object_t *p_this ) +int E_(Import_M3U)( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t *)p_this; - uint8_t *p_peek; - char *psz_ext; - - if( stream_Peek( p_demux->s , &p_peek, 7 ) < 7 ) - { - msg_Err( p_demux, "cannot peek" ); - return VLC_EGENERIC; - } - psz_ext = strrchr ( p_demux->psz_path, '.' ); + CHECK_PEEK( p_peek, 8 ); - if( !strncmp( p_peek, "#EXTM3U", 7 ) ) - { - ; - } - else if( ( psz_ext && !strcasecmp( psz_ext, ".m3u") ) || - ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "m3u") ) ) - { - ; - } - else - { - msg_Warn(p_demux, "m3u import module discarded"); + if(! ( POKE( p_peek, "#EXTM3U", 7 ) || POKE( p_peek, "RTSPtext", 8 ) || + isExtension( p_demux, ".m3u" ) || isExtension( p_demux, ".vlc" ) || + /* A .ram file can contain a single rtsp link */ + isExtension( p_demux, ".ram" ) || isExtension( p_demux, ".rm" ) || + isDemux( p_demux, "m3u" ) ) ) return VLC_EGENERIC; - - } - msg_Dbg( p_demux, "found valid M3U playlist file"); - 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 ); + STANDARD_DEMUX_INIT_MSG( "found valid M3U playlist" ); + p_demux->p_sys->psz_prefix = E_(FindPrefix)( p_demux ); return VLC_SUCCESS; } @@ -94,85 +72,131 @@ int Import_M3U( vlc_object_t *p_this ) /***************************************************************************** * Deactivate: frees unused data *****************************************************************************/ -void Close_M3U( vlc_object_t *p_this ) +void E_(Close_M3U)( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t *)p_this; - if( p_demux->p_sys->psz_prefix ) - { - free( p_demux->p_sys->psz_prefix ); - } + free( p_demux->p_sys->psz_prefix ); free( p_demux->p_sys ); } - static int Demux( demux_t *p_demux ) { - mtime_t i_duration = -1; - char *psz_name = NULL; - char *psz_line; - char *psz_parse; - char *psz_duration; - char *psz_mrl; - playlist_t *p_playlist; - int i_position; - - 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; - } + char *psz_line; + char *psz_name = NULL; + char *psz_artist = NULL; + int i_parsed_duration = 0; + mtime_t i_duration = -1; + const char**ppsz_options = NULL; + int i_options = 0, i; + vlc_bool_t b_cleanup = VLC_FALSE; + input_item_t *p_input; + + INIT_PLAYLIST_STUFF; - p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE; - i_position = p_playlist->i_index + 1; - while( ( psz_line = stream_ReadLine( p_demux->s ) ) ) + psz_line = stream_ReadLine( p_demux->s ); + while( psz_line ) { - if( *psz_line == '#' ) + char *psz_parse = psz_line; + + /* Skip leading tabs and spaces */ + while( *psz_parse == ' ' || *psz_parse == '\t' || + *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; + + if( *psz_parse == '#' ) { - /* parse extra info */ - psz_parse = psz_line; - while( *psz_parse && - strncasecmp( psz_parse, "EXTINF:", sizeof("EXTINF:") - 1 ) ) - psz_parse++; - if( *psz_parse ) + /* Parse extra info */ + + /* Skip leading tabs and spaces */ + while( *psz_parse == ' ' || *psz_parse == '\t' || + *psz_parse == '\n' || *psz_parse == '\r' || + *psz_parse == '#' ) psz_parse++; + + if( !*psz_parse ) goto error; + + if( !strncasecmp( psz_parse, "EXTINF:", sizeof("EXTINF:") -1 ) ) { + /* Extended info */ psz_parse += sizeof("EXTINF:") - 1; - while( *psz_parse == '\t' || *psz_parse == ' ' ) - psz_parse++; - psz_duration = psz_parse; - psz_parse = strchr( psz_parse, ',' ); - if ( psz_parse ) - { - *psz_parse = '\0'; - psz_parse++; - psz_name = strdup( psz_parse ); - i_duration = atoi( psz_duration ); - if( i_duration != -1 ) - { - i_duration *= 1000000; - } - } + parseEXTINF( psz_parse, &psz_artist, &psz_name, &i_parsed_duration ); + if ( i_parsed_duration >= 0 ) + i_duration = i_parsed_duration * 1000000; + if ( psz_name ) + psz_name = strdup( psz_name ); + if ( psz_artist ) + psz_artist = strdup( psz_artist ); + } + else if( !strncasecmp( psz_parse, "EXTVLCOPT:", + sizeof("EXTVLCOPT:") -1 ) ) + { + /* VLC Option */ + const char *psz_option; + psz_parse += sizeof("EXTVLCOPT:") -1; + if( !*psz_parse ) goto error; + + psz_option = strdup( psz_parse ); + if( psz_option ) + INSERT_ELEM( ppsz_options, i_options, i_options, + psz_option ); } } - else + else if( !strncasecmp( psz_parse, "RTSPtext", sizeof("RTSPtext") -1 ) ) { - psz_mrl = ProcessMRL( psz_line, p_demux->p_sys->psz_prefix ); - playlist_Add( p_playlist, psz_mrl, psz_name, - PLAYLIST_INSERT, i_position ); - playlist_SetDuration( p_playlist, i_position, i_duration ); - free( psz_mrl ); - i_position++; - i_duration = -1; - if( psz_name ) + ;/* special case to handle QuickTime RTSPtext redirect files */ + } + else if( *psz_parse ) + { + char *psz_mrl; + if( !psz_name || !*psz_name ) { - free( psz_name ); - psz_name = NULL; + /* Use filename as name for relative entries */ + psz_name = strdup( psz_parse ); } + + psz_mrl = E_(ProcessMRL)( psz_parse, p_demux->p_sys->psz_prefix ); + + b_cleanup = VLC_TRUE; + if( !psz_mrl ) goto error; + + EnsureUTF8( psz_name ); + EnsureUTF8( psz_mrl ); + + for( i = 0; i< i_options; i++ ) + EnsureUTF8( (char*)ppsz_options[i] ); + + p_input = input_ItemNewExt( p_playlist, psz_mrl, psz_name, + i_options, ppsz_options, i_duration ); + if ( psz_artist && *psz_artist ) + input_ItemAddInfo( p_input, _(VLC_META_INFO_CAT), + _(VLC_META_ARTIST), "%s", psz_artist ); + playlist_BothAddInput( p_playlist, p_input, p_item_in_category, + PLAYLIST_APPEND, PLAYLIST_END ); + free( psz_mrl ); + } + + error: + + /* Fetch another line */ + free( psz_line ); + psz_line = stream_ReadLine( p_demux->s ); + if( !psz_line ) b_cleanup = VLC_TRUE; + + if( b_cleanup ) + { + /* Cleanup state */ + while( i_options-- ) free( (char*)ppsz_options[i_options] ); + if( ppsz_options ) free( ppsz_options ); + ppsz_options = NULL; i_options = 0; + if( psz_name ) free( psz_name ); + psz_name = NULL; + if ( psz_artist ) free( psz_artist ); + psz_artist = NULL; + i_parsed_duration = 0; + i_duration = -1; + + b_cleanup = VLC_FALSE; } - free( psz_line); } - vlc_object_release( p_playlist ); + HANDLE_PLAY_AND_RELEASE; return VLC_SUCCESS; } @@ -180,3 +204,71 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) { return VLC_EGENERIC; } + +static void parseEXTINF(char *psz_string, char **ppsz_artist, + char **ppsz_name, int *pi_duration) +{ + char *end = NULL; + char *psz_item = NULL; + + end = psz_string + strlen( psz_string ); + + /* ignore whitespaces */ + for (; psz_string < end && ( *psz_string == '\t' || *psz_string == ' ' ); + psz_string++ ); + + /* duration: read to next comma */ + psz_item = psz_string; + psz_string = strchr( psz_string, ',' ); + if ( psz_string ) + { + *psz_string = '\0'; + *pi_duration = atoi( psz_item ); + } + else + { + return; + } + + if ( psz_string < end ) /* continue parsing if possible */ + psz_string++; + + /* analyse the remaining string */ + psz_item = strstr( psz_string, " - " ); + + /* here we have the 0.8.2+ format with artist */ + if ( psz_item ) + { + /* *** "EXTINF:time,artist - name" */ + *psz_item = '\0'; + *ppsz_artist = psz_string; + *ppsz_name = psz_item + 3; /* points directly after ' - ' */ + return; + } + + /* reaching this point means: 0.8.1- with artist or something without artist */ + if ( *psz_string == ',' ) + { + /* *** "EXTINF:time,,name" */ + psz_string++; + *ppsz_name = psz_string; + return; + } + + psz_item = psz_string; + psz_string = strchr( psz_string, ',' ); + if ( psz_string ) + { + /* *** "EXTINF:time,artist,name" */ + *psz_string = '\0'; + *ppsz_artist = psz_item; + *ppsz_name = psz_string+1; + } + else + { + /* *** "EXTINF:time,name" */ + *ppsz_name = psz_item; + } + return; +} +