main.c 42.9 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
7
 * $Id: main.c,v 1.160 2002/03/04 23:56:38 massiot 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 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
 * 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 */

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

/* Help options */
ADD_CATEGORY_HINT( "Help Options", NULL )
ADD_BOOL    ( "help", NULL,"print help and exit (or use -h)", NULL )
ADD_BOOL    ( "longhelp", NULL, "print long help version and exit (or use -H)",
              NULL )
ADD_BOOL    ( "list", NULL, "list available plugins (or use -l)", NULL )
ADD_STRING  ( "pluginhelp", NULL, NULL,"print help on a plugin and exit",NULL )
ADD_BOOL    ( "version", NULL, "output version information and exit", NULL )

/* Interface options */
ADD_CATEGORY_HINT( "Interface Options", NULL)
ADD_PLUGIN  ( INTF_METHOD_VAR, MODULE_CAPABILITY_INTF, NULL, NULL,
              "interface method", NULL )
ADD_INTEGER ( INTF_WARNING_VAR, 0, NULL, "warning level (or use -v)", NULL )
ADD_BOOL    ( INTF_STATS_VAR, NULL, "output statistics", NULL )
ADD_STRING  ( INTF_PATH_VAR, NULL, NULL, "interface default search path", NULL)

/* Audio Options */
ADD_CATEGORY_HINT( "Audio Options", NULL)
ADD_BOOL    ( AOUT_NOAUDIO_VAR, NULL, "disable audio", NULL )
ADD_PLUGIN  ( AOUT_METHOD_VAR, MODULE_CAPABILITY_AOUT, NULL, NULL,
              "audio output method", NULL )
ADD_BOOL    ( AOUT_MONO_VAR, NULL, "mono audio", NULL )
ADD_INTEGER ( AOUT_VOLUME_VAR, VOLUME_DEFAULT, NULL, "VLC output volume", NULL)
ADD_INTEGER ( AOUT_RATE_VAR, 44100, NULL, "VLC output frequency", NULL )
ADD_INTEGER ( AOUT_DESYNC_VAR, 0, NULL, "Compensate desynchronization of the "
                                        "audio (in ms)", NULL )

/* Video options */
ADD_CATEGORY_HINT( "Video Options", NULL )
ADD_BOOL    ( VOUT_NOVIDEO_VAR, NULL, "disable video", NULL )
ADD_PLUGIN  ( VOUT_METHOD_VAR, MODULE_CAPABILITY_VOUT, NULL, NULL,
              "video output method", NULL )
ADD_STRING  ( VOUT_DISPLAY_VAR, NULL, NULL, "display string", NULL )
ADD_INTEGER ( VOUT_WIDTH_VAR, 720, NULL, "display width", NULL )
ADD_INTEGER ( VOUT_HEIGHT_VAR, 576, NULL, "display height", NULL )
ADD_BOOL    ( VOUT_GRAYSCALE_VAR, NULL, "grayscale output", NULL )
ADD_BOOL    ( VOUT_FULLSCREEN_VAR, NULL, "fullscreen output", NULL )
ADD_BOOL    ( VOUT_NOOVERLAY_VAR, NULL, "disable accelerated display", NULL )
ADD_PLUGIN  ( VOUT_FILTER_VAR, MODULE_CAPABILITY_VOUT, NULL, NULL,
              "video filter module", NULL )
ADD_INTEGER ( VOUT_SPUMARGIN_VAR, -1, NULL, "force SPU position", NULL )

/* Input options */
ADD_CATEGORY_HINT( "Input Options", NULL )
ADD_STRING  ( INPUT_METHOD_VAR, NULL, NULL, "input method", NULL )
gbazin's avatar
 
gbazin committed
158
ADD_INTEGER ( INPUT_PORT_VAR, 1234, NULL, "server port", NULL )
gbazin's avatar
 
gbazin committed
159 160 161 162 163 164 165
ADD_BOOL    ( INPUT_NETWORK_CHANNEL_VAR, NULL, "enable network channel mode",
              NULL )
ADD_STRING  ( INPUT_CHANNEL_SERVER_VAR, "localhost", NULL,
              "channel server address", NULL )
ADD_INTEGER ( INPUT_CHANNEL_PORT_VAR, 6010, NULL, "channel server port", NULL )
ADD_STRING  ( INPUT_IFACE_VAR, "eth0", NULL, "network interface", NULL )

Stéphane Borel's avatar
 
Stéphane Borel committed
166
ADD_INTEGER ( INPUT_AUDIO_VAR, -1, NULL, "choose audio", NULL )
167
ADD_INTEGER ( INPUT_CHANNEL_VAR, -1, NULL, "choose channel", NULL )
gbazin's avatar
 
gbazin committed
168 169
ADD_INTEGER ( INPUT_SUBTITLE_VAR, -1, NULL, "choose subtitles", NULL )

170
ADD_STRING  ( INPUT_DVD_DEVICE_VAR, "/dev/dvd", NULL, "DVD device", NULL )
gbazin's avatar
 
gbazin committed
171
ADD_STRING  ( INPUT_VCD_DEVICE_VAR, "/dev/cdrom", NULL, "VCD device", NULL )
172 173
ADD_BOOL    ( INPUT_IPV6_VAR, NULL, "force IPv6", NULL )
ADD_BOOL    ( INPUT_IPV4_VAR, NULL, "force IPv4", NULL )
gbazin's avatar
 
gbazin committed
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

/* Decoder options */
ADD_CATEGORY_HINT( "Decoders Options", NULL )
ADD_PLUGIN  ( ADEC_MPEG_VAR, MODULE_CAPABILITY_DECODER, NULL, NULL,
              "choose MPEG audio decoder", NULL )
ADD_PLUGIN  ( ADEC_AC3_VAR, MODULE_CAPABILITY_DECODER, NULL, NULL,
              "choose AC3 audio decoder", NULL )
ADD_INTEGER ( VDEC_SMP_VAR, 0, NULL, "use additional processors", NULL )
ADD_STRING  ( VPAR_SYNCHRO_VAR, NULL, NULL, "force synchro algorithm "
                                            "{I|I+|IP|IP+|IPB}", NULL )

/* CPU options */
ADD_CATEGORY_HINT( "CPU Options Options", NULL )
ADD_BOOL    ( NOMMX_VAR, NULL, "disable CPU's MMX support", NULL )
ADD_BOOL    ( NO3DN_VAR, NULL, "disable CPU's 3D Now! support", NULL )
ADD_BOOL    ( NOMMXEXT_VAR, NULL, "disable CPU's MMX EXT support", NULL )
ADD_BOOL    ( NOSSE_VAR, NULL, "disable CPU's SSE support", NULL )
ADD_BOOL    ( NOALTIVEC_VAR, NULL, "disable CPU's AltiVec support", NULL )

/* Playlist options */
ADD_BOOL    ( PLAYLIST_STARTUP_VAR, NULL, "launch playlist on startup", NULL )
ADD_BOOL    ( PLAYLIST_ENQUEUE_VAR, NULL, "enqueue playlist as default", NULL )
ADD_BOOL    ( PLAYLIST_LOOP_VAR, NULL, "loop on playlist end", NULL )

/* Misc options */
ADD_CATEGORY_HINT( "Miscellaneous Options", NULL )
ADD_PLUGIN  ( MEMCPY_METHOD_VAR, MODULE_CAPABILITY_MEMCPY, NULL, NULL,
              "memory copy method", NULL )

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
/*****************************************************************************
 * End configuration.
217
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
218

219
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
220
 * Global variables - these are the only ones, see main.h and modules.h
221
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
222 223
main_t        *p_main;
module_bank_t *p_module_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
224
input_bank_t  *p_input_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
225 226
aout_bank_t   *p_aout_bank;
vout_bank_t   *p_vout_bank;
Michel Kaempf's avatar
Michel Kaempf committed
227

228
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
229
 * Local prototypes
230
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
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
248

249
static jmp_buf env;
Sam Hocevar's avatar
 
Sam Hocevar committed
250 251
static int     i_illegal;
static char   *psz_capability;
Sam Hocevar's avatar
 
Sam Hocevar committed
252

253
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
254
 * main: parse command line, start interface and spawn threads
255
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
256 257
 * Steps during program execution are:
 *      -configuration parsing and messages interface initialization
258
 *      -opening of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
259
 *      -execution of interface, which exit on error or on user request
Vincent Seguin's avatar
Vincent Seguin committed
260
 *      -closing of audio output device and some global modules
261
 * On error, the spawned threads are canceled, and the open devices closed.
262
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
263 264
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
Sam Hocevar's avatar
 
Sam Hocevar committed
265 266
    main_t        main_data;                /* root of all data - see main.h */
    module_bank_t module_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
