📄 asx.c
字号:
/***************************************************************************** * asx.c : ASX playlist format import ***************************************************************************** * Copyright (C) 2005-2006 the VideoLAN team * $Id: 08b0b25ea2d64edc567f00f372a54f64f5fdf07d $ * * Authors: Derk-Jan Hartman <hartman at videolan dot org> * * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//* See also: http://msdn.microsoft.com/library/en-us/wmplay10/mmp_sdk/windowsmediametafilereference.asp *//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_demux.h>#include <ctype.h>#include <vlc_charset.h>#include "playlist.h"#include "vlc_meta.h"struct demux_sys_t{ char *psz_prefix; char *psz_data; int64_t i_data_len; bool b_utf8; bool b_skip_ads;};/***************************************************************************** * Local prototypes *****************************************************************************/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, const char *psz_source_start, const char *psz_source_end ){ demux_sys_t *p_sys = p_demux->p_sys; unsigned len = psz_source_end - psz_source_start; 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 ) { memcpy (buf, psz_source_start, len); (*ppsz_string)[len] = '\0'; EnsureUTF8 (*ppsz_string); } else { /* Latin-1 -> UTF-8 */ for (unsigned i = 0; i < len; i++) { 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 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 ); // skip over possible leading empty lines and empty spaces p_peek = (uint8_t *)SkipBlanks((char *)p_peek, 6); if( POKE( p_peek, "<asx", 4 ) || demux_IsPathExtension( p_demux, ".asx" ) || demux_IsPathExtension( p_demux, ".wax" ) || demux_IsPathExtension( p_demux, ".wvx" ) || demux_IsForced( p_demux, "asx-open" ) ) { ; } else return VLC_EGENERIC; 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 = false; p_demux->p_sys->b_skip_ads = config_GetInt( p_demux, "playlist-skip-ads" ); return VLC_SUCCESS;}/***************************************************************************** * Deactivate: frees unused data *****************************************************************************/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; free( p_sys->psz_prefix ); free( p_sys->psz_data ); free( p_sys );}static int Demux( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; char *psz_parse = NULL; char *psz_backup = NULL; bool b_entry = false; INIT_PLAYLIST_STUFF; /* init txt */ if( p_sys->i_data_len < 0 ) { 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); /* 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_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 -1; } psz_parse = p_sys->psz_data; /* Find first element */ if( ( psz_parse = strcasestr( psz_parse, "<ASX" ) ) ) { /* ASX element */ char *psz_string = NULL; int i_strlen = 0; char *psz_base_asx = NULL; char *psz_title_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_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 && ( psz_parse = strcasestr( psz_parse, "<" ) ) ) { if( !strncasecmp( psz_parse, "<!--", 4 ) ) { /* this is a comment */ if( ( psz_parse = strcasestr( psz_parse, "-->" ) ) ) psz_parse+=3; else continue; } else if( !strncasecmp( psz_parse, "<PARAM ", 7 ) ) { bool b_encoding_flag = false; psz_parse = SkipBlanks(psz_parse+7, (unsigned)-1); if( !strncasecmp( psz_parse, "name", 4 ) ) { if( ( psz_parse = strcasestr( psz_parse, "\"" ) ) ) { psz_backup = ++psz_parse; if( ( psz_parse = strcasestr( psz_parse, "\"" ) ) ) { i_strlen = psz_parse-psz_backup; if( i_strlen < 1 ) continue; msg_Dbg( p_demux, "param name strlen: %d", i_strlen); psz_string = malloc( i_strlen *sizeof( char ) +1); memcpy( psz_string, psz_backup, i_strlen ); psz_string[i_strlen] = '\0'; msg_Dbg( p_demux, "param name: %s", psz_string); b_encoding_flag = !strcasecmp( psz_string, "encoding" ); free( psz_string ); } else continue; } else continue; } psz_parse++; if( !strncasecmp( psz_parse, "value", 5 ) ) { if( ( psz_parse = strcasestr( psz_parse, "\"" ) ) ) { psz_backup = ++psz_parse; if( ( psz_parse = strcasestr( psz_parse, "\"" ) ) ) { i_strlen = psz_parse-psz_backup; if( i_strlen < 1 ) continue; msg_Dbg( p_demux, "param value strlen: %d", i_strlen); psz_string = malloc( i_strlen *sizeof( char ) +1); memcpy( psz_string, psz_backup, i_strlen ); psz_string[i_strlen] = '\0'; msg_Dbg( p_demux, "param value: %s", psz_string); if( b_encoding_flag && !strcasecmp( psz_string, "utf-8" ) ) p_sys->b_utf8 = true; free( psz_string ); } else continue; } else continue; } if( ( psz_parse = strcasestr( psz_parse, "/>" ) ) ) psz_parse += 2; else continue; } else if( !strncasecmp( psz_parse, "<BANNER", 7 ) ) { /* We skip this element */ if( ( psz_parse = strcasestr( psz_parse, "</BANNER>" ) ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -