libvlc.c 70.8 KB
Newer Older
1
2
3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2004 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
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 *
 * 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
31
#define MODULE_PATH main
32
33
34
35
36
#define __BUILTIN__

/*****************************************************************************
 * Preamble
 *****************************************************************************/
37
#include <vlc/vlc.h>
Laurent Aimar's avatar
Laurent Aimar committed
38
#include <vlc/input.h>
39

40
#include <errno.h>                                                 /* ENOMEM */
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
#ifdef HAVE_LOCALE_H
#   include <locale.h>
#endif

63
64
65
66
#ifdef HAVE_HAL
#   include <hal/libhal.h>
#endif

67
#include "vlc_cpu.h"                                        /* CPU detection */
68
#include "os_specific.h"
69

70
#include "vlc_error.h"
71

72
#include "vlc_playlist.h"
73
#include "vlc_interface.h"
74
75
76

#include "audio_output.h"

77
#include "vlc_video.h"
78
79
#include "video_output.h"

zorglub's avatar
zorglub committed
80
81
#include "stream_output.h"

82
83
84
#include "libvlc.h"

/*****************************************************************************
85
 * The evil global variable. We handle it with care, don't worry.
86
 *****************************************************************************/
87
88
89
static libvlc_t   libvlc;
static libvlc_t * p_libvlc;
static vlc_t *    p_static_vlc;
90
91
92
93

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

#ifdef WIN32
static void ShowConsole   ( void );
103
static void PauseConsole  ( void );
104
#endif
105
static int  ConsoleWidth  ( void );
106

hartman's avatar
hartman committed
107
108
static int  VerboseCallback( vlc_object_t *, char const *,
                             vlc_value_t, vlc_value_t, void * );
109

110
111
static void InitDeviceValues( vlc_t * );

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*****************************************************************************
 * vlc_current_object: return the current object.
 *****************************************************************************
 * If i_object is non-zero, return the corresponding object. Otherwise,
 * return the statically allocated p_vlc object.
 *****************************************************************************/
vlc_t * vlc_current_object( int i_object )
{
    if( i_object )
    {
         return vlc_object_get( p_libvlc, i_object );
    }

    return p_static_vlc;
}

128
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
129
 * VLC_Version: return the libvlc version.
130
 *****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
131
 * This function returns full version string (numeric version and codename).
132
 *****************************************************************************/
133
char const * VLC_Version( void )
134
{
Sam Hocevar's avatar
Sam Hocevar committed
135
    return VERSION_MESSAGE;
136
137
}

138
139
140
141
142
143
144
145
146
147
/*****************************************************************************
 * 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
148
149
150
151
152
153
154
/*****************************************************************************
 * 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 )
155
{
156
    int i_ret;
157
    vlc_t * p_vlc = NULL;
158
    vlc_value_t lockval;
159

160
161
162
    /* &libvlc never changes, so we can safely call this multiple times. */
    p_libvlc = &libvlc;

163
164
    /* vlc_threads_init *must* be the first internal call! No other call is
     * allowed before the thread system has been initialized. */
165
    i_ret = vlc_threads_init( p_libvlc );
Sam Hocevar's avatar
Sam Hocevar committed
166
    if( i_ret < 0 )
167
    {
Sam Hocevar's avatar
Sam Hocevar committed
168
        return i_ret;
169
170
171
    }

    /* Now that the thread system is initialized, we don't have much, but
172
     * at least we have var_Create */
173
174
    var_Create( p_libvlc, "libvlc", VLC_VAR_MUTEX );
    var_Get( p_libvlc, "libvlc", &lockval );
175
    vlc_mutex_lock( lockval.p_address );
176
177
    if( !libvlc.b_ready )
    {
178
179
        char *psz_env;

180
181
182
        /* Guess what CPU we have */
        libvlc.i_cpu = CPUCapabilities();

183
184
        /* Find verbosity from VLC_VERBOSE environment variable */
        psz_env = getenv( "VLC_VERBOSE" );
185
        libvlc.i_verbose = psz_env ? atoi( psz_env ) : -1;
186

gbazin's avatar
   
gbazin committed
187
#if defined( HAVE_ISATTY ) && !defined( WIN32 )
188
189
190
191
192
        libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
#else
        libvlc.b_color = VLC_FALSE;
#endif

193
        /* Initialize message queue */
194
        msg_Create( p_libvlc );
195
196

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

200
201
        /* The module bank will be initialized later */
        libvlc.p_module_bank = NULL;
202
203

        libvlc.b_ready = VLC_TRUE;
204
    }
205
    vlc_mutex_unlock( lockval.p_address );
206
    var_Destroy( p_libvlc, "libvlc" );
207
208

    /* Allocate a vlc object */
209
    p_vlc = vlc_object_create( p_libvlc, VLC_OBJECT_VLC );
210
211
    if( p_vlc == NULL )
    {
Sam Hocevar's avatar
Sam Hocevar committed
212
        return VLC_EGENERIC;
213
    }
214
    p_vlc->thread_id = 0;
215
216
217
218

    p_vlc->psz_object_name = "root";

    /* Initialize mutexes */
219
    vlc_mutex_init( p_vlc, &p_vlc->config_lock );
hartman's avatar
hartman committed
220
221
#ifdef SYS_DARWIN
    vlc_mutex_init( p_vlc, &p_vlc->quicktime_lock );
222
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );
hartman's avatar
hartman committed
223
#endif
224
225

    /* Store our newly allocated structure in the global list */
226
    vlc_object_attach( p_vlc, p_libvlc );
227

Sam Hocevar's avatar
Sam Hocevar committed
228
229
230
231
    /* Store data for the non-reentrant API */
    p_static_vlc = p_vlc;

    return p_vlc->i_object_id;
232
233
234
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
235
 * VLC_Init: initialize a vlc_t structure.
236
237
238
239
240
241
242
 *****************************************************************************
 * 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
243
int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
244
{
245
246
    char         p_capabilities[200];
    char *       p_tmp;
247
248
    char *       psz_modules;
    char *       psz_parser;
zorglub's avatar
zorglub committed
249
    char *       psz_control;
250
    vlc_bool_t   b_exit = VLC_FALSE;
251
    vlc_t *      p_vlc = vlc_current_object( i_object );
252
253
    module_t    *p_help_module;
    playlist_t  *p_playlist;
254
    vlc_value_t  val;
255
256
257
#ifndef WIN32
    char *       psz_language;
#endif
258

259
    if( !p_vlc )
260
    {
261
        return VLC_ENOOBJ;
262
263
264
    }

    /*
265
     * System specific initialization code
266
     */
267
    system_Init( p_vlc, &i_argc, ppsz_argv );
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

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

284
285
286
287
    /*
     * Support for gettext
     */
    SetLanguage( "" );
Sam Hocevar's avatar
Sam Hocevar committed
288
289

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

292
293
294
295
    /* 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) */
296
    module_InitBank( p_vlc );
297

298
299
300
301
    /* Hack: insert the help module here */
    p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
    if( p_help_module == NULL )
    {
302
        module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
303
        if( i_object ) vlc_object_release( p_vlc );
304
305
306
        return VLC_EGENERIC;
    }
    p_help_module->psz_object_name = "help";
gbazin's avatar
   
gbazin committed
307
    p_help_module->psz_longname = N_("Help options");
308
    config_Duplicate( p_help_module, p_help_config );
309
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
310
311
    /* End hack */

Sam Hocevar's avatar
Sam Hocevar committed
312
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
313
    {
314
        vlc_object_detach( p_help_module );
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
        return VLC_EGENERIC;
    }

    /* Check for short help option */
    if( config_GetInt( p_vlc, "help" ) )
    {
325
        Help( p_vlc, "help" );
326
        b_exit = VLC_TRUE;
327
328
    }
    /* Check for version option */
329
    else if( config_GetInt( p_vlc, "version" ) )
330
331
    {
        Version();
332
333
334
        b_exit = VLC_TRUE;
    }

gbazin's avatar
   
gbazin committed
335
336
337
338
    /* Set the config file stuff */
    p_vlc->psz_homedir = config_GetHomeDir();
    p_vlc->psz_configfile = config_GetPsz( p_vlc, "config" );

339
340
341
342
343
344
    /* Check for plugins cache options */
    if( config_GetInt( p_vlc, "reset-plugins-cache" ) )
    {
        libvlc.p_module_bank->b_cache_delete = VLC_TRUE;
    }

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

gbazin's avatar
gbazin committed
349
350
351
352
353
354
355
    /* Will be re-done properly later on */
    p_vlc->p_libvlc->i_verbose = config_GetInt( p_vlc, "verbose" );

    /* Check for daemon mode */
#ifndef WIN32
    if( config_GetInt( p_vlc, "daemon" ) )
    {
356
357
358
359
360
361
362
363
364
365
366
#if HAVE_DAEMON
        if( daemon( 0, 0) != 0 )
        {
            msg_Err( p_vlc, "Unable to fork vlc to daemon mode" );
            b_exit = VLC_TRUE;
        }

        p_vlc->p_libvlc->b_daemon = VLC_TRUE;

#else
        pid_t i_pid;
gbazin's avatar
gbazin committed
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

        if( ( i_pid = fork() ) < 0 )
        {
            msg_Err( p_vlc, "Unable to fork vlc to daemon mode" );
            b_exit = VLC_TRUE;
        }
        else if( i_pid )
        {
            /* This is the parent, exit right now */
            msg_Dbg( p_vlc, "closing parent process" );
            b_exit = VLC_TRUE;
        }
        else
        {
            /* We are the child */
            msg_Dbg( p_vlc, "daemon spawned" );
383
384
385
            close( STDIN_FILENO );
            close( STDOUT_FILENO );
            close( STDERR_FILENO );
gbazin's avatar
gbazin committed
386
387
388

            p_vlc->p_libvlc->b_daemon = VLC_TRUE;
        }
389
#endif
gbazin's avatar
gbazin committed
390
391
392
    }
#endif

393
394
    if( b_exit )
    {
395
396
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
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;
    }

gbazin's avatar
   
gbazin committed
402
    /* Check for translation config option */
gbazin's avatar
   
gbazin committed
403
404
405
406
407
408
409
410
#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. */
    config_LoadConfigFile( p_vlc, "main" );
    config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );

411
412
413
    /* 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
414
    {
415
416
        vlc_bool_t b_cache_delete = libvlc.p_module_bank->b_cache_delete;

gbazin's avatar
   
gbazin committed
417
        /* Reset the default domain */
418
        SetLanguage( psz_language );
gbazin's avatar
   
gbazin committed
419

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

Sam Hocevar's avatar
Sam Hocevar committed
423
        textdomain( PACKAGE_NAME );
gbazin's avatar
   
gbazin committed
424

gbazin's avatar
   
gbazin committed
425
#if defined( ENABLE_UTF8 )
Sam Hocevar's avatar
Sam Hocevar committed
426
        bind_textdomain_codeset( PACKAGE_NAME, "UTF-8" );
427
428
#endif

gbazin's avatar
   
gbazin committed
429
        module_EndBank( p_vlc );
430
        module_InitBank( p_vlc );
431
        config_LoadConfigFile( p_vlc, "main" );
gbazin's avatar
   
gbazin committed
432
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
433
        libvlc.p_module_bank->b_cache_delete = b_cache_delete;
gbazin's avatar
   
gbazin committed
434
    }
435
    if( psz_language ) free( psz_language );
436
#endif
gbazin's avatar
   
gbazin committed
437

438
439
440
441
442
443
    /*
     * 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.
     */
444
445
446
447
448
449
450
    module_LoadBuiltins( p_vlc );
    module_LoadPlugins( p_vlc );
    if( p_vlc->b_die )
    {
        b_exit = VLC_TRUE;
    }

