libvlc.c 44.3 KB
Newer Older
1 2 3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2002 VideoLAN
Gildas Bazin's avatar
 
Gildas Bazin committed
5
 * $Id: libvlc.c,v 1.82 2003/05/05 16:09:35 gbazin 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 );
190 191

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

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

    return p_vlc->i_object_id;
198 199 200
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
201
 * VLC_Init: initialize a vlc_t structure.
202 203 204 205 206 207 208
 *****************************************************************************
 * This function initializes a previously allocated vlc_t structure:
 *  - CPU detection
 *  - gettext initialization
 *  - message queue, module bank and playlist initialization
 *  - configuration and commandline parsing
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
209
int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
210
{
211 212
    char         p_capabilities[200];
    char *       p_tmp;
213 214
    char *       psz_modules;
    char *       psz_parser;
215
    vlc_bool_t   b_exit = VLC_FALSE;
Sam Hocevar's avatar
Sam Hocevar committed
216
    vlc_t *      p_vlc;
217 218
    module_t    *p_help_module;
    playlist_t  *p_playlist;
219
    vlc_value_t  lockval;
220

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

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

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

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

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

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

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

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

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

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

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
323
    /* Check for translation config option */
Gildas Bazin's avatar
 
Gildas Bazin committed
324 325 326 327 328 329 330 331 332
#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 );

Gildas Bazin's avatar
 
Gildas Bazin committed
333 334 335 336 337 338
    if( !config_GetInt( p_vlc, "translation" ) )
    {
        /* Reset the default domain */
        SetLanguage( "C" );

        textdomain( "dummy" );
Gildas Bazin's avatar
 
Gildas Bazin committed
339

Gildas Bazin's avatar
 
Gildas Bazin committed
340 341 342
        module_EndBank( p_vlc );
        module_InitBank( &libvlc );
        module_LoadMain( &libvlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
343
        config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
Gildas Bazin's avatar
 
Gildas Bazin committed
344
    }
345
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
346

347 348 349 350 351 352
    /*
     * 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.
     */
353 354
    module_LoadBuiltins( &libvlc );
    module_LoadPlugins( &libvlc );
355
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
356
                    libvlc.p_module_bank->i_children );
357 358

    /* Hack: insert the help module here */
359
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
360 361 362 363 364
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
365
        Usage( p_vlc, p_tmp );
366
        free( p_tmp );
367
        b_exit = VLC_TRUE;
368 369
    }
    /* Check for long help option */
370
    else if( config_GetInt( p_vlc, "longhelp" ) )
371
    {
372
        Usage( p_vlc, NULL );
373
        b_exit = VLC_TRUE;
374 375
    }
    /* Check for module list option */
376
    else if( config_GetInt( p_vlc, "list" ) )
377
    {
378
        ListModules( p_vlc );
379
        b_exit = VLC_TRUE;
380 381 382
    }

    /* Hack: remove the help module here */
383
    vlc_object_detach( p_help_module );
384 385 386 387
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

388 389
    if( b_exit )
    {
390
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
391
        if( i_object ) vlc_object_release( p_vlc );
392 393 394
        return VLC_EEXIT;
    }

395 396 397 398
    /*
     * Override default configuration with config file settings
     */
    p_vlc->psz_homedir = config_GetHomeDir();
399
    config_LoadConfigFile( p_vlc, NULL );
400 401 402 403

    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
404
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
405 406 407 408 409 410 411 412
    {
#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
413
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
414
        if( i_object ) vlc_object_release( p_vlc );
415 416 417 418 419 420
        return VLC_EGENERIC;
    }

    /*
     * System specific configuration
     */
421
    system_Configure( p_vlc );
422

423 424 425 426 427
    /*
     * Message queue options
     */
    if( config_GetInt( p_vlc, "quiet" ) )
    {
428
        libvlc.i_verbose = -1;
429 430 431 432
    }
    else
    {
        int i_tmp = config_GetInt( p_vlc, "verbose" );
433
        if( i_tmp >= 0 )
434
        {
435
            libvlc.i_verbose = __MIN( i_tmp, 2 );
436 437
        }
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
438
    libvlc.b_color = libvlc.b_color && config_GetInt( p_vlc, "color" );
439

440 441 442 443 444
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

445
    /* p_vlc initialization. FIXME ? */
446
    p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
447

448
#if defined( __i386__ )
449
    if( !config_GetInt( p_vlc, "mmx" ) )
450
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
451
    if( !config_GetInt( p_vlc, "3dn" ) )
452
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
453
    if( !config_GetInt( p_vlc, "mmxext" ) )
454
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
455
    if( !config_GetInt( p_vlc, "sse" ) )
456
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
457 458
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
459
    if( !config_GetInt( p_vlc, "altivec" ) )
460
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
461
#endif
462 463

#define PRINT_CAPABILITY( capability, string )                              \
464
    if( libvlc.i_cpu & capability )                                         \
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
    {                                                                       \
        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
     */
486
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
487

488
    if( p_vlc->pf_memcpy == NULL )
489 490 491
    {
        p_vlc->pf_memcpy = memcpy;
    }
492 493 494 495 496

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
497 498 499 500

    /*
     * Initialize playlist and get commandline files
     */
501
    p_playlist = playlist_Create( p_vlc );
502 503 504
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
505 506
        if( p_vlc->p_memcpy_module != NULL )
        {
507
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
508
        }
509
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
510
        if( i_object ) vlc_object_release( p_vlc );
511 512 513
        return VLC_EGENERIC;
    }

514 515 516 517 518 519 520
    /*
     * 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
521
        char *psz_module, *psz_temp;
522 523 524 525 526 527 528
        psz_module = psz_parser;
        psz_parser = strchr( psz_module, ',' );
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
529 530 531 532 533 534 535
        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 );
        }
536 537 538 539 540
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
541

542 543 544 545 546
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );

547 548 549 550 551
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

Gildas Bazin's avatar
 
Gildas Bazin committed
552
    if( i_object ) vlc_object_release( p_vlc );
553 554 555 556
    return VLC_SUCCESS;
}

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

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

572
    if( !p_vlc )
573
    {
574
        return VLC_ENOOBJ;
575 576 577
    }

    /* Try to create the interface */
578
    p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
579 580 581

    if( p_intf == NULL )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
582
        msg_Err( p_vlc, "interface \"%s\" initialization failed", psz_module );
Gildas Bazin's avatar
 
Gildas Bazin committed
583
        if( i_object ) vlc_object_release( p_vlc );
584 585 586 587 588
        return VLC_EGENERIC;
    }

    /* Try to run the interface */
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
589 590
    i_err = intf_RunThread( p_intf );
    if( i_err )
591
    {
592
        vlc_object_detach( p_intf );
593
        intf_Destroy( p_intf );
Gildas Bazin's avatar
 
Gildas Bazin committed
594
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
595
        return i_err;
596 597
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
598
    if( i_object ) vlc_object_release( p_vlc );
599 600 601 602
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
603
 * VLC_Destroy: stop playing and destroy everything.
604
 *****************************************************************************
605
 * This function requests the running threads to finish, waits for their
606 607
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
608
int VLC_Destroy( int i_object )
609
{
Sam Hocevar's avatar
Sam Hocevar committed
610 611 612
    vlc_t *p_vlc;

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

614
    if( !p_vlc )
615
    {
616
        return VLC_ENOOBJ;
617 618
    }

619 620 621 622 623 624 625
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
626 627
    }

628 629 630 631 632
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
633

634 635 636 637
    /*
     * XXX: Free module bank !
     */
    //module_EndBank( p_vlc );
638

639 640 641 642
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
643

644 645 646
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

647 648
    vlc_object_detach( p_vlc );

649 650 651
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

652 653
    vlc_object_destroy( p_vlc );

654 655 656
    /* Stop thread system: last one out please shut the door! */
    vlc_threads_end( &libvlc );

657 658 659
    return VLC_SUCCESS;
}

660
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
661
 * VLC_Die: ask vlc to die.
662 663
 *****************************************************************************
 * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
Sam Hocevar's avatar
Sam Hocevar committed
664
 * task. It is your duty to call vlc_end and VLC_Destroy afterwards.
665
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
666
int VLC_Die( int i_object )
667
{
Sam Hocevar's avatar
Sam Hocevar committed
668 669 670
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
674
        return VLC_ENOOBJ;
675 676 677 678
    }

    p_vlc->b_die = VLC_TRUE;

Gildas Bazin's avatar
 
Gildas Bazin committed
679
    if( i_object ) vlc_object_release( p_vlc );
680 681 682 683
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
684
 * VLC_AddTarget: adds a target for playing.
685 686 687 688
 *****************************************************************************
 * This function adds psz_target to the current playlist. If a playlist does
 * not exist, it will create one.
 *****************************************************************************/
689
int VLC_AddTarget( int i_object, char const *psz_target, int i_mode, int i_pos )
690
{
Sam Hocevar's avatar
Sam Hocevar committed
691
    int i_err;
Sam Hocevar's avatar
Sam Hocevar committed
692
    playlist_t *p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
693 694 695
    vlc_t *p_vlc;

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

697
    if( !p_vlc )
698
    {
699
        return VLC_ENOOBJ;
700 701
    }

Sam Hocevar's avatar
Sam Hocevar committed
702 703 704 705 706 707 708 709 710
    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
711
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
712 713 714 715 716 717
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
    }

