main.c 36.3 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
 *****************************************************************************
 * Copyright (C) 1998, 1999, 2000 VideoLAN
Sam Hocevar's avatar
 
Sam Hocevar committed
7
 * $Id: main.c,v 1.80 2001/03/21 13:42:34 sam Exp $
8
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
9 10
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
11 12 13 14 15
 *
 * 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.
16
 * 
17 18
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
21
 *
22 23 24
 * 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.
25
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
26

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
39
#ifdef SYS_DARWIN1_3
Sam Hocevar's avatar
 
Sam Hocevar committed
40 41 42 43
#include <mach/mach.h>                                  /* Altivec detection */
#include <mach/mach_error.h>          /* some day the header files||compiler *
                                                       will define it for us */
#include <mach/bootstrap.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
44 45
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
46
#include <unistd.h>
47 48 49
#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                  /* getenv(), strtol(),  */
#include <string.h>                                            /* strerror() */
Vincent Seguin's avatar
Vincent Seguin committed
50

Michel Kaempf's avatar
Michel Kaempf committed
51 52
#include "config.h"
#include "common.h"
Christophe Massiot's avatar
Christophe Massiot committed
53
#include "debug.h"
54
#include "threads.h"
Michel Kaempf's avatar
Michel Kaempf committed
55
#include "mtime.h"
56
#include "tests.h"                                              /* TestCPU() */
Sam Hocevar's avatar
 
Sam Hocevar committed
57
#include "modules.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
58

59 60
#include "stream_control.h"
#include "input_ext-intf.h"
61

Vincent Seguin's avatar
Vincent Seguin committed
62
#include "intf_msg.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
63
#include "intf_playlist.h"
Michel Kaempf's avatar
Michel Kaempf committed
64
#include "interface.h"
65

Vincent Seguin's avatar
Vincent Seguin committed
66
#include "audio_output.h"
67

Sam Hocevar's avatar
 
Sam Hocevar committed
68 69 70
#include "video.h"
#include "video_output.h"

71 72 73 74
#ifdef SYS_BEOS
#include "beos_specific.h"
#endif

Vincent Seguin's avatar
Vincent Seguin committed
75
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
76

77
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
78 79
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
80
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
81 82 83 84

/* 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
85 86
#define OPT_STEREO              151
#define OPT_MONO                152
Michel Kaempf's avatar
Michel Kaempf committed
87 88

#define OPT_NOVIDEO             160
Sam Hocevar's avatar
 
Sam Hocevar committed
89 90 91 92 93 94
#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
95

96
#define OPT_VLANS               170
97 98
#define OPT_SERVER              171
#define OPT_PORT                172
99
#define OPT_BROADCAST           173
100

Sam Hocevar's avatar
 
Sam Hocevar committed
101 102 103 104
#define OPT_INPUT               180
#define OPT_MOTION              181
#define OPT_IDCT                182
#define OPT_YUV                 183
105

Sam Hocevar's avatar
 
Sam Hocevar committed
106 107
#define OPT_SYNCHRO             190
#define OPT_WARNING             191
108

109
/* Usage fashion */
110 111 112
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
113

Michel Kaempf's avatar
Michel Kaempf committed
114
/* Long options */
Benoit Steiner's avatar
 
Benoit Steiner committed
115
#ifdef HAVE_GETOPT_H
Michel Kaempf's avatar
Michel Kaempf committed
116
static const struct option longopts[] =
117 118
{
    /*  name,               has_arg,    flag,   val */
Michel Kaempf's avatar
Michel Kaempf committed
119 120

    /* General/common options */
121
    {   "help",             0,          0,      'h' },
122
    {   "longhelp",         0,          0,      'H' },
123
    {   "version",          0,          0,      'v' },
Michel Kaempf's avatar
Michel Kaempf committed
124

Sam Hocevar's avatar
 
Sam Hocevar committed
125
    /* Interface options */
Sam Hocevar's avatar
 
Sam Hocevar committed
126
    {   "intf",             1,          0,      'I' },
Sam Hocevar's avatar
 
Sam Hocevar committed
127 128
    {   "warning",          1,          0,      OPT_WARNING },

Michel Kaempf's avatar
Michel Kaempf committed
129
    /* Audio options */
130
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
Sam Hocevar's avatar
 
Sam Hocevar committed
131
    {   "aout",             1,          0,      'A' },
Michel Kaempf's avatar
Michel Kaempf committed
132
    {   "stereo",           0,          0,      OPT_STEREO },
133
    {   "mono",             0,          0,      OPT_MONO },
Michel Kaempf's avatar
Michel Kaempf committed
134 135

    /* Video options */
136
    {   "novideo",          0,          0,      OPT_NOVIDEO },
Sam Hocevar's avatar
 
Sam Hocevar committed
137
    {   "vout",             1,          0,      'V' },
138
    {   "display",          1,          0,      OPT_DISPLAY },
139
    {   "width",            1,          0,      OPT_WIDTH },
140 141 142
    {   "height",           1,          0,      OPT_HEIGHT },
    {   "grayscale",        0,          0,      'g' },
    {   "color",            0,          0,      OPT_COLOR },
Sam Hocevar's avatar
 
Sam Hocevar committed
143
    {   "motion",           1,          0,      OPT_MOTION },
Sam Hocevar's avatar
 
Sam Hocevar committed
144
    {   "idct",             1,          0,      OPT_IDCT },
Sam Hocevar's avatar
Sam Hocevar committed
145
    {   "yuv",              1,          0,      OPT_YUV },
Sam Hocevar's avatar
 
Sam Hocevar committed
146 147
    {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
    {   "overlay",          0,          0,      OPT_OVERLAY },
Michel Kaempf's avatar
Michel Kaempf committed
148

149
    /* DVD options */
150 151
    {   "dvdtitle",         1,          0,      't' },
    {   "dvdchapter",       1,          0,      'T' },
152 153 154 155
    {   "dvdaudio",         1,          0,      'a' },
    {   "dvdchannel",       1,          0,      'c' },
    {   "dvdsubtitle",      1,          0,      's' },
    
156
    /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
157
    {   "input",            1,          0,      OPT_INPUT },
158
    {   "vlans",            0,          0,      OPT_VLANS },
159 160
    {   "server",           1,          0,      OPT_SERVER },
    {   "port",             1,          0,      OPT_PORT },
161
    {   "broadcast",        0,          0,      OPT_BROADCAST },
Michel Kaempf's avatar
Michel Kaempf committed
162

163 164
    /* Synchro options */
    {   "synchro",          1,          0,      OPT_SYNCHRO },
Michel Kaempf's avatar
Michel Kaempf committed
165 166 167 168
    {   0,                  0,          0,      0 }
};

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

Michel Kaempf's avatar
Michel Kaempf committed
172

173
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
174
 * Global variable program_data - this is the one and only, see main.h
175
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
176
main_t *p_main;
Michel Kaempf's avatar
Michel Kaempf committed
177

178
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
179
 * Local prototypes
180
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
181
static void SetDefaultConfiguration ( void );
182 183
static int  GetConfiguration        ( int i_argc, char *ppsz_argv[],
                                      char *ppsz_env[] );
Sam Hocevar's avatar
 
Sam Hocevar committed
184
static int  GetFilenames            ( int i_argc, char *ppsz_argv[] );
185
static void Usage                   ( int i_fashion );
Vincent Seguin's avatar
Vincent Seguin committed
186
static void Version                 ( void );
Vincent Seguin's avatar
Vincent Seguin committed
187

Michel Kaempf's avatar
Michel Kaempf committed
188
static void InitSignalHandler       ( void );
Benoit Steiner's avatar
 
Benoit Steiner committed
189 190
static void SimpleSignalHandler     ( int i_signal );
static void FatalSignalHandler      ( int i_signal );
Michel Kaempf's avatar
Michel Kaempf committed
191

Sam Hocevar's avatar
 
Sam Hocevar committed
192 193
static int  CPUCapabilities         ( void );

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

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

210 211 212
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
Sam Hocevar committed
213
#ifdef SYS_BEOS
214
    beos_Create();
215 216
#endif

217
    p_main->i_cpu_capabilities = CPUCapabilities();
Sam Hocevar's avatar
 
Sam Hocevar committed
218
    
Michel Kaempf's avatar
Michel Kaempf committed
219
    /*
220
     * Test if our code is likely to run on this CPU 
221
     */
222 223 224
#if defined( __pentium__ ) || defined( __pentiumpro__ )
    if( ! TestCPU( CPU_CAPABILITY_586 ) )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
225 226
        fprintf( stderr, "error: this program needs a Pentium CPU,\n"
                         "please try a version without Pentium support\n" );
227 228 229 230
        return( 1 );
    }
#endif

Sam Hocevar's avatar
Sam Hocevar committed
231
#ifdef HAVE_MMX
232
    if( ! TestCPU( CPU_CAPABILITY_MMX ) )
233
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
234 235
        fprintf( stderr, "error: this program needs MMX extensions,\n"
                         "please try a version without MMX support\n" );
236
        return( 1 );
237 238
    }
#endif
239 240 241 242

    /*
     * Initialize messages interface
     */
Vincent Seguin's avatar
Vincent Seguin committed
243
    p_main->p_msg = intf_MsgCreate();
244
    if( !p_main->p_msg )                         /* start messages interface */
Michel Kaempf's avatar
Michel Kaempf committed
245
    {
246
        fprintf( stderr, "error: can't initialize messages interface (%s)\n",
Sam Hocevar's avatar
 
Sam Hocevar committed
247
                 strerror(errno) );
248
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
249
    }
250

Sam Hocevar's avatar
 
Sam Hocevar committed
251 252
    intf_MsgImm( COPYRIGHT_MESSAGE );

253
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
254
     * Read configuration
255
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
256
    if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )  /* parse cmd line */
Michel Kaempf's avatar
Michel Kaempf committed
257
    {
Vincent Seguin's avatar
Vincent Seguin committed
258
        intf_MsgDestroy();
259
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
260
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
261 262 263

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

265
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
266
     * Initialize playlist and get commandline files
267
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
268
    p_main->p_playlist = intf_PlaylistCreate( );
Sam Hocevar's avatar
 
Sam Hocevar committed
269
    if( !p_main->p_playlist )
270
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
271
        intf_ErrMsg( "playlist error: playlist initialization failed" );
272 273
        intf_MsgDestroy();
        return( errno );
274
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
275
    intf_PlaylistInit( p_main->p_playlist );
276 277

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
278
     * Get input filenames given as commandline arguments
279
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
280
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
281

Sam Hocevar's avatar
 
Sam Hocevar committed
282 283 284
    /*
     * Initialize module bank
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
285 286
    p_main->p_bank = module_CreateBank( );
    if( !p_main->p_bank )
Sam Hocevar's avatar
 
Sam Hocevar committed
287
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
288
        intf_ErrMsg( "module error: module bank initialization failed" );
Sam Hocevar's avatar
 
Sam Hocevar committed
289
        intf_PlaylistDestroy( p_main->p_playlist );
Sam Hocevar's avatar
 
Sam Hocevar committed
290 291 292
        intf_MsgDestroy();
        return( errno );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
293
    module_InitBank( p_main->p_bank );
Sam Hocevar's avatar
 
Sam Hocevar committed
294

Michel Kaempf's avatar
Michel Kaempf committed
295 296 297
    /*
     * Initialize shared resources and libraries
     */
298 299
    /* FIXME: no VLANs */
#if 0
300
    if( p_main->b_vlans && input_VlanCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
301
    {
302 303
        /* On error during vlans initialization, switch off vlans */
        intf_Msg( "Virtual LANs initialization failed : "
Sam Hocevar's avatar
 
Sam Hocevar committed
304
                  "vlans management is deactivated" );
305
        p_main->b_vlans = 0;
Michel Kaempf's avatar
Michel Kaempf committed
306
    }
307
#endif
308

Michel Kaempf's avatar
Michel Kaempf committed
309 310 311
    /*
     * Run interface
     */
312
    p_main->p_intf = intf_Create();
Sam Hocevar's avatar
 
Sam Hocevar committed
313 314 315 316
    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
317
        intf_PlaylistDestroy( p_main->p_playlist );
Sam Hocevar's avatar
 
Sam Hocevar committed
318 319 320
        intf_MsgDestroy();
        return( errno );
    }
321

Sam Hocevar's avatar
 
Sam Hocevar committed
322 323 324 325 326 327 328 329 330
    /*
     * 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
331
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
332 333
        p_main->p_aout = aout_CreateThread( NULL );
        if( p_main->p_aout == NULL )
334
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
335 336 337 338
            /* On error during audio initialization, switch off audio */
            intf_ErrMsg( "aout error: audio initialization failed,"
                         " audio is deactivated" );
            p_main->b_audio = 0;
339
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
340
    }
341

Sam Hocevar's avatar
 
Sam Hocevar committed
342
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
343
     * Open video device and start vout thread
Sam Hocevar's avatar
 
Sam Hocevar committed
344 345 346 347 348
     */
    if( p_main->b_video )
    {
        p_main->p_vout = vout_CreateThread( NULL );
        if( p_main->p_vout == NULL )
349
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
350
            /* On error during video initialization, switch off video */
Sam Hocevar's avatar
 
Sam Hocevar committed
351 352 353
            intf_ErrMsg( "vout error: video initialization failed,"
                         " video is deactivated" );
            p_main->b_video = 0;
354
        }
Michel Kaempf's avatar
Michel Kaempf committed
355
    }
Michel Kaempf's avatar
Michel Kaempf committed
356

Sam Hocevar's avatar
 
Sam Hocevar committed
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
    /* 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
383 384 385
    /*
     * Free shared resources and libraries
     */
386 387
    /* FIXME */
#if 0
388
    if( p_main->b_vlans )
389 390 391
    {
        input_VlanDestroy();
    }
392
#endif
Michel Kaempf's avatar
Michel Kaempf committed
393

Sam Hocevar's avatar
 
Sam Hocevar committed
394 395 396
    /*
     * Free module bank
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
397
    module_DestroyBank( p_main->p_bank );
398 399 400 401

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

404
#ifdef SYS_BEOS
405 406 407 408
    /*
     * System specific cleaning code
     */
    beos_Destroy();
409 410
#endif

Michel Kaempf's avatar
Michel Kaempf committed
411 412 413
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
414
    intf_Msg( "intf: program terminated" );
Vincent Seguin's avatar
Vincent Seguin committed
415
    intf_MsgDestroy();
416

Michel Kaempf's avatar
Michel Kaempf committed
417 418 419
    return( 0 );
}

420
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
421
 * main_GetIntVariable: get the int value of an environment variable
422
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
423
 * This function is used to read some default parameters in modules.
424
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
425 426
int main_GetIntVariable( char *psz_name, int i_default )
{
427 428 429
    char *      psz_env;                                /* environment value */
    char *      psz_end;                             /* end of parsing index */
    long int    i_value;                                            /* value */
Vincent Seguin's avatar
Vincent Seguin committed
430 431 432

    psz_env = getenv( psz_name );
    if( psz_env )
433
    {
434 435 436 437
        i_value = strtol( psz_env, &psz_end, 0 );
        if( (*psz_env != '\0') && (*psz_end == '\0') )
        {
            return( i_value );
438
        }
439
    }
Vincent Seguin's avatar
Vincent Seguin committed
440 441 442
    return( i_default );
}

443
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
444
 * main_GetPszVariable: get the string value of an environment variable
445
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
446
 * This function is used to read some default parameters in modules.
447
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
448 449 450 451 452 453 454
char * main_GetPszVariable( char *psz_name, char *psz_default )
{
    char *psz_env;

    psz_env = getenv( psz_name );
    if( psz_env )
    {
455
        return( psz_env );
Vincent Seguin's avatar
Vincent Seguin committed
456
    }
457
    return( psz_default );
Vincent Seguin's avatar
Vincent Seguin committed
458 459
}

460
/*****************************************************************************
461
 * main_PutPszVariable: set the string value of an environment variable
462
 *****************************************************************************
463 464 465
 * 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.
466
 *****************************************************************************/
467 468 469 470 471 472 473
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
474 475
        intf_ErrMsg( "intf error: cannot create psz_env (%s)",
                     strerror(ENOMEM) );
