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.74 2003/04/07 13:01:39 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 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
    vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );
186 187 188 189

    p_vlc->psz_object_name = "root";

    /* Initialize mutexes */
190
    vlc_mutex_init( p_vlc, &p_vlc->config_lock );
191 192

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

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

    return p_vlc->i_object_id;
199 200 201
}

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

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

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

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

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

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

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

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

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

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

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

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
324
    /* Check for translation config option */
325
#ifndef SYS_DARWIN
Gildas Bazin's avatar
 
Gildas Bazin committed
326 327 328 329 330 331 332 333 334
    if( !config_GetInt( p_vlc, "translation" ) )
    {
        /* Reset the default domain */
        SetLanguage( "C" );

#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
        textdomain( "dummy" );
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
335 336 337
        module_EndBank( p_vlc );
        module_InitBank( &libvlc );
        module_LoadMain( &libvlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
338
    }
339
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
340

341 342 343 344 345 346
    /*
     * 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.
     */
347 348
    module_LoadBuiltins( &libvlc );
    module_LoadPlugins( &libvlc );
349
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
350
                    libvlc.p_module_bank->i_children );
351 352

    /* Hack: insert the help module here */
353
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
354 355 356 357 358
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
359
        Usage( p_vlc, p_tmp );
360
        free( p_tmp );
361
        b_exit = VLC_TRUE;
362 363
    }
    /* Check for long help option */
364
    else if( config_GetInt( p_vlc, "longhelp" ) )
365
    {
366
        Usage( p_vlc, NULL );
367
        b_exit = VLC_TRUE;
368 369
    }
    /* Check for module list option */
370
    else if( config_GetInt( p_vlc, "list" ) )
371
    {
372
        ListModules( p_vlc );
373
        b_exit = VLC_TRUE;
374 375 376
    }

    /* Hack: remove the help module here */
377
    vlc_object_detach( p_help_module );
378 379 380 381
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

382 383
    if( b_exit )
    {
384
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
385
        if( i_object ) vlc_object_release( p_vlc );
386 387 388
        return VLC_EEXIT;
    }

389 390 391 392
    /*
     * Override default configuration with config file settings
     */
    p_vlc->psz_homedir = config_GetHomeDir();
393
    config_LoadConfigFile( p_vlc, NULL );
394 395 396 397

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

    /*
     * System specific configuration
     */
415
    system_Configure( p_vlc );
416

417 418 419 420 421
    /*
     * Message queue options
     */
    if( config_GetInt( p_vlc, "quiet" ) )
    {
422
        libvlc.i_verbose = -1;
423 424 425 426
    }
    else
    {
        int i_tmp = config_GetInt( p_vlc, "verbose" );
427
        if( i_tmp >= 0 )
428
        {
429
            libvlc.i_verbose = __MIN( i_tmp, 2 );
430 431 432 433
        }
    }
    libvlc.b_color = libvlc.b_color || config_GetInt( p_vlc, "color" );

434 435 436 437 438
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

439
    /* p_vlc initialization. FIXME ? */
440
    p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
441

442
#if defined( __i386__ )
443
    if( !config_GetInt( p_vlc, "mmx" ) )
444
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
445
    if( !config_GetInt( p_vlc, "3dn" ) )
446
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
447
    if( !config_GetInt( p_vlc, "mmxext" ) )
448
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
449
    if( !config_GetInt( p_vlc, "sse" ) )
450
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
451 452
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
453
    if( !config_GetInt( p_vlc, "altivec" ) )
454
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
455
#endif
456 457

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

482
    if( p_vlc->pf_memcpy == NULL )
483 484 485
    {
        p_vlc->pf_memcpy = memcpy;
    }
486 487 488 489 490

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
491 492 493 494 495

    /*
     * Initialize shared resources and libraries
     */
    if( config_GetInt( p_vlc, "network-channel" )
496
         && network_ChannelCreate( p_vlc ) )
497 498
    {
        /* On error during Channels initialization, switch off channels */
499 500
        msg_Warn( p_vlc,
                  "channels initialization failed, deactivating channels" );
Sam Hocevar's avatar
Sam Hocevar committed
501
        config_PutInt( p_vlc, "network-channel", VLC_FALSE );
502 503 504 505 506
    }

    /*
     * Initialize playlist and get commandline files
     */
507
    p_playlist = playlist_Create( p_vlc );
508 509 510
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
511 512
        if( p_vlc->p_memcpy_module != NULL )
        {
513
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
514
        }
515
        //module_EndBank( p_vlc );
Gildas Bazin's avatar
 
Gildas Bazin committed
516
        if( i_object ) vlc_object_release( p_vlc );
517 518 519
        return VLC_EGENERIC;
    }

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

548 549 550 551 552
    /*
     * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
     */
    var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );

553 554 555 556 557
    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

Gildas Bazin's avatar
 
Gildas Bazin committed
558
    if( i_object ) vlc_object_release( p_vlc );
559 560 561 562
    return VLC_SUCCESS;
}

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

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

578
    if( !p_vlc )
579
    {
580
        return VLC_ENOOBJ;
581 582 583
    }

    /* Try to create the interface */
584
    p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
585 586 587

    if( p_intf == NULL )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
588
        msg_Err( p_vlc, "interface \"%s\" initialization failed", psz_module );
Gildas Bazin's avatar
 
Gildas Bazin committed
589
        if( i_object ) vlc_object_release( p_vlc );
590 591 592 593 594
        return VLC_EGENERIC;
    }

    /* Try to run the interface */
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
595 596
    i_err = intf_RunThread( p_intf );
    if( i_err )
597
    {
598
        vlc_object_detach( p_intf );
599
        intf_Destroy( p_intf );
Gildas Bazin's avatar
 
Gildas Bazin committed
600
        if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
601
        return i_err;
602 603
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
604
    if( i_object ) vlc_object_release( p_vlc );
605 606 607 608
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
609
 * VLC_Destroy: stop playing and destroy everything.
610
 *****************************************************************************
611
 * This function requests the running threads to finish, waits for their
612 613
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
614
int VLC_Destroy( int i_object )
615
{
Sam Hocevar's avatar
Sam Hocevar committed
616 617 618
    vlc_t *p_vlc;

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

620
    if( !p_vlc )
621
    {
622
        return VLC_ENOOBJ;
623 624
    }

625 626 627 628
    /*
     * Go back into channel 0 which is the network
     */
    if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
629
    {
630 631
        network_ChannelJoin( p_vlc, COMMON_CHANNEL );
    }
632

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

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

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

653 654 655 656
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
657

658 659 660
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

661 662
    vlc_object_detach( p_vlc );

663 664 665
    /* Release object before destroying it */
    if( i_object ) vlc_object_release( p_vlc );

666 667
    vlc_object_destroy( p_vlc );

668 669 670
    /* Stop thread system: last one out please shut the door! */
    vlc_threads_end( &libvlc );

671 672 673
    return VLC_SUCCESS;
}

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

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

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

    p_vlc->b_die = VLC_TRUE;

Gildas Bazin's avatar
 
Gildas Bazin committed
693
    if( i_object ) vlc_object_release( p_vlc );
694 695 696 697
    return VLC_SUCCESS;
}

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

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

711
    if( !p_vlc )
712
    {
713
        return VLC_ENOOBJ;
714 715
    }

Sam Hocevar's avatar
Sam Hocevar committed
716 717 718 719 720 721 722 723 724
    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
725
            if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
726 727 728 729 730 731
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
    }

Sam Hocevar's avatar
Sam Hocevar committed
732
    i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
Sam Hocevar's avatar
Sam Hocevar committed
733 734

    vlc_object_release( p_playlist );
735

Gildas Bazin's avatar
 
Gildas Bazin committed
736
    if( i_object ) vlc_object_release( p_vlc );
Sam Hocevar's avatar
Sam Hocevar committed
737
    return i_err;
738 739
}

740
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
741
 * VLC_Set: set a vlc variable
742 743 744
 *****************************************************************************
 *
 *****************************************************************************/
745
int VLC_Set( int i_object, char const *psz_var, vlc_value_t value )
746
{
Sam Hocevar's avatar
Sam Hocevar committed
747
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
748
    int i_ret;
749

Sam Hocevar's avatar
Sam Hocevar committed
750
    p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
751 752 753

    if( !p_vlc )
    {
754
        return VLC_ENOOBJ;
755 756
    }

Sam Hocevar's avatar
Sam Hocevar committed
757 758 759
    /* 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 ) )
760
    {
Sam Hocevar's avatar
Sam Hocevar committed
761
        module_config_t *p_item;
762
        char const *psz_newvar = psz_var + 6;
763

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
788 789 790 791
    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
792 793 794 795 796 797 798
}

/*****************************************************************************
 * VLC_Get: get a vlc variable
 *****************************************************************************
 *
 *****************************************************************************/
799
int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
800 801
{
    vlc_t *p_vlc;
Gildas Bazin's avatar
 
Gildas Bazin committed
802
    int i_ret;
Sam Hocevar's avatar
Sam Hocevar committed
803 804 805 806

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

    if( !p_vlc )
807
    {
808
        return VLC_ENOOBJ;
809 810
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
811 812 813 814
    i_ret = var_Get( p_vlc, psz_var, p_value );

    if( i_object ) vlc_object_release( p_vlc );
    return i_ret;
815 816
}

Sam Hocevar's avatar
Sam Hocevar committed
817
/* FIXME: temporary hacks */
818 819

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
820
 * VLC_Play: play
821
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
822
int VLC_Play( int i_object )
823 824
{
    playlist_t * p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
825 826 827
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
830
    if( !p_vlc )
831
    {
832
        return VLC_ENOOBJ;
833
    }
834

835 836 837 838
    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
839
        if( i_object ) vlc_object_release( p_vlc );
840
        return VLC_ENOOBJ;
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
    }

    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
856
    if( i_object ) vlc_object_release( p_vlc );
857 858 859 860
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
861
 * VLC_Stop: stop
862
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
863
int VLC_Stop( int i_object )
864 865 866 867 868
{
    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
869 870 871
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
874
    if( !p_vlc )
875
    {
876
        return VLC_ENOOBJ;
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
    }

    /*
     * 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 );
911
        vout_Destroy( p_vout );
912 913 914 915 916 917 918 919 920 921 922 923 924
    }

    /*
     * 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
925
    if( i_object ) vlc_object_release( p_vlc );
926 927 928 929
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
930
 * VLC_Pause: toggle pause
931
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
932
int VLC_Pause( int i_object )
933 934
{
    input_thread_t *p_input;
Sam Hocevar's avatar
Sam Hocevar committed
935 936 937 938 939 940
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
941
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
942
    }
943 944 945 946 947

    p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );

    if( !p_input )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
948
        if( i_object ) vlc_object_release( p_vlc );
949
        return VLC_ENOOBJ;
950 951 952 953 954
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
955
    if( i_object ) vlc_object_release( p_vlc );
956 957 958 959
    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
960
 * VLC_FullScreen: toggle fullscreen mode
961
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
962
int VLC_FullScreen( int i_object )
963 964
{
    vout_thread_t *p_vout;
Sam Hocevar's avatar
Sam Hocevar committed
965 966 967 968 969 970
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
971
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
972
    }
973 974 975 976 977

    p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );

    if( !p_vout )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
978
        if( i_object ) vlc_object_release( p_vlc );
979
        return VLC_ENOOBJ;
980 981 982 983 984
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
985
    if( i_object ) vlc_object_release( p_vlc );
986 987 988
    return VLC_SUCCESS;
}

989 990
/* following functions are local */

Sam Hocevar's avatar
Sam Hocevar committed
991 992 993 994 995 996 997 998 999
/*****************************************************************************
 * 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 )
{
1000 1001 1002
#if defined( ENABLE_NLS ) \
     && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )

1003
    char *          psz_path;
Gildas Bazin's avatar
 
Gildas Bazin committed
1004
#if defined( SYS_DARWIN ) || defined ( WIN32 )
1005 1006 1007
    char            psz_tmp[1024];
#endif

1008 1009
#   if defined( HAVE_INCLUDED_GETTEXT ) && !defined( HAVE_LC_MESSAGES )
    if( *psz_lang )
Sam Hocevar's avatar
Sam Hocevar committed
1010
    {
1011 1012 1013 1014 1015 1016 1017 1018
        /* 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
1019
    }
1020
#   endif
Sam Hocevar's avatar
Sam Hocevar committed
1021

Gildas Bazin's avatar
 
Gildas Bazin committed
1022 1023
    if( psz_lang && !*psz_lang )
    {
1024
#   if defined( HAVE_LC_MESSAGES )
Gildas Bazin's avatar
 
Gildas Bazin committed
1025
        setlocale( LC_MESSAGES, psz_lang );
Sam Hocevar's avatar
Sam Hocevar committed
1026
#   endif
Gildas Bazin's avatar
 
Gildas Bazin committed
1027 1028 1029 1030 1031 1032
        setlocale( LC_CTYPE, psz_lang );
    }
    else
    {
        setlocale( LC_ALL, psz_lang );
    }
Sam Hocevar's avatar
Sam Hocevar committed
1033

1034
    /* Specify where to find the locales for current domain */
Gildas Bazin's avatar
 
Gildas Bazin committed
1035
#if !defined( SYS_DARWIN ) && !defined( WIN32 )
1036 1037
    psz_path = LOCALEDIR;
#else
1038
    snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc.psz_vlcpath,
1039 1040 1041 1042
              "locale" );
    psz_path = psz_tmp;
#endif
    if( !bindtextdomain( PACKAGE, psz_path ) )
Sam Hocevar's avatar
Sam Hocevar committed
1043 1044
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
1045
                 PACKAGE, psz_path );
Sam Hocevar's avatar
Sam Hocevar committed
1046 1047
    }

1048
    /* Set the default domain */
Sam Hocevar's avatar
Sam Hocevar committed
1049 1050 1051 1052
    textdomain( PACKAGE );
#endif
}

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

    return VLC_SUCCESS;
}

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

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

    strcpy( psz_format, FORMAT_STRING );

#ifdef WIN32
    ShowConsole();
#endif

1121
    /* List all modules */
1122
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1123

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

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

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

        /* Ignore modules without config options */