main.c 30.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 31 32
#include <signal.h>                               /* SIGHUP, SIGINT, SIGKILL */
#include <stdio.h>                                              /* sprintf() */

Benoit Steiner's avatar
 
Benoit Steiner committed
33
#ifdef HAVE_GETOPT_H
Benoit Steiner's avatar
Benoit Steiner committed
34 35 36
#include <getopt.h>                                              /* getopt() */
#endif

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

Michel Kaempf's avatar
Michel Kaempf committed
41 42
#include "config.h"
#include "common.h"
Christophe Massiot's avatar
Christophe Massiot committed
43
#include "debug.h"
44
#include "threads.h"
Michel Kaempf's avatar
Michel Kaempf committed
45
#include "mtime.h"
46
#include "tests.h"                                              /* TestCPU() */
47
#include "plugins.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
48
#include "modules.h"
49 50
#include "stream_control.h"
#include "input_ext-intf.h"
51

Vincent Seguin's avatar
Vincent Seguin committed
52
#include "intf_msg.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
53
#include "intf_plst.h"
Michel Kaempf's avatar
Michel Kaempf committed
54
#include "interface.h"
55

Vincent Seguin's avatar
Vincent Seguin committed
56
#include "audio_output.h"
57

58 59 60 61
#ifdef SYS_BEOS
#include "beos_specific.h"
#endif

Vincent Seguin's avatar
Vincent Seguin committed
62
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
63

64
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
65 66
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
67
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
68 69 70 71

/* 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
Sam Hocevar's avatar
 
Sam Hocevar committed
72 73
#define OPT_STEREO              151
#define OPT_MONO                152
Michel Kaempf's avatar
Michel Kaempf committed
74 75

#define OPT_NOVIDEO             160
Sam Hocevar's avatar
 
Sam Hocevar committed
76 77 78 79 80 81
#define OPT_DISPLAY             161
#define OPT_WIDTH               162
#define OPT_HEIGHT              163
#define OPT_COLOR               164
#define OPT_FULLSCREEN          165
#define OPT_OVERLAY             166
Michel Kaempf's avatar
Michel Kaempf committed
82

83
#define OPT_VLANS               170
84 85
#define OPT_SERVER              171
#define OPT_PORT                172
86
#define OPT_BROADCAST           173
87

Sam Hocevar's avatar
 
Sam Hocevar committed
88 89 90 91 92
#define OPT_AOUT                180
#define OPT_VOUT                181
#define OPT_MOTION              182
#define OPT_IDCT                183
#define OPT_YUV                 184
Sam Hocevar's avatar
 
Sam Hocevar committed
93
#define OPT_INPUT               185
94

Sam Hocevar's avatar
 
Sam Hocevar committed
95 96
#define OPT_SYNCHRO             190
#define OPT_WARNING             191
97

98
/* Usage fashion */
99 100 101
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
102

Michel Kaempf's avatar
Michel Kaempf committed
103
/* Long options */
Benoit Steiner's avatar
 
