input.c 20.1 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
Henri Fallon's avatar
   
Henri Fallon committed
7
 * $Id: input.c,v 1.92 2001/03/11 19:00:18 henri 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
35
36
37
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
Michel Kaempf's avatar
Michel Kaempf committed
38

Henri Fallon's avatar
   
Henri Fallon committed
39
40
/* Network functions */

Sam Hocevar's avatar
   
Sam Hocevar committed
41
#ifndef SYS_BEOS
Henri Fallon's avatar
   
Henri Fallon committed
42
43
44
45
46
47
#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
48
#endif
Henri Fallon's avatar
   
Henri Fallon committed
49

50
51
52
53
#ifdef STATS
#   include <sys/times.h>
#endif

Michel Kaempf's avatar
Michel Kaempf committed
54
#include "config.h"
55
56
#include "common.h"
#include "threads.h"
Michel Kaempf's avatar
Michel Kaempf committed
57
#include "mtime.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
58
#include "modules.h"
59

60
#include "intf_msg.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
61
#include "intf_plst.h"
62

63
64
65
#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
Michel Lespinasse's avatar
Yop,    
Michel Lespinasse committed
66

67
#include "input.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
68
69
70
#include "interface.h"

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

Henri Fallon's avatar
   
Henri Fallon committed
72
73
74
 /* #include <netutils.h> */


75
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
76
 * Local prototypes
77
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
78
79
80
81
82
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
83

84
/*****************************************************************************
85
 * input_CreateThread: creates a new input thread
86
 *****************************************************************************
87
88
89
90
 * 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.
91
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
92
input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
93
{
94
95
96
    input_thread_t *    p_input;                        /* thread descriptor */
    int                 i_status;                           /* thread status */

97
98
99
    /* Allocate descriptor */
    p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
    if( p_input == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
100
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
101
102
        intf_ErrMsg( "input error: can't allocate input thread (%s)",
                     strerror(errno) );
Michel Kaempf's avatar
Michel Kaempf committed
103
104
        return( NULL );
    }
105

106
107
108
    /* Packets read once */
    p_input->i_read_once = INPUT_READ_ONCE;

109
110
111
    /* Initialize thread properties */
    p_input->b_die              = 0;
    p_input->b_error            = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
112
113
114
115
116
    p_input->b_eof              = 0;

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

117
    /* I have never understood that stuff --Meuuh */
118
119
    p_input->pi_status          = (pi_status != NULL) ? pi_status : &i_status;
    *p_input->pi_status         = THREAD_CREATE;
Michel Kaempf's avatar
Michel Kaempf committed
120

121
    /* Initialize stream description */
122
123
    p_input->stream.i_es_number = 0;
    p_input->stream.i_selected_es_number = 0;
124
    p_input->stream.i_pgrm_number = 0;
125
    p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
Christophe Massiot's avatar
Christophe Massiot committed
126
    p_input->stream.i_mux_rate = 0;
Michel Kaempf's avatar
Michel Kaempf committed
127

Stéphane Borel's avatar
   
Stéphane Borel committed
128
129
130
131
    p_input->stream.i_area_nb = 0;
    p_input->stream.pp_areas = NULL;
    /* By default there is one areas in a stream */
    input_AddArea( p_input );
132
133
    p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
    p_input->stream.p_selected_area->i_seek = NO_SEEK;
Stéphane Borel's avatar
   
Stéphane Borel committed
134

135
136
137
138
139
    /* 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;
    p_input->stream.control.b_bw = 0;
Michel Kaempf's avatar
Michel Kaempf committed
140

Sam Hocevar's avatar
   
Sam Hocevar committed
141
142
    /* Initialize default settings for spawned decoders */
    p_input->p_default_aout = p_main->p_aout;
Sam Hocevar's avatar
   
Sam Hocevar committed
143
    p_input->p_default_vout = p_main->p_vout;
Sam Hocevar's avatar
   
Sam Hocevar committed
144

Michel Kaempf's avatar
Michel Kaempf committed
145
    /* Create thread and set locks. */
146
    vlc_mutex_init( &p_input->stream.stream_lock );
147
    vlc_cond_init( &p_input->stream.stream_wait );
148
149
150
    vlc_mutex_init( &p_input->stream.control.control_lock );
    if( vlc_thread_create( &p_input->thread_id, "input", (void *) RunThread,
                           (void *) p_input ) )
