input.c 37.6 KB
Newer Older
1
2
/*****************************************************************************
 * input.c: input thread
Michel Kaempf's avatar
Michel Kaempf committed
3
4
 * Read an MPEG2 stream, demultiplex and parse it before sending it to
 * decoders.
5
6
 *****************************************************************************
 * Copyright (C) 1998, 1999, 2000 VideoLAN
7
 * $Id: input.c,v 1.146 2001/10/30 10:48:14 massiot Exp $
8
 *
9
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
10
11
12
13
14
 *
 * 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.
15
 * 
16
17
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
20
 *
21
22
23
 * 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.
24
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
25

26
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
27
 * Preamble
28
 *****************************************************************************/
29
30
#include "defs.h"

31
32
33
34
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
35
36

#ifdef HAVE_UNISTD_H
Sam Hocevar's avatar
   
Sam Hocevar committed
37
#   include <unistd.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
38
#elif defined( _MSC_VER ) && defined( _WIN32 )
Sam Hocevar's avatar
   
Sam Hocevar committed
39
#   include <io.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
40
41
#endif

42
#include <string.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
43
44
#include <errno.h>

Sam Hocevar's avatar
   
Sam Hocevar committed
45
46
47
#ifdef STRNCASECMP_IN_STRINGS_H
#   include <strings.h>
#endif
48
49

#ifdef WIN32
50
#   include <winsock.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
51
52
53
54
55
56
57
58
#   include <winsock2.h>
#elif !defined( SYS_BEOS ) && !defined( SYS_NTO )
#   include <netdb.h>                                         /* hostent ... */
#   include <sys/socket.h>
#   include <netinet/in.h>
#   include <arpa/inet.h>
#   include <sys/types.h>
#   include <sys/socket.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
59
#endif
Henri Fallon's avatar
   
Henri Fallon committed
60

61
62
#ifdef HAVE_SYS_TIMES_H
#   include <sys/times.h>
63
#endif
64

Michel Kaempf's avatar
Michel Kaempf committed
65
#include "config.h"
66
67
#include "common.h"
#include "threads.h"
Michel Kaempf's avatar
Michel Kaempf committed
68
#include "mtime.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
69
#include "netutils.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
70
#include "modules.h"
71

72
#include "intf_msg.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
73
#include "intf_playlist.h"
74

75
76
77
#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
78
#include "input_ext-plugins.h"
Michel Lespinasse's avatar
Yop,    
Michel Lespinasse committed
79

Sam Hocevar's avatar
   
Sam Hocevar committed
80
81
82
#include "interface.h"

#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
83

84
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
85
 * Local prototypes
86
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
87
88
89
90
91
static void RunThread       ( input_thread_t *p_input );
static  int InitThread      ( input_thread_t *p_input );
static void ErrorThread     ( input_thread_t *p_input );
static void DestroyThread   ( input_thread_t *p_input );
static void EndThread       ( input_thread_t *p_input );
Michel Kaempf's avatar
Michel Kaempf committed
92

Sam Hocevar's avatar
   
