libvlc.c 76.7 KB
Newer Older
1 2 3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2006 the VideoLAN team
5
 * $Id$
6 7 8
 *
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
9
 *          Gildas Bazin <gbazin@videolan.org>
10
 *          Derk-Jan Hartman <hartman at videolan dot org>
11
 *          Rémi Denis-Courmont <rem # videolan : org>
12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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
Antoine Cellerier's avatar
Antoine Cellerier committed
25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 27 28 29 30 31
 *****************************************************************************/

/*****************************************************************************
 * Pretend we are a builtin module
 *****************************************************************************/
#define MODULE_NAME main
32
#define MODULE_PATH main
33 34 35 36 37
#define __BUILTIN__

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

41
#include <errno.h>                                                 /* ENOMEM */
42 43 44 45 46 47 48 49 50 51
#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>
Gildas Bazin's avatar
 
Gildas Bazin committed
52
#elif defined( WIN32 ) && !defined( UNDER_CE )
53 54 55
#   include <io.h>
#endif

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

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

64 65 66 67
#ifdef HAVE_HAL
#   include <hal/libhal.h>
#endif

68
#include "vlc_cpu.h"                                        /* CPU detection */
69
#include "os_specific.h"
70

71
#include "vlc_error.h"
72

73
#include "vlc_playlist.h"
74
#include "vlc_interface.h"
75 76 77

#include "audio_output.h"

78
#include "vlc_video.h"
79 80
#include "video_output.h"

81
#include "stream_output.h"
82
#include "charset.h"
83

84 85 86
#include "libvlc.h"

/*****************************************************************************
87
 * The evil global variable. We handle it with care, don't worry.
88
 *****************************************************************************/
89 90 91
static libvlc_t   libvlc;
static libvlc_t * p_libvlc;
static vlc_t *    p_static_vlc;
92 93 94 95

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
96 97 98 99
static int AddIntfInternal( int i_object, char const *psz_module,
                             vlc_bool_t b_block, vlc_bool_t b_play,
                             int i_options, char **ppsz_options );

100 101
void LocaleInit( vlc_object_t * );
void LocaleDeinit( void );
Sam Hocevar's avatar
Sam Hocevar committed
102
static void SetLanguage   ( char const * );
103
static int  GetFilenames  ( vlc_t *, int, char *[] );
104
static void Help          ( vlc_t *, char const *psz_help_name );
105
static void Usage         ( vlc_t *, char const *psz_module_name );
106
static void ListModules   ( vlc_t * );
107 108 109
static void Version       ( void );

#ifdef WIN32
110
static void ShowConsole   ( vlc_bool_t );
111
static void PauseConsole  ( void );
112
#endif
113
static int  ConsoleWidth  ( void );
114

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
115 116
static int  VerboseCallback( vlc_object_t *, char const *,
                             vlc_value_t, vlc_value_t, void * );
117

118 119
static void InitDeviceValues( vlc_t * );

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
/*****************************************************************************
 * vlc_current_object: return the current object.
 *****************************************************************************
 * If i_object is non-zero, return the corresponding object. Otherwise,
 * return the statically allocated p_vlc object.
 *****************************************************************************/
vlc_t * vlc_current_object( int i_object )
{
    if( i_object )
    {
         return vlc_object_get( p_libvlc, i_object );
    }

    return p_static_vlc;
}

136
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
137
 * VLC_Version: return the libvlc version.
138
 *****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
139
 * This function returns full version string (numeric version and codename).
140
 *****************************************************************************/
141
char const * VLC_Version( void )
142
{
Sam Hocevar's avatar
Sam Hocevar committed
143
    return VERSION_MESSAGE;
144 145
}

146
/*****************************************************************************
147
 * VLC_CompileBy, VLC_CompileHost, VLC_CompileDomain,
148 149 150 151 152
 * VLC_Compiler, VLC_Changeset
 *****************************************************************************/
#define DECLARE_VLC_VERSION( func, var )                                    \
char const * VLC_##func ( void )                                            \
{                                                                           \
153
    return VLC_##var ;                                                      \
154 155
}

