libvlc.c 43.5 KB
Newer Older
1 2 3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2002 VideoLAN
5
 * $Id: libvlc.c,v 1.66 2003/02/20 01:52:46 sigmunau 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>
51
#elif defined( _MSC_VER ) && 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 71
#include "netutils.h"                                 /* network_ChannelJoin */

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

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

#include "audio_output.h"

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

#include "libvlc.h"

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

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

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

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

112 113 114 115 116 117 118 119 120 121
/*****************************************************************************
 * 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
122 123 124 125 126 127 128
/*****************************************************************************
 * 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 )
129
{
130
    int i_ret;
131
    vlc_t * p_vlc = NULL;
132
    vlc_value_t lockval;
133

134 135 136
    /* 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
137
    if( i_ret < 0 )
138
    {
Sam Hocevar's avatar
Sam Hocevar committed
139
        return i_ret;
140 141 142
    }

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

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

154 155
        /* Find verbosity from VLC_VERBOSE environment variable */
        psz_env = getenv( "VLC_VERBOSE" );
156
        libvlc.i_verbose = psz_env ? atoi( psz_env ) : -1;
157 158 159 160 161 162 163

#ifdef HAVE_ISATTY
        libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
#else
        libvlc.b_color = VLC_FALSE;
#endif

164 165 166 167 168 169 170
        /* 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 );

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

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

    /* Allocate a vlc object */
    p_vlc = vlc_object_create( &libvlc, VLC_OBJECT_VLC );
181 182
    if( p_vlc == NULL )
    {
Sam Hocevar's avatar
Sam Hocevar committed
183
        return VLC_EGENERIC;
184 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 323 324 325 326 327 328
        return VLC_EEXIT;
    }

    /*
     * 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.
     */
329 330
    module_LoadBuiltins( &libvlc );
    module_LoadPlugins( &libvlc );
331
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
332
                    libvlc.p_module_bank->i_children );
333 334

    /* Hack: insert the help module here */
335
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
336 337 338 339 340
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
341
        Usage( p_vlc, p_tmp );
342
        free( p_tmp );
343
        b_exit = VLC_TRUE;
344 345
    }
    /* Check for long help option */
346
    else if( config_GetInt( p_vlc, "longhelp" ) )
347
    {
348
        Usage( p_vlc, NULL );
349
        b_exit = VLC_TRUE;
350 351
    }
    /* Check for module list option */
352
    else if( config_GetInt( p_vlc, "list" ) )
353
    {
354
        ListModules( p_vlc );
355
        b_exit = VLC_TRUE;
356 357 358
    }

    /* Hack: remove the help module here */
359
    vlc_object_detach( p_help_module );
360 361 362 363
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

364 365
    if( b_exit )
    {
366
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
367
        if( i_object ) vlc_object_release( p_vlc );
368 369 370
        return VLC_EEXIT;
    }

371 372 373 374
    /*
     * Override default configuration with config file settings
     */
    p_vlc->psz_homedir = config_GetHomeDir();
375
    config_LoadConfigFile( p_vlc, NULL );
376 377 378 379

    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
380
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
381 382 383 384 385 386 387 388
    {
#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
389
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
390
        if( i_object ) vlc_object_release( p_vlc );
391 392 393 394 395 396
        return VLC_EGENERIC;
    }

    /*
     * System specific configuration
     */
397
    system_Configure( p_vlc );
398

399 400 401 402 403
    /*
     * Message queue options
     */
    if( config_GetInt( p_vlc, "quiet" ) )
    {
404
        libvlc.i_verbose = -1;
405 406 407 408
    }
    else
    {
        int i_tmp = config_GetInt( p_vlc, "verbose" );
409
        if( i_tmp >= 0 )
410
        {
411
            libvlc.i_verbose = __MIN( i_tmp, 2 );
412 413 414 415
        }
    }
    libvlc.b_color = libvlc.b_color || config_GetInt( p_vlc, "color" );

416 417 418 419 420
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

421
    /* p_vlc initialization. FIXME ? */
422
    p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
423

424
#if defined( __i386__ )
425
    if( !config_GetInt( p_vlc, "mmx" ) )
426
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
427
    if( !config_GetInt( p_vlc, "3dn" ) )
428
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
429
    if( !config_GetInt( p_vlc, "mmxext" ) )
430
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
431
    if( !config_GetInt( p_vlc, "sse" ) )
432
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
433 434
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
435
    if( !config_GetInt( p_vlc, "altivec" ) )
436
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
437
#endif
438 439

#define PRINT_CAPABILITY( capability, string )                              \
440
    if( libvlc.i_cpu & capability )                                         \
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
    {                                                                       \
        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
     */
462
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
463

464
    if( p_vlc->pf_memcpy == NULL )
465 466 467
    {
        p_vlc->pf_memcpy = memcpy;
    }
468 469 470 471 472

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
473 474 475 476 477

    /*
     * Initialize shared resources and libraries
     */
    if( config_GetInt( p_vlc, "network-channel" )
478
         && network_ChannelCreate( p_vlc ) )
479 480
    {
        /* On error during Channels initialization, switch off channels */
481 482
        msg_Warn( p_vlc,
                  "channels initialization failed, deactivating channels" );
Sam Hocevar's avatar
Sam Hocevar committed
483
        config_PutInt( p_vlc, "network-channel", VLC_FALSE );
484 485 486 487 488
    }

    /*
     * Initialize playlist and get commandline files
     */
489
    p_playlist = playlist_Create( p_vlc );
490 491 492
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
493 494
        if( p_vlc->p_memcpy_module != NULL )
        {
495
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
496
        }
497
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
498
        if( i_object ) vlc_object_release( p_vlc );
499 500 501
        return VLC_EGENERIC;
    }

502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
    /*
     * Load background interfaces
     */
    psz_modules = config_GetPsz( p_vlc, "extraintf" );
    psz_parser = psz_modules;
    while ( psz_parser && *psz_parser )
    {
        char *psz_module;
        psz_module = psz_parser;
        psz_parser = strchr( psz_module, ',' );
        if ( psz_parser )
        {
            *psz_parser = '\0';
            psz_parser++;
        }
        VLC_AddIntf( 0, psz_module, VLC_FALSE );
    }
    if ( psz_modules )
    {
        free( psz_modules );
    }
523

524 525 526 527 528
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );

529 530 531 532 533
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

Gildas Bazin's avatar
 
Gildas Bazin committed
534
    if( i_object ) vlc_object_release( p_vlc );
535 536 537 538
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
539
 * VLC_AddIntf: add an interface
540 541
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
542 543
 * 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
544 545
 * user requests to quit.
 *****************************************************************************/
