libvlc.c 37.1 KB
Newer Older
1 2 3
/*****************************************************************************
 * libvlc.c: main libvlc source
 *****************************************************************************
4
 * Copyright (C) 1998-2002 VideoLAN
5
 * $Id: libvlc.c,v 1.40 2002/10/15 08:35:24 sam 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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#define __BUILTIN__

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <errno.h>                                                 /* ENOMEM */
#include <stdio.h>                                              /* sprintf() */
#include <string.h>                                            /* strerror() */
#include <stdlib.h>                                                /* free() */

#include <vlc/vlc.h>

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

#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#elif defined( _MSC_VER ) && defined( _WIN32 )
#   include <io.h>
#endif

53
#ifdef WIN32                       /* optind, getopt(), included in unistd.h */
54
#   include "extras/GNUgetopt/getopt.h"
55 56
#endif

57 58 59 60 61
#ifdef HAVE_LOCALE_H
#   include <locale.h>
#endif

#include "vlc_cpu.h"                                        /* CPU detection */
62
#include "os_specific.h"
63

64
#include "error.h"
65 66 67 68 69
#include "netutils.h"                                 /* network_ChannelJoin */

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

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

#include "audio_output.h"

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

#include "libvlc.h"

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

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

#ifdef WIN32
static void ShowConsole   ( void );
#endif

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

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

130 131 132
    /* 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
133
    if( i_ret < 0 )
134
    {
Sam Hocevar's avatar
Sam Hocevar committed
135
        return i_ret;
136 137 138
    }

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

147 148 149
        /* Guess what CPU we have */
        libvlc.i_cpu = CPUCapabilities();

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

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

160 161 162 163 164 165 166
        /* 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 );

167
        /* Initialize the module bank and load the configuration of the
168 169 170 171 172
         * 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) */
        module_InitBank( &libvlc );
        module_LoadMain( &libvlc );
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 213
    char         p_capabilities[200];
    char *       p_tmp;
    vlc_bool_t   b_exit;
Sam Hocevar's avatar
Sam Hocevar committed
214
    vlc_t *      p_vlc;
215 216
    module_t    *p_help_module;
    playlist_t  *p_playlist;
217

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

220
    if( !p_vlc )
221
    {
222
        return VLC_ENOOBJ;
223 224
    }

225
    /* Support for gettext */
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
#if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
#   if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
    if( !setlocale( LC_MESSAGES, "" ) )
    {
        fprintf( stderr, "warning: unsupported locale settings\n" );
    }

    setlocale( LC_CTYPE, "" );
#   endif

    if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
    {
        fprintf( stderr, "warning: no domain %s in directory %s\n",
                 PACKAGE, LOCALEDIR );
    }

    textdomain( PACKAGE );
#endif

    /*
246
     * System specific initialization code
247
     */
248
    system_Init( p_vlc, &i_argc, ppsz_argv );
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268

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

    /* Hack: insert the help module here */
    p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
    if( p_help_module == NULL )
    {
269
        //module_EndBank( p_vlc );
270 271 272 273
        return VLC_EGENERIC;
    }
    p_help_module->psz_object_name = "help";
    config_Duplicate( p_help_module, p_help_config );
274
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
275 276
    /* End hack */

Sam Hocevar's avatar
Sam Hocevar committed
277
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
278
    {
279
        vlc_object_detach( p_help_module );
280 281
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
282
        //module_EndBank( p_vlc );
283 284 285
        return VLC_EGENERIC;
    }

286 287
    b_exit = VLC_FALSE;

288 289 290
    /* Check for short help option */
    if( config_GetInt( p_vlc, "help" ) )
    {
291
        fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
292
                         p_vlc->psz_object_name );
293
        Usage( p_vlc, "main" );
294 295
        Usage( p_vlc, "help" );
        b_exit = VLC_TRUE;
296 297
    }
    /* Check for version option */
298
    else if( config_GetInt( p_vlc, "version" ) )
