X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Finput.c;h=3528231c12324546be1317d0147a6568b4d2cff7;hb=638dac1c79e39c5a0f46f6d51ba85fc4055bbf94;hp=3190b3d081e40f54c0972e9dde69eda5cab6229c;hpb=5ea5076a0b3a0664acac2640d34d2bf9dbce1021;p=vlc diff --git a/src/input/input.c b/src/input/input.c index 3190b3d081..3528231c12 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -3,8 +3,8 @@ * Read an MPEG2 stream, demultiplex and parse it before sending it to * decoders. ***************************************************************************** - * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: input.c,v 1.156 2001/11/15 18:50:49 sam Exp $ + * Copyright (C) 1998-2001 VideoLAN + * $Id: input.c,v 1.178 2002/02/26 17:22:12 xav Exp $ * * Authors: Christophe Massiot * @@ -26,13 +26,13 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include "defs.h" - #include #include #include #include +#include + #ifdef HAVE_UNISTD_H # include #elif defined( _MSC_VER ) && defined( _WIN32 ) @@ -48,6 +48,7 @@ #ifdef WIN32 # include +# include #elif !defined( SYS_BEOS ) && !defined( SYS_NTO ) # include /* hostent ... */ # include @@ -61,15 +62,8 @@ # include #endif -#include "config.h" -#include "common.h" -#include "threads.h" -#include "mtime.h" -#include "tests.h" #include "netutils.h" -#include "modules.h" -#include "intf_msg.h" #include "intf_playlist.h" #include "stream_control.h" @@ -79,12 +73,10 @@ #include "interface.h" -#include "main.h" - /***************************************************************************** * Local prototypes *****************************************************************************/ -static void RunThread ( input_thread_t *p_input ); +static int RunThread ( input_thread_t *p_input ); static int InitThread ( input_thread_t *p_input ); static void ErrorThread ( input_thread_t *p_input ); static void CloseThread ( input_thread_t *p_input ); @@ -100,6 +92,41 @@ static void HTTPOpen ( input_thread_t *p_input ); static void NetworkClose ( input_thread_t *p_input ); #endif +/***************************************************************************** + * input_InitBank: initialize the input bank. + *****************************************************************************/ +void input_InitBank ( void ) +{ + p_input_bank->i_count = 0; + + /* XXX: Workaround for old interface modules */ + p_input_bank->pp_input[0] = NULL; + + vlc_mutex_init( &p_input_bank->lock ); +} + +/***************************************************************************** + * input_EndBank: empty the input bank. + ***************************************************************************** + * This function ends all unused inputs and empties the bank in + * case of success. + *****************************************************************************/ +void input_EndBank ( void ) +{ + int i_input; + + /* Ask all remaining video outputs to die */ + for( i_input = 0; i_input < p_input_bank->i_count; i_input++ ) + { + input_StopThread( + p_input_bank->pp_input[ i_input ], NULL ); + input_DestroyThread( + p_input_bank->pp_input[ i_input ] ); + } + + vlc_mutex_destroy( &p_input_bank->lock ); +} + /***************************************************************************** * input_CreateThread: creates a new input thread ***************************************************************************** @@ -111,7 +138,6 @@ static void NetworkClose ( input_thread_t *p_input ); input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) { input_thread_t * p_input; /* thread descriptor */ - int i_status; /* thread status */ /* Allocate descriptor */ p_input = (input_thread_t *)malloc( sizeof(input_thread_t) ); @@ -122,22 +148,30 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) return( NULL ); } - /* Packets read once */ - p_input->i_read_once = INPUT_READ_ONCE; - /* Initialize thread properties */ - p_input->b_die = 0; - p_input->b_error = 0; - p_input->b_eof = 0; + p_input->b_die = 0; + p_input->b_error = 0; + p_input->b_eof = 0; /* Set target */ - p_input->p_source = p_item->psz_name; + p_input->p_source = p_item->psz_name; + + /* Set status */ + p_input->i_status = THREAD_CREATE; + + /* Initialize statistics */ + p_input->c_loops = 0; + p_input->stream.c_packets_read = 0; + p_input->stream.c_packets_trashed = 0; + p_input->p_stream = NULL; - /* I have never understood that stuff --Meuuh */ - p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status; - *p_input->pi_status = THREAD_CREATE; + /* Set locks. */ + vlc_mutex_init( &p_input->stream.stream_lock ); + vlc_cond_init( &p_input->stream.stream_wait ); + vlc_mutex_init( &p_input->stream.control.control_lock ); /* Initialize stream description */ + p_input->stream.b_changed = 0; p_input->stream.i_es_number = 0; p_input->stream.i_selected_es_number = 0; p_input->stream.i_pgrm_number = 0; @@ -145,12 +179,18 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) p_input->stream.b_new_mute = MUTE_NO_CHANGE; p_input->stream.i_mux_rate = 0; - /* no stream, no area */ + /* no stream, no program, no area, no es */ + p_input->stream.p_new_program = NULL; + p_input->stream.i_area_nb = 0; p_input->stream.pp_areas = NULL; p_input->stream.p_selected_area = NULL; p_input->stream.p_new_area = NULL; + p_input->stream.pp_selected_es = NULL; + p_input->stream.p_removed_es = NULL; + p_input->stream.p_newly_selected_es = NULL; + /* By default there is one area in a stream */ input_AddArea( p_input ); p_input->stream.p_selected_area = p_input->stream.pp_areas[0]; @@ -159,16 +199,15 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) p_input->stream.control.i_status = PLAYING_S; p_input->stream.control.i_rate = DEFAULT_RATE; p_input->stream.control.b_mute = 0; - p_input->stream.control.b_grayscale = main_GetIntVariable( - VOUT_GRAYSCALE_VAR, VOUT_GRAYSCALE_DEFAULT ); - p_input->stream.control.i_smp = main_GetIntVariable( - VDEC_SMP_VAR, VDEC_SMP_DEFAULT ); + p_input->stream.control.b_grayscale = config_GetIntVariable( + VOUT_GRAYSCALE_VAR ); + p_input->stream.control.i_smp = config_GetIntVariable( VDEC_SMP_VAR ); intf_WarnMsg( 1, "input: playlist item `%s'", p_input->p_source ); /* Create thread. */ - if( vlc_thread_create( &p_input->thread_id, "input", (void *) RunThread, - (void *) p_input ) ) + if( vlc_thread_create( &p_input->thread_id, "input", + (vlc_thread_func_t)RunThread, (void *) p_input ) ) { intf_ErrMsg( "input error: can't create input thread (%s)", strerror(errno) ); @@ -176,6 +215,7 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) return( NULL ); } +#if 0 /* If status is NULL, wait until the thread is created */ if( pi_status == NULL ) { @@ -184,36 +224,30 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) msleep( THREAD_SLEEP ); } while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR) && (i_status != THREAD_FATAL) ); - if( i_status != THREAD_READY ) - { - return( NULL ); - } } +#endif + return( p_input ); } /***************************************************************************** - * input_DestroyThread: mark an input thread as zombie + * input_StopThread: mark an input thread as zombie ***************************************************************************** * This function should not return until the thread is effectively cancelled. *****************************************************************************/ -void input_DestroyThread( input_thread_t *p_input, int *pi_status ) +void input_StopThread( input_thread_t *p_input, int *pi_status ) { - int i_status; /* thread status */ - - /* Set status */ - p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status; - *p_input->pi_status = THREAD_DESTROY; + /* Make the thread exit from a possible vlc_cond_wait() */ + vlc_mutex_lock( &p_input->stream.stream_lock ); /* Request thread destruction */ p_input->b_die = 1; - /* Make the thread exit of an eventual vlc_cond_wait() */ - vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_cond_signal( &p_input->stream.stream_wait ); vlc_mutex_unlock( &p_input->stream.stream_lock ); /* If status is NULL, wait until thread has been destroyed */ +#if 0 if( pi_status == NULL ) { do @@ -222,6 +256,26 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status ) } while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR) && (i_status != THREAD_FATAL) ); } +#endif +} + +/***************************************************************************** + * input_DestroyThread: mark an input thread as zombie + ***************************************************************************** + * This function should not return until the thread is effectively cancelled. + *****************************************************************************/ +void input_DestroyThread( input_thread_t *p_input ) +{ + /* Join the thread */ + vlc_thread_join( p_input->thread_id ); + + /* Destroy Mutex locks */ + vlc_mutex_destroy( &p_input->stream.control.control_lock ); + vlc_cond_destroy( &p_input->stream.stream_wait ); + vlc_mutex_destroy( &p_input->stream.stream_lock ); + + /* Free input structure */ + free( p_input ); } /***************************************************************************** @@ -229,41 +283,57 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status ) ***************************************************************************** * Thread in charge of processing the network packets and demultiplexing. *****************************************************************************/ -static void RunThread( input_thread_t *p_input ) +static int RunThread( input_thread_t *p_input ) { - int i_error, i; - data_packet_t ** pp_packets; - if( InitThread( p_input ) ) { /* If we failed, wait before we are killed, and exit */ - *p_input->pi_status = THREAD_ERROR; + p_input->i_status = THREAD_ERROR; p_input->b_error = 1; ErrorThread( p_input ); DestroyThread( p_input ); - return; + return 0; } - /* initialization is completed */ + p_input->i_status = THREAD_READY; + + /* initialization is complete */ vlc_mutex_lock( &p_input->stream.stream_lock ); p_input->stream.b_changed = 1; vlc_mutex_unlock( &p_input->stream.stream_lock ); - pp_packets = (data_packet_t **) malloc( p_input->i_read_once * - sizeof( data_packet_t * ) ); - if( pp_packets == NULL ) - { - intf_ErrMsg( "input error: out of memory" ); - free( pp_packets ); - p_input->b_error = 1; - } - while( !p_input->b_die && !p_input->b_error && !p_input->b_eof ) { + data_packet_t * p_data; + int i_count, i; + p_input->c_loops++; vlc_mutex_lock( &p_input->stream.stream_lock ); + if( p_input->stream.p_new_program ) + { + if( p_input->pf_set_program != NULL ) + { + + p_input->pf_set_program( p_input, + p_input->stream.p_new_program ); + + for( i = 0; i < p_input->stream.i_pgrm_number; i++ ) + { + pgrm_descriptor_t * p_pgrm + = p_input->stream.pp_programs[i]; + /* Escape all decoders for the stream discontinuity they + * will encounter. */ + input_EscapeDiscontinuity( p_input, p_pgrm ); + + /* Reinitialize synchro. */ + p_pgrm->i_synchro_state = SYNCHRO_REINIT; + } + } + p_input->stream.p_new_program = NULL; + } + if( p_input->stream.p_new_area ) { if( p_input->stream.b_seekable && p_input->pf_set_area != NULL ) @@ -336,33 +406,33 @@ static void RunThread( input_thread_t *p_input ) vlc_mutex_unlock( &p_input->stream.stream_lock ); - i_error = p_input->pf_read( p_input, pp_packets ); + i_count = p_input->pf_read( p_input, &p_data ); /* Demultiplex read packets. */ - for( i = 0; i < p_input->i_read_once && pp_packets[i] != NULL; i++ ) + while( p_data != NULL ) { + data_packet_t * p_next = p_data->p_next; + p_data->p_next = NULL; + p_input->stream.c_packets_read++; - p_input->pf_demux( p_input, pp_packets[i] ); + p_input->pf_demux( p_input, p_data ); + + p_data = p_next; } - if( i_error ) + if( i_count == 0 && p_input->stream.b_seekable ) { - if( i_error == 1 ) - { - /* End of file - we do not set b_die because only the - * interface is allowed to do so. */ - intf_WarnMsg( 3, "input: EOF reached" ); - p_input->b_eof = 1; - } - else - { - p_input->b_error = 1; - } + /* End of file - we do not set b_die because only the + * interface is allowed to do so. */ + intf_WarnMsg( 3, "input: EOF reached" ); + p_input->b_eof = 1; + } + else if( i_count < 0 ) + { + p_input->b_error = 1; } } - free( pp_packets ); - if( p_input->b_error || p_input->b_eof ) { ErrorThread( p_input ); @@ -372,7 +442,7 @@ static void RunThread( input_thread_t *p_input ) DestroyThread( p_input ); - intf_DbgMsg("input: Thread end"); + return 0; } /***************************************************************************** @@ -380,22 +450,14 @@ static void RunThread( input_thread_t *p_input ) *****************************************************************************/ static int InitThread( input_thread_t * p_input ) { - - /* Initialize statistics */ - p_input->c_loops = 0; - p_input->stream.c_packets_read = 0; - p_input->stream.c_packets_trashed = 0; - p_input->p_stream = NULL; - - /* Set locks. */ - vlc_mutex_init( &p_input->stream.stream_lock ); - vlc_cond_init( &p_input->stream.stream_wait ); - vlc_mutex_init( &p_input->stream.control.control_lock ); + char *psz_name; /* Find appropriate module. */ - p_input->p_input_module = module_Need( MODULE_CAPABILITY_INPUT, - (probedata_t *)p_input ); + psz_name = config_GetPszVariable( INPUT_METHOD_VAR ); + p_input->p_input_module = module_Need( MODULE_CAPABILITY_INPUT, psz_name, + (void *)p_input ); + if( psz_name ) free( psz_name ); if( p_input->p_input_module == NULL ) { intf_ErrMsg( "input error: no suitable input module for `%s'", @@ -404,11 +466,12 @@ static int InitThread( input_thread_t * p_input ) } #define f p_input->p_input_module->p_functions->input.functions.input + p_input->pf_probe = f.pf_probe; p_input->pf_init = f.pf_init; p_input->pf_end = f.pf_end; - p_input->pf_init_bit_stream= f.pf_init_bit_stream; p_input->pf_read = f.pf_read; p_input->pf_set_area = f.pf_set_area; + p_input->pf_set_program = f.pf_set_program; p_input->pf_demux = f.pf_demux; p_input->pf_new_packet = f.pf_new_packet; p_input->pf_new_pes = f.pf_new_pes; @@ -417,10 +480,16 @@ static int InitThread( input_thread_t * p_input ) p_input->pf_rewind = f.pf_rewind; p_input->pf_seek = f.pf_seek; + if( f.pf_open != NULL ) + { + f.pf_open( p_input ); + } #if !defined( SYS_BEOS ) && !defined( SYS_NTO ) /* FIXME : this is waaaay too kludgy */ - if( ( strlen( p_input->p_source ) > 3) - && !strncasecmp( p_input->p_source, "ts:", 3 ) ) + else if( ( strlen( p_input->p_source ) >= 10 + && !strncasecmp( p_input->p_source, "udpstream:", 10 ) ) + || ( strlen( p_input->p_source ) >= 4 + && !strncasecmp( p_input->p_source, "udp:", 4 ) ) ) { /* Network stream */ NetworkOpen( p_input ); @@ -433,22 +502,7 @@ static int InitThread( input_thread_t * p_input ) HTTPOpen( p_input ); p_input->stream.i_method = INPUT_METHOD_NETWORK; } - else #endif - if( ( ( strlen( p_input->p_source ) > 4 ) - && !strncasecmp( p_input->p_source, "dvd:", 4 ) ) - || TestMethod( INPUT_METHOD_VAR, "dvd" ) ) - { - /* DVD - this is THE kludge */ - f.pf_open( p_input ); - p_input->stream.i_method = INPUT_METHOD_DVD; - } - else if( ( strlen( p_input->p_source ) > 4 ) - && !strncasecmp( p_input->p_source, "vlc:", 4 ) ) - { - /* Dummy input - very kludgy */ - f.pf_open( p_input ); - } else if( ( strlen( p_input->p_source ) == 1 ) && *p_input->p_source == '-' ) { @@ -480,8 +534,6 @@ static int InitThread( input_thread_t * p_input ) return( -1 ); } - *p_input->pi_status = THREAD_READY; - return( 0 ); } @@ -504,11 +556,8 @@ static void ErrorThread( input_thread_t *p_input ) *****************************************************************************/ static void EndThread( input_thread_t * p_input ) { - int * pi_status; /* thread status */ - /* Store status */ - pi_status = p_input->pi_status; - *pi_status = THREAD_END; + p_input->i_status = THREAD_END; if( p_main->b_stats ) { @@ -547,10 +596,16 @@ static void CloseThread( input_thread_t * p_input ) { #define f p_input->p_input_module->p_functions->input.functions.input + if( f.pf_close != NULL ) + { + f.pf_close( p_input ); + } #if !defined( SYS_BEOS ) && !defined( SYS_NTO ) /* Close stream */ - if( ( strlen( p_input->p_source ) > 3) - && !strncasecmp( p_input->p_source, "ts:", 3 ) ) + else if( ( strlen( p_input->p_source ) > 10 + && !strncasecmp( p_input->p_source, "udpstream:", 10 ) ) + || ( strlen( p_input->p_source ) > 4 + && !strncasecmp( p_input->p_source, "udp:", 4 ) ) ) { NetworkClose( p_input ); } @@ -559,19 +614,7 @@ static void CloseThread( input_thread_t * p_input ) { NetworkClose( p_input ); } - else #endif - if( ( ( strlen( p_input->p_source ) > 4 ) - && !strncasecmp( p_input->p_source, "dvd:", 4 ) ) - || TestMethod( INPUT_METHOD_VAR, "dvd" ) ) - { - f.pf_close( p_input ); - } - else if( ( strlen( p_input->p_source ) > 4 ) - && !strncasecmp( p_input->p_source, "vlc:", 4 ) ) - { - f.pf_close( p_input ); - } else { FileClose( p_input ); @@ -584,20 +627,8 @@ static void CloseThread( input_thread_t * p_input ) *****************************************************************************/ static void DestroyThread( input_thread_t * p_input ) { - int * pi_status; /* thread status */ - - /* Store status */ - pi_status = p_input->pi_status; - - /* Destroy Mutex locks */ - vlc_mutex_destroy( &p_input->stream.control.control_lock ); - vlc_mutex_destroy( &p_input->stream.stream_lock ); - - /* Free input structure */ - free( p_input ); - /* Update status */ - *pi_status = THREAD_OVER; + p_input->i_status = THREAD_OVER; } /***************************************************************************** @@ -633,7 +664,14 @@ static void FileOpen( input_thread_t * p_input ) { int i_size = strlen( psz_name ); - if( ( i_size > 4 ) + if( ( i_size > 8 ) + && !strncasecmp( psz_name, "dvdread:", 8 ) ) + { + /* get rid of the 'dvdread:' stuff and try again */ + psz_name += 8; + i_stat = stat( psz_name, &stat_info ); + } + else if( ( i_size > 4 ) && !strncasecmp( psz_name, "dvd:", 4 ) ) { /* get rid of the 'dvd:' stuff and try again */ @@ -726,78 +764,107 @@ static void FileClose( input_thread_t * p_input ) static void NetworkOpen( input_thread_t * p_input ) { char *psz_server = NULL; - char *psz_broadcast = NULL; - int i_port = 0; + char *psz_bind = NULL; + int i_server_port = 0; + int i_bind_port = 0; int i_opt; int i_opt_size; struct sockaddr_in sock; - unsigned int i_mc_group; - /* Get the remote server */ + /* Get the remote server. Syntax is : + * udp[stream]:[/][/][serveraddr[:serverport]][@[bindaddr]:[bindport]] */ if( p_input->p_source != NULL ) { - psz_server = p_input->p_source; + char * psz_parser = p_input->p_source; + char * psz_server_port = NULL; + char * psz_bind_port = NULL; /* Skip the protocol name */ - while( *psz_server && *psz_server != ':' ) + while( *psz_parser && *psz_parser != ':' ) { - psz_server++; + psz_parser++; } /* Skip the "://" part */ - while( *psz_server && (*psz_server == ':' || *psz_server == '/') ) + while( *psz_parser && (*psz_parser == ':' || *psz_parser == '/') ) { - psz_server++; + psz_parser++; } - /* Found a server name */ - if( *psz_server ) + if( *psz_parser && *psz_parser != '@' ) { - char *psz_port = psz_server; + /* Found server */ + psz_server = psz_parser; - /* Skip the hostname part */ - while( *psz_port && *psz_port != ':' && *psz_port != '/' ) + while( *psz_parser && *psz_parser != ':' && *psz_parser != '@' ) { - psz_port++; + psz_parser++; } - /* Found a port name or a broadcast addres */ - if( *psz_port ) + if( *psz_parser == ':' ) { - /* That's a port name */ - if( *psz_port == ':' ) - { - *psz_port = '\0'; - psz_port++; - i_port = atoi( psz_port ); - } + /* Found server port */ + *psz_parser = '\0'; /* Terminate server name */ + psz_parser++; + psz_server_port = psz_parser; - /* Search for '/' just after the port in case - * we also have a broadcast address */ - psz_broadcast = psz_port; - while( *psz_broadcast && *psz_broadcast != '/' ) + while( *psz_parser && *psz_parser != '@' ) { - psz_broadcast++; + psz_parser++; } + } + } - if( *psz_broadcast ) - { - *psz_broadcast = '\0'; - psz_broadcast++; - while( *psz_broadcast && *psz_broadcast == '/' ) - { - psz_broadcast++; - } - } - else + if( *psz_parser == '@' ) + { + /* Found bind address or bind port */ + *psz_parser = '\0'; /* Terminate server port or name if necessary */ + psz_parser++; + + if( *psz_parser && *psz_parser != ':' ) + { + /* Found bind address */ + psz_bind = psz_parser; + + while( *psz_parser && *psz_parser != ':' ) { - psz_broadcast = NULL; + psz_parser++; } } + + if( *psz_parser == ':' ) + { + /* Found bind port */ + *psz_parser = '\0'; /* Terminate bind address if necessary */ + psz_parser++; + + psz_bind_port = psz_parser; + } } - else + + /* Convert ports format */ + if( psz_server_port != NULL ) { - psz_server = NULL; + i_server_port = strtol( psz_server_port, &psz_parser, 10 ); + if( *psz_parser ) + { + intf_ErrMsg( "input error: cannot parse server port near %s", + psz_parser ); + p_input->b_error = 1; + return; + } + } + + if( psz_bind_port != NULL ) + { + i_bind_port = strtol( psz_bind_port, &psz_parser, 10 ); + if( *psz_parser ) + { + intf_ErrMsg( "input error: cannot parse bind port near %s", + psz_parser ); + p_input->b_error = 1; + return; + } } } else @@ -806,36 +873,14 @@ static void NetworkOpen( input_thread_t * p_input ) p_input->p_source = "ts: network input"; } - /* Check that we got a valid server */ - if( psz_server == NULL ) - { - psz_server = main_GetPszVariable( INPUT_SERVER_VAR, - INPUT_SERVER_DEFAULT ); - } - /* Check that we got a valid port */ - if( i_port == 0 ) + if( i_bind_port == 0 ) { - i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT ); - } - - if( psz_broadcast == NULL ) - { - /* Are we broadcasting ? */ - if( main_GetIntVariable( INPUT_BROADCAST_VAR, - INPUT_BROADCAST_DEFAULT ) ) - { - psz_broadcast = main_GetPszVariable( INPUT_BCAST_ADDR_VAR, - INPUT_BCAST_ADDR_DEFAULT ); - } - else - { - psz_broadcast = NULL; - } + i_bind_port = config_GetIntVariable( INPUT_PORT_VAR ); } - intf_WarnMsg( 2, "input: server=%s port=%d broadcast=%s", - psz_server, i_port, psz_broadcast ); + intf_WarnMsg( 2, "input: server=%s:%d local=%s:%d", + psz_server, i_server_port, psz_bind, i_bind_port ); /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0) * protocol */ @@ -865,7 +910,7 @@ static void NetworkOpen( input_thread_t * p_input ) if( setsockopt( p_input->i_handle, SOL_SOCKET, SO_RCVBUF, (void *) &i_opt, sizeof( i_opt ) ) == -1 ) { - intf_WarnMsg( 1, "input error: can't configure socket (SO_RCVBUF: %s)", + intf_WarnMsg( 1, "input warning: can't configure socket (SO_RCVBUF: %s)", strerror(errno)); } @@ -877,7 +922,7 @@ static void NetworkOpen( input_thread_t * p_input ) if( getsockopt( p_input->i_handle, SOL_SOCKET, SO_RCVBUF, (void*) &i_opt, &i_opt_size ) == -1 ) { - intf_WarnMsg( 1, "input error: can't query socket (SO_RCVBUF: %s)", + intf_WarnMsg( 1, "input warning: can't query socket (SO_RCVBUF: %s)", strerror(errno)); } else if( i_opt < 0x80000 ) @@ -887,7 +932,14 @@ static void NetworkOpen( input_thread_t * p_input ) } /* Build the local socket */ - if ( network_BuildLocalAddr( &sock, i_port, psz_broadcast ) == -1 ) + +/* As we have a problem with multicast under win32, let's bind on INADDR_ANY */ + +#ifdef WIN32 + if ( network_BuildAddr( &sock, NULL, i_bind_port ) == -1 ) +#else + if ( network_BuildAddr( &sock, psz_bind, i_bind_port ) == -1 ) +#endif { intf_ErrMsg( "input error: can't build local address" ); close( p_input->i_handle ); @@ -895,15 +947,6 @@ static void NetworkOpen( input_thread_t * p_input ) return; } - /* Required for IP_ADD_MEMBERSHIP */ - i_mc_group = sock.sin_addr.s_addr; - -#if defined( WIN32 ) - sock.sin_addr.s_addr = INADDR_ANY; - -#define IN_MULTICAST(a) IN_CLASSD(a) -#endif - /* Bind it */ if( bind( p_input->i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 ) @@ -914,38 +957,59 @@ static void NetworkOpen( input_thread_t * p_input ) return; } + /* Allow broadcast reception if we bound on INADDR_ANY */ + if( psz_bind == NULL ) + { + i_opt = 1; + if( setsockopt( p_input->i_handle, SOL_SOCKET, SO_BROADCAST, + (void*) &i_opt, sizeof( i_opt ) ) == -1 ) + { + intf_WarnMsg( 1, "input warning: can't configure socket (SO_BROADCAST: %s)", + strerror(errno)); + } + } + /* Join the multicast group if the socket is a multicast address */ +#ifndef IN_MULTICAST +# define IN_MULTICAST(a) IN_CLASSD(a) +#endif -#ifndef WIN32 - if( IN_MULTICAST( ntohl(i_mc_group) ) ) +#ifdef WIN32 + if( IN_MULTICAST( ntohl( inet_addr (psz_bind) ) ) ) + { + struct ip_mreq imr; + imr.imr_interface.s_addr = INADDR_ANY; + imr.imr_multiaddr.s_addr = inet_addr (psz_bind) ; +#else + if( IN_MULTICAST( ntohl(sock.sin_addr.s_addr) ) ) { struct ip_mreq imr; - imr.imr_interface.s_addr = htonl(INADDR_ANY); - imr.imr_multiaddr.s_addr = i_mc_group; + imr.imr_interface.s_addr = INADDR_ANY; + imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr; +#endif if( setsockopt( p_input->i_handle, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&imr, sizeof(struct ip_mreq) ) == -1 ) { intf_ErrMsg( "input error: failed to join IP multicast group (%s)", strerror(errno) ); - close( p_input->i_handle); + close( p_input->i_handle ); p_input->b_error = 1; return; } } - /* Build socket for remote connection */ - if ( network_BuildRemoteAddr( &sock, psz_server ) == -1 ) + if( psz_server != NULL ) { - intf_ErrMsg( "input error: can't build remote address" ); - close( p_input->i_handle ); - p_input->b_error = 1; - return; - } + /* Build socket for remote connection */ + if ( network_BuildAddr( &sock, psz_server, i_server_port ) == -1 ) + { + intf_ErrMsg( "input error: can't build remote address" ); + close( p_input->i_handle ); + p_input->b_error = 1; + return; + } - /* Only connect if the user has passed a valid host */ - if( sock.sin_addr.s_addr != INADDR_ANY ) - { /* Connect the socket */ if( connect( p_input->i_handle, (struct sockaddr *) &sock, sizeof( sock ) ) == (-1) ) @@ -957,7 +1021,6 @@ static void NetworkOpen( input_thread_t * p_input ) return; } } -#endif p_input->stream.b_pace_control = 0; p_input->stream.b_seekable = 0; @@ -1095,7 +1158,7 @@ static void HTTPOpen( input_thread_t * p_input ) } /* Check proxy */ - if( (psz_proxy = main_GetPszVariable( "http_proxy", NULL )) != NULL ) + if( (psz_proxy = getenv( "http_proxy" )) != NULL ) { /* http://myproxy.mydomain:myport/ */ int i_proxy_port = 0; @@ -1158,26 +1221,24 @@ static void HTTPOpen( input_thread_t * p_input ) } /* Build socket for proxy connection */ - if ( network_BuildRemoteAddr( &sock, psz_proxy ) == -1 ) + if ( network_BuildAddr( &sock, psz_proxy, i_proxy_port ) == -1 ) { intf_ErrMsg( "input error: can't build remote address" ); close( p_input->i_handle ); p_input->b_error = 1; return; } - sock.sin_port = htons( i_proxy_port ); } else { /* No proxy, direct connection */ - if ( network_BuildRemoteAddr( &sock, psz_server ) == -1 ) + if ( network_BuildAddr( &sock, psz_server, i_port ) == -1 ) { intf_ErrMsg( "input error: can't build remote address" ); close( p_input->i_handle ); p_input->b_error = 1; return; } - sock.sin_port = htons( i_port ); } /* Connect the socket */