main.c 50.1 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
Stéphane Borel's avatar
 
Stéphane Borel committed
7
 * $Id: main.c,v 1.163 2002/03/12 18:37:46 stef Exp $
8
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
9 10
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
gbazin's avatar
 
gbazin committed
11
 *          Gildas Bazin <gbazin@netcourrier.com>
12 13 14 15 16
 *
 * 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.
17
 * 
18 19
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
22
 *
23 24 25
 * 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.
26
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
27

28
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
29
 * Preamble
30
 *****************************************************************************/
31 32
#include <signal.h>                               /* SIGHUP, SIGINT, SIGKILL */
#include <stdio.h>                                              /* sprintf() */
33
#include <setjmp.h>                                       /* longjmp, setjmp */
34

Sam Hocevar's avatar
 
Sam Hocevar committed
35 36
#include <videolan/vlc.h>

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
56
#ifdef HAVE_UNISTD_H
Sam Hocevar's avatar
 
Sam Hocevar committed
57 58 59
#   include <unistd.h>
#elif defined( _MSC_VER ) && defined( _WIN32 )
#   include <io.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
60 61
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
62 63 64 65
#ifdef HAVE_LOCALE_H
#    include <locale.h>
#endif

66 67 68
#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                  /* getenv(), strtol(),  */
#include <string.h>                                            /* strerror() */
gbazin's avatar
 
gbazin committed
69 70
#include <fcntl.h>                                       /* open(), O_WRONLY */
#include <sys/stat.h>                                             /* S_IREAD */
Vincent Seguin's avatar
Vincent Seguin committed
71

Sam Hocevar's avatar
 
Sam Hocevar committed
72
#include "netutils.h"                                 /* network_ChannelJoin */
Sam Hocevar's avatar
 
Sam Hocevar committed
73

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

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

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

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

Sam Hocevar's avatar
 
Sam Hocevar committed
85
#include "debug.h"
Henri Fallon's avatar
 
Henri Fallon committed
86

87
/*****************************************************************************
gbazin's avatar
 
gbazin committed
88 89 90 91 92 93 94 95 96 97
 * Configuration options for the main program. Each plugin will also separatly
 * define its own configuration options.
 * Look into configuration.h if you need to know more about the following
 * macros.
 * 
 *****************************************************************************/
#define BUILTIN
#define MODULE_NAME main
#include "modules_inner.h"                        /* for configuration stuff */

gbazin's avatar
 
gbazin committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132

#define INTF_TEXT "interface method"
#define INTF_LONGTEXT "This option allows you to select the interface used by"\
                      " vlc.\nNote that the default behaviour is to" \
                      " automatically select the best method available"

#define WARNING_TEXT "warning level (or use -v, -vv, etc...)"
#define WARNING_LONGTEXT "Increasing the warning level will allow you to see" \
                         " more debug messages and can sometimes help you to" \
                         " troubleshoot a problem"

#define STATS_TEXT "output statistics"
#define STATS_LONGTEXT "Enabling the stats mode will flood your log console" \
                       " with various statistics messages"

#define INTF_PATH_TEXT "interface default search path"
#define INTF_PATH_LONGTEXT "This option allows you to set the default path" \
                           "that the interface will open when looking for a" \
                           " file"

#define AOUT_TEXT "audio output method"
#define AOUT_LONGTEXT "This option allows you to select the audio" \
                      " audio output method used by vlc.\nNote that the" \
                      " default behaviour is to automatically select the best"\
                      " method available"

#define NOAUDIO_TEXT "disable audio"
#define NOAUDIO_LONGTEXT "This will completely disable the audio output. The" \
                         " audio decoding stage shouldn't even be done, so it"\
                         " can allow you to save some processing power"

#define MONO_TEXT "mono audio"
#define MONO_LONGTEXT "This will force a mono audio output"

#define VOLUME_TEXT "audio output volume"
Stéphane Borel's avatar
 
Stéphane Borel committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
#define VOLUME_LONGTEXT "You can set the default audio output volume here," \
                        " in a range from 0 to 1024"

#define FORMAT_TEXT "audio output format"
#define FORMAT_LONGTEXT "You can force the audio output format here.\n" \
                        "0 -> 16 bits signed native endian (default)\n" \
                        "1 ->  8 bits unsigned\n"                       \
                        "2 -> 16 bits signed little endian\n"           \
                        "3 -> 16 bits signed big endian\n"              \
                        "4 ->  8 bits signed\n"                         \
                        "5 -> 16 bits unsigned little endian\n"         \
                        "6 -> 16 bits unsigned big endian\n"            \
                        "7 -> mpeg2 audio (unsupported)\n"              \
                        "8 -> ac3 pass-through"
                         
#define RATE_TEXT "audio output frequency (Hz)"
#define RATE_LONGTEXT "You can force the audio output frequency here.\n"    \
                      "Common values are 48000, 44100, 32000, 22050,"       \
                      " 16000, 11025, 8000"
gbazin's avatar
 
gbazin committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270

#define DESYNC_TEXT "Compensate desynchronization of audio (in ms)"
#define DESYNC_LONGTEXT "This option allows you to delay the audio output." \
                        "This can be handy if you notice a lag between the" \
                        " video and the audio"

#define VOUT_TEXT "video output method"
#define VOUT_LONGTEXT "This option allows you to select the video output" \
                      "method used by vlc.\nNote that the default behaviour" \
                      "is to automatically select the best method available"

#define NOVIDEO_TEXT "disable video"
#define NOVIDEO_LONGTEXT "This will completely disable the video output. The" \
                         "video decoding stage shouldn't even be done, so it" \
                         "can allow you to save some processing power"

#define DISPLAY_TEXT "display identifier"
#define DISPLAY_LONGTEXT NULL

#define WIDTH_TEXT "video width"
#define WIDTH_LONGTEXT "You can enforce the video width here.\nNote" \
                       "that by default vlc will adapt to the video properties"

