libvlc.c 44.9 KB
Newer Older
1
2
3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2002 VideoLAN
5
 * $Id: libvlc.c,v 1.85 2003/05/10 13:40:37 titer 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>
gbazin's avatar
   
gbazin committed
51
#elif defined( WIN32 ) && !defined( UNDER_CE )
52
53
54
#   include <io.h>
#endif

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

59
60
61
62
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

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

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

#include "audio_output.h"

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

#include "libvlc.h"

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

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

#ifdef WIN32
static void ShowConsole   ( void );
#endif
99
static int  ConsoleWidth  ( void );
100
101

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

gbazin's avatar
   
gbazin committed
157
#if defined( HAVE_ISATTY ) && !defined( WIN32 )
158
159
160
161
162
        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
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );
185
186
187
188

    p_vlc->psz_object_name = "root";

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

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

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

    return p_vlc->i_object_id;
198
199
200
}

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

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

224
    if( !p_vlc )
225
    {
226
        return VLC_ENOOBJ;
227
228
229
    }

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

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

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

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

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
    /* 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" );

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

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

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

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

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

gbazin's avatar
   
gbazin committed
324
    /* Check for translation config option */
gbazin's avatar
   
gbazin committed
325
326
327
328
329
330
331
332
333
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )

    /* This ain't really nice to have to reload the config here but it seems
     * the only way to do it. */
    p_vlc->psz_homedir = config_GetHomeDir();
    config_LoadConfigFile( p_vlc, "main" );
    config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );

334
335
336
    /* 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
337
338
    {
        /* Reset the default domain */
339
        SetLanguage( psz_language );
gbazin's avatar
   
gbazin committed
340

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

344
        textdomain( PACKAGE );
gbazin's avatar
   
gbazin committed
345

gbazin's avatar
   
gbazin committed
346
347
348
        module_EndBank( p_vlc );
        module_InitBank( &libvlc );
        module_LoadMain( &libvlc );
gbazin's avatar
   
gbazin committed
349
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
gbazin's avatar
   
gbazin committed
350
    }
351
    if( psz_language ) free( psz_language );
352
#endif
gbazin's avatar
   
gbazin committed
353

354
355
356
357
358
359
    /*
     * 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.
     */
360
361
    module_LoadBuiltins( &libvlc );
    module_LoadPlugins( &libvlc );
362
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
363
                    libvlc.p_module_bank->i_children );
364
365

    /* Hack: insert the help module here */
366
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
367
368
369
370
371
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
372
        Usage( p_vlc, p_tmp );
373
        free( p_tmp );
374
        b_exit = VLC_TRUE;
375
376
    }
    /* Check for long help option */
377
    else if( config_GetInt( p_vlc, "longhelp" ) )
378
    {
379
        Usage( p_vlc, NULL );
380
        b_exit = VLC_TRUE;
381
382
    }
    /* Check for module list option */
383
    else if( config_GetInt( p_vlc, "list" ) )
384
    {
385
        ListModules( p_vlc );
386
        b_exit = VLC_TRUE;
387
388
389
    }

    /* Hack: remove the help module here */
390
    vlc_object_detach( p_help_module );
391
392
393
394
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

395
396
    if( b_exit )
    {
397
        //module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
398
        if( i_object ) vlc_object_release( p_vlc );
399
400
401
        return VLC_EEXIT;
    }

402
403
404
405
    /*
     * Override default configuration with config file settings
     */
    p_vlc->psz_homedir = config_GetHomeDir();
406
    config_LoadConfigFile( p_vlc, NULL );
407
408
409
410

    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
411
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
412
413
414
415
416
417
418
419
    {
#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
420
        //module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
421
        if( i_object ) vlc_object_release( p_vlc );
422
423
424
425
426
427
        return VLC_EGENERIC;
    }

    /*
     * System specific configuration
     */
428
    system_Configure( p_vlc );
429

430
431
432
433
434
    /*
     * Message queue options
     */
    if( config_GetInt( p_vlc, "quiet" ) )
    {
435
        libvlc.i_verbose = -1;
436
437
438
439
    }
    else
    {
        int i_tmp = config_GetInt( p_vlc, "verbose" );
440
        if( i_tmp >= 0 )
441
        {
442
            libvlc.i_verbose = __MIN( i_tmp, 2 );
443
444
        }
    }
gbazin's avatar
   
gbazin committed
445
    libvlc.b_color = libvlc.b_color && config_GetInt( p_vlc, "color" );
446

447
448
449
450
451
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

452
    /* p_vlc initialization. FIXME ? */
453
    p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
454

455
#if defined( __i386__ )
456
    if( !config_GetInt( p_vlc, "mmx" ) )
457
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
458
    if( !config_GetInt( p_vlc, "3dn" ) )
459
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
460
    if( !config_GetInt( p_vlc, "mmxext" ) )
461
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
462
    if( !config_GetInt( p_vlc, "sse" ) )
463
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
464
465
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
466
    if( !config_GetInt( p_vlc, "altivec" ) )
467
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
468
#endif
469
470

#define PRINT_CAPABILITY( capability, string )                              \
471
    if( libvlc.i_cpu & capability )                                         \
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
    {                                                                       \
        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
     */
493
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
494

495
    if( p_vlc->pf_memcpy == NULL )
496
497
498
    {
        p_vlc->pf_memcpy = memcpy;
    }
499
500
501
502
503

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
504
505
506
507

    /*
     * Initialize playlist and get commandline files
     */
508
    p_playlist = playlist_Create( p_vlc );
509
510
511
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
512
513
        if( p_vlc->p_memcpy_module != NULL )
        {
514
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
515
        }
516
        //module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
517
        if( i_object ) vlc_object_release( p_vlc );
518
519
520
        return VLC_EGENERIC;
    }

521
522
523
524
525
526
527
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
gbazin's avatar
   
gbazin committed
528
        char *psz_module, *psz_temp;
529
530
531
532
533
534
535
        psz_module = psz_parser;
        psz_parser = strchr( psz_module, ',' );
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
gbazin's avatar
   
gbazin committed
536
537
538
539
540
541
542
        psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
        if( psz_temp )
        {
            sprintf( psz_temp, "%s,none", psz_module );
            VLC_AddIntf( 0, psz_temp, VLC_FALSE );
            free( psz_temp );
        }
543
544
545
546
547
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
548

549
550
551
552
553
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );

554
555
556
557
558
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

gbazin's avatar
   
gbazin committed
559
    if( i_object ) vlc_object_release( p_vlc );
560
561
562
563
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
564
 * VLC_AddIntf: add an interface
565
566
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
567
568
 * 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
569
570
 * user requests to quit.
 *****************************************************************************/
571
int VLC_AddIntf( int i_object, char const *psz_module, vlc_bool_t b_block )
572
{
Sam Hocevar's avatar
Sam Hocevar committed
573
    int i_err;
574
    intf_thread_t *p_intf;
Sam Hocevar's avatar
Sam Hocevar committed
575
    vlc_t *p_vlc;
576

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

579
    if( !p_vlc )
580
    {
581
        return VLC_ENOOBJ;
582
583
584
    }

    /* Try to create the interface */
585
    p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
586
587
588

    if( p_intf == NULL )
    {
gbazin's avatar
   
gbazin committed
589
        msg_Err( p_vlc, "interface \"%s\" initialization failed", psz_module );
gbazin's avatar
   
gbazin committed
590
        if( i_object ) vlc_object_release( p_vlc );
591
592
593
594
595
        return VLC_EGENERIC;
    }

    /* Try to run the interface */
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
596
597
    i_err = intf_RunThread( p_intf );
    if( i_err )
598
    {
599
        vlc_object_detach( p_intf );
600
        intf_Destroy( p_intf );
gbazin's avatar
   
gbazin committed
601
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
602
        return i_err;
603
604
    }

gbazin's avatar
   
gbazin committed
605
    if( i_object ) vlc_object_release( p_vlc );
606
607
608
609
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
610
 * VLC_Destroy: stop playing and destroy everything.
611
 *****************************************************************************
612
 * This function requests the running threads to finish, waits for their
613
614
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
615
int VLC_Destroy( int i_object )
616
{
Sam Hocevar's avatar
Sam Hocevar committed
617
618
619
    vlc_t *p_vlc;

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

621
    if( !p_vlc )
622
    {
623
        return VLC_ENOOBJ;
624
625
    }

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

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

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

646
647
648
649
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
650

651
652
653
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

654
655
    vlc_object_detach( p_vlc );

656
657
658
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

659
660
    vlc_object_destroy( p_vlc );

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

664
665
666
    return VLC_SUCCESS;
}

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

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

    if( !p_vlc )
    {
681
        return VLC_ENOOBJ;
682
683
684
685
    }

    p_vlc->b_die = VLC_TRUE;

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

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

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

704
    if( !p_vlc )
705
    {
706
        return VLC_ENOOBJ;
707
708
    }

Sam Hocevar's avatar
Sam Hocevar committed
709
710
711
712
713
714
715
716
717
    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
718
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
719
720
721
722
723
724
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
    }

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

    vlc_object_release( p_playlist );
728

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

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

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

    if( !p_vlc )
    {
747
        return VLC_ENOOBJ;
748
749
    }

Sam Hocevar's avatar
Sam Hocevar committed
750
751
752
    /* 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 ) )
753
    {
Sam Hocevar's avatar
Sam Hocevar committed
754
        module_config_t *p_item;
755
        char const *psz_newvar = psz_var + 6;
756

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

Sam Hocevar's avatar
Sam Hocevar committed
759
        if( p_item )
760
        {
Sam Hocevar's avatar
Sam Hocevar committed
761
            switch( p_item->i_type )
762
            {
Sam Hocevar's avatar
Sam Hocevar committed
763
764
765
766
767
768
769
770
771
772
773
774
                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;
775
            }
gbazin's avatar
   
gbazin committed
776
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
777
            return VLC_SUCCESS;
778
779
780
        }
    }

gbazin's avatar
   
gbazin committed
781
782
783
784
    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
785
786
787
788
789
790
791
}

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

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

    if( !p_vlc )
800
    {
801
        return VLC_ENOOBJ;
802
803
    }

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

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
808
809
}

Sam Hocevar's avatar
Sam Hocevar committed
810
/* FIXME: temporary hacks */
811
812

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

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

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

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
    char *          psz_path;
Eric Petit's avatar
Eric Petit committed
997
#if defined( SYS_DARWIN ) || defined ( WIN32 ) || defined( SYS_BEOS )
998
999
1000
    char            psz_tmp[1024];
#endif

1001
1002
#   if defined( HAVE_INCLUDED_GETTEXT ) && !defined( HAVE_LC_MESSAGES )
    if( *psz_lang )
Sam Hocevar's avatar
Sam Hocevar committed
1003
    {
1004
1005
1006
1007
1008
1009
1010
1011
        /* We set LC_ALL manually because it is the only way to set
         * the language at runtime under eg. Windows. Beware that this
         * makes the environment unconsistent when libvlc is unloaded and
         * should probably be moved to a safer place like vlc.c. */
        static char psz_lcall[20];
        snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
        psz_lcall[19] = '\0';
        putenv( psz_lcall );
Sam Hocevar's avatar
Sam Hocevar committed
1012
    }
1013
#   endif
Sam Hocevar's avatar
Sam Hocevar committed
1014

gbazin's avatar
   
gbazin committed
1015
1016
    if( psz_lang && !*psz_lang )
    {
1017
#   if defined( HAVE_LC_MESSAGES )
gbazin's avatar
   
gbazin committed
1018
        setlocale( LC_MESSAGES, psz_lang );
Sam Hocevar's avatar
Sam Hocevar committed
1019
#   endif
gbazin's avatar
   
gbazin committed
1020
1021
1022
1023
        setlocale( LC_CTYPE, psz_lang );
    }
    else
    {
1024
1025
1026
#ifdef SYS_BEOS 
        static char psz_lcall[20];
#endif
gbazin's avatar
   
gbazin committed
1027
        setlocale( LC_ALL, psz_lang );
1028
1029
1030
1031
#ifdef SYS_DARWIN
        /* I need that under Darwin, please check it doesn't disturb
         * other platforms. --Meuuh */
        setenv( "LANG", psz_lang, 1 );
1032
1033
1034
1035
1036
1037
#endif
#ifdef SYS_BEOS
        /* I need this under BeOS... */
        snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
        psz_lcall[19] = '\0';
        putenv( psz_lcall );
1038
#endif
gbazin's avatar
   
gbazin committed
1039
    }
Sam Hocevar's avatar
Sam Hocevar committed
1040

1041
    /* Specify where to find the locales for current domain */
Eric Petit's avatar
Eric Petit committed
1042
#if !defined( SYS_DARWIN ) && !defined( WIN32 ) && !defined( SYS_BEOS )
1043
1044
    psz_path = LOCALEDIR;
#else
1045
    snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc.psz_vlcpath,
1046
1047
1048
1049
              "locale" );
    psz_path = psz_tmp;
#endif
    if( !bindtextdomain( PACKAGE, psz_path ) )
Sam Hocevar's avatar
Sam Hocevar committed
1050
1051
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
1052
                 PACKAGE, psz_path );
Sam Hocevar's avatar
Sam Hocevar committed
1053
1054
    }

1055
    /* Set the default domain */
Sam Hocevar's avatar
Sam Hocevar committed
1056
    textdomain( PACKAGE );
1057
1058
1059
1060
1061
1062

#ifdef SYS_BEOS
    /* BeOS only support UTF8 strings */
    bind_textdomain_codeset( PACKAGE, "UTF-8" );
#endif

Sam Hocevar's avatar
Sam Hocevar committed
1063
1064
1065
#endif
}

1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
/*****************************************************************************
 * GetFilenames: parse command line options which are not flags
 *****************************************************************************
 * Parse command line for input files.
 *****************************************************************************/
static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
{
    int i_opt;

    /* We assume that the remaining parameters are filenames */
1076
    for( i_opt = i_argc - 1; i_opt > optind; i_opt-- )
1077
    {
Sam Hocevar's avatar
Sam Hocevar committed
1078
1079
1080
        /* TODO: write an internal function of this one, to avoid
         *       unnecessary lookups. */
        VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ i_opt ],
1081
1082
1083
1084
1085
1086
1087
1088
                       PLAYLIST_INSERT, 0 );
    }

    /* If there is at least one target, play it */