main.c 49 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
gbazin's avatar
 
gbazin committed
7
 * $Id: main.c,v 1.162 2002/03/11 07:23:10 gbazin 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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 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

#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"
#define VOLUME_LONGTEXT "You can set the default audio output volume here"

#define RATE_TEXT "audio output frequency"
#define RATE_LONGTEXT "You can force the audio output frequency here"

#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
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
/* 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
271 272 273 274 275 276 277 278 279 280 281 282 283 284
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 )
gbazin's avatar
 
gbazin committed
285 286

/* Video options */
gbazin's avatar
 
gbazin committed
287 288 289 290 291 292 293 294 295 296 297
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
298 299

/* Input options */
gbazin's avatar
 
gbazin committed
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
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 )
ADD_INTEGER ( "input channel", -1, NULL, INPUT_CHAN_TEXT, INPUT_CHAN_LONGTEXT )
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
316 317

/* Decoder options */
gbazin's avatar
 
gbazin committed
318 319 320 321 322
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
323 324

/* CPU options */
gbazin's avatar
 
gbazin committed
325 326 327 328 329 330
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
331 332

/* Playlist options */
gbazin's avatar
 
gbazin committed
333 334 335 336
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
337 338

/* Misc options */
gbazin's avatar
 
gbazin committed
339 340
ADD_CATEGORY_HINT( "Miscellaneous", NULL )
ADD_PLUGIN  ( "memcpy", MODULE_CAPABILITY_MEMCPY, NULL, NULL, MEMCPY_TEXT, MEMCPY_LONGTEXT )
gbazin's avatar
 
gbazin committed
341 342 343 344 345 346 347 348 349 350 351 352 353

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
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370

/* 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
371 372
/*****************************************************************************
 * End configuration.
373
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
374

375
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
376
 * Global variables - these are the only ones, see main.h and modules.h
377
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
378 379
main_t        *p_main;
module_bank_t *p_module_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
380
input_bank_t  *p_input_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
381 382
aout_bank_t   *p_aout_bank;
vout_bank_t   *p_vout_bank;
Michel Kaempf's avatar
Michel Kaempf committed
383

384
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
385
 * Local prototypes
386
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
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
404

405
static jmp_buf env;
Sam Hocevar's avatar
 
Sam Hocevar committed
406 407
static int     i_illegal;
static char   *psz_capability;
Sam Hocevar's avatar
 
Sam Hocevar committed
408

409
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
410
 * main: parse command line, start interface and spawn threads
411
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
412 413
 * Steps during program execution are:
 *      -configuration parsing and messages interface initialization
414
 *      -opening of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
415
 *      -execution of interface, which exit on error or on user request
Vincent Seguin's avatar
Vincent Seguin committed
416
 *      -closing of audio output device and some global modules
417
 * On error, the spawned threads are canceled, and the open devices closed.
418
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
419 420
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
Sam Hocevar's avatar
 
Sam Hocevar committed
421 422
    main_t        main_data;                /* root of all data - see main.h */
    module_bank_t module_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
423
    input_bank_t  input_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
424 425
    aout_bank_t   aout_bank;
    vout_bank_t   vout_bank;
gbazin's avatar
 
gbazin committed
426
    char *psz_plugin;
gbazin's avatar
 
gbazin committed
427
    char *p_tmp;
428

Sam Hocevar's avatar
 
Sam Hocevar committed
429 430
    p_main        = &main_data;               /* set up the global variables */
    p_module_bank = &module_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
431
    p_input_bank  = &input_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
432 433
    p_aout_bank   = &aout_bank;
    p_vout_bank   = &vout_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
434

gbazin's avatar
 
gbazin committed
435 436
    p_main->i_warning_level = 0;

Sam Hocevar's avatar
 
Sam Hocevar committed
437
#if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
Sam Hocevar's avatar
 