#define HEIGHT_TEXT "video height"
#define HEIGHT_LONGTEXT NULL

#define GRAYSCALE_TEXT "grayscale video output"
#define GRAYSCALE_LONGTEXT NULL

#define FULLSCREEN_TEXT "fullscreen video output"
#define FULLSCREEN_LONGTEXT NULL

#define NOOVERLAY_TEXT "disable accelerated display"
#define NOOVERLAY_LONGTEXT NULL

#define SPUMARGIN_TEXT "force SPU position"
#define SPUMARGIN_LONGTEXT NULL

#define FILTER_TEXT "video filter module"
#define FILTER_LONGTEXT NULL

#define INPUT_TEXT "input method"
#define INPUT_LONGTEXT NULL

#define SERVER_PORT_TEXT "server port"
#define SERVER_PORT_LONGTEXT NULL

#define NETCHANNEL_TEXT "enable network channel mode"
#define NETCHANNEL_LONGTEXT NULL

#define CHAN_SERV_TEXT "channel server address"
#define CHAN_SERV_LONGTEXT NULL

#define CHAN_PORT_TEXT "channel server port"
#define CHAN_PORT_LONGTEXT NULL

#define IFACE_TEXT "network interface"
#define IFACE_LONGTEXT NULL

#define INPUT_AUDIO_TEXT "choose audio"
#define INPUT_AUDIO_LONGTEXT NULL

#define INPUT_CHAN_TEXT "choose channel"
#define INPUT_CHAN_LONGTEXT NULL

#define INPUT_SUBT_TEXT "choose subtitles"
#define INPUT_SUBT_LONGTEXT NULL

#define DVD_DEV_TEXT "DVD device"
#define DVD_DEV_LONGTEXT NULL

#define VCD_DEV_TEXT "VCD device"
#define VCD_DEV_LONGTEXT NULL

#define IPV6_TEXT "force IPv6"
#define IPV6_LONGTEXT NULL

#define IPV4_TEXT "force IPv6"
#define IPV4_LONGTEXT NULL

#define ADEC_MPEG_TEXT "choose MPEG audio decoder"
#define ADEC_MPEG_LONGTEXT NULL

#define ADEC_AC3_TEXT "choose AC3 audio decoder"
#define ADEC_AC3_LONGTEXT NULL

#define VDEC_SMP_TEXT "use additional processors"
#define VDEC_SMP_LONGTEXT NULL

#define VPAR_SYNCHRO_TEXT "force synchro algorithm {I|I+|IP|IP+|IPB}"
#define VPAR_SYNCHRO_LONGTEXT NULL

#define NOMMX_TEXT "disable CPU's MMX support"
#define NOMMX_LONGTEXT NULL

#define NO3DN_TEXT "disable CPU's 3D Now! support"
#define NO3DN_LONGTEXT NULL

#define NOMMXEXT_TEXT "disable CPU's MMX EXT support"
#define NOMMXEXT_LONGTEXT NULL

#define NOSSE_TEXT "disable CPU's SSE support"
#define NOSSE_LONGTEXT NULL

#define NOALTIVEC_TEXT "disable CPU's AltiVec support"
#define NOALTIVEC_LONGTEXT NULL

#define PLAYLIST_LAUNCH_TEXT "launch playlist on startup"
#define PLAYLIST_LAUNCH_LONGTEXT NULL

#define PLAYLIST_ENQUEUE_TEXT "enqeue playlist as default"
#define PLAYLIST_ENQUEUE_LONGTEXT NULL

#define PLAYLIST_LOOP_TEXT "loop playlist on end"
#define PLAYLIST_LOOP_LONGTEXT NULL

#define MEMCPY_TEXT "memory copy method"
#define MEMCPY_LONGTEXT NULL

gbazin's avatar
 
gbazin committed
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
/* Quick usage guide
MODULE_CONFIG_START
MODULE_CONFIG_STOP
ADD_CATEGORY_HINT( text, longtext )
ADD_SUBCATEGORY_HINT( text, longtext )
ADD_STRING( option_name, value, p_callback, text, longtext )
ADD_FILE( option_name, psz_value, p_callback, text, longtext )
ADD_PLUGIN( option_name, psz_value, i_capability, p_callback, text, longtext )
ADD_INTEGER( option_name, i_value, p_callback, text, longtext )
ADD_BOOL( option_name, p_callback, text, longtext )
*/

MODULE_CONFIG_START

/* Interface options */
gbazin's avatar
 
gbazin committed
286 287 288 289 290 291 292 293 294 295 296 297 298 299
ADD_CATEGORY_HINT( "Interface", NULL)
ADD_PLUGIN  ( "intf", MODULE_CAPABILITY_INTF, NULL, NULL, INTF_TEXT, INTF_LONGTEXT )
ADD_INTEGER ( "warning", 0, NULL, WARNING_TEXT, WARNING_LONGTEXT )
ADD_BOOL    ( "stats", NULL, STATS_TEXT, STATS_LONGTEXT )
ADD_STRING  ( "search_path", NULL, NULL, INTF_PATH_TEXT, INTF_PATH_LONGTEXT )

/* Audio options */
ADD_CATEGORY_HINT( "Audio", NULL)
ADD_PLUGIN  ( "aout", MODULE_CAPABILITY_AOUT, NULL, NULL, AOUT_TEXT, AOUT_LONGTEXT )
ADD_BOOL    ( "noaudio", NULL, NOAUDIO_TEXT, NOAUDIO_LONGTEXT )
ADD_BOOL    ( "mono", NULL, MONO_TEXT, MONO_LONGTEXT )
ADD_INTEGER ( "volume", VOLUME_DEFAULT, NULL, VOLUME_TEXT, VOLUME_LONGTEXT )
ADD_INTEGER ( "rate", 44100, NULL, RATE_TEXT, RATE_LONGTEXT )
ADD_INTEGER ( "desync", 0, NULL, DESYNC_TEXT, DESYNC_LONGTEXT )
Stéphane Borel's avatar
 
