main.c 35.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 38 39 40
#ifdef SYS_DARWIN1_3
#include <Carbon/Carbon.h>                              /* Altivec detection */
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
41
#include <unistd.h>
42 43 44
#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                  /* getenv(), strtol(),  */
#include <string.h>                                            /* strerror() */
Vincent Seguin's avatar
Vincent Seguin committed
45

Michel Kaempf's avatar
Michel Kaempf committed
46 47
#include "config.h"
#include "common.h"
Christophe Massiot's avatar
Christophe Massiot committed
48
#include "debug.h"
49
#include "threads.h"
Michel Kaempf's avatar
Michel Kaempf committed
50
#include "mtime.h"
51
#include "tests.h"                                              /* TestCPU() */
Sam Hocevar's avatar
 
Sam Hocevar committed
52
#include "modules.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
53

54 55
#include "stream_control.h"
#include "input_ext-intf.h"
56

Vincent Seguin's avatar
Vincent Seguin committed
57
#include "intf_msg.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
58
#include "intf_playlist.h"
Michel Kaempf's avatar
Michel Kaempf committed
59
#include "interface.h"
60

Vincent Seguin's avatar
Vincent Seguin committed
61
#include "audio_output.h"
62

Sam Hocevar's avatar
 
Sam Hocevar committed
63 64 65
#include "video.h"
#include "video_output.h"

66 67 68 69
#ifdef SYS_BEOS
#include "beos_specific.h"
#endif

Vincent Seguin's avatar
Vincent Seguin committed
70
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
71

72
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
73 74
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
75
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
76 77 78 79

/* 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
80 81
#define OPT_STEREO              151
#define OPT_MONO                152
Michel Kaempf's avatar
Michel Kaempf committed
82 83

#define OPT_NOVIDEO             160
Sam Hocevar's avatar
 
Sam Hocevar committed
84 85 86 87 88 89
#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
90

91
#define OPT_VLANS               170
92 93
#define OPT_SERVER              171
#define OPT_PORT                172
94
#define OPT_BROADCAST           173
95

Sam Hocevar's avatar
 
Sam Hocevar committed
96 97 98 99
#define OPT_INPUT               180
#define OPT_MOTION              181
#define OPT_IDCT                182
#define OPT_YUV                 183
100

Sam Hocevar's avatar
 
Sam Hocevar committed
101 102
#define OPT_SYNCHRO             190
#define OPT_WARNING             191
103

104
/* Usage fashion */
105 106 107
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
108

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
120
    /* Interface options */
Sam Hocevar's avatar
 
Sam Hocevar committed
121
    {   "intf",             1,          0,      'I' },
Sam Hocevar's avatar
 
Sam Hocevar committed
122 123
    {   "warning",          1,          0,      OPT_WARNING },

Michel Kaempf's avatar
Michel Kaempf committed
124
    /* Audio options */
125
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
Sam Hocevar's avatar
 
Sam Hocevar committed
126
    {   "aout",             1,          0,      'A' },
Michel Kaempf's avatar
Michel Kaempf committed
127
    {   "stereo",           0,          0,      OPT_STEREO },
128
    {   "mono",             0,          0,      OPT_MONO },
Michel Kaempf's avatar
Michel Kaempf committed
129 130

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

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

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

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

Michel Kaempf's avatar
Michel Kaempf committed
167

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
187 188
static int  CPUCapabilities         ( void );

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

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

205 206 207
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
Sam Hocevar committed
208
#ifdef SYS_BEOS
209
    beos_Create();
210 211
#endif

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
246 247
    intf_MsgImm( COPYRIGHT_MESSAGE );

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

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

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

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
273
     * Get input filenames given as commandline arguments
274
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
275
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
276

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

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

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

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
389 390 391
    /*
     * Free module bank
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
392
    module_DestroyBank( p_main->p_bank );
393 394 395 396

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

399
#ifdef SYS_BEOS
400 401 402 403
    /*
     * System specific cleaning code
     */
    beos_Destroy();
404 405
#endif

Michel Kaempf's avatar
Michel Kaempf committed
406 407 408
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
409
    intf_Msg( "intf: program terminated" );
Vincent Seguin's avatar
Vincent Seguin committed
410
    intf_MsgDestroy();
411

Michel Kaempf's avatar
Michel Kaempf committed
412 413 414
    return( 0 );
}

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

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

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

    psz_env = getenv( psz_name );
    if( psz_env )
    {
450
        return( psz_env );
Vincent Seguin's avatar
Vincent Seguin committed
451
    }
452
    return( psz_default );
Vincent Seguin's avatar
Vincent Seguin committed
453 454
}

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

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

493
    sprintf( psz_value, "%d", i_value );
494
    main_PutPszVariable( psz_name, psz_value );
495 496
}

Michel Kaempf's avatar
Michel Kaempf committed
497 498
/* following functions are local */

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

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

    /* Set default configuration and copy arguments */
Vincent Seguin's avatar
Vincent Seguin committed
532 533
    p_main->i_argc    = i_argc;
    p_main->ppsz_argv = ppsz_argv;
534
    p_main->ppsz_env  = ppsz_env;
Vincent Seguin's avatar
Vincent Seguin committed
535
    SetDefaultConfiguration();
Michel Kaempf's avatar
Michel Kaempf committed
536

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

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

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

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

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

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

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

Michel Kaempf's avatar
Michel Kaempf committed
707 708 709
    return( 0 );
}

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

    if( i_fashion == USAGE )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
723 724
        intf_MsgImm( "Try `%s --help' for more information.",
                     p_main->psz_arg0 );
725 726 727
        return;
    }

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

766 767 768
    if( i_fashion == SHORT_HELP )
        return;

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

    /* Audio parameters */
Sam Hocevar's avatar
 
Sam Hocevar committed
777 778 779 780 781
    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
782