main.c 36.6 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.91 2001/05/01 04:18:18 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() */

Sam Hocevar's avatar
 
Sam Hocevar committed
35 36 37 38 39 40
#ifdef HAVE_GETOPT_LONG
#   ifdef HAVE_GETOPT_H
#       include <getopt.h>                                       /* getopt() */
#   endif
#else
#   include "GNUgetopt/getopt.h"
Benoit Steiner's avatar
Benoit Steiner committed
41 42
#endif

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

Sam Hocevar's avatar
 
Sam Hocevar committed
50
#include <unistd.h>
51 52 53
#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                  /* getenv(), strtol(),  */
#include <string.h>                                            /* strerror() */
Vincent Seguin's avatar
Vincent Seguin committed
54

Michel Kaempf's avatar
Michel Kaempf committed
55 56
#include "config.h"
#include "common.h"
Christophe Massiot's avatar
Christophe Massiot committed
57
#include "debug.h"
58
#include "threads.h"
Michel Kaempf's avatar
Michel Kaempf committed
59
#include "mtime.h"
60
#include "tests.h"                                              /* TestCPU() */
Sam Hocevar's avatar
 
Sam Hocevar committed
61
#include "modules.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
62

63 64
#include "stream_control.h"
#include "input_ext-intf.h"
65

Vincent Seguin's avatar
Vincent Seguin committed
66
#include "intf_msg.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
67
#include "intf_playlist.h"
Michel Kaempf's avatar
Michel Kaempf committed
68
#include "interface.h"
69

Vincent Seguin's avatar
Vincent Seguin committed
70
#include "audio_output.h"
71

Sam Hocevar's avatar
 
Sam Hocevar committed
72 73 74
#include "video.h"
#include "video_output.h"

75
#ifdef SYS_BEOS
Sam Hocevar's avatar
 
Sam Hocevar committed
76 77 78 79 80
#   include "beos_specific.h"
#endif

#ifdef SYS_DARWIN1_3
#   include "darwin_specific.h"
81 82
#endif

Henri Fallon's avatar
 
Henri Fallon committed
83 84
#include "netutils.h"                                 /* network_ChannelJoin */

Vincent Seguin's avatar
Vincent Seguin committed
85
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
86

87
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
88 89
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
90
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
91 92 93 94

/* 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
95 96
#define OPT_STEREO              151
#define OPT_MONO                152
97
#define OPT_SPDIF               153
Michel Kaempf's avatar
Michel Kaempf committed
98 99

#define OPT_NOVIDEO             160
Sam Hocevar's avatar
 
Sam Hocevar committed
100 101 102 103 104 105
#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
106

Henri Fallon's avatar
 
Henri Fallon committed
107
#define OPT_CHANNELS            170
108 109
#define OPT_SERVER              171
#define OPT_PORT                172
110
#define OPT_BROADCAST           173
111

Sam Hocevar's avatar
 
Sam Hocevar committed
112 113 114 115
#define OPT_INPUT               180
#define OPT_MOTION              181
#define OPT_IDCT                182
#define OPT_YUV                 183
116

Sam Hocevar's avatar
 
Sam Hocevar committed
117 118
#define OPT_SYNCHRO             190
#define OPT_WARNING             191
Sam Hocevar's avatar
 
Sam Hocevar committed
119
#define OPT_VERSION             192
120

121
/* Usage fashion */
122 123 124
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
125

Michel Kaempf's avatar
Michel Kaempf committed
126 127
/* Long options */
static const struct option longopts[] =
128 129
{
    /*  name,               has_arg,    flag,   val */
Michel Kaempf's avatar
Michel Kaempf committed
130 131

    /* General/common options */
132
    {   "help",             0,          0,      'h' },
133
    {   "longhelp",         0,          0,      'H' },
Sam Hocevar's avatar
 
Sam Hocevar committed
134
    {   "version",          0,          0,      OPT_VERSION },
Michel Kaempf's avatar
Michel Kaempf committed
135

Sam Hocevar's avatar
 
Sam Hocevar committed
136
    /* Interface options */
Sam Hocevar's avatar
 
Sam Hocevar committed
137
    {   "intf",             1,          0,      'I' },
Sam Hocevar's avatar
 
Sam Hocevar committed
138 139
    {   "warning",          1,          0,      OPT_WARNING },

Michel Kaempf's avatar
Michel Kaempf committed
140
    /* Audio options */
141
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
Sam Hocevar's avatar
 
Sam Hocevar committed
142
    {   "aout",             1,          0,      'A' },
Michel Kaempf's avatar
Michel Kaempf committed
143
    {   "stereo",           0,          0,      OPT_STEREO },
144
    {   "mono",             0,          0,      OPT_MONO },
145
    {   "spdif",            0,          0,      OPT_SPDIF },
Michel Kaempf's avatar
Michel Kaempf committed
146 147

    /* Video options */
148
    {   "novideo",          0,          0,      OPT_NOVIDEO },
Sam Hocevar's avatar
 
Sam Hocevar committed
149
    {   "vout",             1,          0,      'V' },
150
    {   "display",          1,          0,      OPT_DISPLAY },
151
    {   "width",            1,          0,      OPT_WIDTH },
152 153 154
    {   "height",           1,          0,      OPT_HEIGHT },
    {   "grayscale",        0,          0,      'g' },
    {   "color",            0,          0,      OPT_COLOR },
Sam Hocevar's avatar
 
Sam Hocevar committed
155
    {   "motion",           1,          0,      OPT_MOTION },
Sam Hocevar's avatar
 
Sam Hocevar committed
156
    {   "idct",             1,          0,      OPT_IDCT },
Sam Hocevar's avatar
Sam Hocevar committed
157
    {   "yuv",              1,          0,      OPT_YUV },
Sam Hocevar's avatar
 
Sam Hocevar committed
158 159
    {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
    {   "overlay",          0,          0,      OPT_OVERLAY },
Michel Kaempf's avatar
Michel Kaempf committed
160

161
    /* DVD options */
162 163
    {   "dvdtitle",         1,          0,      't' },
    {   "dvdchapter",       1,          0,      'T' },
164
    {   "dvdangle",         1,          0,      'u' },
165 166 167 168
    {   "dvdaudio",         1,          0,      'a' },
    {   "dvdchannel",       1,          0,      'c' },
    {   "dvdsubtitle",      1,          0,      's' },
    
169
    /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
170
    {   "input",            1,          0,      OPT_INPUT },
Henri Fallon's avatar
 
Henri Fallon committed
171
    {   "channels",         0,          0,      OPT_CHANNELS },
172 173
    {   "server",           1,          0,      OPT_SERVER },
    {   "port",             1,          0,      OPT_PORT },
Henri Fallon's avatar
 
Henri Fallon committed
174
    {   "broadcast",        1,          0,      OPT_BROADCAST },
Michel Kaempf's avatar
Michel Kaempf committed
175

176 177
    /* Synchro options */
    {   "synchro",          1,          0,      OPT_SYNCHRO },
Michel Kaempf's avatar
Michel Kaempf committed
178 179 180 181
    {   0,                  0,          0,      0 }
};

/* Short options */
182
static const char *psz_shortopts = "hHvgt:T:u:a:s:c:I:A:V:";
Michel Kaempf's avatar
Michel Kaempf committed
183

184
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
185 186
 * Global variable program_data - these are the only ones, see main.h and
 * modules.h
187
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
188
main_t *p_main;
Sam Hocevar's avatar
 
Sam Hocevar committed
189
bank_t *p_bank;
Michel Kaempf's avatar
Michel Kaempf committed
190

191
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
192
 * Local prototypes
193
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
194
static int  GetConfiguration        ( int *pi_argc, char *ppsz_argv[],
195
                                      char *ppsz_env[] );
Sam Hocevar's avatar
 
Sam Hocevar committed
196
static int  GetFilenames            ( int i_argc, char *ppsz_argv[] );
197
static void Usage                   ( int i_fashion );
Vincent Seguin's avatar
Vincent Seguin committed
198
static void Version                 ( void );
Vincent Seguin's avatar
Vincent Seguin committed
199

Michel Kaempf's avatar
Michel Kaempf committed
200
static void InitSignalHandler       ( void );
Benoit Steiner's avatar
 
Benoit Steiner committed
201 202
static void SimpleSignalHandler     ( int i_signal );
static void FatalSignalHandler      ( int i_signal );
Michel Kaempf's avatar
Michel Kaempf committed
203

Sam Hocevar's avatar
 
Sam Hocevar committed
204 205
static int  CPUCapabilities         ( void );

206
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
207
 * main: parse command line, start interface and spawn threads
208
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
209 210
 * Steps during program execution are:
 *      -configuration parsing and messages interface initialization
211
 *      -opening of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
212
 *      -execution of interface, which exit on error or on user request
Vincent Seguin's avatar
Vincent Seguin committed
213
 *      -closing of audio output device and some global modules
214
 * On error, the spawned threads are canceled, and the open devices closed.
215
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
216 217
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
218
    main_t  main_data;                      /* root of all data - see main.h */
Sam Hocevar's avatar
 
Sam Hocevar committed
219
    bank_t  module_bank;
220

Sam Hocevar's avatar
 
Sam Hocevar committed
221 222 223 224 225 226 227 228 229 230
    p_main = &main_data;                      /* set up the global variables */
    p_bank = &module_bank;

    /*
     * Initialize the main structure
     */
    p_main->i_cpu_capabilities = CPUCapabilities();
    
    p_main->p_aout = NULL;
    p_main->p_vout = NULL;
Vincent Seguin's avatar
Vincent Seguin committed
231

232 233 234
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
235 236
#if defined( SYS_BEOS ) || defined( SYS_DARWIN1_3 )
    system_Create( &i_argc, ppsz_argv, ppsz_env );
237 238
#endif

Michel Kaempf's avatar
Michel Kaempf committed
239
    /*
240
     * Test if our code is likely to run on this CPU 
241
     */
242 243 244
#if defined( __pentium__ ) || defined( __pentiumpro__ )
    if( ! TestCPU( CPU_CAPABILITY_586 ) )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
245 246
        fprintf( stderr, "error: this program needs a Pentium CPU,\n"
                         "please try a version without Pentium support\n" );
247 248 249 250
        return( 1 );
    }
