main.c 39.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.105 2001/06/25 11:34:08 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
#include <signal.h>                               /* SIGHUP, SIGINT, SIGKILL */
#include <stdio.h>                                              /* sprintf() */
34
#include <setjmp.h>                                       /* longjmp, setjmp */
35

Sam Hocevar's avatar
 
Sam Hocevar committed
36 37 38 39 40 41
#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
42 43
#endif

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

#ifndef WIN32
#include <netinet/in.h>                               /* BSD: struct in_addr */
#endif
Sam Hocevar's avatar
 
Sam Hocevar committed
54

Sam Hocevar's avatar
 
Sam Hocevar committed
55
#ifdef HAVE_UNISTD_H
Sam Hocevar's avatar
 
Sam Hocevar committed
56
#include <unistd.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
57 58
#endif

59 60 61
#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                  /* getenv(), strtol(),  */
#include <string.h>                                            /* strerror() */
Vincent Seguin's avatar
Vincent Seguin committed
62

Michel Kaempf's avatar
Michel Kaempf committed
63 64
#include "config.h"
#include "common.h"
Christophe Massiot's avatar
Christophe Massiot committed
65
#include "debug.h"
66
#include "threads.h"
Michel Kaempf's avatar
Michel Kaempf committed
67
#include "mtime.h"
68
#include "tests.h"                                              /* TestCPU() */
Sam Hocevar's avatar
 
Sam Hocevar committed
69
#include "modules.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
70

71 72
#include "stream_control.h"
#include "input_ext-intf.h"
73

Vincent Seguin's avatar
Vincent Seguin committed
74
#include "intf_msg.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
75
#include "intf_playlist.h"
Michel Kaempf's avatar
Michel Kaempf committed
76
#include "interface.h"
77

Vincent Seguin's avatar
Vincent Seguin committed
78
#include "audio_output.h"
79

Sam Hocevar's avatar
 
Sam Hocevar committed
80 81 82
#include "video.h"
#include "video_output.h"

83
#ifdef SYS_BEOS
Sam Hocevar's avatar
 
Sam Hocevar committed
84 85 86
#   include "beos_specific.h"
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
87
#ifdef SYS_DARWIN
Sam Hocevar's avatar
 
Sam Hocevar committed
88
#   include "darwin_specific.h"
89 90
#endif

Henri Fallon's avatar
 
Henri Fallon committed
91 92
#include "netutils.h"                                 /* network_ChannelJoin */

Vincent Seguin's avatar
Vincent Seguin committed
93
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
94

95
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
96 97
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
98
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
99 100 101 102

/* 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
103 104
#define OPT_STEREO              151
#define OPT_MONO                152
105
#define OPT_SPDIF               153
Michel Kaempf's avatar
Michel Kaempf committed
106 107

#define OPT_NOVIDEO             160
Sam Hocevar's avatar
 
Sam Hocevar committed
108 109 110 111 112 113
#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
114

Henri Fallon's avatar
 
Henri Fallon committed
115
#define OPT_CHANNELS            170
116 117
#define OPT_SERVER              171
#define OPT_PORT                172
118
#define OPT_BROADCAST           173
119

Sam Hocevar's avatar
 
Sam Hocevar committed
120 121 122 123
#define OPT_INPUT               180
#define OPT_MOTION              181
#define OPT_IDCT                182
#define OPT_YUV                 183
Sam Hocevar's avatar
 
Sam Hocevar committed
124 125
#define OPT_DOWNMIX             184
#define OPT_IMDCT               185
126

Sam Hocevar's avatar
 
Sam Hocevar committed
127 128
#define OPT_SYNCHRO             190
#define OPT_WARNING             191
Sam Hocevar's avatar
 
Sam Hocevar committed
129
#define OPT_VERSION             192
130

131
/* Usage fashion */
132 133 134
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
135

Sam Hocevar's avatar
 
Sam Hocevar committed
136 137 138 139 140 141 142 143 144 145
/* Needed for x86 CPU capabilities detection */
#define cpuid( a )                 \
    asm volatile ( "cpuid"         \
                 : "=a" ( i_eax ), \
                   "=b" ( i_ebx ), \
                   "=c" ( i_ecx ), \
                   "=d" ( i_edx )  \
                 : "a"  ( a )      \
                 : "cc" );

Michel Kaempf's avatar
Michel Kaempf committed
146 147
/* Long options */
static const struct option longopts[] =
148 149
{
    /*  name,               has_arg,    flag,   val */
Michel Kaempf's avatar
Michel Kaempf committed
150 151

    /* General/common options */
152
    {   "help",             0,          0,      'h' },
153
    {   "longhelp",         0,          0,      'H' },
Sam Hocevar's avatar
 
Sam Hocevar committed
154
    {   "version",          0,          0,      OPT_VERSION },
Michel Kaempf's avatar
Michel Kaempf committed
155

Sam Hocevar's avatar
 
Sam Hocevar committed
156
    /* Interface options */
Sam Hocevar's avatar
 
Sam Hocevar committed
157
    {   "intf",             1,          0,      'I' },
Sam Hocevar's avatar
 
Sam Hocevar committed
158 159
    {   "warning",          1,          0,      OPT_WARNING },

Michel Kaempf's avatar
Michel Kaempf committed
160
    /* Audio options */
161
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
Sam Hocevar's avatar
 
Sam Hocevar committed
162
    {   "aout",             1,          0,      'A' },
Michel Kaempf's avatar
Michel Kaempf committed
163
    {   "stereo",           0,          0,      OPT_STEREO },
164
    {   "mono",             0,          0,      OPT_MONO },
165
    {   "spdif",            0,          0,      OPT_SPDIF },
Sam Hocevar's avatar
 
Sam Hocevar committed
166 167
    {   "downmix",          1,          0,      OPT_DOWNMIX },
    {   "imdct",            1,          0,      OPT_IMDCT },
Michel Kaempf's avatar
Michel Kaempf committed
168 169

    /* Video options */
170
    {   "novideo",          0,          0,      OPT_NOVIDEO },
Sam Hocevar's avatar
 
Sam Hocevar committed
171
    {   "vout",             1,          0,      'V' },
172
    {   "display",          1,          0,      OPT_DISPLAY },
173
    {   "width",            1,          0,      OPT_WIDTH },
174 175 176
    {   "height",           1,          0,      OPT_HEIGHT },
    {   "grayscale",        0,          0,      'g' },
    {   "color",            0,          0,      OPT_COLOR },
Sam Hocevar's avatar
 
Sam Hocevar committed
177
    {   "motion",           1,          0,      OPT_MOTION },
Sam Hocevar's avatar
 
Sam Hocevar committed
178
    {   "idct",             1,          0,      OPT_IDCT },
Sam Hocevar's avatar
Sam Hocevar committed
179
    {   "yuv",              1,          0,      OPT_YUV },
Sam Hocevar's avatar
 
Sam Hocevar committed
180 181
    {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
    {   "overlay",          0,          0,      OPT_OVERLAY },
Michel Kaempf's avatar
Michel Kaempf committed
182

183
    /* DVD options */
184 185
    {   "dvdtitle",         1,          0,      't' },
    {   "dvdchapter",       1,          0,      'T' },
186
    {   "dvdangle",         1,          0,      'u' },
187 188 189 190
    {   "dvdaudio",         1,          0,      'a' },
    {   "dvdchannel",       1,          0,      'c' },
    {   "dvdsubtitle",      1,          0,      's' },
    
191
    /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
192
    {   "input",            1,          0,      OPT_INPUT },
193 194
    {   "server",           1,          0,      OPT_SERVER },
    {   "port",             1,          0,      OPT_PORT },
Henri Fallon's avatar
 
Henri Fallon committed
195
    {   "broadcast",        1,          0,      OPT_BROADCAST },
196
    {   "channels",         0,          0,      OPT_CHANNELS },
Michel Kaempf's avatar
Michel Kaempf committed
197

198 199
    /* Synchro options */
    {   "synchro",          1,          0,      OPT_SYNCHRO },
Michel Kaempf's avatar
Michel Kaempf committed
200 201 202 203
    {   0,                  0,          0,      0 }
};

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

206
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
207 208
 * Global variable program_data - these are the only ones, see main.h and
 * modules.h
209
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
210 211 212 213
main_t        *p_main;
module_bank_t *p_module_bank;
aout_bank_t   *p_aout_bank;
vout_bank_t   *p_vout_bank;
Michel Kaempf's avatar
Michel Kaempf committed
214

215
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
216
 * Local prototypes
217
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
218
static int  GetConfiguration        ( int *pi_argc, char *ppsz_argv[],
219
                                      char *ppsz_env[] );
Sam Hocevar's avatar
 
Sam Hocevar committed
220
static int  GetFilenames            ( int i_argc, char *ppsz_argv[] );
221
static void Usage                   ( int i_fashion );
Vincent Seguin's avatar
Vincent Seguin committed
222
static void Version                 ( void );
Vincent Seguin's avatar
Vincent Seguin committed
223

Michel Kaempf's avatar
Michel Kaempf committed
224
static void InitSignalHandler       ( void );
Benoit Steiner's avatar
 
Benoit Steiner committed
225 226
static void SimpleSignalHandler     ( int i_signal );
static void FatalSignalHandler      ( int i_signal );
227
static void InstructionSignalHandler( int i_signal );
Sam Hocevar's avatar
 
Sam Hocevar committed
228
static int  CPUCapabilities         ( void );
229 230
static jmp_buf env;
static int  i_illegal;
Sam Hocevar's avatar
 
Sam Hocevar committed
231

232
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
233
 * main: parse command line, start interface and spawn threads
234
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
235 236
 * Steps during program execution are:
 *      -configuration parsing and messages interface initialization
237
 *      -opening of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
238
 *      -execution of interface, which exit on error or on user request
Vincent Seguin's avatar
Vincent Seguin committed
239
 *      -closing of audio output device and some global modules
240
 * On error, the spawned threads are canceled, and the open devices closed.
241
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
242 243
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
Sam Hocevar's avatar
 
Sam Hocevar committed
244 245 246 247
    main_t        main_data;                /* root of all data - see main.h */
    module_bank_t module_bank;
    aout_bank_t   aout_bank;
    vout_bank_t   vout_bank;
248

Sam Hocevar's avatar
 
Sam Hocevar committed
249 250 251 252
    p_main        = &main_data;               /* set up the global variables */
    p_module_bank = &module_bank;
    p_aout_bank   = &aout_bank;
    p_vout_bank   = &vout_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
253

Sam Hocevar's avatar
 
Sam Hocevar committed
254
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
255
     * Initialize threads system
Sam Hocevar's avatar
 
Sam Hocevar committed
256
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
257
    vlc_threads_init( );
Sam Hocevar's avatar
 
Sam Hocevar committed
258

Sam Hocevar's avatar
 
Sam Hocevar committed
259
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
260
     * Test if our code is likely to run on this CPU 
Sam Hocevar's avatar
 
Sam Hocevar committed
261 262 263
     */
    p_main->i_cpu_capabilities = CPUCapabilities();
    
264 265 266
#if defined( __pentium__ ) || defined( __pentiumpro__ )
    if( ! TestCPU( CPU_CAPABILITY_586 ) )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
267 268
        fprintf( stderr, "error: this program needs a Pentium CPU,\n"
                         "please try a version without Pentium support\n" );
269 270 271 272
        return( 1 );
    }
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
273 274 275
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
276
#if defined( SYS_BEOS ) || defined( SYS_DARWIN )
Sam Hocevar's avatar
 
Sam Hocevar committed
277
    system_Init( &i_argc, ppsz_argv, ppsz_env );
278
#endif
279 280 281 282

    /*
     * Initialize messages interface
     */
Vincent Seguin's avatar
Vincent Seguin committed
283
    p_main->p_msg = intf_MsgCreate();
284
    if( !p_main->p_msg )                         /* start messages interface */
Michel Kaempf's avatar
Michel Kaempf committed
285
    {
286
        fprintf( stderr, "error: can't initialize messages interface (%s)\n",
Sam Hocevar's avatar
 
Sam Hocevar committed
287
                 strerror(errno) );
288
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
289
    }
290

Sam Hocevar's avatar
 
Sam Hocevar committed
291 292
    intf_MsgImm( COPYRIGHT_MESSAGE );

293
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
294
     * Read configuration
295
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
296
    if( GetConfiguration( &i_argc, ppsz_argv, ppsz_env ) ) /* parse cmd line */
Michel Kaempf's avatar
Michel Kaempf committed
297
    {
Vincent Seguin's avatar
Vincent Seguin committed
298
        intf_MsgDestroy();
299
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
300
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
301

302
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
303
     * Initialize playlist and get commandline files
304
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
305
    p_main->p_playlist = intf_PlaylistCreate();
Sam Hocevar's avatar
 
Sam Hocevar committed
306
    if( !p_main->p_playlist )
307
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
308
        intf_ErrMsg( "playlist error: playlist initialization failed" );
309 310
        intf_MsgDestroy();
        return( errno );
311
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
312
    intf_PlaylistInit( p_main->p_playlist );
313 314

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
315
     * Get input filenames given as commandline arguments
316
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
317
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
318

Sam Hocevar's avatar
 
Sam Hocevar committed
319
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
320
     * Initialize module, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
321
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
322
    module_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
323 324
    aout_InitBank();
    vout_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
325

Michel Kaempf's avatar
Michel Kaempf committed
326 327 328
    /*
     * Initialize shared resources and libraries
     */
329 330 331
    if( main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
                             INPUT_NETWORK_CHANNEL_DEFAULT ) &&
        network_ChannelCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
332
    {
Henri Fallon's avatar
 
Henri Fallon committed
333 334 335
        /* On error during Channels initialization, switch off channels */
        intf_Msg( "Channels initialization failed : "
                  "Channel management is deactivated" );
336
        main_PutIntVariable( INPUT_NETWORK_CHANNEL_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
337
    }
338

Michel Kaempf's avatar
Michel Kaempf committed
339
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
340
     * Try to run the interface
Michel Kaempf's avatar
Michel Kaempf committed
341
     */
342
    p_main->p_intf = intf_Create();
Sam Hocevar's avatar
 
Sam Hocevar committed
343
    if( p_main->p_intf == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
344 345 346
    {
        intf_ErrMsg( "intf error: interface initialization failed" );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
347
    else
348
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
        /*
         * Set signal handling policy for all threads
         */
        InitSignalHandler();

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

        /*
         * Finished, destroy the interface
         */
        intf_Destroy( p_main->p_intf );

        /*
         * Go back into channel 0 which is the network
         */
367 368
        if( main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
                                 INPUT_NETWORK_CHANNEL_DEFAULT ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
369 370 371
        {
            network_ChannelJoin( COMMON_CHANNEL );
        }
372
    }
Michel Kaempf's avatar
Michel Kaempf committed
373

Sam Hocevar's avatar
 
Sam Hocevar committed
374
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
375
     * Free module, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
376
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
377 378
    vout_EndBank();
    aout_EndBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
379
    module_EndBank();
380 381 382 383

    /*
     * Free playlist
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
384
    intf_PlaylistDestroy( p_main->p_playlist );
385 386 387 388

    /*
     * System specific cleaning code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
389
#if defined( SYS_BEOS ) || defined( SYS_DARWIN )
Sam Hocevar's avatar
 
Sam Hocevar committed
390
    system_End();
391 392
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
393

Michel Kaempf's avatar
Michel Kaempf committed
394 395 396
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
397
    intf_Msg( "intf: program terminated" );
Vincent Seguin's avatar
Vincent Seguin committed
398
    intf_MsgDestroy();
399

Sam Hocevar's avatar
 
Sam Hocevar committed
400 401 402 403
    /*
     * Stop threads system
     */
    vlc_threads_end( );
Sam Hocevar's avatar
 
Sam Hocevar committed
404

Sam Hocevar's avatar
 
Sam Hocevar committed
405
    return 0;
Michel Kaempf's avatar
Michel Kaempf committed
406 407
}

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

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

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

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

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

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

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

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

492
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
493
 * GetConfiguration: parse command line
494
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
495 496
 * Parse command line and configuration file for configuration. If the inline
 * help is requested, the function Usage() is called and the function returns
497
 * -1 (causing main() to exit). The messages interface is initialized at this
Vincent Seguin's avatar
Vincent Seguin committed
498 499
 * stage, but most structures are not allocated, so only environment should
 * be used.
500
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
501
static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
Michel Kaempf's avatar
Michel Kaempf committed
502
{
Sam Hocevar's avatar
 
Sam Hocevar committed
503 504
    int   i_cmd;
    char *p_tmp;
Michel Kaempf's avatar
Michel Kaempf committed
505 506

    /* Set default configuration and copy arguments */
Sam Hocevar's avatar
 
Sam Hocevar committed
507
    p_main->i_argc    = *pi_argc;
Vincent Seguin's avatar
Vincent Seguin committed
508
    p_main->ppsz_argv = ppsz_argv;
509
    p_main->ppsz_env  = ppsz_env;
Sam Hocevar's avatar
 
Sam Hocevar committed
510

Henri Fallon's avatar
 
Henri Fallon committed
511 512
    p_main->b_audio     = 1;
    p_main->b_video     = 1;
Sam Hocevar's avatar
 
Sam Hocevar committed
513

514
    p_main->i_warning_level = 0;
Michel Kaempf's avatar
Michel Kaempf committed
515

516 517
    p_main->p_channel = NULL;

518
    /* Get the executable name (similar to the basename command) */
Sam Hocevar's avatar
 
Sam Hocevar committed
519 520
    p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
    while( *p_tmp )
Sam Hocevar's avatar
Sam Hocevar committed
521
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
522
        if( *p_tmp == '/' )
Sam Hocevar's avatar
Sam Hocevar committed
523
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
524
            p_main->psz_arg0 = ++p_tmp;
Sam Hocevar's avatar
Sam Hocevar committed
525 526 527
        }
        else
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
528
            ++p_tmp;
Sam Hocevar's avatar
Sam Hocevar committed
529 530 531
        }
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
532
#ifdef SYS_DARWIN
Sam Hocevar's avatar
 
Sam Hocevar committed
533 534 535
    /* 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
536 537
    if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
                                        /* for example -psn_0_9306113 */
538
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
539 540 541 542 543 544 545 546 547
        /* 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--;
548 549 550 551
        return( 0 );
    }
#endif

Vincent Seguin's avatar
Vincent Seguin committed
552
    /* Parse command line options */
Michel Kaempf's avatar
Michel Kaempf committed
553
    opterr = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
554 555
    while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv,
                                   psz_shortopts, longopts, 0 ) ) != EOF )
Michel Kaempf's avatar
Michel Kaempf committed
556
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
557
        switch( i_cmd )
Michel Kaempf's avatar
Michel Kaempf committed
558
        {
559 560
        /* General/common options */
        case 'h':                                              /* -h, --help */
561 562 563
            Usage( SHORT_HELP );
            return( -1 );
            break;
564
        case 'H':                                          /* -H, --longhelp */
565
            Usage( LONG_HELP );
Michel Kaempf's avatar
Michel Kaempf committed
566 567
            return( -1 );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
568
        case OPT_VERSION:                                       /* --version */
Vincent Seguin's avatar
Vincent Seguin committed
569 570
            Version();
            return( -1 );
571
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
572
        case 'v':                                           /* -v, --verbose */
573
            p_main->i_warning_level++;
Sam Hocevar's avatar
 
Sam Hocevar committed
574
            break;
Michel Kaempf's avatar
Michel Kaempf committed
575

Sam Hocevar's avatar
 
Sam Hocevar committed
576
        /* Interface warning messages level */
Sam Hocevar's avatar
 
Sam Hocevar committed
577
        case 'I':                                              /* -I, --intf */
Sam Hocevar's avatar
 
Sam Hocevar committed
578 579 580
            main_PutPszVariable( INTF_METHOD_VAR, optarg );
            break;
        case OPT_WARNING:                                       /* --warning */
Sam Hocevar's avatar
 
Sam Hocevar committed
581 582
            intf_ErrMsg( "intf error: `--warning' is deprecated, use `-v'" );
            p_main->i_warning_level = atoi(optarg);
Sam Hocevar's avatar
 
Sam Hocevar committed
583 584
            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
            break;
598
        case OPT_SPDIF:                                           /* --spdif */
Sam Hocevar's avatar
 
Sam Hocevar committed
599
            main_PutIntVariable( AOUT_SPDIF_VAR, 1 );
600
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
601 602 603 604 605 606
	case OPT_DOWNMIX:                                       /* --downmix */
            main_PutPszVariable( DOWNMIX_METHOD_VAR, optarg );
            break;
        case OPT_IMDCT:                                           /* --imdct */
            main_PutPszVariable( IMDCT_METHOD_VAR, optarg );
            break;
Michel Kaempf's avatar
Michel Kaempf committed
607 608

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

646
        /* DVD options */
647 648 649 650 651 652
        case 't':
            main_PutIntVariable( INPUT_TITLE_VAR, atoi(optarg) );
            break;
        case 'T':
            main_PutIntVariable( INPUT_CHAPTER_VAR, atoi(optarg) );
            break;
653 654 655
        case 'u':
            main_PutIntVariable( INPUT_ANGLE_VAR, atoi(optarg) );
            break;
656
        case 'a':
657
            if ( ! strcmp(optarg, "ac3") )
Sam Hocevar's avatar
 
Sam Hocevar committed
658
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_AC3 );
659
            else if ( ! strcmp(optarg, "lpcm") )
