libvlc.c 81.5 KB
Newer Older
1 2 3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2004 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 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * 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
24
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 26 27 28 29 30
 *****************************************************************************/

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

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

40
#include <errno.h>                                                 /* ENOMEM */
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>
Gildas Bazin's avatar
 
Gildas Bazin committed
51
#elif 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
#ifdef HAVE_LOCALE_H
#   include <locale.h>
#endif

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

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

70
#include "vlc_error.h"
71

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

#include "audio_output.h"

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

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

83 84 85
#include "libvlc.h"

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

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
95 96 97 98
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 );

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

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

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

117 118
static void InitDeviceValues( vlc_t * );

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
/*****************************************************************************
 * 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;
}

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

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

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

extern const char psz_vlc_changeset[];
char const * VLC_Changeset( void )
{
    return psz_vlc_changeset;
}
165

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

188 189 190
    /* &libvlc never changes, so we can safely call this multiple times. */
    p_libvlc = &libvlc;

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

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

208 209 210
        /* Guess what CPU we have */
        libvlc.i_cpu = CPUCapabilities();

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

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

221
        /* Initialize message queue */
222
        msg_Create( p_libvlc );
223 224

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

228 229
        /* The module bank will be initialized later */
        libvlc.p_module_bank = NULL;
230 231

        libvlc.b_ready = VLC_TRUE;
232 233 234

        /* UTF-8 convertor are initialized after the locale */
        libvlc.from_locale = libvlc.to_locale = (vlc_iconv_t)(-1);
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 );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
251 252
#ifdef SYS_DARWIN
    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 ) )
289
    char *       psz_language;
290
#endif
291

292
    if( !p_vlc )
293
    {
294
        return VLC_ENOOBJ;
295 296 297
    }

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

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

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

322 323 324 325 326 327
    /*
     * Global iconv, must be done after setlocale()
     * so that vlc_current_charset() works.
     */
    LocaleInit();

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

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

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

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

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

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

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

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

Gildas Bazin's avatar
Gildas Bazin committed
404 405 406 407 408 409 410
    /* 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" ) )
    {
411
#if HAVE_DAEMON
412
        if( daemon( 1, 0) != 0 )
413 414 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;

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

        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;
433
            i_ret = VLC_EEXITSUCCESS;
Gildas Bazin's avatar
Gildas Bazin committed
434 435 436 437 438
        }
        else
        {
            /* We are the child */
            msg_Dbg( p_vlc, "daemon spawned" );
439 440 441
            close( STDIN_FILENO );
            close( STDOUT_FILENO );
            close( STDERR_FILENO );
Gildas Bazin's avatar
Gildas Bazin committed
442 443 444

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
458
    /* Check for translation config option */
Gildas Bazin's avatar
 
Gildas Bazin committed
459 460 461 462 463 464 465 466
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )

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

467 468 469
    /* 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
470
    {
471 472
        vlc_bool_t b_cache_delete = libvlc.p_module_bank->b_cache_delete;

Gildas Bazin's avatar
 
Gildas Bazin committed
473
        /* Reset the default domain */
474
        SetLanguage( psz_language );
475 476
        LocaleDeinit();
        LocaleInit();
Gildas Bazin's avatar
 
Gildas Bazin committed
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
Gildas Bazin's avatar
 
Gildas Bazin committed
489

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

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

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
    /* 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 );
    }

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

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

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

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

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
598 599 600 601 602 603
    /* 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 */

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

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

    var_Create( p_vlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
614 615
    if( config_GetInt( p_vlc, "quiet" ) )
    {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
616 617
        val.i_int = -1;
        var_Set( p_vlc, "verbose", val );
618
    }
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
619 620
    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
621

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

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

629
    /* p_vlc initialization. FIXME ? */
630

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

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

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

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

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

687 688
    libvlc.b_stats = config_GetInt( p_vlc, "stats" );

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

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

713 714 715 716 717 718 719
    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 );
720

721 722 723 724
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
725 726 727 728 729 730
    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 );
731
        sprintf( psz_modules, "%s:%s", psz_modules, psz_control );
732 733 734 735 736 737 738
    }
    else if( psz_control && *psz_control )
    {
        if( psz_modules ) free( psz_modules );
        psz_modules = strdup( psz_control );
    }

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

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
763
    /*
764
     * Always load the hotkeys interface if it exists
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
765
     */
766
    VLC_AddIntf( 0, "hotkeys,none", VLC_FALSE, VLC_FALSE );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
767

768 769 770 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 )
    {
        VLC_AddIntf( 0, "screensaver", VLC_FALSE, VLC_FALSE );
    }
#endif

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

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

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

801 802 803 804
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );
805 806 807 808 809 810 811 812 813 814 815
    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 );
