libvlc.c 41.4 KB
Newer Older
1
2
3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2002 VideoLAN
5
 * $Id: libvlc.c,v 1.62 2003/02/01 23:39:02 sam Exp $
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 *
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
 *          Gildas Bazin <gbazin@netcourrier.com>
 *
 * 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
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

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

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

#ifdef HAVE_ERRNO_H
#   include <errno.h>                                              /* ENOMEM */
#endif
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>                                              /* sprintf() */
#include <string.h>                                            /* strerror() */
#include <stdlib.h>                                                /* free() */

#ifndef WIN32
#   include <netinet/in.h>                            /* BSD: struct in_addr */
#endif

#ifdef HAVE_UNISTD_H
#   include <unistd.h>
51
#elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
52
53
54
#   include <io.h>
#endif

55
#ifdef WIN32                       /* optind, getopt(), included in unistd.h */
56
#   include "extras/getopt.h"
57
58
#endif

59
60
61
62
63
#ifdef HAVE_LOCALE_H
#   include <locale.h>
#endif

#include "vlc_cpu.h"                                        /* CPU detection */
64
#include "os_specific.h"
65

66
#include "error.h"
67
68
69
70
71
#include "netutils.h"                                 /* network_ChannelJoin */

#include "stream_control.h"
#include "input_ext-intf.h"

72
#include "vlc_playlist.h"
73
74
75
76
77
78
79
80
81
82
#include "interface.h"

#include "audio_output.h"

#include "video.h"
#include "video_output.h"

#include "libvlc.h"

/*****************************************************************************
83
 * The evil global variable. We handle it with care, don't worry.
84
 *****************************************************************************/
85
static libvlc_t libvlc;
Sam Hocevar's avatar
Sam Hocevar committed
86
static vlc_t *  p_static_vlc;
87
88
89
90

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
91
static void SetLanguage   ( char const * );
92
static int  GetFilenames  ( vlc_t *, int, char *[] );
93
static void Usage         ( vlc_t *, char const *psz_module_name );
94
static void ListModules   ( vlc_t * );
95
96
97
98
99
100
101
static void Version       ( void );

#ifdef WIN32
static void ShowConsole   ( void );
#endif

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
102
 * VLC_Version: return the libvlc version.
103
 *****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
104
 * This function returns full version string (numeric version and codename).
105
 *****************************************************************************/
106
char const * VLC_Version( void )
107
{
Sam Hocevar's avatar
Sam Hocevar committed
108
    return VERSION_MESSAGE;
109
110
}

111
112
113
114
115
116
117
118
119
120
/*****************************************************************************
 * 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
121
122
123
124
125
126
127
/*****************************************************************************
 * 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 )
128
{
129
    int i_ret;
130
    vlc_t * p_vlc = NULL;
131
    vlc_value_t lockval;
132

133
134
135
    /* vlc_threads_init *must* be the first internal call! No other call is
     * allowed before the thread system has been initialized. */
    i_ret = vlc_threads_init( &libvlc );
Sam Hocevar's avatar
Sam Hocevar committed
136
    if( i_ret < 0 )
137
    {
Sam Hocevar's avatar
Sam Hocevar committed
138
        return i_ret;
139
140
141
    }

    /* Now that the thread system is initialized, we don't have much, but
142
143
144
145
     * at least we have var_Create */
    var_Create( &libvlc, "libvlc", VLC_VAR_MUTEX );
    var_Get( &libvlc, "libvlc", &lockval );
    vlc_mutex_lock( lockval.p_address );
146
147
    if( !libvlc.b_ready )
    {
148
149
        char *psz_env;

150
151
152
        /* Guess what CPU we have */
        libvlc.i_cpu = CPUCapabilities();

153
154
        /* Find verbosity from VLC_VERBOSE environment variable */
        psz_env = getenv( "VLC_VERBOSE" );
155
        libvlc.i_verbose = psz_env ? atoi( psz_env ) : -1;
156
157
158
159
160
161
162

#ifdef HAVE_ISATTY
        libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
#else
        libvlc.b_color = VLC_FALSE;
#endif

163
164
165
166
167
168
169
        /* Initialize message queue */
        msg_Create( &libvlc );

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

170
171
        /* The module bank will be initialized later */
        libvlc.p_module_bank = NULL;
172
173

        libvlc.b_ready = VLC_TRUE;
174
    }
175
176
    vlc_mutex_unlock( lockval.p_address );
    var_Destroy( &libvlc, "libvlc" );
177
178
179

    /* Allocate a vlc object */
    p_vlc = vlc_object_create( &libvlc, VLC_OBJECT_VLC );
180
181
    if( p_vlc == NULL )
    {
Sam Hocevar's avatar
Sam Hocevar committed
182
        return VLC_EGENERIC;
183
184
185
186
187
    }

    p_vlc->psz_object_name = "root";

    /* Initialize mutexes */
188
    vlc_mutex_init( p_vlc, &p_vlc->config_lock );
189
190

    /* Store our newly allocated structure in the global list */
191
    vlc_object_attach( p_vlc, &libvlc );
192

Sam Hocevar's avatar
Sam Hocevar committed
193
194
195
196
    /* Store data for the non-reentrant API */
    p_static_vlc = p_vlc;

    return p_vlc->i_object_id;
197
198
199
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
200
 * VLC_Init: initialize a vlc_t structure.
201
202
203
204
205
206
207
 *****************************************************************************
 * 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
208
int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
209
{
210
211
    char         p_capabilities[200];
    char *       p_tmp;
212
213
    char *       psz_modules;
    char *       psz_parser;
214
    vlc_bool_t   b_exit = VLC_FALSE;
Sam Hocevar's avatar
Sam Hocevar committed
215
    vlc_t *      p_vlc;
216
217
    module_t    *p_help_module;
    playlist_t  *p_playlist;
218
    vlc_value_t  lockval;
219

Sam Hocevar's avatar
Sam Hocevar committed
220
221
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

222
    if( !p_vlc )
223
    {
224
        return VLC_ENOOBJ;
225
226
227
    }

    /*
228
     * System specific initialization code
229
     */
230
    system_Init( p_vlc, &i_argc, ppsz_argv );
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

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

247
248
249
250
    /*
     * Support for gettext
     */
    SetLanguage( "" );
Sam Hocevar's avatar
Sam Hocevar committed
251
252

    /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
253
254
    msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
    /* 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) */
    var_Create( &libvlc, "libvlc", VLC_VAR_MUTEX );
    var_Get( &libvlc, "libvlc", &lockval );
    vlc_mutex_lock( lockval.p_address );
    if( libvlc.p_module_bank == NULL )
    {
        module_InitBank( &libvlc );
        module_LoadMain( &libvlc );
    }
    vlc_mutex_unlock( lockval.p_address );
    var_Destroy( &libvlc, "libvlc" );

270
271
272
273
    /* Hack: insert the help module here */
    p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
    if( p_help_module == NULL )
    {
274
        //module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
275
        if( i_object ) vlc_object_release( p_vlc );
276
277
278
279
        return VLC_EGENERIC;
    }
    p_help_module->psz_object_name = "help";
    config_Duplicate( p_help_module, p_help_config );
280
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
281
282
    /* End hack */

Sam Hocevar's avatar
Sam Hocevar committed
283
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
284
    {
285
        vlc_object_detach( p_help_module );
286
287
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
288
        //module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
289
        if( i_object ) vlc_object_release( p_vlc );
290
291
292
293
294
295
        return VLC_EGENERIC;
    }

    /* Check for short help option */
    if( config_GetInt( p_vlc, "help" ) )
    {
296
        fprintf( stdout, _("Usage: %s [options] [items]...\n\n"),
297
                         p_vlc->psz_object_name );
298
        Usage( p_vlc, "main" );
299
300
        Usage( p_vlc, "help" );
        b_exit = VLC_TRUE;
301
302
    }
    /* Check for version option */
303
    else if( config_GetInt( p_vlc, "version" ) )
304
305
    {
        Version();
306
307
308
309
310
311
312
313
314
        b_exit = VLC_TRUE;
    }

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

    if( b_exit )
    {
315
316
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
317
        //module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
318
        if( i_object ) vlc_object_release( p_vlc );
319
320
321
322
323
324
325
326
327
        return VLC_EEXIT;
    }

    /*
     * 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.
     */
328
329
    module_LoadBuiltins( &libvlc );
    module_LoadPlugins( &libvlc );
330
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
331
                    libvlc.p_module_bank->i_children );