156 157
DECLARE_VLC_VERSION( CompileBy, COMPILE_BY );
DECLARE_VLC_VERSION( CompileHost, COMPILE_HOST );
Christophe Mutricy's avatar
Typo  
Christophe Mutricy committed
158
DECLARE_VLC_VERSION( CompileDomain, COMPILE_DOMAIN );
159 160
DECLARE_VLC_VERSION( Compiler, COMPILER );

161
#ifndef HAVE_SHARED_LIBVLC
162 163 164 165 166
extern const char psz_vlc_changeset[];
char const * VLC_Changeset( void )
{
    return psz_vlc_changeset;
}
167
#endif
168

169 170 171 172 173 174 175 176 177 178
/*****************************************************************************
 * 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
179 180 181 182 183 184 185
/*****************************************************************************
 * 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 )
186
{
187
    int i_ret;
188
    vlc_t * p_vlc = NULL;
189
    vlc_value_t lockval;
190

191 192 193
    /* &libvlc never changes, so we can safely call this multiple times. */
    p_libvlc = &libvlc;

194 195
    /* vlc_threads_init *must* be the first internal call! No other call is
     * allowed before the thread system has been initialized. */
196
    i_ret = vlc_threads_init( p_libvlc );
Sam Hocevar's avatar
Sam Hocevar committed
197
    if( i_ret < 0 )
198
    {
Sam Hocevar's avatar
Sam Hocevar committed
199
        return i_ret;
200 201 202
    }

    /* Now that the thread system is initialized, we don't have much, but
203
     * at least we have var_Create */
204 205
    var_Create( p_libvlc, "libvlc", VLC_VAR_MUTEX );
    var_Get( p_libvlc, "libvlc", &lockval );
206
    vlc_mutex_lock( lockval.p_address );
207 208
    if( !libvlc.b_ready )
    {
209 210
        char *psz_env;

211 212 213
        /* Guess what CPU we have */
        libvlc.i_cpu = CPUCapabilities();

214 215
        /* Find verbosity from VLC_VERBOSE environment variable */
        psz_env = getenv( "VLC_VERBOSE" );
216
        libvlc.i_verbose = psz_env ? atoi( psz_env ) : -1;
217

Gildas Bazin's avatar
 
Gildas Bazin committed
218
#if defined( HAVE_ISATTY ) && !defined( WIN32 )
219 220 221 222 223
        libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
#else
        libvlc.b_color = VLC_FALSE;
#endif

224
        /* Initialize message queue */
225
        msg_Create( p_libvlc );
226 227

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

231 232
        /* The module bank will be initialized later */
        libvlc.p_module_bank = NULL;
233 234

        libvlc.b_ready = VLC_TRUE;
235
    }
236
    vlc_mutex_unlock( lockval.p_address );
237
    var_Destroy( p_libvlc, "libvlc" );
238 239

    /* Allocate a vlc object */
240
    p_vlc = vlc_object_create( p_libvlc, VLC_OBJECT_VLC );
241 242
    if( p_vlc == NULL )
    {
Sam Hocevar's avatar
Sam Hocevar committed
243
        return VLC_EGENERIC;
244
    }
245
    p_vlc->thread_id = 0;
246 247 248 249

    p_vlc->psz_object_name = "root";

    /* Initialize mutexes */
250
    vlc_mutex_init( p_vlc, &p_vlc->config_lock );
251
#ifdef __APPLE__
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
252
    vlc_mutex_init( p_vlc, &p_vlc->quicktime_lock );
253
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
254
#endif
255 256

    /* Store our newly allocated structure in the global list */
257
    vlc_object_attach( p_vlc, p_libvlc );
258

Sam Hocevar's avatar
Sam Hocevar committed
259 260 261 262
    /* Store data for the non-reentrant API */
    p_static_vlc = p_vlc;

    return p_vlc->i_object_id;
263 264 265
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
266
 * VLC_Init: initialize a vlc_t structure.
267 268 269 270 271 272 273
 *****************************************************************************
 * 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
