main.c 50.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-2001 VideoLAN
Sam Hocevar's avatar
 
Sam Hocevar committed
7
 * $Id: main.c,v 1.135 2001/12/10 13:17:35 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

#ifndef WIN32
Sam Hocevar's avatar
 
Sam Hocevar committed
52
#   include <netinet/in.h>                            /* BSD: struct in_addr */
Sam Hocevar's avatar
 
Sam Hocevar committed
53
#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 57 58
#   include <unistd.h>
#elif defined( _MSC_VER ) && defined( _WIN32 )
#   include <io.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
59 60
#endif

61 62 63
#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                  /* getenv(), strtol(),  */
#include <string.h>                                            /* strerror() */
gbazin's avatar
 
gbazin committed
64 65
#include <fcntl.h>                                       /* open(), O_WRONLY */
#include <sys/stat.h>                                             /* S_IREAD */
Vincent Seguin's avatar
Vincent Seguin committed
66

Michel Kaempf's avatar
Michel Kaempf committed
67
#include "common.h"
Christophe Massiot's avatar
Christophe Massiot committed
68
#include "debug.h"
69
#include "intf_msg.h"
70
#include "threads.h"
Michel Kaempf's avatar
Michel Kaempf committed
71
#include "mtime.h"
72
#include "tests.h"                                              /* TestCPU() */
Sam Hocevar's avatar
 
Sam Hocevar committed
73
#include "modules.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
74

75 76
#include "stream_control.h"
#include "input_ext-intf.h"
77

Sam Hocevar's avatar
 
Sam Hocevar committed
78
#include "intf_playlist.h"
Michel Kaempf's avatar
Michel Kaempf committed
79
#include "interface.h"
80

Vincent Seguin's avatar
Vincent Seguin committed
81
#include "audio_output.h"
82

Sam Hocevar's avatar
 
Sam Hocevar committed
83 84 85
#include "video.h"
#include "video_output.h"

86
#ifdef SYS_BEOS
Sam Hocevar's avatar
 
Sam Hocevar committed
87 88 89
#   include "beos_specific.h"
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
90
#ifdef SYS_DARWIN
Sam Hocevar's avatar
 
Sam Hocevar committed
91
#   include "darwin_specific.h"
92 93
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
94 95 96 97
#ifdef WIN32
#   include "win32_specific.h"
#endif

Henri Fallon's avatar
 
Henri Fallon committed
98 99
#include "netutils.h"                                 /* network_ChannelJoin */

100
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
101 102
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
103
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
104 105 106 107

/* 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
108 109
#define OPT_STEREO              151
#define OPT_MONO                152
110
#define OPT_SPDIF               153
111
#define OPT_VOLUME              154
112
#define OPT_DESYNC              155
Michel Kaempf's avatar
Michel Kaempf committed
113 114

#define OPT_NOVIDEO             160
Sam Hocevar's avatar
 
Sam Hocevar committed
115 116 117 118 119 120
#define OPT_DISPLAY             161
#define OPT_WIDTH               162
#define OPT_HEIGHT              163
#define OPT_COLOR               164
#define OPT_FULLSCREEN          165
#define OPT_OVERLAY             166
Sam Hocevar's avatar
 
Sam Hocevar committed
121 122
#define OPT_XVADAPTOR           167
#define OPT_SMP                 168
Michel Kaempf's avatar
Michel Kaempf committed
123

Henri Fallon's avatar
 
Henri Fallon committed
124
#define OPT_CHANNELS            170
125 126
#define OPT_SERVER              171
#define OPT_PORT                172
127
#define OPT_BROADCAST           173
128
#define OPT_CHANNELSERVER       174
129

Sam Hocevar's avatar
 
Sam Hocevar committed
130 131 132 133
#define OPT_INPUT               180
#define OPT_MOTION              181
#define OPT_IDCT                182
#define OPT_YUV                 183
Sam Hocevar's avatar
 
Sam Hocevar committed
134 135
#define OPT_DOWNMIX             184
#define OPT_IMDCT               185
Sam Hocevar's avatar
 
Sam Hocevar committed
136 137 138
#define OPT_MEMCPY              186
#define OPT_DVDCSS_METHOD       187
#define OPT_DVDCSS_VERBOSE      188
139

Sam Hocevar's avatar
 
Sam Hocevar committed
140 141
#define OPT_SYNCHRO             190
#define OPT_WARNING             191
Sam Hocevar's avatar
 
Sam Hocevar committed
142
#define OPT_VERSION             192
gbazin's avatar
 
gbazin committed
143
#define OPT_STDOUT              193
144
#define OPT_STATS               194
145

146 147
#define OPT_MPEG_ADEC           200

148
/* Usage fashion */
149 150 151
#define USAGE                     0
#define SHORT_HELP                1
#define LONG_HELP                 2
152

Sam Hocevar's avatar
 
Sam Hocevar committed
153 154 155 156 157 158 159 160 161 162
/* 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
163 164
/* Long options */
static const struct option longopts[] =
165 166
{
    /*  name,               has_arg,    flag,   val */
Michel Kaempf's avatar
Michel Kaempf committed
167 168

    /* General/common options */
169
    {   "help",             0,          0,      'h' },
170
    {   "longhelp",         0,          0,      'H' },
Sam Hocevar's avatar
 
Sam Hocevar committed
171
    {   "version",          0,          0,      OPT_VERSION },
Michel Kaempf's avatar
Michel Kaempf committed
172

Sam Hocevar's avatar
 
Sam Hocevar committed
173
    /* Interface options */
Sam Hocevar's avatar
 
Sam Hocevar committed
174
    {   "intf",             1,          0,      'I' },
Sam Hocevar's avatar
 
Sam Hocevar committed
175
    {   "warning",          1,          0,      OPT_WARNING },
gbazin's avatar
 
gbazin committed
176
    {   "stdout",           1,          0,      OPT_STDOUT },
177
    {   "stats",            0,          0,      OPT_STATS },
Sam Hocevar's avatar
 
Sam Hocevar committed
178

Michel Kaempf's avatar
Michel Kaempf committed
179
    /* Audio options */
180
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
Sam Hocevar's avatar
 
Sam Hocevar committed
181
    {   "aout",             1,          0,      'A' },
Michel Kaempf's avatar
Michel Kaempf committed
182
    {   "stereo",           0,          0,      OPT_STEREO },
183
    {   "mono",             0,          0,      OPT_MONO },
184
    {   "spdif",            0,          0,      OPT_SPDIF },
Sam Hocevar's avatar
 
Sam Hocevar committed
185 186
    {   "downmix",          1,          0,      OPT_DOWNMIX },
    {   "imdct",            1,          0,      OPT_IMDCT },
187
    {   "volume",           1,          0,      OPT_VOLUME },
188
    {   "desync",           1,          0,      OPT_DESYNC },
Michel Kaempf's avatar
Michel Kaempf committed
189 190

    /* Video options */
191
    {   "novideo",          0,          0,      OPT_NOVIDEO },
Sam Hocevar's avatar
 
Sam Hocevar committed
192
    {   "vout",             1,          0,      'V' },
193
    {   "display",          1,          0,      OPT_DISPLAY },
194
    {   "width",            1,          0,      OPT_WIDTH },
195 196 197
    {   "height",           1,          0,      OPT_HEIGHT },
    {   "grayscale",        0,          0,      'g' },
    {   "color",            0,          0,      OPT_COLOR },
Sam Hocevar's avatar
 
Sam Hocevar committed
198
    {   "motion",           1,          0,      OPT_MOTION },
Sam Hocevar's avatar
 
Sam Hocevar committed
199
    {   "idct",             1,          0,      OPT_IDCT },
Sam Hocevar's avatar
Sam Hocevar committed
200
    {   "yuv",              1,          0,      OPT_YUV },
Sam Hocevar's avatar
 
Sam Hocevar committed
201 202
    {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
    {   "overlay",          0,          0,      OPT_OVERLAY },
Sam Hocevar's avatar
 
Sam Hocevar committed
203
    {   "xvadaptor",        1,          0,      OPT_XVADAPTOR },
204
    {   "smp",              1,          0,      OPT_SMP },
Michel Kaempf's avatar
Michel Kaempf committed
205

206
    /* DVD options */
207 208
    {   "dvdtitle",         1,          0,      't' },
    {   "dvdchapter",       1,          0,      'T' },
209
    {   "dvdangle",         1,          0,      'u' },
210 211 212
    {   "dvdaudio",         1,          0,      'a' },
    {   "dvdchannel",       1,          0,      'c' },
    {   "dvdsubtitle",      1,          0,      's' },
Sam Hocevar's avatar
 
Sam Hocevar committed
213 214
    {   "dvdcss-method",    1,          0,      OPT_DVDCSS_METHOD },
    {   "dvdcss-verbose",   1,          0,      OPT_DVDCSS_VERBOSE },
215
    
216
    /* Input options */
Sam Hocevar's avatar
 
Sam Hocevar committed
217
    {   "input",            1,          0,      OPT_INPUT },
218
    {   "channels",         0,          0,      OPT_CHANNELS },
219
    {   "channelserver",    1,          0,      OPT_CHANNELSERVER },
Michel Kaempf's avatar
Michel Kaempf committed
220

Sam Hocevar's avatar
 
Sam Hocevar committed
221
    /* Misc options */
222
    {   "synchro",          1,          0,      OPT_SYNCHRO },
Sam Hocevar's avatar
 
Sam Hocevar committed
223
    {   "memcpy",           1,          0,      OPT_MEMCPY },
224 225 226 227

    /* Decoder options */
    {   "mpeg_adec",        1,          0,      OPT_MPEG_ADEC },

Michel Kaempf's avatar
Michel Kaempf committed
228 229 230 231
    {   0,                  0,          0,      0 }
};

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

234
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
235
 * Global variables - these are the only ones, see main.h and modules.h
236
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
237 238 239 240
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
241

242
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
243
 * Local prototypes
244
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
245
static int  GetConfiguration        ( int *pi_argc, char *ppsz_argv[],
246
                                      char *ppsz_env[] );
Sam Hocevar's avatar
 
Sam Hocevar committed
247
static int  GetFilenames            ( int i_argc, char *ppsz_argv[] );
248
static void Usage                   ( int i_fashion );
Vincent Seguin's avatar
Vincent Seguin committed
249
static void Version                 ( void );
Vincent Seguin's avatar
Vincent Seguin committed
250

Michel Kaempf's avatar
Michel Kaempf committed
251
static void InitSignalHandler       ( void );
Benoit Steiner's avatar
 
Benoit Steiner committed
252 253
static void SimpleSignalHandler     ( int i_signal );
static void FatalSignalHandler      ( int i_signal );
254
static void InstructionSignalHandler( int i_signal );
Sam Hocevar's avatar
 
Sam Hocevar committed
255
static int  CPUCapabilities         ( void );
gbazin's avatar
 
gbazin committed
256 257 258 259

static int  RedirectSTDOUT          ( void );
static void ShowConsole             ( void );

260 261
static jmp_buf env;
static int  i_illegal;
Sam Hocevar's avatar
 
Sam Hocevar committed
262

263
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
264
 * main: parse command line, start interface and spawn threads
265
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
266 267
 * Steps during program execution are:
 *      -configuration parsing and messages interface initialization
268
 *      -opening of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
269
 *      -execution of interface, which exit on error or on user request
Vincent Seguin's avatar
Vincent Seguin committed
270
 *      -closing of audio output device and some global modules
271
 * On error, the spawned threads are canceled, and the open devices closed.
272
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
273 274
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
Sam Hocevar's avatar
 
Sam Hocevar committed
275 276 277 278
    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;
279

Sam Hocevar's avatar
 
Sam Hocevar committed
280 281 282 283
    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
284

Sam Hocevar's avatar
 
Sam Hocevar committed
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
#ifdef ENABLE_NLS
    /* 
     * Support for getext
     */
    if( ! setlocale(LC_MESSAGES, "") )
    {
        fprintf( stderr, "warning: unsupported locale.\n" );
    }

    if( ! bindtextdomain(PACKAGE, LOCALEDIR) )
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
                 PACKAGE, LOCALEDIR );
    }

    textdomain( PACKAGE );
#endif
        
Sam Hocevar's avatar
 
Sam Hocevar committed
303
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
304
     * Initialize threads system
Sam Hocevar's avatar
 
Sam Hocevar committed
305
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
306
    vlc_threads_init( );
Sam Hocevar's avatar
 
Sam Hocevar committed
307

Sam Hocevar's avatar
 
Sam Hocevar committed
308
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
309
     * Test if our code is likely to run on this CPU 
Sam Hocevar's avatar
 
Sam Hocevar committed
310 311 312
     */
    p_main->i_cpu_capabilities = CPUCapabilities();
    
Sam Hocevar's avatar
 
Sam Hocevar committed
313 314 315
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
316
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
Sam Hocevar's avatar
 
Sam Hocevar committed
317
    system_Init( &i_argc, ppsz_argv, ppsz_env );
318 319 320 321 322 323

#elif defined( SYS_LINUX )
#   ifdef DEBUG
    /* Activate malloc checking routines to detect heap corruptions. */
    main_PutIntVariable( "MALLOC_CHECK_", 2 );
#   endif
324
#endif
325 326 327 328

    /*
     * Initialize messages interface
     */
Vincent Seguin's avatar
Vincent Seguin committed
329
    p_main->p_msg = intf_MsgCreate();
330
    if( !p_main->p_msg )                         /* start messages interface */
Michel Kaempf's avatar
Michel Kaempf committed
331
    {
332
        fprintf( stderr, "error: can't initialize messages interface (%s)\n",
Sam Hocevar's avatar
 
Sam Hocevar committed
333
                 strerror(errno) );
334
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
335
    }
336

337
    intf_MsgImm( COPYRIGHT_MESSAGE "\n" );
Sam Hocevar's avatar
 
Sam Hocevar committed
338

339
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
340
     * Read configuration
341
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
342
    if( GetConfiguration( &i_argc, ppsz_argv, ppsz_env ) ) /* parse cmd line */
Michel Kaempf's avatar
Michel Kaempf committed
343
    {
Vincent Seguin's avatar
Vincent Seguin committed
344
        intf_MsgDestroy();
345
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
346
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
347

gbazin's avatar
 
gbazin committed
348 349 350 351 352 353
    /*
     * Redirect the standard output if required by the user, and on Win32 we
     * also open a console to display the debug messages.
     */
    RedirectSTDOUT();

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
    if( p_main->b_stats )
    {
        char          p_capabilities[200];
        p_capabilities[0] = '\0';

#define PRINT_CAPABILITY( capability, string )                              \
        if( p_main->i_cpu_capabilities & capability )                       \
        {                                                                   \
            strncat( p_capabilities, string " ",                            \
                     sizeof(p_capabilities) - strlen(p_capabilities) );     \
            p_capabilities[sizeof(p_capabilities) - 1] = '\0';              \
        }

        PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
        PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
        PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
        PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
        PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
        PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
        PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
        PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "Altivec" );
        intf_StatMsg("info: CPU has capabilities %s", p_capabilities );
    }

378
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
379
     * Initialize playlist and get commandline files
380
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
381
    p_main->p_playlist = intf_PlaylistCreate();
Sam Hocevar's avatar
 
Sam Hocevar committed
382
    if( !p_main->p_playlist )
383
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
384
        intf_ErrMsg( "playlist error: playlist initialization failed" );
385 386
        intf_MsgDestroy();
        return( errno );
387
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
388
    intf_PlaylistInit( p_main->p_playlist );
389 390

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
391
     * Get input filenames given as commandline arguments
392
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
393
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
394

Sam Hocevar's avatar
 
Sam Hocevar committed
395
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
396
     * Initialize module, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
397
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
398
    module_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
399 400
    aout_InitBank();
    vout_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
401

Sam Hocevar's avatar
 
Sam Hocevar committed
402 403 404 405 406
    /*
     * Choose the best memcpy module
     */
    p_main->p_memcpy_module = module_Need( MODULE_CAPABILITY_MEMCPY, NULL );

Sam Hocevar's avatar
 
Sam Hocevar committed
407
    if( p_main->p_memcpy_module != NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
408 409
    {
#define f p_main->p_memcpy_module->p_functions->memcpy.functions.memcpy
Sam Hocevar's avatar
 
Sam Hocevar committed
410
        p_main->fast_memcpy = f.fast_memcpy;
Sam Hocevar's avatar
 
Sam Hocevar committed
411 412
#undef f
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
413 414 415 416 417 418
    else
    {
        intf_ErrMsg( "intf error: no suitable memcpy module, "
                     "using libc default" );
        p_main->fast_memcpy = memcpy;
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
419

Michel Kaempf's avatar
Michel Kaempf committed
420 421 422
    /*
     * Initialize shared resources and libraries
     */
423 424 425
    if( main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
                             INPUT_NETWORK_CHANNEL_DEFAULT ) &&
        network_ChannelCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
426
    {
Henri Fallon's avatar
 
Henri Fallon committed
427 428 429
        /* On error during Channels initialization, switch off channels */
        intf_Msg( "Channels initialization failed : "
                  "Channel management is deactivated" );
430
        main_PutIntVariable( INPUT_NETWORK_CHANNEL_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
431
    }
432

Michel Kaempf's avatar
Michel Kaempf committed
433
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
434
     * Try to run the interface
Michel Kaempf's avatar
Michel Kaempf committed
435
     */
436
    p_main->p_intf = intf_Create();
Sam Hocevar's avatar
 
Sam Hocevar committed
437
    if( p_main->p_intf == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
438 439 440
    {
        intf_ErrMsg( "intf error: interface initialization failed" );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
441
    else
442
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
        /*
         * 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
         */
461 462
        if( main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
                                 INPUT_NETWORK_CHANNEL_DEFAULT ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
463 464 465
        {
            network_ChannelJoin( COMMON_CHANNEL );
        }
466
    }
Michel Kaempf's avatar
Michel Kaempf committed
467

Sam Hocevar's avatar
 
Sam Hocevar committed
468 469 470
    /*
     * Free memcpy module
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
471 472 473 474
    if( p_main->p_memcpy_module != NULL )
    {
        module_Unneed( p_main->p_memcpy_module );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
475

Sam Hocevar's avatar
 
Sam Hocevar committed
476
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
477
     * Free module, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
478
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
479 480
    vout_EndBank();
    aout_EndBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
481
    module_EndBank();
482 483 484 485

    /*
     * Free playlist
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
486
    intf_PlaylistDestroy( p_main->p_playlist );
487 488 489 490

    /*
     * System specific cleaning code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
491
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
Sam Hocevar's avatar
 
Sam Hocevar committed
492
    system_End();
493 494
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
495

Michel Kaempf's avatar
Michel Kaempf committed
496 497 498
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
499
    intf_Msg( "intf: program terminated" );
Vincent Seguin's avatar
Vincent Seguin committed
500
    intf_MsgDestroy();
501

Sam Hocevar's avatar
 
Sam Hocevar committed
502 503 504 505
    /*
     * Stop threads system
     */
    vlc_threads_end( );
Sam Hocevar's avatar
 
Sam Hocevar committed
506

Sam Hocevar's avatar
 
Sam Hocevar committed
507
    return 0;
Michel Kaempf's avatar
Michel Kaempf committed
508 509
}

510
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
511
 * main_GetIntVariable: get the int value of an environment variable
512
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
513
 * This function is used to read some default parameters in modules.
514
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
515 516
int main_GetIntVariable( char *psz_name, int i_default )
{
517 518 519
    char *      psz_env;                                /* environment value */
    char *      psz_end;                             /* end of parsing index */
    long int    i_value;                                            /* value */
Vincent Seguin's avatar
Vincent Seguin committed
520 521 522

    psz_env = getenv( psz_name );
    if( psz_env )
523
    {
524 525 526 527
        i_value = strtol( psz_env, &psz_end, 0 );
        if( (*psz_env != '\0') && (*psz_end == '\0') )
        {
            return( i_value );
528
        }
529
    }
Vincent Seguin's avatar
Vincent Seguin committed
530 531 532
    return( i_default );
}

533
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
534
 * main_GetPszVariable: get the string value of an environment variable
535
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
536
 * This function is used to read some default parameters in modules.
537
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
538 539 540 541 542 543 544
char * main_GetPszVariable( char *psz_name, char *psz_default )
{
    char *psz_env;

    psz_env = getenv( psz_name );
    if( psz_env )
    {
545
        return( psz_env );
Vincent Seguin's avatar
Vincent Seguin committed
546
    }
547
    return( psz_default );
Vincent Seguin's avatar
Vincent Seguin committed
548 549
}

550
/*****************************************************************************
551
 * main_PutPszVariable: set the string value of an environment variable
552
 *****************************************************************************
553 554 555
 * 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.
556
 *****************************************************************************/
557 558 559 560 561 562 563
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
564 565
        intf_ErrMsg( "intf error: cannot create psz_env (%s)",
                     strerror(ENOMEM) );
566 567 568 569 570 571
    }
    else
    {
        sprintf( psz_env, "%s=%s", psz_name, psz_value );
        if( putenv( psz_env ) )
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
572
            intf_ErrMsg( "intf error: cannot putenv (%s)", strerror(errno) );
573
        }
574 575 576
    }
}

577
/*****************************************************************************
578
 * main_PutIntVariable: set the integer value of an environment variable
579
 *****************************************************************************
580 581 582
 * 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.
583
 *****************************************************************************/
584 585
void main_PutIntVariable( char *psz_name, int i_value )
{
586
    char psz_value[ 256 ];                               /* buffer for value */
587

588
    sprintf( psz_value, "%d", i_value );
589
    main_PutPszVariable( psz_name, psz_value );
590 591
}

Michel Kaempf's avatar
Michel Kaempf committed
592 593
/* following functions are local */

594
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
595
 * GetConfiguration: parse command line
596
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
597 598
 * Parse command line and configuration file for configuration. If the inline
 * help is requested, the function Usage() is called and the function returns
599
 * -1 (causing main() to exit). The messages interface is initialized at this
Vincent Seguin's avatar
Vincent Seguin committed
600 601
 * stage, but most structures are not allocated, so only environment should
 * be used.
602
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
603
static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
Michel Kaempf's avatar
Michel Kaempf committed
604
{
Sam Hocevar's avatar
 
Sam Hocevar committed
605 606
    int   i_cmd;
    char *p_tmp;
Michel Kaempf's avatar
Michel Kaempf committed
607 608

    /* Set default configuration and copy arguments */
Sam Hocevar's avatar
 
Sam Hocevar committed
609
    p_main->i_argc    = *pi_argc;
Vincent Seguin's avatar
Vincent Seguin committed
610
    p_main->ppsz_argv = ppsz_argv;
611
    p_main->ppsz_env  = ppsz_env;
Sam Hocevar's avatar
 
Sam Hocevar committed
612

Henri Fallon's avatar
 
Henri Fallon committed
613 614
    p_main->b_audio     = 1;
    p_main->b_video     = 1;
Sam Hocevar's avatar
 
Sam Hocevar committed
615

616
    p_main->i_warning_level = 0;
617
    p_main->b_stats = 0;
618
    p_main->i_desync = 0; /* No desynchronization by default */
Michel Kaempf's avatar
Michel Kaempf committed
619

620 621
    p_main->p_channel = NULL;

622
    /* Get the executable name (similar to the basename command) */
Sam Hocevar's avatar
 
Sam Hocevar committed
623 624
    p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
    while( *p_tmp )
Sam Hocevar's avatar
Sam Hocevar committed
625
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
626
        if( *p_tmp == '/' )
Sam Hocevar's avatar
Sam Hocevar committed
627
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
628
            p_main->psz_arg0 = ++p_tmp;
Sam Hocevar's avatar
Sam Hocevar committed
629 630 631
        }
        else
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
632
            ++p_tmp;
Sam Hocevar's avatar
Sam Hocevar committed
633 634 635
        }
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
636
#ifdef SYS_DARWIN
Sam Hocevar's avatar
 
Sam Hocevar committed
637 638 639
    /* 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
640 641
    if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
                                        /* for example -psn_0_9306113 */
642
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
643 644 645 646 647 648 649 650 651
        /* 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--;
652 653 654 655
        return( 0 );
    }
#endif

Vincent Seguin's avatar
Vincent Seguin committed
656
    /* Parse command line options */
Michel Kaempf's avatar
Michel Kaempf committed
657
    opterr = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
658 659
    while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv,
                                   psz_shortopts, longopts, 0 ) ) != EOF )