Sam Hocevar's avatar
 
Sam Hocevar committed
660
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_LPCM );
661
            else if ( ! strcmp(optarg, "mpeg") )
Sam Hocevar's avatar
 
Sam Hocevar committed
662
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_MPEG );
663
            else
Sam Hocevar's avatar
 
Sam Hocevar committed
664
                main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_NOAUDIO );
665 666
            break;
        case 'c':
Sam Hocevar's avatar
 
Sam Hocevar committed
667
            main_PutIntVariable( INPUT_CHANNEL_VAR, atoi(optarg) );
668 669
            break;
        case 's':
Sam Hocevar's avatar
 
Sam Hocevar committed
670
            main_PutIntVariable( INPUT_SUBTITLE_VAR, atoi(optarg) );
671 672
            break;

673
        /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
674
        case OPT_INPUT:                                           /* --input */
Sam Hocevar's avatar
 
Sam Hocevar committed
675 676
            main_PutPszVariable( INPUT_METHOD_VAR, optarg );
            break;
Henri Fallon's avatar
 
Henri Fallon committed
677
        case OPT_CHANNELS:                                     /* --channels */
678
            main_PutIntVariable( INPUT_NETWORK_CHANNEL_VAR, 1 );
679 680
            break;
        case OPT_SERVER:                                         /* --server */
