libvlc.c 45.3 KB
Newer Older
1 2 3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2002 VideoLAN
5
 * $Id: libvlc.c,v 1.88 2003/05/25 17:27:13 massiot Exp $
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 *
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
 *          Gildas Bazin <gbazin@netcourrier.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

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

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

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

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

#ifdef HAVE_UNISTD_H
#   include <unistd.h>
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 63
#ifdef HAVE_LOCALE_H
#   include <locale.h>
#endif

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

66
#include "error.h"
67 68 69 70

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

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

#include "audio_output.h"

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

#include "libvlc.h"

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

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

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

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

111 112 113 114 115 116 117 118 119 120
/*****************************************************************************
 * VLC_Error: strerror() equivalent
 *****************************************************************************
 * This function returns full version string (numeric version and codename).
 *****************************************************************************/
char const * VLC_Error( int i_err )
{
    return vlc_error( i_err );
}

Sam Hocevar's avatar
Sam Hocevar committed
121 122 123 124 125 126 127
/*****************************************************************************
 * VLC_Create: allocate a vlc_t structure, and initialize libvlc if needed.
 *****************************************************************************
 * This function allocates a vlc_t structure and returns a negative value
 * in case of failure. Also, the thread system is initialized.
 *****************************************************************************/
int VLC_Create( void )
128
{
129
    int i_ret;
130
    vlc_t * p_vlc = NULL;
131
    vlc_value_t lockval;
132

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

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

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
157
#if defined( HAVE_ISATTY ) && !defined( WIN32 )
158 159 160 161 162
        libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
#else
        libvlc.b_color = VLC_FALSE;
#endif

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

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

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

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

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

    p_vlc->psz_object_name = "root";

    /* Initialize mutexes */
189
    vlc_mutex_init( p_vlc, &p_vlc->config_lock );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
190 191 192
#ifdef SYS_DARWIN
    vlc_mutex_init( p_vlc, &p_vlc->quicktime_lock );
#endif
193 194

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

Sam Hocevar's avatar
Sam Hocevar committed
197 198 199 200
    /* Store data for the non-reentrant API */
    p_static_vlc = p_vlc;

    return p_vlc->i_object_id;
201 202 203
}

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

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

227
    if( !p_vlc )
228
    {
229
        return VLC_ENOOBJ;
230 231 232
    }

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

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

252 253 254 255
    /*
     * Support for gettext
     */
    SetLanguage( "" );
Sam Hocevar's avatar
Sam Hocevar committed
256 257

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

260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
    /* Initialize the module bank and load the configuration of the
     * main module. We need to do this at this stage to be able to display
     * a short help if required by the user. (short help == main module
     * options) */
    var_Create( &libvlc, "libvlc", VLC_VAR_MUTEX );
    var_Get( &libvlc, "libvlc", &lockval );
    vlc_mutex_lock( lockval.p_address );
    if( libvlc.p_module_bank == NULL )
    {
        module_InitBank( &libvlc );
        module_LoadMain( &libvlc );
    }
    vlc_mutex_unlock( lockval.p_address );
    var_Destroy( &libvlc, "libvlc" );

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

Sam Hocevar's avatar
Sam Hocevar committed
288
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
289
    {
290
        vlc_object_detach( p_help_module );
291 292
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
293
        /*module_EndBank( p_vlc );*/
Gildas Bazin's avatar
 
Gildas Bazin committed
294
        if( i_object ) vlc_object_release( p_vlc );
295 296 297 298 299 300
        return VLC_EGENERIC;
    }

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

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

    if( b_exit )
    {
320 321
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
322
        /*module_EndBank( p_vlc );*/
Gildas Bazin's avatar
 
Gildas Bazin committed
323
        if( i_object ) vlc_object_release( p_vlc );
324 325 326
        return VLC_EEXIT;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
327
    /* Check for translation config option */
Gildas Bazin's avatar
 
Gildas Bazin committed
328 329 330 331 332 333 334 335 336
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )

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

337 338 339
    /* 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
340 341
    {
        /* Reset the default domain */
342
        SetLanguage( psz_language );
Gildas Bazin's avatar
 