332
333

    /* Hack: insert the help module here */
334
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
335
336
337
338
339
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
340
        Usage( p_vlc, p_tmp );
341
        free( p_tmp );
342
        b_exit = VLC_TRUE;
343
344
    }
    /* Check for long help option */
345
    else if( config_GetInt( p_vlc, "longhelp" ) )
346
    {
347
        Usage( p_vlc, NULL );
348
        b_exit = VLC_TRUE;
349
350
    }
    /* Check for module list option */
351
    else if( config_GetInt( p_vlc, "list" ) )
352
    {
353
        ListModules( p_vlc );
354
        b_exit = VLC_TRUE;
355
356
357
    }

    /* Hack: remove the help module here */
358
    vlc_object_detach( p_help_module );
359
360
361
362
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

363
364
    if( b_exit )
    {
365
        //module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
366
        if( i_object ) vlc_object_release( p_vlc );
367
368
369
        return VLC_EEXIT;
    }

370
371
372
373
    /*
     * Override default configuration with config file settings
     */
    p_vlc->psz_homedir = config_GetHomeDir();
374
    config_LoadConfigFile( p_vlc, NULL );
375
376
377
378

    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
379
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
380
381
382
383
384
385
386
387
    {
#ifdef WIN32
        ShowConsole();
        /* 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.\nPress the RETURN key to continue..." );
        getchar();
#endif
388
        //module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
389
        if( i_object ) vlc_object_release( p_vlc );
390
391
392
393
394
395
        return VLC_EGENERIC;
    }

    /*
     * System specific configuration
     */
396
    system_Configure( p_vlc );
397

398
399
400
401
402
    /*
     * Message queue options
     */
    if( config_GetInt( p_vlc, "quiet" ) )
    {
403
        libvlc.i_verbose = -1;
404
405
406
407
    }
    else
    {
        int i_tmp = config_GetInt( p_vlc, "verbose" );
408
        if( i_tmp >= 0 )
409
        {
410
            libvlc.i_verbose = __MIN( i_tmp, 2 );
411
412
413
414
        }
    }
    libvlc.b_color = libvlc.b_color || config_GetInt( p_vlc, "color" );

415
416
417
418
419
420
421
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

    /* p_vlc inititalization. FIXME ? */
    p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
422

423
#if defined( __i386__ )
424
    if( !config_GetInt( p_vlc, "mmx" ) )
425
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
426
    if( !config_GetInt( p_vlc, "3dn" ) )
427
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
428
    if( !config_GetInt( p_vlc, "mmxext" ) )
429
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
430
    if( !config_GetInt( p_vlc, "sse" ) )
431
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
432
433
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
434
    if( !config_GetInt( p_vlc, "altivec" ) )
435
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
436
#endif
437
438

#define PRINT_CAPABILITY( capability, string )                              \
439
    if( libvlc.i_cpu & capability )                                         \
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
    {                                                                       \
        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" );
    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
     */
461
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
462

463
    if( p_vlc->pf_memcpy == NULL )
464
465
466
    {
        p_vlc->pf_memcpy = memcpy;
    }
467
468
469
470
471

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
472
473
474
475
476

    /*
     * Initialize shared resources and libraries
     */
    if( config_GetInt( p_vlc, "network-channel" )
477
         && network_ChannelCreate( p_vlc ) )
478
479
    {
        /* On error during Channels initialization, switch off channels */
480
481
        msg_Warn( p_vlc,
                  "channels initialization failed, deactivating channels" );
Sam Hocevar's avatar
Sam Hocevar committed
482
        config_PutInt( p_vlc, "network-channel", VLC_FALSE );
483
484
485
486
487
    }

    /*
     * Initialize playlist and get commandline files
     */
488
    p_playlist = playlist_Create( p_vlc );
489
490
491
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
492
493
        if( p_vlc->p_memcpy_module != NULL )
        {
494
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
495
        }
496
        //module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
497
        if( i_object ) vlc_object_release( p_vlc );
498
499
500
        return VLC_EGENERIC;
    }

501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
        char *psz_module;
        psz_module = psz_parser;
        psz_parser = strchr( psz_module, ',' );
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
        VLC_AddIntf( 0, psz_module, VLC_FALSE );
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
522

523
524
525
526
527
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );

528
529
530
531
532
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

gbazin's avatar
   
gbazin committed
533
    if( i_object ) vlc_object_release( p_vlc );
534
535
536
537
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
538
 * VLC_AddIntf: add an interface
539
540
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
541
542
 * 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
543
544
 * user requests to quit.
 *****************************************************************************/
545
int VLC_AddIntf( int i_object, char const *psz_module, vlc_bool_t b_block )
546
{
Sam Hocevar's avatar
Sam Hocevar committed
547
    int i_err;
548
    intf_thread_t *p_intf;
Sam Hocevar's avatar
Sam Hocevar committed
549
    vlc_t *p_vlc;
550
551
    char *psz_oldmodule = NULL;

Sam Hocevar's avatar
Sam Hocevar committed
552
553
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

554
    if( !p_vlc )
555
    {
556
        return VLC_ENOOBJ;
557
558
559
560
561
562
563
564
565
    }

    if( psz_module )
    {
        psz_oldmodule = config_GetPsz( p_vlc, "intf" );
        config_PutPsz( p_vlc, "intf", psz_module );
    }

    /* Try to create the interface */
566
    p_intf = intf_Create( p_vlc );
567
568
569
570
571
572
573
574
575
576
577
578
579

    if( psz_module )
    {
        config_PutPsz( p_vlc, "intf", psz_oldmodule );
        if( psz_oldmodule )
        {
            free( psz_oldmodule );
        }
    }

    if( p_intf == NULL )
    {
        msg_Err( p_vlc, "interface initialization failed" );
gbazin's avatar
   
gbazin committed
580
        if( i_object ) vlc_object_release( p_vlc );
581
582
583
584
585
        return VLC_EGENERIC;
    }

    /* Try to run the interface */
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
586
587
    i_err = intf_RunThread( p_intf );
    if( i_err )
588
    {
589
        vlc_object_detach( p_intf );
590
        intf_Destroy( p_intf );
gbazin's avatar
   
gbazin committed
591
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
592
        return i_err;
593
594
    }

gbazin's avatar
   
gbazin committed
595
    if( i_object ) vlc_object_release( p_vlc );
596
597
598
599
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
600
 * VLC_Destroy: stop playing and destroy everything.
601
 *****************************************************************************
602
 * This function requests the running threads to finish, waits for their
603
604
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
605
int VLC_Destroy( int i_object )
606
{
Sam Hocevar's avatar
Sam Hocevar committed
607
608
609
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
610

611
    if( !p_vlc )
612
    {
613
        return VLC_ENOOBJ;
614
615
    }

616
617
618
619
    /*
     * Go back into channel 0 which is the network
     */
    if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
620
    {
621
622
        network_ChannelJoin( p_vlc, COMMON_CHANNEL );
    }
623

624
625
626
627
628
629
630
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
631
632
    }

633
634
635
636
637
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
638

639
640
641
642
    /*
     * XXX: Free module bank !
     */
    //module_EndBank( p_vlc );
643

644
645
646
647
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
648

649
650
651
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

652
653
    vlc_object_detach( p_vlc );

654
655
656
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

657
658
    vlc_object_destroy( p_vlc );

659
660
661
    /* Stop thread system: last one out please shut the door! */
    vlc_threads_end( &libvlc );

662
663
664
    return VLC_SUCCESS;
}

665
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
666
 * VLC_Die: ask vlc to die.
667
668
 *****************************************************************************
 * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
Sam Hocevar's avatar
Sam Hocevar committed
669
 * task. It is your duty to call vlc_end and VLC_Destroy afterwards.
670
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
671
int VLC_Die( int i_object )
672
{
Sam Hocevar's avatar
Sam Hocevar committed
673
674
675
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
676
677
678

    if( !p_vlc )
    {
679
        return VLC_ENOOBJ;
680
681
682
683
    }

    p_vlc->b_die = VLC_TRUE;

gbazin's avatar
   
gbazin committed
684
    if( i_object ) vlc_object_release( p_vlc );
685
686
687
688
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
689
 * VLC_AddTarget: adds a target for playing.
690
691
692
693
 *****************************************************************************
 * This function adds psz_target to the current playlist. If a playlist does
 * not exist, it will create one.
 *****************************************************************************/
694
int VLC_AddTarget( int i_object, char const *psz_target, int i_mode, int i_pos )
695
{
Sam Hocevar's avatar
Sam Hocevar committed
696
    int i_err;
Sam Hocevar's avatar
Sam Hocevar committed
697
    playlist_t *p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
698
699
700
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
Sam Hocevar's avatar
Sam Hocevar committed
701

702
    if( !p_vlc )
703
    {
704
        return VLC_ENOOBJ;
705
706
    }

Sam Hocevar's avatar
Sam Hocevar committed
707
708
709
710
711
712
713
714
715
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );

    if( p_playlist == NULL )
    {
        msg_Dbg( p_vlc, "no playlist present, creating one" );
        p_playlist = playlist_Create( p_vlc );

        if( p_playlist == NULL )
        {
gbazin's avatar
   
gbazin committed
716
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
717
718
719
720
721
722
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
    }

Sam Hocevar's avatar
Sam Hocevar committed
723
    i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
Sam Hocevar's avatar
Sam Hocevar committed
724
725

    vlc_object_release( p_playlist );
726

gbazin's avatar
   
gbazin committed
727
    if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
728
    return i_err;
729
730
}

731
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
732
 * VLC_Set: set a vlc variable
733
734
735
 *****************************************************************************
 *
 *****************************************************************************/
736
int VLC_Set( int i_object, char const *psz_var, vlc_value_t value )
737
{
Sam Hocevar's avatar
Sam Hocevar committed
738
    vlc_t *p_vlc;
gbazin's avatar
   
gbazin committed
739
    int i_ret;
740

Sam Hocevar's avatar
Sam Hocevar committed
741
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
742
743
744

    if( !p_vlc )
    {
745
        return VLC_ENOOBJ;
746
747
    }

Sam Hocevar's avatar
Sam Hocevar committed
748
749
750
    /* FIXME: Temporary hack for Mozilla, if variable starts with conf:: then
     * we handle it as a configuration variable. Don't tell Gildas :) -- sam */
    if( !strncmp( psz_var, "conf::", 6 ) )
751
    {
Sam Hocevar's avatar
Sam Hocevar committed
752
        module_config_t *p_item;
753
        char const *psz_newvar = psz_var + 6;
754

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

Sam Hocevar's avatar
Sam Hocevar committed
757
        if( p_item )
758
        {
Sam Hocevar's avatar
Sam Hocevar committed
759
            switch( p_item->i_type )
760
            {
Sam Hocevar's avatar
Sam Hocevar committed
761
762
763
764
765
766
767
768
769
770
771
772
                case CONFIG_ITEM_BOOL:
                    config_PutInt( p_vlc, psz_newvar, value.b_bool );
                    break;
                case CONFIG_ITEM_INTEGER:
                    config_PutInt( p_vlc, psz_newvar, value.i_int );
                    break;
                case CONFIG_ITEM_FLOAT:
                    config_PutFloat( p_vlc, psz_newvar, value.f_float );
                    break;
                default:
                    config_PutPsz( p_vlc, psz_newvar, value.psz_string );
                    break;
773
            }
gbazin's avatar
   
gbazin committed
774
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
775
            return VLC_SUCCESS;
776
777
778
        }
    }

gbazin's avatar
   
gbazin committed
779
780
781
782
    i_ret = var_Set( p_vlc, psz_var, value );

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
783
784
785
786
787
788
789
}

/*****************************************************************************
 * VLC_Get: get a vlc variable
 *****************************************************************************
 *
 *****************************************************************************/
790
int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
791
792
{
    vlc_t *p_vlc;
gbazin's avatar
   
gbazin committed
793
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
794
795
796
797

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

    if( !p_vlc )
798
    {
799
        return VLC_ENOOBJ;
800
801
    }

gbazin's avatar
   
gbazin committed
802
803
804
805
    i_ret = var_Get( p_vlc, psz_var, p_value );

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
806
807
}

Sam Hocevar's avatar
Sam Hocevar committed
808
/* FIXME: temporary hacks */
809
810

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
811
 * VLC_Play: play
812
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
813
int VLC_Play( int i_object )
814
815
{
    playlist_t * p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
816
817
818
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
819
820

    /* Check that the handle is valid */
821
    if( !p_vlc )
822
    {
823
        return VLC_ENOOBJ;
824
    }
825

826
827
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );

828
829
830
831
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
gbazin's avatar
   
gbazin committed
832
        if( i_object ) vlc_object_release( p_vlc );
833
        return VLC_ENOOBJ;
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
    }

    vlc_mutex_lock( &p_playlist->object_lock );
    if( p_playlist->i_size )
    {
        vlc_mutex_unlock( &p_playlist->object_lock );
        playlist_Play( p_playlist );
    }
    else
    {
        vlc_mutex_unlock( &p_playlist->object_lock );
    }

    vlc_object_release( p_playlist );

gbazin's avatar
   
gbazin committed
849
    if( i_object ) vlc_object_release( p_vlc );
850
851
852
853
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
854
 * VLC_Stop: stop
855
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
856
int VLC_Stop( int i_object )
857
858
859
860
861
{
    intf_thread_t *   p_intf;
    playlist_t    *   p_playlist;
    vout_thread_t *   p_vout;
    aout_instance_t * p_aout;
Sam Hocevar's avatar
Sam Hocevar committed
862
863
864
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
865
866

    /* Check that the handle is valid */
867
    if( !p_vlc )
868
    {
869
        return VLC_ENOOBJ;
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
    }

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

    /*
     * Free playlists
     */
    msg_Dbg( p_vlc, "removing all playlists" );
    while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
                                          FIND_CHILD )) )
    {
        vlc_object_detach( p_playlist );
        vlc_object_release( p_playlist );
        playlist_Destroy( p_playlist );
    }

    /*
     * Free video outputs
     */
    msg_Dbg( p_vlc, "removing all video outputs" );
    while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
    {
        vlc_object_detach( p_vout );
        vlc_object_release( p_vout );
904
        vout_Destroy( p_vout );
905
906
907
908
909
910
911
912
913
914
915
916
917
    }

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

gbazin's avatar
   
gbazin committed
918
    if( i_object ) vlc_object_release( p_vlc );
919
920
921
922
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
923
 * VLC_Pause: toggle pause
924
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
925
int VLC_Pause( int i_object )
926
927
{
    input_thread_t *p_input;
Sam Hocevar's avatar
Sam Hocevar committed
928
929
930
931
932
933
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

    if( !p_vlc )
    {
934
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
935
    }
936
937
938
939
940

    p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );

    if( !p_input )
    {
gbazin's avatar
   
gbazin committed
941
        if( i_object ) vlc_object_release( p_vlc );
942
        return VLC_ENOOBJ;
943
944
945
946
947
    }

    input_SetStatus( p_input, INPUT_STATUS_PAUSE );
    vlc_object_release( p_input );

gbazin's avatar
   
gbazin committed
948
    if( i_object ) vlc_object_release( p_vlc );
949
950
951
952
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
953
 * VLC_FullScreen: toggle fullscreen mode
954
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
955
int VLC_FullScreen( int i_object )
956
957
{
    vout_thread_t *p_vout;
Sam Hocevar's avatar
Sam Hocevar committed
958
959
960
961
962
963
    vlc_t *p_vlc;

    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;

    if( !p_vlc )
    {
964
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
965
    }
966
967
968
969
970

    p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );

    if( !p_vout )
    {
gbazin's avatar
   
gbazin committed
971
        if( i_object ) vlc_object_release( p_vlc );
972
        return VLC_ENOOBJ;
973
974
975
976
977
    }

    p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
    vlc_object_release( p_vout );

gbazin's avatar
   
gbazin committed
978
    if( i_object ) vlc_object_release( p_vlc );
979
980
981
    return VLC_SUCCESS;
}

982
983
/* following functions are local */

Sam Hocevar's avatar
Sam Hocevar committed
984
985
986
987
988
989
990
991
992
/*****************************************************************************
 * SetLanguage: set the interface language.
 *****************************************************************************
 * We set the LC_MESSAGES locale category for interface messages and buttons,
 * as well as the LC_CTYPE category for string sorting and possible wide
 * character support.
 *****************************************************************************/
static void SetLanguage ( char const *psz_lang )
{
993
994
995
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )

996
997
998
999
1000
    char *          psz_path;
#ifdef SYS_DARWIN
    char            psz_tmp[1024];
#endif