546
int VLC_AddIntf( int i_object, char const *psz_module, vlc_bool_t b_block )
547
{
Sam Hocevar's avatar
Sam Hocevar committed
548
    int i_err;
549
    intf_thread_t *p_intf;
Sam Hocevar's avatar
Sam Hocevar committed
550
    vlc_t *p_vlc;
551

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

554
    if( !p_vlc )
555
    {
556
        return VLC_ENOOBJ;
557 558 559
    }

    /* Try to create the interface */
560
    p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
561 562 563 564

    if( p_intf == NULL )
    {
        msg_Err( p_vlc, "interface initialization failed" );
Gildas Bazin's avatar
 
Gildas Bazin committed
565
        if( i_object ) vlc_object_release( p_vlc );
566 567 568 569 570
        return VLC_EGENERIC;
    }

    /* Try to run the interface */
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
571 572
    i_err = intf_RunThread( p_intf );
    if( i_err )
573
    {
574
        vlc_object_detach( p_intf );
575
        intf_Destroy( p_intf );
Gildas Bazin's avatar
 
Gildas Bazin committed
576
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
577
        return i_err;
578 579
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
580
    if( i_object ) vlc_object_release( p_vlc );
581 582 583 584
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
585
 * VLC_Destroy: stop playing and destroy everything.
586
 *****************************************************************************
587
 * This function requests the running threads to finish, waits for their
588 589
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
590
int VLC_Destroy( int i_object )
591
{
Sam Hocevar's avatar
Sam Hocevar committed
592 593 594
    vlc_t *p_vlc;

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

596
    if( !p_vlc )
597
    {
598
        return VLC_ENOOBJ;
599 600
    }

601 602 603 604
    /*
     * Go back into channel 0 which is the network
     */
    if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
605
    {
606 607
        network_ChannelJoin( p_vlc, COMMON_CHANNEL );
    }
608

609 610 611 612 613 614 615
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
616 617
    }

618 619 620 621 622
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
623

624 625 626 627
    /*
     * XXX: Free module bank !
     */
    //module_EndBank( p_vlc );
628

629 630 631 632
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
633

634 635 636
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

637 638
    vlc_object_detach( p_vlc );

639 640 641
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

642 643
    vlc_object_destroy( p_vlc );

644 645 646
    /* Stop thread system: last one out please shut the door! */
    vlc_threads_end( &libvlc );

647 648 649
    return VLC_SUCCESS;
}

650
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
651
 * VLC_Die: ask vlc to die.
652 653
 *****************************************************************************
 * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
Sam Hocevar's avatar
Sam Hocevar committed
654
 * task. It is your duty to call vlc_end and VLC_Destroy afterwards.
655
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
656
int VLC_Die( int i_object )
657
{
Sam Hocevar's avatar
Sam Hocevar committed
658 659 660
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
664
        return VLC_ENOOBJ;
665 666 667 668
    }

    p_vlc->b_die = VLC_TRUE;

Gildas Bazin's avatar
 
Gildas Bazin committed
669
    if( i_object ) vlc_object_release( p_vlc );
670 671 672 673
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
674
 * VLC_AddTarget: adds a target for playing.
675 676 677 678
 *****************************************************************************
 * This function adds psz_target to the current playlist. If a playlist does
 * not exist, it will create one.
 *****************************************************************************/
679
int VLC_AddTarget( int i_object, char const *psz_target, int i_mode, int i_pos )
680
{
Sam Hocevar's avatar
Sam Hocevar committed
681
    int i_err;
Sam Hocevar's avatar
Sam Hocevar committed
682
    playlist_t *p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
683 684 685
    vlc_t *p_vlc;

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

687
    if( !p_vlc )
688
    {
689
        return VLC_ENOOBJ;
690 691
    }

Sam Hocevar's avatar
Sam Hocevar committed
692 693 694 695 696 697 698 699 700
    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
701
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
702 703 704 705 706 707
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
    }

Sam Hocevar's avatar
Sam Hocevar committed
708
    i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
Sam Hocevar's avatar
Sam Hocevar committed
709 710

    vlc_object_release( p_playlist );
711

Gildas Bazin's avatar
 
Gildas Bazin committed
712
    if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
713
    return i_err;
714 715
}

716
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
717
 * VLC_Set: set a vlc variable
718 719 720
 *****************************************************************************
 *
 *****************************************************************************/
721
int VLC_Set( int i_object, char const *psz_var, vlc_value_t value )
722
{
Sam Hocevar's avatar
Sam Hocevar committed
723
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
724
    int i_ret;
725

Sam Hocevar's avatar
Sam Hocevar committed
726
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
727 728 729

    if( !p_vlc )
    {
730
        return VLC_ENOOBJ;
731 732
    }

Sam Hocevar's avatar
Sam Hocevar committed
733 734 735
    /* 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 ) )
736
    {
Sam Hocevar's avatar
Sam Hocevar committed
737
        module_config_t *p_item;
738
        char const *psz_newvar = psz_var + 6;
739

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

Sam Hocevar's avatar
Sam Hocevar committed
742
        if( p_item )
743
        {
Sam Hocevar's avatar
Sam Hocevar committed
744
            switch( p_item->i_type )
745
            {
Sam Hocevar's avatar
Sam Hocevar committed
746 747 748 749 750 751 752 753 754 755 756 757
                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;
758
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
759
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
760
            return VLC_SUCCESS;
761 762 763
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
764 765 766 767
    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
768 769 770 771 772 773 774
}

/*****************************************************************************
 * VLC_Get: get a vlc variable
 *****************************************************************************
 *
 *****************************************************************************/
775
int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
776 777
{
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
778
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
779 780 781 782

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

    if( !p_vlc )
783
    {
784
        return VLC_ENOOBJ;
785 786
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
787 788 789 790
    i_ret = var_Get( p_vlc, psz_var, p_value );

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
791 792
}

Sam Hocevar's avatar
Sam Hocevar committed
793
/* FIXME: temporary hacks */
794 795

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
796
 * VLC_Play: play
797
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
798
int VLC_Play( int i_object )
799 800
{
    playlist_t * p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
801 802 803
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
806
    if( !p_vlc )
807
    {
808
        return VLC_ENOOBJ;
809
    }
810

811 812
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );

813 814 815 816
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
817
        if( i_object ) vlc_object_release( p_vlc );
818
        return VLC_ENOOBJ;
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
    }

    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
834
    if( i_object ) vlc_object_release( p_vlc );
835 836 837 838
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
839
 * VLC_Stop: stop
840
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
841
int VLC_Stop( int i_object )
842 843 844 845 846
{
    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
847 848 849
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
852
    if( !p_vlc )
853
    {
854
        return VLC_ENOOBJ;
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
    }

    /*
     * 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 );
889
        vout_Destroy( p_vout );
890 891 892 893 894 895 896 897 898 899 900 901 902
    }

    /*
     * 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
903
    if( i_object ) vlc_object_release( p_vlc );
904 905 906 907
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
908
 * VLC_Pause: toggle pause
909
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
910
int VLC_Pause( int i_object )
911 912
{
    input_thread_t *p_input;
Sam Hocevar's avatar
Sam Hocevar committed
913 914 915 916 917 918
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
919
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
920
    }
921 922 923 924 925

    p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );

    if( !p_input )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
926
        if( i_object ) vlc_object_release( p_vlc );
927
        return VLC_ENOOBJ;
928 929 930 931 932
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
933
    if( i_object ) vlc_object_release( p_vlc );
934 935 936 937
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
938
 * VLC_FullScreen: toggle fullscreen mode
939
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
940
int VLC_FullScreen( int i_object )
941 942
{
    vout_thread_t *p_vout;
Sam Hocevar's avatar
Sam Hocevar committed
943 944 945 946 947 948
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
949
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
950
    }
951 952 953 954 955

    p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );

    if( !p_vout )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
956
        if( i_object ) vlc_object_release( p_vlc );
957
        return VLC_ENOOBJ;
958 959 960 961 962
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
963
    if( i_object ) vlc_object_release( p_vlc );
964 965 966
    return VLC_SUCCESS;
}

967 968
/* following functions are local */

Sam Hocevar's avatar
Sam Hocevar committed
969 970 971 972 973 974 975 976 977
/*****************************************************************************
 * 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 )
{
978 979 980
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )

981 982 983 984 985
    char *          psz_path;
#ifdef SYS_DARWIN
    char            psz_tmp[1024];
#endif

986 987
#   if defined( HAVE_INCLUDED_GETTEXT ) && !defined( HAVE_LC_MESSAGES )
    if( *psz_lang )
Sam Hocevar's avatar
Sam Hocevar committed
988
    {
989 990 991 992 993 994 995 996
        /* 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
997
    }
998
#   endif
Sam Hocevar's avatar
Sam Hocevar committed
999

1000 1001
#   if defined( HAVE_LC_MESSAGES )
    setlocale( LC_MESSAGES, psz_lang );
Sam Hocevar's avatar
Sam Hocevar committed
1002
#   endif
1003
    setlocale( LC_CTYPE, psz_lang );
Sam Hocevar's avatar
Sam Hocevar committed
1004

1005
    /* Specify where to find the locales for current domain */
1006 1007 1008
#ifndef SYS_DARWIN
    psz_path = LOCALEDIR;
#else
1009
    snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc.psz_vlcpath,
1010 1011 1012 1013
              "locale" );
    psz_path = psz_tmp;
#endif
    if( !bindtextdomain( PACKAGE, psz_path ) )
Sam Hocevar's avatar
Sam Hocevar committed
1014 1015
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
1016
                 PACKAGE, psz_path );
Sam Hocevar's avatar
Sam Hocevar committed
1017 1018
    }