Gildas Bazin committed
343

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

347
        textdomain( PACKAGE );
Gildas Bazin's avatar
 
Gildas Bazin committed
348

349 350 351 352 353 354
#if defined( SYS_BEOS ) || defined ( SYS_DARWIN )
        /* BeOS only support UTF8 strings */
        /* Mac OS X prefers UTF8 */
        bind_textdomain_codeset( PACKAGE, "UTF-8" );
#endif

Gildas Bazin's avatar
 
Gildas Bazin committed
355 356 357
        module_EndBank( p_vlc );
        module_InitBank( &libvlc );
        module_LoadMain( &libvlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
358
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
Gildas Bazin's avatar
 
Gildas Bazin committed
359
    }
360
    if( psz_language ) free( psz_language );
361
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
362

363 364 365 366 367 368
    /*
     * 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.
     */
369 370
    module_LoadBuiltins( &libvlc );
    module_LoadPlugins( &libvlc );
371
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
372
                    libvlc.p_module_bank->i_children );
373 374

    /* Hack: insert the help module here */
375
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
376 377 378 379 380
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
381
        Usage( p_vlc, p_tmp );
382
        free( p_tmp );
383
        b_exit = VLC_TRUE;
384 385
    }
    /* Check for long help option */
386
    else if( config_GetInt( p_vlc, "longhelp" ) )
387
    {
388
        Usage( p_vlc, NULL );
389
        b_exit = VLC_TRUE;
390 391
    }
    /* Check for module list option */
392
    else if( config_GetInt( p_vlc, "list" ) )
393
    {
394
        ListModules( p_vlc );
395
        b_exit = VLC_TRUE;
396 397 398
    }

    /* Hack: remove the help module here */
399
    vlc_object_detach( p_help_module );
400 401 402 403
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

404 405
    if( b_exit )
    {
406
        /*module_EndBank( p_vlc );*/
Gildas Bazin's avatar
 
Gildas Bazin committed
407
        if( i_object ) vlc_object_release( p_vlc );
408 409 410
        return VLC_EEXIT;
    }

411 412 413 414
    /*
     * Override default configuration with config file settings
     */
    p_vlc->psz_homedir = config_GetHomeDir();
415
    config_LoadConfigFile( p_vlc, NULL );
416 417 418 419

    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
420
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
421 422 423 424 425 426 427 428
    {
#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
429
        /*module_EndBank( p_vlc );*/
Gildas Bazin's avatar
 
Gildas Bazin committed
430
        if( i_object ) vlc_object_release( p_vlc );
431 432 433 434 435 436
        return VLC_EGENERIC;
    }

    /*
     * System specific configuration
     */
437
    system_Configure( p_vlc );
438

439 440 441 442 443
    /*
     * Message queue options
     */
    if( config_GetInt( p_vlc, "quiet" ) )
    {
444
        libvlc.i_verbose = -1;
445 446 447 448
    }
    else
    {
        int i_tmp = config_GetInt( p_vlc, "verbose" );
449
        if( i_tmp >= 0 )
450
        {
451
            libvlc.i_verbose = __MIN( i_tmp, 2 );
452 453
        }
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
454
    libvlc.b_color = libvlc.b_color && config_GetInt( p_vlc, "color" );
455

456 457 458 459 460
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

461
    /* p_vlc initialization. FIXME ? */
462
    p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
463

464
#if defined( __i386__ )
465
    if( !config_GetInt( p_vlc, "mmx" ) )
466
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
467
    if( !config_GetInt( p_vlc, "3dn" ) )
468
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
469
    if( !config_GetInt( p_vlc, "mmxext" ) )
470
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
471
    if( !config_GetInt( p_vlc, "sse" ) )
472
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
473 474
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
475
    if( !config_GetInt( p_vlc, "altivec" ) )
476
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
477
#endif
478 479

#define PRINT_CAPABILITY( capability, string )                              \
480
    if( libvlc.i_cpu & capability )                                         \
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
    {                                                                       \
        strncat( p_capabilities, string " ",                                \
                 sizeof(p_capabilities) - strlen(p_capabilities) );         \
        p_capabilities[sizeof(p_capabilities) - 1] = '\0';                  \
    }

    p_capabilities[0] = '\0';
    PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
    PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
    PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
    PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
    PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
    PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
    PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
    PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "AltiVec" );
    PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
    msg_Dbg( p_vlc, "CPU has capabilities %s", p_capabilities );

    /*
     * Choose the best memcpy module
     */
502
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
503

504
    if( p_vlc->pf_memcpy == NULL )
505 506 507
    {
        p_vlc->pf_memcpy = memcpy;
    }
508 509 510 511 512

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
513 514 515 516

    /*
     * Initialize playlist and get commandline files
     */
517
    p_playlist = playlist_Create( p_vlc );
518 519 520
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
521 522
        if( p_vlc->p_memcpy_module != NULL )
        {
523
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
524
        }
525
        /*module_EndBank( p_vlc );*/
Gildas Bazin's avatar
 
Gildas Bazin committed
526
        if( i_object ) vlc_object_release( p_vlc );
527 528 529
        return VLC_EGENERIC;
    }

530 531 532 533 534 535 536
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
537
        char *psz_module, *psz_temp;
538 539 540 541 542 543 544
        psz_module = psz_parser;
        psz_parser = strchr( psz_module, ',' );
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
545 546 547 548 549 550 551
        psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
        if( psz_temp )
        {
            sprintf( psz_temp, "%s,none", psz_module );
            VLC_AddIntf( 0, psz_temp, VLC_FALSE );
            free( psz_temp );
        }
552 553 554 555 556
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
557

558 559 560 561 562
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );

563 564 565 566 567
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

Gildas Bazin's avatar
 
Gildas Bazin committed
568
    if( i_object ) vlc_object_release( p_vlc );
569 570 571 572
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
573
 * VLC_AddIntf: add an interface
574 575
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
576 577
 * 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
578 579
 * user requests to quit.
 *****************************************************************************/
580
int VLC_AddIntf( int i_object, char const *psz_module, vlc_bool_t b_block )
581
{
Sam Hocevar's avatar
Sam Hocevar committed
582
    int i_err;
583
    intf_thread_t *p_intf;
Sam Hocevar's avatar
Sam Hocevar committed
584
    vlc_t *p_vlc;
585

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

588
    if( !p_vlc )
589
    {
590
        return VLC_ENOOBJ;
591 592 593
    }

    /* Try to create the interface */
594
    p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
595 596 597

    if( p_intf == NULL )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
598
        msg_Err( p_vlc, "interface \"%s\" initialization failed", psz_module );
Gildas Bazin's avatar
 
Gildas Bazin committed
599
        if( i_object ) vlc_object_release( p_vlc );
600 601 602 603 604
        return VLC_EGENERIC;
    }

    /* Try to run the interface */
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
605 606
    i_err = intf_RunThread( p_intf );
    if( i_err )
607
    {
608
        vlc_object_detach( p_intf );
609
        intf_Destroy( p_intf );
Gildas Bazin's avatar
 
Gildas Bazin committed
610
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
611
        return i_err;
612 613
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
614
    if( i_object ) vlc_object_release( p_vlc );
615 616 617 618
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
619
 * VLC_Destroy: stop playing and destroy everything.
620
 *****************************************************************************
621
 * This function requests the running threads to finish, waits for their
622 623
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
624
int VLC_Destroy( int i_object )
625
{
Sam Hocevar's avatar
Sam Hocevar committed
626 627 628
    vlc_t *p_vlc;

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

630
    if( !p_vlc )
631
    {
632
        return VLC_ENOOBJ;
633 634
    }

635 636 637 638 639 640 641
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
642 643
    }

644 645 646 647 648
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
649

650 651 652
    /*
     * XXX: Free module bank !
     */
653
    /*module_EndBank( p_vlc );*/
654

655 656 657 658
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
659

660 661
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
662 663 664
#ifdef SYS_DARWIN
    vlc_mutex_destroy( &p_vlc->quicktime_lock );
#endif
665

666 667
    vlc_object_detach( p_vlc );

668 669 670
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

671 672
    vlc_object_destroy( p_vlc );

673 674 675
    /* Stop thread system: last one out please shut the door! */
    vlc_threads_end( &libvlc );

676 677 678
    return VLC_SUCCESS;
}

