libvlc.c 38.4 KB
Newer Older
1 2 3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2002 VideoLAN
Sam Hocevar's avatar
Sam Hocevar committed
5
 * $Id: libvlc.c,v 1.38 2002/10/11 22:32:56 sam Exp $
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 *
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
 *          Gildas Bazin <gbazin@netcourrier.com>
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * 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.
 *****************************************************************************/

/*****************************************************************************
 * Pretend we are a builtin module
 *****************************************************************************/
#define MODULE_NAME main
30
#define MODULE_PATH main
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#define __BUILTIN__

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <errno.h>                                                 /* ENOMEM */
#include <stdio.h>                                              /* sprintf() */
#include <string.h>                                            /* strerror() */
#include <stdlib.h>                                                /* free() */

#include <vlc/vlc.h>

#ifndef WIN32
#   include <netinet/in.h>                            /* BSD: struct in_addr */
#endif

#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#elif defined( _MSC_VER ) && defined( _WIN32 )
#   include <io.h>
#endif

53
#ifdef WIN32                       /* optind, getopt(), included in unistd.h */
54
#   include "extras/GNUgetopt/getopt.h"
55 56
#endif

57 58 59 60 61
#ifdef HAVE_LOCALE_H
#   include <locale.h>
#endif

#include "vlc_cpu.h"                                        /* CPU detection */
62
#include "os_specific.h"
63 64 65 66 67 68

#include "netutils.h"                                 /* network_ChannelJoin */

#include "stream_control.h"
#include "input_ext-intf.h"

69
#include "vlc_playlist.h"
70 71 72 73 74 75 76 77 78 79
#include "interface.h"

#include "audio_output.h"

#include "video.h"
#include "video_output.h"

#include "libvlc.h"

/*****************************************************************************
80
 * The evil global variable. We handle it with care, don't worry.
81
 *****************************************************************************/
82
static libvlc_t libvlc;
Sam Hocevar's avatar
Sam Hocevar committed
83
static vlc_t *  p_static_vlc;
84 85 86 87 88

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int  GetFilenames  ( vlc_t *, int, char *[] );
89 90
static void Usage         ( vlc_t *, const char *psz_module_name );
static void ListModules   ( vlc_t * );
91 92 93 94 95 96 97
static void Version       ( void );

#ifdef WIN32
static void ShowConsole   ( void );
#endif

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
98
 * VLC_Version: return the libvlc version.
99
 *****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
100
 * This function returns full version string (numeric version and codename).
101
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
102
char * VLC_Version( void )
103
{
Sam Hocevar's avatar
Sam Hocevar committed
104
    return VERSION_MESSAGE;
105 106
}

Sam Hocevar's avatar
Sam Hocevar committed
107 108 109 110 111 112 113
/*****************************************************************************
 * VLC_Create: allocate a vlc_t structure, and initialize libvlc if needed.
 *****************************************************************************
 * This function allocates a vlc_t structure and returns a negative value
 * in case of failure. Also, the thread system is initialized.
 *****************************************************************************/
int VLC_Create( void )
114
{
115
    int i_ret;
116
    vlc_t * p_vlc = NULL;
117
    vlc_mutex_t * p_libvlc_lock;
118

119 120 121
    /* vlc_threads_init *must* be the first internal call! No other call is
     * allowed before the thread system has been initialized. */
    i_ret = vlc_threads_init( &libvlc );
Sam Hocevar's avatar
Sam Hocevar committed
122
    if( i_ret < 0 )
123
    {
Sam Hocevar's avatar
Sam Hocevar committed
124
        return i_ret;
125 126 127
    }

    /* Now that the thread system is initialized, we don't have much, but
128 129 130
     * at least we have vlc_mutex_need */
    p_libvlc_lock = vlc_mutex_need( &libvlc, "libvlc" );
    vlc_mutex_lock( p_libvlc_lock );
131 132
    if( !libvlc.b_ready )
    {
133 134
        char *psz_env;

135 136 137
        /* Guess what CPU we have */
        libvlc.i_cpu = CPUCapabilities();

138 139
        /* Find verbosity from VLC_VERBOSE environment variable */
        psz_env = getenv( "VLC_VERBOSE" );
140
        libvlc.i_verbose = psz_env ? atoi( psz_env ) : -1;
141 142 143 144 145 146 147

#ifdef HAVE_ISATTY
        libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
#else
        libvlc.b_color = VLC_FALSE;
#endif

148 149 150 151 152 153 154
        /* Initialize message queue */
        msg_Create( &libvlc );

        /* Announce who we are */
        msg_Dbg( &libvlc, COPYRIGHT_MESSAGE );
        msg_Dbg( &libvlc, "libvlc was configured with %s", CONFIGURE_LINE );

155
        /* Initialize the module bank and load the configuration of the
156 157 158 159 160
         * 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) */
        module_InitBank( &libvlc );
        module_LoadMain( &libvlc );
161 162

        libvlc.b_ready = VLC_TRUE;
163
    }
164 165
    vlc_mutex_unlock( p_libvlc_lock );
    vlc_mutex_unneed( &libvlc, "libvlc" );
166 167 168

    /* Allocate a vlc object */
    p_vlc = vlc_object_create( &libvlc, VLC_OBJECT_VLC );
169 170
    if( p_vlc == NULL )
    {
Sam Hocevar's avatar
Sam Hocevar committed
171
        return VLC_EGENERIC;
172 173 174 175 176
    }

    p_vlc->psz_object_name = "root";

    /* Initialize mutexes */
177
    vlc_mutex_init( p_vlc, &p_vlc->config_lock );
178 179

    /* Store our newly allocated structure in the global list */
180
    vlc_object_attach( p_vlc, &libvlc );
181

Sam Hocevar's avatar
Sam Hocevar committed
182 183 184
    /* Store data for the non-reentrant API */
    p_static_vlc = p_vlc;

185 186 187
    /* Update the handle status */
    p_vlc->i_status = VLC_STATUS_CREATED;

Sam Hocevar's avatar
Sam Hocevar committed
188
    return p_vlc->i_object_id;
189 190 191
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
192
 * VLC_Init: initialize a vlc_t structure.
193 194 195 196 197 198 199
 *****************************************************************************
 * This function initializes a previously allocated vlc_t structure:
 *  - CPU detection
 *  - gettext initialization
 *  - message queue, module bank and playlist initialization
 *  - configuration and commandline parsing
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
200
int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
201
{
202 203 204
    char         p_capabilities[200];
    char *       p_tmp;
    vlc_bool_t   b_exit;
Sam Hocevar's avatar
Sam Hocevar committed
205
    vlc_t *      p_vlc;
206 207
    module_t    *p_help_module;
    playlist_t  *p_playlist;
208

Sam Hocevar's avatar
Sam Hocevar committed
209 210
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

211 212 213
    /* Check that the handle is valid */
    if( !p_vlc || p_vlc->i_status != VLC_STATUS_CREATED )
    {
214
        fprintf( stderr, "error: invalid status (!CREATED)\n" );
215 216 217
        return VLC_ESTATUS;
    }

218
    /* Support for gettext */
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
#if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
#   if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
    if( !setlocale( LC_MESSAGES, "" ) )
    {
        fprintf( stderr, "warning: unsupported locale settings\n" );
    }

    setlocale( LC_CTYPE, "" );
#   endif

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

    textdomain( PACKAGE );
#endif

    /*
239
     * System specific initialization code
240
     */
241
    system_Init( p_vlc, &i_argc, ppsz_argv );
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261

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

    /* Hack: insert the help module here */
    p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
    if( p_help_module == NULL )
    {
262
        //module_EndBank( p_vlc );
263 264 265 266
        return VLC_EGENERIC;
    }
    p_help_module->psz_object_name = "help";
    config_Duplicate( p_help_module, p_help_config );
267
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
268 269
    /* End hack */

Sam Hocevar's avatar
Sam Hocevar committed
270
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
271
    {
272
        vlc_object_detach( p_help_module );
273 274
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
275
        //module_EndBank( p_vlc );
276 277 278
        return VLC_EGENERIC;
    }

279 280
    b_exit = VLC_FALSE;

281 282 283
    /* Check for short help option */
    if( config_GetInt( p_vlc, "help" ) )
    {
284
        fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
285
                         p_vlc->psz_object_name );
286
        Usage( p_vlc, "main" );
287 288
        Usage( p_vlc, "help" );
        b_exit = VLC_TRUE;
289 290
    }
    /* Check for version option */
291
    else if( config_GetInt( p_vlc, "version" ) )
292 293
    {
        Version();
294 295 296 297 298 299 300 301 302
        b_exit = VLC_TRUE;
    }

    /* Hack: remove the help module here */
    vlc_object_detach( p_help_module );
    /* End hack */

    if( b_exit )
    {
303 304
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
305
        //module_EndBank( p_vlc );
306 307 308 309 310 311 312 313 314
        return VLC_EEXIT;
    }

    /*
     * Load the builtins and plugins into the module_bank.
     * We have to do it before config_Load*() because this also gets the
     * list of configuration options exported by each module and loads their
     * default values.
     */
315 316
    module_LoadBuiltins( &libvlc );
    module_LoadPlugins( &libvlc );
317
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
318
                    libvlc.p_module_bank->i_children );
319 320

    /* Hack: insert the help module here */
321
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
322 323 324 325 326
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
327
        Usage( p_vlc, p_tmp );
328
        free( p_tmp );
329
        b_exit = VLC_TRUE;
330 331
    }
    /* Check for long help option */
332
    else if( config_GetInt( p_vlc, "longhelp" ) )
333
    {
334
        Usage( p_vlc, NULL );
335
        b_exit = VLC_TRUE;
336 337
    }
    /* Check for module list option */
338
    else if( config_GetInt( p_vlc, "list" ) )
339
    {
340
        ListModules( p_vlc );
341
        b_exit = VLC_TRUE;
342 343 344
    }

    /* Hack: remove the help module here */
345
    vlc_object_detach( p_help_module );
346 347 348 349
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

350 351
    if( b_exit )
    {
352
        //module_EndBank( p_vlc );
353 354 355
        return VLC_EEXIT;
    }

356 357 358 359
    /*
     * Override default configuration with config file settings
     */
    p_vlc->psz_homedir = config_GetHomeDir();
360
    config_LoadConfigFile( p_vlc, NULL );
361 362 363 364

    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
365
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
366 367 368 369 370 371 372 373
    {
#ifdef WIN32
        ShowConsole();
        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, "The command line options couldn't be loaded, check "
                 "that they are valid.\nPress the RETURN key to continue..." );
        getchar();
#endif
374
        //module_EndBank( p_vlc );
375 376 377 378 379 380
        return VLC_EGENERIC;
    }

    /*
     * System specific configuration
     */
381
    system_Configure( p_vlc );
382

383 384 385 386 387
    /*
     * Message queue options
     */
    if( config_GetInt( p_vlc, "quiet" ) )
    {
388
        libvlc.i_verbose = -1;
389 390 391 392
    }
    else
    {
        int i_tmp = config_GetInt( p_vlc, "verbose" );
393
        if( i_tmp >= 0 )
394
        {
395
            libvlc.i_verbose = __MIN( i_tmp, 2 );
396 397 398 399
        }
    }
    libvlc.b_color = libvlc.b_color || config_GetInt( p_vlc, "color" );

400 401 402 403 404 405 406
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

    /* p_vlc inititalization. FIXME ? */
    p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
407

408
#if defined( __i386__ )
409
    if( !config_GetInt( p_vlc, "mmx" ) )
410
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
411
    if( !config_GetInt( p_vlc, "3dn" ) )
412
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
413
    if( !config_GetInt( p_vlc, "mmxext" ) )
414
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
415
    if( !config_GetInt( p_vlc, "sse" ) )
416
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
417 418
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
419
    if( !config_GetInt( p_vlc, "altivec" ) )
420
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
421
#endif
422 423

#define PRINT_CAPABILITY( capability, string )                              \
424
    if( libvlc.i_cpu & capability )                                         \
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
    {                                                                       \
        strncat( p_capabilities, string " ",                                \
                 sizeof(p_capabilities) - strlen(p_capabilities) );         \
        p_capabilities[sizeof(p_capabilities) - 1] = '\0';                  \
    }

    p_capabilities[0] = '\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" );
    PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
    msg_Dbg( p_vlc, "CPU has capabilities %s", p_capabilities );

    /*
     * Choose the best memcpy module
     */
446
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
447

448
    if( p_vlc->pf_memcpy == NULL )
449 450 451
    {
        p_vlc->pf_memcpy = memcpy;
    }
452 453 454 455 456

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
457 458 459 460 461

    /*
     * Initialize shared resources and libraries
     */
    if( config_GetInt( p_vlc, "network-channel" )
462
         && network_ChannelCreate( p_vlc ) )
463 464
    {
        /* On error during Channels initialization, switch off channels */
465 466
        msg_Warn( p_vlc,
                  "channels initialization failed, deactivating channels" );
Sam Hocevar's avatar
Sam Hocevar committed
467
        config_PutInt( p_vlc, "network-channel", VLC_FALSE );
468 469 470 471 472
    }

    /*
     * Initialize playlist and get commandline files
     */
473
    p_playlist = playlist_Create( p_vlc );
474 475 476
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
477 478
        if( p_vlc->p_memcpy_module != NULL )
        {
479
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
480
        }
481
        //module_EndBank( p_vlc );
482 483 484
        return VLC_EGENERIC;
    }

485 486 487
    /* Update the handle status */
    p_vlc->i_status = VLC_STATUS_STOPPED;

488 489 490 491 492 493 494 495 496
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
497
 * VLC_AddIntf: add an interface
498 499
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
500 501
 * to 0, VLC_AddIntf will return immediately and let the interface run in a
 * separate thread. If b_block is set to 1, VLC_AddIntf will continue until
502 503
 * user requests to quit.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
504
int VLC_AddIntf( int i_object, const char *psz_module, vlc_bool_t b_block )
505
{
Sam Hocevar's avatar
Sam Hocevar committed
506
    int i_err;
507
    intf_thread_t *p_intf;
Sam Hocevar's avatar
Sam Hocevar committed
508
    vlc_t *p_vlc;
509 510
    char *psz_oldmodule = NULL;

Sam Hocevar's avatar
Sam Hocevar committed
511 512
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

513 514 515
    /* Check that the handle is valid */
    if( !p_vlc || p_vlc->i_status != VLC_STATUS_RUNNING )
    {
516
        fprintf( stderr, "error: invalid status (!RUNNING)\n" );
517 518 519 520 521 522 523 524 525 526
        return VLC_ESTATUS;
    }

    if( psz_module )
    {
        psz_oldmodule = config_GetPsz( p_vlc, "intf" );
        config_PutPsz( p_vlc, "intf", psz_module );
    }

    /* Try to create the interface */
527
    p_intf = intf_Create( p_vlc );
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545

    if( psz_module )
    {
        config_PutPsz( p_vlc, "intf", psz_oldmodule );
        if( psz_oldmodule )
        {
            free( psz_oldmodule );
        }
    }

    if( p_intf == NULL )
    {
        msg_Err( p_vlc, "interface initialization failed" );
        return VLC_EGENERIC;
    }

    /* Try to run the interface */
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
546 547
    i_err = intf_RunThread( p_intf );
    if( i_err )
548
    {
549
        vlc_object_detach( p_intf );
550
        intf_Destroy( p_intf );
Sam Hocevar's avatar
Sam Hocevar committed
551
        return i_err;
552 553 554 555 556 557
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
558
 * VLC_Destroy: stop playing and destroy everything.
559
 *****************************************************************************
560
 * This function requests the running threads to finish, waits for their
561 562
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
563
int VLC_Destroy( int i_object )
564
{
Sam Hocevar's avatar
Sam Hocevar committed
565 566 567
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
568

569
    /* Check that the handle is valid */
570
    if( !p_vlc || (p_vlc->i_status != VLC_STATUS_STOPPED
571
                    && p_vlc->i_status != VLC_STATUS_CREATED) )
572
    {
573
        fprintf( stderr, "error: invalid status "
574
                         "(!STOPPED&&!CREATED)\n" );
575 576 577
        return VLC_ESTATUS;
    }

578
    if( p_vlc->i_status == VLC_STATUS_STOPPED )
579
    {
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
        /*
         * Go back into channel 0 which is the network
         */
        if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
        {
            network_ChannelJoin( p_vlc, COMMON_CHANNEL );
        }
    
        /*
         * Free allocated memory
         */
        if( p_vlc->p_memcpy_module != NULL )
        {
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        }
    
        free( p_vlc->psz_homedir );
    
        /*
599
         * XXX: Free module bank !
600
         */
601
        //module_EndBank( p_vlc );
602 603 604 605 606 607 608 609
    
        /*
         * System specific cleaning code
         */
        system_End( p_vlc );
    
        /* Update the handle status */
        p_vlc->i_status = VLC_STATUS_CREATED;
610 611 612 613 614 615 616 617
    }

    /* Update the handle status, just in case */
    p_vlc->i_status = VLC_STATUS_NONE;

    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

618 619
    vlc_object_detach( p_vlc );

620 621
    vlc_object_destroy( p_vlc );

622 623 624
    /* Stop thread system: last one out please shut the door! */
    vlc_threads_end( &libvlc );

625 626 627
    return VLC_SUCCESS;
}

628
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
629
 * VLC_Die: ask vlc to die.
630 631
 *****************************************************************************
 * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
Sam Hocevar's avatar
Sam Hocevar committed
632
 * task. It is your duty to call vlc_end and VLC_Destroy afterwards.
633
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
634
int VLC_Die( int i_object )
635
{
Sam Hocevar's avatar
Sam Hocevar committed
636 637 638
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
639 640 641 642 643 644 645 646 647 648 649 650 651

    if( !p_vlc )
    {
        fprintf( stderr, "error: invalid status (!EXIST)\n" );
        return VLC_ESTATUS;
    }

    p_vlc->b_die = VLC_TRUE;

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
652
 * VLC_AddTarget: adds a target for playing.
653 654 655 656
 *****************************************************************************
 * This function adds psz_target to the current playlist. If a playlist does
 * not exist, it will create one.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
657
int VLC_AddTarget( int i_object, const char *psz_target, int i_mode, int i_pos )
658
{
Sam Hocevar's avatar
Sam Hocevar committed
659
    int i_err;
Sam Hocevar's avatar
Sam Hocevar committed
660
    playlist_t *p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
661 662 663
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
Sam Hocevar's avatar
Sam Hocevar committed
664

665 666 667
    if( !p_vlc || ( p_vlc->i_status != VLC_STATUS_STOPPED
                     && p_vlc->i_status != VLC_STATUS_RUNNING ) )
    {
668
        fprintf( stderr, "error: invalid status (!STOPPED&&!RUNNING)\n" );
669 670 671
        return VLC_ESTATUS;
    }

Sam Hocevar's avatar
Sam Hocevar committed
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );

    if( p_playlist == NULL )
    {
        msg_Dbg( p_vlc, "no playlist present, creating one" );
        p_playlist = playlist_Create( p_vlc );

        if( p_playlist == NULL )
        {
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
    }

Sam Hocevar's avatar
Sam Hocevar committed
687
    i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
Sam Hocevar's avatar
Sam Hocevar committed
688 689

    vlc_object_release( p_playlist );
690

Sam Hocevar's avatar
Sam Hocevar committed
691
    return i_err;
692 693
}

694
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
695
 * VLC_Set: set a vlc variable
696 697 698
 *****************************************************************************
 *
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
699
int VLC_Set( int i_object, const char *psz_var, vlc_value_t value )
700
{
Sam Hocevar's avatar
Sam Hocevar committed
701
    vlc_t *p_vlc;
702

Sam Hocevar's avatar
Sam Hocevar committed
703
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
704 705 706 707 708 709 710

    if( !p_vlc )
    {
        fprintf( stderr, "error: invalid status\n" );
        return VLC_ESTATUS;
    }

Sam Hocevar's avatar
Sam Hocevar committed
711 712 713
    /* FIXME: Temporary hack for Mozilla, if variable starts with conf:: then
     * we handle it as a configuration variable. Don't tell Gildas :) -- sam */
    if( !strncmp( psz_var, "conf::", 6 ) )
714
    {
Sam Hocevar's avatar
Sam Hocevar committed
715 716
        module_config_t *p_item;
        const char *psz_newvar = psz_var + 6;
717

Sam Hocevar's avatar
Sam Hocevar committed
718
        p_item = config_FindConfig( VLC_OBJECT(p_vlc), psz_newvar );
719

Sam Hocevar's avatar
Sam Hocevar committed
720
        if( p_item )
721
        {
Sam Hocevar's avatar
Sam Hocevar committed
722
            switch( p_item->i_type )
723
            {
Sam Hocevar's avatar
Sam Hocevar committed
724 725 726 727 728 729 730 731 732 733 734 735
                case CONFIG_ITEM_BOOL:
                    config_PutInt( p_vlc, psz_newvar, value.b_bool );
                    break;
                case CONFIG_ITEM_INTEGER:
                    config_PutInt( p_vlc, psz_newvar, value.i_int );
                    break;
                case CONFIG_ITEM_FLOAT:
                    config_PutFloat( p_vlc, psz_newvar, value.f_float );
                    break;
                default:
                    config_PutPsz( p_vlc, psz_newvar, value.psz_string );
                    break;
736
            }
Sam Hocevar's avatar
Sam Hocevar committed
737
            return VLC_SUCCESS;
738 739 740
        }
    }

Sam Hocevar's avatar
Sam Hocevar committed
741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
    return var_Set( p_vlc, psz_var, value );
}

/*****************************************************************************
 * VLC_Get: get a vlc variable
 *****************************************************************************
 *
 *****************************************************************************/
int VLC_Get( int i_object, const char *psz_var, vlc_value_t *p_value )
{
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

    if( !p_vlc )
756
    {
Sam Hocevar's avatar
Sam Hocevar committed
757 758
        fprintf( stderr, "error: invalid status\n" );
        return VLC_ESTATUS;
759 760
    }

Sam Hocevar's avatar
Sam Hocevar committed
761
    return var_Get( p_vlc, psz_var, p_value );
762 763
}

Sam Hocevar's avatar
Sam Hocevar committed
764
/* FIXME: temporary hacks */
765 766

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
767
 * VLC_Play: play
768
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
769
int VLC_Play( int i_object )
770 771
{
    playlist_t * p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
772 773 774
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809

    /* Check that the handle is valid */
    if( !p_vlc || p_vlc->i_status != VLC_STATUS_STOPPED )
    {
        fprintf( stderr, "error: invalid status (!STOPPED)\n" );
        return VLC_ESTATUS;
    }

    /* Update the handle status */
    p_vlc->i_status = VLC_STATUS_RUNNING;

    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
        return VLC_EOBJECT;
    }

    vlc_mutex_lock( &p_playlist->object_lock );
    if( p_playlist->i_size )
    {
        vlc_mutex_unlock( &p_playlist->object_lock );
        playlist_Play( p_playlist );
    }
    else
    {
        vlc_mutex_unlock( &p_playlist->object_lock );
    }

    vlc_object_release( p_playlist );

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
810
 * VLC_Stop: stop
811
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
812
int VLC_Stop( int i_object )
813 814 815 816 817
{
    intf_thread_t *   p_intf;
    playlist_t    *   p_playlist;
    vout_thread_t *   p_vout;
    aout_instance_t * p_aout;
Sam Hocevar's avatar
Sam Hocevar committed
818 819 820
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
821 822 823 824 825 826 827 828 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

    /* Check that the handle is valid */
    if( !p_vlc || ( p_vlc->i_status != VLC_STATUS_STOPPED
                     && p_vlc->i_status != VLC_STATUS_RUNNING ) )
    {
        fprintf( stderr, "error: invalid status (!STOPPED&&!RUNNING)\n" );
        return VLC_ESTATUS;
    }

    /*
     * Ask the interfaces to stop and destroy them
     */
    msg_Dbg( p_vlc, "removing all interfaces" );
    while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_CHILD )) )
    {
        intf_StopThread( p_intf );
        vlc_object_detach( p_intf );
        vlc_object_release( p_intf );
        intf_Destroy( p_intf );
    }

    /*
     * Free playlists
     */
    msg_Dbg( p_vlc, "removing all playlists" );
    while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
                                          FIND_CHILD )) )
    {
        vlc_object_detach( p_playlist );
        vlc_object_release( p_playlist );
        playlist_Destroy( p_playlist );
    }

    /*
     * Free video outputs
     */
    msg_Dbg( p_vlc, "removing all video outputs" );
    while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
    {
        vlc_object_detach( p_vout );
        vlc_object_release( p_vout );
        vout_DestroyThread( p_vout );
    }

    /*
     * Free audio outputs
     */
    msg_Dbg( p_vlc, "removing all audio outputs" );
    while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
    {
        vlc_object_detach( (vlc_object_t *)p_aout );
        vlc_object_release( (vlc_object_t *)p_aout );
        aout_Delete( p_aout );
    }

    /* Update the handle status */
    p_vlc->i_status = VLC_STATUS_STOPPED;

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
883
 * VLC_Pause: toggle pause
884
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
885
int VLC_Pause( int i_object )
886 887
{
    input_thread_t *p_input;
Sam Hocevar's avatar
Sam Hocevar committed
888 889 890 891 892 893 894 895
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

    if( !p_vlc )
    {
        return VLC_ESTATUS;
    }
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910

    p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );

    if( !p_input )
    {
        return VLC_EOBJECT;
    }

    input_SetStatus( p_input, INPUT_STATUS_PAUSE );
    vlc_object_release( p_input );

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
911
 * VLC_FullScreen: toggle fullscreen mode
912
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
913
int VLC_FullScreen( int i_object )
914 915
{
    vout_thread_t *p_vout;
Sam Hocevar's avatar
Sam Hocevar committed
916 917 918 919 920 921 922 923
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

    if( !p_vlc )
    {
        return VLC_ESTATUS;
    }
924 925 926 927 928 929 930 931 932 933 934 935 936 937

    p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );

    if( !p_vout )
    {
        return VLC_EOBJECT;
    }

    p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
    vlc_object_release( p_vout );

    return VLC_SUCCESS;
}

938 939 940 941 942 943 944 945 946 947 948 949 950 951
/* following functions are local */

/*****************************************************************************
 * GetFilenames: parse command line options which are not flags
 *****************************************************************************
 * Parse command line for input files.
 *****************************************************************************/
static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
{
    int i_opt;

    /* We assume that the remaining parameters are filenames */
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
Sam Hocevar committed
952 953 954
        /* TODO: write an internal function of this one, to avoid
         *       unnecessary lookups. */
        VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ i_opt ],
955
                          PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
956 957 958 959 960 961 962 963 964 965
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Usage: print program usage
 *****************************************************************************
 * Print a short inline help. Message interface is initialized at this stage.
 *****************************************************************************/
966
static void Usage( vlc_t *p_this, const char *psz_module_name )
967
{
Sam Hocevar's avatar
Sam Hocevar committed
968 969 970 971 972 973 974 975
#define FORMAT_STRING "      --%s%s%s%s%s%s%s %s%s\n"
    /* option name -------------'     | | | |  | |
     * <bra --------------------------' | | |  | |
     * option type or "" ---------------' | |  | |
     * ket> ------------------------------' |  | |
     * padding spaces ----------------------'  | |
     * comment --------------------------------' |
     * comment suffix ---------------------------'
976 977 978 979 980
     *
     * The purpose of having bra and ket is that we might i18n them as well.
     */
#define LINE_START 8
#define PADDING_SPACES 25
981 982
    vlc_list_t *p_list;
    module_t **pp_parser;
983 984 985 986 987 988 989 990 991 992 993 994 995
    module_config_t *p_item;
    char psz_spaces[PADDING_SPACES+LINE_START+1];
    char psz_format[sizeof(FORMAT_STRING)];

    memset( psz_spaces, ' ', PADDING_SPACES+LINE_START );
    psz_spaces[PADDING_SPACES+LINE_START] = '\0';

    strcpy( psz_format, FORMAT_STRING );

#ifdef WIN32
    ShowConsole();
#endif

996 997 998
    /* List all modules */
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );

999
    /* Enumerate the config for each module */
1000 1001 1002
    for( pp_parser = (module_t **)p_list->pp_objects ;
         *pp_parser ;
         pp_parser++ )
1003
    {
1004
        vlc_bool_t b_help_module;
1005 1006

        if( psz_module_name && strcmp( psz_module_name,
1007
                                       (*pp_parser)->psz_object_name ) )
Sam Hocevar's avatar
Sam Hocevar committed
1008
        {
1009
            continue;
Sam Hocevar's avatar
Sam Hocevar committed
1010
        }
1011 1012

        /* Ignore modules without config options */
1013
        if( !(*pp_parser)->i_config_items )
Sam Hocevar's avatar
Sam Hocevar committed
1014 1015 1016
        {
            continue;
        }
1017

1018
        b_help_module = !strcmp( "help", (*pp_parser)->psz_object_name );
1019

1020
        /* Print module options */
1021
        for( p_item = (*pp_parser)->p_config;
Gildas Bazin's avatar
 
Gildas Bazin committed
1022
             p_item->i_type != CONFIG_HINT_END;
1023 1024 1025
             p_item++ )
        {
            char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
Sam Hocevar's avatar
Sam Hocevar committed
1026
            char *psz_suf = "", *psz_prefix = NULL;
1027 1028 1029 1030
            int i;

            switch( p_item->i_type )
            {
Gildas Bazin's avatar
 
Gildas Bazin committed
1031 1032
            case CONFIG_HINT_CATEGORY:
            case CONFIG_HINT_USAGE:
1033 1034 1035
                fprintf( stderr, " %s\n", p_item->psz_text );
                break;

Gildas Bazin's avatar
 
Gildas Bazin committed
1036 1037 1038
            case CONFIG_ITEM_STRING:
            case CONFIG_ITEM_FILE:
            case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
                if( !p_item->ppsz_list )
                {
                    psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
                    break;
                }
                else
                {
                    psz_bra = " [";
                    psz_type = malloc( 1000 );
                    memset( psz_type, 0, 1000 );
                    for( i=0; p_item->ppsz_list[i]; i++ )
                    {
                        strcat( psz_type, p_item->ppsz_list[i] );
                        strcat( psz_type, "|" );
                    }
                    psz_type[ strlen( psz_type ) - 1 ] = '\0';
                    psz_ket = "]";
                    break;
                }
Gildas Bazin's avatar
 
Gildas Bazin committed
1058
            case CONFIG_ITEM_INTEGER:
1059 1060
                psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
1061
            case CONFIG_ITEM_FLOAT:
1062 1063
                psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
1064
            case CONFIG_ITEM_BOOL:
1065 1066 1067 1068 1069 1070 1071 1072 1073
                psz_bra = ""; psz_type = ""; psz_ket = "";
                if( !b_help_module )
                {
                    psz_suf = p_item->i_value ? _(" (default enabled)") :
                                                _(" (default disabled)");
                }
                break;
            }

1074
            /* Add short option if any */
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
            if( p_item->i_short )
            {
                psz_format[2] = '-';
                psz_format[3] = p_item->i_short;
                psz_format[4] = ',';
            }
            else
            {
                psz_format[2] = ' ';
                psz_format[3] = ' ';
                psz_format[4] = ' ';
            }

            if( psz_type )
            {
                i = PADDING_SPACES - strlen( p_item->psz_name )
                     - strlen( psz_bra ) - strlen( psz_type )
                     - strlen( psz_ket ) - 1;
Gildas Bazin's avatar
 
Gildas Bazin committed
1093
                if( p_item->i_type == CONFIG_ITEM_BOOL
1094 1095
                     && !b_help_module )
                {
1096 1097 1098 1099
                    /* If option is of type --foo-bar, we print its counterpart
                     * as --no-foo-bar, but if it is of type --foobar (without
                     * dashes in the name) we print it as --nofoobar. Both
                     * values are of course valid, only the display changes. */
Sam Hocevar's avatar
Sam Hocevar committed
1100
                    vlc_bool_t b_dash = VLC_FALSE;
Sam Hocevar's avatar
Sam Hocevar committed
1101 1102 1103 1104 1105
                    psz_prefix = p_item->psz_name;
                    while( *psz_prefix )
                    {
                        if( *psz_prefix++ == '-' )
                        {
Sam Hocevar's avatar
Sam Hocevar committed
1106
                            b_dash = VLC_TRUE;
Sam Hocevar's avatar
Sam Hocevar committed
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
                            break;
                        }
                    }

                    if( b_dash )
                    {
                        psz_prefix = ", --no-";
                        i -= strlen( p_item->psz_name ) + strlen( ", --no-" );
                    }
                    else
                    {
                        psz_prefix = ", --no";
                        i -= strlen( p_item->psz_name ) + strlen( ", --no" );
                    }
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
                }

                if( i < 0 )
                {
                    i = 0;
                    psz_spaces[i] = '\n';
                }
                else
                {
                    psz_spaces[i] = '\0';
                }

Gildas Bazin's avatar
 
Gildas Bazin committed
1133
                if( p_item->i_type == CONFIG_ITEM_BOOL &&
Sam Hocevar's avatar
Sam Hocevar committed
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
                    !b_help_module )
                {
                    fprintf( stderr, psz_format, p_item->psz_name, psz_prefix,
                             p_item->psz_name, psz_bra, psz_type, psz_ket,
                             psz_spaces, p_item->psz_text, psz_suf );
                }
                else
                {
                    fprintf( stderr, psz_format, p_item->psz_name, "", "",
                             psz_bra, psz_type, psz_ket, psz_spaces,
                             p_item->psz_text, psz_suf );
                }
1146
                psz_spaces[i] = ' ';
1147 1148 1149 1150
                if ( p_item->ppsz_list )
                {
                    free( psz_type );
                }
1151 1152 1153 1154
            }
        }
    }

1155 1156 1157
    /* Release the module list */
    vlc_list_release( p_list );

1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
        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.
 *****************************************************************************/
1170
static void ListModules( vlc_t *p_this )
1171
{
1172 1173
    vlc_list_t *p_list;
    module_t **pp_parser;
1174 1175 1176 1177 1178 1179 1180 1181 1182
    char psz_spaces[22];

    memset( psz_spaces, ' ', 22 );

#ifdef WIN32
    ShowConsole();
#endif

    /* Usage */
1183
    fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
1184 1185 1186 1187
                     p_this->p_vlc->psz_object_name );

    fprintf( stderr, _("[module]              [description]\n") );

1188 1189 1190
    /* List all modules */
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );

1191
    /* Enumerate each module */
1192 1193 1194
    for( pp_parser = (module_t **)p_list->pp_objects ;
         *pp_parser ;
         pp_parser++ )
1195 1196 1197 1198 1199
    {
        int i;

        /* Nasty hack, but right now I'm too tired to think about a nice
         * solution */
1200
        i = 22 - strlen( (*pp_parser)->psz_object_name ) - 1;
1201 1202 1203
        if( i < 0 ) i = 0;
        psz_spaces[i] = 0;

1204 1205
        fprintf( stderr, "  %s%s %s\n", (*pp_parser)->psz_object_name,
                         psz_spaces, (*pp_parser)->psz_longname );
1206 1207 1208 1209

        psz_spaces[i] = ' ';
    }

1210 1211
    vlc_list_release( p_list );

1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
        getchar();
#endif
}

/*****************************************************************************
 * Version: print complete program version
 *****************************************************************************
 * Print complete program version and build number.
 *****************************************************************************/
static void Version( void )
{
#ifdef WIN32
    ShowConsole();
#endif

    fprintf( stderr, VERSION_MESSAGE "\n" );
    fprintf( stderr,
      _("This program comes with NO WARRANTY, to the extent permitted by "
        "law.\nYou may redistribute it under the terms of the GNU General "
        "Public License;\nsee the file named COPYING for details.\n"
        "Written by the VideoLAN team at Ecole Centrale, Paris.\n") );

#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
    fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
    getchar();
#endif
}

/*****************************************************************************
 * ShowConsole: On Win32, create an output console for debug messages
 *****************************************************************************
 * This function is useful only on Win32.
 *****************************************************************************/
#ifdef WIN32 /*  */
static void ShowConsole( void )
{
    AllocConsole();
    freopen( "CONOUT$", "w", stdout );
    freopen( "CONOUT$", "w", stderr );
    freopen( "CONIN$", "r", stdin );
    return;
}
#endif