📄 http.c
字号:
} /* else probably Ogg Vorbis */ } else if( !strcasecmp( p_access->psz_access, "unsv" ) && p_sys->psz_mime && !strcasecmp( p_sys->psz_mime, "misc/ultravox" ) ) { /* Grrrr! detect ultravox server and force NSV demuxer */ p_access->psz_demux = strdup( "nsv" ); } else if( p_sys->psz_mime && !strncasecmp( p_sys->psz_mime, "application/xspf+xml", 20 ) && ( memchr( " ;\t", p_sys->psz_mime[20], 4 ) != NULL ) ) p_access->psz_demux = strdup( "xspf-open" ); if( p_sys->b_reconnect ) msg_Dbg( p_access, "auto re-connect enabled" ); /* PTS delay */ var_Create( p_access, "http-caching", VLC_VAR_INTEGER |VLC_VAR_DOINHERIT ); return VLC_SUCCESS;error: vlc_UrlClean( &p_sys->url ); vlc_UrlClean( &p_sys->proxy ); if( p_sys->psz_mime ) free( p_sys->psz_mime ); if( p_sys->psz_pragma ) free( p_sys->psz_pragma ); if( p_sys->psz_location ) free( p_sys->psz_location ); if( p_sys->psz_user_agent ) free( p_sys->psz_user_agent ); Disconnect( p_access ); free( p_sys ); return VLC_EGENERIC;}/***************************************************************************** * Close: *****************************************************************************/static void Close( vlc_object_t *p_this ){ access_t *p_access = (access_t*)p_this; access_sys_t *p_sys = p_access->p_sys; vlc_UrlClean( &p_sys->url ); vlc_UrlClean( &p_sys->proxy ); if( p_sys->psz_mime ) free( p_sys->psz_mime ); if( p_sys->psz_pragma ) free( p_sys->psz_pragma ); if( p_sys->psz_location ) free( p_sys->psz_location ); if( p_sys->psz_icy_name ) free( p_sys->psz_icy_name ); if( p_sys->psz_icy_genre ) free( p_sys->psz_icy_genre ); if( p_sys->psz_icy_title ) free( p_sys->psz_icy_title ); if( p_sys->psz_user_agent ) free( p_sys->psz_user_agent ); Disconnect( p_access ); free( p_sys );}/***************************************************************************** * Read: Read up to i_len bytes from the http connection and place in * p_buffer. Return the actual number of bytes read *****************************************************************************/static int ReadICYMeta( access_t *p_access );static int Read( access_t *p_access, uint8_t *p_buffer, int i_len ){ access_sys_t *p_sys = p_access->p_sys; int i_read; if( p_sys->fd < 0 ) { p_access->info.b_eof = VLC_TRUE; return 0; } if( p_access->info.i_size > 0 && i_len + p_access->info.i_pos > p_access->info.i_size ) { if( ( i_len = p_access->info.i_size - p_access->info.i_pos ) == 0 ) { p_access->info.b_eof = VLC_TRUE; return 0; } } if( p_sys->b_chunked ) { if( p_sys->i_chunk < 0 ) { p_access->info.b_eof = VLC_TRUE; return 0; } if( p_sys->i_chunk <= 0 ) { char *psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, p_sys->p_vs ); /* read the chunk header */ if( psz == NULL ) { /* fatal error - end of file */ msg_Dbg( p_access, "failed reading chunk-header line" ); return 0; } p_sys->i_chunk = strtoll( psz, NULL, 16 ); free( psz ); if( p_sys->i_chunk <= 0 ) /* eof */ { p_sys->i_chunk = -1; p_access->info.b_eof = VLC_TRUE; return 0; } } if( i_len > p_sys->i_chunk ) { i_len = p_sys->i_chunk; } } if( p_sys->b_continuous && i_len > p_sys->i_remaining ) { /* Only ask for the remaining length */ int i_new_len = p_sys->i_remaining; if( i_new_len == 0 ) { Request( p_access, 0 ); i_read = Read( p_access, p_buffer, i_len ); return i_read; } i_len = i_new_len; } if( p_sys->i_icy_meta > 0 && p_access->info.i_pos > 0 ) { int64_t i_next = p_sys->i_icy_meta - p_access->info.i_pos % p_sys->i_icy_meta; if( i_next == p_sys->i_icy_meta ) { if( ReadICYMeta( p_access ) ) { p_access->info.b_eof = VLC_TRUE; return -1; } } if( i_len > i_next ) i_len = i_next; } i_read = net_Read( p_access, p_sys->fd, p_sys->p_vs, p_buffer, i_len, VLC_FALSE ); if( i_read > 0 ) { p_access->info.i_pos += i_read; if( p_sys->b_chunked ) { p_sys->i_chunk -= i_read; if( p_sys->i_chunk <= 0 ) { /* read the empty line */ char *psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, p_sys->p_vs ); if( psz ) free( psz ); } } } else if( i_read == 0 ) { /* * I very much doubt that this will work. * If i_read == 0, the connection *IS* dead, so the only * sensible thing to do is Disconnect() and then retry. * Otherwise, I got recv() completely wrong. -- Courmisch */ if( p_sys->b_continuous ) { Request( p_access, 0 ); p_sys->b_continuous = VLC_FALSE; i_read = Read( p_access, p_buffer, i_len ); p_sys->b_continuous = VLC_TRUE; } Disconnect( p_access ); if( p_sys->b_reconnect ) { msg_Dbg( p_access, "got disconnected, trying to reconnect" ); if( Connect( p_access, p_access->info.i_pos ) ) { msg_Dbg( p_access, "reconnection failed" ); } else { p_sys->b_reconnect = VLC_FALSE; i_read = Read( p_access, p_buffer, i_len ); p_sys->b_reconnect = VLC_TRUE; } } if( i_read == 0 ) p_access->info.b_eof = VLC_TRUE; } if( p_sys->b_continuous ) { p_sys->i_remaining -= i_read; } return i_read;}static int ReadICYMeta( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; uint8_t buffer; char *p, *psz_meta; int i_read; /* Read meta data length */ i_read = net_Read( p_access, p_sys->fd, p_sys->p_vs, &buffer, 1, VLC_TRUE ); if( i_read <= 0 ) return VLC_EGENERIC; if( buffer == 0 ) return VLC_SUCCESS; i_read = buffer << 4; /* msg_Dbg( p_access, "ICY meta size=%u", i_read); */ psz_meta = malloc( i_read + 1 ); if( net_Read( p_access, p_sys->fd, p_sys->p_vs, (uint8_t *)psz_meta, i_read, VLC_TRUE ) != i_read ) return VLC_EGENERIC; psz_meta[i_read] = '\0'; /* Just in case */ /* msg_Dbg( p_access, "icy-meta=%s", psz_meta ); */ /* Now parse the meta */ /* Look for StreamTitle= */ p = strcasestr( (char *)psz_meta, "StreamTitle=" ); if( p ) { p += strlen( "StreamTitle=" ); if( *p == '\'' || *p == '"' ) { char closing[] = { p[0], ';', '\0' }; char *psz = strstr( &p[1], closing ); if( !psz ) psz = strchr( &p[1], ';' ); if( psz ) *psz = '\0'; } else { char *psz = strchr( &p[1], ';' ); if( psz ) *psz = '\0'; } if( !p_sys->psz_icy_title || strcmp( p_sys->psz_icy_title, &p[1] ) ) { if( p_sys->psz_icy_title ) free( p_sys->psz_icy_title ); p_sys->psz_icy_title = strdup( &p[1] ); p_access->info.i_update |= INPUT_UPDATE_META; msg_Dbg( p_access, "New Title=%s", p_sys->psz_icy_title ); } } free( psz_meta ); return VLC_SUCCESS;}/***************************************************************************** * Seek: close and re-open a connection at the right place *****************************************************************************/static int Seek( access_t *p_access, int64_t i_pos ){ msg_Dbg( p_access, "trying to seek to "I64Fd, i_pos ); Disconnect( p_access ); if( Connect( p_access, i_pos ) ) { msg_Err( p_access, "seek failed" ); p_access->info.b_eof = VLC_TRUE; return VLC_EGENERIC; } return VLC_SUCCESS;}/***************************************************************************** * Control: *****************************************************************************/static int Control( access_t *p_access, int i_query, va_list args ){ access_sys_t *p_sys = p_access->p_sys; vlc_bool_t *pb_bool; int *pi_int; int64_t *pi_64; vlc_meta_t **pp_meta; switch( i_query ) { /* */ case ACCESS_CAN_SEEK: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); *pb_bool = p_sys->b_seekable; break; case ACCESS_CAN_FASTSEEK: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); *pb_bool = VLC_FALSE; break; case ACCESS_CAN_PAUSE: case ACCESS_CAN_CONTROL_PACE: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );#if 0 /* Disable for now until we have a clock synchro algo * which works with something else than MPEG over UDP */ *pb_bool = p_sys->b_pace_control;#endif *pb_bool = VLC_TRUE; break; /* */ case ACCESS_GET_MTU: pi_int = (int*)va_arg( args, int * ); *pi_int = 0; break; case ACCESS_GET_PTS_DELAY: pi_64 = (int64_t*)va_arg( args, int64_t * ); *pi_64 = (int64_t)var_GetInteger( p_access, "http-caching" ) * 1000; break; /* */ case ACCESS_SET_PAUSE_STATE: break; case ACCESS_GET_META: pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); *pp_meta = vlc_meta_New(); if( p_sys->psz_icy_name ) vlc_meta_Add( *pp_meta, VLC_META_TITLE, p_sys->psz_icy_name ); if( p_sys->psz_icy_genre ) vlc_meta_Add( *pp_meta, VLC_META_GENRE, p_sys->psz_icy_genre ); if( p_sys->psz_icy_title ) vlc_meta_Add( *pp_meta, VLC_META_NOW_PLAYING, p_sys->psz_icy_title ); break; case ACCESS_GET_TITLE_INFO: case ACCESS_SET_TITLE: case ACCESS_SET_SEEKPOINT: case ACCESS_SET_PRIVATE_ID_STATE: return VLC_EGENERIC; default: msg_Warn( p_access, "unimplemented query in control" ); return VLC_EGENERIC; } return VLC_SUCCESS;}/***************************************************************************** * Connect: *****************************************************************************/static int Connect( access_t *p_access, int64_t i_tell ){ access_sys_t *p_sys = p_access->p_sys; vlc_url_t srv = p_sys->b_proxy ? p_sys->proxy : p_sys->url; /* Clean info */ if( p_sys->psz_location ) free( p_sys->psz_location ); if( p_sys->psz_mime ) free( p_sys->psz_mime ); if( p_sys->psz_pragma ) free( p_sys->psz_pragma ); if( p_sys->psz_icy_genre ) free( p_sys->psz_icy_genre ); if( p_sys->psz_icy_name ) free( p_sys->psz_icy_name ); if( p_sys->psz_icy_title ) free( p_sys->psz_icy_title ); p_sys->psz_location = NULL; p_sys->psz_mime = NULL; p_sys->psz_pragma = NULL; p_sys->b_mms = VLC_FALSE; p_sys->b_chunked = VLC_FALSE; p_sys->i_chunk = 0; p_sys->i_icy_meta = 0; p_sys->psz_icy_name = NULL; p_sys->psz_icy_genre = NULL; p_sys->psz_icy_title = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -