main.c 25.4 KB
Newer Older
1
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
2
3
4
 * main.c: main vlc source
 * Includes the main() function for vlc. Parses command line, start interface
 * and spawn threads.
5
6
7
8
9
10
11
12
13
 *****************************************************************************
 * Copyright (C) 1998, 1999, 2000 VideoLAN
 *
 * Authors:
 *
 * 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.
14
 * 
15
16
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
19
 *
20
21
22
 * 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.
23
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
24

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

30
#include <signal.h>                               /* SIGHUP, SIGINT, SIGKILL */
31
#include <getopt.h>                                              /* getopt() */
32
33
34
35
36
#include <stdio.h>                                              /* sprintf() */

#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                  /* getenv(), strtol(),  */
#include <string.h>                                            /* strerror() */
Vincent Seguin's avatar
Vincent Seguin committed
37

Michel Kaempf's avatar
Michel Kaempf committed
38
39
#include "config.h"
#include "common.h"
40
#include "threads.h"
Michel Kaempf's avatar
Michel Kaempf committed
41
#include "mtime.h"
Sam Hocevar's avatar
Sam Hocevar committed
42
#include "tests.h"                                              /* TestMMX() */
43
#include "plugins.h"
44
#include "playlist.h"
Michel Kaempf's avatar
Michel Kaempf committed
45
#include "input_vlan.h"
Sam Hocevar's avatar
Sam Hocevar committed
46
#include "input_ps.h"
47

Vincent Seguin's avatar
Vincent Seguin committed
48
#include "intf_msg.h"
Michel Kaempf's avatar
Michel Kaempf committed
49
#include "interface.h"
50

Vincent Seguin's avatar
Vincent Seguin committed
51
#include "audio_output.h"
52

53
54
55
56
#ifdef SYS_BEOS
#include "beos_specific.h"
#endif

Vincent Seguin's avatar
Vincent Seguin committed
57
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
58

59
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
60
61
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
62
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
63
64
65
66

/* Long options return values - note that values corresponding to short options
 * chars, and in general any regular char, should be avoided */
#define OPT_NOAUDIO             150
67
68
69
#define OPT_AOUT                151
#define OPT_STEREO              152
#define OPT_MONO                153
Michel Kaempf's avatar
Michel Kaempf committed
70
71

#define OPT_NOVIDEO             160
72
73
74
75
76
#define OPT_VOUT                161
#define OPT_DISPLAY             162
#define OPT_WIDTH               163
#define OPT_HEIGHT              164
#define OPT_COLOR               165
Sam Hocevar's avatar
Sam Hocevar committed
77
#define OPT_YUV                 166
Michel Kaempf's avatar
Michel Kaempf committed
78
79

#define OPT_NOVLANS             170
80
81
#define OPT_SERVER              171
#define OPT_PORT                172
82

83
/* Usage fashion */
84
85
86
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
87

Michel Kaempf's avatar
Michel Kaempf committed
88
89
/* Long options */
static const struct option longopts[] =
90
91
{
    /*  name,               has_arg,    flag,   val */
Michel Kaempf's avatar
Michel Kaempf committed
92
93

    /* General/common options */
94
    {   "help",             0,          0,      'h' },
95
    {   "longhelp",         0,          0,      'H' },
96
    {   "version",          0,          0,      'v' },
Michel Kaempf's avatar
Michel Kaempf committed
97
98

    /* Audio options */
99
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
100
    {   "aout",             1,          0,      OPT_AOUT },
Michel Kaempf's avatar
Michel Kaempf committed
101
    {   "stereo",           0,          0,      OPT_STEREO },
102
    {   "mono",             0,          0,      OPT_MONO },
Michel Kaempf's avatar
Michel Kaempf committed
103
104

    /* Video options */
105
    {   "novideo",          0,          0,      OPT_NOVIDEO },
106
    {   "vout",             1,          0,      OPT_VOUT },
107
    {   "display",          1,          0,      OPT_DISPLAY },
108
    {   "width",            1,          0,      OPT_WIDTH },
109
110
111
    {   "height",           1,          0,      OPT_HEIGHT },
    {   "grayscale",        0,          0,      'g' },
    {   "color",            0,          0,      OPT_COLOR },
Sam Hocevar's avatar
Sam Hocevar committed
112
    {   "yuv",              1,          0,      OPT_YUV },
Michel Kaempf's avatar
Michel Kaempf committed
113

114
115
116
117
118
    /* DVD options */
    {   "dvdaudio",         1,          0,      'a' },
    {   "dvdchannel",       1,          0,      'c' },
    {   "dvdsubtitle",      1,          0,      's' },
    
119
    /* Input options */
Michel Kaempf's avatar
Michel Kaempf committed
120
    {   "novlans",          0,          0,      OPT_NOVLANS },
121
122
    {   "server",           1,          0,      OPT_SERVER },
    {   "port",             1,          0,      OPT_PORT },
Michel Kaempf's avatar
Michel Kaempf committed
123
124
125
126
127

    {   0,                  0,          0,      0 }
};