679
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
680
 * VLC_Die: ask vlc to die.
681 682
 *****************************************************************************
 * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
Sam Hocevar's avatar
Sam Hocevar committed
683
 * task. It is your duty to call vlc_end and VLC_Destroy afterwards.
684
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
685
int VLC_Die( int i_object )
686
{
Sam Hocevar's avatar
Sam Hocevar committed
687 688 689
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
693
        return VLC_ENOOBJ;
694 695 696 697
    }

    p_vlc->b_die = VLC_TRUE;

Gildas Bazin's avatar
 
Gildas Bazin committed
698
    if( i_object ) vlc_object_release( p_vlc );
699 700 701 702
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
703
 * VLC_AddTarget: adds a target for playing.
704 705 706 707
 *****************************************************************************
 * This function adds psz_target to the current playlist. If a playlist does
 * not exist, it will create one.
 *****************************************************************************/
708
int VLC_AddTarget( int i_object, char const *psz_target, int i_mode, int i_pos )
709
{
Sam Hocevar's avatar
Sam Hocevar committed
710
    int i_err;
Sam Hocevar's avatar
Sam Hocevar committed
711
    playlist_t *p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
712 713 714
    vlc_t *p_vlc;

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

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

Sam Hocevar's avatar
Sam Hocevar committed
721 722 723 724 725 726 727 728 729
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );

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

        if( p_playlist == NULL )
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
730
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
731 732 733 734 735 736
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
    }

Sam Hocevar's avatar
Sam Hocevar committed
737
    i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
Sam Hocevar's avatar
Sam Hocevar committed
738 739

    vlc_object_release( p_playlist );
740

Gildas Bazin's avatar
 
Gildas Bazin committed
741
    if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
742
    return i_err;
743 744
}

745
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
746
 * VLC_Set: set a vlc variable
747 748 749
 *****************************************************************************
 *
 *****************************************************************************/
750
int VLC_Set( int i_object, char const *psz_var, vlc_value_t value )
751
{
Sam Hocevar's avatar
Sam Hocevar committed
752
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
753
    int i_ret;
754

Sam Hocevar's avatar
Sam Hocevar committed
755
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
756 757 758

    if( !p_vlc )
    {
759
        return VLC_ENOOBJ;
760 761
    }

Sam Hocevar's avatar
Sam Hocevar committed
762 763 764
    /* 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 ) )
765
    {
Sam Hocevar's avatar
Sam Hocevar committed
766
        module_config_t *p_item;
767
        char const *psz_newvar = psz_var + 6;
768

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

Sam Hocevar's avatar
Sam Hocevar committed
771
        if( p_item )
772
        {
Sam Hocevar's avatar
Sam Hocevar committed
773
            switch( p_item->i_type )
774
            {
Sam Hocevar's avatar
Sam Hocevar committed
775 776 777 778 779 780 781 782 783 784 785 786
                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;
787
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
788
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
789
            return VLC_SUCCESS;
790 791 792
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
793 794 795 796
    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
797 798 799 800 801 802 803
}

/*****************************************************************************
 * VLC_Get: get a vlc variable
 *****************************************************************************
 *
 *****************************************************************************/
804
int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
805 806
{
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
807
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
808 809 810 811

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

    if( !p_vlc )
812
    {
813
        return VLC_ENOOBJ;
814 815
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
816 817 818 819
    i_ret = var_Get( p_vlc, psz_var, p_value );

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
820 821
}

Sam Hocevar's avatar
Sam Hocevar committed
822
/* FIXME: temporary hacks */
823 824

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
825
 * VLC_Play: play
826
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
827
int VLC_Play( int i_object )
828 829
{
    playlist_t * p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
830 831 832
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
835
    if( !p_vlc )
836
    {
837
        return VLC_ENOOBJ;
838
    }
839

840 841 842 843
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
844
        if( i_object ) vlc_object_release( p_vlc );
845
        return VLC_ENOOBJ;
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
    }

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

    vlc_object_release( p_playlist );

Gildas Bazin's avatar
 
Gildas Bazin committed
861
    if( i_object ) vlc_object_release( p_vlc );
862 863 864 865
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
866
 * VLC_Stop: stop
867
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
868
int VLC_Stop( int i_object )
869 870 871 872 873
{
    intf_thread_t *   p_intf;
    playlist_t    *   p_playlist;
    vout_thread_t *   p_vout;
    aout_instance_t * p_aout;
Sam Hocevar's avatar
Sam Hocevar committed
874 875 876
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
879
    if( !p_vlc )
880
    {
881
        return VLC_ENOOBJ;
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
    }

    /*
     * 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 );
916
        vout_Destroy( p_vout );
917 918 919 920 921 922 923 924 925 926 927 928 929
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
930
    if( i_object ) vlc_object_release( p_vlc );
931 932 933 934
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
935
 * VLC_Pause: toggle pause
936
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
937
int VLC_Pause( int i_object )
938 939
{
    input_thread_t *p_input;
Sam Hocevar's avatar
Sam Hocevar committed
940 941 942 943 944 945
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
946
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
947
    }
948 949 950 951 952

    p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );

    if( !p_input )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
953
        if( i_object ) vlc_object_release( p_vlc );
954
        return VLC_ENOOBJ;
955 956 957 958 959
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
960
    if( i_object ) vlc_object_release( p_vlc );
961 962 963 964
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
965
 * VLC_FullScreen: toggle fullscreen mode
966
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
967
int VLC_FullScreen( int i_object )
968 969
{
    vout_thread_t *p_vout;
Sam Hocevar's avatar
Sam Hocevar committed
970 971 972 973 974 975
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
976
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
977
    }
978 979 980 981 982

    p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );

    if( !p_vout )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
983
        if( i_object ) vlc_object_release( p_vlc );
984
        return VLC_ENOOBJ;
985 986 987 988 989
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
990
    if( i_object ) vlc_object_release( p_vlc );
991 992 993
    return VLC_SUCCESS;
}

994 995
/* following functions are local */

Sam Hocevar's avatar
Sam Hocevar committed
996 997 998 999 1000 1001 1002 1003 1004
/*****************************************************************************
 * SetLanguage: set the interface language.
 *****************************************************************************
 * We set the LC_MESSAGES locale category for interface messages and buttons,
 * as well as the LC_CTYPE category for string sorting and possible wide
 * character support.
 *****************************************************************************/
static void SetLanguage ( char const *psz_lang )
{
1005 1006 1007
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )

1008
    char *          psz_path;
Eric Petit's avatar
Eric Petit committed
1009
#if defined( SYS_DARWIN ) || defined ( WIN32 ) || defined( SYS_BEOS )
1010 1011 1012
    char            psz_tmp[1024];
#endif

1013 1014
#   if defined( HAVE_INCLUDED_GETTEXT ) && !defined( HAVE_LC_MESSAGES )
    if( *psz_lang )
Sam Hocevar's avatar
Sam Hocevar committed
1015
    {
1016 1017 1018 1019 1020 1021 1022 1023
        /* We set LC_ALL manually because it is the only way to set
         * the language at runtime under eg. Windows. Beware that this
         * makes the environment unconsistent when libvlc is unloaded and
         * should probably be moved to a safer place like vlc.c. */
        static char psz_lcall[20];
        snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
        psz_lcall[19] = '\0';
        putenv( psz_lcall );
Sam Hocevar's avatar
Sam Hocevar committed
1024
    }
1025
#   endif
Sam Hocevar's avatar
Sam Hocevar committed
1026

Gildas Bazin's avatar
 
Gildas Bazin committed
1027 1028
    if( psz_lang && !*psz_lang )
    {
1029
#   if defined( HAVE_LC_MESSAGES )
Gildas Bazin's avatar
 
Gildas Bazin committed
1030
        setlocale( LC_MESSAGES, psz_lang );
Sam Hocevar's avatar
Sam Hocevar committed
1031
#   endif
Gildas Bazin's avatar
 
Gildas Bazin committed
1032 1033 1034 1035
        setlocale( LC_CTYPE, psz_lang );
    }
    else
    {
1036 1037 1038
#ifdef SYS_BEOS 
        static char psz_lcall[20];
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
1039
        setlocale( LC_ALL, psz_lang );
1040 1041 1042 1043
#ifdef SYS_DARWIN
        /* I need that under Darwin, please check it doesn't disturb
         * other platforms. --Meuuh */
        setenv( "LANG", psz_lang, 1 );
1044 1045 1046 1047 1048 1049
#endif
#ifdef SYS_BEOS
        /* I need this under BeOS... */
        snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
        psz_lcall[19] = '\0';
        putenv( psz_lcall );
1050
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
1051
    }
Sam Hocevar's avatar
Sam Hocevar committed
1052

1053
    /* Specify where to find the locales for current domain */
Eric Petit's avatar
Eric Petit committed
1054
#if !defined( SYS_DARWIN ) && !defined( WIN32 ) && !defined( SYS_BEOS )
1055 1056
    psz_path = LOCALEDIR;
#else
1057
    snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc.psz_vlcpath,
1058 1059 1060 1061
              "locale" );
    psz_path = psz_tmp;
#endif
    if( !bindtextdomain( PACKAGE, psz_path ) )
Sam Hocevar's avatar
Sam Hocevar committed
1062 1063
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
1064
                 PACKAGE, psz_path );
Sam Hocevar's avatar
Sam Hocevar committed
1065 1066
    }

1067
    /* Set the default domain */
Sam Hocevar's avatar
Sam Hocevar committed
1068
    textdomain( PACKAGE );
1069

1070
#if defined( SYS_BEOS ) || defined ( SYS_DARWIN )
1071
    /* BeOS only support UTF8 strings */
1072
    /* Mac OS X prefers UTF8 */
1073 1074 1075
    bind_textdomain_codeset( PACKAGE, "UTF-8" );
#endif

Sam Hocevar's avatar
Sam Hocevar committed
1076 1077 1078
#endif
}

1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
/*****************************************************************************
 * GetFilenames: parse command line options which are not flags
 *****************************************************************************
 * Parse command line for input files.
 *****************************************************************************/
static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
{
    int i_opt;

    /* We assume that the remaining parameters are filenames */
1089
    for( i_opt = i_argc - 1; i_opt > optind; i_opt-- )
1090
    {
Sam Hocevar's avatar
Sam Hocevar committed
1091 1092 1093
        /* TODO: write an internal function of this one, to avoid
         *       unnecessary lookups. */
        VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ i_opt ],
1094 1095 1096 1097 1098 1099 1100 1101
                       PLAYLIST_INSERT, 0 );
    }

    /* If there is at least one target, play it */
    if( i_argc > optind )
    {
        VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ optind ],
                       PLAYLIST_INSERT | PLAYLIST_GO, 0 );
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Usage: print program usage
 *****************************************************************************
 * Print a short inline help. Message interface is initialized at this stage.
 *****************************************************************************/
1112
static void Usage( vlc_t *p_this, char const *psz_module_name )
1113
{
1114 1115 1116 1117 1118 1119 1120 1121 1122
#define FORMAT_STRING "  %s --%s%s%s%s%s%s%s "
    /* short option ------'    |     | | | |  | |
     * option name ------------'     | | | |  | |
     * <bra -------------------------' | | |  | |
     * option type or "" --------------' | |  | |
     * ket> -----------------------------' |  | |
     * padding spaces ---------------------'  | |
     * comment -------------------------------' |
     * comment suffix --------------------------'
1123 1124 1125 1126 1127
     *
     * The purpose of having bra and ket is that we might i18n them as well.
     */
#define LINE_START 8
#define PADDING_SPACES 25
1128
    vlc_list_t *p_list;
Gildas Bazin's avatar
 
Gildas Bazin committed
1129
    module_t *p_parser;
1130 1131 1132
    module_config_t *p_item;
    char psz_spaces[PADDING_SPACES+LINE_START+1];
    char psz_format[sizeof(FORMAT_STRING)];