476 477 478 479 480 481
    }
    else
    {
        sprintf( psz_env, "%s=%s", psz_name, psz_value );
        if( putenv( psz_env ) )
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
482
            intf_ErrMsg( "intf error: cannot putenv (%s)", strerror(errno) );
483
        }
484 485 486
    }
}

487
/*****************************************************************************
488
 * main_PutIntVariable: set the integer value of an environment variable
489
 *****************************************************************************
490 491 492
 * 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.
493
 *****************************************************************************/
494 495
void main_PutIntVariable( char *psz_name, int i_value )
{
496
    char psz_value[ 256 ];                               /* buffer for value */
497

498
    sprintf( psz_value, "%d", i_value );
499
    main_PutPszVariable( psz_name, psz_value );
500 501
}

Michel Kaempf's avatar
Michel Kaempf committed
502 503
/* following functions are local */

504
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
505
 * SetDefaultConfiguration: set default options
506
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
507
 * This function is called by GetConfiguration before command line is parsed.
Vincent Seguin's avatar
Vincent Seguin committed
508 509 510
 * 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.
511
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
512
static void SetDefaultConfiguration( void )
Michel Kaempf's avatar
Michel Kaempf committed
513 514
{
    /*
515
     * All features are activated by default except vlans
Michel Kaempf's avatar
Michel Kaempf committed
516
     */
Vincent Seguin's avatar
Vincent Seguin committed
517 518
    p_main->b_audio  = 1;
    p_main->b_video  = 1;
519
    p_main->b_vlans  = 0;
Michel Kaempf's avatar
Michel Kaempf committed
520 521
}

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

    /* Set default configuration and copy arguments */
Vincent Seguin's avatar
Vincent Seguin committed
537 538
    p_main->i_argc    = i_argc;
    p_main->ppsz_argv = ppsz_argv;
539
    p_main->ppsz_env  = ppsz_env;
Vincent Seguin's avatar
Vincent Seguin committed
540
    SetDefaultConfiguration();
Michel Kaempf's avatar
Michel Kaempf committed
541

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

Sam Hocevar's avatar
 
Sam Hocevar committed
577
        /* Interface warning messages level */
Sam Hocevar's avatar
 
Sam Hocevar committed
578
	case 'I':                                              /* -I, --intf */
Sam Hocevar's avatar
 
Sam Hocevar committed
579 580 581 582 583 584
            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
585
        /* Audio options */
586
        case OPT_NOAUDIO:                                       /* --noaudio */
587
            p_main->b_audio = 0;
Michel Kaempf's avatar
Michel Kaempf committed
588
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
589
        case 'A':                                              /* -A, --aout */
590 591
            main_PutPszVariable( AOUT_METHOD_VAR, optarg );
            break;
592
        case OPT_STEREO:                                         /* --stereo */
593
            main_PutIntVariable( AOUT_STEREO_VAR, 1 );
Michel Kaempf's avatar
Michel Kaempf committed
594
            break;
595
        case OPT_MONO:                                             /* --mono */
596
            main_PutIntVariable( AOUT_STEREO_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
597 598 599
            break;

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

637
        /* DVD options */
638 639 640 641 642 643
        case 't':
            main_PutIntVariable( INPUT_TITLE_VAR, atoi(optarg) );
            break;
        case 'T':
            main_PutIntVariable( INPUT_CHAPTER_VAR, atoi(optarg) );
            break;
644
        case 'a':
645
            if ( ! strcmp(optarg, "ac3") )
Sam Hocevar's avatar
 
Sam Hocevar committed
646
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_AC3 );
647
            else if ( ! strcmp(optarg, "lpcm") )
Sam Hocevar's avatar
 
Sam Hocevar committed
648
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_LPCM );
649
            else if ( ! strcmp(optarg, "mpeg") )
Sam Hocevar's avatar
 
Sam Hocevar committed
650
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_MPEG );
651
            else
Sam Hocevar's avatar
 
Sam Hocevar committed
652
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_NOAUDIO );
653 654
            break;
        case 'c':
Sam Hocevar's avatar
 
Sam Hocevar committed
655
            main_PutIntVariable( INPUT_CHANNEL_VAR, atoi(optarg) );
656 657
            break;
        case 's':
Sam Hocevar's avatar
 
