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

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() */
Sam Hocevar's avatar
 
Sam Hocevar committed
47
#include "modules.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
48

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

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

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

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

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

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
91 92
#define OPT_AOUT                180
#define OPT_VOUT                181
Sam Hocevar's avatar
 
Sam Hocevar committed
93 94 95 96 97
#define OPT_INTF                182
#define OPT_MOTION              183
#define OPT_IDCT                184
#define OPT_YUV                 185
#define OPT_INPUT               186
98

Sam Hocevar's avatar
 
Sam Hocevar committed
99 100
#define OPT_SYNCHRO             190
#define OPT_WARNING             191
101

102
/* Usage fashion */
103 104 105
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
106

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
118 119 120 121
    /* Interface options */
    {   "intf",             1,          0,      OPT_INTF },
    {   "warning",          1,          0,      OPT_WARNING },

Michel Kaempf's avatar
Michel Kaempf committed
122
    /* Audio options */
123
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
124
    {   "aout",             1,          0,      OPT_AOUT },
Michel Kaempf's avatar
Michel Kaempf committed
125
    {   "stereo",           0,          0,      OPT_STEREO },
126
    {   "mono",             0,          0,      OPT_MONO },
Michel Kaempf's avatar
Michel Kaempf committed
127 128

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

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

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

/* Short options */
162
static const char *psz_shortopts = "hHvgt:T:a:s:c:";
Benoit Steiner's avatar
Benoit Steiner committed
163 164
#endif

Michel Kaempf's avatar
Michel Kaempf committed
165

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

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

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

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

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

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

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
242 243
    intf_MsgImm( COPYRIGHT_MESSAGE );

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

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

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

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

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

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

Michel Kaempf's avatar
Michel Kaempf committed
300 301 302
    /*
     * Run interface
     */
303
    p_main->p_intf = intf_Create();
Sam Hocevar's avatar
 
Sam Hocevar committed
304 305 306 307 308 309 310 311
    if( !p_main->p_intf )
    {
        intf_ErrMsg( "intf error: interface initialization failed" );
        module_DestroyBank( p_main->p_bank );
        intf_PlstDestroy( p_main->p_playlist );
        intf_MsgDestroy();
        return( errno );
    }
312

Sam Hocevar's avatar
 
Sam Hocevar committed
313 314 315 316 317 318 319 320 321
    /*
     * 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
322
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
323 324
        p_main->p_aout = aout_CreateThread( NULL );
        if( p_main->p_aout == NULL )
325
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
326 327 328 329
            /* On error during audio initialization, switch off audio */
            intf_ErrMsg( "aout error: audio initialization failed,"
                         " audio is deactivated" );
            p_main->b_audio = 0;
330
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
331
    }
332

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

Sam Hocevar's avatar
 
Sam Hocevar committed
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
    /* 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
374 375 376
    /*
     * Free shared resources and libraries
     */
377 378
    /* FIXME */
#if 0
379
    if( p_main->b_vlans )
380 381 382
    {
        input_VlanDestroy();
    }
383
#endif
Michel Kaempf's avatar
Michel Kaempf committed
384

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

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

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

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

Michel Kaempf's avatar
Michel Kaempf committed
408 409 410
    return( 0 );
}

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

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

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

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

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

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

489
    sprintf( psz_value, "%d", i_value );
490
    main_PutPszVariable( psz_name, psz_value );
491 492
}

Michel Kaempf's avatar
Michel Kaempf committed
493 494
/* following functions are local */

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

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
568 569 570 571 572 573 574 575
        /* Interface warning messages level */
        case OPT_INTF:                                             /* --intf */
            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
576
        /* Audio options */
577
        case OPT_NOAUDIO:                                       /* --noaudio */
578
            p_main->b_audio = 0;
Michel Kaempf's avatar
Michel Kaempf committed
579
            break;
580 581 582
        case OPT_AOUT:                                             /* --aout */
            main_PutPszVariable( AOUT_METHOD_VAR, optarg );
            break;
583
        case OPT_STEREO:                                         /* --stereo */
584
            main_PutIntVariable( AOUT_STEREO_VAR, 1 );
Michel Kaempf's avatar
Michel Kaempf committed
585
            break;
586
        case OPT_MONO:                                             /* --mono */
587
            main_PutIntVariable( AOUT_STEREO_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
588 589 590
            break;

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

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

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

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

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

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

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

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

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

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

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

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

    /* Video parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
779 780 781 782 783 784 785 786 787 788 789 790 791
    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
792

793
    /* DVD parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
794 795
    intf_MsgImm( "\nDVD parameters:"
        "\n  " INPUT_DVD_DEVICE_VAR "=<device>           \tDVD device"
Sam Hocevar's avatar
 
Sam Hocevar committed
796 797 798 799 800
        "\n  " INPUT_TITLE_VAR "=<title>             \ttitle number"
        "\n  " INPUT_CHAPTER_VAR "=<chapter>         \tchapter number"
        "\n  " INPUT_AUDIO_VAR "={ac3|lpcm|mpeg|off} \taudio type"
        "\n  " INPUT_CHANNEL_VAR "=[0-15]            \taudio channel"
        "\n  " INPUT_SUBTITLE_VAR "=[0-31]           \tsubtitle channel" );
801

802
    /* Input parameters */
Sam Hocevar's avatar