299 300
    {
        Version();
301 302 303 304 305 306 307 308 309
        b_exit = VLC_TRUE;
    }

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

    if( b_exit )
    {
310 311
        config_Free( p_help_module );
        vlc_object_destroy( p_help_module );
312
        //module_EndBank( p_vlc );
313 314 315 316 317 318 319 320 321
        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.
     */
322 323
    module_LoadBuiltins( &libvlc );
    module_LoadPlugins( &libvlc );
324
    msg_Dbg( p_vlc, "module bank initialized, found %i modules",
325
                    libvlc.p_module_bank->i_children );
326 327

    /* Hack: insert the help module here */
328
    vlc_object_attach( p_help_module, libvlc.p_module_bank );
329 330 331 332 333
    /* End hack */

    /* Check for help on modules */
    if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
    {
334
        Usage( p_vlc, p_tmp );
335
        free( p_tmp );
336
        b_exit = VLC_TRUE;
337 338
    }
    /* Check for long help option */
339
    else if( config_GetInt( p_vlc, "longhelp" ) )
340
    {
341
        Usage( p_vlc, NULL );
342
        b_exit = VLC_TRUE;
343 344
    }
    /* Check for module list option */
345
    else if( config_GetInt( p_vlc, "list" ) )
346
    {
347
        ListModules( p_vlc );
348
        b_exit = VLC_TRUE;
349 350 351
    }

    /* Hack: remove the help module here */
352
    vlc_object_detach( p_help_module );
353 354 355 356
    config_Free( p_help_module );
    vlc_object_destroy( p_help_module );
    /* End hack */

357 358
    if( b_exit )
    {
359
        //module_EndBank( p_vlc );
360 361 362
        return VLC_EEXIT;
    }

363 364 365 366
    /*
     * Override default configuration with config file settings
     */
    p_vlc->psz_homedir = config_GetHomeDir();
367
    config_LoadConfigFile( p_vlc, NULL );
368 369 370 371

    /*
     * Override configuration with command line settings
     */
Sam Hocevar's avatar
Sam Hocevar committed
372
    if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
373 374 375 376 377 378 379 380
    {
#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
381
        //module_EndBank( p_vlc );
382 383 384 385 386 387
        return VLC_EGENERIC;
    }

    /*
     * System specific configuration
     */
388
    system_Configure( p_vlc );
389

390 391 392 393 394
    /*
     * Message queue options
     */
    if( config_GetInt( p_vlc, "quiet" ) )
    {
395
        libvlc.i_verbose = -1;
396 397 398 399
    }
    else
    {
        int i_tmp = config_GetInt( p_vlc, "verbose" );
400
        if( i_tmp >= 0 )
401
        {
402
            libvlc.i_verbose = __MIN( i_tmp, 2 );
403 404 405 406
        }
    }
    libvlc.b_color = libvlc.b_color || config_GetInt( p_vlc, "color" );

407 408 409 410 411 412 413
    /*
     * Output messages that may still be in the queue
     */
    msg_Flush( p_vlc );

    /* p_vlc inititalization. FIXME ? */
    p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
414

415
#if defined( __i386__ )
416
    if( !config_GetInt( p_vlc, "mmx" ) )
417
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
418
    if( !config_GetInt( p_vlc, "3dn" ) )
419
        libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
420
    if( !config_GetInt( p_vlc, "mmxext" ) )
421
        libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
422
    if( !config_GetInt( p_vlc, "sse" ) )
423
        libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
424 425
#endif
#if defined( __powerpc__ ) || defined( SYS_DARWIN )
426
    if( !config_GetInt( p_vlc, "altivec" ) )
427
        libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
428
#endif
429 430

#define PRINT_CAPABILITY( capability, string )                              \
431
    if( libvlc.i_cpu & capability )                                         \
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
    {                                                                       \
        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
     */
453
    p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
454

455
    if( p_vlc->pf_memcpy == NULL )
456 457 458
    {
        p_vlc->pf_memcpy = memcpy;
    }
459 460 461 462 463

    if( p_vlc->pf_memset == NULL )
    {
        p_vlc->pf_memset = memset;
    }
464 465 466 467 468

    /*
     * Initialize shared resources and libraries
     */
    if( config_GetInt( p_vlc, "network-channel" )
469
         && network_ChannelCreate( p_vlc ) )
470 471
    {
        /* On error during Channels initialization, switch off channels */
472 473
        msg_Warn( p_vlc,
                  "channels initialization failed, deactivating channels" );
Sam Hocevar's avatar
Sam Hocevar committed
474
        config_PutInt( p_vlc, "network-channel", VLC_FALSE );
475 476 477 478 479
    }

    /*
     * Initialize playlist and get commandline files
     */
480
    p_playlist = playlist_Create( p_vlc );
481 482 483
    if( !p_playlist )
    {
        msg_Err( p_vlc, "playlist initialization failed" );
484 485
        if( p_vlc->p_memcpy_module != NULL )
        {
486
            module_Unneed( p_vlc, p_vlc->p_memcpy_module );
487
        }
488
        //module_EndBank( p_vlc );
489 490 491 492 493 494 495 496 497 498 499 500
        return VLC_EGENERIC;
    }

    /*
     * Get input filenames given as commandline arguments
     */
    GetFilenames( p_vlc, i_argc, ppsz_argv );

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
501
 * VLC_AddIntf: add an interface
502 503
 *****************************************************************************
 * This function opens an interface plugin and runs it. If b_block is set
Sam Hocevar's avatar
Sam Hocevar committed
504 505
 * 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
506 507
 * user requests to quit.
 *****************************************************************************/
508
int VLC_AddIntf( int i_object, char const *psz_module, vlc_bool_t b_block )
509
{
Sam Hocevar's avatar
Sam Hocevar committed
510
    int i_err;
511
    intf_thread_t *p_intf;
Sam Hocevar's avatar
Sam Hocevar committed
512
    vlc_t *p_vlc;
513 514
    char *psz_oldmodule = NULL;

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

517
    if( !p_vlc )
518
    {
519
        return VLC_ENOOBJ;
520 521 522 523 524 525 526 527 528
    }

    if( psz_module )
    {
        psz_oldmodule = config_GetPsz( p_vlc, "intf" );
        config_PutPsz( p_vlc, "intf", psz_module );
    }

    /* Try to create the interface */
529
    p_intf = intf_Create( p_vlc );
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547

    if( psz_module )
    {
        config_PutPsz( p_vlc, "intf", psz_oldmodule );
        if( psz_oldmodule )
        {
            free( psz_oldmodule );
        }
    }

    if( p_intf == NULL )
    {
        msg_Err( p_vlc, "interface initialization failed" );
        return VLC_EGENERIC;
    }

    /* Try to run the interface */
    p_intf->b_block = b_block;
Sam Hocevar's avatar
Sam Hocevar committed
548 549
    i_err = intf_RunThread( p_intf );
    if( i_err )
550
    {
551
        vlc_object_detach( p_intf );
552
        intf_Destroy( p_intf );
Sam Hocevar's avatar
Sam Hocevar committed
553
        return i_err;
554 555 556 557 558 559
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
560
 * VLC_Destroy: stop playing and destroy everything.
561
 *****************************************************************************
562
 * This function requests the running threads to finish, waits for their
563 564
 * termination, and destroys their structure.
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
565
int VLC_Destroy( int i_object )
566
{
Sam Hocevar's avatar
Sam Hocevar committed
567 568 569
    vlc_t *p_vlc;

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

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

576 577 578 579
    /*
     * Go back into channel 0 which is the network
     */
    if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
580
    {
581 582
        network_ChannelJoin( p_vlc, COMMON_CHANNEL );
    }
583
    
584 585 586 587 588 589 590
    /*
     * Free allocated memory
     */
    if( p_vlc->p_memcpy_module )
    {
        module_Unneed( p_vlc, p_vlc->p_memcpy_module );
        p_vlc->p_memcpy_module = NULL;
591 592
    }

593 594 595 596 597
    if( p_vlc->psz_homedir )
    {
        free( p_vlc->psz_homedir );
        p_vlc->psz_homedir = NULL;
    }
598

599 600 601 602 603 604 605 606 607 608
    /*
     * XXX: Free module bank !
     */
    //module_EndBank( p_vlc );
    
    /*
     * System specific cleaning code
     */
    system_End( p_vlc );
    
609 610 611
    /* Destroy mutexes */
    vlc_mutex_destroy( &p_vlc->config_lock );

612 613
    vlc_object_detach( p_vlc );

614 615
    vlc_object_destroy( p_vlc );

616 617 618
    /* Stop thread system: last one out please shut the door! */
    vlc_threads_end( &libvlc );

619 620 621
    return VLC_SUCCESS;
}

622
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
623
 * VLC_Die: ask vlc to die.
624 625
 *****************************************************************************
 * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
Sam Hocevar's avatar
Sam Hocevar committed
626
 * task. It is your duty to call vlc_end and VLC_Destroy afterwards.
627
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
628
int VLC_Die( int i_object )
629
{
Sam Hocevar's avatar
Sam Hocevar committed
630 631 632
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
636
        return VLC_ENOOBJ;
637 638 639 640 641 642 643 644
    }

    p_vlc->b_die = VLC_TRUE;

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
645
 * VLC_AddTarget: adds a target for playing.
646 647 648 649
 *****************************************************************************
 * This function adds psz_target to the current playlist. If a playlist does
 * not exist, it will create one.
 *****************************************************************************/
650
int VLC_AddTarget( int i_object, char const *psz_target, int i_mode, int i_pos )
651
{
Sam Hocevar's avatar
Sam Hocevar committed
652
    int i_err;
Sam Hocevar's avatar
Sam Hocevar committed
653
    playlist_t *p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
654 655 656
    vlc_t *p_vlc;

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

658
    if( !p_vlc )
659
    {
660
        return VLC_ENOOBJ;
661 662
    }

Sam Hocevar's avatar
Sam Hocevar committed
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
    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 )
        {
            return VLC_EGENERIC;
        }

        vlc_object_yield( p_playlist );
    }

Sam Hocevar's avatar
Sam Hocevar committed
678
    i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
Sam Hocevar's avatar
Sam Hocevar committed
679 680

    vlc_object_release( p_playlist );
681

Sam Hocevar's avatar
Sam Hocevar committed
682
    return i_err;
683 684
}

685
/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
686
 * VLC_Set: set a vlc variable
687 688 689
 *****************************************************************************
 *
 *****************************************************************************/
690
int VLC_Set( int i_object, char const *psz_var, vlc_value_t value )
691
{
Sam Hocevar's avatar
Sam Hocevar committed
692
    vlc_t *p_vlc;
693

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

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

Sam Hocevar's avatar
Sam Hocevar committed
701 702 703
    /* 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 ) )
704
    {
Sam Hocevar's avatar
Sam Hocevar committed
705
        module_config_t *p_item;
706
        char const *psz_newvar = psz_var + 6;
707

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

Sam Hocevar's avatar
Sam Hocevar committed
710
        if( p_item )
711
        {
Sam Hocevar's avatar
Sam Hocevar committed
712
            switch( p_item->i_type )
713
            {
Sam Hocevar's avatar
Sam Hocevar committed
714 715 716 717 718 719 720 721 722 723 724 725
                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;
726
            }
Sam Hocevar's avatar
Sam Hocevar committed
727
            return VLC_SUCCESS;
728 729 730
        }
    }

Sam Hocevar's avatar
Sam Hocevar committed
731 732 733 734 735 736 737 738
    return var_Set( p_vlc, psz_var, value );
}

/*****************************************************************************
 * VLC_Get: get a vlc variable
 *****************************************************************************
 *
 *****************************************************************************/
739
int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
Sam Hocevar's avatar
Sam Hocevar committed
740 741 742 743 744 745
{
    vlc_t *p_vlc;

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

    if( !p_vlc )
746
    {
747
        return VLC_ENOOBJ;
748 749
    }

Sam Hocevar's avatar
Sam Hocevar committed
750
    return var_Get( p_vlc, psz_var, p_value );
751 752
}

Sam Hocevar's avatar
Sam Hocevar committed
753
/* FIXME: temporary hacks */
754 755

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
756
 * VLC_Play: play
757
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
758
int VLC_Play( int i_object )
759 760
{
    playlist_t * p_playlist;
Sam Hocevar's avatar
Sam Hocevar committed
761 762 763
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
766
    if( !p_vlc )
767
    {
768
        return VLC_ENOOBJ;
769 770 771 772 773 774
    }

    p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );

    if( !p_playlist )
    {
775
        return VLC_ENOOBJ;
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
    }

    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 );

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
795
 * VLC_Stop: stop
796
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
797
int VLC_Stop( int i_object )
798 799 800 801 802
{
    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
803 804 805
    vlc_t *p_vlc;

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

    /* Check that the handle is valid */
808
    if( !p_vlc )
809
    {
810
        return VLC_ENOOBJ;
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862
    }

    /*
     * Ask the interfaces to stop and destroy them
     */
    msg_Dbg( p_vlc, "removing all interfaces" );
    while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_CHILD )) )
    {
        intf_StopThread( p_intf );
        vlc_object_detach( p_intf );
        vlc_object_release( p_intf );
        intf_Destroy( p_intf );
    }

    /*
     * Free playlists
     */
    msg_Dbg( p_vlc, "removing all playlists" );
    while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
                                          FIND_CHILD )) )
    {
        vlc_object_detach( p_playlist );
        vlc_object_release( p_playlist );
        playlist_Destroy( p_playlist );
    }

    /*
     * Free video outputs
     */
    msg_Dbg( p_vlc, "removing all video outputs" );
    while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
    {
        vlc_object_detach( p_vout );
        vlc_object_release( p_vout );
        vout_DestroyThread( p_vout );
    }

    /*
     * Free audio outputs
     */
    msg_Dbg( p_vlc, "removing all audio outputs" );
    while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
    {
        vlc_object_detach( (vlc_object_t *)p_aout );
        vlc_object_release( (vlc_object_t *)p_aout );
        aout_Delete( p_aout );
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
863
 * VLC_Pause: toggle pause
864
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
865
int VLC_Pause( int i_object )
866 867
{
    input_thread_t *p_input;
Sam Hocevar's avatar
Sam Hocevar committed
868 869 870 871 872 873
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
874
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
875
    }
876 877 878 879 880

    p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );

    if( !p_input )
    {
881
        return VLC_ENOOBJ;
882 883 884 885 886 887 888 889 890
    }

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

    return VLC_SUCCESS;
}