Sam Hocevar committed
438
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
439 440
     * Support for getext
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
441 442
#if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
    if( !setlocale( LC_MESSAGES, "" ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
443 444 445
    {
        fprintf( stderr, "warning: unsupported locale.\n" );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
446
#endif
Sam Hocevar's avatar
 
Sam Hocevar committed
447

Sam Hocevar's avatar
 
Sam Hocevar committed
448
    if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
449 450 451 452 453 454 455
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
                 PACKAGE, LOCALEDIR );
    }

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

Sam Hocevar's avatar
 
Sam Hocevar committed
457
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
458
     * Initialize threads system
Sam Hocevar's avatar
 
Sam Hocevar committed
459
     */
gbazin's avatar
 
gbazin committed
460
    vlc_threads_init();
Sam Hocevar's avatar
 
Sam Hocevar committed
461

Sam Hocevar's avatar
 
Sam Hocevar committed
462
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
463
     * Test if our code is likely to run on this CPU
Sam Hocevar's avatar
 
Sam Hocevar committed
464 465
     */
    p_main->i_cpu_capabilities = CPUCapabilities();
Sam Hocevar's avatar
 
Sam Hocevar committed
466

Sam Hocevar's avatar
 
Sam Hocevar committed
467 468 469
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
470
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
Sam Hocevar's avatar
 
Sam Hocevar committed
471
    system_Init( &i_argc, ppsz_argv, ppsz_env );
472 473 474 475

#elif defined( SYS_LINUX )
#   ifdef DEBUG
    /* Activate malloc checking routines to detect heap corruptions. */
gbazin's avatar
 
gbazin committed
476
    putenv( "MALLOC_CHECK_=2" );
Sam Hocevar's avatar
 
Sam Hocevar committed
477
    putenv( "GNOME_DISABLE_CRASH_DIALOG=1" );
478
#   endif
479
#endif
480 481 482 483

    /*
     * Initialize messages interface
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
484
    intf_MsgCreate();
485

Sam Hocevar's avatar
 
Sam Hocevar committed
486
    intf_Msg( COPYRIGHT_MESSAGE "\n" );
Sam Hocevar's avatar
 
Sam Hocevar committed
487

gbazin's avatar
 
gbazin committed
488 489 490 491 492 493 494 495 496

    /* 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;
    }

497
    /*
gbazin's avatar
 
gbazin committed
498 499 500
     * 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)
501
     */
gbazin's avatar
 
gbazin committed
502 503 504
    module_InitBank();
    module_LoadMain();

gbazin's avatar
 
gbazin committed
505 506 507 508 509 510 511 512 513 514 515
    /* 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
516
    if( GetConfigurationFromCmdLine( &i_argc, ppsz_argv, 1 ) )
Michel Kaempf's avatar
Michel Kaempf committed
517
    {
Vincent Seguin's avatar
Vincent Seguin committed
518
        intf_MsgDestroy();
519
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
520
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
521

gbazin's avatar
 
gbazin committed
522 523 524
    /* Check for short help option */
    if( config_GetIntVariable( "help" ) )
    {
gbazin's avatar
 
gbazin committed
525 526 527 528
        intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
                  p_main->psz_arg0 );

        Usage( "help" );
gbazin's avatar
 
gbazin committed
529 530 531 532 533 534 535 536 537 538 539
        Usage( "main" );
        return( -1 );
    }

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

gbazin's avatar
 
gbazin committed
540 541 542 543
    /* Hack: remove the help module here */
    p_module_bank->first = help_module.next;
    /* end hack */

gbazin's avatar
 
gbazin committed
544
    /*
gbazin's avatar
 
gbazin committed
545 546 547 548
     * 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
549
     */
gbazin's avatar
 
gbazin committed
550 551 552 553 554
    module_LoadBuiltins();
    module_LoadPlugins();
    intf_WarnMsg( 2, "module: module bank initialized, found %i modules",
                  p_module_bank->i_count );

gbazin's avatar
 
gbazin committed
555 556 557 558 559
    /* 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
560
    /* Check for help on plugins */
gbazin's avatar
 
gbazin committed
561
    if( (p_tmp = config_GetPszVariable( "plugin" )) )
gbazin's avatar
 
gbazin committed
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
    {
        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
582 583 584 585 586
    /* Hack: remove the help module here */
    p_module_bank->first = help_module.next;
    /* end hack */


gbazin's avatar
 
gbazin committed
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
    /*
     * 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
606
    p_main->i_desync = (mtime_t)config_GetIntVariable( "desync" )
gbazin's avatar
 
gbazin committed
607
      * (mtime_t)1000;
gbazin's avatar
 
gbazin committed
608 609 610 611 612
    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
613
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMX;
gbazin's avatar
 
gbazin committed
614
    if( config_GetIntVariable( "no3dn" ) )
gbazin's avatar
 
gbazin committed
615
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_3DNOW;
gbazin's avatar
 
gbazin committed
616
    if( config_GetIntVariable( "nommxext" ) )
gbazin's avatar
 
gbazin committed
617
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMXEXT;
gbazin's avatar
 
gbazin committed
618
    if( config_GetIntVariable( "nosse" ) )
gbazin's avatar
 
gbazin committed
619
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_SSE;
gbazin's avatar
 
gbazin committed
620
    if( config_GetIntVariable( "noaltivec" ) )
gbazin's avatar
 
gbazin committed
621 622 623
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_ALTIVEC;


624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
    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
645
        PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
Sam Hocevar's avatar
 
Sam Hocevar committed
646
        intf_StatMsg( "info: CPU has capabilities : %s", p_capabilities );
647 648
    }

649
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
650
     * Initialize playlist and get commandline files
651
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
652
    p_main->p_playlist = intf_PlaylistCreate();
Sam Hocevar's avatar
 
Sam Hocevar committed
653
    if( !p_main->p_playlist )
654
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
655
        intf_ErrMsg( "playlist error: playlist initialization failed" );
656 657
        intf_MsgDestroy();
        return( errno );
658
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
659
    intf_PlaylistInit( p_main->p_playlist );
660 661

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
662
     * Get input filenames given as commandline arguments
663
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
664
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
665

Sam Hocevar's avatar
 
Sam Hocevar committed
666
    /*
gbazin's avatar
 
gbazin committed
667
     * Initialize input, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
668
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
669
    input_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
670 671
    aout_InitBank();
    vout_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
672

Sam Hocevar's avatar
 
Sam Hocevar committed
673 674 675
    /*
     * Choose the best memcpy module
     */
gbazin's avatar
 
gbazin committed
676
    psz_plugin = config_GetPszVariable( "memcpy" );
Sam Hocevar's avatar
 
Sam Hocevar committed
677
    p_main->p_memcpy_module = module_Need( MODULE_CAPABILITY_MEMCPY, NULL,
gbazin's avatar
 
gbazin committed
678 679
                                           psz_plugin );
    if( psz_plugin ) free( psz_plugin );
Sam Hocevar's avatar
 
Sam Hocevar committed
680
    if( p_main->p_memcpy_module == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
681 682 683
    {
        intf_ErrMsg( "intf error: no suitable memcpy module, "
                     "using libc default" );
Sam Hocevar's avatar
 
Sam Hocevar committed
684 685 686 687 688 689
        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
690
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
691

Michel Kaempf's avatar
Michel Kaempf committed
692 693 694
    /*
     * Initialize shared resources and libraries
     */
gbazin's avatar
 
gbazin committed
695
    if( config_GetIntVariable( "network_channel" ) &&
696
        network_ChannelCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
697
    {
Henri Fallon's avatar
 
Henri Fallon committed
698
        /* On error during Channels initialization, switch off channels */
Sam Hocevar's avatar
 
Sam Hocevar committed
699 700
        intf_ErrMsg( "intf error: channels initialization failed, " 
                                 "deactivating channels" );
gbazin's avatar
 
gbazin committed
701
        config_PutIntVariable( "network_channel", 0 );
Michel Kaempf's avatar
Michel Kaempf committed
702
    }
703

Michel Kaempf's avatar
Michel Kaempf committed
704
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
705
     * Try to run the interface
Michel Kaempf's avatar
Michel Kaempf committed
706
     */
707
    p_main->p_intf = intf_Create();
Sam Hocevar's avatar
 
Sam Hocevar committed
708
    if( p_main->p_intf == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
709 710 711
    {
        intf_ErrMsg( "intf error: interface initialization failed" );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
712
    else
713
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
        /*
         * 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
732
        if( config_GetIntVariable( "network_channel" ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
733 734 735
        {
            network_ChannelJoin( COMMON_CHANNEL );
        }
736
    }
Michel Kaempf's avatar
Michel Kaempf committed
737

Sam Hocevar's avatar
 
Sam Hocevar committed
738
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
739
     * Free input, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
740
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
741
    input_EndBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
742 743 744 745 746 747 748 749
    vout_EndBank();
    aout_EndBank();

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

Sam Hocevar's avatar
 
Sam Hocevar committed
750
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
751
     * Free memcpy module if it was allocated
Sam Hocevar's avatar
 
Sam Hocevar committed
752
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
753
    if( p_main->p_memcpy_module != NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
754
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
755
        module_Unneed( p_main->p_memcpy_module );
Sam Hocevar's avatar
 
Sam Hocevar committed
756
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
757

Sam Hocevar's avatar
 
Sam Hocevar committed
758
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
759
     * Free module bank
Sam Hocevar's avatar
 
Sam Hocevar committed
760
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
761
    module_EndBank();
762 763 764 765

    /*
     * System specific cleaning code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
766
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
Sam Hocevar's avatar
 
Sam Hocevar committed
767
    system_End();
768 769
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
770

Michel Kaempf's avatar
Michel Kaempf committed
771 772 773
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
774
    intf_WarnMsg( 1, "intf: program terminated" );
Vincent Seguin's avatar
Vincent Seguin committed
775
    intf_MsgDestroy();
776

Sam Hocevar's avatar
 
Sam Hocevar committed
777 778 779 780
    /*
     * Stop threads system
     */
    vlc_threads_end( );
Sam Hocevar's avatar
 
Sam Hocevar committed
781

Sam Hocevar's avatar
 
Sam Hocevar committed
782
    return 0;
Michel Kaempf's avatar
Michel Kaempf committed
783 784
}

Vincent Seguin's avatar
Vincent Seguin committed
785

gbazin's avatar
 
gbazin committed
786
/* following functions are local */
787

788
/*****************************************************************************
gbazin's avatar
 
gbazin committed
789
 * GetConfigurationFromCmdLine: parse command line
790
 *****************************************************************************
gbazin's avatar
 
gbazin committed
791 792 793 794 795 796 797
 * 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.
798
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
799 800
static int GetConfigurationFromCmdLine( int *pi_argc, char *ppsz_argv[],
                                        boolean_t b_ignore_errors )
801
{
gbazin's avatar
 
gbazin committed
802 803 804
    int i_cmd, i, i_index, i_longopts_size;
    module_t *p_module;
    struct option *p_longopts;
805

gbazin's avatar
 
gbazin committed
806
    /* Short options */
gbazin's avatar
 
gbazin committed
807
    const char *psz_shortopts = "hHvlp:";
Michel Kaempf's avatar
Michel Kaempf committed
808 809

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

813 814
    p_main->p_channel = NULL;

Sam Hocevar's avatar
 
Sam Hocevar committed
815
#ifdef SYS_DARWIN
Sam Hocevar's avatar
 
Sam Hocevar committed
816 817 818
    /* 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
819 820
    if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
                                        /* for example -psn_0_9306113 */
821
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
822 823 824 825 826 827 828 829 830
        /* 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--;
831 832 833 834
        return( 0 );
    }
#endif

gbazin's avatar
 
gbazin committed
835 836 837 838 839

    /*
     * Generate the longopts structure used by getopt_long
     */
    i_longopts_size = 0;
gbazin's avatar
 
gbazin committed
840
    for( p_module = p_module_bank->first;
gbazin's avatar
 
gbazin committed
841 842 843 844
         p_module != NULL ;
         p_module = p_module->next )
    {
        /* count the number of exported configuration options (to allocate
gbazin's avatar
 
gbazin committed
845 846
         * longopts). */
        i_longopts_size += p_module->i_config_items;
gbazin's avatar
 
gbazin committed
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
    }

    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
864
        for( i = 0; i < p_module->i_config_lines; i++ )
gbazin's avatar
 
gbazin committed
865
        {
gbazin's avatar
 
gbazin committed
866 867 868
            if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
                /* ignore hints */
                continue;
gbazin's avatar
 
gbazin committed
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
            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
885
    opterr = 0;
gbazin's avatar
 
gbazin committed
886 887 888
    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
889
    {
gbazin's avatar
 
gbazin committed
890 891 892 893 894

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

Sam Hocevar's avatar
 
Sam Hocevar committed
895
            module_config_t *p_conf;
gbazin's avatar
 
gbazin committed
896 897

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

Sam Hocevar's avatar
 
Sam Hocevar committed
900
            switch( p_conf->i_type )
gbazin's avatar
 
gbazin committed
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
            {
            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
919
        switch( i_cmd )
Michel Kaempf's avatar
Michel Kaempf committed
920
        {
gbazin's avatar
 
gbazin committed
921

922 923
        /* General/common options */
        case 'h':                                              /* -h, --help */
gbazin's avatar
 
gbazin committed
924
            config_PutIntVariable( "help", 1 );
925
            break;
926
        case 'H':                                          /* -H, --longhelp */
gbazin's avatar
 
gbazin committed
927
            config_PutIntVariable( "longhelp", 1 );
Michel Kaempf's avatar
Michel Kaempf committed
928
            break;
gbazin's avatar
 
gbazin committed
929 930
        case 'l':                                              /* -l, --list */
            config_PutIntVariable( "list", 1 );
931
            break;
gbazin's avatar
 
gbazin committed
932 933 934
        case 'p':                                            /* -p, --plugin */
            config_PutPszVariable( "plugin", optarg );
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
935
        case 'v':                                           /* -v, --verbose */
936
            p_main->i_warning_level++;
Sam Hocevar's avatar
 
Sam Hocevar committed
937
            break;
Michel Kaempf's avatar
Michel Kaempf committed
938 939

        /* Internal error: unknown option */
940
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
941
        default:
gbazin's avatar
 
gbazin committed
942

gbazin's avatar
 
gbazin committed
943 944 945 946 947 948 949
            if( !b_ignore_errors )
            {
                intf_ErrMsg( "intf error: unknown option `%s'",
                             ppsz_argv[optind] );
                intf_Msg( "Try `%s --help' for more information.\n",
                          p_main->psz_arg0 );

gbazin's avatar
 
gbazin committed
950
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
gbazin's avatar
 
gbazin committed
951 952
                intf_Msg( "\nPress the RETURN key to continue..." );
                getchar();
gbazin's avatar
 
gbazin committed
953
#endif
gbazin's avatar
 
gbazin committed
954 955 956
                free( p_longopts );
                return( EINVAL );
            }
Michel Kaempf's avatar
Michel Kaempf committed
957
        }
gbazin's avatar
 
gbazin committed
958

Michel Kaempf's avatar
Michel Kaempf committed
959
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
960 961 962 963 964 965

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

gbazin's avatar
 
gbazin committed
966
    free( p_longopts );
Sam Hocevar's avatar
 
Sam Hocevar committed
967 968 969 970 971 972 973 974 975 976 977
    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
978

Sam Hocevar's avatar
 
Sam Hocevar committed
979
    /* We assume that the remaining parameters are filenames */
Vincent Seguin's avatar
Vincent Seguin committed
980 981
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
982 983
        intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
                          ppsz_argv[ i_opt ] );
Vincent Seguin's avatar
Vincent Seguin committed
984
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
985

Michel Kaempf's avatar
Michel Kaempf committed
986 987 988
    return( 0 );
}

989
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
990
 * Usage: print program usage
991
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
992
 * Print a short inline help. Message interface is initialized at this stage.
993
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
994
static void Usage( const char *psz_module_name )
Michel Kaempf's avatar
Michel Kaempf committed
995
{
gbazin's avatar
 
gbazin committed
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
    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 )
1010
    {
gbazin's avatar
 
gbazin committed
1011 1012 1013 1014

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

gbazin's avatar
 
gbazin committed
1015 1016 1017
        /* ignore plugins without config options */
        if( !p_module->i_config_items ) continue;

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

gbazin's avatar
 
gbazin committed
1021
        for( i = 0; i < p_module->i_config_lines; i++ )
gbazin's avatar
 
gbazin committed
1022 1023 1024 1025 1026
        {
            int j;

            switch( p_module->p_config[i].i_type )
            {
gbazin's avatar
 
gbazin committed
1027
            case MODULE_CONFIG_HINT_CATEGORY:
gbazin's avatar
 
gbazin committed
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
                intf_Msg( " %s", p_module->p_config[i].psz_text );
                break;

            case MODULE_CONFIG_ITEM_STRING:
            case MODULE_CONFIG_ITEM_FILE:
            case MODULE_CONFIG_ITEM_PLUGIN:
                /* Nasty hack, but right now I'm too tired to think about
                 * a nice solution */
                j = 25 - strlen( p_module->p_config[i].psz_name )
                    - strlen(" <string>") - 1;
                if( j < 0 ) j = 0; psz_spaces[j] = 0;

                intf_Msg( "  --%s <string>%s %s",
                          p_module->p_config[i].psz_name, psz_spaces,
                          p_module->p_config[i].psz_text );
                psz_spaces[j] = 32;
                break;
            case MODULE_CONFIG_ITEM_INTEGER:
                /* Nasty hack, but right now I'm too tired to think about
                 * a nice solution */
                j = 25 - strlen( p_module->p_config[i].psz_name )
                    - strlen(" <integer>") - 1;
                if( j < 0 ) j = 0; psz_spaces[j] = 0;

                intf_Msg( "  --%s <integer>%s %s",
                          p_module->p_config[i].psz_name, psz_spaces,
                          p_module->p_config[i].psz_text );
                psz_spaces[j] = 32;
                break;
gbazin's avatar
 
gbazin committed
1057
            case MODULE_CONFIG_ITEM_BOOL:
gbazin's avatar
 
gbazin committed
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
                /* Nasty hack, but right now I'm too tired to think about
                 * a nice solution */
                j = 25 - strlen( p_module->p_config[i].psz_name ) - 1;
                if( j < 0 ) j = 0; psz_spaces[j] = 0;

                intf_Msg( "  --%s%s %s",
                          p_module->p_config[i].psz_name, psz_spaces,
                          p_module->p_config[i].psz_text );
                psz_spaces[j] = 32;
                break;
            }