libvlc.c 61.8 KB
Newer Older
1
/*****************************************************************************
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
2
 * libvlc.c: libvlc instances creation and deletion, interfaces handling
3
 *****************************************************************************
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
4
 * Copyright (C) 1998-2008 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
 *****************************************************************************/

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
28
29
30
/** \file
 * This file contains functions to create and destroy libvlc instances
 */
31
32
33
34

/*****************************************************************************
 * Preamble
 *****************************************************************************/
35
36
37
38
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

39
#include <vlc_common.h>
zorglub's avatar
zorglub committed
40
#include "control/libvlc_internal.h"
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
41
#include <vlc_input.h>
42

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
43
44
#include "modules/modules.h"
#include "config/configuration.h"
45

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
46
47
48
#include <stdio.h>                                              /* sprintf() */
#include <string.h>
#include <stdlib.h>                                                /* free() */
49

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
50
51
52
#ifndef WIN32
#   include <netinet/in.h>                            /* BSD: struct in_addr */
#endif
53

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
54
55
56
57
58
#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#elif defined( WIN32 ) && !defined( UNDER_CE )
#   include <io.h>
#endif
59

60
#include "config/vlc_getopt.h"
61

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
62
63
64
#ifdef HAVE_LOCALE_H
#   include <locale.h>
#endif
65

66
#ifdef HAVE_DBUS
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
67
68
69
/* used for one-instance mode */
#   include <dbus/dbus.h>
#endif
70

jetru's avatar
jetru committed
71
72

#include <vlc_media_library.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
73
74
#include <vlc_playlist.h>
#include <vlc_interface.h>
Sam Hocevar's avatar
Sam Hocevar committed
75

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
76
77
#include <vlc_aout.h>
#include "audio_output/aout_internal.h"
78

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
79
#include <vlc_charset.h>
80
#include <vlc_fs.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
81
#include <vlc_cpu.h>
82
#include <vlc_url.h>
83
#include <vlc_atomic.h>
84
#include <vlc_modules.h>
85

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
86
#include "libvlc.h"
87

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
88
#include "playlist/playlist_internal.h"
89

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
90
#include <vlc_vlm.h>
91

92
93
94
95
#ifdef __APPLE__
# include <libkern/OSAtomic.h>
#endif

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
96
#include <assert.h>
97

98
/*****************************************************************************
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
99
 * The evil global variables. We handle them with care, don't worry.
100
 *****************************************************************************/
101

102
#ifndef WIN32
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
103
static bool b_daemon = false;
104
#endif
105

106
107
108
#undef vlc_gc_init
#undef vlc_hold
#undef vlc_release
109

110
111
112
113
114
115
116
117
/**
 * Atomically set the reference count to 1.
 * @param p_gc reference counted object
 * @param pf_destruct destruction calback
 * @return p_gc.
 */
void *vlc_gc_init (gc_object_t *p_gc, void (*pf_destruct) (gc_object_t *))
{
geal's avatar
geal committed
118
    /* There is no point in using the GC if there is no destructor... */
119
    assert (pf_destruct);
120
121
    p_gc->pf_destructor = pf_destruct;

122
    vlc_atomic_set (&p_gc->refs, 1);
123
    return p_gc;
124
125
}

126
127
128
129
130
131
/**
 * Atomically increment the reference count.
 * @param p_gc reference counted object
 * @return p_gc.
 */
void *vlc_hold (gc_object_t * p_gc)
132
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
133
    uintptr_t refs;
134

135
    assert( p_gc );
136
    refs = vlc_atomic_inc (&p_gc->refs);
137
    assert (refs != 1); /* there had to be a reference already */
138
    return p_gc;
139
140
}

141
142
143
144
145
/**
 * Atomically decrement the reference count and, if it reaches zero, destroy.
 * @param p_gc reference counted object.
 */
void vlc_release (gc_object_t *p_gc)
146
{
147
    uintptr_t refs;
148
149

    assert( p_gc );
150
    refs = vlc_atomic_dec (&p_gc->refs);
151
152
    assert (refs != (uintptr_t)(-1)); /* reference underflow?! */
    if (refs == 0)
153
        p_gc->pf_destructor (p_gc);
154
155
}

156
/*****************************************************************************
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
157
 * Local prototypes
158
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Oops    
Rémi Denis-Courmont committed
159
160
161
162
#if defined( ENABLE_NLS ) && (defined (__APPLE__) || defined (WIN32)) && \
    ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
static void SetLanguage   ( char const * );
#endif
163
static void GetFilenames  ( libvlc_int_t *, unsigned, const char *const [] );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
164
static void Help          ( libvlc_int_t *, char const *psz_help_name );
165
static void Usage         ( libvlc_int_t *, char const *psz_search );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
166
167
168
169
170
171
172
173
static void ListModules   ( libvlc_int_t *, bool );
static void Version       ( void );

#ifdef WIN32
static void ShowConsole   ( bool );
static void PauseConsole  ( void );
#endif
static int  ConsoleWidth  ( void );
174

175
extern const char psz_vlc_changeset[];
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
176

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
177
178
179
180
181
182
183
184
185
186
187
188
189
/**
 * Allocate a libvlc instance, initialize global data if needed
 * It also initializes the threading system
 */