/*****************************************************************************
Sam Hocevar's avatar
Sam Hocevar committed
891
 * VLC_FullScreen: toggle fullscreen mode
892
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
893
int VLC_FullScreen( int i_object )
894 895
{
    vout_thread_t *p_vout;
Sam Hocevar's avatar
Sam Hocevar committed
896 897 898 899 900 901
    vlc_t *p_vlc;

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

    if( !p_vlc )
    {
902
        return VLC_ENOOBJ;
Sam Hocevar's avatar
Sam Hocevar committed
903
    }
904 905 906 907 908

    p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );

    if( !p_vout )
    {
909
        return VLC_ENOOBJ;
910 911 912 913 914 915 916 917
    }

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

    return VLC_SUCCESS;
}

918 919 920 921 922 923 924 925 926 927 928 929 930 931
/* following functions are local */

/*****************************************************************************
 * 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 */
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
Sam Hocevar's avatar
Sam Hocevar committed
932 933 934
        /* TODO: write an internal function of this one, to avoid
         *       unnecessary lookups. */
        VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ i_opt ],
935
                          PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
936 937 938 939 940 941 942 943 944 945
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Usage: print program usage
 *****************************************************************************
 * Print a short inline help. Message interface is initialized at this stage.
 *****************************************************************************/
946
static void Usage( vlc_t *p_this, char const *psz_module_name )
947
{
Sam Hocevar's avatar
Sam Hocevar committed
948 949 950 951 952 953 954 955
#define FORMAT_STRING "      --%s%s%s%s%s%s%s %s%s\n"
    /* option name -------------'     | | | |  | |
     * <bra --------------------------' | | |  | |
     * option type or "" ---------------' | |  | |
     * ket> ------------------------------' |  | |
     * padding spaces ----------------------'  | |
     * comment --------------------------------' |
     * comment suffix ---------------------------'
956 957 958 959 960
     *
     * The purpose of having bra and ket is that we might i18n them as well.
     */
#define LINE_START 8
#define PADDING_SPACES 25
961 962
    vlc_list_t *p_list;
    module_t **pp_parser;
963 964 965 966 967 968 969 970 971 972 973 974 975
    module_config_t *p_item;
    char psz_spaces[PADDING_SPACES+LINE_START+1];
    char psz_format[sizeof(FORMAT_STRING)];

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

    strcpy( psz_format, FORMAT_STRING );

#ifdef WIN32
    ShowConsole();
#endif

976 977 978
    /* List all modules */
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );

979
    /* Enumerate the config for each module */
980 981 982
    for( pp_parser = (module_t **)p_list->pp_objects ;
         *pp_parser ;
         pp_parser++ )
983
    {
984
        vlc_bool_t b_help_module;
985 986

        if( psz_module_name && strcmp( psz_module_name,
987
                                       (*pp_parser)->psz_object_name ) )
Sam Hocevar's avatar
Sam Hocevar committed
988
        {
989
            continue;
Sam Hocevar's avatar
Sam Hocevar committed
990
        }
991 992

        /* Ignore modules without config options */
993
        if( !(*pp_parser)->i_config_items )
Sam Hocevar's avatar
Sam Hocevar committed
994 995 996
        {
            continue;
        }
997

998
        b_help_module = !strcmp( "help", (*pp_parser)->psz_object_name );
999

1000
        /* Print module options */
1001
        for( p_item = (*pp_parser)->p_config;
Gildas Bazin's avatar
 
Gildas Bazin committed
1002
             p_item->i_type != CONFIG_HINT_END;
1003 1004 1005
             p_item++ )
        {
            char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
Sam Hocevar's avatar
Sam Hocevar committed
1006
            char *psz_suf = "", *psz_prefix = NULL;
1007 1008 1009 1010
            int i;

            switch( p_item->i_type )
            {
Gildas Bazin's avatar
 
Gildas Bazin committed
1011 1012
            case CONFIG_HINT_CATEGORY:
            case CONFIG_HINT_USAGE:
1013 1014 1015
                fprintf( stderr, " %s\n", p_item->psz_text );
                break;

Gildas Bazin's avatar
 
Gildas Bazin committed
1016 1017 1018
            case CONFIG_ITEM_STRING:
            case CONFIG_ITEM_FILE:
            case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
                if( !p_item->ppsz_list )
                {
                    psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
                    break;
                }
                else
                {
                    psz_bra = " [";
                    psz_type = malloc( 1000 );
                    memset( psz_type, 0, 1000 );
                    for( i=0; p_item->ppsz_list[i]; i++ )
                    {
                        strcat( psz_type, p_item->ppsz_list[i] );
                        strcat( psz_type, "|" );
                    }
                    psz_type[ strlen( psz_type ) - 1 ] = '\0';
                    psz_ket = "]";
                    break;
                }
Gildas Bazin's avatar
 
Gildas Bazin committed
1038
            case CONFIG_ITEM_INTEGER:
1039 1040
                psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
1041
            case CONFIG_ITEM_FLOAT:
1042 1043
                psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
1044
            case CONFIG_ITEM_BOOL:
1045 1046 1047 1048 1049 1050 1051 1052 1053
                psz_bra = ""; psz_type = ""; psz_ket = "";
                if( !b_help_module )
                {
                    psz_suf = p_item->i_value ? _(" (default enabled)") :
                                                _(" (default disabled)");
                }
                break;
            }

1054
            /* Add short option if any */
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
            if( p_item->i_short )
            {
                psz_format[2] = '-';
                psz_format[3] = p_item->i_short;
                psz_format[4] = ',';
            }
            else
            {
                psz_format[2] = ' ';
                psz_format[3] = ' ';
                psz_format[4] = ' ';
            }

            if( psz_type )
            {
                i = PADDING_SPACES - strlen( p_item->psz_name )
                     - strlen( psz_bra ) - strlen( psz_type )
                     - strlen( psz_ket ) - 1;
Gildas Bazin's avatar
 
Gildas Bazin committed
1073
                if( p_item->i_type == CONFIG_ITEM_BOOL
1074 1075
                     && !b_help_module )
                {
1076 1077 1078 1079
                    /* If option is of type --foo-bar, we print its counterpart
                     * as --no-foo-bar, but if it is of type --foobar (without
                     * dashes in the name) we print it as --nofoobar. Both
                     * values are of course valid, only the display changes. */
Sam Hocevar's avatar
Sam Hocevar committed
1080
                    vlc_bool_t b_dash = VLC_FALSE;
Sam Hocevar's avatar
Sam Hocevar committed
1081 1082 1083 1084 1085
                    psz_prefix = p_item->psz_name;
                    while( *psz_prefix )
                    {
                        if( *psz_prefix++ == '-' )
                        {
Sam Hocevar's avatar
Sam Hocevar committed
1086
                            b_dash = VLC_TRUE;
Sam Hocevar's avatar
Sam Hocevar committed
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
                            break;
                        }
                    }

                    if( b_dash )
                    {
                        psz_prefix = ", --no-";
                        i -= strlen( p_item->psz_name ) + strlen( ", --no-" );
                    }
                    else
                    {
                        psz_prefix = ", --no";
                        i -= strlen( p_item->psz_name ) + strlen( ", --no" );
                    }
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
                }

                if( i < 0 )
                {
                    i = 0;
                    psz_spaces[i] = '\n';
                }
                else
                {
                    psz_spaces[i] = '\0';
                }

Gildas Bazin's avatar
 
Gildas Bazin committed
1113
                if( p_item->i_type == CONFIG_ITEM_BOOL &&
Sam Hocevar's avatar
Sam Hocevar committed
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
                    !b_help_module )
                {
                    fprintf( stderr, psz_format, p_item->psz_name, psz_prefix,
                             p_item->psz_name, psz_bra, psz_type, psz_ket,
                             psz_spaces, p_item->psz_text, psz_suf );
                }
                else
                {
                    fprintf( stderr, psz_format, p_item->psz_name, "", "",
                             psz_bra, psz_type, psz_ket, psz_spaces,
                             p_item->psz_text, psz_suf );
                }
1126
                psz_spaces[i] = ' ';
1127 1128 1129 1130
                if ( p_item->ppsz_list )
                {
                    free( psz_type );
                }
1131 1132 1133 1134
            }
        }
    }