816

817 818 819
    /* Create volume callback system. */
    var_Create( p_vlc, "volume-change", VLC_VAR_BOOL );

820 821 822 823 824
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

825 826 827 828 829 830 831 832 833 834 835 836
    /*
     * 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
837
    if( i_object ) vlc_object_release( p_vlc );
838 839 840 841
    return VLC_SUCCESS;
}

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

856

857
/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
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
 * 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;
888
    stats_handler_t    * p_stats;
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
    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
910
     * Free playlist
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
911
     */
Clément Stenac's avatar
Clément Stenac committed
912
    msg_Dbg( p_vlc, "removing playlist handler" );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
    while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
                                          FIND_CHILD )) )
    {
        vlc_object_detach( p_playlist );
        vlc_object_release( p_playlist );
        playlist_Destroy( p_playlist );
    }

    /*
     * Free video outputs
     */
    msg_Dbg( p_vlc, "removing all video outputs" );
    while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
    {
        vlc_object_detach( p_vout );
        vlc_object_release( p_vout );
        vout_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 );
    }

943 944
    while( ( p_stats = vlc_object_find( p_vlc, VLC_OBJECT_STATS, FIND_CHILD) ))
    {
945
        stats_TimersDumpAll( p_vlc );
Clément Stenac's avatar
Clément Stenac committed
946
        stats_HandlerDestroy( p_stats );
947 948 949 950 951
        vlc_object_detach( (vlc_object_t*) p_stats );
        vlc_object_release( (vlc_object_t *)p_stats );
        // TODO: Delete it
    }

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
952 953 954 955 956
    /*
     * 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
957 958
    {
        msg_Dbg( p_vlc, "removing announce handler" );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
959 960 961
        vlc_object_detach( p_announce );
        vlc_object_release( p_announce );
        announce_HandlerDestroy( p_announce );
Clément Stenac's avatar
Clément Stenac committed
962
    }
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
963 964 965 966 967 968 969

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

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

978
    if( !p_vlc )
979
    {
980
        return VLC_ENOOBJ;
981 982
    }

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

992
    /*
993
     * Free module bank !
994 995 996
     */
    module_EndBank( p_vlc );

997 998 999 1000 1001
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
1002

1003 1004 1005 1006 1007 1008
    if( p_vlc->psz_userdir )
    {
        free( p_vlc->psz_userdir );
        p_vlc->psz_userdir = NULL;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
1009 1010 1011 1012 1013 1014
    if( p_vlc->psz_configfile )
    {
        free( p_vlc->psz_configfile );
        p_vlc->psz_configfile = NULL;
    }

1015 1016 1017 1018 1019 1020
    if( p_vlc->p_hotkeys )
    {
        free( p_vlc->p_hotkeys );
        p_vlc->p_hotkeys = NULL;
    }

1021 1022 1023 1024
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
1025

1026 1027 1028 1029 1030 1031 1032
    /*
     * Free message queue.
     * Nobody shall use msg_* afterward.
     */
    msg_Flush( p_vlc );
    msg_Destroy( p_libvlc );

1033
    /* Destroy global iconv */
1034
    LocaleDeinit();
1035

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

1039 1040
    vlc_object_detach( p_vlc );

1041 1042 1043
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

1044 1045
    vlc_object_destroy( p_vlc );

1046
    /* Stop thread system: last one out please shut the door! */
1047
    vlc_threads_end( p_libvlc );
1048

1049 1050 1051
    return VLC_SUCCESS;
}

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

    if( !p_vlc )
    {
1062
        return VLC_ENOOBJ;
1063 1064
    }

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

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

Sam Hocevar's avatar
Sam Hocevar committed
1074
        if( p_item )
1075
        {
Sam Hocevar's avatar
Sam Hocevar committed
1076
            switch( p_item->i_type )
1077
            {
Sam Hocevar's avatar
Sam Hocevar committed
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
                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;
1090
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
1091
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
1092
            return VLC_SUCCESS;
1093 1094 1095
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
1096 1097 1098 1099
    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
1100 1101 1102
}

/*****************************************************************************
1103
 * VLC_VariableGet: get a vlc variable
Sam Hocevar's avatar
Sam Hocevar committed
1104
 *****************************************************************************/
1105
int VLC_VariableGet( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
1106
{
1107
    vlc_t *p_vlc = vlc_current_object( i_object );
Gildas Bazin's avatar
 
Gildas Bazin committed
1108
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
1109 1110

    if( !p_vlc )
1111
    {
1112
        return VLC_ENOOBJ;
1113 1114
    }

1115
    i_ret = var_Get( p_vlc , psz_var, p_value );
Gildas Bazin's avatar
 
Gildas Bazin committed
1116 1117 1118

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
1119 1120
}