main.c 32.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

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

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

50 51
#include "stream_control.h"
#include "input_ext-intf.h"
52

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
59 60 61
#include "video.h"
#include "video_output.h"

62 63 64 65
#ifdef SYS_BEOS
#include "beos_specific.h"
#endif

Vincent Seguin's avatar
Vincent Seguin committed
66
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
67

68
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
69 70
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
71
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
72 73 74 75

/* 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
76 77
#define OPT_STEREO              151
#define OPT_MONO                152
Michel Kaempf's avatar
Michel Kaempf committed
78 79

#define OPT_NOVIDEO             160
Sam Hocevar's avatar
 
Sam Hocevar committed
80 81 82 83 84 85
#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
86

87
#define OPT_VLANS               170
88 89
#define OPT_SERVER              171
#define OPT_PORT                172
90
#define OPT_BROADCAST           173
91

Sam Hocevar's avatar
 
Sam Hocevar committed
92 93 94 95
#define OPT_INPUT               180
#define OPT_MOTION              181
#define OPT_IDCT                182
#define OPT_YUV                 183
96

Sam Hocevar's avatar
 
Sam Hocevar committed
97 98
#define OPT_SYNCHRO             190
#define OPT_WARNING             191
99

100
/* Usage fashion */
101 102 103
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
104

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
116
    /* Interface options */
Sam Hocevar's avatar
 
Sam Hocevar committed
117
    {   "intf",             1,          0,      'I' },
Sam Hocevar's avatar
 
Sam Hocevar committed
118 119
    {   "warning",          1,          0,      OPT_WARNING },

Michel Kaempf's avatar
Michel Kaempf committed
120
    /* Audio options */
121
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
Sam Hocevar's avatar
 
Sam Hocevar committed
122
    {   "aout",             1,          0,      'A' },
Michel Kaempf's avatar
Michel Kaempf committed
123
    {   "stereo",           0,          0,      OPT_STEREO },
124
    {   "mono",             0,          0,      OPT_MONO },
Michel Kaempf's avatar
Michel Kaempf committed
125 126

    /* Video options */
127
    {   "novideo",          0,          0,      OPT_NOVIDEO },
Sam Hocevar's avatar
 
Sam Hocevar committed
128
    {   "vout",             1,          0,      'V' },
129
    {   "display",          1,          0,      OPT_DISPLAY },
130
    {   "width",            1,          0,      OPT_WIDTH },
131 132 133
    {   "height",           1,          0,      OPT_HEIGHT },
    {   "grayscale",        0,          0,      'g' },
    {   "color",            0,          0,      OPT_COLOR },
Sam Hocevar's avatar
 
Sam Hocevar committed
134
    {   "motion",           1,          0,      OPT_MOTION },
Sam Hocevar's avatar
 
Sam Hocevar committed
135
    {   "idct",             1,          0,      OPT_IDCT },
Sam Hocevar's avatar
Sam Hocevar committed
136
    {   "yuv",              1,          0,      OPT_YUV },
Sam Hocevar's avatar
 
Sam Hocevar committed
137 138
    {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
    {   "overlay",          0,          0,      OPT_OVERLAY },
Michel Kaempf's avatar
Michel Kaempf committed
139

140
    /* DVD options */
141 142
    {   "dvdtitle",         1,          0,      't' },
    {   "dvdchapter",       1,          0,      'T' },
143 144 145 146
    {   "dvdaudio",         1,          0,      'a' },
    {   "dvdchannel",       1,          0,      'c' },
    {   "dvdsubtitle",      1,          0,      's' },
    
147
    /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
148
    {   "input",            1,          0,      OPT_INPUT },
149
    {   "vlans",            0,          0,      OPT_VLANS },
150 151
    {   "server",           1,          0,      OPT_SERVER },
    {   "port",             1,          0,      OPT_PORT },
152
    {   "broadcast",        0,          0,      OPT_BROADCAST },
Michel Kaempf's avatar
Michel Kaempf committed
153

154 155
    /* Synchro options */
    {   "synchro",          1,          0,      OPT_SYNCHRO },
Michel Kaempf's avatar
Michel Kaempf committed
156 157 158 159
    {   0,                  0,          0,      0 }
};

/* Short options */
Sam Hocevar's avatar
 
Sam Hocevar committed
160
static const char *psz_shortopts = "hHvgt:T:a:s:c:I:A:V:";
Benoit Steiner's avatar
Benoit Steiner committed
161 162
#endif

Michel Kaempf's avatar
Michel Kaempf committed
163

164
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
165
 * Global variable program_data - this is the one and only, see main.h
166
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
167
main_t *p_main;
Michel Kaempf's avatar
Michel Kaempf committed
168

169
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
170
 * Local prototypes
171
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
172
static void SetDefaultConfiguration ( void );
173 174
static int  GetConfiguration        ( int i_argc, char *ppsz_argv[],
                                      char *ppsz_env[] );
Sam Hocevar's avatar
 
Sam Hocevar committed
175
static int  GetFilenames            ( int i_argc, char *ppsz_argv[] );
176
static void Usage                   ( int i_fashion );
Vincent Seguin's avatar
Vincent Seguin committed
177
static void Version                 ( void );
Vincent Seguin's avatar
Vincent Seguin committed
178

Michel Kaempf's avatar
Michel Kaempf committed
179
static void InitSignalHandler       ( void );
Benoit Steiner's avatar
 
Benoit Steiner committed
180 181
static void SimpleSignalHandler     ( int i_signal );
static void FatalSignalHandler      ( int i_signal );
Michel Kaempf's avatar
Michel Kaempf committed
182

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

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

199 200 201
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
Sam Hocevar committed
202
#ifdef SYS_BEOS
203
    beos_Create();
204 205
#endif

206
    p_main->i_cpu_capabilities = CPUCapabilities();
Sam Hocevar's avatar
 
Sam Hocevar committed
207
    
Michel Kaempf's avatar
Michel Kaempf committed
208
    /*
209
     * Test if our code is likely to run on this CPU 
210
     */
211 212 213
#if defined( __pentium__ ) || defined( __pentiumpro__ )
    if( ! TestCPU( CPU_CAPABILITY_586 ) )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
214 215
        fprintf( stderr, "error: this program needs a Pentium CPU,\n"
                         "please try a version without Pentium support\n" );
216 217 218 219
        return( 1 );
    }
#endif

Sam Hocevar's avatar
Sam Hocevar committed
220
#ifdef HAVE_MMX
221
    if( ! TestCPU( CPU_CAPABILITY_MMX ) )
222
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
223 224
        fprintf( stderr, "error: this program needs MMX extensions,\n"
                         "please try a version without MMX support\n" );
225
        return( 1 );
226 227
    }
#endif
228 229 230 231

    /*
     * Initialize messages interface
     */
Vincent Seguin's avatar
Vincent Seguin committed
232
    p_main->p_msg = intf_MsgCreate();
233
    if( !p_main->p_msg )                         /* start messages interface */
Michel Kaempf's avatar
Michel Kaempf committed
234
    {
235
        fprintf( stderr, "error: can't initialize messages interface (%s)\n",
Sam Hocevar's avatar
 
Sam Hocevar committed
236
                 strerror(errno) );
237
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
238
    }
239

Sam Hocevar's avatar
 
Sam Hocevar committed
240 241
    intf_MsgImm( COPYRIGHT_MESSAGE );

242
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
243
     * Read configuration
244
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
245
    if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )  /* parse cmd line */