#endif

Sam Hocevar's avatar
Sam Hocevar committed
251
#ifdef HAVE_MMX
252
    if( ! TestCPU( CPU_CAPABILITY_MMX ) )
253
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
254 255
        fprintf( stderr, "error: this program needs MMX extensions,\n"
                         "please try a version without MMX support\n" );
256
        return( 1 );
257 258
    }
#endif
259 260 261 262

    /*
     * Initialize messages interface
     */
Vincent Seguin's avatar
Vincent Seguin committed
263
    p_main->p_msg = intf_MsgCreate();
264
    if( !p_main->p_msg )                         /* start messages interface */
Michel Kaempf's avatar
Michel Kaempf committed
265
    {
266
        fprintf( stderr, "error: can't initialize messages interface (%s)\n",
Sam Hocevar's avatar
 
Sam Hocevar committed
267
                 strerror(errno) );
268
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
269
    }
270

Sam Hocevar's avatar
 
Sam Hocevar committed
271 272
    intf_MsgImm( COPYRIGHT_MESSAGE );

273
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
274
     * Read configuration
275
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
276
    if( GetConfiguration( &i_argc, ppsz_argv, ppsz_env ) ) /* parse cmd line */
Michel Kaempf's avatar
Michel Kaempf committed
277
    {
Vincent Seguin's avatar
Vincent Seguin committed
278
        intf_MsgDestroy();
279
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
280
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
281

282
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
283
     * Initialize playlist and get commandline files
284
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
285
    p_main->p_playlist = intf_PlaylistCreate();
Sam Hocevar's avatar
 
Sam Hocevar committed
286
    if( !p_main->p_playlist )
287
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
288
        intf_ErrMsg( "playlist error: playlist initialization failed" );
289 290
        intf_MsgDestroy();
        return( errno );
291
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
292
    intf_PlaylistInit( p_main->p_playlist );
293 294

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
295
     * Get input filenames given as commandline arguments
296
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
297
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
298

Sam Hocevar's avatar
 
Sam Hocevar committed
299 300 301
    /*
     * Initialize module bank
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
302
    module_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
303

Michel Kaempf's avatar
Michel Kaempf committed
304 305 306
    /*
     * Initialize shared resources and libraries
     */
Henri Fallon's avatar
 
Henri Fallon committed
307
    if( p_main->b_channels && network_ChannelCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
308
    {
Henri Fallon's avatar
 
Henri Fallon committed
309 310 311 312
        /* On error during Channels initialization, switch off channels */
        intf_Msg( "Channels initialization failed : "
                  "Channel management is deactivated" );
        p_main->b_channels = 0;
Michel Kaempf's avatar
Michel Kaempf committed
313
    }
314

Michel Kaempf's avatar
Michel Kaempf committed
315 316 317
    /*
     * Run interface
     */
318
    p_main->p_intf = intf_Create();
Sam Hocevar's avatar
 
Sam Hocevar committed
319 320 321
    if( !p_main->p_intf )
    {
        intf_ErrMsg( "intf error: interface initialization failed" );
Sam Hocevar's avatar
 
Sam Hocevar committed
322
        module_EndBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
323
        intf_PlaylistDestroy( p_main->p_playlist );
Sam Hocevar's avatar
 
Sam Hocevar committed
324 325 326
        intf_MsgDestroy();
        return( errno );
    }
327

Sam Hocevar's avatar
 
Sam Hocevar committed
328 329 330 331 332 333 334 335 336 337
    /*
     * Set signal handling policy for all threads
     */
    InitSignalHandler();

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

Sam Hocevar's avatar
 
Sam Hocevar committed
338 339 340
    /*
     * Finished, destroy the interface
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
341 342 343
    intf_Destroy( p_main->p_intf );

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
344
     * Close all video devices
Sam Hocevar's avatar
 
Sam Hocevar committed
345
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
346
    if( p_main->p_vout != NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
347 348 349 350 351
    {
        vout_DestroyThread( p_main->p_vout, NULL );
    }

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
352
     * Close all audio devices
Sam Hocevar's avatar
 
Sam Hocevar committed
353
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
354
    if( p_main->p_aout != NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
355 356 357 358
    {
        aout_DestroyThread( p_main->p_aout, NULL );
    }

Michel Kaempf's avatar
Michel Kaempf committed
359
    /*
Henri Fallon's avatar
 
Henri Fallon committed
360
     * Go back into channel 0 which is the network
Michel Kaempf's avatar
Michel Kaempf committed
361
     */
Henri Fallon's avatar
 
Henri Fallon committed
362
    if( p_main->b_channels )
363
    {
Henri Fallon's avatar
 
Henri Fallon committed
364
        network_ChannelJoin( COMMON_CHANNEL );
365
    }
Michel Kaempf's avatar
Michel Kaempf committed
366

Sam Hocevar's avatar
 
Sam Hocevar committed
367 368 369
    /*
     * Free module bank
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
370
    module_EndBank();
371 372 373 374

    /*
     * Free playlist
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
375
    intf_PlaylistDestroy( p_main->p_playlist );
376 377 378 379

    /*
     * System specific cleaning code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
380 381
#if defined( SYS_BEOS ) || defined( SYS_DARWIN1_3 )
    system_Destroy();
382 383
#endif

Michel Kaempf's avatar
Michel Kaempf committed
384 385 386
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
387
    intf_Msg( "intf: program terminated" );
Vincent Seguin's avatar
Vincent Seguin committed
388
    intf_MsgDestroy();
389

Michel Kaempf's avatar
Michel Kaempf committed
390 391 392
    return( 0 );
}

393
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
394
 * main_GetIntVariable: get the int value of an environment variable
395
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
396
 * This function is used to read some default parameters in modules.
397
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
398 399
int main_GetIntVariable( char *psz_name, int i_default )
{
400 401 402
    char *      psz_env;                                /* environment value */
    char *      psz_end;                             /* end of parsing index */
    long int    i_value;                                            /* value */
Vincent Seguin's avatar
Vincent Seguin committed
403 404 405

    psz_env = getenv( psz_name );
    if( psz_env )
406
    {
407 408 409 410
        i_value = strtol( psz_env, &psz_end, 0 );
        if( (*psz_env != '\0') && (*psz_end == '\0') )
        {
            return( i_value );
411
        }
412
    }
Vincent Seguin's avatar
Vincent Seguin committed
413 414 415
    return( i_default );
}

416
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
417
 * main_GetPszVariable: get the string value of an environment variable
418
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
419
 * This function is used to read some default parameters in modules.
420
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
421 422 423 424 425 426 427
char * main_GetPszVariable( char *psz_name, char *psz_default )
{
    char *psz_env;

    psz_env = getenv( psz_name );
    if( psz_env )
    {
428
        return( psz_env );
Vincent Seguin's avatar
Vincent Seguin committed
429
    }
430
    return( psz_default );
Vincent Seguin's avatar
Vincent Seguin committed
431 432
}

433
/*****************************************************************************
434
 * main_PutPszVariable: set the string value of an environment variable
435
 *****************************************************************************
436 437 438
 * 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.
439
 *****************************************************************************/
440 441 442 443 444 445 446
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
447 448
        intf_ErrMsg( "intf error: cannot create psz_env (%s)",
                     strerror(ENOMEM) );
449 450 451 452 453 454
    }
    else
    {
        sprintf( psz_env, "%s=%s", psz_name, psz_value );
        if( putenv( psz_env ) )
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
455
            intf_ErrMsg( "intf error: cannot putenv (%s)", strerror(errno) );
456
        }