Sam Hocevar's avatar
Sam Hocevar committed
718
    i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
Sam Hocevar's avatar
Sam Hocevar committed
719 720

    vlc_object_release( p_playlist );
721

Gildas Bazin's avatar
 
Gildas Bazin committed
722
    if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
723
    return i_err;
724 725
}

726
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
727
 * VLC_Set: set a vlc variable
728 729 730
 *****************************************************************************
 *
 *****************************************************************************/
731
int VLC_Set( int i_object, char const *psz_var, vlc_value_t value )
732
{
Sam Hocevar's avatar
Sam Hocevar committed
733
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
734
    int i_ret;
735

Sam Hocevar's avatar
Sam Hocevar committed
736
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
737 738 739

    if( !p_vlc )
    {
740
        return VLC_ENOOBJ;
741 742
    }

Sam Hocevar's avatar
Sam Hocevar committed
743 744 745
    /* 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 ) )
746
    {
Sam Hocevar's avatar
Sam Hocevar committed
747
        module_config_t *p_item;
748
        char const *psz_newvar = psz_var + 6;
749

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

Sam Hocevar's avatar
Sam Hocevar committed
752
        if( p_item )
753
        {
Sam Hocevar's avatar
Sam Hocevar committed
754
            switch( p_item->i_type )
755
            {
Sam Hocevar's avatar
Sam Hocevar committed
756 757 758 759 760 761 762 763 764 765 766 767
                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;
768
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
769
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
770
            return VLC_SUCCESS;
771 772 773
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
774 775 776 777
    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
778 779 780 781 782 783 784
}

/*****************************************************************************
 * VLC_Get: get a vlc variable
 *****************************************************************************
 *
 *****************************************************************************/
785
int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
786 787
{
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
788
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
789 790 791 792

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

    if( !p_vlc )
793
    {
794
        return VLC_ENOOBJ;
795 796
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
797 798 799 800
    i_ret = var_Get( p_vlc, psz_var, p_value );

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
801 802
}

Sam Hocevar's avatar
Sam Hocevar committed
803
/* FIXME: temporary hacks */
804 805

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
806
 * VLC_Play: play
807
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
808
int VLC_Play( int i_object )
809 810
{
    playlist_t * p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
811 812 813
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
816
    if( !p_vlc )
817
    {
818
        return VLC_ENOOBJ;
819
    }
820

821 822 823 824
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
825
        if( i_object ) vlc_object_release( p_vlc );
826
        return VLC_ENOOBJ;
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
    }

    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
842
    if( i_object ) vlc_object_release( p_vlc );
843 844 845 846
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
847
 * VLC_Stop: stop
848
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
849
int VLC_Stop( int i_object )
850 851 852 853 854
{
    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
855 856 857
    vlc_t *p_vlc;

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

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

    /*
     * 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 );
897
        vout_Destroy( p_vout );
898 899 900 901 902 903 904 905 906 907 908 909 910
    }

    /*
     * 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
911
    if( i_object ) vlc_object_release( p_vlc );
912 913 914 915
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
916
 * VLC_Pause: toggle pause
917
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
918
int VLC_Pause( int i_object )
919 920
{
    input_thread_t *p_input;
Sam Hocevar's avatar
Sam Hocevar committed
921 922 923 924 925 926
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
927
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
928
    }
929 930 931 932 933

    p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );

    if( !p_input )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
934
        if( i_object ) vlc_object_release( p_vlc );
935
        return VLC_ENOOBJ;
936 937 938 939 940
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
941
    if( i_object ) vlc_object_release( p_vlc );
942 943 944 945
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
946
 * VLC_FullScreen: toggle fullscreen mode
947
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
948
int VLC_FullScreen( int i_object )
949 950
{
    vout_thread_t *p_vout;
Sam Hocevar's avatar
Sam Hocevar committed
951 952 953 954 955 956
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
957
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
958
    }
959 960 961 962 963

    p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );

    if( !p_vout )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
964
        if( i_object ) vlc_object_release( p_vlc );
965
        return VLC_ENOOBJ;
966 967 968 969 970
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
971
    if( i_object ) vlc_object_release( p_vlc );
972 973 974
    return VLC_SUCCESS;
}

975 976
/* following functions are local */

Sam Hocevar's avatar
Sam Hocevar committed
977 978 979 980 981 982 983 984 985
/*****************************************************************************
 * 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 )
{
986 987 988
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )

989
    char *          psz_path;
Eric Petit's avatar
Eric Petit committed
990
#if defined( SYS_DARWIN ) || defined ( WIN32 ) || defined( SYS_BEOS )
991 992 993
    char            psz_tmp[1024];
#endif

994 995
#   if defined( HAVE_INCLUDED_GETTEXT ) && !defined( HAVE_LC_MESSAGES )
    if( *psz_lang )
Sam Hocevar's avatar
Sam Hocevar committed
996
    {
997 998 999 1000 1001 1002 1003 1004
        /* 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
1005
    }
1006
#   endif
Sam Hocevar's avatar
Sam Hocevar committed
1007

Gildas Bazin's avatar
 
Gildas Bazin committed
1008 1009
    if( psz_lang && !*psz_lang )
    {
1010
#   if defined( HAVE_LC_MESSAGES )
Gildas Bazin's avatar
 
Gildas Bazin committed
1011
        setlocale( LC_MESSAGES, psz_lang );
Sam Hocevar's avatar
Sam Hocevar committed
1012
#   endif
Gildas Bazin's avatar
 
Gildas Bazin committed
1013 1014 1015 1016 1017
        setlocale( LC_CTYPE, psz_lang );
    }
    else
    {
        setlocale( LC_ALL, psz_lang );
1018 1019 1020 1021 1022
#ifdef SYS_DARWIN
        /* I need that under Darwin, please check it doesn't disturb
         * other platforms. --Meuuh */
        setenv( "LANG", psz_lang, 1 );
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
1023
    }
Sam Hocevar's avatar
Sam Hocevar committed
1024

1025
    /* Specify where to find the locales for current domain */
Eric Petit's avatar
Eric Petit committed
1026
#if !defined( SYS_DARWIN ) && !defined( WIN32 ) && !defined( SYS_BEOS )
1027 1028
    psz_path = LOCALEDIR;
#else
1029
    snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc.psz_vlcpath,
1030 1031 1032 1033
              "locale" );
    psz_path = psz_tmp;
#endif
    if( !bindtextdomain( PACKAGE, psz_path ) )
Sam Hocevar's avatar
Sam Hocevar committed
1034 1035
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
1036
                 PACKAGE, psz_path );
Sam Hocevar's avatar
Sam Hocevar committed
1037 1038
    }

1039
    /* Set the default domain */
Sam Hocevar's avatar
Sam Hocevar committed
1040
    textdomain( PACKAGE );
1041 1042 1043 1044 1045 1046

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

Sam Hocevar's avatar
Sam Hocevar committed
1047 1048 1049
#endif
}

1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
/*****************************************************************************
 * 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 */
1060
    for( i_opt = i_argc - 1; i_opt > optind; i_opt-- )
1061
    {
Sam Hocevar's avatar
Sam Hocevar committed
1062 1063 1064
        /* TODO: write an internal function of this one, to avoid
         *       unnecessary lookups. */
        VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ i_opt ],
1065 1066 1067 1068 1069 1070 1071 1072
                       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 );
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Usage: print program usage
 *****************************************************************************
 * Print a short inline help. Message interface is initialized at this stage.
 *****************************************************************************/
1083
static void Usage( vlc_t *p_this, char const *psz_module_name )
1084
{
1085 1086 1087 1088 1089 1090 1091 1092 1093
#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 --------------------------'
1094 1095 1096 1097 1098
     *
     * The purpose of having bra and ket is that we might i18n them as well.
     */
#define LINE_START 8
#define PADDING_SPACES 25
1099
    vlc_list_t *p_list;
Gildas Bazin's avatar
 
Gildas Bazin committed
1100
    module_t *p_parser;
1101 1102 1103
    module_config_t *p_item;
    char psz_spaces[PADDING_SPACES+LINE_START+1];
    char psz_format[sizeof(FORMAT_STRING)];
1104 1105
    char psz_buffer[1000];
    char psz_short[4];
Gildas Bazin's avatar
 
Gildas Bazin committed
1106
    int i_index;
1107
    int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117

    memset( psz_spaces, ' ', PADDING_SPACES+LINE_START );
    psz_spaces[PADDING_SPACES+LINE_START] = '\0';

    strcpy( psz_format, FORMAT_STRING );

#ifdef WIN32
    ShowConsole();
#endif

1118
    /* List all modules */
1119
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1120

1121
    /* Enumerate the config for each module */
1122
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
1123
    {
1124
        vlc_bool_t b_help_module;
1125

1126
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
Gildas Bazin's avatar
 
Gildas Bazin committed
1127

1128
        if( psz_module_name && strcmp( psz_module_name,
Gildas Bazin's avatar
 
Gildas Bazin committed
1129
                                       p_parser->psz_object_name ) )
Sam Hocevar's avatar
Sam Hocevar committed
1130
        {
1131
            continue;
Sam Hocevar's avatar
Sam Hocevar committed
1132
        }
1133 1134