libvlc.c 77.3 KB
Newer Older
1
2
3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2006 the VideoLAN team
zorglub's avatar
zorglub committed
5
 * $Id$
6
7
8
 *
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
9
 *          Gildas Bazin <gbazin@videolan.org>
hartman's avatar
hartman committed
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
dionoea's avatar
dionoea 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>
Laurent Aimar's avatar
Laurent Aimar committed
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>
gbazin's avatar
   
gbazin 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"

zorglub's avatar
zorglub committed
81
#include "stream_output.h"
82
#include "charset.h"
zorglub's avatar
zorglub committed
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

hartman's avatar
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

gbazin's avatar
   
gbazin 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__
hartman's avatar
hartman committed
252
    vlc_mutex_init( p_vlc, &p_vlc->quicktime_lock );
253
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );
hartman's avatar
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;
zorglub's avatar
zorglub committed
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 );
gbazin's avatar
   
gbazin committed
344
        if( i_object ) vlc_object_release( p_vlc );
345
346
347
        return VLC_EGENERIC;
    }
    p_help_module->psz_object_name = "help";
gbazin's avatar
   
gbazin 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 );
gbazin's avatar
   
gbazin 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
    }

gbazin's avatar
   
gbazin 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);
gbazin's avatar
   
gbazin 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;
    }
gbazin's avatar
   
gbazin 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 */

gbazin's avatar
gbazin 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
445
446
447
		/* lets check if we need to write the pidfile */
		p_vlc->psz_pidfile = config_GetPsz( p_vlc, "pidfile" );

		msg_Dbg( p_vlc, "p_vlc->psz_pidfile is %s", p_vlc->psz_pidfile );

		if( p_vlc->psz_pidfile != NULL )
		{
			pid_t i_pid;
			FILE *pidfile;
			
			i_pid = getpid();

			msg_Dbg( p_vlc, "our PID is %d, writing it to %s", i_pid, p_vlc->psz_pidfile );
			
			pidfile = utf8_fopen( p_vlc->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", p_vlc->psz_pidfile, strerror(errno) );
			}
        }

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

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

            p_vlc->p_libvlc->b_daemon = VLC_TRUE;
        }
473
#endif
gbazin's avatar
gbazin committed
474
475
476
    }
#endif

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

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

495
496
497
    /* Check if the user specified a custom language */
    psz_language = config_GetPsz( p_vlc, "language" );
    if( psz_language && *psz_language && strcmp( psz_language, "auto" ) )
gbazin's avatar
   
gbazin committed
498
    {
499
500
        vlc_bool_t b_cache_delete = libvlc.p_module_bank->b_cache_delete;

gbazin's avatar
   
gbazin committed
501
        /* Reset the default domain */
502
        SetLanguage( psz_language );
503

gbazin's avatar
   
gbazin committed
504
505
506
        /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
        msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );

gbazin's avatar
   
gbazin committed
507
        module_EndBank( p_vlc );
508
        module_InitBank( p_vlc );
509
        config_LoadConfigFile( p_vlc, "main" );
gbazin's avatar
   
gbazin committed
510
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
511
        libvlc.p_module_bank->b_cache_delete = b_cache_delete;
gbazin's avatar
   
gbazin committed
512
    }
513
    if( psz_language ) free( psz_language );
514
# endif
515
#endif
gbazin's avatar
   
gbazin committed
516

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

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

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

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

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

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

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

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

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

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

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

gbazin's avatar
   
gbazin committed
625
626
627
628
629
630
    /* 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 */

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

636
637
638
    /*
     * Message queue options
     */
hartman's avatar
hartman committed
639
640

    var_Create( p_vlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
641
642
    if( config_GetInt( p_vlc, "quiet" ) )
    {
hartman's avatar
hartman committed
643
644
        val.i_int = -1;
        var_Set( p_vlc, "verbose", val );
645
    }
hartman's avatar
hartman committed
646
647
    var_AddCallback( p_vlc, "verbose", VerboseCallback, NULL );
    var_Change( p_vlc, "verbose", VLC_VAR_TRIGGER_CALLBACKS, NULL, NULL );
zorglub's avatar
zorglub committed
648

gbazin's avatar
   
gbazin committed
649
    libvlc.b_color = libvlc.b_color && config_GetInt( p_vlc, "color" );
650

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

656
    /* p_vlc initialization. FIXME ? */
657

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

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

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

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

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

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

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

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

743
744
745
746
747
748
749
    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 );
zorglub's avatar
zorglub committed
750

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

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

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

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

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

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

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

831
832
833
834
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );
835
836
837
838
839
840
841
842
843
844
845
    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 );
846

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

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

855
856
857
858
859
860
861
862
863
864
865
866
    /*
     * 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 );

gbazin's avatar
   
gbazin committed
867
    if( i_object ) vlc_object_release( p_vlc );
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
/*****************************************************************************
hartman's avatar
hartman committed
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
937
938
 * 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 );
    }

    /*
zorglub's avatar
zorglub committed
939
     * Free playlist
hartman's avatar
hartman committed
940
     */
zorglub's avatar
zorglub committed
941
    msg_Dbg( p_vlc, "removing playlist handler" );
hartman's avatar
hartman committed
942
943
944
945
946
    while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
                                          FIND_CHILD )) )
    {
        vlc_object_detach( p_playlist );
        vlc_object_release( p_playlist );
947
        playlist_ThreadDestroy( p_playlist );
hartman's avatar
hartman committed
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
    }

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

972
973
    stats_TimersDumpAll( p_vlc );
    stats_TimersClean( p_vlc );
zorglub's avatar
zorglub committed
974

hartman's avatar
hartman committed
975
976
977
978
979
    /*
     * Free announce handler(s?)
     */
    while( (p_announce = vlc_object_find( p_vlc, VLC_OBJECT_ANNOUNCE,
                                                 FIND_CHILD ) ) )
zorglub's avatar
zorglub committed
980
981
    {
        msg_Dbg( p_vlc, "removing announce handler" );
hartman's avatar
hartman committed
982
983
984
        vlc_object_detach( p_announce );
        vlc_object_release( p_announce );
        announce_HandlerDestroy( p_announce );
zorglub's avatar
zorglub committed
985
    }
hartman's avatar
hartman committed
986
987
988
989
990
991
992

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

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

1001
    if( !p_vlc )
1002
    {
1003
        return VLC_ENOOBJ;
1004
1005
    }

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

1015
    /*
1016
     * Free module bank !
1017
1018
1019
     */
    module_EndBank( p_vlc );

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

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
1026
1027
1028
1029
1030
1031
    if( p_vlc->psz_userdir )
    {
        free( p_vlc->psz_userdir );
        p_vlc->psz_userdir = NULL;
    }

gbazin's avatar
   
gbazin committed
1032
1033
1034
1035
1036
1037
    if( p_vlc->psz_configfile )
    {
        free( p_vlc->psz_configfile );
        p_vlc->psz_configfile = NULL;
    }

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

1044
1045
1046
1047
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
1048

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

1056
    /* Destroy global iconv */
1057
    LocaleDeinit();
1058

1059
1060
1061
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

1062
1063
    vlc_object_detach( p_vlc );

1064
1065
1066
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

1067
1068
    vlc_object_destroy( p_vlc );

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

1072
1073
1074