/* Short options */
128
static const char *psz_shortopts = "hHvga:s:c:";
Michel Kaempf's avatar
Michel Kaempf committed
129

130
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
131
 * Global variable program_data - this is the one and only, see main.h
132
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
133
main_t *p_main;
Michel Kaempf's avatar
Michel Kaempf committed
134

135
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
136
 * Local prototypes
137
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
138
static void SetDefaultConfiguration ( void );
139
140
static int  GetConfiguration        ( int i_argc, char *ppsz_argv[],
                                      char *ppsz_env[] );
141
static void Usage                   ( int i_fashion );
Vincent Seguin's avatar
Vincent Seguin committed
142
static void Version                 ( void );
Vincent Seguin's avatar
Vincent Seguin committed
143

Michel Kaempf's avatar
Michel Kaempf committed
144
145
static void InitSignalHandler       ( void );
static void SignalHandler           ( int i_signal );
146
#ifdef HAVE_MMX
147
static int  TestMMX                 ( void );
148
#endif
Michel Kaempf's avatar
Michel Kaempf committed
149

150
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
151
 * main: parse command line, start interface and spawn threads
152
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
153
154
 * Steps during program execution are:
 *      -configuration parsing and messages interface initialization
155
 *      -opening of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
156
 *      -execution of interface, which exit on error or on user request
Vincent Seguin's avatar
Vincent Seguin committed
157
 *      -closing of audio output device and some global modules
158
 * On error, the spawned threads are canceled, and the open devices closed.
159
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
160
161
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
162
    main_t  main_data;                      /* root of all data - see main.h */
163

164
    p_main = &main_data;                       /* set up the global variable */
Vincent Seguin's avatar
Vincent Seguin committed
165

166
167
168
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
Sam Hocevar committed
169
#ifdef SYS_BEOS
170
    beos_Create();
171
172
#endif

Michel Kaempf's avatar
Michel Kaempf committed
173
    /*
174
     * Test if our code is likely to run on this CPU 
175
     */
Sam Hocevar's avatar
Sam Hocevar committed
176
#ifdef HAVE_MMX
177
178
    if( !TestMMX() )
    {
179
180
        fprintf( stderr, "Sorry, this program needs an MMX processor. "
                         "Please run the non-MMX version.\n" );
181
        return( 1 );
182
183
    }
#endif
184
185
186
187

    /*
     * Initialize messages interface
     */
Vincent Seguin's avatar
Vincent Seguin committed
188
    p_main->p_msg = intf_MsgCreate();
189
    if( !p_main->p_msg )                         /* start messages interface */
Michel Kaempf's avatar
Michel Kaempf committed
190
    {
191
        fprintf( stderr, "error: can't initialize messages interface (%s)\n",
192
193
                strerror(errno) );
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
194
    }
195
196
197
198

    /*
     * Read configuration
     */
199
    if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )  /* parse cmd line */
Michel Kaempf's avatar
Michel Kaempf committed
200
    {
Vincent Seguin's avatar
Vincent Seguin committed
201
        intf_MsgDestroy();
202
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
203
    }
204

205
206
207
208
209
    /*
     * Initialize playlist and get commandline files
     */
    p_main->p_playlist = playlist_Create( );
    if( !p_main->p_playlist )
210
    {
211
212
213
        intf_Msg( "Playlist initialization failed\n" );
        intf_MsgDestroy();
        return( errno );
214
    }
215
216
217
218
219
220
221
    playlist_Init( p_main->p_playlist, optind );

    /*
     * Initialize plugin bank
     */
    p_main->p_bank = bank_Create( );
    if( !p_main->p_bank )
222
    {
223
224
225
226
        intf_Msg( "Plugin bank initialization failed\n" );
        playlist_Destroy( p_main->p_playlist );
        intf_MsgDestroy();
        return( errno );
227
    }
228
    bank_Init( p_main->p_bank );
Michel Kaempf's avatar
Michel Kaempf committed
229
230
231
232

    /*
     * Initialize shared resources and libraries
     */
233
    if( p_main->b_vlans && input_VlanCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
234
    {
235
236
237
238
        /* On error during vlans initialization, switch off vlans */
        intf_Msg( "Virtual LANs initialization failed : "
                  "vlans management is deactivated\n" );
        p_main->b_vlans = 0;
Michel Kaempf's avatar
Michel Kaempf committed
239
    }
240

Michel Kaempf's avatar
Michel Kaempf committed
241
    /*
Vincent Seguin's avatar
Vincent Seguin committed
242
     * Open audio device and start aout thread
Michel Kaempf's avatar
Michel Kaempf committed
243
     */
244
    if( p_main->b_audio )
Vincent Seguin's avatar
Vincent Seguin committed
245
    {
246
247
        p_main->p_aout = aout_CreateThread( NULL );
        if( p_main->p_aout == NULL )
248
        {
249
            /* On error during audio initialization, switch off audio */
250
            intf_Msg( "Audio initialization failed : audio is deactivated\n" );
251
            p_main->b_audio = 0;
252
        }
Michel Kaempf's avatar
Michel Kaempf committed
253
    }
254

Michel Kaempf's avatar
Michel Kaempf committed
255
256
257
    /*
     * Run interface
     */
258
259
    p_main->p_intf = intf_Create();
    if( p_main->p_intf != NULL )
Vincent Seguin's avatar
Vincent Seguin committed
260
    {
261
        InitSignalHandler();             /* prepare signals for interception */
262

Sam Hocevar's avatar
Sam Hocevar committed
263
264
265
        /*
         * This is the main loop
         */
266
267
268
        intf_Run( p_main->p_intf );

        intf_Destroy( p_main->p_intf );
Vincent Seguin's avatar
Vincent Seguin committed
269
    }
Michel Kaempf's avatar
Michel Kaempf committed
270

Michel Kaempf's avatar
Michel Kaempf committed
271
    /*
Michel Kaempf's avatar
Michel Kaempf committed
272
273
     * Close audio device
     */
274
    if( p_main->b_audio )
Michel Kaempf's avatar
Michel Kaempf committed
275
    {
276
        aout_DestroyThread( p_main->p_aout, NULL );
Michel Kaempf's avatar
Michel Kaempf committed
277
    }
Michel Kaempf's avatar
Michel Kaempf committed
278
279
280
281

    /*
     * Free shared resources and libraries
     */
282
    if( p_main->b_vlans )
283
284
285
    {
        input_VlanDestroy();
    }
Michel Kaempf's avatar
Michel Kaempf committed
286

287
    /*
288
     * Free plugin bank
289
     */
290
291
292
293
294
295
296
    bank_Destroy( p_main->p_bank );

    /*
     * Free playlist
     */
    playlist_Destroy( p_main->p_playlist );

297
#ifdef SYS_BEOS
298
299
300
301
    /*
     * System specific cleaning code
     */
    beos_Destroy();
302
303
#endif

Michel Kaempf's avatar
Michel Kaempf committed
304
305
306
    /*
     * Terminate messages interface and program
     */
Vincent Seguin's avatar
Vincent Seguin committed
307
308
    intf_Msg( "Program terminated.\n" );
    intf_MsgDestroy();
309

Michel Kaempf's avatar
Michel Kaempf committed
310
311
312
    return( 0 );
}

313
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
314
 * main_GetIntVariable: get the int value of an environment variable
315
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
316
 * This function is used to read some default parameters in modules.
317
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
318
319
int main_GetIntVariable( char *psz_name, int i_default )
{
320
321
322
    char *      psz_env;                                /* environment value */
    char *      psz_end;                             /* end of parsing index */
    long int    i_value;                                            /* value */
Vincent Seguin's avatar
Vincent Seguin committed
323
324
325

    psz_env = getenv( psz_name );
    if( psz_env )
326
    {
327
328
329
330
        i_value = strtol( psz_env, &psz_end, 0 );
        if( (*psz_env != '\0') && (*psz_end == '\0') )
        {
            return( i_value );
331
        }
332
    }
Vincent Seguin's avatar
Vincent Seguin committed
333
334
335
    return( i_default );
}

336
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
337
 * main_GetPszVariable: get the string value of an environment variable
338
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
339
 * This function is used to read some default parameters in modules.
340
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
341
342
343
344
345
346
347
char * main_GetPszVariable( char *psz_name, char *psz_default )
{
    char *psz_env;

    psz_env = getenv( psz_name );
    if( psz_env )
    {
348
        return( psz_env );
Vincent Seguin's avatar
Vincent Seguin committed
349
    }
350
    return( psz_default );
Vincent Seguin's avatar
Vincent Seguin committed
351
352
}

353
/*****************************************************************************
354
 * main_PutPszVariable: set the string value of an environment variable
355
 *****************************************************************************
356
357
358
 * This function is used to set some default parameters in modules. The use of
 * this function will cause some memory leak: since some systems use the pointer
 * passed to putenv to store the environment string, it can't be freed.
359
 *****************************************************************************/
360
361
362
363
364
365
366
void main_PutPszVariable( char *psz_name, char *psz_value )
{
    char *psz_env;

    psz_env = malloc( strlen(psz_name) + strlen(psz_value) + 2 );
    if( psz_env == NULL )
    {
367
        intf_ErrMsg( "error: %s\n", strerror(ENOMEM) );
368
369
370
371
372
373
    }
    else
    {
        sprintf( psz_env, "%s=%s", psz_name, psz_value );
        if( putenv( psz_env ) )
        {
374
            intf_ErrMsg( "error: %s\n", strerror(errno) );
375
        }
376
377
378
    }
}

379
/*****************************************************************************
380
 * main_PutIntVariable: set the integer value of an environment variable
381
 *****************************************************************************
382
383
384
 * This function is used to set some default parameters in modules. The use of
 * this function will cause some memory leak: since some systems use the pointer
 * passed to putenv to store the environment string, it can't be freed.
385
 *****************************************************************************/
386
387
void main_PutIntVariable( char *psz_name, int i_value )
{
388
    char psz_value[ 256 ];                               /* buffer for value */
389

390
    sprintf( psz_value, "%d", i_value );
391
    main_PutPszVariable( psz_name, psz_value );
392
393
}

Michel Kaempf's avatar
Michel Kaempf committed
394
395
/* following functions are local */

396
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
397
 * SetDefaultConfiguration: set default options
398
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
399
 * This function is called by GetConfiguration before command line is parsed.
Vincent Seguin's avatar
Vincent Seguin committed
400
401
402
 * It sets all the default values required later by the program. At this stage,
 * most structure are not yet allocated, so initialization must be done using
 * environment.
403
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
404
static void SetDefaultConfiguration( void )
Michel Kaempf's avatar
Michel Kaempf committed
405
406
{
    /*
Vincent Seguin's avatar
Vincent Seguin committed
407
     * All features are activated by default
Michel Kaempf's avatar
Michel Kaempf committed
408
     */
Vincent Seguin's avatar
Vincent Seguin committed
409
410
411
    p_main->b_audio  = 1;
    p_main->b_video  = 1;
    p_main->b_vlans  = 1;
Michel Kaempf's avatar
Michel Kaempf committed
412
413
}

414
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
415
 * GetConfiguration: parse command line
416
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
417
418
 * Parse command line and configuration file for configuration. If the inline
 * help is requested, the function Usage() is called and the function returns
419
 * -1 (causing main() to exit). The messages interface is initialized at this
Vincent Seguin's avatar
Vincent Seguin committed
420
421
 * stage, but most structures are not allocated, so only environment should
 * be used.
422
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
423
static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
Michel Kaempf's avatar
Michel Kaempf committed
424
{
Vincent Seguin's avatar
Vincent Seguin committed
425
    int c, i_opt;
Sam Hocevar's avatar
Sam Hocevar committed
426
    char * p_pointer;
Michel Kaempf's avatar
Michel Kaempf committed
427
428

    /* Set default configuration and copy arguments */
Vincent Seguin's avatar
Vincent Seguin committed
429
430
    p_main->i_argc    = i_argc;
    p_main->ppsz_argv = ppsz_argv;
431
    p_main->ppsz_env  = ppsz_env;
Vincent Seguin's avatar
Vincent Seguin committed
432
    SetDefaultConfiguration();
Michel Kaempf's avatar
Michel Kaempf committed
433

Sam Hocevar's avatar
Sam Hocevar committed
434
435
    intf_MsgImm( COPYRIGHT_MESSAGE "\n" );

Sam Hocevar's avatar
Sam Hocevar committed
436
437
438
439
440
441
442
443
444
445
446
447
448
449
    /* Get the executable name */
    p_main->psz_arg0 = p_pointer = ppsz_argv[ 0 ];
    while( *p_pointer )
    {
        if( *p_pointer == '/' )
        {
            p_main->psz_arg0 = ++p_pointer;
        }
        else
        {
            ++p_pointer;
        }
    }

Vincent Seguin's avatar
Vincent Seguin committed
450
    /* Parse command line options */
Michel Kaempf's avatar
Michel Kaempf committed
451
452
453
454
455
    opterr = 0;
    while( ( c = getopt_long( i_argc, ppsz_argv, psz_shortopts, longopts, 0 ) ) != EOF )
    {
        switch( c )
        {
456
457
        /* General/common options */
        case 'h':                                              /* -h, --help */
458
459
460
            Usage( SHORT_HELP );
            return( -1 );
            break;
461
        case 'H':                                          /* -H, --longhelp */
462
            Usage( LONG_HELP );
Michel Kaempf's avatar
Michel Kaempf committed
463
464
            return( -1 );
            break;
465
        case 'v':                                           /* -v, --version */
Vincent Seguin's avatar
Vincent Seguin committed
466
467
            Version();
            return( -1 );
468
            break;
Michel Kaempf's avatar
Michel Kaempf committed
469
470

        /* Audio options */
471
        case OPT_NOAUDIO:                                       /* --noaudio */
472
            p_main->b_audio = 0;
Michel Kaempf's avatar
Michel Kaempf committed
473
            break;
474
475
476
        case OPT_AOUT:                                             /* --aout */
            main_PutPszVariable( AOUT_METHOD_VAR, optarg );
            break;
477
        case OPT_STEREO:                                         /* --stereo */
478
            main_PutIntVariable( AOUT_STEREO_VAR, 1 );
Michel Kaempf's avatar
Michel Kaempf committed
479
            break;
480
        case OPT_MONO:                                             /* --mono */
481
            main_PutIntVariable( AOUT_STEREO_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
482
483
484
            break;

        /* Video options */
485
        case OPT_NOVIDEO:                                       /* --novideo */
Vincent Seguin's avatar
Vincent Seguin committed
486
            p_main->b_video = 0;
487
            break;
488
489
490
        case OPT_VOUT:                                             /* --vout */
            main_PutPszVariable( VOUT_METHOD_VAR, optarg );
            break;
491
        case OPT_DISPLAY:                                       /* --display */
492
            main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
493
494
            break;
        case OPT_WIDTH:                                           /* --width */
495
            main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
496
497
498
499
500
501
            break;
        case OPT_HEIGHT:                                         /* --height */
            main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );
            break;

        case 'g':                                         /* -g, --grayscale */
502
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
503
504
            break;
        case OPT_COLOR:                                           /* --color */
505
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
506
            break;
Sam Hocevar's avatar
Sam Hocevar committed
507
508
509
        case OPT_YUV:                                               /* --yuv */
            main_PutPszVariable( YUV_METHOD_VAR, optarg );
            break;
Michel Kaempf's avatar
Michel Kaempf committed
510

511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
        /* DVD options */
        case 'a':
            if ( ! strcmp(optarg, "mpeg") )
                main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_MPEG );
            else if ( ! strcmp(optarg, "lpcm") )
                main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_LPCM );
            else if ( ! strcmp(optarg, "off") )
                main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_NOAUDIO );
            else
                main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_AC3 );
            break;
        case 'c':
            main_PutIntVariable( INPUT_DVD_CHANNEL_VAR, atoi(optarg) );
            break;
        case 's':
            main_PutIntVariable( INPUT_DVD_SUBTITLE_VAR, atoi(optarg) );
            break;

529
        /* Input options */
