libvlc.c 77.4 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
        {
            msg_Err( p_vlc, "Unable to fork vlc to daemon mode" );
            b_exit = VLC_TRUE;
        }

        p_vlc->p_libvlc->b_daemon = VLC_TRUE;

422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
        /* lets check if we need to write the pidfile */
        char * psz_pidfile = config_GetPsz( p_vlc, "pidfile" );
        
        msg_Dbg( p_vlc, "psz_pidfile is %s", psz_pidfile );
        
        if( psz_pidfile != NULL )
        {
            FILE *pidfile;
            pid_t i_pid = getpid ();
            
            msg_Dbg( p_vlc, "our PID is %d, writing it to %s", i_pid, psz_pidfile );
            
            pidfile = utf8_fopen( psz_pidfile,"w" );
            if( pidfile != NULL )
            {
                utf8_fprintf( pidfile, "%d", (int)i_pid );
                fclose( pidfile );
            }
            else
            {
                msg_Err( p_vlc, "Cannot open pid file for writing: %s, error: %s", 
                        psz_pidfile, strerror(errno) );
            }
445 446
        }

447 448
        free( psz_pidfile );

449 450
#else
        pid_t i_pid;
Gildas Bazin's avatar
Gildas Bazin committed
451 452 453 454 455 456 457 458 459 460 461

        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;
462
            i_ret = VLC_EEXITSUCCESS;
Gildas Bazin's avatar
Gildas Bazin committed
463 464 465 466 467
        }
        else
        {
            /* We are the child */
            msg_Dbg( p_vlc, "daemon spawned" );
468 469 470
            close( STDIN_FILENO );
            close( STDOUT_FILENO );
            close( STDERR_FILENO );
Gildas Bazin's avatar
Gildas Bazin committed
471 472 473

            p_vlc->p_libvlc->b_daemon = VLC_TRUE;
        }
474
#endif
Gildas Bazin's avatar
Gildas Bazin committed
475 476 477
    }
#endif

478 479
    if( b_exit )
    {
480 481
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
482
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
483
        if( i_object ) vlc_object_release( p_vlc );
484
        return i_ret;
485 486
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
487
    /* Check for translation config option */
Gildas Bazin's avatar
 
Gildas Bazin committed
488 489
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
490
# if defined (WIN32) || defined (__APPLE__)
Gildas Bazin's avatar
 
Gildas Bazin committed
491 492 493 494 495
    /* 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 );

496 497 498
    /* 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
499
    {
500 501
        vlc_bool_t b_cache_delete = libvlc.p_module_bank->b_cache_delete;

Gildas Bazin's avatar
 
Gildas Bazin committed
502
        /* Reset the default domain */
503
        SetLanguage( psz_language );
504

Gildas Bazin's avatar
 
Gildas Bazin committed
505 506 507
        /* 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
508
        module_EndBank( p_vlc );
509
        module_InitBank( p_vlc );
510
        config_LoadConfigFile( p_vlc, "main" );
Gildas Bazin's avatar
 
Gildas Bazin committed
511
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
512
        libvlc.p_module_bank->b_cache_delete = b_cache_delete;
Gildas Bazin's avatar
 
Gildas Bazin committed
513
    }
514
    if( psz_language ) free( psz_language );
515
# endif
516
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
517

518 519 520 521 522 523
    /*
     * 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.
     */
524 525 526 527 528 529 530
    module_LoadBuiltins( p_vlc );
    module_LoadPlugins( p_vlc );
    if( p_vlc->b_die )
    {
        b_exit = VLC_TRUE;
    }

531
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
532
                    libvlc.p_module_bank->i_children );
533 534

    /* Hack: insert the help module here */
535
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
536 537 538 539 540
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
541
        Help( p_vlc, p_tmp );
542
        free( p_tmp );
543
        b_exit = VLC_TRUE;
544
        i_ret = VLC_EEXITSUCCESS;
545 546
    }
    /* Check for long help option */
547
    else if( config_GetInt( p_vlc, "longhelp" ) )