457 458 459
    }
}

460
/*****************************************************************************
461
 * main_PutIntVariable: set the integer 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
void main_PutIntVariable( char *psz_name, int i_value )
{
469
    char psz_value[ 256 ];                               /* buffer for value */
470

471
    sprintf( psz_value, "%d", i_value );
472
    main_PutPszVariable( psz_name, psz_value );
473 474
}

Michel Kaempf's avatar
Michel Kaempf committed
475 476
/* following functions are local */

477
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
478
 * GetConfiguration: parse command line
479
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
480 481
 * Parse command line and configuration file for configuration. If the inline
 * help is requested, the function Usage() is called and the function returns
482
 * -1 (causing main() to exit). The messages interface is initialized at this
Vincent Seguin's avatar
Vincent Seguin committed
483 484
 * stage, but most structures are not allocated, so only environment should
 * be used.
485
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
486
static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
Michel Kaempf's avatar
Michel Kaempf committed
487
{
Sam Hocevar's avatar
 
Sam Hocevar committed
488 489
    int   i_cmd;
    char *p_tmp;
Michel Kaempf's avatar
Michel Kaempf committed
490 491

    /* Set default configuration and copy arguments */
Sam Hocevar's avatar
 
Sam Hocevar committed
492
    p_main->i_argc    = *pi_argc;
Vincent Seguin's avatar
Vincent Seguin committed
493
    p_main->ppsz_argv = ppsz_argv;
494
    p_main->ppsz_env  = ppsz_env;
Sam Hocevar's avatar
 
Sam Hocevar committed
495

Henri Fallon's avatar
 
Henri Fallon committed
496 497 498
    p_main->b_audio     = 1;
    p_main->b_video     = 1;
    p_main->b_channels  = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
499 500

    p_main->i_warning_level = 4;
Michel Kaempf's avatar
Michel Kaempf committed
501

502
    /* Get the executable name (similar to the basename command) */
Sam Hocevar's avatar
 
Sam Hocevar committed
503 504
    p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
    while( *p_tmp )
Sam Hocevar's avatar
Sam Hocevar committed
505
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
506
        if( *p_tmp == '/' )
Sam Hocevar's avatar
Sam Hocevar committed
507
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
508
            p_main->psz_arg0 = ++p_tmp;
Sam Hocevar's avatar
Sam Hocevar committed
509 510 511
        }
        else
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
512
            ++p_tmp;
Sam Hocevar's avatar
Sam Hocevar committed
513 514 515
        }
    }

516
#ifdef SYS_DARWIN1_3
Sam Hocevar's avatar
 
Sam Hocevar committed
517 518 519
    /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
     * is the PSN - process serial number (a unique PID-ish thingie)
     * still ok for real Darwin & when run from command line */
Sam Hocevar's avatar
 
Sam Hocevar committed
520 521
    if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
                                        /* for example -psn_0_9306113 */
522
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
523 524 525 526 527 528 529 530 531
        /* GDMF!... I can't do this or else the MacOSX window server will
         * not pick up the PSN and not register the app and we crash...
         * hence the following kludge otherwise we'll get confused w/ argv[1]
         * being an input file name */
#if 0
        ppsz_argv[ 1 ] = NULL;
#endif
        *pi_argc = *pi_argc - 1;
        pi_argc--;
532 533 534 535
        return( 0 );
    }
#endif

Vincent Seguin's avatar
Vincent Seguin committed
536
    /* Parse command line options */
Michel Kaempf's avatar
Michel Kaempf committed
537
    opterr = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
538 539
    while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv,
                                   psz_shortopts, longopts, 0 ) ) != EOF )
Michel Kaempf's avatar
Michel Kaempf committed
540
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
541
        switch( i_cmd )
