X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fplaylist%2Fasx.c;h=030c3410cd6d40b848021df56d32bd323b5b1d7f;hb=d3081ffff71448139a319259179e365846b711a2;hp=4e73551efb2120938b68cd5b23aca6c1c5f9890b;hpb=f0ddd6157663426507a2ac18ef1341e69fbed2bf;p=vlc diff --git a/modules/demux/playlist/asx.c b/modules/demux/playlist/asx.c index 4e73551efb..030c3410cd 100644 --- a/modules/demux/playlist/asx.c +++ b/modules/demux/playlist/asx.c @@ -1,7 +1,7 @@ /***************************************************************************** * asx.c : ASX playlist format import ***************************************************************************** - * Copyright (C) 2005 the VideoLAN team + * Copyright (C) 2005-2006 the VideoLAN team * $Id$ * * Authors: Derk-Jan Hartman @@ -27,24 +27,25 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* malloc(), free() */ -#include /* isspace() */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include -#include +#include +#include -#include /* ENOMEM */ +#include +#include #include "playlist.h" #include "vlc_meta.h" -#define FREE( p ) if( p ) { free( p ); (p) = NULL; } - struct demux_sys_t { char *psz_prefix; char *psz_data; int64_t i_data_len; - vlc_bool_t b_utf8; + bool b_utf8; + bool b_skip_ads; }; /***************************************************************************** @@ -53,74 +54,175 @@ 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 int StoreString( demux_t *p_demux, char **ppsz_string, char *psz_source_start, char *psz_source_end ) +static int StoreString( demux_t *p_demux, char **ppsz_string, + const char *psz_source_start, + const char *psz_source_end ) { demux_sys_t *p_sys = p_demux->p_sys; - int i_strlen = psz_source_end-psz_source_start; - if( i_strlen < 1 ) - return VLC_EGENERIC; + unsigned len = psz_source_end - psz_source_start; - if( *ppsz_string ) free( *ppsz_string ); - *ppsz_string = malloc( i_strlen*sizeof( char ) +1); - memcpy( *ppsz_string, psz_source_start, i_strlen ); - (*ppsz_string)[i_strlen] = '\0'; + free( *ppsz_string ); + + char *buf = *ppsz_string = malloc ((len * (1 + !p_sys->b_utf8)) + 1); + if (buf == NULL) + return VLC_ENOMEM; if( p_sys->b_utf8 ) - EnsureUTF8( *ppsz_string ); + { + memcpy (buf, psz_source_start, len); + (*ppsz_string)[len] = '\0'; + EnsureUTF8 (*ppsz_string); + } else { - char *psz_temp; - psz_temp = FromLocaleDup( *ppsz_string ); - if( psz_temp ) + /* Latin-1 -> UTF-8 */ + for (unsigned i = 0; i < len; i++) { - free( *ppsz_string ); - *ppsz_string = psz_temp; - } else EnsureUTF8( *ppsz_string ); + unsigned char c = psz_source_start[i]; + if (c & 0x80) + { + *buf++ = 0xc0 | (c >> 6); + *buf++ = 0x80 | (c & 0x3f); + } + else + *buf++ = c; + } + *buf++ = '\0'; + + buf = *ppsz_string = realloc (*ppsz_string, buf - *ppsz_string); } return VLC_SUCCESS; } +static char *SkipBlanks(char *s, size_t i_strlen ) +{ + while( i_strlen > 0 ) { + switch( *s ) + { + case ' ': + case '\t': + case '\r': + case '\n': + --i_strlen; + ++s; + break; + default: + i_strlen = 0; + } + } + return s; +} + +static int ParseTime(char *s, size_t i_strlen) +{ + // need to parse hour:minutes:sec.fraction string + int result = 0; + int val; + const char *end = s + i_strlen; + // skip leading spaces if any + s = SkipBlanks(s, i_strlen); + + val = 0; + while( (s < end) && isdigit(*s) ) + { + int newval = val*10 + (*s - '0'); + if( newval < val ) + { + // overflow + val = 0; + break; + } + val = newval; + ++s; + } + result = val; + s = SkipBlanks(s, end-s); + if( *s == ':' ) + { + ++s; + s = SkipBlanks(s, end-s); + result = result * 60; + val = 0; + while( (s < end) && isdigit(*s) ) + { + int newval = val*10 + (*s - '0'); + if( newval < val ) + { + // overflow + val = 0; + break; + } + val = newval; + ++s; + } + result += val; + s = SkipBlanks(s, end-s); + if( *s == ':' ) + { + ++s; + s = SkipBlanks(s, end-s); + result = result * 60; + val = 0; + while( (s < end) && isdigit(*s) ) + { + int newval = val*10 + (*s - '0'); + if( newval < val ) + { + // overflow + val = 0; + break; + } + val = newval; + ++s; + } + result += val; + // TODO: one day, we may need to parse fraction for sub-second resolution + } + } + return result; +} + /***************************************************************************** * Import_ASX: main import function *****************************************************************************/ -int E_(Import_ASX)( vlc_object_t *p_this ) +int Import_ASX( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t *)p_this; + const uint8_t *p_peek; + CHECK_PEEK( p_peek, 10 ); - char *psz_ext; - - psz_ext = strrchr ( p_demux->psz_path, '.' ); + // skip over possible leading empty lines and empty spaces + p_peek = (uint8_t *)SkipBlanks((char *)p_peek, 6); - if( ( psz_ext && !strcasecmp( psz_ext, ".asx") ) || - ( psz_ext && !strcasecmp( psz_ext, ".wax") ) || - ( psz_ext && !strcasecmp( psz_ext, ".wvx") ) || - isDemux( p_demux, "asx-open" ) ) + if( POKE( p_peek, "p_sys->psz_prefix = E_(FindPrefix)( p_demux ); + + STANDARD_DEMUX_INIT_MSG( "found valid ASX playlist" ); + p_demux->p_sys->psz_prefix = FindPrefix( p_demux ); p_demux->p_sys->psz_data = NULL; p_demux->p_sys->i_data_len = -1; - p_demux->p_sys->b_utf8 = VLC_FALSE; - + p_demux->p_sys->b_utf8 = false; + p_demux->p_sys->b_skip_ads = config_GetInt( p_demux, "playlist-skip-ads" ); + return VLC_SUCCESS; } /***************************************************************************** * Deactivate: frees unused data *****************************************************************************/ -void E_(Close_ASX)( vlc_object_t *p_this ) +void Close_ASX( 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->psz_data ) free( p_sys->psz_data ); + free( p_sys->psz_prefix ); + free( p_sys->psz_data ); free( p_sys ); } @@ -129,8 +231,7 @@ static int Demux( demux_t *p_demux ) demux_sys_t *p_sys = p_demux->p_sys; char *psz_parse = NULL; char *psz_backup = NULL; - vlc_bool_t b_entry = VLC_FALSE; - + bool b_entry = false; INIT_PLAYLIST_STUFF; /* init txt */ @@ -139,21 +240,21 @@ static int Demux( demux_t *p_demux ) int64_t i_pos = 0; p_sys->i_data_len = stream_Size( p_demux->s ) +1; /* This is a cheat to prevent unnecessary realloc */ if( p_sys->i_data_len <= 0 && p_sys->i_data_len < 16384 ) p_sys->i_data_len = 1024; - p_sys->psz_data = malloc( p_sys->i_data_len * sizeof(char) +1); - + p_sys->psz_data = malloc( p_sys->i_data_len +1); + /* load the complete file */ for( ;; ) { int i_read = stream_Read( p_demux->s, &p_sys->psz_data[i_pos], p_sys->i_data_len - i_pos ); - p_sys->psz_data[i_read] = '\0'; - + p_sys->psz_data[i_pos + i_read] = '\0'; + if( i_read < p_sys->i_data_len - i_pos ) break; /* Done */ - + i_pos += i_read; p_sys->i_data_len += 1024; p_sys->psz_data = realloc( p_sys->psz_data, p_sys->i_data_len * sizeof( char * ) +1 ); } - if( p_sys->i_data_len <= 0 ) return VLC_EGENERIC; + if( p_sys->i_data_len <= 0 ) return -1; } psz_parse = p_sys->psz_data; @@ -166,22 +267,27 @@ static int Demux( demux_t *p_demux ) char *psz_base_asx = NULL; char *psz_title_asx = NULL; - char *psz_author_asx = NULL; + char *psz_artist_asx = NULL; char *psz_copyright_asx = NULL; char *psz_moreinfo_asx = NULL; char *psz_abstract_asx = NULL; - + char *psz_base_entry = NULL; char *psz_title_entry = NULL; - char *psz_author_entry = NULL; + char *psz_artist_entry = NULL; char *psz_copyright_entry = NULL; char *psz_moreinfo_entry = NULL; char *psz_abstract_entry = NULL; int i_entry_count = 0; - + bool b_skip_entry = false; + + char *psz_href = NULL; + int i_starttime = 0; + int i_duration = 0; + psz_parse = strcasestr( psz_parse, ">" ); - while( ( psz_parse = strcasestr( psz_parse, "<" ) ) && psz_parse && *psz_parse ) + while( psz_parse && ( psz_parse = strcasestr( psz_parse, "<" ) ) ) { if( !strncasecmp( psz_parse, "