libvlc_int_t * libvlc_InternalCreate( void )
{
    libvlc_int_t *p_libvlc;
    libvlc_priv_t *priv;
    char *psz_env = NULL;

    /* Now that the thread system is initialized, we don't have much, but
     * at least we have variables */
    /* Allocate a libvlc instance object */
190
    p_libvlc = vlc_custom_create( (vlc_object_t *)NULL, sizeof (*priv),
191
                                  "libvlc" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
192
193
194
195
196
    if( p_libvlc == NULL )
        return NULL;

    priv = libvlc_priv (p_libvlc);
    priv->p_playlist = NULL;
jetru's avatar
jetru committed
197
    priv->p_ml = NULL;
198
    priv->p_dialog_provider = NULL;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
199
200
201
202
203
204
    priv->p_vlm = NULL;

    /* Find verbosity from VLC_VERBOSE environment variable */
    psz_env = getenv( "VLC_VERBOSE" );
    if( psz_env != NULL )
        priv->i_verbose = atoi( psz_env );
205
    else
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
206
207
208
209
210
211
212
213
        priv->i_verbose = 3;
#if defined( HAVE_ISATTY ) && !defined( WIN32 )
    priv->b_color = isatty( 2 ); /* 2 is for stderr */
#else
    priv->b_color = false;
#endif

    /* Initialize mutexes */
jetru's avatar
jetru committed
214
    vlc_mutex_init( &priv->ml_lock );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
215
    vlc_mutex_init( &priv->timer_lock );
216
    vlc_ExitInit( &priv->exit );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
217
218

    return p_libvlc;
hartman's avatar
hartman committed
219
220
221
}

/**
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
222
223
224
225
226
227
 * Initialize a libvlc instance
 * This function initializes a previously allocated libvlc instance:
 *  - CPU detection
 *  - gettext initialization
 *  - message queue, module bank and playlist initialization
 *  - configuration and commandline parsing
hartman's avatar
hartman committed
228
 */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
229
int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
230
                         const char *ppsz_argv[] )
hartman's avatar
hartman committed
231
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
232
233
234
235
236
237
238
239
    libvlc_priv_t *priv = libvlc_priv (p_libvlc);
    char *       p_tmp = NULL;
    char *       psz_modules = NULL;
    char *       psz_parser = NULL;
    char *       psz_control = NULL;
    bool   b_exit = false;
    int          i_ret = VLC_EEXIT;
    playlist_t  *p_playlist = NULL;
ivoire's avatar
ivoire committed
240
    char        *psz_val;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
241
242
243
244
245
246
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
# if defined (WIN32) || defined (__APPLE__)
    char *       psz_language;
#endif
#endif
hartman's avatar
hartman committed
247

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
248
    /* System specific initialization code */
249
    system_Init();
hartman's avatar
hartman committed
250

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
251
252
253
    /*
     * Support for gettext
     */
254
    vlc_bindtextdomain (PACKAGE_NAME);
hartman's avatar
hartman committed
255

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
256
257
258
259
    /* 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) */
260
    module_InitBank ();
hartman's avatar
hartman committed
261

262
    if( config_LoadCmdLine( p_libvlc, i_argc, ppsz_argv, NULL ) )
hartman's avatar
hartman committed
263
    {
264
        module_EndBank (false);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
265
        return VLC_EGENERIC;
hartman's avatar
hartman committed
266
267
    }

268
    priv->i_verbose = var_InheritInteger( p_libvlc, "verbose" );
269
    /* Announce who we are - Do it only for first instance ? */
270
    msg_Dbg( p_libvlc, "VLC media player - %s", VERSION_MESSAGE );
271
    msg_Dbg( p_libvlc, "%s", COPYRIGHT_MESSAGE );
272
273
    msg_Dbg( p_libvlc, "revision %s", psz_vlc_changeset );
    msg_Dbg( p_libvlc, "configured with %s", CONFIGURE_LINE );
274
    /*xgettext: Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
275
    msg_Dbg( p_libvlc, "translation test: code is \"%s\"", _("C") );
276

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
277
    /* Check for short help option */