267
    input_bank_t  input_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
268 269
    aout_bank_t   aout_bank;
    vout_bank_t   vout_bank;
gbazin's avatar
 
gbazin committed
270
    char *p_tmp;
271

Sam Hocevar's avatar
 
Sam Hocevar committed
272 273
    p_main        = &main_data;               /* set up the global variables */
    p_module_bank = &module_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
274
    p_input_bank  = &input_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
275 276
    p_aout_bank   = &aout_bank;
    p_vout_bank   = &vout_bank;
Sam Hocevar's avatar
 
Sam Hocevar committed
277

gbazin's avatar
 
gbazin committed
278 279
    p_main->i_warning_level = 0;

Sam Hocevar's avatar
 
Sam Hocevar committed
280
#if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
Sam Hocevar's avatar
 
Sam Hocevar committed
281
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
282 283
     * Support for getext
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
284 285
#if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
    if( !setlocale( LC_MESSAGES, "" ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
286 287 288
    {
        fprintf( stderr, "warning: unsupported locale.\n" );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
289
#endif
Sam Hocevar's avatar
 
Sam Hocevar committed
290

Sam Hocevar's avatar
 
Sam Hocevar committed
291
    if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
292 293 294 295 296 297 298
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
                 PACKAGE, LOCALEDIR );
    }

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

Sam Hocevar's avatar
 
Sam Hocevar committed
300
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
301
     * Initialize threads system
Sam Hocevar's avatar
 
Sam Hocevar committed
302
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
303
    vlc_threads_init( );
Sam Hocevar's avatar
 
Sam Hocevar committed
304

Sam Hocevar's avatar
 
Sam Hocevar committed
305
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
306
     * Test if our code is likely to run on this CPU
Sam Hocevar's avatar
 
Sam Hocevar committed
307 308
     */
    p_main->i_cpu_capabilities = CPUCapabilities();
Sam Hocevar's avatar
 
Sam Hocevar committed
309

Sam Hocevar's avatar
 
Sam Hocevar committed
310 311 312
    /*
     * System specific initialization code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
313
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
Sam Hocevar's avatar
 
Sam Hocevar committed
314
    system_Init( &i_argc, ppsz_argv, ppsz_env );
315 316 317 318

#elif defined( SYS_LINUX )
#   ifdef DEBUG
    /* Activate malloc checking routines to detect heap corruptions. */
gbazin's avatar
 
gbazin committed
319
    putenv( "MALLOC_CHECK_=2" );
320
#   endif
321
#endif
322 323 324 325

    /*
     * Initialize messages interface
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
326
    intf_MsgCreate();
327

Sam Hocevar's avatar
 
Sam Hocevar committed
328
    intf_Msg( COPYRIGHT_MESSAGE "\n" );
Sam Hocevar's avatar
 
Sam Hocevar committed
329

gbazin's avatar
 
gbazin committed
330 331 332 333 334 335 336 337 338

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

339
    /*
gbazin's avatar
 
gbazin committed
340 341 342
     * 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)
343
     */
gbazin's avatar
 
gbazin committed
344 345 346 347
    module_InitBank();
    module_LoadMain();

    if( GetConfigurationFromCmdLine( &i_argc, ppsz_argv, 1 ) )
Michel Kaempf's avatar
Michel Kaempf committed
348
    {
Vincent Seguin's avatar
Vincent Seguin committed
349
        intf_MsgDestroy();
350
        return( errno );
Michel Kaempf's avatar
Michel Kaempf committed
351
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
352

gbazin's avatar
 
gbazin committed
353 354 355 356 357 358 359 360 361 362 363 364 365 366
    /* Check for short help option */
    if( config_GetIntVariable( "help" ) )
    {
        Usage( "main" );
        return( -1 );
    }

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

gbazin's avatar
 
gbazin committed
367
    /*
gbazin's avatar
 
gbazin committed
368 369 370 371
     * 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
372
     */
gbazin's avatar
 
gbazin committed
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
    module_LoadBuiltins();
    module_LoadPlugins();
    intf_WarnMsg( 2, "module: module bank initialized, found %i modules",
                  p_module_bank->i_count );

    /* Check for help on plugins */
    if( (p_tmp = config_GetPszVariable( "pluginhelp" )) )
    {
        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 );
    }

    /*
     * 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 ? */
    p_main->i_desync = (mtime_t)config_GetIntVariable( AOUT_DESYNC_VAR )
      * (mtime_t)1000;
    p_main->b_stats = config_GetIntVariable( INTF_STATS_VAR );
    p_main->b_audio = !config_GetIntVariable( AOUT_NOAUDIO_VAR );
    p_main->b_stereo= !config_GetIntVariable( AOUT_MONO_VAR );
    p_main->b_video = !config_GetIntVariable( VOUT_NOVIDEO_VAR );
    if( config_GetIntVariable( NOMMX_VAR ) )
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMX;
    if( config_GetIntVariable( NO3DN_VAR ) )
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_3DNOW;
    if( config_GetIntVariable( NOMMXEXT_VAR ) )
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMXEXT;
    if( config_GetIntVariable( NOSSE_VAR ) )
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_SSE;
    if( config_GetIntVariable( NOALTIVEC_VAR ) )
        p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_ALTIVEC;


437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
    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
458
        PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
Sam Hocevar's avatar
 
Sam Hocevar committed
459
        intf_StatMsg( "info: CPU has capabilities : %s", p_capabilities );
460 461
    }

462
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
463
     * Initialize playlist and get commandline files
464
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
465
    p_main->p_playlist = intf_PlaylistCreate();
Sam Hocevar's avatar
 
Sam Hocevar committed
466
    if( !p_main->p_playlist )
467
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
468
        intf_ErrMsg( "playlist error: playlist initialization failed" );
469 470
        intf_MsgDestroy();
        return( errno );
471
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
472
    intf_PlaylistInit( p_main->p_playlist );
473 474

    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
475
     * Get input filenames given as commandline arguments
476
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
477
    GetFilenames( i_argc, ppsz_argv );
Michel Kaempf's avatar
Michel Kaempf committed
478

Sam Hocevar's avatar
 
Sam Hocevar committed
479
    /*
gbazin's avatar
 
gbazin committed
480
     * Initialize input, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
481
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
482
    input_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
483 484
    aout_InitBank();
    vout_InitBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
485

Sam Hocevar's avatar
 
Sam Hocevar committed
486 487 488
    /*
     * Choose the best memcpy module
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
489 490 491
    p_main->p_memcpy_module = module_Need( MODULE_CAPABILITY_MEMCPY, NULL,
                                           NULL );
    if( p_main->p_memcpy_module == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
492 493 494
    {
        intf_ErrMsg( "intf error: no suitable memcpy module, "
                     "using libc default" );
Sam Hocevar's avatar
 
Sam Hocevar committed
495 496 497 498 499 500
        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
501
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
502

Michel Kaempf's avatar
Michel Kaempf committed
503 504 505
    /*
     * Initialize shared resources and libraries
     */
gbazin's avatar
 
gbazin committed
506
    if( config_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR ) &&
507
        network_ChannelCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
508
    {
Henri Fallon's avatar
 
Henri Fallon committed
509
        /* On error during Channels initialization, switch off channels */
Sam Hocevar's avatar
 
Sam Hocevar committed
510 511
        intf_ErrMsg( "intf error: channels initialization failed, " 
                                 "deactivating channels" );
gbazin's avatar
 
gbazin committed
512
        config_PutIntVariable( INPUT_NETWORK_CHANNEL_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
513
    }
514

Michel Kaempf's avatar
Michel Kaempf committed
515
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
516
     * Try to run the interface
Michel Kaempf's avatar
Michel Kaempf committed
517
     */
518
    p_main->p_intf = intf_Create();
Sam Hocevar's avatar
 
Sam Hocevar committed
519
    if( p_main->p_intf == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
520 521 522
    {
        intf_ErrMsg( "intf error: interface initialization failed" );
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
523
    else
524
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
        /*
         * 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
543
        if( config_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
544 545 546
        {
            network_ChannelJoin( COMMON_CHANNEL );
        }
547
    }
Michel Kaempf's avatar
Michel Kaempf committed
548

Sam Hocevar's avatar
 
Sam Hocevar committed
549
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
550
     * Free input, aout and vout banks
Sam Hocevar's avatar
 
Sam Hocevar committed
551
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
552
    input_EndBank();
Sam Hocevar's avatar
 
Sam Hocevar committed
553 554 555 556 557 558 559 560
    vout_EndBank();
    aout_EndBank();

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

Sam Hocevar's avatar
 
Sam Hocevar committed
561
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
562
     * Free memcpy module if it was allocated
Sam Hocevar's avatar
 
Sam Hocevar committed
563
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
564
    if( p_main->p_memcpy_module != NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
565
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
566
        module_Unneed( p_main->p_memcpy_module );
Sam Hocevar's avatar
 
Sam Hocevar committed
567
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
568

Sam Hocevar's avatar
 
Sam Hocevar committed
569
    /*
Sam Hocevar's avatar
 
Sam Hocevar committed
570
     * Free module bank
Sam Hocevar's avatar
 
Sam Hocevar committed
571
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
572
    module_EndBank();
573 574 575 576

    /*
     * System specific cleaning code
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
577
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
Sam Hocevar's avatar
 
Sam Hocevar committed
578
    system_End();
579 580
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
581

Michel Kaempf's avatar
Michel Kaempf committed
582 583 584
    /*
     * Terminate messages interface and program
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
585
    intf_WarnMsg( 1, "intf: program terminated" );
Vincent Seguin's avatar
Vincent Seguin committed
586
    intf_MsgDestroy();
587

Sam Hocevar's avatar
 
Sam Hocevar committed
588 589 590 591
    /*
     * Stop threads system
     */
    vlc_threads_end( );
Sam Hocevar's avatar
 
Sam Hocevar committed
592

Sam Hocevar's avatar
 
Sam Hocevar committed
593
    return 0;
Michel Kaempf's avatar
Michel Kaempf committed
594 595
}

Vincent Seguin's avatar
Vincent Seguin committed
596

gbazin's avatar
 
gbazin committed
597
/* following functions are local */
598

599
/*****************************************************************************
gbazin's avatar
 
gbazin committed
600
 * GetConfigurationFromCmdLine: parse command line
601
 *****************************************************************************
gbazin's avatar
 
gbazin committed
602 603 604 605 606 607 608
 * 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.
609
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
610 611
static int GetConfigurationFromCmdLine( int *pi_argc, char *ppsz_argv[],
                                        boolean_t b_ignore_errors )
612
{
gbazin's avatar
 
gbazin committed
613 614 615
    int i_cmd, i, i_index, i_longopts_size;
    module_t *p_module;
    struct option *p_longopts;
616

gbazin's avatar
 
gbazin committed
617 618
    /* Short options */
    const char *psz_shortopts = "hHvl";
619

Michel Kaempf's avatar
Michel Kaempf committed
620 621

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

625 626
    p_main->p_channel = NULL;

Sam Hocevar's avatar
 
Sam Hocevar committed
627
#ifdef SYS_DARWIN
Sam Hocevar's avatar
 
Sam Hocevar committed
628 629 630
    /* 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
631 632
    if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
                                        /* for example -psn_0_9306113 */
633
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
634 635 636 637 638 639 640 641 642
        /* 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--;
643 644 645 646
        return( 0 );
    }
#endif

gbazin's avatar
 
gbazin committed
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701

    /*
     * Generate the longopts structure used by getopt_long
     */
    i_longopts_size = 0;
    for( p_module = p_module_bank->first ;
         p_module != NULL ;
         p_module = p_module->next )
    {
        /* count the number of exported configuration options (to allocate
         * longopts). The i_config_options we use is an approximation of the
         * real number of options (it also includes markers like: category ...)
         * but it is enough for our purpose */
        i_longopts_size += p_module->i_config_options -1;
    }

    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 )
    {
        for( i = 1; i < (p_module->i_config_options -1); i++ )
        {
            if( (p_module->p_config[i].i_type == MODULE_CONFIG_ITEM_CATEGORY)||
                (p_module->p_config[i].i_type ==
                     MODULE_CONFIG_ITEM_SUBCATEGORY)||
                (p_module->p_config[i].i_type ==
                     MODULE_CONFIG_ITEM_SUBCATEGORY_END) )
                 continue;
            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
702
    opterr = 0;
gbazin's avatar
 
gbazin committed
703 704 705
    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
706
    {
gbazin's avatar
 
gbazin committed
707 708 709 710 711

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

Sam Hocevar's avatar
 
Sam Hocevar committed
712
            module_config_t *p_conf;
gbazin's avatar
 
gbazin committed
713 714

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

Sam Hocevar's avatar
 
Sam Hocevar committed
717
            switch( p_conf->i_type )
gbazin's avatar
 
gbazin committed
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
            {
            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
736
        switch( i_cmd )
Michel Kaempf's avatar
Michel Kaempf committed
737
        {
gbazin's avatar
 
gbazin committed
738

739 740
        /* General/common options */
        case 'h':                                              /* -h, --help */
gbazin's avatar
 
gbazin committed
741
            config_PutIntVariable( "help", 1 );
742
            break;
743
        case 'H':                                          /* -H, --longhelp */
gbazin's avatar
 
gbazin committed
744
            config_PutIntVariable( "longhelp", 1 );
Michel Kaempf's avatar
Michel Kaempf committed
745
            break;
gbazin's avatar
 
gbazin committed
746 747
        case 'l':                                              /* -l, --list */
            config_PutIntVariable( "list", 1 );
748
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
749
        case 'v':                                           /* -v, --verbose */
750
            p_main->i_warning_level++;
Sam Hocevar's avatar
 
Sam Hocevar committed
751
            break;
Michel Kaempf's avatar
Michel Kaempf committed
752 753

        /* Internal error: unknown option */
754
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
755
        default:
gbazin's avatar
 
gbazin committed
756 757 758 759 760 761 762
            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
763
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
gbazin's avatar
 
gbazin committed
764 765
                intf_Msg( "\nPress the RETURN key to continue..." );
                getchar();
gbazin's avatar
 
gbazin committed
766
#endif
gbazin's avatar
 
gbazin committed
767 768 769 770
                free( p_longopts );
                return( EINVAL );
                break;
            }
Michel Kaempf's avatar
Michel Kaempf committed
771
        }
gbazin's avatar
 
gbazin committed
772

Michel Kaempf's avatar
Michel Kaempf committed
773
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
774 775 776 777 778 779

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

gbazin's avatar
 
gbazin committed
780
    free( p_longopts );
Sam Hocevar's avatar
 
Sam Hocevar committed
781 782 783 784 785 786 787 788 789 790 791
    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
792

Sam Hocevar's avatar
 
Sam Hocevar committed
793
    /* We assume that the remaining parameters are filenames */
Vincent Seguin's avatar
Vincent Seguin committed
794 795
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
796 797
        intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
                          ppsz_argv[ i_opt ] );
Vincent Seguin's avatar
Vincent Seguin committed
798
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
799

Michel Kaempf's avatar
Michel Kaempf committed
800 801 802
    return( 0 );
}

803
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
804
 * Usage: print program usage
805
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
806
 * Print a short inline help. Message interface is initialized at this stage.
807
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
808
static void Usage( const char *psz_module_name )
Michel Kaempf's avatar
Michel Kaempf committed
809
{
gbazin's avatar
 
gbazin committed
810 811 812 813 814 815 816 817 818 819
    int i;
    module_t *p_module;
    char psz_spaces[30];

    memset( psz_spaces, 32, 30 );

#ifdef WIN32
    ShowConsole();
#endif

Vincent Seguin's avatar
Vincent Seguin committed
820
    /* Usage */
gbazin's avatar
 
gbazin committed
821 822
    intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
              p_main->psz_arg0 );
823

gbazin's avatar
 
gbazin committed
824 825 826 827
    /* Enumerate the config of each module */
    for( p_module = p_module_bank->first ;
         p_module != NULL ;
         p_module = p_module->next )
828
    {
gbazin's avatar
 
gbazin committed
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891

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

        /* print module name */
        intf_Msg( "%s configuration:\n", p_module->psz_name );

        for( i = 0; i < (p_module->i_config_options -1); i++ )
        {
            int j;

            switch( p_module->p_config[i].i_type )
            {
            case MODULE_CONFIG_ITEM_CATEGORY:
                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;
            default:
                /* 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;
            }
        }

        /* Yet another nasty hack.
         * Maybe we could use MODULE_CONFIG_ITEM_END to display tail messages
         * for each module?? */
        if( !strcmp( "main", p_module->psz_name ) )
            intf_Msg( "\nPlaylist items:"
                "\n  *.mpg, *.vob                   \tPlain MPEG-1/2 files"
gbazin's avatar
 
gbazin committed
892 893
                "\n  [dvd:][device][@raw_device][@[title][,[chapter][,angle]]]"
                "\n                                 \tDVD device"
gbazin's avatar
 
gbazin committed
894 895 896 897 898 899 900 901 902 903 904 905
                "\n  vcd:<device>                   \tVCD device"
                "\n  udpstream:[<server>[:<server port>]][@[<bind address>]"
                      "[:<bind port>]]"
                "\n                                 \tUDP stream sent by VLS"
                "\n  vlc:loop                       \tLoop execution of the "
                      "playlist"
                "\n  vlc:pause                      \tPause execution of "
                      "playlist items"
                "\n  vlc:quit                       \tQuit VLC" );

        intf_Msg( "" );

906 907
    }

gbazin's avatar
 
gbazin committed
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
        intf_Msg( "\nPress the RETURN key to continue..." );
        getchar();
#endif
}

/*****************************************************************************
 * ListModules: list the available modules with their description
 *****************************************************************************
 * Print a list of all available modules (builtins and plugins) and a short
 * description for each one.
 *****************************************************************************/
static void ListModules( void )
{
    module_t *p_module;
    char psz_spaces[20];

    memset( psz_spaces, 32, 20 );

#ifdef WIN32
    ShowConsole();
#endif

    /* Usage */
    intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
              p_main->psz_arg0 );

    intf_Msg( "[plugin]              [description]" );

    /* Enumerate each module */
    for( p_module = p_module_bank->first ;
         p_module != NULL ;
         p_module = p_module->next )
    {
        int i;

        /* Nasty hack, but right now I'm too tired to think about a nice
         * solution */
        i = 20 - strlen( p_module->psz_name ) - 1;
        if( i < 0 ) i = 0;
        psz_spaces[i] = 0;

        intf_Msg( "  %s%s %s", p_module->psz_name, psz_spaces,
                  p_module->psz_longname );

        psz_spaces[i] = 32;

    }

#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
        intf_Msg( "\nPress the RETURN key to continue..." );
        getchar();
#endif
Michel Kaempf's avatar
Michel Kaempf committed
961 962
}

963
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
964
 * Version: print complete program version
965
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
966
 * Print complete program version and build number.
967
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
968 969
static void Version( void )
{
gbazin's avatar
 
gbazin committed
970 971 972
#ifdef WIN32
    ShowConsole();
#endif
Sam Hocevar's avatar
 
Sam Hocevar committed
973
    intf_Msg( VERSION_MESSAGE
Sam Hocevar's avatar
 
Sam Hocevar committed
974 975 976 977
        "This program comes with NO WARRANTY, to the extent permitted by law.\n"
        "You may redistribute it under the terms of the GNU General Public License;\n"
        "see the file named COPYING for details.\n"
        "Written by the VideoLAN team at Ecole Centrale, Paris." );
gbazin's avatar
 
gbazin committed
978 979 980 981
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
        intf_Msg( "\nPress the RETURN key to continue..." );
        getchar();
#endif
982
}
Vincent Seguin's avatar
Vincent Seguin committed
983

984
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
985
 * InitSignalHandler: system signal handler initialization
986
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
987
 * Set the signal handlers. SIGTERM is not intercepted, because we need at
988
 * at least a method to kill the program when all other methods failed, and
Michel Kaempf's avatar
Michel Kaempf committed
989
 * when we don't want to use SIGKILL.
990
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
991 992
static void InitSignalHandler( void )
{
Vincent Seguin's avatar
Vincent Seguin committed
993
    /* Termination signals */
Sam Hocevar's avatar
 
Sam Hocevar committed
994
#ifndef WIN32
Benoit Steiner's avatar
 
Benoit Steiner committed
995
    signal( SIGINT,  FatalSignalHandler );
Sam Hocevar's avatar
 
Sam Hocevar committed
996
    signal( SIGHUP,  FatalSignalHandler );
Benoit Steiner's avatar
 
Benoit Steiner committed
997 998 999 1000 1001
    signal( SIGQUIT, FatalSignalHandler );

    /* Other signals */
    signal( SIGALRM, SimpleSignalHandler );
    signal( SIGPIPE, SimpleSignalHandler );
Sam Hocevar's avatar
 
Sam Hocevar committed
1002
#endif
Benoit Steiner's avatar
 
Benoit Steiner committed
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
}

/*****************************************************************************
 * SimpleSignalHandler: system signal handler
 *****************************************************************************
 * This function is called when a non fatal signal is received by the program.
 *****************************************************************************/
static void SimpleSignalHandler( int i_signal )
{
    /* Acknowledge the signal received */
Sam Hocevar's avatar
 
Sam Hocevar committed
1013
    intf_WarnMsg( 0, "intf: ignoring signal %d", i_signal );
Michel Kaempf's avatar
Michel Kaempf committed
1014 1015
}

1016
/*****************************************************************************
Benoit Steiner's avatar
 
Benoit Steiner committed
1017
 * FatalSignalHandler: system signal handler
1018
 *****************************************************************************
Benoit Steiner's avatar
 
Benoit Steiner committed
1019 1020
 * This function is called when a fatal signal is received by the program.
 * It tries to end the program in a clean way.
1021
 *****************************************************************************/
Benoit Steiner's avatar
 
Benoit Steiner committed
1022
static void FatalSignalHandler( int i_signal )
Michel Kaempf's avatar
Michel Kaempf committed
1023
{
Sam Hocevar's avatar
 
Sam Hocevar committed
1024 1025 1026
    /* Once a signal has been trapped, the termination sequence will be
     * armed and following signals will be ignored to avoid sending messages
     * to an interface having been destroyed */
Sam Hocevar's avatar
 
Sam Hocevar committed
1027
#ifndef WIN32
Vincent Seguin's avatar
Vincent Seguin committed
1028
    signal( SIGINT,  SIG_IGN );
Sam Hocevar's avatar
 
Sam Hocevar committed
1029
    signal( SIGHUP,  SIG_IGN );
Vincent Seguin's avatar
Vincent Seguin committed
1030
    signal( SIGQUIT, SIG_IGN );
Sam Hocevar's avatar
 
Sam Hocevar committed
1031
#endif
Vincent Seguin's avatar
Vincent Seguin committed
1032 1033

    /* Acknowledge the signal received */
Sam Hocevar's avatar
 
Sam Hocevar committed
1034
    intf_ErrMsg( "intf error: signal %d received, exiting", i_signal );
Vincent Seguin's avatar
Vincent Seguin committed
1035

1036
    /* Try to terminate everything - this is done by requesting the end of the
Vincent Seguin's avatar
Vincent Seguin committed
1037 1038 1039 1040
     * interface thread */
    p_main->p_intf->b_die = 1;
}

1041
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
1042
 * IllegalSignalHandler: system signal handler
1043
 *****************************************************************************
gbazin's avatar
 
gbazin committed
1044
 * This function is called when an illegal instruction signal is received by
Sam Hocevar's avatar
 
Sam Hocevar committed
1045
 * the program. We use this function to test OS and CPU capabilities