274
int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
275
{
276 277
    char         p_capabilities[200];
    char *       p_tmp;
278 279
    char *       psz_modules;
    char *       psz_parser;
280
    char *       psz_control;
281
    vlc_bool_t   b_exit = VLC_FALSE;
282
    int          i_ret = VLC_EEXIT;
283
    vlc_t *      p_vlc = vlc_current_object( i_object );
284 285
    module_t    *p_help_module;
    playlist_t  *p_playlist;
286
    vlc_value_t  val;
287 288
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
Jean-Paul Saman's avatar
Jean-Paul Saman committed
289
# if defined (WIN32) || defined (__APPLE__)
290
    char *       psz_language;
Jean-Paul Saman's avatar
Jean-Paul Saman committed
291
#endif
292
#endif
293

294
    if( !p_vlc )
295
    {
296
        return VLC_ENOOBJ;
297 298 299
    }

    /*
300
     * System specific initialization code
301
     */
302
    system_Init( p_vlc, &i_argc, ppsz_argv );
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318

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

319 320 321 322
    /*
     * Support for gettext
     */
    SetLanguage( "" );
Sam Hocevar's avatar
Sam Hocevar committed
323

324 325 326 327
    /*
     * Global iconv, must be done after setlocale()
     * so that vlc_current_charset() works.
     */
328
    LocaleInit( (vlc_object_t *)p_vlc );
329

Sam Hocevar's avatar
Sam Hocevar committed
330
    /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
331 332
    msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );

333 334 335 336
    /* 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) */
337
    module_InitBank( p_vlc );
338

339 340 341 342
    /* Hack: insert the help module here */
    p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
    if( p_help_module == NULL )
    {
343
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
344
        if( i_object ) vlc_object_release( p_vlc );
345 346 347
        return VLC_EGENERIC;
    }
    p_help_module->psz_object_name = "help";
Gildas Bazin's avatar
 
Gildas Bazin committed
348
    p_help_module->psz_longname = N_("Help options");
349
    config_Duplicate( p_help_module, p_help_config );
350
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
351 352
    /* End hack */

Sam Hocevar's avatar
Sam Hocevar committed
353
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
354
    {
355
        vlc_object_detach( p_help_module );
356 357
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
358
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
359
        if( i_object ) vlc_object_release( p_vlc );
360 361 362 363 364 365
        return VLC_EGENERIC;
    }

    /* Check for short help option */
    if( config_GetInt( p_vlc, "help" ) )
    {
366
        Help( p_vlc, "help" );
367
        b_exit = VLC_TRUE;
368
        i_ret = VLC_EEXITSUCCESS;
369 370
    }
    /* Check for version option */
371
    else if( config_GetInt( p_vlc, "version" ) )
372 373
    {
        Version();
374
        b_exit = VLC_TRUE;
375
        i_ret = VLC_EEXITSUCCESS;
376 377
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
378 379
    /* Set the config file stuff */
    p_vlc->psz_homedir = config_GetHomeDir();
380 381 382
    p_vlc->psz_userdir = config_GetUserDir();
    if( p_vlc->psz_userdir == NULL )
        p_vlc->psz_userdir = strdup(p_vlc->psz_homedir);
Gildas Bazin's avatar
 
Gildas Bazin committed
383
    p_vlc->psz_configfile = config_GetPsz( p_vlc, "config" );
384 385 386
    if( p_vlc->psz_configfile != NULL && p_vlc->psz_configfile[0] == '~'
         && p_vlc->psz_configfile[1] == '/' )
    {
387
        char *psz = malloc( strlen(p_vlc->psz_userdir)
388 389
                             + strlen(p_vlc->psz_configfile) );
        /* This is incomplete : we should also support the ~cmassiot/ syntax. */
390
        sprintf( psz, "%s/%s", p_vlc->psz_userdir,
391 392 393 394
                               p_vlc->psz_configfile + 2 );
        free( p_vlc->psz_configfile );
        p_vlc->psz_configfile = psz;
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
395

396 397 398 399 400 401
    /* Check for plugins cache options */
    if( config_GetInt( p_vlc, "reset-plugins-cache" ) )
    {
        libvlc.p_module_bank->b_cache_delete = VLC_TRUE;
    }

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

Gildas Bazin's avatar
Gildas Bazin committed
406 407 408 409 410 411 412
    /* Will be re-done properly later on */
    p_vlc->p_libvlc->i_verbose = config_GetInt( p_vlc, "verbose" );

    /* Check for daemon mode */
#ifndef WIN32
    if( config_GetInt( p_vlc, "daemon" ) )
    {
413
#if HAVE_DAEMON
414
        if( daemon( 1, 0) != 0 )
415 416 417 418 419 420 421 422 423
        {
            msg_Err( p_vlc, "Unable to fork vlc to daemon mode" );
            b_exit = VLC_TRUE;
        }

        p_vlc->p_libvlc->b_daemon = VLC_TRUE;

#else
        pid_t i_pid;
Gildas Bazin's avatar
Gildas Bazin committed
424 425 426 427 428 429 430 431 432 433 434

        if( ( i_pid = fork() ) < 0 )
        {
            msg_Err( p_vlc, "Unable to fork vlc to daemon mode" );
            b_exit = VLC_TRUE;
        }
        else if( i_pid )
        {
            /* This is the parent, exit right now */
            msg_Dbg( p_vlc, "closing parent process" );
            b_exit = VLC_TRUE;
435
            i_ret = VLC_EEXITSUCCESS;
Gildas Bazin's avatar
Gildas Bazin committed
436 437 438 439 440
        }
        else
        {
            /* We are the child */
            msg_Dbg( p_vlc, "daemon spawned" );
441 442 443
            close( STDIN_FILENO );
            close( STDOUT_FILENO );
            close( STDERR_FILENO );
Gildas Bazin's avatar
Gildas Bazin committed
444 445 446

            p_vlc->p_libvlc->b_daemon = VLC_TRUE;
        }
447
#endif
Gildas Bazin's avatar
Gildas Bazin committed
448 449 450
    }
#endif

451 452
    if( b_exit )
    {
453 454
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
455
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
456
        if( i_object ) vlc_object_release( p_vlc );
457
        return i_ret;
458 459
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
460
    /* Check for translation config option */
Gildas Bazin's avatar
 
Gildas Bazin committed
461 462
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
463
# if defined (WIN32) || defined (__APPLE__)
Gildas Bazin's avatar
 
Gildas Bazin committed
464 465 466 467 468
    /* This ain't really nice to have to reload the config here but it seems
     * the only way to do it. */
    config_LoadConfigFile( p_vlc, "main" );
    config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );

469 470 471
    /* Check if the user specified a custom language */
    psz_language = config_GetPsz( p_vlc, "language" );
    if( psz_language && *psz_language && strcmp( psz_language, "auto" ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
472
    {
473 474
        vlc_bool_t b_cache_delete = libvlc.p_module_bank->b_cache_delete;

Gildas Bazin's avatar
 
Gildas Bazin committed
475
        /* Reset the default domain */
476
        SetLanguage( psz_language );
477

Gildas Bazin's avatar
 
Gildas Bazin committed
478 479 480
        /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
        msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );

Gildas Bazin's avatar
 
Gildas Bazin committed
481
        module_EndBank( p_vlc );
482
        module_InitBank( p_vlc );
483
        config_LoadConfigFile( p_vlc, "main" );
Gildas Bazin's avatar
 
Gildas Bazin committed
484
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
485
        libvlc.p_module_bank->b_cache_delete = b_cache_delete;
Gildas Bazin's avatar
 
Gildas Bazin committed
486
    }
487
    if( psz_language ) free( psz_language );
488
# endif
489
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
490

491 492 493 494 495 496
    /*
     * 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.
     */
497 498 499 500 501 502 503
    module_LoadBuiltins( p_vlc );
    module_LoadPlugins( p_vlc );
    if( p_vlc->b_die )
    {
        b_exit = VLC_TRUE;
    }

504
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
505
                    libvlc.p_module_bank->i_children );
506 507

    /* Hack: insert the help module here */
508
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
509 510 511 512 513
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
514
        Help( p_vlc, p_tmp );
515
        free( p_tmp );
516
        b_exit = VLC_TRUE;
517
        i_ret = VLC_EEXITSUCCESS;
518 519
    }
    /* Check for long help option */
520
    else if( config_GetInt( p_vlc, "longhelp" ) )
521
    {
522
        Help( p_vlc, "longhelp" );
523
        b_exit = VLC_TRUE;
524
        i_ret = VLC_EEXITSUCCESS;
525 526
    }
    /* Check for module list option */
527
    else if( config_GetInt( p_vlc, "list" ) )
528
    {
529
        ListModules( p_vlc );
530
        b_exit = VLC_TRUE;
531
        i_ret = VLC_EEXITSUCCESS;
532 533
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
    /* Check for config file options */
    if( config_GetInt( p_vlc, "reset-config" ) )
    {
        vlc_object_detach( p_help_module );
        config_ResetAll( p_vlc );
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
        config_SaveConfigFile( p_vlc, NULL );
        vlc_object_attach( p_help_module, libvlc.p_module_bank );
    }
    if( config_GetInt( p_vlc, "save-config" ) )
    {
        vlc_object_detach( p_help_module );
        config_LoadConfigFile( p_vlc, NULL );
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
        config_SaveConfigFile( p_vlc, NULL );
        vlc_object_attach( p_help_module, libvlc.p_module_bank );
    }

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

556 557
    if( b_exit )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
558 559
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
560
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
561
        if( i_object ) vlc_object_release( p_vlc );
562
        return i_ret;
563 564
    }

565 566 567 568 569
    /*
     * Init device values
     */
    InitDeviceValues( p_vlc );

570 571 572
    /*
     * Override default configuration with config file settings
     */
573
    config_LoadConfigFile( p_vlc, NULL );
574

Gildas Bazin's avatar
 
Gildas Bazin committed
575 576 577 578
    /* Hack: insert the help module here */
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
    /* End hack */

579 580 581
    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
582
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
583 584
    {
#ifdef WIN32
585
        ShowConsole( VLC_FALSE );
586 587
        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, "The command line options couldn't be loaded, check "
588 589
                 "that they are valid.\n" );
        PauseConsole();
590
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
591 592 593
        vlc_object_detach( p_help_module );
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
594
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
595
        if( i_object ) vlc_object_release( p_vlc );
596 597 598
        return VLC_EGENERIC;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
599 600 601 602 603 604
    /* Hack: remove the help module here */
    vlc_object_detach( p_help_module );
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

605 606 607
    /*
     * System specific configuration
     */
Gildas Bazin's avatar
 
Gildas Bazin committed
608
    system_Configure( p_vlc, &i_argc, ppsz_argv );
609

610 611 612
    /*
     * Message queue options
     */
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
613 614

    var_Create( p_vlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
615 616
    if( config_GetInt( p_vlc, "quiet" ) )
    {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
617 618
        val.i_int = -1;
        var_Set( p_vlc, "verbose", val );
619
    }
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
620 621
    var_AddCallback( p_vlc, "verbose", VerboseCallback, NULL );
    var_Change( p_vlc, "verbose", VLC_VAR_TRIGGER_CALLBACKS, NULL, NULL );
Clément Stenac's avatar
Clément Stenac committed
622

Gildas Bazin's avatar
 
Gildas Bazin committed
623
    libvlc.b_color = libvlc.b_color && config_GetInt( p_vlc, "color" );
624

625 626 627 628 629
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

630
    /* p_vlc initialization. FIXME ? */
631

632 633 634
    if( !config_GetInt( p_vlc, "fpu" ) )
        libvlc.i_cpu &= ~CPU_CAPABILITY_FPU;

Christophe Massiot's avatar
Christophe Massiot committed
635
#if defined( __i386__ ) || defined( __x86_64__ )
636
    if( !config_GetInt( p_vlc, "mmx" ) )
637
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
638
    if( !config_GetInt( p_vlc, "3dn" ) )
639
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
640
    if( !config_GetInt( p_vlc, "mmxext" ) )
641
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
642
    if( !config_GetInt( p_vlc, "sse" ) )
643
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
644 645
    if( !config_GetInt( p_vlc, "sse2" ) )
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE2;
646
#endif
647
#if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
648
    if( !config_GetInt( p_vlc, "altivec" ) )
649
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
650
#endif
651 652

#define PRINT_CAPABILITY( capability, string )                              \
653
    if( libvlc.i_cpu & capability )                                         \
654 655 656 657 658 659 660 661 662 663 664 665 666 667
    {                                                                       \
        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" );
668
    PRINT_CAPABILITY( CPU_CAPABILITY_SSE2, "SSE2" );
669 670 671 672 673 674 675
    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
     */
Gildas Bazin's avatar
 
Gildas Bazin committed
676
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy", 0 );
677

678
    if( p_vlc->pf_memcpy == NULL )
679 680 681
    {
        p_vlc->pf_memcpy = memcpy;
    }
682 683 684 685 686

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
687

688
    libvlc.b_stats = config_GetInt( p_vlc, "stats" );
689 690 691
    libvlc.i_timers = 0;
    libvlc.pp_timers = NULL;
    vlc_mutex_init( p_vlc, &libvlc.timer_lock );
692

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
693 694 695 696
    /*
     * Initialize hotkey handling
     */
    var_Create( p_vlc, "key-pressed", VLC_VAR_INTEGER );
Gildas Bazin's avatar
 
Gildas Bazin committed
697 698
    p_vlc->p_hotkeys = malloc( sizeof(p_hotkeys) );
    /* Do a copy (we don't need to modify the strings) */
699
    memcpy( p_vlc->p_hotkeys, p_hotkeys, sizeof(p_hotkeys) );
Gildas Bazin's avatar
 
Gildas Bazin committed
700

701 702 703
    /*
     * Initialize playlist and get commandline files
     */
704
    p_playlist = playlist_ThreadCreate( p_vlc );
705 706 707
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
708 709
        if( p_vlc->p_memcpy_module != NULL )
        {
710
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
711
        }
712
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
713
        if( i_object ) vlc_object_release( p_vlc );
714 715 716
        return VLC_EGENERIC;
    }

717 718 719 720 721 722 723
    psz_modules = config_GetPsz( p_playlist, "services-discovery" );
    if( psz_modules && *psz_modules )
    {
        /* Add service discovery modules */
        playlist_AddSDModules( p_playlist, psz_modules );
    }
    if( psz_modules ) free( psz_modules );
724

725 726 727 728
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
729 730 731 732 733 734
    psz_control = config_GetPsz( p_vlc, "control" );

    if( psz_modules && *psz_modules && psz_control && *psz_control )
    {
        psz_modules = (char *)realloc( psz_modules, strlen( psz_modules ) +
                                                    strlen( psz_control ) + 1 );
735
        sprintf( psz_modules, "%s:%s", psz_modules, psz_control );
736 737 738 739 740 741 742
    }
    else if( psz_control && *psz_control )
    {
        if( psz_modules ) free( psz_modules );
        psz_modules = strdup( psz_control );
    }

743 744 745
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
746
        char *psz_module, *psz_temp;
747
        psz_module = psz_parser;
748
        psz_parser = strchr( psz_module, ':' );
749 750 751 752 753
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
754 755 756 757
        psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
        if( psz_temp )
        {
            sprintf( psz_temp, "%s,none", psz_module );
758
            VLC_AddIntf( 0, psz_temp, VLC_FALSE, VLC_FALSE );
Gildas Bazin's avatar
 
Gildas Bazin committed
759 760
            free( psz_temp );
        }
761 762 763 764 765
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
766

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
767
    /*
768
     * Always load the hotkeys interface if it exists
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
769
     */
770
    VLC_AddIntf( 0, "hotkeys,none", VLC_FALSE, VLC_FALSE );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
771

772 773 774 775 776 777 778
    /*
     * If needed, load the Xscreensaver interface
     * Currently, only for X
     */
#ifdef HAVE_X11_XLIB_H
    if( config_GetInt( p_vlc, "disable-screensaver" ) == 1 )
    {
779
        VLC_AddIntf( 0, "screensaver,none", VLC_FALSE, VLC_FALSE );
780 781 782
    }
#endif

783 784
    if( config_GetInt( p_vlc, "file-logging" ) == 1 )
    {
785
        VLC_AddIntf( 0, "logger,none", VLC_FALSE, VLC_FALSE );
786
    }
787
#ifdef HAVE_SYSLOG_H
788 789 790
    if( config_GetInt( p_vlc, "syslog" ) == 1 )
    {
        char *psz_logmode = "logmode=syslog";
791
        AddIntfInternal( 0, "logger,none", VLC_FALSE, VLC_FALSE, 1, &psz_logmode );
792
    }
793
#endif
794

795 796
    if( config_GetInt( p_vlc, "show-intf" ) == 1 )
    {
797
        VLC_AddIntf( 0, "showintf,none", VLC_FALSE, VLC_FALSE );
798 799 800 801
    }

    if( config_GetInt( p_vlc, "network-synchronisation") == 1 )
    {
802
        VLC_AddIntf( 0, "netsync,none", VLC_FALSE, VLC_FALSE );
803 804
    }

805 806 807 808
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );
809 810 811 812 813 814 815 816 817 818 819
    var_Create( p_vlc, "drawableredraw", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawablet", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawablel", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawableb", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawabler", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawablex", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawabley", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawablew", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawableh", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawableportx", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawableporty", VLC_VAR_INTEGER );
820

821 822 823
    /* Create volume callback system. */
    var_Create( p_vlc, "volume-change", VLC_VAR_BOOL );

824 825 826 827 828
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

829 830 831 832 833 834 835 836 837 838 839 840
    /*
     * Get --open argument
     */
    var_Create( p_vlc, "open", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Get( p_vlc, "open", &val );
    if ( val.psz_string != NULL && *val.psz_string )
    {
        VLC_AddTarget( p_vlc->i_object_id, val.psz_string, NULL, 0,
                       PLAYLIST_INSERT, 0 );
    }
    if ( val.psz_string != NULL ) free( val.psz_string );

Gildas Bazin's avatar
 
Gildas Bazin committed
841
    if( i_object ) vlc_object_release( p_vlc );
842 843 844 845
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
846
 * VLC_AddIntf: add an interface
847 848
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
849 850
 * 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
851 852
 * user requests to quit. If b_play is set to 1, VLC_AddIntf will start playing
 * the playlist when it is completely initialised.
853
 *****************************************************************************/
854 855
int VLC_AddIntf( int i_object, char const *psz_module,
                 vlc_bool_t b_block, vlc_bool_t b_play )
856
{
857
    return AddIntfInternal( i_object, psz_module, b_block, b_play, 0, NULL );
858 859
}

860

861
/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
 * VLC_Die: ask vlc to die.
 *****************************************************************************
 * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
 * task. It is your duty to call VLC_CleanUp and VLC_Destroy afterwards.
 *****************************************************************************/
int VLC_Die( int i_object )
{
    vlc_t *p_vlc = vlc_current_object( i_object );

    if( !p_vlc )
    {
        return VLC_ENOOBJ;
    }

    p_vlc->b_die = VLC_TRUE;

    if( i_object ) vlc_object_release( p_vlc );
    return VLC_SUCCESS;
}

/*****************************************************************************
 * VLC_CleanUp: CleanUp all the intf, playlist, vout, aout
 *****************************************************************************/
int VLC_CleanUp( int i_object )
{
    intf_thread_t      * p_intf;
    playlist_t         * p_playlist;
    vout_thread_t      * p_vout;
    aout_instance_t    * p_aout;
    announce_handler_t * p_announce;
    vlc_t *p_vlc = vlc_current_object( i_object );

    /* Check that the handle is valid */
    if( !p_vlc )
    {
        return VLC_ENOOBJ;
    }

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

    /*
Clément Stenac's avatar
Clément Stenac committed
913
     * Free playlist
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
914
     */
Clément Stenac's avatar
Clément Stenac committed
915
    msg_Dbg( p_vlc, "removing playlist handler" );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
916 917 918 919 920
    while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
                                          FIND_CHILD )) )
    {
        vlc_object_detach( p_playlist );
        vlc_object_release( p_playlist );
921
        playlist_ThreadDestroy( p_playlist );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
    }

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

946 947
    stats_TimersDumpAll( p_vlc );
    stats_TimersClean( p_vlc );
948

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
949 950 951 952 953
    /*
     * Free announce handler(s?)
     */
    while( (p_announce = vlc_object_find( p_vlc, VLC_OBJECT_ANNOUNCE,
                                                 FIND_CHILD ) ) )
Clément Stenac's avatar
Clément Stenac committed
954 955
    {
        msg_Dbg( p_vlc, "removing announce handler" );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
956 957 958
        vlc_object_detach( p_announce );
        vlc_object_release( p_announce );
        announce_HandlerDestroy( p_announce );
Clément Stenac's avatar
Clément Stenac committed
959
    }
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
960 961 962 963 964 965 966

    if( i_object ) vlc_object_release( p_vlc );
    return VLC_SUCCESS;
}

/*****************************************************************************
 * VLC_Destroy: Destroy everything.
967
 *****************************************************************************
968
 * This function requests the running threads to finish, waits for their
969 970
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
971
int VLC_Destroy( int i_object )
972
{
973
    vlc_t *p_vlc = vlc_current_object( i_object );
974

975
    if( !p_vlc )
976
    {
977
        return VLC_ENOOBJ;
978 979
    }

980 981 982 983 984 985 986
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
987 988
    }

989
    /*
990
     * Free module bank !
991 992 993
     */
    module_EndBank( p_vlc );

994 995 996 997 998
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
999

1000 1001 1002 1003 1004 1005
    if( p_vlc->psz_userdir )
    {
        free( p_vlc->psz_userdir );
        p_vlc->psz_userdir = NULL;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
1006 1007 1008 1009 1010 1011
    if( p_vlc->psz_configfile )
    {
        free( p_vlc->psz_configfile );
        p_vlc->psz_configfile = NULL;
    }

1012 1013 1014 1015 1016 1017
    if( p_vlc->p_hotkeys )
    {
        free( p_vlc->p_hotkeys );
        p_vlc->p_hotkeys = NULL;
    }

1018 1019 1020 1021
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
1022

1023 1024 1025 1026 1027 1028 1029
    /*
     * Free message queue.
     * Nobody shall use msg_* afterward.
     */
    msg_Flush( p_vlc );
    msg_Destroy( p_libvlc );

1030
    /* Destroy global iconv */
1031
    LocaleDeinit();
1032

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

1036 1037
    vlc_object_detach( p_vlc );

1038 1039 1040
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

1041 1042
    vlc_object_destroy( p_vlc );

1043
    /* Stop thread system: last one out please shut the door! */
1044
    vlc_threads_end( p_libvlc );
1045

1046 1047 1048
    return VLC_SUCCESS;
}

1049
/*****************************************************************************
1050
 * VLC_VariableSet: set a vlc variable
1051
 *****************************************************************************/
1052
int VLC_VariableSet( int i_object, char const *psz_var, vlc_value_t value )
1053
{
1054
    vlc_t *p_vlc = vlc_current_object( i_object );
Gildas Bazin's avatar
 
Gildas Bazin committed
1055
    int i_ret;
1056 1057 1058

    if( !p_vlc )
    {
1059
        return VLC_ENOOBJ;
1060 1061
    }

Sam Hocevar's avatar
Sam Hocevar committed
1062 1063 1064
    /* 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 ) )
1065
    {
Sam Hocevar's avatar
Sam Hocevar committed
1066
        module_config_t *p_item;
1067
        char const *psz_newvar = psz_var + 6;
1068

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

Sam Hocevar's avatar
Sam Hocevar committed
1071
        if( p_item )
1072
        {
Sam Hocevar's avatar
Sam Hocevar committed
1073
            switch( p_item->i_type )
1074
            {
Sam Hocevar's avatar
Sam Hocevar committed
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
                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;