Michel Kaempf's avatar
Michel Kaempf committed
151
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
152
153
        intf_ErrMsg( "input error: can't create input thread (%s)",
                     strerror(errno) );
Michel Kaempf's avatar
Michel Kaempf committed
154
155
156
        free( p_input );
        return( NULL );
    }
157

158
159
160
161
    /* If status is NULL, wait until the thread is created */
    if( pi_status == NULL )
    {
        do
162
        {
163
            msleep( THREAD_SLEEP );
164
        } while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
Sam Hocevar's avatar
   
Sam Hocevar committed
165
                && (i_status != THREAD_FATAL) );
166
167
        if( i_status != THREAD_READY )
        {
168
169
            return( NULL );
        }
170
    }
Michel Kaempf's avatar
Michel Kaempf committed
171
172
173
    return( p_input );
}

174
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
175
 * input_DestroyThread: mark an input thread as zombie
176
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
177
 * This function should not return until the thread is effectively cancelled.
178
 *****************************************************************************/
179
void input_DestroyThread( input_thread_t *p_input, int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
180
{
181
    int         i_status;                                   /* thread status */
182
183
184

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

187
188
    /* Request thread destruction */
    p_input->b_die = 1;
Michel Kaempf's avatar
Michel Kaempf committed
189

190
191
192
193
194
    /* 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 );

195
196
197
198
199
200
    /* If status is NULL, wait until thread has been destroyed */
    if( pi_status == NULL )
    {
        do
        {
            msleep( THREAD_SLEEP );
201
202
        } while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
                  && (i_status != THREAD_FATAL) );
203
    }
Michel Kaempf's avatar
Michel Kaempf committed
204
205
}

206
/*****************************************************************************
207
 * RunThread: main thread loop
208
 *****************************************************************************
209
 * Thread in charge of processing the network packets and demultiplexing.
210
 *****************************************************************************/