Benoit Steiner committed
104
#ifdef HAVE_GETOPT_H
Michel Kaempf's avatar
Michel Kaempf committed
105
static const struct option longopts[] =
106 107
{
    /*  name,               has_arg,    flag,   val */
Michel Kaempf's avatar
Michel Kaempf committed
108 109

    /* General/common options */
110
    {   "help",             0,          0,      'h' },
111
    {   "longhelp",         0,          0,      'H' },
112
    {   "version",          0,          0,      'v' },
Michel Kaempf's avatar
Michel Kaempf committed
113 114

    /* Audio options */
115
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
116
    {   "aout",             1,          0,      OPT_AOUT },
Michel Kaempf's avatar
Michel Kaempf committed
117
    {   "stereo",           0,          0,      OPT_STEREO },
118
    {   "mono",             0,          0,      OPT_MONO },
Michel Kaempf's avatar
Michel Kaempf committed
119 120

    /* Video options */
121
    {   "novideo",          0,          0,      OPT_NOVIDEO },
122
    {   "vout",             1,          0,      OPT_VOUT },
123
    {   "display",          1,          0,      OPT_DISPLAY },
124
    {   "width",            1,          0,      OPT_WIDTH },
125 126 127
    {   "height",           1,          0,      OPT_HEIGHT },
    {   "grayscale",        0,          0,      'g' },
    {   "color",            0,          0,      OPT_COLOR },
Sam Hocevar's avatar
 
Sam Hocevar committed
128
    {   "motion",           1,          0,      OPT_MOTION },
Sam Hocevar's avatar
 
Sam Hocevar committed
129
    {   "idct",             1,          0,      OPT_IDCT },
Sam Hocevar's avatar
Sam Hocevar committed
130
    {   "yuv",              1,          0,      OPT_YUV },
Sam Hocevar's avatar
 
Sam Hocevar committed
131 132
    {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
    {   "overlay",          0,          0,      OPT_OVERLAY },
Michel Kaempf's avatar
Michel Kaempf committed
133

134 135 136 137 138
    /* DVD options */
    {   "dvdaudio",         1,          0,      'a' },
    {   "dvdchannel",       1,          0,      'c' },
    {   "dvdsubtitle",      1,          0,      's' },
    
139
    /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
140
    {   "input",            1,          0,      OPT_INPUT },
141
    {   "vlans",            0,          0,      OPT_VLANS },
142 143
    {   "server",           1,          0,      OPT_SERVER },
    {   "port",             1,          0,      OPT_PORT },
144
    {   "broadcast",        0,          0,      OPT_BROADCAST },
Michel Kaempf's avatar
Michel Kaempf committed
145

146 147 148
    /* Synchro options */
    {   "synchro",          1,          0,      OPT_SYNCHRO },

149 150
    /* Interface messages */
    {   "warning",          1,          0,      OPT_WARNING },
Michel Kaempf's avatar
Michel Kaempf committed
151 152 153 154
    {   0,                  0,          0,      0 }
};

/* Short options */
155
static const char *psz_shortopts = "hHvga:s:c:";
Benoit Steiner's avatar
Benoit Steiner committed
156 157
#endif

Michel Kaempf's avatar
Michel Kaempf committed
158

159
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
160
 * Global variable program_data - this is the one and only, see main.h
161
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
162
main_t *p_main;
Michel Kaempf's avatar
Michel Kaempf committed
163

164
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
165
 * Local prototypes
166
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
167
static void SetDefaultConfiguration ( void );
168 169
static int  GetConfiguration        ( int i_argc, char *ppsz_argv[],
                                      char *ppsz_env[] );
170
static void Usage                   ( int i_fashion );
Vincent Seguin's avatar
Vincent Seguin committed
171
static void Version                 ( void );
Vincent Seguin's avatar
Vincent Seguin committed
172

Michel Kaempf's avatar
Michel Kaempf committed
173
static void InitSignalHandler       ( void );
Benoit Steiner's avatar
 
Benoit Steiner committed
174 175
static void SimpleSignalHandler     ( int i_signal );
static void FatalSignalHandler      ( int i_signal );
Michel Kaempf's avatar
Michel Kaempf committed
176

177
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
178
 * main: parse command line, start interface and spawn threads
179
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
180 181
 * Steps during program execution are:
 *      -configuration parsing and messages interface initialization
182
 *      -opening of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
183
 *      -execution of interface, which exit on error or on user request
Vincent Seguin's avatar
Vincent Seguin committed
184
 *      -closing of audio output device and some global modules
185
 * On error, the spawned threads are canceled, and the open devices closed.
186
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
187 188
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
189
    main_t  main_data;                      /* root of all data - see main.h */
190

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

193 194 195
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
Sam Hocevar committed
196
#ifdef SYS_BEOS
197
    beos_Create();
198 199
#endif

200 201
    p_main->i_cpu_capabilities = CPUCapabilities();

Michel Kaempf's avatar
Michel Kaempf committed
202
    /*
203
     * Test if our code is likely to run on this CPU 
204
     */
205 206 207 208 209 210 211 212 213
#if defined( __pentium__ ) || defined( __pentiumpro__ )
    if( ! TestCPU( CPU_CAPABILITY_586 ) )
    {
        fprintf( stderr, "Sorry, this program needs a Pentium CPU.\n"
                         "Please try a version without Pentium support.\n" );
        return( 1 );
    }
#endif

Sam Hocevar's avatar
Sam Hocevar committed
214
#ifdef HAVE_MMX
215
    if( ! TestCPU( CPU_CAPABILITY_MMX ) )
216
    {
217 218
        fprintf( stderr, "Sorry, this program needs MMX extensions.\n"
                         "Please try a version without MMX support.\n" );
219
        return( 1 );
220 221
    }
#endif
222 223 224 225

    /*
     * Initialize messages interface
     */
Vincent Seguin's avatar
Vincent Seguin committed
226
    p_main->p_msg = intf_MsgCreate();
227
    if( !p_main->p_msg )                         /* start messages interface */
Michel Kaempf's avatar
Michel Kaempf committed
228
    {
229
        fprintf( stderr, "error: can't initialize messages interface (%s)\n",
Sam Hocevar's avatar
 
Sam Hocevar committed
230
                 strerror(errno) );
231
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
232
    }
233

Sam Hocevar's avatar
 
Sam Hocevar committed
234 235
    intf_MsgImm( COPYRIGHT_MESSAGE );

236
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
237
     * Initialize playlist and get commandline files
238
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
239
    p_main->p_playlist = intf_PlstCreate( );
Sam Hocevar's avatar
 
Sam Hocevar committed
240
    if( !p_main->p_playlist )
Michel Kaempf's avatar
Michel Kaempf committed
241
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
242
        intf_ErrMsg( "playlist error: playlist initialization failed" );
Vincent Seguin's avatar
Vincent Seguin committed
243
        intf_MsgDestroy();
244
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
245
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
246
    intf_PlstInit( p_main->p_playlist );
247

248
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
249
     * Read configuration
250
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
251
    if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )  /* parse cmd line */
252
    {
253 254
        intf_MsgDestroy();
        return( errno );
255
    }
256 257 258 259 260 261

    /*
     * Initialize plugin bank
     */
    p_main->p_bank = bank_Create( );
    if( !p_main->p_bank )
262
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
263
        intf_ErrMsg( "plugin error: plugin bank initialization failed" );
Sam Hocevar's avatar
 
Sam Hocevar committed
264
        intf_PlstDestroy( p_main->p_playlist );
265 266
        intf_MsgDestroy();
        return( errno );
267
    }
268
    bank_Init( p_main->p_bank );
Michel Kaempf's avatar
Michel Kaempf committed
269

Sam Hocevar's avatar
 
Sam Hocevar committed
270 271 272 273 274 275
    /*
     * Initialize module bank
     */
    p_main->p_module_bank = module_CreateBank( );
    if( !p_main->p_module_bank )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
276
        intf_ErrMsg( "module error: module bank initialization failed" );
Sam Hocevar's avatar
 
Sam Hocevar committed
277
        bank_Destroy( p_main->p_bank );
Sam Hocevar's avatar
 
Sam Hocevar committed
278
        intf_PlstDestroy( p_main->p_playlist );
Sam Hocevar's avatar
 
Sam Hocevar committed
279 280 281 282 283
        intf_MsgDestroy();
        return( errno );
    }
    module_InitBank( p_main->p_module_bank );

Michel Kaempf's avatar
Michel Kaempf committed
284 285 286
    /*
     * Initialize shared resources and libraries
     */
287 288
    /* FIXME: no VLANs */
#if 0
289
    if( p_main->b_vlans && input_VlanCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
290
    {
291 292
        /* On error during vlans initialization, switch off vlans */
        intf_Msg( "Virtual LANs initialization failed : "
Sam Hocevar's avatar
 
Sam Hocevar committed
293
                  "vlans management is deactivated" );
294
        p_main->b_vlans = 0;
Michel Kaempf's avatar
Michel Kaempf committed
295
    }
296
#endif
297

Michel Kaempf's avatar
Michel Kaempf committed
298 299 300
    /*
     * Run interface
     */
301
    p_main->p_intf = intf_Create();
302

303
    if( p_main->p_intf != NULL )
Vincent Seguin's avatar
Vincent Seguin committed
304
    {
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
        /*
         * Set signal handling policy for all threads
         */
        InitSignalHandler();

        /*
         * Open audio device and start aout thread
         */
        if( p_main->b_audio )
        {
            p_main->p_aout = aout_CreateThread( NULL );
            if( p_main->p_aout == NULL )
            {
                /* On error during audio initialization, switch off audio */
                intf_ErrMsg( "aout error: audio initialization failed,"
                             " audio is deactivated" );
                p_main->b_audio = 0;
            }
        }

Sam Hocevar's avatar
Sam Hocevar committed
325 326 327
        /*
         * This is the main loop
         */
328 329 330
        intf_Run( p_main->p_intf );

        intf_Destroy( p_main->p_intf );
Michel Kaempf's avatar
Michel Kaempf committed
331

332 333 334 335 336 337 338
        /*
         * Close audio device
         */
        if( p_main->b_audio )
        {
            aout_DestroyThread( p_main->p_aout, NULL );
        }
Michel Kaempf's avatar
Michel Kaempf committed
339
    }
Michel Kaempf's avatar
Michel Kaempf committed
340 341 342 343

    /*
     * Free shared resources and libraries
     */
344 345
    /* FIXME */
#if 0
346
    if( p_main->b_vlans )
347 348 349
    {
        input_VlanDestroy();
    }
350
#endif
Michel Kaempf's avatar
Michel Kaempf committed
351

Sam Hocevar's avatar
 
Sam Hocevar committed
352 353 354 355 356
    /*
     * Free module bank
     */
    module_DestroyBank( p_main->p_module_bank );

357
    /*
358
     * Free plugin bank
359
     */
360 361 362 363 364
    bank_Destroy( p_main->p_bank );

    /*
     * Free playlist
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
365
    intf_PlstDestroy( p_main->p_playlist );
366

367
#ifdef SYS_BEOS
368 369 370 371
    /*
     * System specific cleaning code
     */
    beos_Destroy();
372 373
#endif

Michel Kaempf's avatar
Michel Kaempf committed
374 375 376
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
377
    intf_Msg( "intf: program terminated." );
Vincent Seguin's avatar
Vincent Seguin committed
378
    intf_MsgDestroy();
379

Michel Kaempf's avatar
Michel Kaempf committed
380 381 382
    return( 0 );
}

383
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
384
 * main_GetIntVariable: get the int value of an environment variable
385
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
386
 * This function is used to read some default parameters in modules.
387
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
388 389
int main_GetIntVariable( char *psz_name, int i_default )
{
390 391 392
    char *      psz_env;                                /* environment value */
    char *      psz_end;                             /* end of parsing index */
    long int    i_value;                                            /* value */
Vincent Seguin's avatar
Vincent Seguin committed
393 394 395

    psz_env = getenv( psz_name );
    if( psz_env )
396
    {
397 398 399 400
        i_value = strtol( psz_env, &psz_end, 0 );
        if( (*psz_env != '\0') && (*psz_end == '\0') )
        {
            return( i_value );
401
        }
402
    }
Vincent Seguin's avatar
Vincent Seguin committed
403 404 405
    return( i_default );
}

406
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
407
 * main_GetPszVariable: get the string value of an environment variable
408
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
409
 * This function is used to read some default parameters in modules.
410
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
411 412 413 414 415 416 417
char * main_GetPszVariable( char *psz_name, char *psz_default )
{
    char *psz_env;

    psz_env = getenv( psz_name );
    if( psz_env )
    {
418
        return( psz_env );
Vincent Seguin's avatar
Vincent Seguin committed
419
    }
420
    return( psz_default );
Vincent Seguin's avatar
Vincent Seguin committed
421 422
}

423
/*****************************************************************************
424
 * main_PutPszVariable: set the string value of an environment variable
425
 *****************************************************************************
426 427 428
 * 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.
429
 *****************************************************************************/
430 431 432 433 434 435 436
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 )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
437 438
        intf_ErrMsg( "intf error: cannot create psz_env (%s)",
                     strerror(ENOMEM) );
439 440 441 442 443 444
    }
    else
    {
        sprintf( psz_env, "%s=%s", psz_name, psz_value );
        if( putenv( psz_env ) )
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
445
            intf_ErrMsg( "intf error: cannot putenv (%s)", strerror(errno) );
446
        }
447 448 449
    }
}

450
/*****************************************************************************
451
 * main_PutIntVariable: set the integer value of an environment variable
452
 *****************************************************************************
453 454 455
 * 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.
456
 *****************************************************************************/
457 458
void main_PutIntVariable( char *psz_name, int i_value )
{
459
    char psz_value[ 256 ];                               /* buffer for value */
460

461
    sprintf( psz_value, "%d", i_value );
462
    main_PutPszVariable( psz_name, psz_value );
463 464
}

Michel Kaempf's avatar
Michel Kaempf committed
465 466
/* following functions are local */

467
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
468
 * SetDefaultConfiguration: set default options
469
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
470
 * This function is called by GetConfiguration before command line is parsed.
Vincent Seguin's avatar
Vincent Seguin committed
471 472 473
 * 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.
474
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
475
static void SetDefaultConfiguration( void )
Michel Kaempf's avatar
Michel Kaempf committed
476 477
{
    /*
478
     * All features are activated by default except vlans
Michel Kaempf's avatar
Michel Kaempf committed
479
     */
Vincent Seguin's avatar
Vincent Seguin committed
480 481
    p_main->b_audio  = 1;
    p_main->b_video  = 1;
482
    p_main->b_vlans  = 0;
Michel Kaempf's avatar
Michel Kaempf committed
483 484
}

485
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
486
 * GetConfiguration: parse command line
487
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
488 489
 * Parse command line and configuration file for configuration. If the inline
 * help is requested, the function Usage() is called and the function returns
490
 * -1 (causing main() to exit). The messages interface is initialized at this
Vincent Seguin's avatar
Vincent Seguin committed
491 492
 * stage, but most structures are not allocated, so only environment should
 * be used.
493
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
494
static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
Michel Kaempf's avatar
Michel Kaempf committed
495
{
Vincent Seguin's avatar
Vincent Seguin committed
496
    int c, i_opt;
Sam Hocevar's avatar
Sam Hocevar committed
497
    char * p_pointer;
Michel Kaempf's avatar
Michel Kaempf committed
498 499

    /* Set default configuration and copy arguments */
Vincent Seguin's avatar
Vincent Seguin committed
500 501
    p_main->i_argc    = i_argc;
    p_main->ppsz_argv = ppsz_argv;
502
    p_main->ppsz_env  = ppsz_env;
Vincent Seguin's avatar
Vincent Seguin committed
503
    SetDefaultConfiguration();
Michel Kaempf's avatar
Michel Kaempf committed
504

505
    /* Get the executable name (similar to the basename command) */
Sam Hocevar's avatar
Sam Hocevar committed
506 507 508 509 510 511 512 513 514 515 516 517 518
    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
519
    /* Parse command line options */
Benoit Steiner's avatar
 
Benoit Steiner committed
520
#ifdef HAVE_GETOPT_H
Michel Kaempf's avatar
Michel Kaempf committed
521 522 523 524 525
    opterr = 0;
    while( ( c = getopt_long( i_argc, ppsz_argv, psz_shortopts, longopts, 0 ) ) != EOF )
    {
        switch( c )
        {
526 527
        /* General/common options */
        case 'h':                                              /* -h, --help */
528 529 530
            Usage( SHORT_HELP );
            return( -1 );
            break;
531
        case 'H':                                          /* -H, --longhelp */
532
            Usage( LONG_HELP );
Michel Kaempf's avatar
Michel Kaempf committed
533 534
            return( -1 );
            break;
535
        case 'v':                                           /* -v, --version */
Vincent Seguin's avatar
Vincent Seguin committed
536 537
            Version();
            return( -1 );
538
            break;
Michel Kaempf's avatar
Michel Kaempf committed
539 540

        /* Audio options */
541
        case OPT_NOAUDIO:                                       /* --noaudio */
542
            p_main->b_audio = 0;
Michel Kaempf's avatar
Michel Kaempf committed
543
            break;
544 545 546
        case OPT_AOUT:                                             /* --aout */
            main_PutPszVariable( AOUT_METHOD_VAR, optarg );
            break;
547
        case OPT_STEREO:                                         /* --stereo */
548
            main_PutIntVariable( AOUT_STEREO_VAR, 1 );
Michel Kaempf's avatar
Michel Kaempf committed
549
            break;
550
        case OPT_MONO:                                             /* --mono */
551
            main_PutIntVariable( AOUT_STEREO_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
552 553 554
            break;

        /* Video options */
555
        case OPT_NOVIDEO:                                       /* --novideo */
Vincent Seguin's avatar
Vincent Seguin committed
556
            p_main->b_video = 0;
557
            break;
558 559 560
        case OPT_VOUT:                                             /* --vout */
            main_PutPszVariable( VOUT_METHOD_VAR, optarg );
            break;
561
        case OPT_DISPLAY:                                       /* --display */
562
            main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
563 564
            break;
        case OPT_WIDTH:                                           /* --width */
565
            main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
566 567 568 569 570
            break;
        case OPT_HEIGHT:                                         /* --height */
            main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );
            break;
        case 'g':                                         /* -g, --grayscale */
571
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
572 573
            break;
        case OPT_COLOR:                                           /* --color */
574
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
575
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
576 577 578 579 580 581
	case OPT_FULLSCREEN:                                 /* --fullscreen */
            main_PutIntVariable( VOUT_FULLSCREEN_VAR, 1 );
            break;
	case OPT_OVERLAY:                                       /* --overlay */
            main_PutIntVariable( VOUT_OVERLAY_VAR, 1 );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
582 583 584
	case OPT_MOTION:                                         /* --motion */
            main_PutPszVariable( MOTION_METHOD_VAR, optarg );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
585 586 587
	case OPT_IDCT:                                             /* --idct */
            main_PutPszVariable( IDCT_METHOD_VAR, optarg );
            break;
Sam Hocevar's avatar
Sam Hocevar committed
588 589 590
        case OPT_YUV:                                               /* --yuv */
            main_PutPszVariable( YUV_METHOD_VAR, optarg );
            break;
Michel Kaempf's avatar
Michel Kaempf committed
591

592 593
        /* DVD options */
        case 'a':
594 595
            if ( ! strcmp(optarg, "ac3") )
                main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_AC3 );
596 597
            else if ( ! strcmp(optarg, "lpcm") )
                main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_LPCM );
598
            else if ( ! strcmp(optarg, "mpeg") )
599
                main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_MPEG );
600 601
            else
                main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_NOAUDIO );
602 603 604 605 606 607 608 609
            break;
        case 'c':
            main_PutIntVariable( INPUT_DVD_CHANNEL_VAR, atoi(optarg) );
            break;
        case 's':
            main_PutIntVariable( INPUT_DVD_SUBTITLE_VAR, atoi(optarg) );
            break;

610
        /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
611 612 613
	case OPT_INPUT:                                           /* --input */
            main_PutPszVariable( INPUT_METHOD_VAR, optarg );
            break;
614
        case OPT_VLANS:                                           /* --vlans */
615
            p_main->b_vlans = 1;
616 617
            break;
        case OPT_SERVER:                                         /* --server */
618
            main_PutPszVariable( INPUT_SERVER_VAR, optarg );
619 620
            break;
        case OPT_PORT:                                             /* --port */
621
            main_PutPszVariable( INPUT_PORT_VAR, optarg );
622
            break;
623 624 625
        case OPT_BROADCAST:                                   /* --broadcast */
            main_PutIntVariable( INPUT_BROADCAST_VAR, 1 );
            break;
626

627
        /* Synchro options */
628
        case OPT_SYNCHRO:                                      
629 630 631
            main_PutPszVariable( VPAR_SYNCHRO_VAR, optarg );
            break;

632 633 634 635 636
        /* Interface warning messages level */
        case OPT_WARNING:                                       /* --warning */
            main_PutIntVariable( INTF_WARNING_VAR, atoi(optarg) );
            break;
            
Michel Kaempf's avatar
Michel Kaempf committed
637
        /* Internal error: unknown option */
638
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
639
        default:
Sam Hocevar's avatar
 
Sam Hocevar committed
640
            intf_ErrMsg( "intf error: unknown option `%s'", ppsz_argv[optind - 1] );
641
            Usage( USAGE );
Michel Kaempf's avatar
Michel Kaempf committed
642 643 644 645
            return( EINVAL );
            break;
        }
    }
Benoit Steiner's avatar
Benoit Steiner committed
646
#endif
Michel Kaempf's avatar
Michel Kaempf committed
647

Sam Hocevar's avatar
 
Sam Hocevar committed
648
    /* We assume that the remaining parameters are filenames */
Vincent Seguin's avatar
Vincent Seguin committed
649 650
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
651
        intf_PlstAdd( p_main->p_playlist, PLAYLIST_END, ppsz_argv[ i_opt ] );
Vincent Seguin's avatar
Vincent Seguin committed
652
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
653

Michel Kaempf's avatar
Michel Kaempf committed
654 655 656
    return( 0 );
}

657
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
658
 * Usage: print program usage
659
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
660
 * Print a short inline help. Message interface is initialized at this stage.
661
 *****************************************************************************/
662
static void Usage( int i_fashion )
Michel Kaempf's avatar
Michel Kaempf committed
663
{
Vincent Seguin's avatar
Vincent Seguin committed
664
    /* Usage */
Sam Hocevar's avatar
 
Sam Hocevar committed
665 666
    intf_MsgImm( "Usage: %s [options] [parameters] [file]...",
                 p_main->psz_arg0 );
667 668 669

    if( i_fashion == USAGE )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
670 671
        intf_MsgImm( "Try `%s --help' for more information.",
                     p_main->psz_arg0 );
672 673 674
        return;
    }

Vincent Seguin's avatar
Vincent Seguin committed
675
    /* Options */
Sam Hocevar's avatar
 
Sam Hocevar committed
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
    intf_MsgImm( "\nOptions:"
          "\n      --noaudio                  \tdisable audio"
          "\n      --aout <module>            \taudio output method"
          "\n      --stereo, --mono           \tstereo/mono audio"
          "\n"
          "\n      --novideo                  \tdisable video"
          "\n      --vout <module>            \tvideo output method"
          "\n      --display <display>        \tdisplay string"
          "\n      --width <w>, --height <h>  \tdisplay dimensions"
          "\n  -g, --grayscale                \tgrayscale output"
          "\n      --fullscreen               \tfullscreen output"
          "\n      --overlay                  \taccelerated display"
          "\n      --color                    \tcolor output"
          "\n      --motion <module>          \tmotion compensation method"
          "\n      --idct <module>            \tIDCT method"
          "\n      --yuv <module>             \tYUV method"
          "\n      --synchro <type>           \tforce synchro algorithm"
          "\n"
          "\n  -a, --dvdaudio <type>          \tchoose DVD audio type"
          "\n  -c, --dvdchannel <channel>     \tchoose DVD audio channel"
          "\n  -s, --dvdsubtitle <channel>    \tchoose DVD subtitle channel"
          "\n"
          "\n      --input                    \tinput method"
          "\n      --vlans                    \tenable vlans"
          "\n      --server <host>            \tvideo server address"
          "\n      --port <port>              \tvideo server port"
          "\n      --broadcast                \tlisten to a broadcast"
          "\n"
          "\n      --warning <level>          \tdisplay warning messages"
          "\n"
          "\n  -h, --help                     \tprint help and exit"
          "\n  -H, --longhelp                 \tprint long help and exit"
          "\n  -v, --version                  \toutput version information and exit" );
Michel Kaempf's avatar
Michel Kaempf committed
709

710 711 712
    if( i_fashion == SHORT_HELP )
        return;

Vincent Seguin's avatar
Vincent Seguin committed
713
    /* Interface parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
714 715 716 717
    intf_MsgImm( "\nInterface parameters:\n"
        "\n  " INTF_INIT_SCRIPT_VAR "=<filename>               \tinitialization script"
        "\n  " INTF_CHANNELS_VAR "=<filename>            \tchannels list"
        "\n  " INTF_WARNING_VAR "=<level>                \twarning level" );
Vincent Seguin's avatar
Vincent Seguin committed
718 719

    /* Audio parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
720 721 722 723 724
    intf_MsgImm( "\nAudio 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" );
Vincent Seguin's avatar
Vincent Seguin committed
725 726

    /* Video parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
727 728 729 730 731 732 733 734 735 736 737 738 739
    intf_MsgImm( "\nVideo 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  " VOUT_FULLSCREEN_VAR "={1|0}            \tfullscreen"
        "\n  " VOUT_OVERLAY_VAR "={1|0}               \toverlay"
        "\n  " MOTION_METHOD_VAR "=<method name>      \tmotion compensation method"
        "\n  " IDCT_METHOD_VAR "=<method name>        \tIDCT method"
        "\n  " YUV_METHOD_VAR "=<method name>         \tYUV method"
        "\n  " VPAR_SYNCHRO_VAR "={I|I+|IP|IP+|IPB}   \tsynchro algorithm" );
Vincent Seguin's avatar
Vincent Seguin committed
740

741
    /* DVD parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
742 743 744 745 746
    intf_MsgImm( "\nDVD parameters:"
        "\n  " INPUT_DVD_DEVICE_VAR "=<device>           \tDVD device"
        "\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" );
747

748
    /* Input parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
749 750 751 752 753 754 755
    intf_MsgImm( "\nInput parameters:\n"
        "\n  " INPUT_SERVER_VAR "=<hostname>          \tvideo server"
        "\n  " INPUT_PORT_VAR "=<port>            \tvideo server port"
        "\n  " INPUT_IFACE_VAR "=<interface>          \tnetwork interface"
        "\n  " INPUT_BROADCAST_VAR "={1|0}            \tbroadcast mode"
        "\n  " INPUT_VLAN_SERVER_VAR "=<hostname>     \tvlan server"
        "\n  " INPUT_VLAN_PORT_VAR "=<port>           \tvlan server port" );
756

Michel Kaempf's avatar
Michel Kaempf committed
757 758
}

759
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
760
 * Version: print complete program version
761
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
762
 * Print complete program version and build number.
763
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
764 765
static void Version( void )
{
Sam Hocevar's avatar
 
Sam Hocevar committed
766 767 768 769 770
    intf_MsgImm( VERSION_MESSAGE
        "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." );
771
}
Vincent Seguin's avatar
Vincent Seguin committed
772

773
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
774
 * InitSignalHandler: system signal handler initialization
775
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
776
 * Set the signal handlers. SIGTERM is not intercepted, because we need at
777
 * at least a method to kill the program when all other methods failed, and
Michel Kaempf's avatar
Michel Kaempf committed
778
 * when we don't want to use SIGKILL.
779
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
780 781
static void InitSignalHandler( void )
{
Vincent Seguin's avatar
Vincent Seguin committed
782
    /* Termination signals */
Benoit Steiner's avatar
 
Benoit Steiner committed
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
    signal( SIGHUP,  FatalSignalHandler );
    signal( SIGINT,  FatalSignalHandler );
    signal( SIGQUIT, FatalSignalHandler );

    /* Other signals */
    signal( SIGALRM, SimpleSignalHandler );
    signal( SIGPIPE, SimpleSignalHandler );
}


/*****************************************************************************
 * SimpleSignalHandler: system signal handler
 *****************************************************************************
 * This function is called when a non fatal signal is received by the program.
 *****************************************************************************/
static void SimpleSignalHandler( int i_signal )
{
    /* Acknowledge the signal received */
Sam Hocevar's avatar
 
Sam Hocevar committed
801
    intf_WarnMsg(0, "intf: ignoring signal %d", i_signal );
Michel Kaempf's avatar
Michel Kaempf committed
802 803
}

Benoit Steiner's avatar
 
Benoit Steiner committed
804

805
/*****************************************************************************
Benoit Steiner's avatar
 
Benoit Steiner committed
806
 * FatalSignalHandler: system signal handler
807
 *****************************************************************************
Benoit Steiner's avatar
 
Benoit Steiner committed
808 809
 * This function is called when a fatal signal is received by the program.
 * It tries to end the program in a clean way.
810
 *****************************************************************************/
Benoit Steiner's avatar
 
Benoit Steiner committed
811
static void FatalSignalHandler( int i_signal )
Michel Kaempf's avatar
Michel Kaempf committed
812
{
813
    /* Once a signal has been trapped, the termination sequence will be armed and
Vincent Seguin's avatar
Vincent Seguin committed
814 815 816 817 818 819 820
     * 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 */
Sam Hocevar's avatar
 
Sam Hocevar committed
821
    intf_ErrMsgImm("intf error: signal %d received, exiting", i_signal );
Vincent Seguin's avatar
Vincent Seguin committed
822

823
    /* Try to terminate everything - this is done by requesting the end of the
Vincent Seguin's avatar