548
    {
549
        Help( p_vlc, "longhelp" );
550
        b_exit = VLC_TRUE;
551
        i_ret = VLC_EEXITSUCCESS;
552 553
    }
    /* Check for module list option */
554
    else if( config_GetInt( p_vlc, "list" ) )
555
    {
556
        ListModules( p_vlc );
557
        b_exit = VLC_TRUE;
558
        i_ret = VLC_EEXITSUCCESS;
559 560
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
    /* 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 );
    }

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

583 584
    if( b_exit )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
585 586
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
587
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
588
        if( i_object ) vlc_object_release( p_vlc );
589
        return i_ret;
590 591
    }

592 593 594 595 596
    /*
     * Init device values
     */
    InitDeviceValues( p_vlc );

597 598 599
    /*
     * Override default configuration with config file settings
     */
600
    config_LoadConfigFile( p_vlc, NULL );
601

Gildas Bazin's avatar
 
Gildas Bazin committed
602 603 604 605
    /* Hack: insert the help module here */
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
    /* End hack */

606 607 608
    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
609
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
610 611
    {
#ifdef WIN32
612
        ShowConsole( VLC_FALSE );
613 614
        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, "The command line options couldn't be loaded, check "
615 616
                 "that they are valid.\n" );
        PauseConsole();
617
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
618 619 620
        vlc_object_detach( p_help_module );
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
621
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
622
        if( i_object ) vlc_object_release( p_vlc );
623 624 625
        return VLC_EGENERIC;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
626 627 628 629 630 631
    /* 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 */

632 633 634
    /*
     * System specific configuration
     */
Gildas Bazin's avatar
 
Gildas Bazin committed
635
    system_Configure( p_vlc, &i_argc, ppsz_argv );
636

637 638 639
    /*
     * Message queue options
     */
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
640 641

    var_Create( p_vlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
642 643
    if( config_GetInt( p_vlc, "quiet" ) )
    {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
644 645
        val.i_int = -1;
        var_Set( p_vlc, "verbose", val );
646
    }
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
647 648
    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
649

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

652 653 654 655 656
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

657
    /* p_vlc initialization. FIXME ? */
658

659 660 661
    if( !config_GetInt( p_vlc, "fpu" ) )
        libvlc.i_cpu &= ~CPU_CAPABILITY_FPU;

Christophe Massiot's avatar
Christophe Massiot committed
662
#if defined( __i386__ ) || defined( __x86_64__ )
663
    if( !config_GetInt( p_vlc, "mmx" ) )
664
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
665
    if( !config_GetInt( p_vlc, "3dn" ) )
666
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
667
    if( !config_GetInt( p_vlc, "mmxext" ) )
668
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
669
    if( !config_GetInt( p_vlc, "sse" ) )
670
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
671 672
    if( !config_GetInt( p_vlc, "sse2" ) )
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE2;
673
#endif
674
#if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
675
    if( !config_GetInt( p_vlc, "altivec" ) )
676
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
677
#endif
678 679

#define PRINT_CAPABILITY( capability, string )                              \
680
    if( libvlc.i_cpu & capability )                                         \
681 682 683 684 685 686 687 688 689 690 691 692 693 694
    {                                                                       \
        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" );
695
    PRINT_CAPABILITY( CPU_CAPABILITY_SSE2, "SSE2" );
696 697 698 699 700 701 702
    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
703
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy", 0 );
704

705
    if( p_vlc->pf_memcpy == NULL )
706 707 708
    {
        p_vlc->pf_memcpy = memcpy;
    }
709 710 711 712 713

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

715
    libvlc.b_stats = config_GetInt( p_vlc, "stats" );
716 717 718
    libvlc.i_timers = 0;
    libvlc.pp_timers = NULL;
    vlc_mutex_init( p_vlc, &libvlc.timer_lock );
719

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
720 721 722 723
    /*
     * Initialize hotkey handling
     */
    var_Create( p_vlc, "key-pressed", VLC_VAR_INTEGER );
Gildas Bazin's avatar
 
Gildas Bazin committed
724 725
    p_vlc->p_hotkeys = malloc( sizeof(p_hotkeys) );
    /* Do a copy (we don't need to modify the strings) */
726
    memcpy( p_vlc->p_hotkeys, p_hotkeys, sizeof(p_hotkeys) );
Gildas Bazin's avatar
 
Gildas Bazin committed
727

728 729 730
    /*
     * Initialize playlist and get commandline files
     */
731
    p_playlist = playlist_ThreadCreate( p_vlc );
732 733 734
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
735 736
        if( p_vlc->p_memcpy_module != NULL )
        {
737
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
738
        }
739
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
740
        if( i_object ) vlc_object_release( p_vlc );
741 742 743
        return VLC_EGENERIC;
    }

744 745 746 747 748 749 750
    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 );
751

752 753 754 755
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
756 757 758 759 760 761
    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 );
762
        sprintf( psz_modules, "%s:%s", psz_modules, psz_control );
763 764 765 766 767 768 769
    }
    else if( psz_control && *psz_control )
    {
        if( psz_modules ) free( psz_modules );
        psz_modules = strdup( psz_control );
    }

770 771 772
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
773
        char *psz_module, *psz_temp;
774
        psz_module = psz_parser;
775
        psz_parser = strchr( psz_module, ':' );
776 777 778 779 780
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
781 782 783 784
        psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
        if( psz_temp )
        {
            sprintf( psz_temp, "%s,none", psz_module );
785
            VLC_AddIntf( 0, psz_temp, VLC_FALSE, VLC_FALSE );
Gildas Bazin's avatar
 
Gildas Bazin committed
786 787
            free( psz_temp );
        }
788 789 790 791 792
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
793

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
794
    /*
795
     * Always load the hotkeys interface if it exists
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
796
     */
797
    VLC_AddIntf( 0, "hotkeys,none", VLC_FALSE, VLC_FALSE );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
798

799 800 801 802 803 804 805
    /*
     * If needed, load the Xscreensaver interface
     * Currently, only for X
     */
#ifdef HAVE_X11_XLIB_H
    if( config_GetInt( p_vlc, "disable-screensaver" ) == 1 )
    {
806
        VLC_AddIntf( 0, "screensaver,none", VLC_FALSE, VLC_FALSE );
807 808 809
    }
#endif

810 811
    if( config_GetInt( p_vlc, "file-logging" ) == 1 )
    {
812
        VLC_AddIntf( 0, "logger,none", VLC_FALSE, VLC_FALSE );
813
    }
814
#ifdef HAVE_SYSLOG_H
815 816 817
    if( config_GetInt( p_vlc, "syslog" ) == 1 )
    {
        char *psz_logmode = "logmode=syslog";
818
        AddIntfInternal( 0, "logger,none", VLC_FALSE, VLC_FALSE, 1, &psz_logmode );
819
    }
820
#endif
821

822 823
    if( config_GetInt( p_vlc, "show-intf" ) == 1 )
    {
824
        VLC_AddIntf( 0, "showintf,none", VLC_FALSE, VLC_FALSE );
825 826 827 828
    }

    if( config_GetInt( p_vlc, "network-synchronisation") == 1 )
    {
829
        VLC_AddIntf( 0, "netsync,none", VLC_FALSE, VLC_FALSE );
830 831
    }