Sam Hocevar committed
93
94
static void FileOpen        ( input_thread_t *p_input );
static void FileClose       ( input_thread_t *p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
95
#if !defined( SYS_BEOS ) && !defined( SYS_NTO )
Sam Hocevar's avatar
   
Sam Hocevar committed
96
static void NetworkOpen     ( input_thread_t *p_input );
97
static void HTTPOpen        ( input_thread_t *p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
98
static void NetworkClose    ( input_thread_t *p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
99
#endif
Sam Hocevar's avatar
   
Sam Hocevar committed
100

101
/*****************************************************************************
102
 * input_CreateThread: creates a new input thread
103
 *****************************************************************************
104
105
106
107
 * This function creates a new input, and returns a pointer
 * to its description. On error, it returns NULL.
 * If pi_status is NULL, then the function will block until the thread is ready.
 * If not, it will be updated using one of the THREAD_* constants.
108
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
109
input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
110
{
111
112
113
    input_thread_t *    p_input;                        /* thread descriptor */
    int                 i_status;                           /* thread status */

114
115
116
    /* Allocate descriptor */
    p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
    if( p_input == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
117
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
118
119
        intf_ErrMsg( "input error: can't allocate input thread (%s)",
                     strerror(errno) );
Michel Kaempf's avatar
Michel Kaempf committed
120
121
        return( NULL );
    }
122

123
124
125
    /* Packets read once */
    p_input->i_read_once = INPUT_READ_ONCE;

126
127
128
    /* Initialize thread properties */
    p_input->b_die              = 0;
    p_input->b_error            = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
129
130
131
132
133
    p_input->b_eof              = 0;

    /* Set target */
    p_input->p_source           = p_item->psz_name;

134
    /* I have never understood that stuff --Meuuh */
135
136
    p_input->pi_status          = (pi_status != NULL) ? pi_status : &i_status;
    *p_input->pi_status         = THREAD_CREATE;
Michel Kaempf's avatar
Michel Kaempf committed
137

138
    /* Initialize stream description */
139
140
    p_input->stream.i_es_number = 0;
    p_input->stream.i_selected_es_number = 0;
141
    p_input->stream.i_pgrm_number = 0;
142
    p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
143
    p_input->stream.b_new_mute = MUTE_NO_CHANGE;
Christophe Massiot's avatar
Christophe Massiot committed
144
    p_input->stream.i_mux_rate = 0;
Michel Kaempf's avatar
Michel Kaempf committed
145

146
    /* no stream, no area */
Stéphane Borel's avatar
   
Stéphane Borel committed
147
148
    p_input->stream.i_area_nb = 0;
    p_input->stream.pp_areas = NULL;
149
    p_input->stream.p_selected_area = NULL;
150
    p_input->stream.p_new_area = NULL;
Sam Hocevar's avatar
   
Sam Hocevar committed
151
152

    /* By default there is one area in a stream */
Stéphane Borel's avatar
   
Stéphane Borel committed
153
    input_AddArea( p_input );
154
    p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
Stéphane Borel's avatar
   
Stéphane Borel committed
155

156
157
158
159
    /* Initialize stream control properties. */
    p_input->stream.control.i_status = PLAYING_S;
    p_input->stream.control.i_rate = DEFAULT_RATE;
    p_input->stream.control.b_mute = 0;
160
161
162
163
    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 );
Michel Kaempf's avatar
Michel Kaempf committed
164

Sam Hocevar's avatar
   
Sam Hocevar committed
165
166
    intf_WarnMsg( 1, "input: playlist item `%s'", p_input->p_source );

Sam Hocevar's avatar
   
Sam Hocevar committed
167
    /* Create thread. */
168
169
    if( vlc_thread_create( &p_input->thread_id, "input", (void *) RunThread,
                           (void *) p_input ) )
Michel Kaempf's avatar
Michel Kaempf committed
170
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
171
172
        intf_ErrMsg( "input error: can't create input thread (%s)",
                     strerror(errno) );
Michel Kaempf's avatar
Michel Kaempf committed
173
174
175
        free( p_input );
        return( NULL );
    }
176

177
178
179
180
    /* If status is NULL, wait until the thread is created */
    if( pi_status == NULL )
    {
        do
181
        {
182
            msleep( THREAD_SLEEP );
183
        } while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
Sam Hocevar's avatar
   
Sam Hocevar committed
184
                && (i_status != THREAD_FATAL) );
185
186
        if( i_status != THREAD_READY )
        {
187
188
            return( NULL );
        }
189
    }
Michel Kaempf's avatar
Michel Kaempf committed
190
191
192
    return( p_input );
}

193
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
194
 * input_DestroyThread: mark an input thread as zombie
195
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
196
 * This function should not return until the thread is effectively cancelled.
197
 *****************************************************************************/
198
void input_DestroyThread( input_thread_t *p_input, int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
199
{
200
    int         i_status;                                   /* thread status */
201
202
203

    /* Set status */
    p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status;
204
205
    *p_input->pi_status = THREAD_DESTROY;

206
207
    /* Request thread destruction */
    p_input->b_die = 1;
Michel Kaempf's avatar
Michel Kaempf committed
208

209
210
211
212
213
    /* 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 );

214
215
216
217
218
219
    /* If status is NULL, wait until thread has been destroyed */
    if( pi_status == NULL )
    {
        do
        {
            msleep( THREAD_SLEEP );
220
221
        } while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
                  && (i_status != THREAD_FATAL) );
222
    }
Michel Kaempf's avatar
Michel Kaempf committed
223
224
}

225
/*****************************************************************************
226
 * RunThread: main thread loop
227
 *****************************************************************************
228
 * Thread in charge of processing the network packets and demultiplexing.
229
 *****************************************************************************/
230
static void RunThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
231
{
232
    int                     i_error, i;
Sam Hocevar's avatar
   
Sam Hocevar committed
233
    data_packet_t **        pp_packets;
Michel Kaempf's avatar
Michel Kaempf committed
234

Sam Hocevar's avatar
   
Sam Hocevar committed
235
236
237
238
239
240
241
242
243
    if( InitThread( p_input ) )
    {
        /* If we failed, wait before we are killed, and exit */
        *p_input->pi_status = THREAD_ERROR;
        p_input->b_error = 1;
        ErrorThread( p_input );
        DestroyThread( p_input );
        return;
    }
Michel Kaempf's avatar
Michel Kaempf committed
244

245
246
247
248
249
    /* initialization is completed */
    vlc_mutex_lock( &p_input->stream.stream_lock );
    p_input->stream.b_changed = 1;
    vlc_mutex_unlock( &p_input->stream.stream_lock );

Sam Hocevar's avatar
   
Sam Hocevar committed
250
251
252
    pp_packets = (data_packet_t **) malloc( p_input->i_read_once *
                                        sizeof( data_packet_t * ) );
    if( pp_packets == NULL )
253
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
254
        intf_ErrMsg( "input error: out of memory" );
Sam Hocevar's avatar
   
Sam Hocevar committed
255
        free( pp_packets );
Sam Hocevar's avatar
   
Sam Hocevar committed
256
257
        p_input->b_error = 1;
    }
258

Sam Hocevar's avatar
   
Sam Hocevar committed
259
260
    while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
261
        p_input->c_loops++;