681
            main_PutPszVariable( INPUT_SERVER_VAR, optarg );
682 683
            break;
        case OPT_PORT:                                             /* --port */
684
            main_PutPszVariable( INPUT_PORT_VAR, optarg );
685
            break;
686
        case OPT_BROADCAST:                                   /* --broadcast */
687 688
            main_PutIntVariable( INPUT_BROADCAST_VAR, 1 );
            main_PutPszVariable( INPUT_BCAST_ADDR_VAR, optarg );
689
            break;
690

691
        /* Synchro options */
692
        case OPT_SYNCHRO:                                      
693 694
            main_PutPszVariable( VPAR_SYNCHRO_VAR, optarg );
            break;
695
            
Michel Kaempf's avatar
Michel Kaempf committed
696
        /* Internal error: unknown option */
697
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
698
        default:
Sam Hocevar's avatar
 
Sam Hocevar committed
699 700
            intf_ErrMsg( "intf error: unknown option `%s'",
                         ppsz_argv[optind - 1] );
701
            Usage( USAGE );
Michel Kaempf's avatar
Michel Kaempf committed
702 703 704 705
            return( EINVAL );
            break;
        }
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
706 707 708 709 710 711

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

Sam Hocevar's avatar
 
Sam Hocevar committed
712 713 714 715 716 717 718 719 720 721 722
    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
723

Sam Hocevar's avatar
 
Sam Hocevar committed
724
    /* We assume that the remaining parameters are filenames */
Vincent Seguin's avatar
Vincent Seguin committed
725 726
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
727 728
        intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
                          ppsz_argv[ i_opt ] );
Vincent Seguin's avatar
Vincent Seguin committed
729
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
730

Michel Kaempf's avatar
Michel Kaempf committed
731 732 733
    return( 0 );
}

734
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
735
 * Usage: print program usage
736
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
737
 * Print a short inline help. Message interface is initialized at this stage.
738
 *****************************************************************************/
739
static void Usage( int i_fashion )
Michel Kaempf's avatar
Michel Kaempf committed
740
{
Vincent Seguin's avatar
Vincent Seguin committed
741
    /* Usage */
Sam Hocevar's avatar
 
Sam Hocevar committed
742 743
    intf_MsgImm( "Usage: %s [options] [parameters] [file]...",
                 p_main->psz_arg0 );
744 745 746

    if( i_fashion == USAGE )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
747 748
        intf_MsgImm( "Try `%s --help' for more information.",
                     p_main->psz_arg0 );
749 750 751
        return;
    }

Vincent Seguin's avatar
Vincent Seguin committed
752
    /* Options */
Sam Hocevar's avatar
 
Sam Hocevar committed
753
    intf_MsgImm( "\nOptions:"
Sam Hocevar's avatar
 
Sam Hocevar committed
754
          "\n  -I, --intf <module>            \tinterface method"
Sam Hocevar's avatar
 
Sam Hocevar committed
755
          "\n  -v, --verbose                  \tverbose mode (cumulative)"
Sam Hocevar's avatar