451
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
452
                    libvlc.p_module_bank->i_children );
453
454

    /* Hack: insert the help module here */
455
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
456
457
458
459
460
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
461
        Help( p_vlc, p_tmp );
462
        free( p_tmp );
463
        b_exit = VLC_TRUE;
464
465
    }
    /* Check for long help option */
466
    else if( config_GetInt( p_vlc, "longhelp" ) )
467
    {
468
        Help( p_vlc, "longhelp" );
469
        b_exit = VLC_TRUE;
470
471
    }
    /* Check for module list option */
472
    else if( config_GetInt( p_vlc, "list" ) )
473
    {
474
        ListModules( p_vlc );
475
        b_exit = VLC_TRUE;
476
477
    }

gbazin's avatar
   
gbazin committed
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
    /* Check for config file options */
    if( config_GetInt( p_vlc, "reset-config" ) )
    {
        vlc_object_detach( p_help_module );
        config_ResetAll( p_vlc );
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
        config_SaveConfigFile( p_vlc, NULL );
        vlc_object_attach( p_help_module, libvlc.p_module_bank );
    }
    if( config_GetInt( p_vlc, "save-config" ) )
    {
        vlc_object_detach( p_help_module );
        config_LoadConfigFile( p_vlc, NULL );
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
        config_SaveConfigFile( p_vlc, NULL );
        vlc_object_attach( p_help_module, libvlc.p_module_bank );
    }

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

500
501
    if( b_exit )
    {
gbazin's avatar
   
gbazin committed
502
503
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
504
        module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
505
        if( i_object ) vlc_object_release( p_vlc );
506
507
508
        return VLC_EEXIT;
    }

509
510
511
512
513
    /*
     * Init device values
     */
    InitDeviceValues( p_vlc );

514
515
516
    /*
     * Override default configuration with config file settings
     */
517
    config_LoadConfigFile( p_vlc, NULL );
518

gbazin's avatar
   
gbazin committed
519
520
521
522
    /* Hack: insert the help module here */
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
    /* End hack */

523
524
525
    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
526
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
527
528
529
530
531
    {
#ifdef WIN32
        ShowConsole();
        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, "The command line options couldn't be loaded, check "
532
533
                 "that they are valid.\n" );
        PauseConsole();
534
#endif
gbazin's avatar
   
gbazin committed
535
536
537
        vlc_object_detach( p_help_module );
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
538
        module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
539
        if( i_object ) vlc_object_release( p_vlc );
540
541
542
        return VLC_EGENERIC;
    }

gbazin's avatar
   
gbazin committed
543
544
545
546
547
548
    /* Hack: remove the help module here */
    vlc_object_detach( p_help_module );
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

549
550
551
    /*
     * System specific configuration
     */
gbazin's avatar
   
gbazin committed
552
    system_Configure( p_vlc, &i_argc, ppsz_argv );
553

554
555
556
    /*
     * Message queue options
     */