Sam Hocevar's avatar
   
Sam Hocevar committed
262

263
        vlc_mutex_lock( &p_input->stream.stream_lock );
264

265
266
        if( p_input->stream.p_new_area )
        {
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
            if( p_input->stream.b_seekable && p_input->pf_set_area != NULL )
            {

                p_input->pf_set_area( p_input, p_input->stream.p_new_area );

                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;
                }
            }
284
285
286
            p_input->stream.p_new_area = NULL;
        }

287
        if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
Sam Hocevar's avatar
   
Sam Hocevar committed
288
        {
289
290
            if( p_input->stream.b_seekable && p_input->pf_seek != NULL )
            {
291
292
                p_input->pf_seek( p_input,
                                  p_input->stream.p_selected_area->i_seek );
293
294
295
296
297
298
299
300
301
302
303
304
305

                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;
                }
            }
306
            p_input->stream.p_selected_area->i_seek = NO_SEEK;
Sam Hocevar's avatar
   
Sam Hocevar committed
307
        }
308

309
310
311
312
313
314
315
316
317
318
319
320
        if( p_input->stream.p_removed_es )
        {
            input_UnselectES( p_input, p_input->stream.p_removed_es );
            p_input->stream.p_removed_es = NULL;
        }

        if( p_input->stream.p_newly_selected_es )
        {
            input_SelectES( p_input, p_input->stream.p_newly_selected_es );
            p_input->stream.p_newly_selected_es = NULL;
        }

321
322
323
324
325
326
327
328
329
330
331
332
333
334
        if( p_input->stream.b_new_mute != MUTE_NO_CHANGE )
        {
            if( p_input->stream.b_new_mute )
            {
                input_EscapeAudioDiscontinuity( p_input );
            }

            vlc_mutex_lock( &p_input->stream.control.control_lock );
            p_input->stream.control.b_mute = p_input->stream.b_new_mute;
            vlc_mutex_unlock( &p_input->stream.control.control_lock );

            p_input->stream.b_new_mute = MUTE_NO_CHANGE;
        }

335
        vlc_mutex_unlock( &p_input->stream.stream_lock );
Sam Hocevar's avatar
   
Sam Hocevar committed
336
337

        i_error = p_input->pf_read( p_input, pp_packets );
Sam Hocevar's avatar
   
Sam Hocevar committed
338

Sam Hocevar's avatar
   
Sam Hocevar committed
339
        /* Demultiplex read packets. */
340
        for( i = 0; i < p_input->i_read_once && pp_packets[i] != NULL; i++ )
Sam Hocevar's avatar
   
