main.c 37.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.90 2001/04/29 02:48:51 stef 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
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
185
 * Global variable program_data - this is the one and only, see main.h
186
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
187
main_t *p_main;
Michel Kaempf's avatar
Michel Kaempf committed
188

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
202 203
static int  CPUCapabilities         ( void );

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

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

220 221 222
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
223 224
#if defined( SYS_BEOS ) || defined( SYS_DARWIN1_3 )
    system_Create( &i_argc, ppsz_argv, ppsz_env );
225 226
#endif

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

Sam Hocevar's avatar
Sam Hocevar committed
241
#ifdef HAVE_MMX
242
    if( ! TestCPU( CPU_CAPABILITY_MMX ) )
243
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
244 245
        fprintf( stderr, "error: this program needs MMX extensions,\n"
                         "please try a version without MMX support\n" );
246
        return( 1 );
247 248
    }
#endif
249 250 251 252

    /*
     * Initialize messages interface
     */
Vincent Seguin's avatar
Vincent Seguin committed
253
    p_main->p_msg = intf_MsgCreate();
254
    if( !p_main->p_msg )                         /* start messages interface */
Michel Kaempf's avatar
Michel Kaempf committed
255
    {
256
        fprintf( stderr, "error: can't initialize messages interface (%s)\n",
Sam Hocevar's avatar
 
Sam Hocevar committed
257
                 strerror(errno) );
258
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
259
    }
260

Sam Hocevar's avatar
 
Sam Hocevar committed
261 262
    intf_MsgImm( COPYRIGHT_MESSAGE );

263
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
264
     * Read configuration
265
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
266
    if( GetConfiguration( &i_argc, ppsz_argv, ppsz_env ) ) /* parse cmd line */
Michel Kaempf's avatar
Michel Kaempf committed
267
    {
Vincent Seguin's avatar
Vincent Seguin committed
268
        intf_MsgDestroy();
269
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
270
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
271

272
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
273
     * Initialize playlist and get commandline files
274
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
275
    p_main->p_playlist = intf_PlaylistCreate( );
Sam Hocevar's avatar
 
Sam Hocevar committed
276
    if( !p_main->p_playlist )
277
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
278
        intf_ErrMsg( "playlist error: playlist initialization failed" );
279 280
        intf_MsgDestroy();
        return( errno );
281
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
282
    intf_PlaylistInit( p_main->p_playlist );
283 284

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
285
     * Get input filenames given as commandline arguments
286
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
287
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
288

Sam Hocevar's avatar
 
Sam Hocevar committed
289 290 291
    /*
     * Initialize module bank
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
292 293
    p_main->p_bank = module_CreateBank( );
    if( !p_main->p_bank )
Sam Hocevar's avatar
 
Sam Hocevar committed
294
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
295
        intf_ErrMsg( "module error: module bank initialization failed" );
Sam Hocevar's avatar
 
Sam Hocevar committed
296
        intf_PlaylistDestroy( p_main->p_playlist );
Sam Hocevar's avatar
 
Sam Hocevar committed
297 298 299
        intf_MsgDestroy();
        return( errno );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
300
    module_InitBank( p_main->p_bank );
Sam Hocevar's avatar
 
Sam Hocevar committed
301

Michel Kaempf's avatar
Michel Kaempf committed
302 303 304
    /*
     * Initialize shared resources and libraries
     */
Henri Fallon's avatar
 
Henri Fallon committed
305
    if( p_main->b_channels && network_ChannelCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
306
    {
Henri Fallon's avatar
 
Henri Fallon committed
307 308 309 310
        /* 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
311
    }
312

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

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

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

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

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

    /*
     * Free playlist
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
403
    intf_PlaylistDestroy( p_main->p_playlist );
404 405 406 407

    /*
     * System specific cleaning code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
408 409
#if defined( SYS_BEOS ) || defined( SYS_DARWIN1_3 )
    system_Destroy();
410 411
#endif

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

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

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

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

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

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

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

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

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

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

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

    /* Set default configuration and copy arguments */
Sam Hocevar's avatar
 
Sam Hocevar committed
520
    p_main->i_argc    = *pi_argc;
Vincent Seguin's avatar
Vincent Seguin committed
521
    p_main->ppsz_argv = ppsz_argv;
522
    p_main->ppsz_env  = ppsz_env;
Sam Hocevar's avatar
 
Sam Hocevar committed
523

Henri Fallon's avatar
 
Henri Fallon committed
524 525 526
    p_main->b_audio     = 1;
    p_main->b_video     = 1;
    p_main->b_channels  = 0;
527
    p_main->b_spdif     = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
528 529

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

531
    /* Get the executable name (similar to the basename command) */
Sam Hocevar's avatar
 
Sam Hocevar committed
532 533
    p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
    while( *p_tmp )
Sam Hocevar's avatar
Sam Hocevar committed
534
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
535
        if( *p_tmp == '/' )
Sam Hocevar's avatar
Sam Hocevar committed
536
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
537
            p_main->psz_arg0 = ++p_tmp;
Sam Hocevar's avatar
Sam Hocevar committed
538 539 540
        }
        else
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
541
            ++p_tmp;
Sam Hocevar's avatar
Sam Hocevar committed
542 543 544
        }
    }

545
#ifdef SYS_DARWIN1_3
Sam Hocevar's avatar
 
Sam Hocevar committed
546 547 548
    /* 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
549 550
    if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
                                        /* for example -psn_0_9306113 */
551
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
552 553 554 555 556 557 558 559 560
        /* 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--;
561 562 563 564
        return( 0 );
    }
#endif

Vincent Seguin's avatar
Vincent Seguin committed
565
    /* Parse command line options */
Michel Kaempf's avatar
Michel Kaempf committed
566
    opterr = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
567 568
    while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv,
                                   psz_shortopts, longopts, 0 ) ) != EOF )
Michel Kaempf's avatar
Michel Kaempf committed
569
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
570
        switch( i_cmd )
Michel Kaempf's avatar
Michel Kaempf committed
571
        {
572 573
        /* General/common options */
        case 'h':                                              /* -h, --help */
574 575 576
            Usage( SHORT_HELP );
            return( -1 );
            break;
577
        case 'H':                                          /* -H, --longhelp */
578
            Usage( LONG_HELP );
Michel Kaempf's avatar
Michel Kaempf committed
579 580
            return( -1 );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
581
        case OPT_VERSION:                                       /* --version */
Vincent Seguin's avatar
Vincent Seguin committed
582 583
            Version();
            return( -1 );
584
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
585
        case 'v':                                           /* -v, --verbose */
Sam Hocevar's avatar
 
Sam Hocevar committed
586
            p_main->i_warning_level--;
Sam Hocevar's avatar
 
Sam Hocevar committed
587
            break;
Michel Kaempf's avatar
Michel Kaempf committed
588

Sam Hocevar's avatar
 
Sam Hocevar committed
589
        /* Interface warning messages level */
Sam Hocevar's avatar
 
Sam Hocevar committed
590
        case 'I':                                              /* -I, --intf */
Sam Hocevar's avatar
 
Sam Hocevar committed
591 592 593
            main_PutPszVariable( INTF_METHOD_VAR, optarg );
            break;
        case OPT_WARNING:                                       /* --warning */
Sam Hocevar's avatar
 
Sam Hocevar committed
594 595
            intf_ErrMsg( "intf error: `--warning' is deprecated, use `-v'" );
            p_main->i_warning_level = atoi(optarg);
Sam Hocevar's avatar
 
Sam Hocevar committed
596 597
            break;

Michel Kaempf's avatar
Michel Kaempf committed
598
        /* Audio options */
599
        case OPT_NOAUDIO:                                       /* --noaudio */
600
            p_main->b_audio = 0;
Michel Kaempf's avatar
Michel Kaempf committed
601
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
602
        case 'A':                                              /* -A, --aout */
603 604
            main_PutPszVariable( AOUT_METHOD_VAR, optarg );
            break;
605
        case OPT_STEREO:                                         /* --stereo */
606
            main_PutIntVariable( AOUT_STEREO_VAR, 1 );
Michel Kaempf's avatar
Michel Kaempf committed
607
            break;
608
        case OPT_MONO:                                             /* --mono */
609
            main_PutIntVariable( AOUT_STEREO_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
610
            break;
611 612 613
        case OPT_SPDIF:                                           /* --spdif */
            p_main->b_spdif = 1;
            break;
Michel Kaempf's avatar
Michel Kaempf committed
614 615

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

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

680
        /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
681
        case OPT_INPUT:                                           /* --input */
Sam Hocevar's avatar
 
Sam Hocevar committed
682 683
            main_PutPszVariable( INPUT_METHOD_VAR, optarg );
            break;
Henri Fallon's avatar
 
Henri Fallon committed
684 685
        case OPT_CHANNELS:                                     /* --channels */
            p_main->b_channels = 1;
686 687
            break;
        case OPT_SERVER:                                         /* --server */
688
            main_PutPszVariable( INPUT_SERVER_VAR, optarg );
689 690
            break;
        case OPT_PORT:                                             /* --port */
691
            main_PutPszVariable( INPUT_PORT_VAR, optarg );
692
            break;
693
        case OPT_BROADCAST:                                   /* --broadcast */
Henri Fallon's avatar
 
Henri Fallon committed
694
            main_PutPszVariable( INPUT_BROADCAST_VAR, optarg );
695
            break;
696

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
718 719 720 721 722 723 724 725 726 727 728
    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
729

Sam Hocevar's avatar
 
Sam Hocevar committed
730
    /* We assume that the remaining parameters are filenames */
Vincent Seguin's avatar
Vincent Seguin committed
731 732
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
733 734
        intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
                          ppsz_argv[ i_opt ] );
Vincent Seguin's avatar
Vincent Seguin committed
735
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
736

Michel Kaempf's avatar
Michel Kaempf committed
737 738 739
    return( 0 );
}

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

    if( i_fashion == USAGE )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
753 754
        intf_MsgImm( "Try `%s --help' for more information.",
                     p_main->psz_arg0 );
755 756 757
        return;
    }

Vincent Seguin's avatar
Vincent Seguin committed
758
    /* Options */
Sam Hocevar's avatar
 
Sam Hocevar committed
759
    intf_MsgImm( "\nOptions:"
Sam Hocevar's avatar
 
Sam Hocevar committed
760
          "\n  -I, --intf <module>            \tinterface method"
Sam Hocevar's avatar
 
Sam Hocevar committed
761
          "\n  -v, --verbose                  \tverbose mode (cumulative)"
Sam Hocevar's avatar
 
Sam Hocevar committed
762
          "\n"
Sam Hocevar's avatar
 
Sam Hocevar committed
763
          "\n      --noaudio                  \tdisable audio"