hartman's avatar
hartman committed
557
558

    var_Create( p_vlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
559
560
    if( config_GetInt( p_vlc, "quiet" ) )
    {
hartman's avatar
hartman committed
561
562
        val.i_int = -1;
        var_Set( p_vlc, "verbose", val );
563
    }
hartman's avatar
hartman committed
564
565
    var_AddCallback( p_vlc, "verbose", VerboseCallback, NULL );
    var_Change( p_vlc, "verbose", VLC_VAR_TRIGGER_CALLBACKS, NULL, NULL );
zorglub's avatar
zorglub committed
566

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

569
570
571
572
573
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

574
    /* p_vlc initialization. FIXME ? */
575

576
577
578
    if( !config_GetInt( p_vlc, "fpu" ) )
        libvlc.i_cpu &= ~CPU_CAPABILITY_FPU;

Christophe Massiot's avatar
Christophe Massiot committed
579
#if defined( __i386__ ) || defined( __x86_64__ )
580
    if( !config_GetInt( p_vlc, "mmx" ) )
581
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
582
    if( !config_GetInt( p_vlc, "3dn" ) )
583
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
584
    if( !config_GetInt( p_vlc, "mmxext" ) )
585
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
586
    if( !config_GetInt( p_vlc, "sse" ) )
587
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
sigmunau's avatar
sigmunau committed
588
589
    if( !config_GetInt( p_vlc, "sse2" ) )
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE2;
590
591
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
592
    if( !config_GetInt( p_vlc, "altivec" ) )
593
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
594
#endif
595
596

#define PRINT_CAPABILITY( capability, string )                              \
597
    if( libvlc.i_cpu & capability )                                         \
598
599
600
601
602
603
604
605
606
607
608
609
610
611
    {                                                                       \
        strncat( p_capabilities, string " ",                                \
                 sizeof(p_capabilities) - strlen(p_capabilities) );         \
        p_capabilities[sizeof(p_capabilities) - 1] = '\0';                  \
    }

    p_capabilities[0] = '\0';
    PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
    PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
    PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
    PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
    PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
    PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
    PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
sigmunau's avatar
sigmunau committed
612
    PRINT_CAPABILITY( CPU_CAPABILITY_SSE2, "SSE2" );
613
614
615
616
617
618
619
    PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "AltiVec" );
    PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
    msg_Dbg( p_vlc, "CPU has capabilities %s", p_capabilities );

    /*
     * Choose the best memcpy module
     */
gbazin's avatar
   
gbazin committed
620
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy", 0 );
621

622
    if( p_vlc->pf_memcpy == NULL )
623
624
625
    {
        p_vlc->pf_memcpy = memcpy;
    }
626
627
628
629
630

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

sigmunau's avatar
sigmunau committed
632
633
634
635
    /*
     * Initialize hotkey handling
     */
    var_Create( p_vlc, "key-pressed", VLC_VAR_INTEGER );
gbazin's avatar
   
gbazin committed
636
637
    p_vlc->p_hotkeys = malloc( sizeof(p_hotkeys) );
    /* Do a copy (we don't need to modify the strings) */
638
    memcpy( p_vlc->p_hotkeys, p_hotkeys, sizeof(p_hotkeys) );
gbazin's avatar
   
gbazin committed
639

640
641
642
    /*
     * Initialize playlist and get commandline files
     */
643
    p_playlist = playlist_Create( p_vlc );
644
645
646
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
647
648
        if( p_vlc->p_memcpy_module != NULL )
        {
649
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
650
        }
651
        module_EndBank( p_vlc );
gbazin's avatar
   
gbazin committed
652
        if( i_object ) vlc_object_release( p_vlc );
653
654
655
        return VLC_EGENERIC;
    }

656
657
658
659
660
661
662
    psz_modules = config_GetPsz( p_playlist, "services-discovery" );
    if( psz_modules && *psz_modules )
    {
        /* Add service discovery modules */
        playlist_AddSDModules( p_playlist, psz_modules );
    }
    if( psz_modules ) free( psz_modules );
zorglub's avatar
zorglub committed
663

664
665
666
667
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
zorglub's avatar
zorglub committed
668
669
670
671
672
673
    psz_control = config_GetPsz( p_vlc, "control" );

    if( psz_modules && *psz_modules && psz_control && *psz_control )
    {
        psz_modules = (char *)realloc( psz_modules, strlen( psz_modules ) +
                                                    strlen( psz_control ) + 1 );
674
        sprintf( psz_modules, "%s:%s", psz_modules, psz_control );
zorglub's avatar
zorglub committed
675
676
677
678
679
680
681
    }
    else if( psz_control && *psz_control )
    {
        if( psz_modules ) free( psz_modules );
        psz_modules = strdup( psz_control );
    }

682
683
684
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
gbazin's avatar
   
gbazin committed
685
        char *psz_module, *psz_temp;
686
        psz_module = psz_parser;
687
        psz_parser = strchr( psz_module, ':' );
688
689
690
691
692
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
gbazin's avatar
   
gbazin committed
693
694
695
696
        psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
        if( psz_temp )
        {
            sprintf( psz_temp, "%s,none", psz_module );
697
            VLC_AddIntf( 0, psz_temp, VLC_FALSE, VLC_FALSE );
gbazin's avatar
   
gbazin committed
698
699
            free( psz_temp );
        }
700
701
702
703
704
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
705

sigmunau's avatar
sigmunau committed
706
707
708
    /*
     * Allways load the hotkeys interface if it exists
     */
709
    VLC_AddIntf( 0, "hotkeys,none", VLC_FALSE, VLC_FALSE );
sigmunau's avatar
sigmunau committed
710

711
712
713
714
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );
715
716
717
718
719
720
721
722
723
724
725
    var_Create( p_vlc, "drawableredraw", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawablet", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawablel", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawableb", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawabler", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawablex", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawabley", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawablew", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawableh", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawableportx", VLC_VAR_INTEGER );
    var_Create( p_vlc, "drawableporty", VLC_VAR_INTEGER );
726

727
728
729
730
731
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

732
733
734
735
736
737
738
739
740
741
742
743
    /*
     * Get --open argument
     */
    var_Create( p_vlc, "open", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Get( p_vlc, "open", &val );
    if ( val.psz_string != NULL && *val.psz_string )
    {
        VLC_AddTarget( p_vlc->i_object_id, val.psz_string, NULL, 0,
                       PLAYLIST_INSERT, 0 );
    }
    if ( val.psz_string != NULL ) free( val.psz_string );

gbazin's avatar
   
gbazin committed
744
    if( i_object ) vlc_object_release( p_vlc );
745
746
747
748
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
749
 * VLC_AddIntf: add an interface
750
751
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
752
753
 * 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
754
755
 * user requests to quit. If b_play is set to 1, VLC_AddIntf will start playing
 * the playlist when it is completely initialised.
756
 *****************************************************************************/
757
758
int VLC_AddIntf( int i_object, char const *psz_module,
                 vlc_bool_t b_block, vlc_bool_t b_play )
759
{
Sam Hocevar's avatar
Sam Hocevar committed
760
    int i_err;
761
    intf_thread_t *p_intf;
762
    vlc_t *p_vlc = vlc_current_object( i_object );
Sam Hocevar's avatar
Sam Hocevar committed
763

764
    if( !p_vlc )
765
    {
766
        return VLC_ENOOBJ;
767
768
    }

gbazin's avatar
gbazin committed
769
770
771
772
773
774
775
776
777
778
779
#ifndef WIN32
    if( p_vlc->p_libvlc->b_daemon && b_block && !psz_module )
    {
        /* Daemon mode hack.
         * We prefer the dummy interface if none is specified. */
        char *psz_interface = config_GetPsz( p_vlc, "intf" );
        if( !psz_interface || !*psz_interface ) psz_module = "dummy";
        if( psz_interface ) free( psz_interface );
    }
#endif

780
    /* Try to create the interface */
781
    p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
782
783
784

    if( p_intf == NULL )
    {
gbazin's avatar
   
gbazin committed
785
        msg_Err( p_vlc, "interface \"%s\" initialization failed", psz_module );
gbazin's avatar
   
gbazin committed
786
        if( i_object ) vlc_object_release( p_vlc );
787
788
789
        return VLC_EGENERIC;
    }

790
791
792
    /* Interface doesn't handle play on start so do it ourselves */
    if( !p_intf->b_play && b_play ) VLC_Play( i_object );

793
    /* Try to run the interface */
794
    p_intf->b_play = b_play;
795
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
796
797
    i_err = intf_RunThread( p_intf );
    if( i_err )
798
    {
799
        vlc_object_detach( p_intf );
800
        intf_Destroy( p_intf );
gbazin's avatar
   
gbazin committed
801
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
802
        return i_err;
803
804
    }

gbazin's avatar
   
gbazin committed
805
    if( i_object ) vlc_object_release( p_vlc );
806
807
808
809
    return VLC_SUCCESS;
}

/*****************************************************************************
hartman's avatar
hartman committed
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
904
905
906
907
908
909
910
911
 * VLC_Die: ask vlc to die.
 *****************************************************************************
 * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
 * task. It is your duty to call VLC_CleanUp and VLC_Destroy afterwards.
 *****************************************************************************/
int VLC_Die( int i_object )
{
    vlc_t *p_vlc = vlc_current_object( i_object );

    if( !p_vlc )
    {
        return VLC_ENOOBJ;
    }

    p_vlc->b_die = VLC_TRUE;

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

/*****************************************************************************
 * VLC_CleanUp: CleanUp all the intf, playlist, vout, aout
 *****************************************************************************/
int VLC_CleanUp( int i_object )
{
    intf_thread_t      * p_intf;
    playlist_t         * p_playlist;
    vout_thread_t      * p_vout;
    aout_instance_t    * p_aout;
    announce_handler_t * p_announce;
    vlc_t *p_vlc = vlc_current_object( i_object );

    /* Check that the handle is valid */
    if( !p_vlc )
    {
        return VLC_ENOOBJ;
    }

    /*
     * Ask the interfaces to stop and destroy them
     */
    msg_Dbg( p_vlc, "removing all interfaces" );
    while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_CHILD )) )
    {
        intf_StopThread( p_intf );
        vlc_object_detach( p_intf );
        vlc_object_release( p_intf );
        intf_Destroy( p_intf );
    }

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

    /*
     * Free audio outputs
     */
    msg_Dbg( p_vlc, "removing all audio outputs" );
    while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
    {
        vlc_object_detach( (vlc_object_t *)p_aout );
        vlc_object_release( (vlc_object_t *)p_aout );
        aout_Delete( p_aout );
    }

    /*
     * Free announce handler(s?)
     */
    msg_Dbg( p_vlc, "removing announce handler" );
    while( (p_announce = vlc_object_find( p_vlc, VLC_OBJECT_ANNOUNCE,
                                                 FIND_CHILD ) ) )
   {
        vlc_object_detach( p_announce );
        vlc_object_release( p_announce );
        announce_HandlerDestroy( p_announce );
   }

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

/*****************************************************************************
 * VLC_Destroy: Destroy everything.
912
 *****************************************************************************
913
 * This function requests the running threads to finish, waits for their
914
915
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
916
int VLC_Destroy( int i_object )
917
{
918
    vlc_t *p_vlc = vlc_current_object( i_object );
919

920
    if( !p_vlc )
921
    {
922
        return VLC_ENOOBJ;
923
924
    }

925
926
927
928
929
930
931
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
932
933
    }

934
    /*
935
     * Free module bank !
936
937
938
     */
    module_EndBank( p_vlc );

939
940
941
942
943
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
944

gbazin's avatar
   
gbazin committed
945
946
947
948
949
950
    if( p_vlc->psz_configfile )
    {
        free( p_vlc->psz_configfile );
        p_vlc->psz_configfile = NULL;
    }

951
952
953
954
955
956
    if( p_vlc->p_hotkeys )
    {
        free( p_vlc->p_hotkeys );
        p_vlc->p_hotkeys = NULL;
    }

957
958
959
960
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
961

962
963
964
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

965
966
    vlc_object_detach( p_vlc );

967
968
969
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

970
971
    vlc_object_destroy( p_vlc );

972
    /* Stop thread system: last one out please shut the door! */
973
    vlc_threads_end( p_libvlc );
974

975
976
977
    return VLC_SUCCESS;
}

978
/*****************************************************************************
hartman's avatar
hartman committed
979
 * VLC_VariableSet: set a vlc variable
980
 *****************************************************************************/
hartman's avatar
hartman committed
981
int VLC_VariableSet( int i_object, char const *psz_var, vlc_value_t value )
982
{
983
    vlc_t *p_vlc = vlc_current_object( i_object );
gbazin's avatar
   
gbazin committed
984
    int i_ret;
985
986
987

    if( !p_vlc )
    {
988
        return VLC_ENOOBJ;
989
990
    }

Sam Hocevar's avatar
Sam Hocevar committed
991
992
993
    /* 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 ) )
994
    {
Sam Hocevar's avatar
Sam Hocevar committed
995
        module_config_t *p_item;
996
        char const *psz_newvar = psz_var + 6;
997

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

Sam Hocevar's avatar
Sam Hocevar committed
1000
        if( p_item )
1001
        {
Sam Hocevar's avatar
Sam Hocevar committed
1002
            switch( p_item->i_type )
1003
            {
Sam Hocevar's avatar
Sam Hocevar committed
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
                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;
1016
            }
gbazin's avatar
   
gbazin committed
1017
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
1018
            return VLC_SUCCESS;
1019
1020
1021
        }
    }

gbazin's avatar
   
gbazin committed
1022
1023
1024
1025
    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
1026
1027
1028
}

/*****************************************************************************
hartman's avatar
hartman committed
1029
 * VLC_VariableGet: get a vlc variable
Sam Hocevar's avatar
Sam Hocevar committed
1030
 *****************************************************************************/
1031
int VLC_VariableGet( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
1032
{
1033
    vlc_t *p_vlc = vlc_current_object( i_object );
gbazin's avatar
   
gbazin committed
1034
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
1035
1036

    if( !p_vlc )
1037
    {
1038
        return VLC_ENOOBJ;
1039
1040
    }

1041
    i_ret = var_Get( p_vlc , psz_var, p_value );
gbazin's avatar
   
gbazin committed
1042
1043
1044

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
1045
1046
}

1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
/*****************************************************************************
 * VLC_VariableType: get a vlc variable type
 *****************************************************************************/
int VLC_VariableType( int i_object, char const *psz_var, int *pi_type )
{
    int i_type;
    vlc_t *p_vlc = vlc_current_object( i_object );

    if( !p_vlc )
    {
        return VLC_ENOOBJ;
    }

1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
    /* 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 ) )
    {
        module_config_t *p_item;
        char const *psz_newvar = psz_var + 6;

        p_item = config_FindConfig( VLC_OBJECT(p_vlc), psz_newvar );

        if( p_item )
        {
            switch( p_item->i_type )
            {
                case CONFIG_ITEM_BOOL:
                    i_type = VLC_VAR_BOOL;
                    break;
                case CONFIG_ITEM_INTEGER:
                    i_type = VLC_VAR_INTEGER;
                    break;
                case CONFIG_ITEM_FLOAT:
                    i_type = VLC_VAR_FLOAT;
                    break;
                default:
                    i_type = VLC_VAR_STRING;
                    break;
            }
        }
        else
            i_type = 0;
    }
    else
        i_type = VLC_VAR_TYPE & var_Type( p_vlc , psz_var );
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102

    if( i_object ) vlc_object_release( p_vlc );

    if( i_type > 0 )
    {
        *pi_type = i_type;
        return VLC_SUCCESS;
    }
    return VLC_ENOVAR;
}

1103
/*****************************************************************************
hartman's avatar
hartman committed
1104
1105
1106
1107
 * VLC_AddTarget: adds a target for playing.
 *****************************************************************************
 * This function adds psz_target to the current playlist. If a playlist does
 * not exist, it will create one.
1108
 *****************************************************************************/
hartman's avatar
hartman committed
1109
1110
1111
int VLC_AddTarget( int i_object, char const *psz_target,
                   char const **ppsz_options, int i_options,
                   int i_mode, int i_pos )
1112
{
hartman's avatar
hartman committed
1113
1114
    int i_err;
    playlist_t *p_playlist;
1115
1116
1117
1118
1119
1120
1121
    vlc_t *p_vlc = vlc_current_object( i_object );

    if( !p_vlc )
    {
        return VLC_ENOOBJ;
    }

hartman's avatar
hartman committed
1122
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1123

hartman's avatar
hartman committed
1124
    if( p_playlist == NULL )
1125