278
    if( var_InheritBool( p_libvlc, "help" ) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
279
280
281
282
283
284
    {
        Help( p_libvlc, "help" );
        b_exit = true;
        i_ret = VLC_EEXITSUCCESS;
    }
    /* Check for version option */
285
    else if( var_InheritBool( p_libvlc, "version" ) )
hartman's avatar
hartman committed
286
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
287
288
289
        Version();
        b_exit = true;
        i_ret = VLC_EEXITSUCCESS;
hartman's avatar
hartman committed
290
291
    }

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
292
    /* Check for daemon mode */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
293
#if !defined( WIN32 ) && !defined( __SYMBIAN32__ )
294
    if( var_InheritBool( p_libvlc, "daemon" ) )
hartman's avatar
hartman committed
295
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
296
297
298
299
300
301
302
303
304
305
306
#ifdef HAVE_DAEMON
        char *psz_pidfile = NULL;

        if( daemon( 1, 0) != 0 )
        {
            msg_Err( p_libvlc, "Unable to fork vlc to daemon mode" );
            b_exit = true;
        }
        b_daemon = true;

        /* lets check if we need to write the pidfile */
307
        psz_pidfile = var_CreateGetNonEmptyString( p_libvlc, "pidfile" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
308
309
310
311
312
313
        if( psz_pidfile != NULL )
        {
            FILE *pidfile;
            pid_t i_pid = getpid ();
            msg_Dbg( p_libvlc, "PID is %d, writing it to %s",
                               i_pid, psz_pidfile );
314
            pidfile = vlc_fopen( psz_pidfile,"w" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
            if( pidfile != NULL )
            {
                utf8_fprintf( pidfile, "%d", (int)i_pid );
                fclose( pidfile );
            }
            else
            {
                msg_Err( p_libvlc, "cannot open pid file for writing: %s (%m)",
                         psz_pidfile );
            }
        }
        free( psz_pidfile );

#else
        pid_t i_pid;
hartman's avatar
hartman committed
330

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
        if( ( i_pid = fork() ) < 0 )
        {
            msg_Err( p_libvlc, "unable to fork vlc to daemon mode" );
            b_exit = true;
        }
        else if( i_pid )
        {
            /* This is the parent, exit right now */
            msg_Dbg( p_libvlc, "closing parent process" );
            b_exit = true;
            i_ret = VLC_EEXITSUCCESS;
        }
        else
        {
            /* We are the child */
            msg_Dbg( p_libvlc, "daemon spawned" );
            close( STDIN_FILENO );
            close( STDOUT_FILENO );
            close( STDERR_FILENO );

            b_daemon = true;
        }
#endif
    }
#endif
hartman's avatar
hartman committed
356

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
357
    if( b_exit )
hartman's avatar
hartman committed
358
    {
359
        module_EndBank (false);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
360
        return i_ret;
hartman's avatar
hartman committed
361
362
    }

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
363
364
365
366
    /* Check for translation config option */
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
# if defined (WIN32) || defined (__APPLE__)
367
    if( !var_InheritBool( p_libvlc, "ignore-config" ) )
368
        config_LoadConfigFile( p_libvlc );
369
    priv->i_verbose = var_InheritInteger( p_libvlc, "verbose" );
hartman's avatar
hartman committed
370

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
371
    /* Check if the user specified a custom language */
372
373
    psz_language = var_CreateGetNonEmptyString( p_libvlc, "language" );
    if( psz_language && strcmp( psz_language, "auto" ) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
    {
        /* Reset the default domain */
        SetLanguage( psz_language );

        /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
        msg_Dbg( p_libvlc, "translation test: code is \"%s\"", _("C") );
    }
    free( psz_language );
# endif
#endif

    /*
     * 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.
     */
391
    module_LoadPlugins( p_libvlc );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
392
    if( p_libvlc->b_die )
hartman's avatar
hartman committed
393
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
394
        b_exit = true;
hartman's avatar
hartman committed
395
396
    }

397
398
399
    size_t module_count;
    module_t **list = module_list_get( &module_count );
    module_list_free( list );
hartman's avatar
hartman committed
400
    msg_Dbg( p_libvlc, "module bank initialized (%zu modules)", module_count );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
401
402

    /* Check for help on modules */
403
    if( (p_tmp = var_InheritString( p_libvlc, "module" )) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
404
405
406
407
408
409
    {
        Help( p_libvlc, p_tmp );
        free( p_tmp );
        b_exit = true;
        i_ret = VLC_EEXITSUCCESS;
    }
410
    /* Check for full help option */
411
    else if( var_InheritBool( p_libvlc, "full-help" ) )
412
    {
413
414
415
416
        var_Create( p_libvlc, "advanced", VLC_VAR_BOOL );
        var_SetBool( p_libvlc, "advanced", true );
        var_Create( p_libvlc, "help-verbose", VLC_VAR_BOOL );
        var_SetBool( p_libvlc, "help-verbose", true );
417
418
419
420
        Help( p_libvlc, "full-help" );
        b_exit = true;
        i_ret = VLC_EEXITSUCCESS;
    }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
421
    /* Check for long help option */
422
    else if( var_InheritBool( p_libvlc, "longhelp" ) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
423
424
425
426
427
428
    {
        Help( p_libvlc, "longhelp" );
        b_exit = true;
        i_ret = VLC_EEXITSUCCESS;
    }
    /* Check for module list option */
429
    else if( var_InheritBool( p_libvlc, "list" ) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
430
431
432
433
434
    {
        ListModules( p_libvlc, false );
        b_exit = true;
        i_ret = VLC_EEXITSUCCESS;
    }
435
    else if( var_InheritBool( p_libvlc, "list-verbose" ) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
436
437
438
439
440
    {
        ListModules( p_libvlc, true );
        b_exit = true;
        i_ret = VLC_EEXITSUCCESS;
    }
hartman's avatar
hartman committed
441

442
    if( module_count <= 1 )
443
    {
444
        msg_Err( p_libvlc, "No plugins found! Check your VLC installation.");
445
446
447
448
        b_exit = true;
        i_ret = VLC_ENOITEM;
    }

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
449
    if( b_exit )
hartman's avatar
hartman committed
450
    {
451
        module_EndBank (true);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
452
        return i_ret;
hartman's avatar
hartman committed
453
    }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
454
455
456
457

    /*
     * Override default configuration with config file settings
     */
458
    if( !var_InheritBool( p_libvlc, "ignore-config" ) )
459
460
461
462
463
464
465
466
467
    {
        if( var_InheritBool( p_libvlc, "reset-config" ) )
        {
            config_ResetAll( p_libvlc );
            config_SaveConfigFile( p_libvlc );
        }
        else
            config_LoadConfigFile( p_libvlc );
    }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
468
469
470
471

    /*
     * Override configuration with command line settings
     */
472
473
    int vlc_optind;
    if( config_LoadCmdLine( p_libvlc, i_argc, ppsz_argv, &vlc_optind ) )
hartman's avatar
hartman committed
474
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
475
476
477
478
479
480
481
#ifdef WIN32
        ShowConsole( false );
        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, "The command line options couldn't be loaded, check "
                 "that they are valid.\n" );
        PauseConsole();
#endif
482
        module_EndBank (true);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
483
        return VLC_EGENERIC;
hartman's avatar
hartman committed
484
    }
485
    priv->i_verbose = var_InheritInteger( p_libvlc, "verbose" );
hartman's avatar
hartman committed
486

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
487
/* FIXME: could be replaced by using Unix sockets */
488
#ifdef HAVE_DBUS
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
489
    dbus_threads_init_default();
hartman's avatar
hartman committed
490

491
492
493
    if( var_InheritBool( p_libvlc, "one-instance" )
    || ( var_InheritBool( p_libvlc, "one-instance-when-started-from-file" )
      && var_InheritBool( p_libvlc, "started-from-file" ) ) )
hartman's avatar
hartman committed
494
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
        /* Initialise D-Bus interface, check for other instances */
        DBusConnection  *p_conn = NULL;
        DBusError       dbus_error;

        dbus_error_init( &dbus_error );

        /* connect to the session bus */
        p_conn = dbus_bus_get( DBUS_BUS_SESSION, &dbus_error );
        if( !p_conn )
        {
            msg_Err( p_libvlc, "Failed to connect to D-Bus session daemon: %s",
                    dbus_error.message );
            dbus_error_free( &dbus_error );
        }
        else
        {
            /* check if VLC is available on the bus
             * if not: D-Bus control is not enabled on the other
             * instance and we can't pass MRLs to it */
514
            DBusMessage *p_test_msg   = NULL;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
515
            DBusMessage *p_test_reply = NULL;
516

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
517
            p_test_msg =  dbus_message_new_method_call(
518
                    "org.mpris.MediaPlayer2.vlc", "/org/mpris/MediaPlayer2",
Rafaël Carré's avatar
Rafaël Carré committed
519
                    "org.freedesktop.DBus.Introspectable", "Introspect" );
520

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
            /* block until a reply arrives */
            p_test_reply = dbus_connection_send_with_reply_and_block(
                    p_conn, p_test_msg, -1, &dbus_error );
            dbus_message_unref( p_test_msg );
            if( p_test_reply == NULL )
            {
                dbus_error_free( &dbus_error );
                msg_Dbg( p_libvlc, "No Media Player is running. "
                        "Continuing normally." );
            }
            else
            {
                int i_input;
                DBusMessage* p_dbus_msg = NULL;
                DBusMessageIter dbus_args;
                DBusPendingCall* p_dbus_pending = NULL;
                dbus_bool_t b_play;

                dbus_message_unref( p_test_reply );
                msg_Warn( p_libvlc, "Another Media Player is running. Exiting");

542
                for( i_input = vlc_optind; i_input < i_argc;i_input++ )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
543
                {
544
545
546
547
548
549
550
551
                    /* Skip input options, we can't pass them through D-Bus */
                    if( ppsz_argv[i_input][0] == ':' )
                    {
                        msg_Warn( p_libvlc, "Ignoring option %s",
                                  ppsz_argv[i_input] );
                        continue;
                    }

552
553
                    /* We need to resolve relative paths in this instance */
                    char *psz_mrl = make_URI( ppsz_argv[i_input], NULL );
Rémi Denis-Courmont's avatar
Warning    
Rémi Denis-Courmont committed
554
                    const char *psz_after_track = "/";
555

556
557
                    if( psz_mrl == NULL )
                        continue;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
558
                    msg_Dbg( p_libvlc, "Adds %s to the running Media Player",
559
                             psz_mrl );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
560
561

                    p_dbus_msg = dbus_message_new_method_call(
562
563
                        "org.mpris.MediaPlayer2.vlc", "/org/mpris/MediaPlayer2",
                        "org.mpris.MediaPlayer2.TrackList", "AddTrack" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
564
565
566
567

                    if ( NULL == p_dbus_msg )
                    {
                        msg_Err( p_libvlc, "D-Bus problem" );
568
                        free( psz_mrl );
569
                        system_End( );
570
                        exit( 1 );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
571
572
573
574
575
                    }

                    /* append MRLs */
                    dbus_message_iter_init_append( p_dbus_msg, &dbus_args );
                    if ( !dbus_message_iter_append_basic( &dbus_args,
576
                                DBUS_TYPE_STRING, &psz_mrl ) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
577
578
                    {
                        dbus_message_unref( p_dbus_msg );
579
                        free( psz_mrl );
580
                        system_End( );
581
                        exit( 1 );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
582
                    }
583
                    free( psz_mrl );
584
585
586
587
588

                    if( !dbus_message_iter_append_basic( &dbus_args,
                                DBUS_TYPE_OBJECT_PATH, &psz_after_track ) )
                    {
                        dbus_message_unref( p_dbus_msg );
589
                        system_End( );
590
591
592
                        exit( 1 );
                    }

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
593
                    b_play = TRUE;
594
                    if( var_InheritBool( p_libvlc, "playlist-enqueue" ) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
595
                        b_play = FALSE;
596

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
597
598
599
600
                    if ( !dbus_message_iter_append_basic( &dbus_args,
                                DBUS_TYPE_BOOLEAN, &b_play ) )
                    {
                        dbus_message_unref( p_dbus_msg );
601
                        system_End( );
602
                        exit( 1 );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
603
604
605
606
607
608
609
610
                    }

                    /* send message and get a handle for a reply */
                    if ( !dbus_connection_send_with_reply ( p_conn,
                                p_dbus_msg, &p_dbus_pending, -1 ) )
                    {
                        msg_Err( p_libvlc, "D-Bus problem" );
                        dbus_message_unref( p_dbus_msg );
611
                        system_End( );
612
                        exit( 1 );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
613
614
615
616
617
618
                    }

                    if ( NULL == p_dbus_pending )
                    {
                        msg_Err( p_libvlc, "D-Bus problem" );
                        dbus_message_unref( p_dbus_msg );
619
                        system_End( );
620
                        exit( 1 );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
621
622
623
624
625
626
627
628
629
                    }
                    dbus_connection_flush( p_conn );
                    dbus_message_unref( p_dbus_msg );
                    /* block until we receive a reply */
                    dbus_pending_call_block( p_dbus_pending );
                    dbus_pending_call_unref( p_dbus_pending );
                } /* processes all command line MRLs */

                /* bye bye */
630
                system_End( );
631
                exit( 0 );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
632
633
634
635
            }
        }
        /* we unreference the connection when we've finished with it */
        if( p_conn ) dbus_connection_unref( p_conn );
hartman's avatar
hartman committed
636
    }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
637
#endif
hartman's avatar
hartman committed
638

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
639
640
641
    /*
     * Message queue options
     */
642
    /* Last chance to set the verbosity. Once we start interfaces and other
643
     * threads, verbosity becomes read-only. */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
644
    var_Create( p_libvlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
645
    if( var_InheritBool( p_libvlc, "quiet" ) )
hartman's avatar
hartman committed
646
    {
647
648
        var_SetInteger( p_libvlc, "verbose", -1 );
        priv->i_verbose = -1;
hartman's avatar
hartman committed
649
    }
650
    vlc_threads_setup( p_libvlc );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
651
652

    if( priv->b_color )
653
        priv->b_color = var_InheritBool( p_libvlc, "color" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
654

655
    vlc_CPU_dump( VLC_OBJECT(p_libvlc) );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
656
657
658
    /*
     * Choose the best memcpy module
     */
659
    priv->p_memcpy_module = module_need( p_libvlc, "memcpy", "$memcpy", false );
660
661
    /* Avoid being called "memcpy":*/
    vlc_object_set_name( p_libvlc, "main" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
662

663
    priv->b_stats = var_InheritBool( p_libvlc, "stats" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
664
665
666
667
668
669
    priv->i_timers = 0;
    priv->pp_timers = NULL;

    /*
     * Initialize hotkey handling
     */
670
    priv->actions = vlc_InitActions( p_libvlc );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
671

672
673
674
675
676
677
678
    /* Create a variable for showing the fullscreen interface */
    var_Create( p_libvlc, "intf-show", VLC_VAR_BOOL );
    var_SetBool( p_libvlc, "intf-show", true );

    /* Create a variable for showing the right click menu */
    var_Create( p_libvlc, "intf-popupmenu", VLC_VAR_BOOL );

679
680
681
682
    /* variables for signalling creation of new files */
    var_Create( p_libvlc, "snapshot-file", VLC_VAR_STRING );
    var_Create( p_libvlc, "record-file", VLC_VAR_STRING );

683
    /* some default internal settings */
684
    var_Create( p_libvlc, "window", VLC_VAR_STRING );
685
686
    var_Create( p_libvlc, "user-agent", VLC_VAR_STRING );
    var_SetString( p_libvlc, "user-agent", "(LibVLC "VERSION")" );
687

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
688
    /* Initialize playlist and get commandline files */
689
690
    p_playlist = playlist_Create( VLC_OBJECT(p_libvlc) );
    if( !p_playlist )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
691
692
693
694
    {
        msg_Err( p_libvlc, "playlist initialization failed" );
        if( priv->p_memcpy_module != NULL )
        {
695
            module_unneed( p_libvlc, priv->p_memcpy_module );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
696
        }
697
        module_EndBank (true);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
698
699
        return VLC_EGENERIC;
    }
hartman's avatar
hartman committed
700

701
    /* System specific configuration */
702
    system_Configure( p_libvlc, i_argc - vlc_optind, ppsz_argv + vlc_optind );
703

jetru's avatar
jetru committed
704
705
#if defined(MEDIA_LIBRARY)
    /* Get the ML */
ivoire's avatar
ivoire committed
706
    if( var_GetBool( p_libvlc, "load-media-library-on-startup" ) )
jetru's avatar
jetru committed
707
    {
708
        priv->p_ml = ml_Create( VLC_OBJECT( p_libvlc ), NULL );
jetru's avatar
jetru committed
709
710
711
712
713
714
715
716
717
718
719
720
        if( !priv->p_ml )
        {
            msg_Err( p_libvlc, "ML initialization failed" );
            return VLC_EGENERIC;
        }
    }
    else
    {
        priv->p_ml = NULL;
    }
#endif

721
    /* Add service discovery modules */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
722
    psz_modules = var_InheritString( p_libvlc, "services-discovery" );
723
    if( psz_modules )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
724
    {
725
726
727
        char *p = psz_modules, *m;
        while( ( m = strsep( &p, " :," ) ) != NULL )
            playlist_ServicesDiscoveryAdd( p_playlist, m );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
728
        free( psz_modules );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
729
    }
hartman's avatar
hartman committed
730

731
#ifdef ENABLE_VLM
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
732
    /* Initialize VLM if vlm-conf is specified */
733
734
    psz_parser = var_CreateGetNonEmptyString( p_libvlc, "vlm-conf" );
    if( psz_parser )
hartman's avatar
hartman committed
735
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
736
737
738
        priv->p_vlm = vlm_New( p_libvlc );
        if( !priv->p_vlm )
            msg_Err( p_libvlc, "VLM initialization failed" );
hartman's avatar
hartman committed
739
    }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
740
741
    free( psz_parser );
#endif
hartman's avatar
hartman committed
742

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
743
744
745
    /*
     * Load background interfaces
     */
746
747
    psz_modules = var_CreateGetNonEmptyString( p_libvlc, "extraintf" );
    psz_control = var_CreateGetNonEmptyString( p_libvlc, "control" );
hartman's avatar
hartman committed
748

749
    if( psz_modules && psz_control )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
750
    {
751
752
753
754
755
756
        char* psz_tmp;
        if( asprintf( &psz_tmp, "%s:%s", psz_modules, psz_control ) != -1 )
        {
            free( psz_modules );
            psz_modules = psz_tmp;
        }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
757
    }
758
    else if( psz_control )
hartman's avatar
hartman committed
759
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
760
761
        free( psz_modules );
        psz_modules = strdup( psz_control );
hartman's avatar
hartman committed
762
763
    }

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
764
765
766
767
768
769
770
771
772
773
774
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
        char *psz_module, *psz_temp;
        psz_module = psz_parser;
        psz_parser = strchr( psz_module, ':' );
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
775
        if( asprintf( &psz_temp, "%s,none", psz_module ) != -1)
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
776
        {
777
            intf_Create( p_libvlc, psz_temp );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
778
779
780
781
782
783
784
785
786
            free( psz_temp );
        }
    }
    free( psz_modules );
    free( psz_control );

    /*
     * Always load the hotkeys interface if it exists
     */
787
    intf_Create( p_libvlc, "hotkeys,none" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
788

789
#ifdef HAVE_DBUS
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
790
791
    /* loads dbus control interface if in one-instance mode
     * we do it only when playlist exists, because dbus module needs it */
792
793
794
    if( var_InheritBool( p_libvlc, "one-instance" )
     || ( var_InheritBool( p_libvlc, "one-instance-when-started-from-file" )
       && var_InheritBool( p_libvlc, "started-from-file" ) ) )
795
        intf_Create( p_libvlc, "dbus,none" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
796

797
# if !defined (HAVE_MAEMO)
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
798
799
    /* Prevents the power management daemon from suspending the system
     * when VLC is active */
800
    if( var_InheritBool( p_libvlc, "inhibit" ) > 0 )
801
        intf_Create( p_libvlc, "inhibit,none" );
802
# endif
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
803
#endif
hartman's avatar
hartman committed
804

805
806
    if( var_InheritBool( p_libvlc, "file-logging" ) &&
        !var_InheritBool( p_libvlc, "syslog" ) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
807
    {
808
        intf_Create( p_libvlc, "logger,none" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
809
810
    }
#ifdef HAVE_SYSLOG_H
811
    if( var_InheritBool( p_libvlc, "syslog" ) )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
812
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
813
        char *logmode = var_CreateGetNonEmptyString( p_libvlc, "logmode" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
814
        var_SetString( p_libvlc, "logmode", "syslog" );
815
        intf_Create( p_libvlc, "logger,none" );
hartman's avatar
hartman committed
816

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
817
818
819
820
821
        if( logmode )
        {
            var_SetString( p_libvlc, "logmode", logmode );
            free( logmode );
        }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
822
        var_Destroy( p_libvlc, "logmode" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
823
824
825
    }
#endif

826
    if( var_InheritBool( p_libvlc, "network-synchronisation") )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
827
    {
828
        intf_Create( p_libvlc, "netsync,none" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
829
    }
hartman's avatar
hartman committed
830

831
#ifdef __APPLE__
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
832
833
834
835
836
837
838
839
    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 );
840
    var_Create( p_libvlc, "drawable-nsobject", VLC_VAR_ADDRESS );
841
#endif
842
#ifdef WIN32
843
    var_Create( p_libvlc, "drawable-hwnd", VLC_VAR_INTEGER );
844
#endif
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
845
846

    /*
847
848
849
     * Get input filenames given as commandline arguments.
     * We assume that the remaining parameters are filenames
     * and their input options.
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
850
     */
851
    GetFilenames( p_libvlc, i_argc - vlc_optind, ppsz_argv + vlc_optind );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
852
853
854
855

    /*
     * Get --open argument
     */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
856
    psz_val = var_InheritString( p_libvlc, "open" );
857
    if ( psz_val != NULL )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
858
    {
ivoire's avatar
ivoire committed
859
        playlist_AddExt( p_playlist, psz_val, NULL, PLAYLIST_INSERT, 0,
860
                         -1, 0, NULL, 0, true, pl_Unlocked );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
861
        free( psz_val );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
862
    }
hartman's avatar
hartman committed
863

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
864
    return VLC_SUCCESS;
hartman's avatar
hartman committed
865
866
867
}

/**
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
868
869
 * Cleanup a libvlc instance. The instance is not completely deallocated
 * \param p_libvlc the instance to clean
hartman's avatar
hartman committed
870
 */
871
void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
hartman's avatar
hartman committed
872
{
873
    libvlc_priv_t *priv = libvlc_priv (p_libvlc);
874
    playlist_t    *p_playlist = libvlc_priv (p_libvlc)->p_playlist;
875
876
877

    /* Deactivate the playlist */
    msg_Dbg( p_libvlc, "deactivating the playlist" );
878
    pl_Deactivate( p_libvlc );
879
880
881
882

    /* Remove all services discovery */
    msg_Dbg( p_libvlc, "removing all services discovery tasks" );
    playlist_ServicesDiscoveryKillAll( p_playlist );
hartman's avatar
hartman committed
883

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
884
885
    /* Ask the interfaces to stop and destroy them */
    msg_Dbg( p_libvlc, "removing all interfaces" );
886
    libvlc_Quit( p_libvlc );
887
    intf_DestroyAll( p_libvlc );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
888

889
#ifdef ENABLE_VLM
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
890
891
892
893
894
895
896
    /* Destroy VLM if created in libvlc_InternalInit */
    if( priv->p_vlm )
    {
        vlm_Delete( priv->p_vlm );
    }
#endif

897
898
899
900
901
902
903
904
905
906
#if defined(MEDIA_LIBRARY)
    media_library_t* p_ml = priv->p_ml;
    if( p_ml )
    {
        ml_Destroy( VLC_OBJECT( p_ml ) );
        vlc_object_release( p_ml );
        libvlc_priv(p_playlist->p_libvlc)->p_ml = NULL;
    }
#endif

907
908
    /* Free playlist now, all threads are gone */
    playlist_Destroy( p_playlist );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
909
910
911
912
913
914
915
916
917
918
    stats_TimersDumpAll( p_libvlc );
    stats_TimersCleanAll( p_libvlc );

    msg_Dbg( p_libvlc, "removing stats" );

#ifndef WIN32
    char* psz_pidfile = NULL;

    if( b_daemon )
    {
919
        psz_pidfile = var_CreateGetNonEmptyString( p_libvlc, "pidfile" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
        if( psz_pidfile != NULL )
        {
            msg_Dbg( p_libvlc, "removing pid file %s", psz_pidfile );
            if( unlink( psz_pidfile ) == -1 )
            {
                msg_Dbg( p_libvlc, "removing pid file %s: %m",
                        psz_pidfile );
            }
        }
        free( psz_pidfile );
    }
#endif

    if( priv->p_memcpy_module )
    {
935
        module_unneed( p_libvlc, priv->p_memcpy_module );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
936
937
938
        priv->p_memcpy_module = NULL;
    }

939
940
941
942
    /* Save the configuration */
    if( !var_InheritBool( p_libvlc, "ignore-config" ) )
        config_AutoSaveConfigFile( VLC_OBJECT(p_libvlc) );

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
943
    /* Free module bank. It is refcounted, so we call this each time  */
944
    module_EndBank (true);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
945

946
    vlc_DeinitActions( p_libvlc, priv->actions );
947
948
949
950
951
952
953
954
955
956
957
958
}

/**
 * Destroy everything.
 * This function requests the running threads to finish, waits for their
 * termination, and destroys their structure.
 * It stops the thread systems: no instance can run after this has run
 * \param p_libvlc the instance to destroy
 */
void libvlc_InternalDestroy( libvlc_int_t *p_libvlc )
{
    libvlc_priv_t *priv = libvlc_priv( p_libvlc );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
959

960
    system_End( );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
961
962

    /* Destroy mutexes */
963
    vlc_ExitDestroy( &priv->exit );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
964
    vlc_mutex_destroy( &priv->timer_lock );
jetru's avatar
jetru committed
965
    vlc_mutex_destroy( &priv->ml_lock );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
966

967
968
969
970
971
972
#ifndef NDEBUG /* Hack to dump leaked objects tree */
    if( vlc_internals( p_libvlc )->i_refcount > 1 )
        while( vlc_internals( p_libvlc )->i_refcount > 0 )
            vlc_object_release( p_libvlc );
#endif

973
    assert( vlc_internals( p_libvlc )->i_refcount == 1 );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
974
    vlc_object_release( p_libvlc );
hartman's avatar
hartman committed
975
976
977
}

/**
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
978
 * Add an interface plugin and run it
hartman's avatar
hartman committed
979
 */
980
int libvlc_InternalAddIntf( libvlc_int_t *p_libvlc, char const *psz_module )
hartman's avatar
hartman committed
981
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
982
983
984
985
986
    if( !p_libvlc )
        return VLC_EGENERIC;

    if( !psz_module ) /* requesting the default interface */
    {
987
988
        char *psz_interface = var_CreateGetNonEmptyString( p_libvlc, "intf" );
        if( !psz_interface ) /* "intf" has not been set */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
989
990
991
992
993
994
995
996
        {
#ifndef WIN32
            if( b_daemon )
                 /* Daemon mode hack.
                  * We prefer the dummy interface if none is specified. */
                psz_module = "dummy";
            else
#endif
997
998
999
                msg_Info( p_libvlc, "%s",
                          _("Running vlc with the default interface. "
                            "Use 'cvlc' to use vlc without interface.") );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed