libvlc.c 41.1 KB
Newer Older
1 2 3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2002 VideoLAN
5
 * $Id: libvlc.c,v 1.63 2003/02/06 23:59:40 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
#define __BUILTIN__

/*****************************************************************************
 * Preamble
 *****************************************************************************/
36 37 38 39 40
#include <vlc/vlc.h>

#ifdef HAVE_ERRNO_H
#   include <errno.h>                                              /* ENOMEM */
#endif
41 42 43 44 45 46 47 48 49 50
#include <stdio.h>                                              /* sprintf() */
#include <string.h>                                            /* strerror() */
#include <stdlib.h>                                                /* free() */

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

#ifdef HAVE_UNISTD_H
#   include <unistd.h>
51
#elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
52 53 54
#   include <io.h>
#endif

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

59 60 61 62 63
#ifdef HAVE_LOCALE_H
#   include <locale.h>
#endif

#include "vlc_cpu.h"                                        /* CPU detection */
64
#include "os_specific.h"
65

66
#include "error.h"
67 68 69 70 71
#include "netutils.h"                                 /* network_ChannelJoin */

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

72
#include "vlc_playlist.h"
73 74 75 76 77 78 79 80 81 82
#include "interface.h"

#include "audio_output.h"

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

#include "libvlc.h"

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

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
91
static void SetLanguage   ( char const * );
92
static int  GetFilenames  ( vlc_t *, int, char *[] );
93
static void Usage         ( vlc_t *, char const *psz_module_name );
94
static void ListModules   ( vlc_t * );
95 96 97 98 99 100 101
static void Version       ( void );

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

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

111 112 113 114 115 116 117 118 119 120
/*****************************************************************************
 * VLC_Error: strerror() equivalent
 *****************************************************************************
 * This function returns full version string (numeric version and codename).
 *****************************************************************************/
char const * VLC_Error( int i_err )
{
    return vlc_error( i_err );
}

Sam Hocevar's avatar
Sam Hocevar committed
121 122 123 124 125 126 127
/*****************************************************************************
 * 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 )
128
{
129
    int i_ret;
130
    vlc_t * p_vlc = NULL;
131
    vlc_value_t lockval;
132

133 134 135
    /* 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
136
    if( i_ret < 0 )
137
    {
Sam Hocevar's avatar
Sam Hocevar committed
138
        return i_ret;
139 140 141
    }

    /* Now that the thread system is initialized, we don't have much, but
142 143 144 145
     * at least we have var_Create */
    var_Create( &libvlc, "libvlc", VLC_VAR_MUTEX );
    var_Get( &libvlc, "libvlc", &lockval );
    vlc_mutex_lock( lockval.p_address );
146 147
    if( !libvlc.b_ready )
    {
148 149
        char *psz_env;

150 151 152
        /* Guess what CPU we have */
        libvlc.i_cpu = CPUCapabilities();

153 154
        /* Find verbosity from VLC_VERBOSE environment variable */
        psz_env = getenv( "VLC_VERBOSE" );
155
        libvlc.i_verbose = psz_env ? atoi( psz_env ) : -1;
156 157 158 159 160 161 162

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

163 164 165 166 167 168 169
        /* 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 );

170 171
        /* The module bank will be initialized later */
        libvlc.p_module_bank = NULL;
172 173

        libvlc.b_ready = VLC_TRUE;
174
    }
175 176
    vlc_mutex_unlock( lockval.p_address );
    var_Destroy( &libvlc, "libvlc" );
177 178 179

    /* Allocate a vlc object */
    p_vlc = vlc_object_create( &libvlc, VLC_OBJECT_VLC );
180 181
    if( p_vlc == NULL )
    {
Sam Hocevar's avatar
Sam Hocevar committed
182
        return VLC_EGENERIC;
183 184 185 186 187
    }

    p_vlc->psz_object_name = "root";

    /* Initialize mutexes */
188
    vlc_mutex_init( p_vlc, &p_vlc->config_lock );
189 190

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

Sam Hocevar's avatar
Sam Hocevar committed
193 194 195 196
    /* Store data for the non-reentrant API */
    p_static_vlc = p_vlc;

    return p_vlc->i_object_id;
197 198 199
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
200
 * VLC_Init: initialize a vlc_t structure.
201 202 203 204 205 206 207
 *****************************************************************************
 * 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
208
int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
209
{
210 211
    char         p_capabilities[200];
    char *       p_tmp;
212 213
    char *       psz_modules;
    char *       psz_parser;
214
    vlc_bool_t   b_exit = VLC_FALSE;
Sam Hocevar's avatar
Sam Hocevar committed
215
    vlc_t *      p_vlc;
216 217
    module_t    *p_help_module;
    playlist_t  *p_playlist;
218
    vlc_value_t  lockval;
219

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

222
    if( !p_vlc )
223
    {
224
        return VLC_ENOOBJ;
225 226 227
    }

    /*
228
     * System specific initialization code
229
     */
230
    system_Init( p_vlc, &i_argc, ppsz_argv );
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

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

247 248 249 250
    /*
     * Support for gettext
     */
    SetLanguage( "" );
Sam Hocevar's avatar
Sam Hocevar committed
251 252

    /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
253 254
    msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );

255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
    /* Initialize the module bank 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) */
    var_Create( &libvlc, "libvlc", VLC_VAR_MUTEX );
    var_Get( &libvlc, "libvlc", &lockval );
    vlc_mutex_lock( lockval.p_address );
    if( libvlc.p_module_bank == NULL )
    {
        module_InitBank( &libvlc );
        module_LoadMain( &libvlc );
    }
    vlc_mutex_unlock( lockval.p_address );
    var_Destroy( &libvlc, "libvlc" );

270 271 272 273
    /* Hack: insert the help module here */
    p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
    if( p_help_module == NULL )
    {
274
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
275
        if( i_object ) vlc_object_release( p_vlc );
276 277 278 279
        return VLC_EGENERIC;
    }
    p_help_module->psz_object_name = "help";
    config_Duplicate( p_help_module, p_help_config );
280
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
281 282
    /* End hack */

Sam Hocevar's avatar
Sam Hocevar committed
283
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
284
    {
285
        vlc_object_detach( p_help_module );
286 287
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
288
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
289
        if( i_object ) vlc_object_release( p_vlc );
290 291 292 293 294 295
        return VLC_EGENERIC;
    }

    /* Check for short help option */
    if( config_GetInt( p_vlc, "help" ) )
    {
296
        fprintf( stdout, _("Usage: %s [options] [items]...\n\n"),
297
                         p_vlc->psz_object_name );
298
        Usage( p_vlc, "main" );
299 300
        Usage( p_vlc, "help" );
        b_exit = VLC_TRUE;
301 302
    }
    /* Check for version option */
303
    else if( config_GetInt( p_vlc, "version" ) )
304 305
    {
        Version();
306 307 308 309 310 311 312 313 314
        b_exit = VLC_TRUE;
    }

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

    if( b_exit )
    {
315 316
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
317
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
318
        if( i_object ) vlc_object_release( p_vlc );
319 320 321 322 323 324 325 326 327
        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.
     */
328 329
    module_LoadBuiltins( &libvlc );
    module_LoadPlugins( &libvlc );
330
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
331
                    libvlc.p_module_bank->i_children );
332 333

    /* Hack: insert the help module here */
334
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
335 336 337 338 339
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
340
        Usage( p_vlc, p_tmp );
341
        free( p_tmp );
342
        b_exit = VLC_TRUE;
343 344
    }
    /* Check for long help option */
345
    else if( config_GetInt( p_vlc, "longhelp" ) )
346
    {
347
        Usage( p_vlc, NULL );
348
        b_exit = VLC_TRUE;
349 350
    }
    /* Check for module list option */
351
    else if( config_GetInt( p_vlc, "list" ) )
352
    {
353
        ListModules( p_vlc );
354
        b_exit = VLC_TRUE;
355 356 357
    }

    /* Hack: remove the help module here */
358
    vlc_object_detach( p_help_module );
359 360 361 362
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

363 364
    if( b_exit )
    {
365
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
366
        if( i_object ) vlc_object_release( p_vlc );
367 368 369
        return VLC_EEXIT;
    }

370 371 372 373
    /*
     * Override default configuration with config file settings
     */
    p_vlc->psz_homedir = config_GetHomeDir();
374
    config_LoadConfigFile( p_vlc, NULL );
375 376 377 378

    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
379
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
380 381 382 383 384 385 386 387
    {
#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
388
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
389
        if( i_object ) vlc_object_release( p_vlc );
390 391 392 393 394 395
        return VLC_EGENERIC;
    }

    /*
     * System specific configuration
     */
396
    system_Configure( p_vlc );
397

