main.c 36.5 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
7
 * $Id: main.c,v 1.84 2001/04/11 14:10:49 ej 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 46 47
#include <mach/mach.h>                                  /* Altivec detection */
#include <mach/mach_error.h>          /* some day the header files||compiler *
                                                       will define it for us */
#include <mach/bootstrap.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
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 76 77 78
#ifdef SYS_BEOS
#include "beos_specific.h"
#endif

Henri Fallon's avatar
 
Henri Fallon committed
79 80
#include "netutils.h"                                 /* network_ChannelJoin */

Vincent Seguin's avatar
Vincent Seguin committed
81
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
82

83
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
84 85
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
86
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
87 88 89 90

/* 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
91 92
#define OPT_STEREO              151
#define OPT_MONO                152
Michel Kaempf's avatar
Michel Kaempf committed
93 94

#define OPT_NOVIDEO             160
Sam Hocevar's avatar
 
Sam Hocevar committed
95 96 97 98 99 100
#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
101

Henri Fallon's avatar
 
Henri Fallon committed
102
#define OPT_CHANNELS            170
103 104
#define OPT_SERVER              171
#define OPT_PORT                172
105
#define OPT_BROADCAST           173
106

Sam Hocevar's avatar
 
Sam Hocevar committed
107 108 109 110
#define OPT_INPUT               180
#define OPT_MOTION              181
#define OPT_IDCT                182
#define OPT_YUV                 183
111

Sam Hocevar's avatar
 
Sam Hocevar committed
112 113
#define OPT_SYNCHRO             190
#define OPT_WARNING             191
Sam Hocevar's avatar
 
Sam Hocevar committed
114
#define OPT_VERSION             192
115

116
/* Usage fashion */
117 118 119
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
120

Michel Kaempf's avatar
Michel Kaempf committed
121 122
/* Long options */
static const struct option longopts[] =
123 124
{
    /*  name,               has_arg,    flag,   val */
Michel Kaempf's avatar
Michel Kaempf committed
125 126

    /* General/common options */
127
    {   "help",             0,          0,      'h' },
128
    {   "longhelp",         0,          0,      'H' },
Sam Hocevar's avatar
 
Sam Hocevar committed
129
    {   "version",          0,          0,      OPT_VERSION },
Michel Kaempf's avatar
Michel Kaempf committed
130

Sam Hocevar's avatar
 
Sam Hocevar committed
131
    /* Interface options */
Sam Hocevar's avatar
 
Sam Hocevar committed
132
    {   "intf",             1,          0,      'I' },
Sam Hocevar's avatar
 
Sam Hocevar committed
133 134
    {   "warning",          1,          0,      OPT_WARNING },

Michel Kaempf's avatar
Michel Kaempf committed
135
    /* Audio options */
136
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
Sam Hocevar's avatar
 
Sam Hocevar committed
137
    {   "aout",             1,          0,      'A' },
Michel Kaempf's avatar
Michel Kaempf committed
138
    {   "stereo",           0,          0,      OPT_STEREO },
139
    {   "mono",             0,          0,      OPT_MONO },
Michel Kaempf's avatar
Michel Kaempf committed
140 141

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

155
    /* DVD options */
156 157
    {   "dvdtitle",         1,          0,      't' },
    {   "dvdchapter",       1,          0,      'T' },
158 159 160 161
    {   "dvdaudio",         1,          0,      'a' },
    {   "dvdchannel",       1,          0,      'c' },
    {   "dvdsubtitle",      1,          0,      's' },
    
162
    /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
163
    {   "input",            1,          0,      OPT_INPUT },
Henri Fallon's avatar
 
Henri Fallon committed
164
    {   "channels",         0,          0,      OPT_CHANNELS },
165 166
    {   "server",           1,          0,      OPT_SERVER },
    {   "port",             1,          0,      OPT_PORT },
167
    {   "broadcast",        0,          0,      OPT_BROADCAST },
Michel Kaempf's avatar
Michel Kaempf committed
168

169 170
    /* Synchro options */
    {   "synchro",          1,          0,      OPT_SYNCHRO },
Michel Kaempf's avatar
Michel Kaempf committed
171 172 173 174
    {   0,                  0,          0,      0 }
};

/* Short options */
Sam Hocevar's avatar
 
Sam Hocevar committed
175
static const char *psz_shortopts = "hHvgt:T:a:s:c:I:A:V:";
Michel Kaempf's avatar
Michel Kaempf committed
176

177
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
178
 * Global variable program_data - this is the one and only, see main.h
179
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
180
main_t *p_main;
Michel Kaempf's avatar
Michel Kaempf committed
181

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

Michel Kaempf's avatar
Michel Kaempf committed
191
static void InitSignalHandler       ( void );
Benoit Steiner's avatar
 
Benoit Steiner committed
192 193
static void SimpleSignalHandler     ( int i_signal );
static void FatalSignalHandler      ( int i_signal );
Michel Kaempf's avatar
Michel Kaempf committed
194

Sam Hocevar's avatar
 
Sam Hocevar committed
195 196
static int  CPUCapabilities         ( void );

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

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

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

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
254 255
    intf_MsgImm( COPYRIGHT_MESSAGE );

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

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

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

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

Michel Kaempf's avatar
Michel Kaempf committed
295 296 297
    /*
     * Initialize shared resources and libraries
     */
Henri Fallon's avatar
 
Henri Fallon committed
298
    if( p_main->b_channels && network_ChannelCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
299
    {
Henri Fallon's avatar
 
Henri Fallon committed
300 301 302 303
        /* 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
304
    }
305

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
    /* 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
380
    /*
Henri Fallon's avatar
 
Henri Fallon committed
381
     * Go back into channel 0 which is the network
Michel Kaempf's avatar
Michel Kaempf committed
382
     */
Henri Fallon's avatar
 
Henri Fallon committed
383
    if( p_main->b_channels )
384
    {
Henri Fallon's avatar
 
Henri Fallon committed
385
        network_ChannelJoin( COMMON_CHANNEL );
386
    }
Michel Kaempf's avatar
Michel Kaempf committed
387

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /* Set default configuration and copy arguments */
513
    p_main->i_argc    = *i_argc;
Vincent Seguin's avatar
Vincent Seguin committed
514
    p_main->ppsz_argv = ppsz_argv;
515
    p_main->ppsz_env  = ppsz_env;
Sam Hocevar's avatar
 
Sam Hocevar committed
516

Henri Fallon's avatar
 
Henri Fallon committed
517 518 519
    p_main->b_audio     = 1;
    p_main->b_video     = 1;
    p_main->b_channels  = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
520 521

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

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

537 538 539 540 541 542 543 544 545 546 547 548 549
//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
#ifdef SYS_DARWIN1_3
    if ( strncmp( ppsz_argv[ 1 ] , "-psn" , 4) == 0 ) //for example -psn_0_9306113
    {
        //ppsz_argv[ 1 ] = NULL; //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
        *i_argc = *i_argc - 1;
        p_main->i_argc--;
        return( 0 );
    }
#endif

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

Sam Hocevar's avatar
 
Sam Hocevar committed
574
        /* Interface warning messages level */
Sam Hocevar's avatar
 
Sam Hocevar committed
575
        case 'I':                                              /* -I, --intf */
Sam Hocevar's avatar
 
Sam Hocevar committed
576 577 578
            main_PutPszVariable( INTF_METHOD_VAR, optarg );
            break;
        case OPT_WARNING:                                       /* --warning */
Sam Hocevar's avatar
 
Sam Hocevar committed
579 580
            intf_ErrMsg( "intf error: `--warning' is deprecated, use `-v'" );
            p_main->i_warning_level = atoi(optarg);
Sam Hocevar's avatar
 
Sam Hocevar committed
581 582
            break;

Michel Kaempf's avatar
Michel Kaempf committed
583
        /* Audio options */
584
        case OPT_NOAUDIO:                                       /* --noaudio */
585
            p_main->b_audio = 0;
Michel Kaempf's avatar
Michel Kaempf committed
586
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
587
        case 'A':                                              /* -A, --aout */
588 589
            main_PutPszVariable( AOUT_METHOD_VAR, optarg );
            break;
590
        case OPT_STEREO:                                         /* --stereo */
591
            main_PutIntVariable( AOUT_STEREO_VAR, 1 );
Michel Kaempf's avatar
Michel Kaempf committed
592
            break;
593
        case OPT_MONO:                                             /* --mono */
594
            main_PutIntVariable( AOUT_STEREO_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
595 596 597
            break;

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

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

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

676
        /* Synchro options */
677
        case OPT_SYNCHRO:                                      
678 679
            main_PutPszVariable( VPAR_SYNCHRO_VAR, optarg );
            break;
680
            
Michel Kaempf's avatar
Michel Kaempf committed
681
        /* Internal error: unknown option */
682
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
683
        default:
Sam Hocevar's avatar
 
Sam Hocevar committed
684 685
            intf_ErrMsg( "intf error: unknown option `%s'",
                         ppsz_argv[optind - 1] );
686
            Usage( USAGE );
Michel Kaempf's avatar
Michel Kaempf committed
687 688 689 690
            return( EINVAL );
            break;
        }
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
691 692 693 694 695 696

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

Sam Hocevar's avatar
 
Sam Hocevar committed
697 698 699 700 701 702 703 704 705 706 707
    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
708

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

Michel Kaempf's avatar
Michel Kaempf committed
716 717 718
    return( 0 );
}

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

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

Vincent Seguin's avatar
Vincent Seguin committed
737
    /* Options */
Sam Hocevar's avatar
 
Sam Hocevar committed
738
    intf_MsgImm( "\nOptions:"
Sam Hocevar's avatar
 
Sam Hocevar committed
739
          "\n  -I, --intf <module>            \tinterface method"
Sam Hocevar's avatar
 
Sam Hocevar committed
740
          "\n  -v, --verbose                  \tverbose mode (cumulative)"
Sam Hocevar's avatar
 
Sam Hocevar committed
741
          "\n"
Sam Hocevar's avatar
 
Sam Hocevar committed
742
          "\n      --noaudio                  \tdisable audio"
Sam Hocevar's avatar
 
Sam Hocevar committed
743
          "\n  -A, --aout <module>            \taudio output method"
Sam Hocevar's avatar
 
Sam Hocevar committed
744 745 746
          "\n      --stereo, --mono           \tstereo/mono audio"
          "\n"
          "\n      --novideo                  \tdisable video"
Sam Hocevar's avatar
 
Sam Hocevar committed
747
          "\n  -V, --vout <module>            \tvideo output method"
Sam Hocevar's avatar
 
Sam Hocevar committed
748 749 750 751 752 753 754 755 756 757 758
          "\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"
759 760
          "\n  -t, --dvdtitle <num>           \tchoose DVD title"
          "\n  -T, --dvdchapter <num>         \tchoose DVD chapter"
Sam Hocevar's avatar
 
Sam Hocevar committed
761 762 763 764 765
          "\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"
Henri Fallon's avatar
 
Henri Fallon committed
766
          "\n      --channels                    \tenable channels"
Sam Hocevar's avatar
 
Sam Hocevar committed
767 768 769 770 771 772
          "\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"
Sam Hocevar's avatar
 
Sam Hocevar committed
773
          "\n      --version                  \toutput version information and exit" );
Michel Kaempf's avatar
Michel Kaempf committed
774