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

80
#include "stream_output.h"
81
#include "charset.h"
82

83 84 85
#include "libvlc.h"

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

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

#ifdef WIN32
static void ShowConsole   ( void );
106
static void PauseConsole  ( void );
107
#endif
108
static int  ConsoleWidth  ( void );
109

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
110 111
static int  VerboseCallback( vlc_object_t *, char const *,
                             vlc_value_t, vlc_value_t, void * );
112

113 114
static void InitDeviceValues( vlc_t * );

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
/*****************************************************************************
 * 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;
}

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

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

163 164 165
    /* &libvlc never changes, so we can safely call this multiple times. */
    p_libvlc = &libvlc;

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

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

183 184 185
        /* Guess what CPU we have */
        libvlc.i_cpu = CPUCapabilities();

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

Gildas Bazin's avatar
 
Gildas Bazin committed
190
#if defined( HAVE_ISATTY ) && !defined( WIN32 )
191 192 193 194 195
        libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
#else
        libvlc.b_color = VLC_FALSE;
#endif

196
        /* Initialize message queue */
197
        msg_Create( p_libvlc );
198 199

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

203 204
        /* The module bank will be initialized later */
        libvlc.p_module_bank = NULL;
205 206

        libvlc.b_ready = VLC_TRUE;
207 208 209

        /* UTF-8 convertor are initialized after the locale */
        libvlc.from_locale = libvlc.to_locale = (vlc_iconv_t)(-1);
210
    }
211
    vlc_mutex_unlock( lockval.p_address );
212
    var_Destroy( p_libvlc, "libvlc" );
213 214

    /* Allocate a vlc object */
215
    p_vlc = vlc_object_create( p_libvlc, VLC_OBJECT_VLC );
216 217
    if( p_vlc == NULL )
    {
Sam Hocevar's avatar
Sam Hocevar committed
218
        return VLC_EGENERIC;
219
    }
220
    p_vlc->thread_id = 0;
221 222 223 224

    p_vlc->psz_object_name = "root";

    /* Initialize mutexes */
225
    vlc_mutex_init( p_vlc, &p_vlc->config_lock );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
226 227
#ifdef SYS_DARWIN
    vlc_mutex_init( p_vlc, &p_vlc->quicktime_lock );
228
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
229
#endif
230 231

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

Sam Hocevar's avatar
Sam Hocevar committed
234 235 236 237
    /* Store data for the non-reentrant API */
    p_static_vlc = p_vlc;

    return p_vlc->i_object_id;
238 239 240
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
241
 * VLC_Init: initialize a vlc_t structure.
242 243 244 245 246 247 248
 *****************************************************************************
 * 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
249
int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
250
{
251 252
    char         p_capabilities[200];
    char *       p_tmp;
253 254
    char *       psz_modules;
    char *       psz_parser;
255
    char *       psz_control;
256
    vlc_bool_t   b_exit = VLC_FALSE;
257
    vlc_t *      p_vlc = vlc_current_object( i_object );
258 259
    module_t    *p_help_module;
    playlist_t  *p_playlist;
260
    vlc_value_t  val;
261 262
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
263
    char *       psz_language;
264
#endif
265

266
    if( !p_vlc )
267
    {
268
        return VLC_ENOOBJ;
269 270 271
    }

    /*
272
     * System specific initialization code
273
     */
274
    system_Init( p_vlc, &i_argc, ppsz_argv );
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290

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

291 292 293 294
    /*
     * Support for gettext
     */
    SetLanguage( "" );
Sam Hocevar's avatar
Sam Hocevar committed
295

296 297 298 299 300 301
    /*
     * Global iconv, must be done after setlocale()
     * so that vlc_current_charset() works.
     */
    LocaleInit();

Sam Hocevar's avatar
Sam Hocevar committed
302
    /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
303 304
    msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );

305 306 307 308
    /* 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) */
309
    module_InitBank( p_vlc );
310

311 312 313 314
    /* Hack: insert the help module here */
    p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
    if( p_help_module == NULL )
    {
315
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
316
        if( i_object ) vlc_object_release( p_vlc );
317 318 319
        return VLC_EGENERIC;
    }
    p_help_module->psz_object_name = "help";
Gildas Bazin's avatar
 
Gildas Bazin committed
320
    p_help_module->psz_longname = N_("Help options");
321
    config_Duplicate( p_help_module, p_help_config );