Michel Kaempf's avatar
Michel Kaempf committed
660
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
661
        switch( i_cmd )
Michel Kaempf's avatar
Michel Kaempf committed
662
        {
663 664
        /* General/common options */
        case 'h':                                              /* -h, --help */
gbazin's avatar
 
gbazin committed
665 666
            ShowConsole();
            RedirectSTDOUT();
667
            Usage( SHORT_HELP );
gbazin's avatar
 
gbazin committed
668 669 670 671 672 673 674 675 676
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
            if( strcmp( "", main_GetPszVariable( INTF_STDOUT_VAR,
                                                 INTF_STDOUT_DEFAULT ) ) == 0 )
            {
                /* No stdout redirection has been asked for */
                intf_MsgImm( "\nPress the RETURN key to continue..." );
                getchar();
            }
#endif
677 678
            return( -1 );
            break;
679
        case 'H':                                          /* -H, --longhelp */
gbazin's avatar
 
gbazin committed
680 681
            ShowConsole();
            RedirectSTDOUT();
682
            Usage( LONG_HELP );
gbazin's avatar
 
gbazin committed
683 684 685 686 687 688 689 690 691
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
            if( strcmp( "", main_GetPszVariable( INTF_STDOUT_VAR,
                                                 INTF_STDOUT_DEFAULT ) ) == 0 )
            {
                /* No stdout redirection has been asked for */
                intf_MsgImm( "\nPress the RETURN key to continue..." );
                getchar();
            }
#endif
Michel Kaempf's avatar
Michel Kaempf committed
692 693
            return( -1 );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
694
        case OPT_VERSION:                                       /* --version */
gbazin's avatar
 
gbazin committed
695 696
            ShowConsole();
            RedirectSTDOUT();
Vincent Seguin's avatar
Vincent Seguin committed
697
            Version();
gbazin's avatar
 
gbazin committed
698 699 700 701 702 703 704 705 706
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
            if( strcmp( "", main_GetPszVariable( INTF_STDOUT_VAR,
                                                 INTF_STDOUT_DEFAULT ) ) == 0 )
            {
                /* No stdout redirection has been asked for */
                intf_MsgImm( "\nPress the RETURN key to continue..." );
                getchar();
            }
#endif
Vincent Seguin's avatar
Vincent Seguin committed
707
            return( -1 );
708
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
709
        case 'v':                                           /* -v, --verbose */
710
            p_main->i_warning_level++;
Sam Hocevar's avatar
 
Sam Hocevar committed
711
            break;
Michel Kaempf's avatar
Michel Kaempf committed
712

Sam Hocevar's avatar
 
Sam Hocevar committed
713
        /* Interface warning messages level */
Sam Hocevar's avatar
 
Sam Hocevar committed
714
        case 'I':                                              /* -I, --intf */
Sam Hocevar's avatar
 
Sam Hocevar committed
715 716 717
            main_PutPszVariable( INTF_METHOD_VAR, optarg );
            break;
        case OPT_WARNING:                                       /* --warning */
Sam Hocevar's avatar
 
Sam Hocevar committed
718 719
            intf_ErrMsg( "intf error: `--warning' is deprecated, use `-v'" );
            p_main->i_warning_level = atoi(optarg);
Sam Hocevar's avatar
 
Sam Hocevar committed
720 721
            break;

gbazin's avatar
 
gbazin committed
722 723 724 725
        case OPT_STDOUT:                                         /* --stdout */
            main_PutPszVariable( INTF_STDOUT_VAR, optarg );
            break;

726 727 728 729
        case OPT_STATS:
            p_main->b_stats = 1;
            break;

Michel Kaempf's avatar
Michel Kaempf committed
730
        /* Audio options */
731
        case OPT_NOAUDIO:                                       /* --noaudio */
732
            p_main->b_audio = 0;
Michel Kaempf's avatar
Michel Kaempf committed
733
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
734
        case 'A':                                              /* -A, --aout */
735 736
            main_PutPszVariable( AOUT_METHOD_VAR, optarg );
            break;
737
        case OPT_STEREO:                                         /* --stereo */
738
            main_PutIntVariable( AOUT_STEREO_VAR, 1 );
Michel Kaempf's avatar
Michel Kaempf committed
739
            break;
740
        case OPT_MONO:                                             /* --mono */
741
            main_PutIntVariable( AOUT_STEREO_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
742
            break;
743
        case OPT_SPDIF:                                           /* --spdif */
Sam Hocevar's avatar
 
Sam Hocevar committed
744
            main_PutIntVariable( AOUT_SPDIF_VAR, 1 );
745
            break;
gbazin's avatar
 
gbazin committed
746
        case OPT_DOWNMIX:                                       /* --downmix */
Sam Hocevar's avatar
 
Sam Hocevar committed
747 748 749 750 751
            main_PutPszVariable( DOWNMIX_METHOD_VAR, optarg );
            break;
        case OPT_IMDCT:                                           /* --imdct */
            main_PutPszVariable( IMDCT_METHOD_VAR, optarg );
            break;
752 753 754
        case OPT_VOLUME:                                         /* --volume */
            main_PutIntVariable( AOUT_VOLUME_VAR, atoi(optarg) );
            break;
755 756 757
        case OPT_DESYNC:                                         /* --desync */
            p_main->i_desync = atoi(optarg);
            break;
Michel Kaempf's avatar
Michel Kaempf committed
758 759

        /* Video options */
760
        case OPT_NOVIDEO:                                       /* --novideo */
Vincent Seguin's avatar
Vincent Seguin committed
761
            p_main->b_video = 0;
762
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
763
        case 'V':                                              /* -V, --vout */
764 765
            main_PutPszVariable( VOUT_METHOD_VAR, optarg );
            break;
766
        case OPT_DISPLAY:                                       /* --display */
767
            main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
768 769
            break;
        case OPT_WIDTH:                                           /* --width */
770
            main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
771 772 773 774 775
            break;
        case OPT_HEIGHT:                                         /* --height */
            main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );
            break;
        case 'g':                                         /* -g, --grayscale */
776
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
777 778
            break;
        case OPT_COLOR:                                           /* --color */
779
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
780
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
781
        case OPT_FULLSCREEN:                                 /* --fullscreen */
Sam Hocevar's avatar
 
Sam Hocevar committed
782 783
            main_PutIntVariable( VOUT_FULLSCREEN_VAR, 1 );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
784
        case OPT_OVERLAY:                                       /* --overlay */
Sam Hocevar's avatar
 
Sam Hocevar committed
785 786
            main_PutIntVariable( VOUT_OVERLAY_VAR, 1 );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
787 788 789
        case OPT_XVADAPTOR:                                   /* --xvadaptor */
            main_PutIntVariable( VOUT_XVADAPTOR_VAR, atoi(optarg) );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
790
        case OPT_MOTION:                                         /* --motion */
Sam Hocevar's avatar
 
Sam Hocevar committed
791 792
            main_PutPszVariable( MOTION_METHOD_VAR, optarg );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
793
        case OPT_IDCT:                                             /* --idct */
Sam Hocevar's avatar
 
Sam Hocevar committed
794 795
            main_PutPszVariable( IDCT_METHOD_VAR, optarg );
            break;
Sam Hocevar's avatar
Sam Hocevar committed
796 797 798
        case OPT_YUV:                                               /* --yuv */
            main_PutPszVariable( YUV_METHOD_VAR, optarg );
            break;
799 800 801