Michel Kaempf's avatar
Michel Kaempf committed
542
        {
543 544
        /* General/common options */
        case 'h':                                              /* -h, --help */
545 546 547
            Usage( SHORT_HELP );
            return( -1 );
            break;
548
        case 'H':                                          /* -H, --longhelp */
549
            Usage( LONG_HELP );
Michel Kaempf's avatar
Michel Kaempf committed
550 551
            return( -1 );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
552
        case OPT_VERSION:                                       /* --version */
Vincent Seguin's avatar
Vincent Seguin committed
553 554
            Version();
            return( -1 );
555
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
556
        case 'v':                                           /* -v, --verbose */
Sam Hocevar's avatar
 
Sam Hocevar committed
557
            p_main->i_warning_level--;
Sam Hocevar's avatar
 
Sam Hocevar committed
558
            break;
Michel Kaempf's avatar
Michel Kaempf committed
559

Sam Hocevar's avatar
 
Sam Hocevar committed
560
        /* Interface warning messages level */
Sam Hocevar's avatar
 
Sam Hocevar committed
561
        case 'I':                                              /* -I, --intf */
Sam Hocevar's avatar
 
Sam Hocevar committed
562 563 564
            main_PutPszVariable( INTF_METHOD_VAR, optarg );
            break;
        case OPT_WARNING:                                       /* --warning */
Sam Hocevar's avatar
 
Sam Hocevar committed
565 566
            intf_ErrMsg( "intf error: `--warning' is deprecated, use `-v'" );
            p_main->i_warning_level = atoi(optarg);
Sam Hocevar's avatar
 
Sam Hocevar committed
567 568
            break;

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

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

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

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

668
        /* Synchro options */
669
        case OPT_SYNCHRO:                                      
670 671
            main_PutPszVariable( VPAR_SYNCHRO_VAR, optarg );
            break;
672
            
Michel Kaempf's avatar
Michel Kaempf committed
673
        /* Internal error: unknown option */
674
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
675
        default:
Sam Hocevar's avatar
 
Sam Hocevar committed
676 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;
        }
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
683 684 685 686 687 688

    if( p_main->i_warning_level < 0 )
    {
        p_main->i_warning_level = 0;
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
689 690 691 692 693 694 695 696 697 698 699
    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
700

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

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

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

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

Vincent Seguin's avatar
Vincent Seguin committed
729
    /* Options */
Sam Hocevar's avatar
 
Sam Hocevar committed
730
    intf_MsgImm( "\nOptions:"
Sam Hocevar's avatar
 
Sam Hocevar committed
731
          "\n  -I, --intf <module>            \tinterface method"
Sam Hocevar's avatar
 
Sam Hocevar committed
732
          "\n  -v, --verbose                  \tverbose mode (cumulative)"
Sam Hocevar's avatar
 
Sam Hocevar committed
733
          "\n"
Sam Hocevar's avatar
 
Sam Hocevar committed
734
          "\n      --noaudio                  \tdisable audio"
Sam Hocevar's avatar
 
Sam Hocevar committed
735
          "\n  -A, --aout <module>            \taudio output method"
Sam Hocevar's avatar
 
Sam Hocevar committed
736
          "\n      --stereo, --mono           \tstereo/mono audio"
Sam Hocevar's avatar
 
Sam Hocevar committed
737
          "\n      --spdif                    \tAC3 pass-through mode"
Sam Hocevar's avatar
 
Sam Hocevar committed
738 739
          "\n"
          "\n      --novideo                  \tdisable video"
Sam Hocevar's avatar
 
Sam Hocevar committed
740
          "\n  -V, --vout <module>            \tvideo output method"
Sam Hocevar's avatar
 
Sam Hocevar committed
741 742 743 744 745 746 747 748 749 750 751
          "\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"
752 753
          "\n  -t, --dvdtitle <num>           \tchoose DVD title"
          "\n  -T, --dvdchapter <num>         \tchoose DVD chapter"
754
          "\n  -u, --dvdangle <num>           \tchoose DVD angle"
Sam Hocevar's avatar
 
Sam Hocevar committed
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"
760
          "\n      --channels                 \tenable channels"