322
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
323 324
    /* End hack */

Sam Hocevar's avatar
Sam Hocevar committed
325
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
326
    {
327
        vlc_object_detach( p_help_module );
328 329
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
330
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
331
        if( i_object ) vlc_object_release( p_vlc );
332 333 334 335 336 337
        return VLC_EGENERIC;
    }

    /* Check for short help option */
    if( config_GetInt( p_vlc, "help" ) )
    {
338
        Help( p_vlc, "help" );
339
        b_exit = VLC_TRUE;
340 341
    }
    /* Check for version option */
342
    else if( config_GetInt( p_vlc, "version" ) )
343 344
    {
        Version();
345 346 347
        b_exit = VLC_TRUE;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
348 349 350 351
    /* Set the config file stuff */
    p_vlc->psz_homedir = config_GetHomeDir();
    p_vlc->psz_configfile = config_GetPsz( p_vlc, "config" );

352 353 354 355 356 357
    /* Check for plugins cache options */
    if( config_GetInt( p_vlc, "reset-plugins-cache" ) )
    {
        libvlc.p_module_bank->b_cache_delete = VLC_TRUE;
    }

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

Gildas Bazin's avatar
Gildas Bazin committed
362 363 364 365 366 367 368
    /* 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" ) )
    {
369 370 371 372 373 374 375 376 377 378 379
#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;
Gildas Bazin's avatar
Gildas Bazin committed
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395

        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" );
396 397 398
            close( STDIN_FILENO );
            close( STDOUT_FILENO );
            close( STDERR_FILENO );
Gildas Bazin's avatar
Gildas Bazin committed
399 400 401

            p_vlc->p_libvlc->b_daemon = VLC_TRUE;
        }
402
#endif
Gildas Bazin's avatar
Gildas Bazin committed
403 404 405
    }
#endif

406 407
    if( b_exit )
    {
408 409
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
410
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
411
        if( i_object ) vlc_object_release( p_vlc );
412 413 414
        return VLC_EEXIT;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
415
    /* Check for translation config option */
Gildas Bazin's avatar
 
Gildas Bazin committed
416 417 418 419 420 421 422 423
#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 );

424 425 426
    /* Check if the user specified a custom language */
    psz_language = config_GetPsz( p_vlc, "language" );
    if( psz_language && *psz_language && strcmp( psz_language, "auto" ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
427
    {
428 429
        vlc_bool_t b_cache_delete = libvlc.p_module_bank->b_cache_delete;

Gildas Bazin's avatar
 
Gildas Bazin committed
430
        /* Reset the default domain */
431
        SetLanguage( psz_language );
432 433
        LocaleDeinit();
        LocaleInit();
Gildas Bazin's avatar
 
Gildas Bazin committed
434

Gildas Bazin's avatar
 
Gildas Bazin committed
435 436 437
        /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
        msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );

Gildas Bazin's avatar
 
Gildas Bazin committed
438
        module_EndBank( p_vlc );
439
        module_InitBank( p_vlc );
440
        config_LoadConfigFile( p_vlc, "main" );
Gildas Bazin's avatar
 
Gildas Bazin committed
441
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
442
        libvlc.p_module_bank->b_cache_delete = b_cache_delete;
Gildas Bazin's avatar
 
Gildas Bazin committed
443
    }
444
    if( psz_language ) free( psz_language );
445
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
446

447 448 449 450 451 452
    /*
     * 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.
     */
453 454 455 456 457 458 459
    module_LoadBuiltins( p_vlc );
    module_LoadPlugins( p_vlc );
    if( p_vlc->b_die )
    {
        b_exit = VLC_TRUE;
    }

460
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
461
                    libvlc.p_module_bank->i_children );
462 463

    /* Hack: insert the help module here */
464
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
465 466 467 468 469
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
470
        Help( p_vlc, p_tmp );
471
        free( p_tmp );
472
        b_exit = VLC_TRUE;
473 474
    }
    /* Check for long help option */
475
    else if( config_GetInt( p_vlc, "longhelp" ) )
476
    {
477
        Help( p_vlc, "longhelp" );
478
        b_exit = VLC_TRUE;
479 480
    }
    /* Check for module list option */
481
    else if( config_GetInt( p_vlc, "list" ) )
482
    {
483
        ListModules( p_vlc );
484
        b_exit = VLC_TRUE;
485 486
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
    /* 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 );
    }

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

509 510
    if( b_exit )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
511 512
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
513
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
514
        if( i_object ) vlc_object_release( p_vlc );
515 516 517
        return VLC_EEXIT;
    }

518 519 520 521 522
    /*
     * Init device values
     */
    InitDeviceValues( p_vlc );

523 524 525
    /*
     * Override default configuration with config file settings
     */
526
    config_LoadConfigFile( p_vlc, NULL );
527

Gildas Bazin's avatar
 
Gildas Bazin committed
528 529 530 531
    /* Hack: insert the help module here */
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
    /* End hack */

532 533 534
    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
535
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
536 537 538 539 540
    {
#ifdef WIN32
        ShowConsole();
        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, "The command line options couldn't be loaded, check "
541 542
                 "that they are valid.\n" );
        PauseConsole();
543
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
544 545 546
        vlc_object_detach( p_help_module );
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
547
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
548
        if( i_object ) vlc_object_release( p_vlc );
549 550 551
        return VLC_EGENERIC;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
552 553 554 555 556 557
    /* 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 */

558 559 560
    /*
     * System specific configuration
     */
Gildas Bazin's avatar
 
Gildas Bazin committed
561
    system_Configure( p_vlc, &i_argc, ppsz_argv );
562

563 564 565
    /*
     * Message queue options
     */
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
566 567

    var_Create( p_vlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
568 569
    if( config_GetInt( p_vlc, "quiet" ) )
    {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
570 571
        val.i_int = -1;
        var_Set( p_vlc, "verbose", val );
572
    }
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
573 574
    var_AddCallback( p_vlc, "verbose", VerboseCallback, NULL );
    var_Change( p_vlc, "verbose", VLC_VAR_TRIGGER_CALLBACKS, NULL, NULL );
Clément Stenac's avatar
Clément Stenac committed
575

Gildas Bazin's avatar
 
Gildas Bazin committed
576
    libvlc.b_color = libvlc.b_color && config_GetInt( p_vlc, "color" );
577

578 579 580 581 582
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

583
    /* p_vlc initialization. FIXME ? */
584

585 586 587
    if( !config_GetInt( p_vlc, "fpu" ) )
        libvlc.i_cpu &= ~CPU_CAPABILITY_FPU;

Christophe Massiot's avatar
Christophe Massiot committed
588
#if defined( __i386__ ) || defined( __x86_64__ )
589
    if( !config_GetInt( p_vlc, "mmx" ) )
590
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
591
    if( !config_GetInt( p_vlc, "3dn" ) )
592
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
593
    if( !config_GetInt( p_vlc, "mmxext" ) )
594
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
595
    if( !config_GetInt( p_vlc, "sse" ) )
596
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
597 598
    if( !config_GetInt( p_vlc, "sse2" ) )
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE2;
599 600
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
601
    if( !config_GetInt( p_vlc, "altivec" ) )
602
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
603
#endif
604 605

#define PRINT_CAPABILITY( capability, string )                              \
606
    if( libvlc.i_cpu & capability )                                         \
607 608 609 610 611 612 613 614 615 616 617 618 619 620
    {                                                                       \
        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" );
621
    PRINT_CAPABILITY( CPU_CAPABILITY_SSE2, "SSE2" );
622 623 624 625 626 627 628
    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
     */
Gildas Bazin's avatar
 
Gildas Bazin committed
629
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy", 0 );
630

631
    if( p_vlc->pf_memcpy == NULL )
632 633 634
    {
        p_vlc->pf_memcpy = memcpy;
    }
635 636 637 638 639

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

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
641 642 643 644
    /*
     * Initialize hotkey handling
     */
    var_Create( p_vlc, "key-pressed", VLC_VAR_INTEGER );
Gildas Bazin's avatar
 
Gildas Bazin committed
645 646
    p_vlc->p_hotkeys = malloc( sizeof(p_hotkeys) );
    /* Do a copy (we don't need to modify the strings) */
647
    memcpy( p_vlc->p_hotkeys, p_hotkeys, sizeof(p_hotkeys) );
Gildas Bazin's avatar
 
Gildas Bazin committed
648

649 650 651
    /*
     * Initialize playlist and get commandline files
     */
652
    p_playlist = playlist_Create( p_vlc );
653 654 655
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
656 657
        if( p_vlc->p_memcpy_module != NULL )
        {
658
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
659
        }
660
        module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
661
        if( i_object ) vlc_object_release( p_vlc );
662 663 664
        return VLC_EGENERIC;
    }

665 666 667 668 669 670 671
    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 );
672

673 674 675 676
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
677 678 679 680 681 682
    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 );
683
        sprintf( psz_modules, "%s:%s", psz_modules, psz_control );
684 685 686 687 688 689 690
    }
    else if( psz_control && *psz_control )
    {
        if( psz_modules ) free( psz_modules );
        psz_modules = strdup( psz_control );
    }

691 692 693
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
694
        char *psz_module, *psz_temp;
695
        psz_module = psz_parser;
696
        psz_parser = strchr( psz_module, ':' );
697 698 699 700 701
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
702 703 704 705
        psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
        if( psz_temp )
        {
            sprintf( psz_temp, "%s,none", psz_module );
706
            VLC_AddIntf( 0, psz_temp, VLC_FALSE, VLC_FALSE );
Gildas Bazin's avatar
 
Gildas Bazin committed
707 708
            free( psz_temp );
        }
709 710 711 712 713
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
714

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
715 716 717
    /*
     * Allways load the hotkeys interface if it exists
     */
718
    VLC_AddIntf( 0, "hotkeys,none", VLC_FALSE, VLC_FALSE );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
719

720 721 722 723
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );
724 725 726 727 728 729 730 731 732 733 734
    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 );
735

736 737 738 739 740
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

741 742 743 744 745 746 747 748 749 750 751 752
    /*
     * 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 );

Gildas Bazin's avatar
 
Gildas Bazin committed
753
    if( i_object ) vlc_object_release( p_vlc );
754 755 756 757
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
758
 * VLC_AddIntf: add an interface
759 760
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
761 762
 * 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
763 764
 * user requests to quit. If b_play is set to 1, VLC_AddIntf will start playing
 * the playlist when it is completely initialised.
765
 *****************************************************************************/
766 767
int VLC_AddIntf( int i_object, char const *psz_module,
                 vlc_bool_t b_block, vlc_bool_t b_play )
768
{
Sam Hocevar's avatar
Sam Hocevar committed
769
    int i_err;
770
    intf_thread_t *p_intf;
771
    vlc_t *p_vlc = vlc_current_object( i_object );
Sam Hocevar's avatar
Sam Hocevar committed
772

773
    if( !p_vlc )
774
    {
775
        return VLC_ENOOBJ;
776 777
    }

Gildas Bazin's avatar
Gildas Bazin committed
778 779 780 781 782 783 784 785 786 787 788
#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

789
    /* Try to create the interface */
790
    p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
791 792 793

    if( p_intf == NULL )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
794
        msg_Err( p_vlc, "interface \"%s\" initialization failed", psz_module );
Gildas Bazin's avatar
 
Gildas Bazin committed
795
        if( i_object ) vlc_object_release( p_vlc );
796 797 798
        return VLC_EGENERIC;
    }

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

802
    /* Try to run the interface */
803
    p_intf->b_play = b_play;
804
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
805 806
    i_err = intf_RunThread( p_intf );
    if( i_err )
807
    {
808
        vlc_object_detach( p_intf );
809
        intf_Destroy( p_intf );
Gildas Bazin's avatar
 
Gildas Bazin committed
810
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
811
        return i_err;
812 813
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
814
    if( i_object ) vlc_object_release( p_vlc );
815 816 817 818
    return VLC_SUCCESS;
}

/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
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 912 913 914 915 916 917 918 919 920
 * 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.
921
 *****************************************************************************
922
 * This function requests the running threads to finish, waits for their
923 924
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
925
int VLC_Destroy( int i_object )
926
{
927
    vlc_t *p_vlc = vlc_current_object( i_object );
928

929
    if( !p_vlc )
930
    {
931
        return VLC_ENOOBJ;
932 933
    }

934 935 936 937 938 939 940
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
941 942
    }

943
    /*
944
     * Free module bank !
945 946 947
     */
    module_EndBank( p_vlc );

948 949 950 951 952
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
953

Gildas Bazin's avatar
 
Gildas Bazin committed
954 955 956 957 958 959
    if( p_vlc->psz_configfile )
    {
        free( p_vlc->psz_configfile );
        p_vlc->psz_configfile = NULL;
    }

960 961 962 963 964 965
    if( p_vlc->p_hotkeys )
    {
        free( p_vlc->p_hotkeys );
        p_vlc->p_hotkeys = NULL;
    }

966 967 968 969
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
970

971 972 973 974 975 976 977
    /*
     * Free message queue.
     * Nobody shall use msg_* afterward.
     */
    msg_Flush( p_vlc );
    msg_Destroy( p_libvlc );

978
    /* Destroy global iconv */
979
    LocaleDeinit();
980

981 982 983
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

984 985
    vlc_object_detach( p_vlc );

986 987 988
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

989 990
    vlc_object_destroy( p_vlc );

991
    /* Stop thread system: last one out please shut the door! */
992
    vlc_threads_end( p_libvlc );
993

994 995 996
    return VLC_SUCCESS;
}

997
/*****************************************************************************
998
 * VLC_VariableSet: set a vlc variable
999
 *****************************************************************************/
1000
int VLC_VariableSet( int i_object, char const *psz_var, vlc_value_t value )
1001
{
1002
    vlc_t *p_vlc = vlc_current_object( i_object );
Gildas Bazin's avatar
 
Gildas Bazin committed
1003
    int i_ret;
1004 1005 1006

    if( !p_vlc )
    {
1007
        return VLC_ENOOBJ;
1008 1009
    }

Sam Hocevar's avatar
Sam Hocevar committed
1010 1011 1012
    /* 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 ) )
1013
    {
Sam Hocevar's avatar
Sam Hocevar committed
1014
        module_config_t *p_item;
1015
        char const *psz_newvar = psz_var + 6;
1016

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

Sam Hocevar's avatar
Sam Hocevar committed
1019
        if( p_item )
1020
        {
Sam Hocevar's avatar
Sam Hocevar committed
1021
            switch( p_item->i_type )
1022
            {
Sam Hocevar's avatar
Sam Hocevar committed
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
                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;
1035
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
1036
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
1037
            return VLC_SUCCESS;
1038 1039 1040
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
1041 1042 1043 1044
    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
1045 1046 1047
}

/*****************************************************************************
1048
 * VLC_VariableGet: get a vlc variable
Sam Hocevar's avatar
Sam Hocevar committed
1049
 *****************************************************************************/
1050
int VLC_VariableGet( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
1051
{
1052
    vlc_t *p_vlc = vlc_current_object( i_object );
Gildas Bazin's avatar
 
Gildas Bazin committed
1053
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
1054 1055

    if( !p_vlc )
1056
    {
1057
        return VLC_ENOOBJ;
1058 1059
    }

1060
    i_ret = var_Get( p_vlc , psz_var, p_value );
Gildas Bazin's avatar
 
Gildas Bazin committed
1061 1062 1063

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
1064 1065
}

1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
/*****************************************************************************
 * 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;
    }

1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
    /* 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 );
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121

    if( i_object ) vlc_object_release( p_vlc );

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

1122
/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1123 1124 1125 1126
 * 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.
1127
 *****************************************************************************/
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1128 1129 1130
int VLC_AddTarget( int i_object, char const *psz_target,
                   char const **ppsz_options, int i_options,
                   int i_mode, int i_pos )
1131
{
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1132 1133
    int i_err;
    playlist_t *p_playlist;
1134 1135 1136 1137 1138 1139 1140
    vlc_t *p_vlc = vlc_current_object( i_object );

    if( !p_vlc )
    {
        return VLC_ENOOBJ;
    }

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1141
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1142

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1143
    if( p_playlist == NULL )
1144
    {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
        msg_Dbg( p_vlc, "no playlist present, creating one" );
        p_playlist = playlist_Create( p_vlc );

        if( p_playlist == NULL )
        {
            if( i_object ) vlc_object_release( p_vlc );
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
1155 1156
    }

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1157 1158
    i_err = playlist_AddExt( p_playlist, psz_target, psz_target,
                             i_mode, i_pos, -1, ppsz_options, i_options);
1159 1160 1161 1162

    vlc_object_release( p_playlist );

    if( i_object ) vlc_object_release( p_vlc );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1163
    return i_err;
1164 1165 1166
}

/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1167
 * VLC_Play: play
1168
 *****************************************************************************/
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1169
int VLC_Play( int i_object )
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
{
    playlist_t * p_playlist;
    vlc_t *p_vlc = vlc_current_object( i_object );

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

    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
        if( i_object ) vlc_object_release( p_vlc );
        return VLC_ENOOBJ;
    }