Stéphane Borel committed
300 301
ADD_INTEGER ( "aout_format", 0, NULL, FORMAT_TEXT,
              FORMAT_LONGTEXT )
gbazin's avatar
 
gbazin committed
302 303

/* Video options */
gbazin's avatar
 
gbazin committed
304 305 306 307 308 309 310 311 312 313 314
ADD_CATEGORY_HINT( "Video", NULL )
ADD_PLUGIN  ( "vout", MODULE_CAPABILITY_VOUT, NULL, NULL, VOUT_TEXT, VOUT_LONGTEXT )
ADD_BOOL    ( "novideo", NULL, NOVIDEO_TEXT, NOVIDEO_LONGTEXT )
ADD_STRING  ( "display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT )
ADD_INTEGER ( "width", 720, NULL, WIDTH_TEXT, WIDTH_LONGTEXT )
ADD_INTEGER ( "height", 576, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT )
ADD_BOOL    ( "grayscale", NULL, GRAYSCALE_TEXT, GRAYSCALE_LONGTEXT )
ADD_BOOL    ( "fullscreen", NULL, FULLSCREEN_TEXT, FULLSCREEN_LONGTEXT )
ADD_BOOL    ( "nooverlay", NULL, NOOVERLAY_TEXT, NOOVERLAY_LONGTEXT )
ADD_INTEGER ( "spumargin", -1, NULL, SPUMARGIN_TEXT, SPUMARGIN_LONGTEXT )
ADD_PLUGIN  ( "filter", MODULE_CAPABILITY_VOUT, NULL, NULL, FILTER_TEXT, FILTER_LONGTEXT )
gbazin's avatar
 
gbazin committed
315 316

/* Input options */
gbazin's avatar
 
gbazin committed
317 318 319 320 321 322 323 324 325
ADD_CATEGORY_HINT( "Input", NULL )
ADD_STRING  ( "input", NULL, NULL, INPUT_TEXT, INPUT_LONGTEXT )
ADD_INTEGER ( "server_port", 1234, NULL, SERVER_PORT_TEXT, SERVER_PORT_LONGTEXT )
ADD_BOOL    ( "network_channel", NULL, NETCHANNEL_TEXT, NETCHANNEL_LONGTEXT )
ADD_STRING  ( "channel_server", "localhost", NULL, CHAN_SERV_TEXT, CHAN_SERV_LONGTEXT )
ADD_INTEGER ( "channel_port", 6010, NULL, CHAN_PORT_TEXT, CHAN_PORT_LONGTEXT )
ADD_STRING  ( "iface", "eth0", NULL, IFACE_TEXT, IFACE_LONGTEXT )

ADD_INTEGER ( "input_audio", -1, NULL, INPUT_AUDIO_TEXT, INPUT_AUDIO_LONGTEXT )
Stéphane Borel's avatar
 
Stéphane Borel committed
326
ADD_INTEGER ( "input_channel", -1, NULL, INPUT_CHAN_TEXT, INPUT_CHAN_LONGTEXT )
gbazin's avatar
 
gbazin committed
327 328 329 330 331 332
ADD_INTEGER ( "input_subtitle", -1, NULL, INPUT_SUBT_TEXT, INPUT_SUBT_LONGTEXT )

ADD_STRING  ( "dvd_device", "/dev/dvd", NULL, DVD_DEV_TEXT, DVD_DEV_LONGTEXT )
ADD_STRING  ( "vcd_device", "/dev/cdrom", NULL, VCD_DEV_TEXT, VCD_DEV_LONGTEXT )
ADD_BOOL    ( "ipv6", NULL, IPV6_TEXT, IPV6_LONGTEXT )
ADD_BOOL    ( "ipv4", NULL, IPV4_TEXT, IPV4_LONGTEXT )
gbazin's avatar
 
gbazin committed
333 334

/* Decoder options */
gbazin's avatar
 
gbazin committed
335 336 337 338 339
ADD_CATEGORY_HINT( "Decoders", NULL )
ADD_PLUGIN  ( "mpeg_adec", MODULE_CAPABILITY_DECODER, NULL, NULL, ADEC_MPEG_TEXT, ADEC_MPEG_LONGTEXT )
ADD_PLUGIN  ( "ac3_adec", MODULE_CAPABILITY_DECODER, NULL, NULL, ADEC_AC3_TEXT, ADEC_AC3_LONGTEXT )
ADD_INTEGER ( "vdec_smp", 0, NULL, VDEC_SMP_TEXT, VDEC_SMP_LONGTEXT )
ADD_STRING  ( "vpar_synchro", NULL, NULL, VPAR_SYNCHRO_TEXT, VPAR_SYNCHRO_LONGTEXT )
gbazin's avatar
 
gbazin committed
340 341

/* CPU options */
gbazin's avatar
 
gbazin committed
342 343 344 345 346 347
ADD_CATEGORY_HINT( "CPU", NULL )
ADD_BOOL    ( "nommx", NULL, NOMMX_TEXT, NOMMX_LONGTEXT )
ADD_BOOL    ( "no3dn", NULL, NO3DN_TEXT, NO3DN_LONGTEXT )
ADD_BOOL    ( "nommxext", NULL, NOMMXEXT_TEXT, NOMMXEXT_LONGTEXT )
ADD_BOOL    ( "nosse", NULL, NOSSE_TEXT, NOSSE_LONGTEXT )
ADD_BOOL    ( "noaltivec", NULL, NOALTIVEC_TEXT, NOALTIVEC_LONGTEXT )
gbazin's avatar
 
gbazin committed
348 349

/* Playlist options */
gbazin's avatar
 
gbazin committed
350 351 352 353
ADD_CATEGORY_HINT( "Playlist", NULL )
ADD_BOOL    ( "playlist_launch", NULL, PLAYLIST_LAUNCH_TEXT, PLAYLIST_LAUNCH_LONGTEXT )
ADD_BOOL    ( "playlist_enqueue", NULL, PLAYLIST_ENQUEUE_TEXT, PLAYLIST_ENQUEUE_LONGTEXT )
ADD_BOOL    ( "playlist_loop", NULL, PLAYLIST_LOOP_TEXT, PLAYLIST_LOOP_LONGTEXT )
gbazin's avatar
 
gbazin committed
354 355

/* Misc options */
gbazin's avatar
 
gbazin committed
356 357
ADD_CATEGORY_HINT( "Miscellaneous", NULL )
ADD_PLUGIN  ( "memcpy", MODULE_CAPABILITY_MEMCPY, NULL, NULL, MEMCPY_TEXT, MEMCPY_LONGTEXT )
gbazin's avatar
 
gbazin committed
358 359 360 361 362 363 364 365 366 367 368 369 370

MODULE_CONFIG_STOP

MODULE_INIT_START
    SET_DESCRIPTION( "Main program" )
    ADD_CAPABILITY( MAIN, 100/*whatever*/ )
MODULE_INIT_STOP

MODULE_ACTIVATE_START
MODULE_ACTIVATE_STOP

MODULE_DEACTIVATE_START
MODULE_DEACTIVATE_STOP
gbazin's avatar
 
gbazin committed
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387

/* Hack for help options */
static module_t help_module;
static module_config_t p_help_config[] = {
    { MODULE_CONFIG_ITEM_BOOL, "help", "print help (or use -h)",
      NULL, NULL, 0, NULL, NULL, 0 },
    { MODULE_CONFIG_ITEM_BOOL, "longhelp", "print detailed help (or use -H)",
      NULL, NULL, 0, NULL, NULL, 0 },
    { MODULE_CONFIG_ITEM_BOOL, "list", "print a list of available plugins "
      "(or use -l)", NULL, NULL, 0, NULL, NULL, 0 },
    { MODULE_CONFIG_ITEM_STRING, "plugin", "print help on plugin (or use -p)",
      NULL, NULL, 0, NULL, &help_module.config_lock, 0 },
    { MODULE_CONFIG_ITEM_BOOL, "version", "print version information",
      NULL, NULL, 0, NULL, NULL, 0 },
    { MODULE_CONFIG_HINT_END, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 } };


gbazin's avatar
 
gbazin committed
388 389
/*****************************************************************************
 * End configuration.
390
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
391

392
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
393
 * Global variables - these are the only ones, see main.h and modules.h
394
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
395 396
main_t        *p_main;
module_bank_t *p_module_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
397
input_bank_t  *p_input_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
398 399
aout_bank_t   *p_aout_bank;
vout_bank_t   *p_vout_bank;
Michel Kaempf's avatar
Michel Kaempf committed
400

401
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
402
 * Local prototypes
403
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
static int  GetConfigurationFromFile    ( void ){return 0;};
static int  GetConfigurationFromCmdLine ( int *pi_argc, char *ppsz_argv[],
                                          boolean_t b_ignore_errors );
static int  GetFilenames                ( int i_argc, char *ppsz_argv[] );
static void Usage                       ( const char *psz_module_name );
static void ListModules                 ( void );
static void Version                     ( void );

static void InitSignalHandler           ( void );
static void SimpleSignalHandler         ( int i_signal );
static void FatalSignalHandler          ( int i_signal );
static void IllegalSignalHandler        ( int i_signal );
static u32  CPUCapabilities             ( void );

#ifdef WIN32
static void ShowConsole                 ( void );
#endif
gbazin's avatar
 
gbazin committed
421

422
static jmp_buf env;
Sam Hocevar's avatar
 
Sam Hocevar committed
423 424
static int     i_illegal;
static char   *psz_capability;
Sam Hocevar's avatar
 
Sam Hocevar committed
425

426
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
427
 * main: parse command line, start interface and spawn threads
428
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
429 430
 * Steps during program execution are:
 *      -configuration parsing and messages interface initialization
431
 *      -opening of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
432
 *      -execution of interface, which exit on error or on user request
Vincent Seguin's avatar
Vincent Seguin committed
433
 *      -closing of audio output device and some global modules
434
 * On error, the spawned threads are canceled, and the open devices closed.
435
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
436 437
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
Sam Hocevar's avatar
 
Sam Hocevar committed
438 439
    main_t        main_data;                /* root of all data - see main.h */
    module_bank_t module_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
440
    input_bank_t  input_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
441 442
    aout_bank_t   aout_bank;
    vout_bank_t   vout_bank;
gbazin's avatar
 
gbazin committed
443
    char *psz_plugin;
gbazin's avatar
 
gbazin committed
444
    char *p_tmp;
445

Sam Hocevar's avatar
 
Sam Hocevar committed
446 447
    p_main        = &main_data;               /* set up the global variables */
    p_module_bank = &module_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
448
    p_input_bank  = &input_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
449 450
    p_aout_bank   = &aout_bank;
    p_vout_bank   = &vout_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
451

gbazin's avatar
 
gbazin committed
452 453
    p_main->i_warning_level = 0;

Sam Hocevar's avatar
 
Sam Hocevar committed
454
#if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
Sam Hocevar's avatar
 
Sam Hocevar committed
455
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
456 457
     * Support for getext
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
458 459
#if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
    if( !setlocale( LC_MESSAGES, "" ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
460 461 462
    {
        fprintf( stderr, "warning: unsupported locale.\n" );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
463
#endif
Sam Hocevar's avatar
 
Sam Hocevar committed
464

Sam Hocevar's avatar
 
Sam Hocevar committed
465
    if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
466 467 468 469 470 471 472
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
                 PACKAGE, LOCALEDIR );
    }

    textdomain( PACKAGE );
#endif
Sam Hocevar's avatar
 
Sam Hocevar committed
473

Sam Hocevar's avatar
 
Sam Hocevar committed
474
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
475
     * Initialize threads system
Sam Hocevar's avatar
 
Sam Hocevar committed
476
     */
gbazin's avatar
 
gbazin committed
477
    vlc_threads_init();
Sam Hocevar's avatar
 
Sam Hocevar committed
478

Sam Hocevar's avatar
 
Sam Hocevar committed
479
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
480
     * Test if our code is likely to run on this CPU
Sam Hocevar's avatar
 
Sam Hocevar committed
481 482
     */
    p_main->i_cpu_capabilities = CPUCapabilities();
Sam Hocevar's avatar
 
Sam Hocevar committed
483

Sam Hocevar's avatar
 
Sam Hocevar committed
484 485 486
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
487
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
Sam Hocevar's avatar
 
Sam Hocevar committed
488
    system_Init( &i_argc, ppsz_argv, ppsz_env );
489 490 491 492

#elif defined( SYS_LINUX )
#   ifdef DEBUG
    /* Activate malloc checking routines to detect heap corruptions. */
gbazin's avatar
 
gbazin committed
493
    putenv( "MALLOC_CHECK_=2" );
Sam Hocevar's avatar
 
Sam Hocevar committed
494
    putenv( "GNOME_DISABLE_CRASH_DIALOG=1" );
495
#   endif
496
#endif
497 498 499 500

    /*
     * Initialize messages interface
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
501
    intf_MsgCreate();
502

Sam Hocevar's avatar
 
Sam Hocevar committed
503
    intf_Msg( COPYRIGHT_MESSAGE "\n" );
Sam Hocevar's avatar
 
Sam Hocevar committed
504

gbazin's avatar
 
gbazin committed
505 506 507 508 509 510 511 512 513

    /* Get the executable name (similar to the basename command) */
    p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
    while( *p_tmp )
    {
        if( *p_tmp == '/' ) p_main->psz_arg0 = ++p_tmp;
        else ++p_tmp;
    }

514
    /*
gbazin's avatar
 
gbazin committed
515 516 517
     * Initialize the module bank and and load the configuration of the main
     * module. We need to do this at this stage to be able to display a short
     * help if required by the user. (short help == main module options)
518
     */
gbazin's avatar
 
gbazin committed
519 520 521
    module_InitBank();
    module_LoadMain();

gbazin's avatar
 
gbazin committed
522 523 524 525 526 527 528 529 530 531 532
    /* Hack: insert the help module here */
    help_module.psz_name = "help";
    help_module.i_config_lines = sizeof(p_help_config) /
                                     sizeof(module_config_t);
    help_module.i_config_items = help_module.i_config_lines - 1;
    vlc_mutex_init( &help_module.config_lock );
    help_module.p_config = p_help_config;
    help_module.next = p_module_bank->first;
    p_module_bank->first = &help_module;
    /* end hack */

gbazin's avatar
 
gbazin committed
533
    if( GetConfigurationFromCmdLine( &i_argc, ppsz_argv, 1 ) )
Michel Kaempf's avatar
Michel Kaempf committed
534
    {
Vincent Seguin's avatar
Vincent Seguin committed
535
        intf_MsgDestroy();
536
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
537
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
538

gbazin's avatar
 
gbazin committed
539 540 541
    /* Check for short help option */
    if( config_GetIntVariable( "help" ) )
    {
gbazin's avatar
 
gbazin committed
542 543 544 545
        intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
                  p_main->psz_arg0 );

        Usage( "help" );
gbazin's avatar
 
gbazin committed
546 547 548 549 550 551 552 553 554 555 556
        Usage( "main" );
        return( -1 );
    }

    /* Check for version option */
    if( config_GetIntVariable( "version" ) )
    {
        Version();
        return( -1 );
    }

gbazin's avatar
 
gbazin committed
557 558 559 560
    /* Hack: remove the help module here */
    p_module_bank->first = help_module.next;
    /* end hack */

gbazin's avatar
 
gbazin committed
561
    /*
gbazin's avatar
 
gbazin committed
562 563 564 565
     * Load the builtins and plugins into the module_bank.
     * We have to do it before GetConfiguration() because this also gets the
     * list of configuration options exported by each plugin and loads their
     * default values.
gbazin's avatar
 
gbazin committed
566
     */
gbazin's avatar
 
gbazin committed
567 568 569 570 571
    module_LoadBuiltins();
    module_LoadPlugins();
    intf_WarnMsg( 2, "module: module bank initialized, found %i modules",
                  p_module_bank->i_count );

gbazin's avatar
 
gbazin committed
572 573 574 575 576
    /* Hack: insert the help module here */
    help_module.next = p_module_bank->first;
    p_module_bank->first = &help_module;
    /* end hack */

gbazin's avatar
 
gbazin committed
577
    /* Check for help on plugins */
gbazin's avatar
 
gbazin committed
578
    if( (p_tmp = config_GetPszVariable( "plugin" )) )
gbazin's avatar
 
gbazin committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
    {
        Usage( p_tmp );
        free( p_tmp );
        return( -1 );
    }

    /* Check for long help option */
    if( config_GetIntVariable( "longhelp" ) )
    {
        Usage( NULL );
        return( -1 );
    }

    /* Check for plugin list option */
    if( config_GetIntVariable( "list" ) )
    {
        ListModules();
        return( -1 );
    }

gbazin's avatar
 
gbazin committed
599 600 601 602 603
    /* Hack: remove the help module here */
    p_module_bank->first = help_module.next;
    /* end hack */


gbazin's avatar
 
gbazin committed
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
    /*
     * Override default configuration with config file settings
     */
    if( GetConfigurationFromFile() )
    {
        intf_MsgDestroy();
        return( errno );
    }

    /*
     * Override configuration with command line settings
     */
    if( GetConfigurationFromCmdLine( &i_argc, ppsz_argv, 0 ) )
    {
        intf_MsgDestroy();
        return( errno );
    }

    /* p_main inititalization. FIXME ? */
gbazin's avatar
 
gbazin committed
623
    p_main->i_desync = (mtime_t)config_GetIntVariable( "desync" )
gbazin's avatar
 
gbazin committed
624
      * (mtime_t)1000;
gbazin's avatar
 
gbazin committed
625 626 627 628 629
    p_main->b_stats = config_GetIntVariable( "stats" );
    p_main->b_audio = !config_GetIntVariable( "noaudio" );
    p_main->b_stereo= !config_GetIntVariable( "mono" );
    p_main->b_video = !config_GetIntVariable( "novideo" );
    if( config_GetIntVariable( "nommx" ) )
gbazin's avatar
 
gbazin committed
630
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMX;
gbazin's avatar
 
gbazin committed
631
    if( config_GetIntVariable( "no3dn" ) )
gbazin's avatar
 
gbazin committed
632
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_3DNOW;
gbazin's avatar
 
gbazin committed
633
    if( config_GetIntVariable( "nommxext" ) )
gbazin's avatar
 
gbazin committed
634
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMXEXT;
gbazin's avatar
 
gbazin committed
635
    if( config_GetIntVariable( "nosse" ) )
gbazin's avatar
 
gbazin committed
636
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_SSE;
gbazin's avatar
 
gbazin committed
637
    if( config_GetIntVariable( "noaltivec" ) )
gbazin's avatar
 
gbazin committed
638 639 640
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_ALTIVEC;


641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
    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" );
Sam Hocevar's avatar
 
Sam Hocevar committed
662
        PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
Sam Hocevar's avatar
 
Sam Hocevar committed
663
        intf_StatMsg( "info: CPU has capabilities : %s", p_capabilities );
664 665
    }

666
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
667
     * Initialize playlist and get commandline files
668
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
669
    p_main->p_playlist = intf_PlaylistCreate();
Sam Hocevar's avatar
 
Sam Hocevar committed
670
    if( !p_main->p_playlist )
671
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
672
        intf_ErrMsg( "playlist error: playlist initialization failed" );
673 674
        intf_MsgDestroy();
        return( errno );
675
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
676
    intf_PlaylistInit( p_main->p_playlist );
677 678

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
679
     * Get input filenames given as commandline arguments
680
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
681
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
682

Sam Hocevar's avatar
 
Sam Hocevar committed
683
    /*
gbazin's avatar
 
gbazin committed
684
     * Initialize input, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
685
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
686
    input_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
687 688
    aout_InitBank();
    vout_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
689

Sam Hocevar's avatar
 
Sam Hocevar committed
690 691 692
    /*
     * Choose the best memcpy module
     */
gbazin's avatar
 
gbazin committed
693
    psz_plugin = config_GetPszVariable( "memcpy" );
Sam Hocevar's avatar
 
Sam Hocevar committed
694
    p_main->p_memcpy_module = module_Need( MODULE_CAPABILITY_MEMCPY, NULL,
gbazin's avatar
 
gbazin committed
695 696
                                           psz_plugin );
    if( psz_plugin ) free( psz_plugin );
Sam Hocevar's avatar
 
Sam Hocevar committed
697
    if( p_main->p_memcpy_module == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
698 699 700
    {
        intf_ErrMsg( "intf error: no suitable memcpy module, "
                     "using libc default" );
Sam Hocevar's avatar
 
Sam Hocevar committed
701 702 703 704 705 706
        p_main->pf_memcpy = memcpy;
    }
    else
    {
        p_main->pf_memcpy = p_main->p_memcpy_module->p_functions
                                  ->memcpy.functions.memcpy.pf_memcpy;
Sam Hocevar's avatar
 
Sam Hocevar committed
707
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
708

Michel Kaempf's avatar
Michel Kaempf committed
709 710 711
    /*
     * Initialize shared resources and libraries
     */
gbazin's avatar
 
gbazin committed
712
    if( config_GetIntVariable( "network_channel" ) &&
713
        network_ChannelCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
714
    {
Henri Fallon's avatar
 
Henri Fallon committed
715
        /* On error during Channels initialization, switch off channels */
Sam Hocevar's avatar
 
Sam Hocevar committed
716 717
        intf_ErrMsg( "intf error: channels initialization failed, " 
                                 "deactivating channels" );
gbazin's avatar
 
gbazin committed
718
        config_PutIntVariable( "network_channel", 0 );
Michel Kaempf's avatar
Michel Kaempf committed
719
    }
720

Michel Kaempf's avatar
Michel Kaempf committed
721
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
722
     * Try to run the interface
Michel Kaempf's avatar
Michel Kaempf committed
723
     */
724
    p_main->p_intf = intf_Create();
Sam Hocevar's avatar
 
Sam Hocevar committed
725
    if( p_main->p_intf == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
726 727 728
    {
        intf_ErrMsg( "intf error: interface initialization failed" );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
729
    else
730
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
        /*
         * 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
         */
gbazin's avatar
 
gbazin committed
749
        if( config_GetIntVariable( "network_channel" ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
750 751 752
        {
            network_ChannelJoin( COMMON_CHANNEL );
        }
753
    }
Michel Kaempf's avatar
Michel Kaempf committed
754

Sam Hocevar's avatar
 
Sam Hocevar committed
755
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
756
     * Free input, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
757
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
758
    input_EndBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
759 760 761 762 763 764 765 766
    vout_EndBank();
    aout_EndBank();

    /*
     * Free playlist
     */
    intf_PlaylistDestroy( p_main->p_playlist );

Sam Hocevar's avatar
 
Sam Hocevar committed
767
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
768
     * Free memcpy module if it was allocated
Sam Hocevar's avatar
 
Sam Hocevar committed
769
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
770
    if( p_main->p_memcpy_module != NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
771
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
772
        module_Unneed( p_main->p_memcpy_module );
Sam Hocevar's avatar
 
Sam Hocevar committed
773
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
774

Sam Hocevar's avatar
 
Sam Hocevar committed
775
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
776
     * Free module bank
Sam Hocevar's avatar
 
Sam Hocevar committed
777
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
778
    module_EndBank();
779 780 781 782

    /*
     * System specific cleaning code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
783
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
Sam Hocevar's avatar
 
Sam Hocevar committed
784
    system_End();
785 786
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
787

Michel Kaempf's avatar
Michel Kaempf committed
788 789 790
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
791
    intf_WarnMsg( 1, "intf: program terminated" );
Vincent Seguin's avatar
Vincent Seguin committed
792
    intf_MsgDestroy();
793

Sam Hocevar's avatar
 
Sam Hocevar committed
794 795 796 797
    /*
     * Stop threads system
     */
    vlc_threads_end( );
Sam Hocevar's avatar
 
Sam Hocevar committed
798

Sam Hocevar's avatar
 
Sam Hocevar committed
799
    return 0;
Michel Kaempf's avatar
Michel Kaempf committed
800 801
}

Vincent Seguin's avatar
Vincent Seguin committed
802

gbazin's avatar
 
gbazin committed
803
/* following functions are local */
804

805
/*****************************************************************************
gbazin's avatar
 
gbazin committed
806
 * GetConfigurationFromCmdLine: parse command line
807
 *****************************************************************************
gbazin's avatar
 
gbazin committed
808 809 810 811 812 813 814
 * Parse command line for configuration. If the inline help is requested, the
 * function Usage() is called and the function returns -1 (causing main() to
 * exit).
 * Now that the module_bank has been initialized, we can dynamically
 * generate the longopts structure used by getops. We have to do it this way
 * because we don't know (and don't want to know) in advance the configuration
 * options used (ie. exported) by each module.
815
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
816 817
static int GetConfigurationFromCmdLine( int *pi_argc, char *ppsz_argv[],
                                        boolean_t b_ignore_errors )
818
{
gbazin's avatar
 
gbazin committed
819 820 821
    int i_cmd, i, i_index, i_longopts_size;
    module_t *p_module;
    struct option *p_longopts;
822

gbazin's avatar
 
gbazin committed
823
    /* Short options */
gbazin's avatar
 
gbazin committed
824
    const char *psz_shortopts = "hHvlp:";
Michel Kaempf's avatar
Michel Kaempf committed
825 826

    /* Set default configuration and copy arguments */
Sam Hocevar's avatar
 
Sam Hocevar committed
827
    p_main->i_argc    = *pi_argc;
Vincent Seguin's avatar
Vincent Seguin committed
828
    p_main->ppsz_argv = ppsz_argv;
Michel Kaempf's avatar
Michel Kaempf committed
829

830 831
    p_main->p_channel = NULL;

Sam Hocevar's avatar
 
Sam Hocevar committed
832
#ifdef SYS_DARWIN
Sam Hocevar's avatar
 
Sam Hocevar committed
833 834 835
    /* 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
836 837
    if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
                                        /* for example -psn_0_9306113 */
838
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
839 840 841 842 843 844 845 846 847
        /* 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--;
848 849 850 851
        return( 0 );
    }
#endif

gbazin's avatar
 
gbazin committed
852 853 854 855 856

    /*
     * Generate the longopts structure used by getopt_long
     */
    i_longopts_size = 0;
gbazin's avatar
 
gbazin committed
857
    for( p_module = p_module_bank->first;
gbazin's avatar
 
gbazin committed
858 859 860 861
         p_module != NULL ;
         p_module = p_module->next )
    {
        /* count the number of exported configuration options (to allocate
gbazin's avatar
 
gbazin committed
862 863
         * longopts). */
        i_longopts_size += p_module->i_config_items;
gbazin's avatar
 
gbazin committed
864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
    }

    p_longopts = (struct option *)malloc( sizeof(struct option)
                                          * (i_longopts_size + 1) );
    if( p_longopts == NULL )
    {
        intf_ErrMsg( "GetConfigurationFromCmdLine error: "
                     "can't allocate p_longopts" );
        return( -1 );
    }

    /* Fill the longopts structure */
    i_index = 0;
    for( p_module = p_module_bank->first ;
         p_module != NULL ;
         p_module = p_module->next )
    {
gbazin's avatar
 
gbazin committed
881
        for( i = 0; i < p_module->i_config_lines; i++ )
gbazin's avatar
 
gbazin committed
882
        {
gbazin's avatar
 
gbazin committed
883 884 885
            if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
                /* ignore hints */
                continue;
gbazin's avatar
 
gbazin committed
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
            p_longopts[i_index].name = p_module->p_config[i].psz_name;
            p_longopts[i_index].has_arg =
                (p_module->p_config[i].i_type == MODULE_CONFIG_ITEM_BOOL)?
                                               no_argument : required_argument;
            p_longopts[i_index].flag = 0;
            p_longopts[i_index].val = 0;
            i_index++;
        }
    }
    /* Close the longopts structure */
    memset( &p_longopts[i_index], 0, sizeof(struct option) );


    /*
     * Parse the command line options
     */
Michel Kaempf's avatar
Michel Kaempf committed
902
    opterr = 0;
gbazin's avatar
 
gbazin committed
903 904 905
    optind = 1;
    while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv, psz_shortopts,
                                  p_longopts, &i_index ) ) != EOF )
Michel Kaempf's avatar
Michel Kaempf committed
906
    {
gbazin's avatar
 
gbazin committed
907 908 909 910 911

        if( i_cmd == 0 )
        {
            /* A long option has been recognized */

Sam Hocevar's avatar
 
Sam Hocevar committed
912
            module_config_t *p_conf;
gbazin's avatar
 
gbazin committed
913 914

            /* Store the configuration option */
Sam Hocevar's avatar
 
Sam Hocevar committed
915
            p_conf = config_FindConfig( p_longopts[i_index].name );
gbazin's avatar
 
gbazin committed
916

Sam Hocevar's avatar
 
Sam Hocevar committed
917
            switch( p_conf->i_type )
gbazin's avatar
 
gbazin committed
918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935
            {
            case MODULE_CONFIG_ITEM_STRING:
            case MODULE_CONFIG_ITEM_FILE:
            case MODULE_CONFIG_ITEM_PLUGIN:
                config_PutPszVariable( p_longopts[i_index].name, optarg );
                break;
            case MODULE_CONFIG_ITEM_INTEGER:
                config_PutIntVariable( p_longopts[i_index].name, atoi(optarg));
                break;
            case MODULE_CONFIG_ITEM_BOOL:
                config_PutIntVariable( p_longopts[i_index].name, 1 );
                break;
            }

            continue;
        }

        /* short options handled here for now */
Sam Hocevar's avatar
 
Sam Hocevar committed
936
        switch( i_cmd )
Michel Kaempf's avatar
Michel Kaempf committed
937
        {
gbazin's avatar
 
gbazin committed
938

939 940
        /* General/common options */
        case 'h':                                              /* -h, --help */
gbazin's avatar
 
gbazin committed
941
            config_PutIntVariable( "help", 1 );
942
            break;
943
        case 'H':                                          /* -H, --longhelp */
gbazin's avatar
 
gbazin committed
944
            config_PutIntVariable( "longhelp", 1 );
Michel Kaempf's avatar
Michel Kaempf committed
945
            break;
gbazin's avatar
 
gbazin committed
946 947
        case 'l':                                              /* -l, --list */
            config_PutIntVariable( "list", 1 );
948
            break;
gbazin's avatar
 
gbazin committed
949 950 951
        case 'p':                                            /* -p, --plugin */
            config_PutPszVariable( "plugin", optarg );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
952
        case 'v':                                           /* -v, --verbose */
953
            p_main->i_warning_level++;
Sam Hocevar's avatar
 
Sam Hocevar committed
954
            break;
Michel Kaempf's avatar
Michel Kaempf committed
955 956

        /* Internal error: unknown option */
957
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
958
        default:
gbazin's avatar
 
gbazin committed
959

gbazin's avatar
 
gbazin committed
960 961 962
            if( !b_ignore_errors )
            {
                intf_ErrMsg( "intf error: unknown option `%s'",
Stéphane Borel's avatar
 
Stéphane Borel committed
963
                             ppsz_argv[optind-1] );
gbazin's avatar
 
gbazin committed
964 965 966
                intf_Msg( "Try `%s --help' for more information.\n",
                          p_main->psz_arg0 );

gbazin's avatar
 
gbazin committed
967
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
gbazin's avatar
 
gbazin committed
968 969
                intf_Msg( "\nPress the RETURN key to continue..." );
                getchar();
gbazin's avatar
 
gbazin committed
970
#endif
gbazin's avatar
 
gbazin committed
971 972 973
                free( p_longopts );
                return( EINVAL );
            }
Michel Kaempf's avatar
Michel Kaempf committed
974
        }
gbazin's avatar
 
gbazin committed
975

Michel Kaempf's avatar
Michel Kaempf committed
976
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
977 978 979 980 981 982

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

gbazin's avatar
 
gbazin committed
983
    free( p_longopts );
Sam Hocevar's avatar
 
Sam Hocevar committed
984 985 986 987 988 989 990 991 992 993 994
    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
995

Sam Hocevar's avatar
 
Sam Hocevar committed
996
    /* We assume that the remaining parameters are filenames */
Vincent Seguin's avatar
Vincent Seguin committed
997 998
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
999 1000
        intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
                          ppsz_argv[ i_opt ] );
Vincent Seguin's avatar
Vincent Seguin committed
1001
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
1002

Michel Kaempf's avatar
Michel Kaempf committed
1003 1004 1005
    return( 0 );
}

1006
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
1007
 * Usage: print program usage
1008
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
1009
 * Print a short inline help. Message interface is initialized at this stage.
1010
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
1011
static void Usage( const char *psz_module_name )
Michel Kaempf's avatar
Michel Kaempf committed
1012
{
gbazin's avatar
 
gbazin committed
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
    int i;
    module_t *p_module;
    char psz_spaces[30];

    memset( psz_spaces, 32, 30 );

#ifdef WIN32
    ShowConsole();
#endif

    /* Enumerate the config of each module */
    for( p_module = p_module_bank->first ;
         p_module != NULL ;
         p_module = p_module->next )
1027
    {
gbazin's avatar
 
gbazin committed
1028 1029 1030 1031

        if( psz_module_name && strcmp( psz_module_name, p_module->psz_name ) )
            continue;

gbazin's avatar
 
gbazin committed
1032 1033 1034
        /* ignore plugins without config options */
        if( !p_module->i_config_items ) continue;

gbazin's avatar
 
gbazin committed
1035
        /* print module name */
gbazin's avatar
 
gbazin committed
1036
        intf_Msg( "%s options:\n", p_module->psz_name );
gbazin's avatar
 
gbazin committed
1037

gbazin's avatar
 
gbazin committed
1038
        for( i = 0; i < p_module->i_config_lines; i++ )
gbazin's avatar
 
gbazin committed
1039 1040 1041 1042 1043
        {
            int j;

            switch( p_module->p_config[i].i_type )
            {
gbazin's avatar
 
gbazin committed
1044
            case MODULE_CONFIG_HINT_CATEGORY:
gbazin's avatar
 
gbazin committed
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
                intf_Msg( " %s", p_module->p_config[i].psz_text );
                break;

            case MODULE_CONFIG_ITEM_STRING: