libvlc.c 79.1 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_global_data_t   libvlc_global;
static libvlc_global_data_t * p_libvlc_global;
static libvlc_int_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 104 105 106
static int  GetFilenames  ( libvlc_int_t *, int, char *[] );
static void Help          ( libvlc_int_t *, char const *psz_help_name );
static void Usage         ( libvlc_int_t *, char const *psz_module_name );
static void ListModules   ( libvlc_int_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
static void InitDeviceValues( libvlc_int_t * );
119

120 121 122 123 124 125
/*****************************************************************************
 * 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.
 *****************************************************************************/
126
libvlc_int_t * vlc_current_object( int i_object )
127 128 129
{
    if( i_object )
    {
130
         return vlc_object_get( p_libvlc_global, i_object );
131 132 133 134 135
    }

    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
    libvlc_int_t * p_libvlc = NULL;
189
    vlc_value_t lockval;
190

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

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_global );
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_global, "libvlc", VLC_VAR_MUTEX );
    var_Get( p_libvlc_global, "libvlc", &lockval );
206
    vlc_mutex_lock( lockval.p_address );
207
    if( !libvlc_global.b_ready )
208
    {
209 210
        char *psz_env;

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

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

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

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

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

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

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

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

248
    p_libvlc->psz_object_name = "root";
249 250

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

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

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

263
    return p_libvlc->i_object_id;
264 265 266
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
267
 * VLC_Init: initialize a vlc_t structure.
268 269 270 271 272 273 274
 *****************************************************************************
 * 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
275
int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
276
{
277 278
    char         p_capabilities[200];
    char *       p_tmp;
279 280
    char *       psz_modules;
    char *       psz_parser;
281
    char *       psz_control;
282
    vlc_bool_t   b_exit = VLC_FALSE;
283
    int          i_ret = VLC_EEXIT;
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
    libvlc_int_t * p_libvlc = vlc_current_object( i_object );
294

295
    if( !p_libvlc )
296
    {
297
        return VLC_ENOOBJ;
298 299 300
    }

    /*
301
     * System specific initialization code
302
     */
303
    system_Init( p_libvlc, &i_argc, ppsz_argv );
304 305 306 307

    /* Get the executable name (similar to the basename command) */
    if( i_argc > 0 )
    {
308
        p_libvlc->psz_object_name = p_tmp = ppsz_argv[ 0 ];
309 310
        while( *p_tmp )
        {
311
            if( *p_tmp == '/' ) p_libvlc->psz_object_name = ++p_tmp;
312 313 314 315 316
            else ++p_tmp;
        }
    }
    else
    {
317
        p_libvlc->psz_object_name = "vlc";
318 319
    }

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

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

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

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

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

354
    if( config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE ) )
355
    {
356
        vlc_object_detach( p_help_module );
357 358
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
359 360
        module_EndBank( p_libvlc );
        if( i_object ) vlc_object_release( p_libvlc );
361 362 363 364
        return VLC_EGENERIC;
    }

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

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

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

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

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

    /* Check for daemon mode */
#ifndef WIN32
412
    if( config_GetInt( p_libvlc, "daemon" ) )
Gildas Bazin's avatar
Gildas Bazin committed
413
    {
414
#if HAVE_DAEMON
415
        if( daemon( 1, 0) != 0 )
416
        {
417
            msg_Err( p_libvlc, "Unable to fork vlc to daemon mode" );
418 419 420
            b_exit = VLC_TRUE;
        }

421
        p_libvlc->p_libvlc_global->b_daemon = VLC_TRUE;
422

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

448 449
        free( psz_pidfile );

450 451
#else
        pid_t i_pid;
Gildas Bazin's avatar
Gildas Bazin committed
452 453 454

        if( ( i_pid = fork() ) < 0 )
        {
455
            msg_Err( p_libvlc, "Unable to fork vlc to daemon mode" );
Gildas Bazin's avatar
Gildas Bazin committed
456 457 458 459 460
            b_exit = VLC_TRUE;
        }
        else if( i_pid )
        {
            /* This is the parent, exit right now */
461
            msg_Dbg( p_libvlc, "closing parent process" );
Gildas Bazin's avatar
Gildas Bazin committed
462
            b_exit = VLC_TRUE;
463
            i_ret = VLC_EEXITSUCCESS;
Gildas Bazin's avatar
Gildas Bazin committed
464 465 466 467
        }
        else
        {
            /* We are the child */
468
            msg_Dbg( p_libvlc, "daemon spawned" );
469 470 471
            close( STDIN_FILENO );
            close( STDOUT_FILENO );
            close( STDERR_FILENO );
Gildas Bazin's avatar
Gildas Bazin committed
472

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

479 480
    if( b_exit )
    {
481 482
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
483 484
        module_EndBank( p_libvlc );
        if( i_object ) vlc_object_release( p_libvlc );
485
        return i_ret;
486 487
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
488
    /* Check for translation config option */
Gildas Bazin's avatar
 
Gildas Bazin committed
489 490
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
491
# if defined (WIN32) || defined (__APPLE__)
Gildas Bazin's avatar
 
Gildas Bazin committed
492 493
    /* This ain't really nice to have to reload the config here but it seems
     * the only way to do it. */
494 495
    config_LoadConfigFile( p_libvlc, "main" );
    config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE );
Gildas Bazin's avatar
 
Gildas Bazin committed
496

497
    /* Check if the user specified a custom language */
498
    psz_language = config_GetPsz( p_libvlc, "language" );
499
    if( psz_language && *psz_language && strcmp( psz_language, "auto" ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
500
    {
501
        vlc_bool_t b_cache_delete = libvlc_global.p_module_bank->b_cache_delete;
502

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

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

509 510 511 512 513
        module_EndBank( p_libvlc );
        module_InitBank( p_libvlc );
        config_LoadConfigFile( p_libvlc, "main" );
        config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE );
        libvlc_global.p_module_bank->b_cache_delete = b_cache_delete;
Gildas Bazin's avatar
 
Gildas Bazin committed
514
    }
515
    if( psz_language ) free( psz_language );
516
# endif
517
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
518

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

532 533
    msg_Dbg( p_libvlc, "module bank initialized, found %i modules",
                    libvlc_global.p_module_bank->i_children );
534 535

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
562
    /* Check for config file options */
563
    if( config_GetInt( p_libvlc, "reset-config" ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
564 565
    {
        vlc_object_detach( p_help_module );
566 567 568 569
        config_ResetAll( p_libvlc );
        config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE );
        config_SaveConfigFile( p_libvlc, NULL );
        vlc_object_attach( p_help_module, libvlc_global.p_module_bank );
Gildas Bazin's avatar
 
Gildas Bazin committed
570
    }
571
    if( config_GetInt( p_libvlc, "save-config" ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
572 573
    {
        vlc_object_detach( p_help_module );
574 575 576 577
        config_LoadConfigFile( p_libvlc, NULL );
        config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE );
        config_SaveConfigFile( p_libvlc, NULL );
        vlc_object_attach( p_help_module, libvlc_global.p_module_bank );
Gildas Bazin's avatar
 
Gildas Bazin committed
578 579
    }

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

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

593 594 595
    /*
     * Init device values
     */
596
    InitDeviceValues( p_libvlc );
597

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

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

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

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

633 634 635
    /*
     * System specific configuration
     */
636
    system_Configure( p_libvlc, &i_argc, ppsz_argv );
637

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

642 643
    var_Create( p_libvlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    if( config_GetInt( p_libvlc, "quiet" ) )
644
    {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
645
        val.i_int = -1;
646
        var_Set( p_libvlc, "verbose", val );
647
    }
648 649
    var_AddCallback( p_libvlc, "verbose", VerboseCallback, NULL );
    var_Change( p_libvlc, "verbose", VLC_VAR_TRIGGER_CALLBACKS, NULL, NULL );
Clément Stenac's avatar
Clément Stenac committed
650

651 652
    libvlc_global.b_color = libvlc_global.b_color && 
                                config_GetInt( p_libvlc, "color" );
653

654 655 656
    /*
     * Output messages that may still be in the queue
     */
657
    msg_Flush( p_libvlc );
658

659
    /* p_libvlc initialization. FIXME ? */
660

661 662
    if( !config_GetInt( p_libvlc, "fpu" ) )
        libvlc_global.i_cpu &= ~CPU_CAPABILITY_FPU;
663

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

#define PRINT_CAPABILITY( capability, string )                              \
682
    if( libvlc_global.i_cpu & capability )                                         \
683 684 685 686 687 688 689 690 691 692 693 694 695 696
    {                                                                       \
        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" );
697
    PRINT_CAPABILITY( CPU_CAPABILITY_SSE2, "SSE2" );
698 699
    PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "AltiVec" );
    PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
700
    msg_Dbg( p_libvlc, "CPU has capabilities %s", p_capabilities );
701 702 703 704

    /*
     * Choose the best memcpy module
     */
705
    p_libvlc->p_memcpy_module = module_Need( p_libvlc, "memcpy", "$memcpy", 0 );
706

707
    if( p_libvlc->pf_memcpy == NULL )
708
    {
709
        p_libvlc->pf_memcpy = memcpy;
710
    }
711

712
    if( p_libvlc->pf_memset == NULL )
713
    {
714
        p_libvlc->pf_memset = memset;
715
    }
716

717 718 719 720
    p_libvlc->b_stats = config_GetInt( p_libvlc, "stats" );
    p_libvlc->i_timers = 0;
    p_libvlc->pp_timers = NULL;
    vlc_mutex_init( p_libvlc, &p_libvlc->timer_lock );
721

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

730 731 732
    /*
     * Initialize playlist and get commandline files
     */
733
    p_playlist = playlist_ThreadCreate( p_libvlc );
734 735
    if( !p_playlist )
    {
736 737
        msg_Err( p_libvlc, "playlist initialization failed" );
        if( p_libvlc->p_memcpy_module != NULL )
738
        {
739
            module_Unneed( p_libvlc, p_libvlc->p_memcpy_module );
740
        }
741 742
        module_EndBank( p_libvlc );
        if( i_object ) vlc_object_release( p_libvlc );
743 744 745
        return VLC_EGENERIC;
    }

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

754 755 756
    /*
     * Load background interfaces
     */
757 758
    psz_modules = config_GetPsz( p_libvlc, "extraintf" );
    psz_control = config_GetPsz( p_libvlc, "control" );
759 760 761 762 763

    if( psz_modules && *psz_modules && psz_control && *psz_control )
    {
        psz_modules = (char *)realloc( psz_modules, strlen( psz_modules ) +
                                                    strlen( psz_control ) + 1 );
764
        sprintf( psz_modules, "%s:%s", psz_modules, psz_control );
765 766 767 768 769 770 771
    }
    else if( psz_control && *psz_control )
    {
        if( psz_modules ) free( psz_modules );
        psz_modules = strdup( psz_control );
    }

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

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

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

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

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

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

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

847
    /* Create volume callback system. */
848
    var_Create( p_libvlc, "volume-change", VLC_VAR_BOOL );
849

850 851 852
    /*
     * Get input filenames given as commandline arguments
     */
853
    GetFilenames( p_libvlc, i_argc, ppsz_argv );
854

855 856 857
    /*
     * Get --open argument
     */
858 859
    var_Create( p_libvlc, "open", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Get( p_libvlc, "open", &val );
860 861
    if ( val.psz_string != NULL && *val.psz_string )
    {
862
        VLC_AddTarget( p_libvlc->i_object_id, val.psz_string, NULL, 0,
863 864 865 866
                       PLAYLIST_INSERT, 0 );
    }
    if ( val.psz_string != NULL ) free( val.psz_string );

867
    if( i_object ) vlc_object_release( p_libvlc );
868 869 870 871
    return VLC_SUCCESS;
}

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

886

887
/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
888 889 890 891 892 893 894
 * 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 )
{
895
    libvlc_int_t *p_libvlc = vlc_current_object( i_object );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
896

897
    if( !p_libvlc )
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
898 899 900 901
    {
        return VLC_ENOOBJ;
    }

902
    p_libvlc->b_die = VLC_TRUE;
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
903

904
    if( i_object ) vlc_object_release( p_libvlc );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
905 906 907 908 909 910 911 912 913 914 915 916 917
    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;
918
    libvlc_int_t *p_libvlc = vlc_current_object( i_object );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
919 920

    /* Check that the handle is valid */
921
    if( !p_libvlc )
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
922 923 924 925 926 927 928
    {
        return VLC_ENOOBJ;
    }

    /*
     * Ask the interfaces to stop and destroy them
     */