Michel Kaempf's avatar
Michel Kaempf committed
246
    {
Vincent Seguin's avatar
Vincent Seguin committed
247
        intf_MsgDestroy();
248
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
249
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
250 251 252

    p_main->i_warning_level = main_GetIntVariable( INTF_WARNING_VAR,
                                                   INTF_WARNING_DEFAULT );
253

254
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
255
     * Initialize playlist and get commandline files
256
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
257
    p_main->p_playlist = intf_PlaylistCreate( );
Sam Hocevar's avatar
 
Sam Hocevar committed
258
    if( !p_main->p_playlist )
259
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
260
        intf_ErrMsg( "playlist error: playlist initialization failed" );
261 262
        intf_MsgDestroy();
        return( errno );
263
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
264
    intf_PlaylistInit( p_main->p_playlist );
265 266

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
267
     * Get input filenames given as commandline arguments
268
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
269
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
270

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

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();
Sam Hocevar's avatar
 
Sam Hocevar committed
302 303 304 305
    if( !p_main->p_intf )
    {
        intf_ErrMsg( "intf error: interface initialization failed" );
        module_DestroyBank( p_main->p_bank );
Sam Hocevar's avatar
 
Sam Hocevar committed
306
        intf_PlaylistDestroy( p_main->p_playlist );
Sam Hocevar's avatar
 
Sam Hocevar committed
307 308 309
        intf_MsgDestroy();
        return( errno );
    }
310

Sam Hocevar's avatar
 
Sam Hocevar committed
311 312 313 314 315 316 317 318 319
    /*
     * Set signal handling policy for all threads
     */
    InitSignalHandler();

    /*
     * Open audio device and start aout thread
     */
    if( p_main->b_audio )
Vincent Seguin's avatar
Vincent Seguin committed
320
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
321 322
        p_main->p_aout = aout_CreateThread( NULL );
        if( p_main->p_aout == NULL )
323
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
324 325 326 327
            /* On error during audio initialization, switch off audio */
            intf_ErrMsg( "aout error: audio initialization failed,"
                         " audio is deactivated" );
            p_main->b_audio = 0;
328
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
329
    }
330

Sam Hocevar's avatar
 
Sam Hocevar committed
331
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
332
     * Open video device and start vout thread
Sam Hocevar's avatar
 
Sam Hocevar committed
333 334 335 336 337
     */
    if( p_main->b_video )
    {
        p_main->p_vout = vout_CreateThread( NULL );
        if( p_main->p_vout == NULL )
338
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
339
            /* On error during video initialization, switch off video */
Sam Hocevar's avatar
 
Sam Hocevar committed
340 341 342
            intf_ErrMsg( "vout error: video initialization failed,"
                         " video is deactivated" );
            p_main->b_video = 0;
343
        }
Michel Kaempf's avatar
Michel Kaempf committed
344
    }
Michel Kaempf's avatar
Michel Kaempf committed
345

Sam Hocevar's avatar
 
Sam Hocevar committed
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
    /* Flush messages before entering the main loop */
    intf_FlushMsg();

    /*
     * This is the main loop
     */
    p_main->p_intf->pf_run( p_main->p_intf );

    intf_Destroy( p_main->p_intf );

    /*
     * Close video device
     */
    if( p_main->b_video )
    {
        vout_DestroyThread( p_main->p_vout, NULL );
    }

    /*
     * Close audio device
     */
    if( p_main->b_audio )
    {
        aout_DestroyThread( p_main->p_aout, NULL );
    }

Michel Kaempf's avatar
Michel Kaempf committed
372 373 374
    /*
     * Free shared resources and libraries
     */
375 376
    /* FIXME */
#if 0
377
    if( p_main->b_vlans )
378 379 380
    {
        input_VlanDestroy();
    }
381
#endif
Michel Kaempf's avatar
Michel Kaempf committed
382

Sam Hocevar's avatar
 
Sam Hocevar committed
383 384 385
    /*
     * Free module bank
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
386
    module_DestroyBank( p_main->p_bank );
387 388 389 390

    /*
     * Free playlist
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
391
    intf_PlaylistDestroy( p_main->p_playlist );
392

393
#ifdef SYS_BEOS
394 395 396 397
    /*
     * System specific cleaning code
     */
    beos_Destroy();
398 399
#endif

Michel Kaempf's avatar
Michel Kaempf committed
400 401 402
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
403
    intf_Msg( "intf: program terminated" );
Vincent Seguin's avatar
Vincent Seguin committed
404
    intf_MsgDestroy();
405

Michel Kaempf's avatar
Michel Kaempf committed
406 407 408
    return( 0 );
}

409
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
410
 * main_GetIntVariable: get the int value of an environment variable
411
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
412
 * This function is used to read some default parameters in modules.
413
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
414 415
int main_GetIntVariable( char *psz_name, int i_default )
{
416 417 418
    char *      psz_env;                                /* environment value */
    char *      psz_end;                             /* end of parsing index */
    long int    i_value;                                            /* value */
Vincent Seguin's avatar
Vincent Seguin committed
419 420 421

    psz_env = getenv( psz_name );
    if( psz_env )
422
    {
423 424 425 426
        i_value = strtol( psz_env, &psz_end, 0 );
        if( (*psz_env != '\0') && (*psz_end == '\0') )
        {
            return( i_value );
427
        }
428
    }
Vincent Seguin's avatar
Vincent Seguin committed
429 430 431
    return( i_default );
}

432
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
433
 * main_GetPszVariable: get the string value of an environment variable
434
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
435
 * This function is used to read some default parameters in modules.
436
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
437 438 439 440 441 442 443
char * main_GetPszVariable( char *psz_name, char *psz_default )
{
    char *psz_env;

    psz_env = getenv( psz_name );
    if( psz_env )
    {
444
        return( psz_env );
Vincent Seguin's avatar
Vincent Seguin committed
445
    }
446
    return( psz_default );
Vincent Seguin's avatar
Vincent Seguin committed
447 448
}

449
/*****************************************************************************
450
 * main_PutPszVariable: set the string value of an environment variable
451
 *****************************************************************************
452 453 454
 * 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.
455
 *****************************************************************************/
456 457 458 459 460 461 462
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
463 464
        intf_ErrMsg( "intf error: cannot create psz_env (%s)",
                     strerror(ENOMEM) );
465 466 467 468 469 470
    }
    else
    {
        sprintf( psz_env, "%s=%s", psz_name, psz_value );
        if( putenv( psz_env ) )
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
471
            intf_ErrMsg( "intf error: cannot putenv (%s)", strerror(errno) );
472
        }
473 474 475
    }
}

476
/*****************************************************************************
477
 * main_PutIntVariable: set the integer value of an environment variable
478
 *****************************************************************************
479 480 481
 * 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.
482
 *****************************************************************************/
483 484
void main_PutIntVariable( char *psz_name, int i_value )
{
485
    char psz_value[ 256 ];                               /* buffer for value */
486

487
    sprintf( psz_value, "%d", i_value );
488
    main_PutPszVariable( psz_name, psz_value );
489 490
}

Michel Kaempf's avatar
Michel Kaempf committed
491 492
/* following functions are local */

493
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
494
 * SetDefaultConfiguration: set default options
495
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
496
 * This function is called by GetConfiguration before command line is parsed.
Vincent Seguin's avatar
Vincent Seguin committed
497 498 499
 * 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.
500
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
501
static void SetDefaultConfiguration( void )
Michel Kaempf's avatar
Michel Kaempf committed
502 503
{
    /*
504
     * All features are activated by default except vlans
Michel Kaempf's avatar
Michel Kaempf committed
505
     */
Vincent Seguin's avatar
Vincent Seguin committed
506 507
    p_main->b_audio  = 1;
    p_main->b_video  = 1;
508
    p_main->b_vlans  = 0;
Michel Kaempf's avatar
Michel Kaempf committed
509 510
}

511
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
512
 * GetConfiguration: parse command line
513
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
514 515
 * Parse command line and configuration file for configuration. If the inline
 * help is requested, the function Usage() is called and the function returns
516
 * -1 (causing main() to exit). The messages interface is initialized at this
Vincent Seguin's avatar
Vincent Seguin committed
517 518
 * stage, but most structures are not allocated, so only environment should
 * be used.
519
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
520
static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
Michel Kaempf's avatar
Michel Kaempf committed
521
{
Sam Hocevar's avatar
 
Sam Hocevar committed
522
    int c;
Sam Hocevar's avatar
Sam Hocevar committed
523
    char * p_pointer;
Michel Kaempf's avatar
Michel Kaempf committed
524 525

    /* Set default configuration and copy arguments */
Vincent Seguin's avatar
Vincent Seguin committed
526 527
    p_main->i_argc    = i_argc;
    p_main->ppsz_argv = ppsz_argv;
528
    p_main->ppsz_env  = ppsz_env;
Vincent Seguin's avatar
Vincent Seguin committed
529
    SetDefaultConfiguration();
Michel Kaempf's avatar
Michel Kaempf committed
530

531
    /* Get the executable name (similar to the basename command) */
Sam Hocevar's avatar
Sam Hocevar committed
532 533 534 535 536 537 538 539 540 541 542 543 544
    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
545
    /* Parse command line options */
Benoit Steiner's avatar
 
Benoit Steiner committed
546
#ifdef HAVE_GETOPT_H
Michel Kaempf's avatar
Michel Kaempf committed
547 548 549 550 551
    opterr = 0;
    while( ( c = getopt_long( i_argc, ppsz_argv, psz_shortopts, longopts, 0 ) ) != EOF )
    {
        switch( c )
        {
552 553
        /* General/common options */
        case 'h':                                              /* -h, --help */
554 555 556
            Usage( SHORT_HELP );
            return( -1 );
            break;
557
        case 'H':                                          /* -H, --longhelp */
558
            Usage( LONG_HELP );
Michel Kaempf's avatar
Michel Kaempf committed
559 560
            return( -1 );
            break;
561
        case 'v':                                           /* -v, --version */
Vincent Seguin's avatar
Vincent Seguin committed
562 563
            Version();
            return( -1 );
564
            break;
Michel Kaempf's avatar
Michel Kaempf committed
565

Sam Hocevar's avatar
 
Sam Hocevar committed
566
        /* Interface warning messages level */
Sam Hocevar's avatar
 
Sam Hocevar committed
567
	case 'I':                                              /* -I, --intf */
Sam Hocevar's avatar
 
Sam Hocevar committed
568 569 570 571 572 573
            main_PutPszVariable( INTF_METHOD_VAR, optarg );
            break;
        case OPT_WARNING:                                       /* --warning */
            main_PutIntVariable( INTF_WARNING_VAR, atoi(optarg) );
            break;

Michel Kaempf's avatar
Michel Kaempf committed
574
        /* Audio options */
575
        case OPT_NOAUDIO:                                       /* --noaudio */
576
            p_main->b_audio = 0;
Michel Kaempf's avatar
Michel Kaempf committed
577
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
578
        case 'A':                                              /* -A, --aout */
579 580
            main_PutPszVariable( AOUT_METHOD_VAR, optarg );
            break;
581
        case OPT_STEREO:                                         /* --stereo */
582
            main_PutIntVariable( AOUT_STEREO_VAR, 1 );
Michel Kaempf's avatar
Michel Kaempf committed
583
            break;
584
        case OPT_MONO:                                             /* --mono */
585
            main_PutIntVariable( AOUT_STEREO_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
586 587 588
            break;

        /* Video options */
589
        case OPT_NOVIDEO:                                       /* --novideo */
Vincent Seguin's avatar
Vincent Seguin committed
590
            p_main->b_video = 0;
591
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
592
        case 'V':                                              /* -V, --vout */
593 594
            main_PutPszVariable( VOUT_METHOD_VAR, optarg );
            break;
595
        case OPT_DISPLAY:                                       /* --display */
596
            main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
597 598
            break;
        case OPT_WIDTH:                                           /* --width */
599
            main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
600 601 602 603 604
            break;
        case OPT_HEIGHT:                                         /* --height */
            main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );
            break;
        case 'g':                                         /* -g, --grayscale */
605
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
606 607
            break;
        case OPT_COLOR:                                           /* --color */
608
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
609
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
610
        case OPT_FULLSCREEN:                                 /* --fullscreen */
Sam Hocevar's avatar
 
Sam Hocevar committed
611 612
            main_PutIntVariable( VOUT_FULLSCREEN_VAR, 1 );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
613
        case OPT_OVERLAY:                                       /* --overlay */
Sam Hocevar's avatar
 
Sam Hocevar committed
614 615
            main_PutIntVariable( VOUT_OVERLAY_VAR, 1 );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
616
        case OPT_MOTION:                                         /* --motion */
Sam Hocevar's avatar
 
Sam Hocevar committed
617 618
            main_PutPszVariable( MOTION_METHOD_VAR, optarg );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
619
        case OPT_IDCT:                                             /* --idct */
Sam Hocevar's avatar
 
Sam Hocevar committed
620 621
            main_PutPszVariable( IDCT_METHOD_VAR, optarg );
            break;
Sam Hocevar's avatar
Sam Hocevar committed
622 623 624
        case OPT_YUV:                                               /* --yuv */
            main_PutPszVariable( YUV_METHOD_VAR, optarg );
            break;
Michel Kaempf's avatar
Michel Kaempf committed
625

626
        /* DVD options */
627 628 629 630 631 632
        case 't':
            main_PutIntVariable( INPUT_TITLE_VAR, atoi(optarg) );
            break;
        case 'T':
            main_PutIntVariable( INPUT_CHAPTER_VAR, atoi(optarg) );
            break;
633
        case 'a':
634
            if ( ! strcmp(optarg, "ac3") )
Sam Hocevar's avatar
 
Sam Hocevar committed
635
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_AC3 );
636
            else if ( ! strcmp(optarg, "lpcm") )
Sam Hocevar's avatar
 
Sam Hocevar committed
637
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_LPCM );
638
            else if ( ! strcmp(optarg, "mpeg") )
Sam Hocevar's avatar
 
Sam Hocevar committed
639
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_MPEG );
640
            else
Sam Hocevar's avatar
 
Sam Hocevar committed
641
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_NOAUDIO );
642 643
            break;
        case 'c':
Sam Hocevar's avatar
 
Sam Hocevar committed
644
            main_PutIntVariable( INPUT_CHANNEL_VAR, atoi(optarg) );
645 646
            break;
        case 's':
Sam Hocevar's avatar
 
Sam Hocevar committed
647
            main_PutIntVariable( INPUT_SUBTITLE_VAR, atoi(optarg) );
648 649
            break;

650
        /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
651
        case OPT_INPUT:                                           /* --input */
Sam Hocevar's avatar
 
Sam Hocevar committed
652 653
            main_PutPszVariable( INPUT_METHOD_VAR, optarg );
            break;
654
        case OPT_VLANS:                                           /* --vlans */
655
            p_main->b_vlans = 1;
656 657
            break;
        case OPT_SERVER:                                         /* --server */
658
            main_PutPszVariable( INPUT_SERVER_VAR, optarg );
659 660
            break;
        case OPT_PORT:                                             /* --port */
661
            main_PutPszVariable( INPUT_PORT_VAR, optarg );
662
            break;
663 664 665
        case OPT_BROADCAST:                                   /* --broadcast */
            main_PutIntVariable( INPUT_BROADCAST_VAR, 1 );
            break;
666

667
        /* Synchro options */
668
        case OPT_SYNCHRO:                                      
669 670
            main_PutPszVariable( VPAR_SYNCHRO_VAR, optarg );
            break;
671
            
Michel Kaempf's avatar
Michel Kaempf committed
672
        /* Internal error: unknown option */
673
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
674
        default:
Sam Hocevar's avatar
 
Sam Hocevar committed
675
            intf_ErrMsg( "intf error: unknown option `%s'", ppsz_argv[optind - 1] );
676
            Usage( USAGE );
Michel Kaempf's avatar
Michel Kaempf committed
677 678 679 680
            return( EINVAL );
            break;
        }
    }
Benoit Steiner's avatar
Benoit Steiner committed
681
#endif
Sam Hocevar's avatar
 
Sam Hocevar committed
682 683 684 685 686 687 688 689 690 691 692
    return( 0 );
}