530
        case OPT_NOVLANS:                                       /* --novlans */
Vincent Seguin's avatar
Vincent Seguin committed
531
            p_main->b_vlans = 0;
532
533
            break;
        case OPT_SERVER:                                         /* --server */
534
            main_PutPszVariable( INPUT_SERVER_VAR, optarg );
535
536
            break;
        case OPT_PORT:                                             /* --port */
537
            main_PutPszVariable( INPUT_PORT_VAR, optarg );
538
            break;
539

Michel Kaempf's avatar
Michel Kaempf committed
540
        /* Internal error: unknown option */
541
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
542
        default:
543
544
            intf_ErrMsg( "intf error: unknown option `%s'\n", ppsz_argv[optind - 1] );
            Usage( USAGE );
Michel Kaempf's avatar
Michel Kaempf committed
545
546
547
548
549
            return( EINVAL );
            break;
        }
    }

Vincent Seguin's avatar
Vincent Seguin committed
550
551
552
    /* Parse command line parameters - no check is made for these options */
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
553
        putenv( ppsz_argv[ i_opt ] );
Vincent Seguin's avatar
Vincent Seguin committed
554
    }
Michel Kaempf's avatar
Michel Kaempf committed
555
556
557
    return( 0 );
}

558
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
559
 * Usage: print program usage
560
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
561
 * Print a short inline help. Message interface is initialized at this stage.
562
 *****************************************************************************/
563
static void Usage( int i_fashion )
Michel Kaempf's avatar
Michel Kaempf committed
564
{
Vincent Seguin's avatar
Vincent Seguin committed
565
    /* Usage */
Sam Hocevar's avatar
Sam Hocevar committed
566
567
    intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
              p_main->psz_arg0 );
568
569
570

    if( i_fashion == USAGE )
    {
Sam Hocevar's avatar
Sam Hocevar committed
571
572
        intf_Msg( "Try `%s --help' for more information.\n",
                  p_main->psz_arg0 );
573
574
575
        return;
    }

Vincent Seguin's avatar
Vincent Seguin committed
576
    /* Options */
577
578
579
580
581
582
    intf_Msg( "\n"
              "Options:\n"
              "      --noaudio                  \tdisable audio\n"
              "      --aout <plugin>            \taudio output method\n"
              "      --stereo, --mono           \tstereo/mono audio\n"
              "\n"
583
              "      --novideo                  \tdisable video\n"
584
585
586
587
588
589
              "      --vout <plugin>            \tvideo output method\n"
              "      --display <display>        \tdisplay string\n"
              "      --width <w>, --height <h>  \tdisplay dimensions\n"
              "  -g, --grayscale                \tgrayscale output\n"
              "      --color                    \tcolor output\n"
              "\n"
590
591
592
593
              "  -a, --dvdaudio                 \tchoose DVD audio type\n"
              "  -c, --dvdchannel               \tchoose DVD audio channel\n"
              "  -s, --dvdsubtitle              \tchoose DVD subtitle channel\n"
              "\n"
594
595
596
597
598
599
600
              "      --novlans                  \tdisable vlans\n"
              "      --server <host>            \tvideo server address\n"
              "      --port <port>              \tvideo server port\n"
              "\n"
              "  -h, --help                     \tprint help and exit\n"
              "  -H, --longhelp                 \tprint long help and exit\n"
              "  -v, --version                  \toutput version information and exit\n" );
Michel Kaempf's avatar
Michel Kaempf committed
601

602
603
604
    if( i_fashion == SHORT_HELP )
        return;

Vincent Seguin's avatar
Vincent Seguin committed
605
    /* Interface parameters */
606
607
608
609
    intf_Msg( "\n"
              "Interface parameters:\n"
              "  " INTF_INIT_SCRIPT_VAR "=<filename>             \tinitialization script\n"
              "  " INTF_CHANNELS_VAR "=<filename>            \tchannels list\n" );
Vincent Seguin's avatar
Vincent Seguin committed
610
611

    /* Audio parameters */
612
613
614
615
616
617
    intf_Msg( "\n"
              "Audio parameters:\n"
              "  " AOUT_METHOD_VAR "=<method name>        \taudio method\n"
              "  " AOUT_DSP_VAR "=<filename>              \tdsp device path\n"
              "  " AOUT_STEREO_VAR "={1|0}                \tstereo or mono output\n"
              "  " AOUT_RATE_VAR "=<rate>             \toutput rate\n" );
Vincent Seguin's avatar
Vincent Seguin committed
618
619

    /* Video parameters */
620
621
622
623
624
625
626
627
    intf_Msg( "\n"
              "Video parameters:\n"
              "  " VOUT_METHOD_VAR "=<method name>        \tdisplay method\n"
              "  " VOUT_DISPLAY_VAR "=<display name>      \tdisplay used\n"
              "  " VOUT_WIDTH_VAR "=<width>               \tdisplay width\n"
              "  " VOUT_HEIGHT_VAR "=<height>             \tdislay height\n"
              "  " VOUT_FB_DEV_VAR "=<filename>           \tframebuffer device path\n"
              "  " VOUT_GRAYSCALE_VAR "={1|0}             \tgrayscale or color output\n" );
Vincent Seguin's avatar
Vincent Seguin committed
628

629
630
631
632
633
634
635
    /* DVD parameters */
    intf_Msg( "\n"
              "DVD parameters:\n"
              "  " INPUT_DVD_AUDIO_VAR "={ac3|lpcm|mpeg|off} \taudio type\n"
              "  " INPUT_DVD_CHANNEL_VAR "=[0-15]            \taudio channel\n"
              "  " INPUT_DVD_SUBTITLE_VAR "=[0-31]           \tsubtitle channel\n" );

636
    /* Input parameters */
637
638
639
640
641
642
643
    intf_Msg( "\n"
              "Input parameters:\n"
              "  " INPUT_SERVER_VAR "=<hostname>          \tvideo server\n"
              "  " INPUT_PORT_VAR "=<port>            \tvideo server port\n"
              "  " INPUT_IFACE_VAR "=<interface>          \tnetwork interface\n"
              "  " INPUT_VLAN_SERVER_VAR "=<hostname>     \tvlan server\n"
              "  " INPUT_VLAN_PORT_VAR "=<port>           \tvlan server port\n" );
Michel Kaempf's avatar
Michel Kaempf committed
644
645
}

646
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
647
 * Version: print complete program version
648
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
649
 * Print complete program version and build number.
650
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
651
652
static void Version( void )
{
653
    intf_Msg( VERSION_MESSAGE
654
655
656
657
              "This program comes with NO WARRANTY, to the extent permitted by law.\n"
              "You may redistribute it under the terms of the GNU General Public License;\n"
              "see the file named COPYING for details.\n"
              "Written by the VideoLAN team at Ecole Centrale, Paris.\n" );
658

659
}
Vincent Seguin's avatar
Vincent Seguin committed
660

661
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
662
 * InitSignalHandler: system signal handler initialization
663
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
664
 * Set the signal handlers. SIGTERM is not intercepted, because we need at
665
 * at least a method to kill the program when all other methods failed, and
Michel Kaempf's avatar
Michel Kaempf committed
666
 * when we don't want to use SIGKILL.
667
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
668
669
static void InitSignalHandler( void )
{
Vincent Seguin's avatar
Vincent Seguin committed
670
671
672
673
    /* Termination signals */
    signal( SIGHUP,  SignalHandler );
    signal( SIGINT,  SignalHandler );
    signal( SIGQUIT, SignalHandler );
Michel Kaempf's avatar
Michel Kaempf committed
674
675
}

676
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
677
 * SignalHandler: system signal handler
678
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
679
680
 * This function is called when a signal is received by the program. It tries to
 * end the program in a clean way.
681
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
682
683
static void SignalHandler( int i_signal )
{
684
    /* Once a signal has been trapped, the termination sequence will be armed and
Vincent Seguin's avatar
Vincent Seguin committed
685
686
687
688
689
690
691
692
693
     * following signals will be ignored to avoid sending messages to an interface
     * having been destroyed */
    signal( SIGHUP,  SIG_IGN );
    signal( SIGINT,  SIG_IGN );
    signal( SIGQUIT, SIG_IGN );

    /* Acknowledge the signal received */
    intf_ErrMsgImm("intf: signal %d received\n", i_signal );

694
    /* Try to terminate everything - this is done by requesting the end of the
Vincent Seguin's avatar
Vincent Seguin committed
695
696
697
698
     * interface thread */
    p_main->p_intf->b_die = 1;
}