211
static void RunThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
212
{
213
    int                     i_error, i;
Michel Kaempf's avatar
Michel Kaempf committed
214

Sam Hocevar's avatar
   
Sam Hocevar committed
215
216
217
218
219
220
221
222
223
224
    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
225

Sam Hocevar's avatar
   
Sam Hocevar committed
226
    while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
227
    {
228
        data_packet_t *         pp_packets[p_input->i_read_once];
229

Sam Hocevar's avatar
   
Sam Hocevar committed
230
#ifdef STATS
Sam Hocevar's avatar
   
Sam Hocevar committed
231
        p_input->c_loops++;
Sam Hocevar's avatar
   
Sam Hocevar committed
232
233
#endif

234
        vlc_mutex_lock( &p_input->stream.stream_lock );
235
        if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
Sam Hocevar's avatar
   
Sam Hocevar committed
236
        {
237
238
            if( p_input->stream.b_seekable && p_input->pf_seek != NULL )
            {
239
240
                p_input->pf_seek( p_input,
                                  p_input->stream.p_selected_area->i_seek );
241
242
243
244
245
246
247
248
249
250
251
252
253

                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;
                }
            }
254
            p_input->stream.p_selected_area->i_seek = NO_SEEK;
Sam Hocevar's avatar
   
Sam Hocevar committed
255
        }
256
        vlc_mutex_unlock( &p_input->stream.stream_lock );
Sam Hocevar's avatar
   
Sam Hocevar committed
257
258

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

Sam Hocevar's avatar
   
Sam Hocevar committed
260
        /* Demultiplex read packets. */
261
        for( i = 0; i < p_input->i_read_once && pp_packets[i] != NULL; i++ )
Sam Hocevar's avatar
   
Sam Hocevar committed
262
263
264
        {
            p_input->pf_demux( p_input, pp_packets[i] );
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
265

Sam Hocevar's avatar
   
Sam Hocevar committed
266
267
268
        if( i_error )
        {
            if( i_error == 1 )
Sam Hocevar's avatar
Sam Hocevar committed
269
            {
Sam Hocevar's avatar
   
Sam Hocevar committed
270
271
272
273
                /* End of file - we do not set b_die because only the
                 * interface is allowed to do so. */
                intf_WarnMsg( 1, "End of file reached" );
                p_input->b_eof = 1;
Sam Hocevar's avatar
   
Sam Hocevar committed
274
            }
Sam Hocevar's avatar
   
Sam Hocevar committed
275
            else
Sam Hocevar's avatar
   
Sam Hocevar committed
276
            {
Sam Hocevar's avatar
   
Sam Hocevar committed
277
                p_input->b_error = 1;
Sam Hocevar's avatar
Sam Hocevar committed
278
            }
279
280
281
        }
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
282
    if( p_input->b_error || p_input->b_eof )
283
284
285
    {
        ErrorThread( p_input );
    }
286

287
    EndThread( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
288
289
290

    DestroyThread( p_input );

291
    intf_DbgMsg("Thread end");
292
293
}

294
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
295
 * InitThread: init the input Thread
296
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
297
static int InitThread( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
298
299
300
{

#ifdef STATS
301
302
303
304
305
306
    /* Initialize statistics */
    p_input->c_loops                    = 0;
    p_input->c_bytes                    = 0;
    p_input->c_payload_bytes            = 0;
    p_input->c_packets_read             = 0;
    p_input->c_packets_trashed          = 0;
Michel Kaempf's avatar
Michel Kaempf committed
307
#endif
Sam Hocevar's avatar
Sam Hocevar committed
308

Sam Hocevar's avatar
   
Sam Hocevar committed
309
    p_input->p_input_module = module_Need( p_main->p_bank,
Sam Hocevar's avatar
   
Sam Hocevar committed
310
311
                                           MODULE_CAPABILITY_INPUT,
                                           (probedata_t *)p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
312
313

    if( p_input->p_input_module == NULL )
314
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
315
        intf_ErrMsg( "input error: no suitable input module" );
Sam Hocevar's avatar
   
Sam Hocevar committed
316
        return( -1 );
Michel Kaempf's avatar
Michel Kaempf committed
317
    }
318

Sam Hocevar's avatar
   
Sam Hocevar committed
319
320
321
322
323
324
#define f p_input->p_input_module->p_functions->input.functions.input
    p_input->pf_init          = f.pf_init;
    p_input->pf_open          = f.pf_open;
    p_input->pf_close         = f.pf_close;
    p_input->pf_end           = f.pf_end;
    p_input->pf_read          = f.pf_read;
325
    p_input->pf_set_area      = f.pf_set_area;
Sam Hocevar's avatar
   
Sam Hocevar committed
326
327
328
329
330
331
332
333
334
    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
    p_input->pf_open( p_input );
335

Sam Hocevar's avatar
   
Sam Hocevar committed
336
    if( p_input->b_error )
337
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
338
339
        /* We barfed -- exit nicely */
        p_input->pf_close( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
340
        module_Unneed( p_main->p_bank, p_input->p_input_module );
Sam Hocevar's avatar
   
Sam Hocevar committed
341
        return( -1 );
342
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
343
344

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

Sam Hocevar's avatar
   
Sam Hocevar committed
346
    *p_input->pi_status = THREAD_READY;
Sam Hocevar's avatar
   
Sam Hocevar committed
347
348

    return( 0 );
Michel Kaempf's avatar
Michel Kaempf committed
349
350
}

351
/*****************************************************************************
352
 * ErrorThread: RunThread() error loop
353
 *****************************************************************************
354
 * This function is called when an error occured during thread main's loop.
355
 *****************************************************************************/
356
static void ErrorThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
357
{
358
    while( !p_input->b_die )
Michel Kaempf's avatar
Michel Kaempf committed
359
    {
360
361
        /* Sleep a while */
        msleep( INPUT_IDLE_SLEEP );
Michel Kaempf's avatar
Michel Kaempf committed
362
363
364
    }
}

365
/*****************************************************************************
366
 * EndThread: end the input thread
367
 *****************************************************************************/
368
static void EndThread( input_thread_t * p_input )
369
{
370
    int *       pi_status;                                  /* thread status */
371

372
373
374
    /* Store status */
    pi_status = p_input->pi_status;
    *pi_status = THREAD_END;
Sam Hocevar's avatar
Sam Hocevar committed
375

Sam Hocevar's avatar
   
Sam Hocevar committed
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
#ifdef STATS
    {
        struct tms cpu_usage;
        times( &cpu_usage );

        intf_Msg("input stats: cpu usage (user: %d, system: %d)",
                 cpu_usage.tms_utime, cpu_usage.tms_stime);
    }
#endif

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

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

Sam Hocevar's avatar
   
Sam Hocevar committed
392
393
394
    /* Close stream */
    p_input->pf_close( p_input );

Sam Hocevar's avatar
   
Sam Hocevar committed
395
    /* Release modules */
Sam Hocevar's avatar
   
Sam Hocevar committed
396
    module_Unneed( p_main->p_bank, p_input->p_input_module );
Sam Hocevar's avatar
   
Sam Hocevar committed
397

Sam Hocevar's avatar
   
Sam Hocevar committed
398
399
400
401
402
403
404
405
406
407
408
}

/*****************************************************************************
 * 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
409

Henri Fallon's avatar
   
Henri Fallon committed
410
411
    /* Destroy Mutex locks */
    vlc_mutex_destroy( &p_input->stream.control.control_lock );
Henri Fallon's avatar
   
Henri Fallon committed
412
    vlc_mutex_destroy( &p_input->stream.stream_lock );
Henri Fallon's avatar
   
Henri Fallon committed
413
    
414
    /* Free input structure */
415
    free( p_input );
416

417
418
    /* Update status */
    *pi_status = THREAD_OVER;
Sam Hocevar's avatar
Sam Hocevar committed
419
}
420

Sam Hocevar's avatar
Sam Hocevar committed
421
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
422
 * input_FileOpen : open a file descriptor
Sam Hocevar's avatar
Sam Hocevar committed
423
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
424
void input_FileOpen( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
425
{
426
    struct stat         stat_info;
Sam Hocevar's avatar
   
Sam Hocevar committed
427
428
429
    int                 i_stat;

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

Sam Hocevar's avatar
   
Sam Hocevar committed
431
432
433
    /* FIXME: this code ought to be in the plugin so that code can
     * be shared with the *_Probe function */
    if( ( i_stat = stat( psz_name, &stat_info ) ) == (-1) )
Sam Hocevar's avatar
   
Sam Hocevar committed
434
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
435
436
437
438
439
440
441
442
        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
443
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
444
        else if( ( i_size > 5 )
Sam Hocevar's avatar
   
Sam Hocevar committed
445
446
447
448
449
                 && !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
450
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
451

Sam Hocevar's avatar
   
Sam Hocevar committed
452
        if( i_stat == (-1) )
Sam Hocevar's avatar
   
Sam Hocevar committed
453
454
455
456
457
458
        {
            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
459
460
461
462
463
464
465
466
467
468
469
    }

    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)
         || S_ISBLK(stat_info.st_mode) )
    {
        p_input->stream.b_seekable = 1;
470
        p_input->stream.p_selected_area->i_size = stat_info.st_size;
Sam Hocevar's avatar
   
Sam Hocevar committed
471
    }
Jean-Marc Dressler's avatar
   
Jean-Marc Dressler committed
472
473
474
475
476
    else if( S_ISFIFO(stat_info.st_mode)
#ifndef SYS_BEOS
             || S_ISSOCK(stat_info.st_mode)
#endif
             )
Sam Hocevar's avatar
Sam Hocevar committed
477
    {
478
        p_input->stream.b_seekable = 0;
479
        p_input->stream.p_selected_area->i_size = 0;
Benoit Steiner's avatar
   
Benoit Steiner committed
480
481
482
    }
    else
    {
483
        vlc_mutex_unlock( &p_input->stream.stream_lock );
Sam Hocevar's avatar
   
Sam Hocevar committed
484
        intf_ErrMsg( "input error: unknown file type for `%s'",
Sam Hocevar's avatar
   
Sam Hocevar committed
485
                     psz_name );
Sam Hocevar's avatar
   
Sam Hocevar committed
486
487
488
        p_input->b_error = 1;
        return;
    }
489

490
    p_input->stream.p_selected_area->i_tell = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
491
492
    vlc_mutex_unlock( &p_input->stream.stream_lock );

Sam Hocevar's avatar
   
Sam Hocevar committed
493
494
    intf_Msg( "input: opening %s", p_input->p_source );
    if( (p_input->i_handle = open( psz_name,
Sam Hocevar's avatar
   
Sam Hocevar committed
495
496
                                   /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
497
        intf_ErrMsg( "input error: cannot open file (%s)", strerror(errno) );
Sam Hocevar's avatar
   
Sam Hocevar committed
498
499
        p_input->b_error = 1;
        return;
Michel Kaempf's avatar
Michel Kaempf committed
500
501
502
    }

}
Stéphane Borel's avatar
Stéphane Borel committed
503
504

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
505
 * input_FileClose : close a file descriptor
Stéphane Borel's avatar
Stéphane Borel committed
506
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
507
void input_FileClose( input_thread_t * p_input )
Stéphane Borel's avatar
Stéphane Borel committed
508
{
Sam Hocevar's avatar
   
Sam Hocevar committed
509
    close( p_input->i_handle );
Stéphane Borel's avatar
Stéphane Borel committed
510

Sam Hocevar's avatar
   
Sam Hocevar committed
511
    return;
Stéphane Borel's avatar
Stéphane Borel committed
512
}
Sam Hocevar's avatar
   
Sam Hocevar committed
513

Henri Fallon's avatar
   
Henri Fallon committed
514

Sam Hocevar's avatar
   
Sam Hocevar committed
515
#ifndef SYS_BEOS
Henri Fallon's avatar
   
Henri Fallon committed
516
/*****************************************************************************
Henri Fallon's avatar
   
Henri Fallon committed
517
 * input_NetworkOpen : open a network socket 
Henri Fallon's avatar
   
Henri Fallon committed
518
 *****************************************************************************/
Henri Fallon's avatar
   
Henri Fallon committed
519
void input_NetworkOpen( input_thread_t * p_input )
Henri Fallon's avatar
   
Henri Fallon committed
520
{
Henri Fallon's avatar
   
Henri Fallon committed
521
522
523
524
 
    int                 i_option_value, i_port;
    struct sockaddr_in  s_socket;
    boolean_t           b_broadcast;
Henri Fallon's avatar
   
Henri Fallon committed
525
    
Henri Fallon's avatar
   
Henri Fallon committed
526
    /* FIXME : we don't handle channels for the moment */
Henri Fallon's avatar
   
Henri Fallon committed
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
    
    /* Get the remote server */
    if( p_input->p_source == NULL )
    {
        p_input->p_source = main_GetPszVariable( INPUT_SERVER_VAR, 
                                                 INPUT_SERVER_DEFAULT );
    }
    
    /* 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 )
    {
        intf_ErrMsg("NetworkOpen : can't create socket : %s", strerror(errno));
        p_input->b_error = 1;
        return;
    }

    /* We may want to reuse an already used socket */
    i_option_value = 1;
    if( setsockopt( p_input->i_handle, SOL_SOCKET, SO_REUSEADDR,
                    &i_option_value,sizeof( i_option_value ) ) == -1 )
    {
        intf_ErrMsg("NetworkOpen : can't configure socket (SO_REUSEADDR: %s)",
                    strerror(errno));
        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 */
    i_option_value = 524288;
    if( setsockopt( p_input->i_handle, SOL_SOCKET, SO_RCVBUF, &i_option_value,
                    sizeof( i_option_value ) ) == -1 )
    {
        intf_ErrMsg("NetworkOpen : can't configure socket (SO_RCVBUF: %s)", 
                    strerror(errno));
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }

    /* Get details about what we are supposed to do */
    b_broadcast = (boolean_t)main_GetIntVariable( INPUT_BROADCAST_VAR, 0 );
    i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );

    /* TODO : here deal with channel stufs */
Henri Fallon's avatar
   
Henri Fallon committed
575
    
Henri Fallon's avatar
   
Henri Fallon committed
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
    /* Build the local socket */
    if ( input_BuildLocalAddr( &s_socket, i_port, b_broadcast ) 
         == -1 )
    {
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }
    
    /* Bind it */
    if( bind( p_input->i_handle, (struct sockaddr *)&s_socket, 
              sizeof( s_socket ) ) < 0 )
    {
        intf_ErrMsg("NetworkOpen: can't bind socket (%s)", strerror(errno));
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }

    /* Build socket for remote connection */
Henri Fallon's avatar
   
Henri Fallon committed
596
    if ( input_BuildRemoteAddr( &s_socket, p_input->p_source ) 
Henri Fallon's avatar
   
Henri Fallon committed
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
         == -1 )
    {
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }

    /* And connect it ... should we really connect ? */
    if( connect( p_input->i_handle, (struct sockaddr *) &s_socket,
                 sizeof( s_socket ) ) == (-1) )
    {
        intf_ErrMsg("NetworkOpen: can't connect socket" );
        close( p_input->i_handle );
        p_input->b_error = 1;
        return;
    }

    /* We can't pace control, but FIXME : bug in meuuh's code to sync PCR
     * with the server. */
    p_input->stream.b_pace_control = 1;
    
    return;
}

/*****************************************************************************
 * input_NetworkClose : close a network socket
 *****************************************************************************/
void input_NetworkClose( input_thread_t * p_input )
{
    close( p_input->i_handle );
    /* FIXME: deal with channels */
}
Sam Hocevar's avatar
   
Sam Hocevar committed
629
#endif