/*****************************************************************************
 * GetFilenames: parse command line options which are not flags
 *****************************************************************************
 * Parse command line for input files.
 *****************************************************************************/
static int GetFilenames( int i_argc, char *ppsz_argv[] )
{
    int i_opt;
Michel Kaempf's avatar
Michel Kaempf committed
693

Sam Hocevar's avatar
 
Sam Hocevar committed
694
    /* We assume that the remaining parameters are filenames */
Vincent Seguin's avatar
Vincent Seguin committed
695 696
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
697 698
        intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
                          ppsz_argv[ i_opt ] );
Vincent Seguin's avatar
Vincent Seguin committed
699
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
700

Michel Kaempf's avatar
Michel Kaempf committed
701 702 703
    return( 0 );
}

704
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
705
 * Usage: print program usage
706
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
707
 * Print a short inline help. Message interface is initialized at this stage.
708
 *****************************************************************************/
709
static void Usage( int i_fashion )
Michel Kaempf's avatar
Michel Kaempf committed
710
{
Vincent Seguin's avatar
Vincent Seguin committed
711
    /* Usage */
Sam Hocevar's avatar
 
Sam Hocevar committed
712 713
    intf_MsgImm( "Usage: %s [options] [parameters] [file]...",
                 p_main->psz_arg0 );
714 715 716

    if( i_fashion == USAGE )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
717 718
        intf_MsgImm( "Try `%s --help' for more information.",
                     p_main->psz_arg0 );
719 720 721
        return;
    }

Vincent Seguin's avatar
Vincent Seguin committed
722
    /* Options */
Sam Hocevar's avatar
 
Sam Hocevar committed
723
    intf_MsgImm( "\nOptions:"
Sam Hocevar's avatar
 
Sam Hocevar committed
724
          "\n  -I, --intf <module>            \tinterface method"
Sam Hocevar's avatar
 
Sam Hocevar committed
725 726
          "\n      --warning <level>          \tdisplay warning messages"
          "\n"
Sam Hocevar's avatar
 
Sam Hocevar committed
727
          "\n      --noaudio                  \tdisable audio"
Sam Hocevar's avatar
 
Sam Hocevar committed
728
          "\n  -A, --aout <module>            \taudio output method"
Sam Hocevar's avatar
 
Sam Hocevar committed
729 730 731
          "\n      --stereo, --mono           \tstereo/mono audio"
          "\n"
          "\n      --novideo                  \tdisable video"
Sam Hocevar's avatar
 
Sam Hocevar committed
732
          "\n  -V, --vout <module>            \tvideo output method"
Sam Hocevar's avatar
 
Sam Hocevar committed
733 734 735 736 737 738 739 740 741 742 743
          "\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"
744 745
          "\n  -t, --dvdtitle <num>           \tchoose DVD title"
          "\n  -T, --dvdchapter <num>         \tchoose DVD chapter"
Sam Hocevar's avatar
 
Sam Hocevar committed
746 747 748 749 750 751 752 753 754 755 756 757 758
          "\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  -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
759

760 761 762
    if( i_fashion == SHORT_HELP )
        return;

Vincent Seguin's avatar
Vincent Seguin committed
763
    /* Interface parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
764
    intf_MsgImm( "\nInterface parameters:"
Sam Hocevar's avatar
 
Sam Hocevar committed
765
        "\n  " INTF_METHOD_VAR "=<method name>          \tinterface method"
Sam Hocevar's avatar
 
Sam Hocevar committed
766
        "\n  " INTF_INIT_SCRIPT_VAR "=<filename>               \tinitialization script"
Sam Hocevar's avatar
 
Sam Hocevar committed
767 768
        "\n  " INTF_CHANNELS_VAR "=<filename>            \tchannels list"
        "\n  " INTF_WARNING_VAR "=<level>                \twarning level" );
Vincent Seguin's avatar
Vincent Seguin committed
769 770

    /* Audio parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
771 772 773 774 775
    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
776 777

    /* Video parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
778 779 780 781 782 783 784 785 786 787 788 789