Sam Hocevar committed
658
            main_PutIntVariable( INPUT_SUBTITLE_VAR, atoi(optarg) );
659 660
            break;

661
        /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
662
        case OPT_INPUT:                                           /* --input */
Sam Hocevar's avatar
 
Sam Hocevar committed
663 664
            main_PutPszVariable( INPUT_METHOD_VAR, optarg );
            break;
665
        case OPT_VLANS:                                           /* --vlans */
666
            p_main->b_vlans = 1;
667 668
            break;
        case OPT_SERVER:                                         /* --server */
669
            main_PutPszVariable( INPUT_SERVER_VAR, optarg );
670 671
            break;
        case OPT_PORT:                                             /* --port */
672
            main_PutPszVariable( INPUT_PORT_VAR, optarg );
673
            break;
674 675 676
        case OPT_BROADCAST:                                   /* --broadcast */
            main_PutIntVariable( INPUT_BROADCAST_VAR, 1 );
            break;
677

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

Sam Hocevar's avatar
 
Sam Hocevar committed
705
    /* We assume that the remaining parameters are filenames */
Vincent Seguin's avatar
Vincent Seguin committed
706 707
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
708 709
        intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
                          ppsz_argv[ i_opt ] );
Vincent Seguin's avatar
Vincent Seguin committed
710
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
711

Michel Kaempf's avatar
Michel Kaempf committed
712 713 714
    return( 0 );
}

715
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
716
 * Usage: print program usage
717
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
718
 * Print a short inline help. Message interface is initialized at this stage.
719
 *****************************************************************************/
720
static void Usage( int i_fashion )
Michel Kaempf's avatar
Michel Kaempf committed
721
{
Vincent Seguin's avatar
Vincent Seguin committed
722
    /* Usage */
Sam Hocevar's avatar
 
Sam Hocevar committed
723 724
    intf_MsgImm( "Usage: %s [options] [parameters] [file]...",
                 p_main->psz_arg0 );
725 726 727

    if( i_fashion == USAGE )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
728 729
        intf_MsgImm( "Try `%s --help' for more information.",
                     p_main->psz_arg0 );
730 731 732
        return;
    }

Vincent Seguin's avatar
Vincent Seguin committed
733
    /* Options */
Sam Hocevar's avatar
 
Sam Hocevar committed
734
    intf_MsgImm( "\nOptions:"
Sam Hocevar's avatar
 
Sam Hocevar committed
735
          "\n  -I, --intf <module>            \tinterface method"
Sam Hocevar's avatar
 
Sam Hocevar committed
736 737
          "\n      --warning <level>          \tdisplay warning messages"
          "\n"
Sam Hocevar's avatar
 
Sam Hocevar committed
738
          "\n      --noaudio                  \tdisable audio"
Sam Hocevar's avatar
 
Sam Hocevar committed
739
          "\n  -A, --aout <module>            \taudio output method"
Sam Hocevar's avatar
 
Sam Hocevar committed
740 741 742
          "\n      --stereo, --mono           \tstereo/mono audio"
          "\n"
          "\n      --novideo                  \tdisable video"
Sam Hocevar's avatar
 
Sam Hocevar committed
743
          "\n  -V, --vout <module>            \tvideo output method"
Sam Hocevar's avatar
 
Sam Hocevar committed
744 745 746 747 748 749 750 751 752 753 754
          "\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"
755 756
          "\n  -t, --dvdtitle <num>           \tchoose DVD title"
          "\n  -T, --dvdchapter <num>         \tchoose DVD chapter"
Sam Hocevar's avatar
 
Sam Hocevar committed
757 758 759 760 761 762 763 764 765 766 767 768 769
          "\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
770

771 772 773
    if( i_fashion == SHORT_HELP )
        return;

Vincent Seguin's avatar
Vincent Seguin committed
774
    /* Interface parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
775
    intf_MsgImm( "\nInterface parameters:"
Sam Hocevar's avatar
 
Sam Hocevar committed
776
        "\n  " INTF_METHOD_VAR "=<method name>          \tinterface method"
Sam Hocevar's avatar
 
Sam Hocevar committed
777
        "\n  " INTF_INIT_SCRIPT_VAR "=<filename>               <