1135 1136 1137
    /* Release the module list */
    vlc_list_release( p_list );

1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
        getchar();
#endif
}

/*****************************************************************************
 * ListModules: list the available modules with their description
 *****************************************************************************
 * Print a list of all available modules (builtins and plugins) and a short
 * description for each one.
 *****************************************************************************/
1150
static void ListModules( vlc_t *p_this )
1151
{
1152 1153
    vlc_list_t *p_list;
    module_t **pp_parser;
1154 1155 1156 1157 1158 1159 1160 1161 1162
    char psz_spaces[22];

    memset( psz_spaces, ' ', 22 );

#ifdef WIN32
    ShowConsole();
#endif

    /* Usage */
1163
    fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
1164 1165 1166 1167
                     p_this->p_vlc->psz_object_name );

    fprintf( stderr, _("[module]              [description]\n") );

1168 1169 1170
    /* List all modules */
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );

1171
    /* Enumerate each module */
1172 1173 1174
    for( pp_parser = (module_t **)p_list->pp_objects ;
         *pp_parser ;
         pp_parser++ )
1175 1176 1177 1178 1179
    {
        int i;

        /* Nasty hack, but right now I'm too tired to think about a nice
         * solution */
1180
        i = 22 - strlen( (*pp_parser)->psz_object_name ) - 1;
1181 1182 1183
        if( i < 0 ) i = 0;
        psz_spaces[i] = 0;

1184 1185
        fprintf( stderr, "  %s%s %s\n", (*pp_parser)->psz_object_name,
                         psz_spaces, (*pp_parser)->psz_longname );
1186 1187 1188 1189

        psz_spaces[i] = ' ';
    }

1190 1191
    vlc_list_release( p_list );

1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
        fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
        getchar();
#endif
}

/*****************************************************************************
 * Version: print complete program version
 *****************************************************************************
 * Print complete program version and build number.
 *****************************************************************************/
static void Version( void )
{
#ifdef WIN32
    ShowConsole();
#endif

    fprintf( stderr, VERSION_MESSAGE "\n" );
    fprintf( stderr,
      _("This program comes with NO WARRANTY, to the extent permitted by "
        "law.\nYou may redistribute it under the terms of the GNU General "
        "Public License;\nsee the file named COPYING for details.\n"
        "Written by the VideoLAN team at Ecole Centrale, Paris.\n") );

#ifdef WIN32        /* Pause the console because it's destroyed when we exit */
    fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
    getchar();
#endif
}

/*****************************************************************************
 * ShowConsole: On Win32, create an output console for debug messages
 *****************************************************************************
 * This function is useful only on Win32.
 *****************************************************************************/
#ifdef WIN32 /*  */
static void ShowConsole( void )
{
    AllocConsole();
    freopen( "CONOUT$", "w", stdout );
    freopen( "CONOUT$", "w", stderr );
    freopen( "CONIN$", "r", stdin );
    return;
}
#endif