Sam Hocevar committed
341
        {
342
            p_input->stream.c_packets_read++;
Sam Hocevar's avatar
   
Sam Hocevar committed
343
344
            p_input->pf_demux( p_input, pp_packets[i] );
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
345

Sam Hocevar's avatar
   
Sam Hocevar committed
346
347
348
        if( i_error )
        {
            if( i_error == 1 )
Sam Hocevar's avatar
Sam Hocevar committed
349
            {
Sam Hocevar's avatar
   
Sam Hocevar committed
350
351
                /* End of file - we do not set b_die because only the
                 * interface is allowed to do so. */
352
                intf_WarnMsg( 3, "input: EOF reached" );
Sam Hocevar's avatar
   
Sam Hocevar committed
353
                p_input->b_eof = 1;
Sam Hocevar's avatar
   
Sam Hocevar committed
354
            }
Sam Hocevar's avatar
   
Sam Hocevar committed
355
            else
Sam Hocevar's avatar
   
Sam Hocevar committed
356
            {
Sam Hocevar's avatar
   
Sam Hocevar committed
357
                p_input->b_error = 1;
Sam Hocevar's avatar
Sam Hocevar committed
358
            }
359
360
361
        }
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
362
363
    free( pp_packets );

Sam Hocevar's avatar
   
Sam Hocevar committed
364
    if( p_input->b_error || p_input->b_eof )
365
366
367
    {
        ErrorThread( p_input );
    }
368

369
    EndThread( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
370
371
372

    DestroyThread( p_input );

Sam Hocevar's avatar
   
Sam Hocevar committed
373
    intf_DbgMsg("input: Thread end");
374
375
}

376
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
377
 * InitThread: init the input Thread
378
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
379
static int InitThread( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
380
381
{

382
383
    /* Initialize statistics */
    p_input->c_loops                    = 0;
384
385
    p_input->stream.c_packets_read      = 0;
    p_input->stream.c_packets_trashed   = 0;
386
    p_input->p_stream                   = NULL;
Sam Hocevar's avatar
Sam Hocevar committed
387

Sam Hocevar's avatar
   
Sam Hocevar committed
388
389
390
391
392
    /* 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 );

393
    /* Find appropriate module. */
Sam Hocevar's avatar
   
Sam Hocevar committed
394
    p_input->p_input_module = module_Need( MODULE_CAPABILITY_INPUT,
Sam Hocevar's avatar
   
Sam Hocevar committed
395
                                           (probedata_t *)p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
396
397

    if( p_input->p_input_module == NULL )
398
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
399
400
        intf_ErrMsg( "input error: no suitable input module for `%s'",
                     p_input->p_source );
Sam Hocevar's avatar
   
Sam Hocevar committed
401
        return( -1 );
Michel Kaempf's avatar
Michel Kaempf committed
402
    }
403

Sam Hocevar's avatar
   
Sam Hocevar committed
404
405
406
#define f p_input->p_input_module->p_functions->input.functions.input
    p_input->pf_init          = f.pf_init;
    p_input->pf_end           = f.pf_end;
407
    p_input->pf_init_bit_stream= f.pf_init_bit_stream;
Sam Hocevar's avatar
   
Sam Hocevar committed
408
    p_input->pf_read          = f.pf_read;
409
    p_input->pf_set_area      = f.pf_set_area;
Sam Hocevar's avatar
   
Sam Hocevar committed
410
411
412
413
414
415
416
417
    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;
    p_input->pf_delete_packet = f.pf_delete_packet;
    p_input->pf_delete_pes    = f.pf_delete_pes;
    p_input->pf_rewind        = f.pf_rewind;
    p_input->pf_seek          = f.pf_seek;
#undef f
Sam Hocevar's avatar
   
Sam Hocevar committed
418

419
#if !defined( SYS_BEOS ) && !defined( SYS_NTO )
420
421
422
423
424
425
426
427
428
429
430
431
432
    /* FIXME : this is waaaay too kludgy */
    if( (strlen( p_input->p_source ) > 3) && !strncasecmp( p_input->p_source, "ts:", 3 ) )
    {
        /* Network stream */
        NetworkOpen( p_input );
        p_input->stream.i_method = INPUT_METHOD_NETWORK;
    }
    else if( ( strlen( p_input->p_source ) > 5 ) && !strncasecmp( p_input->p_source, "http:", 5 ) )
    {
        /* HTTP stream */
        HTTPOpen( p_input );
        p_input->stream.i_method = INPUT_METHOD_NETWORK;
    }
433
434
435
    else 
#endif
        if( ( strlen( p_input->p_source ) > 4 ) && !strncasecmp( p_input->p_source, "dvd:", 4 ) )
436
437
438
439
440
    {
        /* DVD - this is THE kludge */
        p_input->p_input_module->p_functions->input.functions.input.pf_open( p_input );
        p_input->stream.i_method = INPUT_METHOD_DVD;
    }
441
442
443
444
445
    else if( ( strlen( p_input->p_source ) > 4 ) && !strncasecmp( p_input->p_source, "vlc:", 4 ) )
    {
        /* Dummy input - very kludgy */
        p_input->p_input_module->p_functions->input.functions.input.pf_open( p_input );
    }
446
447
448
449
450
451
    else
    {
        /* File input */
        FileOpen( p_input );
        p_input->stream.i_method = INPUT_METHOD_FILE;
    }
452

Sam Hocevar's avatar
   
Sam Hocevar committed
453
    if( p_input->b_error )
454
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
455
        /* We barfed -- exit nicely */
Sam Hocevar's avatar
   
Sam Hocevar committed
456
        module_Unneed( p_input->p_input_module );
Sam Hocevar's avatar
   
Sam Hocevar committed
457
        return( -1 );
458
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
459
460

    p_input->pf_init( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
461

462
463
464
465
    if( p_input->b_error )
    {
        /* We barfed -- exit nicely */
        p_input->pf_close( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
466
        module_Unneed( p_input->p_input_module );
467
468
469
        return( -1 );
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
470
    *p_input->pi_status = THREAD_READY;
Sam Hocevar's avatar
   
Sam Hocevar committed
471
472

    return( 0 );
Michel Kaempf's avatar
Michel Kaempf committed
473
474
}

475
/*****************************************************************************
476
 * ErrorThread: RunThread() error loop
477
 *****************************************************************************
478
 * This function is called when an error occured during thread main's loop.
479
 *****************************************************************************/
480
static void ErrorThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
481
{
482
    while( !p_input->b_die )
Michel Kaempf's avatar
Michel Kaempf committed
483
    {
484
485
        /* Sleep a while */
        msleep( INPUT_IDLE_SLEEP );
Michel Kaempf's avatar
Michel Kaempf committed
486
487
488
    }
}

489
/*****************************************************************************
490
 * EndThread: end the input thread
491
 *****************************************************************************/
492
static void EndThread( input_thread_t * p_input )
493
{
494
    int *       pi_status;                                  /* thread status */
495

496
497
498
    /* Store status */
    pi_status = p_input->pi_status;
    *pi_status = THREAD_END;
Sam Hocevar's avatar
Sam Hocevar committed
499

500
    if( p_main->b_stats )
Sam Hocevar's avatar
   
Sam Hocevar committed
501
    {
502
#ifdef HAVE_SYS_TIMES_H
503
504
        /* Display statistics */
        struct tms  cpu_usage;
Sam Hocevar's avatar
   
Sam Hocevar committed
505
506
        times( &cpu_usage );

507
508
509
        intf_StatMsg( "input stats: %d loops consuming user: %d, system: %d",
                      p_input->c_loops,
                      cpu_usage.tms_utime, cpu_usage.tms_stime );
510
511
512
#else
        intf_StatMsg( "input stats: %d loops", p_input->c_loops );
#endif
513
514

        input_DumpStream( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
515
516
517
518
519
520
521
522
    }

    /* Free all ES and destroy all decoder threads */
    input_EndStream( p_input );

    /* Free demultiplexer's data */
    p_input->pf_end( p_input );

523
#if !defined( SYS_BEOS ) && !defined( SYS_NTO )
Sam Hocevar's avatar
   
Sam Hocevar committed
524
    /* Close stream */
525
526
527
528
529
530
531
532
    if( (strlen( p_input->p_source ) > 3) && !strncasecmp( p_input->p_source, "ts:", 3 ) )
    {
        NetworkClose( p_input );
    }
    else if( ( strlen( p_input->p_source ) > 5 ) && !strncasecmp( p_input->p_source, "http:", 5 ) )
    {
        NetworkClose( p_input );
    }
533
534
535
    else 
#endif
    if( ( strlen( p_input->p_source ) > 4 ) && !strncasecmp( p_input->p_source, "dvd:", 4 ) )
536
537
538
    {
        p_input->p_input_module->p_functions->input.functions.input.pf_close( p_input );
    }
539
540
541
542
    else if( ( strlen( p_input->p_source ) > 4 ) && !strncasecmp( p_input->p_source, "vlc:", 4 ) )
    {
        p_input->p_input_module->p_functions->input.functions.input.pf_close( p_input );
    }
543
544
545
546
    else
    {
        FileClose( p_input );
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
547

Sam Hocevar's avatar
   
Sam Hocevar committed
548
    /* Release modules */
Sam Hocevar's avatar
   
Sam Hocevar committed
549
    module_Unneed( p_input->p_input_module );
Sam Hocevar's avatar
   
Sam Hocevar committed
550

Sam Hocevar's avatar
   
Sam Hocevar committed
551
552
553
554
555
556
557
558
559
560
561
}

/*****************************************************************************
 * DestroyThread: destroy the input thread
 *****************************************************************************/
static void DestroyThread( input_thread_t * p_input )
{
    int *       pi_status;                                  /* thread status */

    /* Store status */
    pi_status = p_input->pi_status;
Sam Hocevar's avatar
   
Sam Hocevar committed
562

Henri Fallon's avatar
   
Henri Fallon committed
563
564
    /* Destroy Mutex locks */
    vlc_mutex_destroy( &p_input->stream.control.control_lock );
Henri Fallon's avatar
   
Henri Fallon committed
565
    vlc_mutex_destroy( &p_input->stream.stream_lock );
Henri Fallon's avatar
   
Henri Fallon committed
566
    
567
    /* Free input structure */
568
    free( p_input );
569

570
571
    /* Update status */
    *pi_status = THREAD_OVER;
Sam Hocevar's avatar
Sam Hocevar committed
572
}
573

Sam Hocevar's avatar
Sam Hocevar committed
574
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
575
 * FileOpen : open a file descriptor
Sam Hocevar's avatar
Sam Hocevar committed
576
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
577
static void FileOpen( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
578
{
579
    struct stat         stat_info;
Sam Hocevar's avatar
   
Sam Hocevar committed
580
581
582
    int                 i_stat;

    char *psz_name = p_input->p_source;
Michel Kaempf's avatar
Michel Kaempf committed
583

Sam Hocevar's avatar
   
Sam Hocevar committed
584
    if( ( i_stat = stat( psz_name, &stat_info ) ) == (-1) )
Sam Hocevar's avatar
   
Sam Hocevar committed
585
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
586
587
588
589
590
591
592
593
        int i_size = strlen( psz_name );

        if( ( i_size > 4 )
            && !strncasecmp( psz_name, "dvd:", 4 ) )
        {
            /* get rid of the 'dvd:' stuff and try again */
            psz_name += 4;
            i_stat = stat( psz_name, &stat_info );
Henri Fallon's avatar
   
Henri Fallon committed
594
        }
595
596
        else if( ( i_size > 4 )
                 && !strncasecmp( psz_name, "vcd:", 4 ) )
597
598
599
600
601
        {
            /* get rid of the 'vcd:' stuff and try again */
            psz_name += 4;
            i_stat = stat( psz_name, &stat_info );
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
602
        else if( ( i_size > 5 )
Sam Hocevar's avatar
   
Sam Hocevar committed
603
604
605
606
607
                 && !strncasecmp( psz_name, "file:", 5 ) )
        {
            /* get rid of the 'file:' stuff and try again */
            psz_name += 5;
            i_stat = stat( psz_name, &stat_info );
Henri Fallon's avatar
   
Henri Fallon committed
608
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
609

Sam Hocevar's avatar
   
Sam Hocevar committed
610
        if( i_stat == (-1) )
Sam Hocevar's avatar
   
Sam Hocevar committed
611
612
613
614
615
616
        {
            intf_ErrMsg( "input error: cannot stat() file `%s' (%s)",
                         psz_name, strerror(errno));
            p_input->b_error = 1;
            return;
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
617
618
619
620
621
622
623
624
    }

    vlc_mutex_lock( &p_input->stream.stream_lock );

    /* If we are here we can control the pace... */
    p_input->stream.b_pace_control = 1;

    if( S_ISREG(stat_info.st_mode) || S_ISCHR(stat_info.st_mode)
Sam Hocevar's avatar
   
Sam Hocevar committed
625
         || S_ISBLK(stat_info.st_mode) )
Sam Hocevar's avatar
   
Sam Hocevar committed
626
627
    {
        p_input->stream.b_seekable = 1;
628
        p_input->stream.p_selected_area->i_size = stat_info.st_size;
Sam Hocevar's avatar
   
Sam Hocevar committed
629
    }
Jean-Marc Dressler's avatar
   
Jean-Marc Dressler committed
630
    else if( S_ISFIFO(stat_info.st_mode)
Sam Hocevar's avatar
   
Sam Hocevar committed
631
#if !defined( SYS_BEOS ) && !defined( WIN32 )
Jean-Marc Dressler's avatar
   
Jean-Marc Dressler committed
632
633
634
             || S_ISSOCK(stat_info.st_mode)
#endif
             )
Sam Hocevar's avatar
Sam Hocevar committed
635
    {
636
        p_input->stream.b_seekable = 0;
637
        p_input->stream.p_selected_area->i_size = 0;
Benoit Steiner's avatar
   
Benoit Steiner committed
638
639
640
    }
    else
    {
641
        vlc_mutex_unlock( &p_input->stream.stream_lock );
Sam Hocevar's avatar
   
Sam Hocevar committed
642
        intf_ErrMsg( "input error: unknown file type for `%s'",
Sam Hocevar's avatar
   
Sam Hocevar committed
643
                     psz_name );
Sam Hocevar's avatar
   
Sam Hocevar committed
644
645
646
        p_input->b_error = 1;
        return;
    }
647

648
    p_input->stream.p_selected_area->i_tell = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
649
650
    vlc_mutex_unlock( &p_input->stream.stream_lock );

Sam Hocevar's avatar
   
Sam Hocevar committed
651
    intf_WarnMsg( 2, "input: opening file `%s'", p_input->p_source );
Sam Hocevar's avatar
   
Sam Hocevar committed
652
    if( (p_input->i_handle = open( psz_name,
Sam Hocevar's avatar
   
Sam Hocevar committed
653
654
                                   /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
655
        intf_ErrMsg( "input error: cannot open file (%s)", strerror(errno) );
Sam Hocevar's avatar
   
Sam Hocevar committed
656
657
        p_input->b_error = 1;
        return;
Michel Kaempf's avatar
Michel Kaempf committed
658
659
660
    }

}
Stéphane Borel's avatar
Stéphane Borel committed
661
662

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
663
 * FileClose : close a file descriptor
Stéphane Borel's avatar
Stéphane Borel committed
664
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
665
static void FileClose( input_thread_t * p_input )
Stéphane Borel's avatar
Stéphane Borel committed
666
{
Sam Hocevar's avatar
   
Sam Hocevar committed
667
    intf_WarnMsg( 2, "input: closing file `%s'", p_input->p_source );
Sam Hocevar's avatar
   
Sam Hocevar committed
668

Sam Hocevar's avatar
   
Sam Hocevar committed
669
    close( p_input->i_handle );
Stéphane Borel's avatar
Stéphane Borel committed
670

Sam Hocevar's avatar
   
Sam Hocevar committed
671
    return;
Stéphane Borel's avatar
Stéphane Borel committed
672
}
Sam Hocevar's avatar
   
Sam Hocevar committed
673

674
#if !defined( SYS_BEOS ) && !defined( SYS_NTO )
Henri Fallon's avatar
   
Henri Fallon committed
675
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
676
 * NetworkOpen : open a network socket 
Henri Fallon's avatar
   
Henri Fallon committed
677
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
678
static void NetworkOpen( input_thread_t * p_input )
Henri Fallon's avatar
   
Henri Fallon committed
679
{
Henri Fallon's avatar
   
Henri Fallon committed
680
    char                *psz_server = NULL;
681
    char                *psz_broadcast = NULL;
Henri Fallon's avatar
   
Henri Fallon committed
682
    int                 i_port = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
683
    int                 i_opt;
684
    int                 i_opt_size;
Sam Hocevar's avatar
   
Sam Hocevar committed
685
    struct sockaddr_in  sock;
686
687
    unsigned int        i_mc_group;

Sam Hocevar's avatar
   
Sam Hocevar committed
688
689
#ifdef WIN32
    WSADATA Data;
Sam Hocevar's avatar
   
Sam Hocevar committed
690
691
692
693
694
695
    int i_err;
#endif
    
#ifdef WIN32
    /* WinSock Library Init. */
    i_err = WSAStartup( MAKEWORD( 1, 1 ), &Data );
Sam Hocevar's avatar
   
Sam Hocevar committed
696
697
698
699
700
701
702

    if( i_err )
    {
        intf_ErrMsg( "input: can't initiate WinSocks, error %i", i_err );
        return ;
    }
#endif
Henri Fallon's avatar
   
Henri Fallon committed
703
704
    
    /* Get the remote server */
Sam Hocevar's avatar
   
Sam Hocevar committed
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
    if( p_input->p_source != NULL )
    {
        psz_server = p_input->p_source;

        /* Skip the protocol name */
        while( *psz_server && *psz_server != ':' )
        {
            psz_server++;
        }

        /* Skip the "://" part */
        while( *psz_server && (*psz_server == ':' || *psz_server == '/') )
        {
            psz_server++;
        }

        /* Found a server name */
        if( *psz_server )
        {
            char *psz_port = psz_server;

            /* Skip the hostname part */
Sam Hocevar's avatar
   
Sam Hocevar committed
727
            while( *psz_port && *psz_port != ':' && *psz_port != '/' )
Sam Hocevar's avatar
   
Sam Hocevar committed
728
729
730
731
            {
                psz_port++;
            }

Sam Hocevar's avatar
   
Sam Hocevar committed
732
            /* Found a port name or a broadcast addres */
Sam Hocevar's avatar
   
Sam Hocevar committed
733
734
            if( *psz_port )
            {
Sam Hocevar's avatar
   
Sam Hocevar committed
735
736
737
738
739
740
741
		/* That's a port name */
		if( *psz_port == ':' )
		{
                    *psz_port = '\0';
                    psz_port++;
                    i_port = atoi( psz_port );
		}
Sam Hocevar's avatar
   
Sam Hocevar committed
742

Sam Hocevar's avatar
   
Sam Hocevar committed
743
744
		/* Search for '/' just after the port in case
		 * we also have a broadcast address */
745
                psz_broadcast = psz_port;
Sam Hocevar's avatar
   
Sam Hocevar committed
746
                while( *psz_broadcast && *psz_broadcast != '/' )
747
748
749
750
751
752
753
754
                {
                    psz_broadcast++;
                }

                if( *psz_broadcast )
                {
                    *psz_broadcast = '\0';
                    psz_broadcast++;
Sam Hocevar's avatar
   
Sam Hocevar committed
755
                    while( *psz_broadcast && *psz_broadcast == '/' )
756
757
758
759
760
761
762
763
                    {
                        psz_broadcast++;
                    }
                }
                else
                {
                    psz_broadcast = NULL;
                }
Sam Hocevar's avatar
   
Sam Hocevar committed
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
            }
        }
        else
        {
            psz_server = NULL;
        }
    }

    /* 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 )
Henri Fallon's avatar
   
Henri Fallon committed
781
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
782
        i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
Henri Fallon's avatar
   
Henri Fallon committed
783
    }
784
785
786
787

    if( psz_broadcast == NULL )
    {
        /* Are we broadcasting ? */
788
789
790
791
792
793
794
795
796
797
        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; 
        }
798
799
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
800
    intf_WarnMsg( 2, "input: server=%s port=%d broadcast=%s",
801
802
                     psz_server, i_port, psz_broadcast );

Henri Fallon's avatar
   
Henri Fallon committed
803
804
805
806
807
    /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
     * protocol */
    p_input->i_handle = socket( AF_INET, SOCK_DGRAM, 0 );
    if( p_input->i_handle == -1 )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
808
        intf_ErrMsg( "input error: can't create socket (%s)", strerror(errno) );
Henri Fallon's avatar
   
Henri Fallon committed
809
810
811
812
813
        p_input->b_error = 1;
        return;
    }

    /* We may want to reuse an already used socket */
Sam Hocevar's avatar
   
Sam Hocevar committed
814
    i_opt = 1;
Henri Fallon's avatar
   
Henri Fallon committed
815
    if( setsockopt( p_input->i_handle, SOL_SOCKET, SO_REUSEADDR,
816
                    (void *) &i_opt, sizeof( i_opt ) ) == -1 )
Henri Fallon's avatar
   
Henri Fallon committed
817
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
818
819
        intf_ErrMsg( "input error: can't configure socket (SO_REUSEADDR: %s)",
                     strerror(errno));
Henri Fallon's avatar
   
Henri Fallon committed
820
821
822
823
824
825
826
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }

    /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
     * packet loss caused by scheduling problems */
Sam Hocevar's avatar
   
Sam Hocevar committed
827
828
    i_opt = 0x80000;
    if( setsockopt( p_input->i_handle, SOL_SOCKET, SO_RCVBUF,
829
                    (void *) &i_opt, sizeof( i_opt ) ) == -1 )
Henri Fallon's avatar
   
Henri Fallon committed
830
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
831
832
        intf_ErrMsg( "input error: can't configure socket (SO_RCVBUF: %s)", 
                     strerror(errno));
Henri Fallon's avatar
   
Henri Fallon committed
833
834
835
836
837
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }

838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
    /* Check if we really got what we have asked for, because Linux, etc.
     * will silently limit the max buffer size to net.core.rmem_max which
     * is typically only 65535 bytes */
    i_opt = 0;
    i_opt_size = sizeof( i_opt );
    if( getsockopt( p_input->i_handle, SOL_SOCKET, SO_RCVBUF,
                    (void*) &i_opt, &i_opt_size ) == -1 )
    {
        intf_ErrMsg( "input error: can't configure socket (SO_RCVBUF: %s)", 
                     strerror(errno));
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }
    
    if( i_opt < 0x80000 )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
855
856
        intf_WarnMsg( 1, "input warning: socket receive buffer size just 0x%x"
                         " instead of 0x%x bytes.", i_opt, 0x80000 );
857
858
    }

Henri Fallon's avatar
   
Henri Fallon committed
859
    /* Build the local socket */
Sam Hocevar's avatar
   
Sam Hocevar committed
860
    if ( network_BuildLocalAddr( &sock, i_port, psz_broadcast ) == -1 )
Henri Fallon's avatar
   
Henri Fallon committed
861
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
862
        intf_ErrMsg( "input error: can't build local address" );
Henri Fallon's avatar
   
Henri Fallon committed
863
864
865
866
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
867

868
869
870
    /* Required for IP_ADD_MEMBERSHIP */
    i_mc_group = sock.sin_addr.s_addr;

Sam Hocevar's avatar
   
Sam Hocevar committed
871
872
873
874
875
#if defined( WIN32 )
    if ( psz_broadcast != NULL )
    {
        sock.sin_addr.s_addr = INADDR_ANY;
    }
876
    
877
#define IN_MULTICAST(a)         IN_CLASSD(a)
Sam Hocevar's avatar
   
Sam Hocevar committed
878
#endif
879

Henri Fallon's avatar
   
Henri Fallon committed
880
    /* Bind it */
Sam Hocevar's avatar
   
Sam Hocevar committed
881
882
    if( bind( p_input->i_handle, (struct sockaddr *)&sock, 
              sizeof( sock ) ) < 0 )
Henri Fallon's avatar
   
Henri Fallon committed
883
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
884
        intf_ErrMsg( "input error: can't bind socket (%s)", strerror(errno) );
Henri Fallon's avatar
   
Henri Fallon committed
885
886
887
888
889
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }

890
    /* Join the multicast group if the socket is a multicast address */
891
892

#ifndef WIN32    
893
894
895
896
897
898
    if( IN_MULTICAST( ntohl(i_mc_group) ) )
    {
        struct ip_mreq imr;

        imr.imr_interface.s_addr = htonl(INADDR_ANY);
        imr.imr_multiaddr.s_addr = i_mc_group;
899
        if( setsockopt( p_input->i_handle, IPPROTO_IP, IP_ADD_MEMBERSHIP,
900
901
902
903
904
905
906
907
908
                        (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);
            p_input->b_error = 1;
            return;
        }
    }
909
910
#endif
    
Henri Fallon's avatar
   
Henri Fallon committed
911
    /* Build socket for remote connection */
Sam Hocevar's avatar
   
Sam Hocevar committed
912
    if ( network_BuildRemoteAddr( &sock, psz_server ) == -1 )
Henri Fallon's avatar
   
Henri Fallon committed
913
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
914
        intf_ErrMsg( "input error: can't build remote address" );
Henri Fallon's avatar
   
Henri Fallon committed
915
916
917
918
919
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }

920
921
    /* Only connect if the user has passed a valid host */
    if( sock.sin_addr.s_addr != INADDR_ANY )
Henri Fallon's avatar
   
Henri Fallon committed
922
    {
923
924
925
926
927
928
929
930
931
932
        /* Connect the socket */
        if( connect( p_input->i_handle, (struct sockaddr *) &sock,
                     sizeof( sock ) ) == (-1) )
        {
            intf_ErrMsg( "input error: can't connect socket (%s)", 
                         strerror(errno) );
            close( p_input->i_handle );
            p_input->b_error = 1;
            return;
        }
Henri Fallon's avatar
   
Henri Fallon committed
933
934
    }

Henri Fallon's avatar
   
Henri Fallon committed
935
    p_input->stream.b_pace_control = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
936
    p_input->stream.b_seekable = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
937
938

    intf_WarnMsg( 3, "input: successfully opened network mode" );
Henri Fallon's avatar
   
Henri Fallon committed
939
940
941
942
943
    
    return;
}

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
944
 * NetworkClose : close a network socket
Henri Fallon's avatar
   
Henri Fallon committed
945
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
946
static void NetworkClose( input_thread_t * p_input )
Henri Fallon's avatar
   
Henri Fallon committed
947
948
{
    close( p_input->i_handle );
949

Sam Hocevar's avatar
   
Sam Hocevar committed
950
951
952
#ifdef WIN32 
    WSACleanup();
#endif
Henri Fallon's avatar
   
Henri Fallon committed
953
}
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981

/*****************************************************************************
 * HTTPOpen : make an HTTP request
 *****************************************************************************/
static void HTTPOpen( input_thread_t * p_input )
{
    char                *psz_server = NULL;
    char                *psz_path = NULL;
    char                *psz_proxy;
    int                 i_port = 0;
    int                 i_opt;
    struct sockaddr_in  sock;
    char                psz_buffer[256];

#ifdef WIN32
    WSADATA Data;
    int i_err;
#endif
    
#ifdef WIN32
    /* WinSock Library Init. */
    i_err = WSAStartup( MAKEWORD( 1, 1 ), &Data );

    if( i_err )
    {
        intf_ErrMsg( "input: can't initiate WinSocks, error %i", i_err );
        return ;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
982
#endif
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110