398 399 400 401 402
    /*
     * Message queue options
     */
    if( config_GetInt( p_vlc, "quiet" ) )
    {
403
        libvlc.i_verbose = -1;
404 405 406 407
    }
    else
    {
        int i_tmp = config_GetInt( p_vlc, "verbose" );
408
        if( i_tmp >= 0 )
409
        {
410
            libvlc.i_verbose = __MIN( i_tmp, 2 );
411 412 413 414
        }
    }
    libvlc.b_color = libvlc.b_color || config_GetInt( p_vlc, "color" );

415 416 417 418 419 420 421
    /*
     * 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;
422

423
#if defined( __i386__ )
424
    if( !config_GetInt( p_vlc, "mmx" ) )
425
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
426
    if( !config_GetInt( p_vlc, "3dn" ) )
427
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
428
    if( !config_GetInt( p_vlc, "mmxext" ) )
429
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
430
    if( !config_GetInt( p_vlc, "sse" ) )
431
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
432 433
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
434
    if( !config_GetInt( p_vlc, "altivec" ) )
435
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
436
#endif
437 438

#define PRINT_CAPABILITY( capability, string )                              \
439
    if( libvlc.i_cpu & capability )                                         \
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
    {                                                                       \
        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
     */
461
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
462

463
    if( p_vlc->pf_memcpy == NULL )
464 465 466
    {
        p_vlc->pf_memcpy = memcpy;
    }
467 468 469 470 471

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
472 473 474 475 476

    /*
     * Initialize shared resources and libraries
     */
    if( config_GetInt( p_vlc, "network-channel" )
477
         && network_ChannelCreate( p_vlc ) )
478 479
    {
        /* On error during Channels initialization, switch off channels */
480 481
        msg_Warn( p_vlc,
                  "channels initialization failed, deactivating channels" );
Sam Hocevar's avatar
Sam Hocevar committed
482
        config_PutInt( p_vlc, "network-channel", VLC_FALSE );
483 484 485 486 487
    }

    /*
     * Initialize playlist and get commandline files
     */
488
    p_playlist = playlist_Create( p_vlc );
489 490 491
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
492 493
        if( p_vlc->p_memcpy_module != NULL )
        {
494
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
495
        }
496
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
497
        if( i_object ) vlc_object_release( p_vlc );
498 499 500
        return VLC_EGENERIC;
    }

501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
        char *psz_module;
        psz_module = psz_parser;
        psz_parser = strchr( psz_module, ',' );
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
        VLC_AddIntf( 0, psz_module, VLC_FALSE );
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
522

523 524 525 526 527
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );

528 529 530 531 532
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

Gildas Bazin's avatar
 
Gildas Bazin committed
533
    if( i_object ) vlc_object_release( p_vlc );
534 535 536 537
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
538
 * VLC_AddIntf: add an interface
539 540
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
541 542
 * 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
543 544
 * user requests to quit.
 *****************************************************************************/
545
int VLC_AddIntf( int i_object, char const *psz_module, vlc_bool_t b_block )
546
{
Sam Hocevar's avatar
Sam Hocevar committed
547
    int i_err;
548
    intf_thread_t *p_intf;
Sam Hocevar's avatar
Sam Hocevar committed
549
    vlc_t *p_vlc;
550

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

553
    if( !p_vlc )
554
    {
555
        return VLC_ENOOBJ;
556 557 558
    }

    /* Try to create the interface */
559
    p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
560 561 562 563

    if( p_intf == NULL )
    {
        msg_Err( p_vlc, "interface initialization failed" );
Gildas Bazin's avatar
 
Gildas Bazin committed
564
        if( i_object ) vlc_object_release( p_vlc );
565 566 567 568 569
        return VLC_EGENERIC;
    }

    /* Try to run the interface */
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
570 571
    i_err = intf_RunThread( p_intf );
    if( i_err )
572
    {
573
        vlc_object_detach( p_intf );
574
        intf_Destroy( p_intf );
Gildas Bazin's avatar
 
Gildas Bazin committed
575
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
576
        return i_err;
577 578
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
579
    if( i_object ) vlc_object_release( p_vlc );
580 581 582 583
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
584
 * VLC_Destroy: stop playing and destroy everything.
585
 *****************************************************************************
586
 * This function requests the running threads to finish, waits for their
587 588
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
589
int VLC_Destroy( int i_object )
590
{
Sam Hocevar's avatar
Sam Hocevar committed
591 592 593
    vlc_t *p_vlc;

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

595
    if( !p_vlc )
596
    {
597
        return VLC_ENOOBJ;
598 599
    }

600 601 602 603
    /*
     * Go back into channel 0 which is the network
     */
    if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
604
    {
605 606
        network_ChannelJoin( p_vlc, COMMON_CHANNEL );
    }
607

608 609 610 611 612 613 614
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
615 616
    }

617 618 619 620 621
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
622

623 624 625 626
    /*
     * XXX: Free module bank !
     */
    //module_EndBank( p_vlc );
627

628 629 630 631
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
632

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

636 637
    vlc_object_detach( p_vlc );

638 639 640
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

641 642
    vlc_object_destroy( p_vlc );

643 644 645
    /* Stop thread system: last one out please shut the door! */
    vlc_threads_end( &libvlc );

646 647 648
    return VLC_SUCCESS;
}

649
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
650
 * VLC_Die: ask vlc to die.
651 652
 *****************************************************************************
 * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
Sam Hocevar's avatar
Sam Hocevar committed
653
 * task. It is your duty to call vlc_end and VLC_Destroy afterwards.
654
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
655
int VLC_Die( int i_object )
656
{
Sam Hocevar's avatar
Sam Hocevar committed
657 658 659
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
663
        return VLC_ENOOBJ;
664 665 666 667
    }

    p_vlc->b_die = VLC_TRUE;

Gildas Bazin's avatar
 
Gildas Bazin committed
668
    if( i_object ) vlc_object_release( p_vlc );
669 670 671 672
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
673
 * VLC_AddTarget: adds a target for playing.
674 675 676 677
 *****************************************************************************
 * This function adds psz_target to the current playlist. If a playlist does
 * not exist, it will create one.
 *****************************************************************************/
678
int VLC_AddTarget( int i_object, char const *psz_target, int i_mode, int i_pos )
679
{
Sam Hocevar's avatar
Sam Hocevar committed
680
    int i_err;
Sam Hocevar's avatar
Sam Hocevar committed
681
    playlist_t *p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
682 683 684
    vlc_t *p_vlc;

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

686
    if( !p_vlc )
687
    {
688
        return VLC_ENOOBJ;
689 690
    }

Sam Hocevar's avatar
Sam Hocevar committed
691 692 693 694 695 696 697 698 699
    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 )
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
700
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
701 702 703 704 705 706
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
    }

Sam Hocevar's avatar
Sam Hocevar committed
707
    i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
Sam Hocevar's avatar
Sam Hocevar committed
708 709

    vlc_object_release( p_playlist );
710

Gildas Bazin's avatar
 
Gildas Bazin committed
711
    if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
712
    return i_err;
713 714
}

715
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
716
 * VLC_Set: set a vlc variable
717 718 719
 *****************************************************************************
 *
 *****************************************************************************/
720
int VLC_Set( int i_object, char const *psz_var, vlc_value_t value )
721
{
Sam Hocevar's avatar
Sam Hocevar committed
722
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
723
    int i_ret;
724

Sam Hocevar's avatar
Sam Hocevar committed
725
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
726 727 728

    if( !p_vlc )
    {
729
        return VLC_ENOOBJ;
730 731
    }

Sam Hocevar's avatar
Sam Hocevar committed
732 733 734
    /* 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 ) )
735
    {
Sam Hocevar's avatar
Sam Hocevar committed
736
        module_config_t *p_item;
737
        char const *psz_newvar = psz_var + 6;
738

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

Sam Hocevar's avatar
Sam Hocevar committed
741
        if( p_item )
742
        {
Sam Hocevar's avatar
Sam Hocevar committed
743
            switch( p_item->i_type )
744
            {
Sam Hocevar's avatar
Sam Hocevar committed
745 746 747 748 749 750 751 752 753 754 755 756
                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;
757
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
758
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
759
            return VLC_SUCCESS;
760 761 762
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
763 764 765 766
    i_ret = var_Set( p_vlc, psz_var, value );

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
767 768 769 770 771 772 773
}

/*****************************************************************************
 * VLC_Get: get a vlc variable
 *****************************************************************************
 *
 *****************************************************************************/
774
int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
775 776
{
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
777
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
778 779 780 781

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

    if( !p_vlc )
782
    {
783
        return VLC_ENOOBJ;
784 785
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
786 787 788 789
    i_ret = var_Get( p_vlc, psz_var, p_value );

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
790 791
}

Sam Hocevar's avatar
Sam Hocevar committed
792
/* FIXME: temporary hacks */
793 794

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
795
 * VLC_Play: play
796
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
797
int VLC_Play( int i_object )
798 799
{
    playlist_t * p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
800 801 802
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
805
    if( !p_vlc )
806
    {
807
        return VLC_ENOOBJ;
808
    }
809

810 811
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );

812 813 814 815
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
816
        if( i_object ) vlc_object_release( p_vlc );
817
        return VLC_ENOOBJ;
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
    }

    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 );

Gildas Bazin's avatar
 
Gildas Bazin committed
833
    if( i_object ) vlc_object_release( p_vlc );
834 835 836 837
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
838
 * VLC_Stop: stop
839
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
840
int VLC_Stop( int i_object )
841 842 843 844 845
{
    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
846 847 848
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
851
    if( !p_vlc )
852
    {
853
        return VLC_ENOOBJ;
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
    }

    /*
     * 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 );
888
        vout_Destroy( p_vout );
889 890 891 892 893 894 895 896 897 898 899 900 901
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
902
    if( i_object ) vlc_object_release( p_vlc );
903 904 905 906
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
907
 * VLC_Pause: toggle pause
908
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
909
int VLC_Pause( int i_object )
910 911
{
    input_thread_t *p_input;
Sam Hocevar's avatar
Sam Hocevar committed
912 913 914 915 916 917
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
918
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
919
    }
920 921 922 923 924

    p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );

    if( !p_input )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
925
        if( i_object ) vlc_object_release( p_vlc );
926
        return VLC_ENOOBJ;
927 928 929 930 931
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
932
    if( i_object ) vlc_object_release( p_vlc );
933 934 935 936
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
937
 * VLC_FullScreen: toggle fullscreen mode
938
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
939
int VLC_FullScreen( int i_object )
940 941
{
    vout_thread_t *p_vout;
Sam Hocevar's avatar
Sam Hocevar committed
942 943 944 945 946 947
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
948
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
949
    }
950 951 952 953 954

    p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );

    if( !p_vout )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
955
        if( i_object ) vlc_object_release( p_vlc );
956
        return VLC_ENOOBJ;
957 958 959 960 961
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
962
    if( i_object ) vlc_object_release( p_vlc );
963 964 965
    return VLC_SUCCESS;
}

966 967
/* following functions are local */

Sam Hocevar's avatar
Sam Hocevar committed
968 969 970 971 972 973 974 975 976
/*****************************************************************************
 * SetLanguage: set the interface language.
 *****************************************************************************
 * We set the LC_MESSAGES locale category for interface messages and buttons,
 * as well as the LC_CTYPE category for string sorting and possible wide
 * character support.
 *****************************************************************************/
static void SetLanguage ( char const *psz_lang )
{
977 978 979
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )

980 981 982 983 984
    char *          psz_path;
#ifdef SYS_DARWIN
    char            psz_tmp[1024];
#endif

985 986
#   if defined( HAVE_INCLUDED_GETTEXT ) && !defined( HAVE_LC_MESSAGES )
    if( *psz_lang )
Sam Hocevar's avatar
Sam Hocevar committed
987
    {
988 989 990 991 992 993 994 995
        /* We set LC_ALL manually because it is the only way to set
         * the language at runtime under eg. Windows. Beware that this
         * makes the environment unconsistent when libvlc is unloaded and
         * should probably be moved to a safer place like vlc.c. */
        static char psz_lcall[20];
        snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
        psz_lcall[19] = '\0';
        putenv( psz_lcall );
Sam Hocevar's avatar
Sam Hocevar committed
996
    }
997
#   endif
Sam Hocevar's avatar
Sam Hocevar committed
998

999 1000
#   if defined( HAVE_LC_MESSAGES )
    setlocale( LC_MESSAGES, psz_lang );
Sam Hocevar's avatar
Sam Hocevar committed
1001
#   endif
1002
    setlocale( LC_CTYPE, psz_lang );
Sam Hocevar's avatar
Sam Hocevar committed
1003

1004
    /* Specify where to find the locales for current domain */
1005 1006 1007
#ifndef SYS_DARWIN
    psz_path = LOCALEDIR;
#else
1008
    snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc.psz_vlcpath,
1009 1010 1011 1012
              "locale" );
    psz_path = psz_tmp;
#endif
    if( !bindtextdomain( PACKAGE, psz_path ) )
Sam Hocevar's avatar
Sam Hocevar committed
1013 1014
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
1015
                 PACKAGE, psz_path );
Sam Hocevar's avatar
Sam Hocevar committed
1016 1017
    }

1018
    /* Set the default domain */
Sam Hocevar's avatar
Sam Hocevar committed
1019 1020 1021 1022
    textdomain( PACKAGE );
#endif
}

1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
/*****************************************************************************
 * 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 */
1033
    for( i_opt = i_argc - 1; i_opt > optind; i_opt-- )
1034
    {
Sam Hocevar's avatar
Sam Hocevar committed
1035 1036 1037
        /* TODO: write an internal function of this one, to avoid
         *       unnecessary lookups. */
        VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ i_opt ],
1038 1039 1040 1041 1042 1043 1044 1045
                       PLAYLIST_INSERT, 0 );
    }

    /* If there is at least one target, play it */
    if( i_argc > optind )
    {
        VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ optind ],
                       PLAYLIST_INSERT | PLAYLIST_GO, 0 );
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Usage: print program usage
 *****************************************************************************
 * Print a short inline help. Message interface is initialized at this stage.
 *****************************************************************************/
1056
static void Usage( vlc_t *p_this, char const *psz_module_name )
1057
{
Sam Hocevar's avatar
Sam Hocevar committed
1058 1059 1060 1061 1062 1063 1064 1065
#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 ---------------------------'
1066 1067 1068 1069 1070
     *
     * The purpose of having bra and ket is that we might i18n them as well.
     */
#define LINE_START 8
#define PADDING_SPACES 25
1071
    vlc_list_t *p_list;
Gildas Bazin's avatar
 
Gildas Bazin committed
1072
    module_t *p_parser;
1073 1074 1075
    module_config_t *p_item;
    char psz_spaces[PADDING_SPACES+LINE_START+1];
    char psz_format[sizeof(FORMAT_STRING)];
Gildas Bazin's avatar
 
Gildas Bazin committed
1076
    int i_index;
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086

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

    strcpy( psz_format, FORMAT_STRING );

#ifdef WIN32
    ShowConsole();
#endif

1087
    /* List all modules */
1088
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1089

1090
    /* Enumerate the config for each module */
1091
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
1092
    {
1093
        vlc_bool_t b_help_module;
1094

1095
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
Gildas Bazin's avatar
 
Gildas Bazin committed
1096

1097
        if( psz_module_name && strcmp( psz_module_name,
Gildas Bazin's avatar
 
Gildas Bazin committed
1098
                                       p_parser->psz_object_name ) )
Sam Hocevar's avatar
Sam Hocevar committed
1099
        {
1100
            continue;
Sam Hocevar's avatar
Sam Hocevar committed
1101
        }
1102 1103

        /* Ignore modules without config options */
Gildas Bazin's avatar
 
Gildas Bazin committed
1104
        if( !p_parser->i_config_items )
Sam Hocevar's avatar
Sam Hocevar committed
1105 1106 1107
        {
            continue;
        }
1108

Gildas Bazin's avatar
 
Gildas Bazin committed
1109
        b_help_module = !strcmp( "help", p_parser->psz_object_name );
1110

1111
        /* Print module options */
Gildas Bazin's avatar
 
Gildas Bazin committed
1112
        for( p_item = p_parser->p_config;
Gildas Bazin's avatar
 
Gildas Bazin committed
1113
             p_item->i_type != CONFIG_HINT_END;
1114 1115 1116
             p_item++ )
        {
            char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
Sam Hocevar's avatar
Sam Hocevar committed
1117
            char *psz_suf = "", *psz_prefix = NULL;
1118 1119 1120 1121
            int i;

            switch( p_item->i_type )
            {
Gildas Bazin's avatar
 
Gildas Bazin committed
1122 1123
            case CONFIG_HINT_CATEGORY:
            case CONFIG_HINT_USAGE:
1124
                fprintf( stdout, " %s\n", p_item->psz_text );
1125 1126
                break;

Gildas Bazin's avatar
 
Gildas Bazin committed
1127 1128 1129
            case CONFIG_ITEM_STRING:
            case CONFIG_ITEM_FILE:
            case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
                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
1149
            case CONFIG_ITEM_INTEGER:
1150 1151
                psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
1152
            case CONFIG_ITEM_FLOAT:
1153 1154
                psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
                break;
Gildas Bazin's avatar