832 833 834 835
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );
836 837 838 839 840 841 842 843
    var_Create( p_vlc, "drawable-view-top", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawable-view-left", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawable-view-bottom", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawable-view-right", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawable-clip-top", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawable-clip-left", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawable-clip-bottom", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawable-clip-right", VLC_VAR_INTEGER );
844

845 846 847
    /* Create volume callback system. */
    var_Create( p_vlc, "volume-change", VLC_VAR_BOOL );

848 849 850 851 852
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

853 854 855 856 857 858 859 860 861 862 863 864
    /*
     * 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
865
    if( i_object ) vlc_object_release( p_vlc );
866 867 868 869
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
870
 * VLC_AddIntf: add an interface
871 872
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
873 874
 * 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
875 876
 * user requests to quit. If b_play is set to 1, VLC_AddIntf will start playing
 * the playlist when it is completely initialised.
877
 *****************************************************************************/
878 879
int VLC_AddIntf( int i_object, char const *psz_module,
                 vlc_bool_t b_block, vlc_bool_t b_play )
880
{
881
    return AddIntfInternal( i_object, psz_module, b_block, b_play, 0, NULL );
882 883
}

884

885
/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
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 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
 * 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
937
     * Free playlist
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
938
     */
Clément Stenac's avatar
Clément Stenac committed
939
    msg_Dbg( p_vlc, "removing playlist handler" );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
940 941 942 943 944
    while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
                                          FIND_CHILD )) )
    {
        vlc_object_detach( p_playlist );
        vlc_object_release( p_playlist );
945
        playlist_ThreadDestroy( p_playlist );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969
    }

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

970 971
    stats_TimersDumpAll( p_vlc );
    stats_TimersClean( p_vlc );
972

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
973 974 975 976 977
    /*
     * 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
978 979
    {
        msg_Dbg( p_vlc, "removing announce handler" );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
980 981 982
        vlc_object_detach( p_announce );
        vlc_object_release( p_announce );
        announce_HandlerDestroy( p_announce );
Clément Stenac's avatar
Clément Stenac committed
983
    }
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
984 985 986 987 988 989 990

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

/*****************************************************************************
 * VLC_Destroy: Destroy everything.
991
 *****************************************************************************
992
 * This function requests the running threads to finish, waits for their
993 994
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
995
int VLC_Destroy( int i_object )
996
{
997
    vlc_t *p_vlc = vlc_current_object( i_object );
998

999
    if( !p_vlc )
1000
    {
1001
        return VLC_ENOOBJ;
1002 1003
    }

1004 1005 1006 1007 1008 1009 1010
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
1011 1012
    }

1013
    /*
1014
     * Free module bank !
1015 1016 1017
     */
    module_EndBank( p_vlc );

1018 1019 1020 1021 1022
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
1023

1024 1025 1026 1027 1028 1029
    if( p_vlc->psz_userdir )
    {
        free( p_vlc->psz_userdir );
        p_vlc->psz_userdir = NULL;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
1030 1031 1032 1033 1034 1035
    if( p_vlc->psz_configfile )
    {
        free( p_vlc->psz_configfile );
        p_vlc->psz_configfile = NULL;
    }

1036 1037 1038 1039 1040 1041
    if( p_vlc->p_hotkeys )
    {
        free( p_vlc->p_hotkeys );
        p_vlc->p_hotkeys = NULL;
    }

1042 1043 1044 1045
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
1046

1047 1048 1049 1050 1051 1052 1053
    /*
     * Free message queue.
     * Nobody shall use msg_* afterward.
     */
    msg_Flush( p_vlc );
    msg_Destroy( p_libvlc );

1054
    /* Destroy global iconv */
1055
    LocaleDeinit();
1056

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

1060 1061
    vlc_object_detach( p_vlc );

1062 1063 1064
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

1065 1066
    vlc_object_destroy( p_vlc );

1067
    /* Stop thread system: last one out please shut the door! */
1068
    vlc_threads_end( p_libvlc );
1069

1070 1071 1072
    return VLC_SUCCESS;
}

1073
/*****************************************************************************
1074
 * VLC_VariableSet: set a vlc variable
1075
 *****************************************************************************/
1076
int VLC_VariableSet( int i_object, char const *psz_var, vlc_value_t value )
1077
{
1078
    vlc_t *p_vlc = vlc_current_object( i_object );
Gildas Bazin's avatar
 
Gildas Bazin committed
1079
    int i_ret;
1080 1081 1082

    if( !p_vlc )
    {
1083
        return VLC_ENOOBJ;
1084 1085
    }

Sam Hocevar's avatar
Sam Hocevar committed
1086 1087 1088
    /* 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 ) )
1089
    {
Sam Hocevar's avatar
Sam Hocevar committed
1090
        module_config_t *p_item;
1091
        char const *psz_newvar = psz_var + 6;
1092

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