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

#ifdef HAVE_ERRNO_H
#   include <errno.h>                                              /* ENOMEM */
#endif
43 44 45 46 47 48 49 50 51 52
#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>
53
#elif defined( WIN32 ) && !defined( UNDER_CE )
54 55 56
#   include <io.h>
#endif

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

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

65 66 67 68
#ifdef HAVE_HAL
#   include <hal/libhal.h>
#endif

69
#include "vlc_cpu.h"                                        /* CPU detection */
70
#include "os_specific.h"
71

72
#include "vlc_error.h"
73

74
#include "vlc_playlist.h"
75
#include "vlc_interface.h"
76 77 78

#include "audio_output.h"

79
#include "vlc_video.h"
80 81
#include "video_output.h"

82 83
#include "stream_output.h"

84 85 86
#include "libvlc.h"

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

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

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

Derk-Jan Hartman's avatar
Derk-Jan 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

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
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );
216 217 218 219

    p_vlc->psz_object_name = "root";

    /* Initialize mutexes */
220
    vlc_mutex_init( p_vlc, &p_vlc->config_lock );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
221 222 223
#ifdef SYS_DARWIN
    vlc_mutex_init( p_vlc, &p_vlc->quicktime_lock );
#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;
249
    char *       psz_language;
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

255
    if( !p_vlc )
256
    {
257
        return VLC_ENOOBJ;
258 259 260
    }

    /*
261
     * System specific initialization code
262
     */
263
    system_Init( p_vlc, &i_argc, ppsz_argv );
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279

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

280 281 282 283
    /*
     * Support for gettext
     */
    SetLanguage( "" );
Sam Hocevar's avatar
Sam Hocevar committed
284 285

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

288 289 290 291
    /* 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) */
292
    module_InitBank( p_vlc );
293

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

Sam Hocevar's avatar
Sam Hocevar committed
308
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
309
    {
310
        vlc_object_detach( p_help_module );
311 312
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
313
        module_EndBank( p_vlc );
314
        if( i_object ) vlc_object_release( p_vlc );
315 316 317 318 319 320
        return VLC_EGENERIC;
    }

    /* Check for short help option */
    if( config_GetInt( p_vlc, "help" ) )
    {
321
        fprintf( stdout, _("Usage: %s [options] [items]...\n"),
322
                         p_vlc->psz_object_name );
323
        Usage( p_vlc, "main" );
324 325
        Usage( p_vlc, "help" );
        b_exit = VLC_TRUE;
326 327
    }
    /* Check for version option */
328
    else if( config_GetInt( p_vlc, "version" ) )
329 330
    {
        Version();
331 332 333
        b_exit = VLC_TRUE;
    }

334 335 336 337
    /* Set the config file stuff */
    p_vlc->psz_homedir = config_GetHomeDir();
    p_vlc->psz_configfile = config_GetPsz( p_vlc, "config" );

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

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

Gildas Bazin's avatar
Gildas Bazin committed
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
    /* 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" ) )
    {
        pid_t i_pid = 0;

        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" );
            close( 0 );
            close( 1 );
            close( 2 );

            p_vlc->p_libvlc->b_daemon = VLC_TRUE;
        }
    }
#endif

381 382
    if( b_exit )
    {
383 384
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
385
        module_EndBank( p_vlc );
386
        if( i_object ) vlc_object_release( p_vlc );
387 388 389
        return VLC_EEXIT;
    }

390
    /* Check for translation config option */
391 392 393 394 395 396 397 398
#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 );

399 400 401
    /* Check if the user specified a custom language */
    psz_language = config_GetPsz( p_vlc, "language" );
    if( psz_language && *psz_language && strcmp( psz_language, "auto" ) )
402
    {
403 404
        vlc_bool_t b_cache_delete = libvlc.p_module_bank->b_cache_delete;

405
        /* Reset the default domain */
406
        SetLanguage( psz_language );
407

408 409 410
        /* 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
411
        textdomain( PACKAGE_NAME );
412

413
#if defined( ENABLE_UTF8 )
Sam Hocevar's avatar
Sam Hocevar committed
414
        bind_textdomain_codeset( PACKAGE_NAME, "UTF-8" );
415 416
#endif

417
        module_EndBank( p_vlc );
418
        module_InitBank( p_vlc );
419
        config_LoadConfigFile( p_vlc, "main" );
420
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
421
        libvlc.p_module_bank->b_cache_delete = b_cache_delete;
422
    }
423
    if( psz_language ) free( psz_language );
424
#endif
425

426 427 428 429 430 431
    /*
     * 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.
     */
432 433 434 435 436 437 438
    module_LoadBuiltins( p_vlc );
    module_LoadPlugins( p_vlc );
    if( p_vlc->b_die )
    {
        b_exit = VLC_TRUE;
    }

439
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
440
                    libvlc.p_module_bank->i_children );
441 442

    /* Hack: insert the help module here */
443
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
444 445 446 447 448
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
449
        Usage( p_vlc, p_tmp );
450
        free( p_tmp );
451
        b_exit = VLC_TRUE;
452 453
    }
    /* Check for long help option */
454
    else if( config_GetInt( p_vlc, "longhelp" ) )
455
    {
456
        Usage( p_vlc, NULL );
457
        b_exit = VLC_TRUE;
458 459
    }
    /* Check for module list option */
460
    else if( config_GetInt( p_vlc, "list" ) )
461
    {
462
        ListModules( p_vlc );
463
        b_exit = VLC_TRUE;
464 465
    }

466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
    /* 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 );
    }

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

488 489
    if( b_exit )
    {
490 491
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
492
        module_EndBank( p_vlc );
493
        if( i_object ) vlc_object_release( p_vlc );
494 495 496
        return VLC_EEXIT;
    }

497 498 499 500 501
    /*
     * Init device values
     */
    InitDeviceValues( p_vlc );

502 503 504
    /*
     * Override default configuration with config file settings
     */
505
    config_LoadConfigFile( p_vlc, NULL );
506

507 508 509 510
    /* Hack: insert the help module here */
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
    /* End hack */

511 512 513
    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
514
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
515 516 517 518 519 520 521 522
    {
#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
523 524 525
        vlc_object_detach( p_help_module );
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
526
        module_EndBank( p_vlc );
527
        if( i_object ) vlc_object_release( p_vlc );
528 529 530
        return VLC_EGENERIC;
    }

531 532 533 534 535 536
    /* 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 */

537 538 539
    /*
     * System specific configuration
     */
540
    system_Configure( p_vlc, &i_argc, ppsz_argv );
541

542 543 544
    /*
     * Message queue options
     */
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
545 546

    var_Create( p_vlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
547 548
    if( config_GetInt( p_vlc, "quiet" ) )
    {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
549 550 551
        vlc_value_t val;
        val.i_int = -1;
        var_Set( p_vlc, "verbose", val );
552
    }
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
553 554
    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
555

556
    libvlc.b_color = libvlc.b_color && config_GetInt( p_vlc, "color" );
557

558 559 560 561 562
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

563
    /* p_vlc initialization. FIXME ? */
564

565
#if defined( __i386__ )
566
    if( !config_GetInt( p_vlc, "mmx" ) )
567
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
568
    if( !config_GetInt( p_vlc, "3dn" ) )
569
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
570
    if( !config_GetInt( p_vlc, "mmxext" ) )
571
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
572
    if( !config_GetInt( p_vlc, "sse" ) )
573
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
574 575
    if( !config_GetInt( p_vlc, "sse2" ) )
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE2;
576 577
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
578
    if( !config_GetInt( p_vlc, "altivec" ) )
579
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
580
#endif
581 582

#define PRINT_CAPABILITY( capability, string )                              \
583
    if( libvlc.i_cpu & capability )                                         \
584 585 586 587 588 589 590 591 592 593 594 595 596 597
    {                                                                       \
        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" );
598
    PRINT_CAPABILITY( CPU_CAPABILITY_SSE2, "SSE2" );
599 600 601 602 603 604 605
    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
     */
606
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy", 0 );
607

608
    if( p_vlc->pf_memcpy == NULL )
609 610 611
    {
        p_vlc->pf_memcpy = memcpy;
    }
612 613 614 615 616

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

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
618 619 620 621
    /*
     * Initialize hotkey handling
     */
    var_Create( p_vlc, "key-pressed", VLC_VAR_INTEGER );
622 623
    p_vlc->p_hotkeys = malloc( sizeof(p_hotkeys) );
    /* Do a copy (we don't need to modify the strings) */
624
    memcpy( p_vlc->p_hotkeys, p_hotkeys, sizeof(p_hotkeys) );
625

626 627 628
    /*
     * Initialize playlist and get commandline files
     */
629
    p_playlist = playlist_Create( p_vlc );
630 631 632
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
633 634
        if( p_vlc->p_memcpy_module != NULL )
        {
635
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
636
        }
637
        module_EndBank( p_vlc );
638
        if( i_object ) vlc_object_release( p_vlc );
639 640 641
        return VLC_EGENERIC;
    }

642 643 644 645 646 647 648
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
649
        char *psz_module, *psz_temp;
650 651 652 653 654 655 656
        psz_module = psz_parser;
        psz_parser = strchr( psz_module, ',' );
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
657 658 659 660
        psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
        if( psz_temp )
        {
            sprintf( psz_temp, "%s,none", psz_module );
661
            VLC_AddIntf( 0, psz_temp, VLC_FALSE, VLC_FALSE );
662 663
            free( psz_temp );
        }
664 665 666 667 668
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
669

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
670 671 672
    /*
     * Allways load the hotkeys interface if it exists
     */
673
    VLC_AddIntf( 0, "hotkeys,none", VLC_FALSE, VLC_FALSE );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
674

675 676 677 678
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );
679 680 681 682 683 684 685 686 687 688 689
    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 );
690

691 692 693 694 695
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

696
    if( i_object ) vlc_object_release( p_vlc );
697 698 699 700
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
701
 * VLC_AddIntf: add an interface
702 703
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
704 705
 * 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
706 707
 * user requests to quit. If b_play is set to 1, VLC_AddIntf will start playing
 * the playlist when it is completely initialised.
708
 *****************************************************************************/
709 710
int VLC_AddIntf( int i_object, char const *psz_module,
                 vlc_bool_t b_block, vlc_bool_t b_play )
711
{
Sam Hocevar's avatar
Sam Hocevar committed
712
    int i_err;
713
    intf_thread_t *p_intf;
714
    vlc_t *p_vlc = vlc_current_object( i_object );
Sam Hocevar's avatar
Sam Hocevar committed
715

716
    if( !p_vlc )
717
    {
718
        return VLC_ENOOBJ;
719 720
    }

Gildas Bazin's avatar
Gildas Bazin committed
721 722 723 724 725 726 727 728 729 730 731
#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

732
    /* Try to create the interface */
733
    p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
734 735 736

    if( p_intf == NULL )
    {
737
        msg_Err( p_vlc, "interface \"%s\" initialization failed", psz_module );
738
        if( i_object ) vlc_object_release( p_vlc );
739 740 741
        return VLC_EGENERIC;
    }

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

745
    /* Try to run the interface */
746
    p_intf->b_play = b_play;
747
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
748 749
    i_err = intf_RunThread( p_intf );
    if( i_err )
750
    {
751
        vlc_object_detach( p_intf );
752
        intf_Destroy( p_intf );
753
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
754
        return i_err;
755 756
    }

757
    if( i_object ) vlc_object_release( p_vlc );
758 759 760 761
    return VLC_SUCCESS;
}

/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 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
 * 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.
864
 *****************************************************************************
865
 * This function requests the running threads to finish, waits for their
866 867
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
868
int VLC_Destroy( int i_object )
869
{
870
    vlc_t *p_vlc = vlc_current_object( i_object );
871

872
    if( !p_vlc )
873
    {
874
        return VLC_ENOOBJ;
875 876
    }

877 878 879 880 881 882 883
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
884 885
    }

886
    /*
887
     * Free module bank !
888 889 890
     */
    module_EndBank( p_vlc );

891 892 893 894 895
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
896

897 898 899 900 901 902
    if( p_vlc->psz_configfile )
    {
        free( p_vlc->psz_configfile );
        p_vlc->psz_configfile = NULL;
    }

903 904 905 906 907 908
    if( p_vlc->p_hotkeys )
    {
        free( p_vlc->p_hotkeys );
        p_vlc->p_hotkeys = NULL;
    }

909 910 911 912
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
913

914 915 916
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

917 918
    vlc_object_detach( p_vlc );

919 920 921
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

922 923
    vlc_object_destroy( p_vlc );

924
    /* Stop thread system: last one out please shut the door! */
925
    vlc_threads_end( p_libvlc );
926

927 928 929
    return VLC_SUCCESS;
}

930
/*****************************************************************************
931
 * VLC_VariableSet: set a vlc variable
932
 *****************************************************************************/
933
int VLC_VariableSet( int i_object, char const *psz_var, vlc_value_t value )
934
{
935
    vlc_t *p_vlc = vlc_current_object( i_object );
936
    int i_ret;
937 938 939

    if( !p_vlc )
    {
940
        return VLC_ENOOBJ;
941 942
    }

Sam Hocevar's avatar
Sam Hocevar committed
943 944 945
    /* 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 ) )
946
    {
Sam Hocevar's avatar
Sam Hocevar committed
947
        module_config_t *p_item;
948
        char const *psz_newvar = psz_var + 6;
949

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

Sam Hocevar's avatar
Sam Hocevar committed
952
        if( p_item )
953
        {
Sam Hocevar's avatar
Sam Hocevar committed
954
            switch( p_item->i_type )
955
            {
Sam Hocevar's avatar
Sam Hocevar committed
956 957 958 959 960 961 962 963 964 965 966 967
                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;
968
            }
969
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
970
            return VLC_SUCCESS;
971 972 973
        }
    }

974 975 976 977
    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
978 979 980
}

/*****************************************************************************
981
 * VLC_VariableGet: get a vlc variable
Sam Hocevar's avatar
Sam Hocevar committed
982
 *****************************************************************************/
983
int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
984
{
985
    vlc_t *p_vlc = vlc_current_object( i_object );
986
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
987 988

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

993 994 995 996
    i_ret = var_Get( p_vlc, psz_var, p_value );

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
997 998
}

999
/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1000 1001 1002 1003
 * 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.
1004
 *****************************************************************************/
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1005 1006 1007
int VLC_AddTarget( int i_object, char const *psz_target,
                   char const **ppsz_options, int i_options,
                   int i_mode, int i_pos )
1008
{
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1009 1010
    int i_err;
    playlist_t *p_playlist;
1011 1012 1013 1014 1015 1016 1017
    vlc_t *p_vlc = vlc_current_object( i_object );

    if( !p_vlc )
    {
        return VLC_ENOOBJ;
    }

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

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1020
    if( p_playlist == NULL )
1021
    {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
        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 );
1032 1033
    }

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1034 1035
    i_err = playlist_AddExt( p_playlist, psz_target, psz_target,
                             i_mode, i_pos, -1, ppsz_options, i_options);
1036 1037 1038 1039

    vlc_object_release( p_playlist );

    if( i_object ) vlc_object_release( p_vlc );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1040
    return i_err;
1041 1042 1043
}

/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1044
 * VLC_Play: play
1045
 *****************************************************************************/
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1046
int VLC_Play( int i_object )
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
{
    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;
    }

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1065
    playlist_Play( p_playlist );
1066 1067 1068
    vlc_object_release( p_playlist );

    if( i_object ) vlc_object_release( p_vlc );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1069
    return VLC_SUCCESS;
1070 1071
}

1072
/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1073
 * VLC_Pause: toggle pause
1074
 *****************************************************************************/
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1075
int VLC_Pause( int i_object )
1076 1077
{
    playlist_t * p_playlist;
1078
    vlc_t *p_vlc = vlc_current_object( i_object );
1079 1080

    /* Check that the handle is valid */
1081
    if( !p_vlc )
1082
    {
1083
        return VLC_ENOOBJ;
1084
    }
1085

1086 1087 1088 1089
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
1090
        if( i_object ) vlc_object_release( p_vlc );
1091
        return VLC_ENOOBJ;
1092 1093
    }

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1094
    playlist_Pause( p_playlist );
1095 1096
    vlc_object_release( p_playlist );

1097
    if( i_object ) vlc_object_release( p_vlc );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1098
    return VLC_SUCCESS;
1099 1100 1101
}

/*****************************************************************************
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1102
 * VLC_Pause: toggle pause
1103
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
1104
int VLC_Stop( int i_object )
1105
{
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1106
    playlist_t * p_playlist;
1107
    vlc_t *p_vlc = vlc_current_object( i_object );
1108 1109

    /* Check that the handle is valid */
1110
    if( !p_vlc )
1111
    {
1112
        return VLC_ENOOBJ;
1113 1114
    }

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1115
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );
1116

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1117
    if( !p_playlist )
1118
    {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1119 1120
        if( i_object ) vlc_object_release( p_vlc );
        return VLC_ENOOBJ;
1121 1122
    }

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1123
    playlist_Stop( p_playlist );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1124
    vlc_object_release( p_playlist );
Clément Stenac's avatar
Clément Stenac committed
1125

Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
1126
    if( i_object ) vlc_object_release( p_vlc );