* ./configure.ac.in: duplicated arguments to AM_INIT_AUTOMAKE to fix
[vlc.git] / src / libvlc.c
1 /*****************************************************************************
2  * libvlc.c: main libvlc source
3  *****************************************************************************
4  * Copyright (C) 1998-2002 VideoLAN
5  * $Id: libvlc.c,v 1.35 2002/10/03 18:56:09 sam Exp $
6  *
7  * Authors: Vincent Seguin <seguin@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
9  *          Gildas Bazin <gbazin@netcourrier.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Pretend we are a builtin module
28  *****************************************************************************/
29 #define MODULE_NAME main
30 #define MODULE_PATH main
31 #define __BUILTIN__
32
33 /*****************************************************************************
34  * Preamble
35  *****************************************************************************/
36 #include <errno.h>                                                 /* ENOMEM */
37 #include <stdio.h>                                              /* sprintf() */
38 #include <string.h>                                            /* strerror() */
39 #include <stdlib.h>                                                /* free() */
40
41 #include <vlc/vlc.h>
42
43 #ifndef WIN32
44 #   include <netinet/in.h>                            /* BSD: struct in_addr */
45 #endif
46
47 #ifdef HAVE_UNISTD_H
48 #   include <unistd.h>
49 #elif defined( _MSC_VER ) && defined( _WIN32 )
50 #   include <io.h>
51 #endif
52
53 #ifdef WIN32                       /* optind, getopt(), included in unistd.h */
54 #   include "extras/GNUgetopt/getopt.h"
55 #endif
56
57 #ifdef HAVE_LOCALE_H
58 #   include <locale.h>
59 #endif
60
61 #include "vlc_cpu.h"                                        /* CPU detection */
62 #include "os_specific.h"
63
64 #include "netutils.h"                                 /* network_ChannelJoin */
65
66 #include "stream_control.h"
67 #include "input_ext-intf.h"
68
69 #include "vlc_playlist.h"
70 #include "interface.h"
71
72 #include "audio_output.h"
73
74 #include "video.h"
75 #include "video_output.h"
76
77 #include "libvlc.h"
78
79 /*****************************************************************************
80  * The evil global variable. We handle it with care, don't worry.
81  *****************************************************************************/
82 static libvlc_t libvlc;
83
84 //#define GLOBAL_VLC NULL
85 #define GLOBAL_VLC ((vlc_t*)libvlc.pp_children[1])
86
87 /*****************************************************************************
88  * Local prototypes
89  *****************************************************************************/
90 static int  GetFilenames  ( vlc_t *, int, char *[] );
91 static void Usage         ( vlc_t *, const char *psz_module_name );
92 static void ListModules   ( vlc_t * );
93 static void Version       ( void );
94
95 #ifdef WIN32
96 static void ShowConsole   ( void );
97 #endif
98
99 /*****************************************************************************
100  * vlc_create: allocate a vlc_t structure, and initialize libvlc if needed.
101  *****************************************************************************
102  * This function allocates a vlc_t structure and returns NULL in case of
103  * failure. Also, the thread system is initialized.
104  *****************************************************************************/
105 vlc_error_t vlc_create( void )
106 {
107     vlc_t * p_vlc;
108     vlc_bool_t b_failed = VLC_FALSE;
109
110     /* This call should be thread-safe, but an additional check will be
111      * necessary afterwards to check that only one p_vlc is created. */
112     p_vlc = vlc_create_r();
113
114     if( p_vlc == NULL )
115     {
116         return VLC_EGENERIC;
117     }
118
119     /* We have created an object, which ensures us that p_global_lock has
120      * been properly initialized. We can now atomically check that we are
121      * the only p_vlc object. */
122 #if 0
123     vlc_mutex_lock( libvlc.p_global_lock );
124     if( libvlc.i_children != 1 ) /* FIXME !!! FIXME */
125     {
126         b_failed = VLC_TRUE;
127     }
128     vlc_mutex_unlock( libvlc.p_global_lock );
129 #endif
130
131     /* There can be only one */
132     if( b_failed )
133     {
134         vlc_destroy_r( p_vlc );
135         return VLC_EGENERIC;
136     }
137
138     return VLC_SUCCESS;
139 }
140
141 vlc_t * vlc_create_r( void )
142 {
143     int i_ret;
144     vlc_t * p_vlc = NULL;
145
146     /* vlc_threads_init *must* be the first internal call! No other call is
147      * allowed before the thread system has been initialized. */
148     i_ret = vlc_threads_init( &libvlc );
149     if( i_ret )
150     {
151         return NULL;
152     }
153
154     /* Now that the thread system is initialized, we don't have much, but
155      * at least we have libvlc.global_lock */
156     vlc_mutex_lock( &libvlc.global_lock );
157     if( !libvlc.b_ready )
158     {
159         char *psz_env;
160
161         vlc_mutex_init( &libvlc, &libvlc.structure_lock );
162         libvlc.p_global_data = NULL;
163         libvlc.b_ready = VLC_TRUE;
164
165         /* Guess what CPU we have */
166         libvlc.i_cpu = CPUCapabilities();
167
168         /* Find verbosity from VLC_VERBOSE environment variable */
169         psz_env = getenv( "VLC_VERBOSE" );
170         libvlc.i_verbose = psz_env ? atoi( psz_env ) : 0;
171
172 #ifdef HAVE_ISATTY
173         libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
174 #else
175         libvlc.b_color = VLC_FALSE;
176 #endif
177
178         /* Initialize message queue */
179         msg_Create( &libvlc );
180
181         /* Announce who we are */
182         msg_Dbg( &libvlc, COPYRIGHT_MESSAGE );
183         msg_Dbg( &libvlc, "libvlc was configured with %s", CONFIGURE_LINE );
184
185         /* Initialize the module bank and and load the configuration of the
186          * main module. We need to do this at this stage to be able to display
187          * a short help if required by the user. (short help == main module
188          * options) */
189         module_InitBank( &libvlc );
190         module_LoadMain( &libvlc );
191     }
192     vlc_mutex_unlock( &libvlc.global_lock );
193
194     /* Allocate a vlc object */
195     p_vlc = vlc_object_create( &libvlc, VLC_OBJECT_VLC );
196     if( p_vlc == NULL )
197     {
198         return NULL;
199     }
200
201     p_vlc->psz_object_name = "root";
202
203     /* Initialize mutexes */
204     vlc_mutex_init( p_vlc, &p_vlc->config_lock );
205
206     /* Store our newly allocated structure in the global list */
207     vlc_object_attach( p_vlc, &libvlc );
208
209     /* Update the handle status */
210     p_vlc->i_status = VLC_STATUS_CREATED;
211
212     return p_vlc;
213 }
214
215 /*****************************************************************************
216  * vlc_init: initialize a vlc_t structure.
217  *****************************************************************************
218  * This function initializes a previously allocated vlc_t structure:
219  *  - CPU detection
220  *  - gettext initialization
221  *  - message queue, module bank and playlist initialization
222  *  - configuration and commandline parsing
223  *****************************************************************************/
224 vlc_error_t vlc_init( int i_argc, char *ppsz_argv[] )
225 {
226     return vlc_init_r( GLOBAL_VLC, i_argc, ppsz_argv );
227 }
228
229 vlc_error_t vlc_init_r( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
230 {
231     char         p_capabilities[200];
232     char *       p_tmp;
233     vlc_bool_t   b_exit;
234     module_t    *p_help_module;
235     playlist_t  *p_playlist;
236
237     /* Check that the handle is valid */
238     if( !p_vlc || p_vlc->i_status != VLC_STATUS_CREATED )
239     {
240         fprintf( stderr, "error: invalid status (!CREATED)\n" );
241         return VLC_ESTATUS;
242     }
243
244     /* Support for gettext */
245 #if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
246 #   if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
247     if( !setlocale( LC_MESSAGES, "" ) )
248     {
249         fprintf( stderr, "warning: unsupported locale settings\n" );
250     }
251
252     setlocale( LC_CTYPE, "" );
253 #   endif
254
255     if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
256     {
257         fprintf( stderr, "warning: no domain %s in directory %s\n",
258                  PACKAGE, LOCALEDIR );
259     }
260
261     textdomain( PACKAGE );
262 #endif
263
264     /*
265      * System specific initialization code
266      */
267     system_Init( p_vlc, &i_argc, ppsz_argv );
268
269     /* Get the executable name (similar to the basename command) */
270     if( i_argc > 0 )
271     {
272         p_vlc->psz_object_name = p_tmp = ppsz_argv[ 0 ];
273         while( *p_tmp )
274         {
275             if( *p_tmp == '/' ) p_vlc->psz_object_name = ++p_tmp;
276             else ++p_tmp;
277         }
278     }
279     else
280     {
281         p_vlc->psz_object_name = "vlc";
282     }
283
284     /* Hack: insert the help module here */
285     p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
286     if( p_help_module == NULL )
287     {
288         //module_EndBank( p_vlc );
289         return VLC_EGENERIC;
290     }
291     p_help_module->psz_object_name = "help";
292     config_Duplicate( p_help_module, p_help_config );
293     vlc_object_attach( p_help_module, libvlc.p_module_bank );
294     /* End hack */
295
296     if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
297     {
298         vlc_object_detach( p_help_module );
299         config_Free( p_help_module );
300         vlc_object_destroy( p_help_module );
301         //module_EndBank( p_vlc );
302         return VLC_EGENERIC;
303     }
304
305     b_exit = VLC_FALSE;
306
307     /* Check for short help option */
308     if( config_GetInt( p_vlc, "help" ) )
309     {
310         fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
311                          p_vlc->psz_object_name );
312         Usage( p_vlc, "main" );
313         Usage( p_vlc, "help" );
314         b_exit = VLC_TRUE;
315     }
316     /* Check for version option */
317     else if( config_GetInt( p_vlc, "version" ) )
318     {
319         Version();
320         b_exit = VLC_TRUE;
321     }
322
323     /* Hack: remove the help module here */
324     vlc_object_detach( p_help_module );
325     /* End hack */
326
327     if( b_exit )
328     {
329         config_Free( p_help_module );
330         vlc_object_destroy( p_help_module );
331         //module_EndBank( p_vlc );
332         return VLC_EEXIT;
333     }
334
335     /*
336      * Load the builtins and plugins into the module_bank.
337      * We have to do it before config_Load*() because this also gets the
338      * list of configuration options exported by each module and loads their
339      * default values.
340      */
341     module_LoadBuiltins( &libvlc );
342     module_LoadPlugins( &libvlc );
343     msg_Dbg( p_vlc, "module bank initialized, found %i modules",
344                     libvlc.p_module_bank->i_children );
345
346     /* Hack: insert the help module here */
347     vlc_object_attach( p_help_module, libvlc.p_module_bank );
348     /* End hack */
349
350     /* Check for help on modules */
351     if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
352     {
353         Usage( p_vlc, p_tmp );
354         free( p_tmp );
355         b_exit = VLC_TRUE;
356     }
357     /* Check for long help option */
358     else if( config_GetInt( p_vlc, "longhelp" ) )
359     {
360         Usage( p_vlc, NULL );
361         b_exit = VLC_TRUE;
362     }
363     /* Check for module list option */
364     else if( config_GetInt( p_vlc, "list" ) )
365     {
366         ListModules( p_vlc );
367         b_exit = VLC_TRUE;
368     }
369
370     /* Hack: remove the help module here */
371     vlc_object_detach( p_help_module );
372     config_Free( p_help_module );
373     vlc_object_destroy( p_help_module );
374     /* End hack */
375
376     if( b_exit )
377     {
378         //module_EndBank( p_vlc );
379         return VLC_EEXIT;
380     }
381
382     /*
383      * Override default configuration with config file settings
384      */
385     p_vlc->psz_homedir = config_GetHomeDir();
386     config_LoadConfigFile( p_vlc, NULL );
387
388     /*
389      * Override configuration with command line settings
390      */
391     if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
392     {
393 #ifdef WIN32
394         ShowConsole();
395         /* Pause the console because it's destroyed when we exit */
396         fprintf( stderr, "The command line options couldn't be loaded, check "
397                  "that they are valid.\nPress the RETURN key to continue..." );
398         getchar();
399 #endif
400         //module_EndBank( p_vlc );
401         return VLC_EGENERIC;
402     }
403
404     /*
405      * System specific configuration
406      */
407     system_Configure( p_vlc );
408
409     /*
410      * Message queue options
411      */
412     if( config_GetInt( p_vlc, "quiet" ) )
413     {
414         libvlc.i_verbose = 0;
415     }
416     else
417     {
418         int i_tmp = config_GetInt( p_vlc, "verbose" );
419         if( i_tmp >= 0 && i_tmp <= 4 )
420         {
421             libvlc.i_verbose = i_tmp;
422         }
423     }
424     libvlc.b_color = libvlc.b_color || config_GetInt( p_vlc, "color" );
425
426     /*
427      * Output messages that may still be in the queue
428      */
429     msg_Flush( p_vlc );
430
431     /* p_vlc inititalization. FIXME ? */
432     p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
433
434 #if defined( __i386__ )
435     if( !config_GetInt( p_vlc, "mmx" ) )
436         libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
437     if( !config_GetInt( p_vlc, "3dn" ) )
438         libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
439     if( !config_GetInt( p_vlc, "mmxext" ) )
440         libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
441     if( !config_GetInt( p_vlc, "sse" ) )
442         libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
443 #endif
444 #if defined( __powerpc__ ) || defined( SYS_DARWIN )
445     if( !config_GetInt( p_vlc, "altivec" ) )
446         libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
447 #endif
448
449 #define PRINT_CAPABILITY( capability, string )                              \
450     if( libvlc.i_cpu & capability )                                         \
451     {                                                                       \
452         strncat( p_capabilities, string " ",                                \
453                  sizeof(p_capabilities) - strlen(p_capabilities) );         \
454         p_capabilities[sizeof(p_capabilities) - 1] = '\0';                  \
455     }
456
457     p_capabilities[0] = '\0';
458     PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
459     PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
460     PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
461     PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
462     PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
463     PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
464     PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
465     PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "AltiVec" );
466     PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
467     msg_Dbg( p_vlc, "CPU has capabilities %s", p_capabilities );
468
469     /*
470      * Choose the best memcpy module
471      */
472     p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
473
474     if( p_vlc->pf_memcpy == NULL )
475     {
476         p_vlc->pf_memcpy = memcpy;
477     }
478
479     if( p_vlc->pf_memset == NULL )
480     {
481         p_vlc->pf_memset = memset;
482     }
483
484     /*
485      * Initialize shared resources and libraries
486      */
487     if( config_GetInt( p_vlc, "network-channel" )
488          && network_ChannelCreate( p_vlc ) )
489     {
490         /* On error during Channels initialization, switch off channels */
491         msg_Warn( p_vlc,
492                   "channels initialization failed, deactivating channels" );
493         config_PutInt( p_vlc, "network-channel", VLC_FALSE );
494     }
495
496     /*
497      * Initialize playlist and get commandline files
498      */
499     p_playlist = playlist_Create( p_vlc );
500     if( !p_playlist )
501     {
502         msg_Err( p_vlc, "playlist initialization failed" );
503         if( p_vlc->p_memcpy_module != NULL )
504         {
505             module_Unneed( p_vlc, p_vlc->p_memcpy_module );
506         }
507         //module_EndBank( p_vlc );
508         return VLC_EGENERIC;
509     }
510
511     /* Update the handle status */
512     p_vlc->i_status = VLC_STATUS_STOPPED;
513
514     /*
515      * Get input filenames given as commandline arguments
516      */
517     GetFilenames( p_vlc, i_argc, ppsz_argv );
518
519     return VLC_SUCCESS;
520 }
521
522 /*****************************************************************************
523  * vlc_add_intf: add an interface
524  *****************************************************************************
525  * This function opens an interface plugin and runs it. If b_block is set
526  * to 0, vlc_add_intf will return immediately and let the interface run in a
527  * separate thread. If b_block is set to 1, vlc_add_intf will continue until
528  * user requests to quit.
529  *****************************************************************************/
530 vlc_error_t vlc_add_intf( const char *psz_module, vlc_bool_t b_block )
531 {
532     return vlc_add_intf_r( GLOBAL_VLC,
533                            psz_module, b_block );
534 }
535
536 vlc_error_t vlc_add_intf_r( vlc_t *p_vlc, const char *psz_module,
537                                           vlc_bool_t b_block )
538 {
539     vlc_error_t err;
540     intf_thread_t *p_intf;
541     char *psz_oldmodule = NULL;
542
543     /* Check that the handle is valid */
544     if( !p_vlc || p_vlc->i_status != VLC_STATUS_RUNNING )
545     {
546         fprintf( stderr, "error: invalid status (!RUNNING)\n" );
547         return VLC_ESTATUS;
548     }
549
550     if( psz_module )
551     {
552         psz_oldmodule = config_GetPsz( p_vlc, "intf" );
553         config_PutPsz( p_vlc, "intf", psz_module );
554     }
555
556     /* Try to create the interface */
557     p_intf = intf_Create( p_vlc );
558
559     if( psz_module )
560     {
561         config_PutPsz( p_vlc, "intf", psz_oldmodule );
562         if( psz_oldmodule )
563         {
564             free( psz_oldmodule );
565         }
566     }
567
568     if( p_intf == NULL )
569     {
570         msg_Err( p_vlc, "interface initialization failed" );
571         return VLC_EGENERIC;
572     }
573
574     /* Try to run the interface */
575     p_intf->b_block = b_block;
576     err = intf_RunThread( p_intf );
577     if( err )
578     {
579         vlc_object_detach( p_intf );
580         intf_Destroy( p_intf );
581         return err;
582     }
583
584     return VLC_SUCCESS;
585 }
586
587 /*****************************************************************************
588  * vlc_destroy: stop playing and destroy everything.
589  *****************************************************************************
590  * This function requests the running threads to finish, waits for their
591  * termination, and destroys their structure.
592  *****************************************************************************/
593 vlc_error_t vlc_destroy( void )
594 {
595     return vlc_destroy_r( GLOBAL_VLC );
596 }
597
598 vlc_error_t vlc_destroy_r( vlc_t *p_vlc )
599 {
600     /* Check that the handle is valid */
601     if( !p_vlc || (p_vlc->i_status != VLC_STATUS_STOPPED
602                     && p_vlc->i_status != VLC_STATUS_CREATED) )
603     {
604         fprintf( stderr, "error: invalid status "
605                          "(!STOPPED&&!CREATED)\n" );
606         return VLC_ESTATUS;
607     }
608
609     if( p_vlc->i_status == VLC_STATUS_STOPPED )
610     {
611         /*
612          * Go back into channel 0 which is the network
613          */
614         if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
615         {
616             network_ChannelJoin( p_vlc, COMMON_CHANNEL );
617         }
618     
619         /*
620          * Free allocated memory
621          */
622         if( p_vlc->p_memcpy_module != NULL )
623         {
624             module_Unneed( p_vlc, p_vlc->p_memcpy_module );
625         }
626     
627         free( p_vlc->psz_homedir );
628     
629         /*
630          * XXX: Free module bank !
631          */
632         //module_EndBank( p_vlc );
633     
634         /*
635          * System specific cleaning code
636          */
637         system_End( p_vlc );
638     
639         /* Update the handle status */
640         p_vlc->i_status = VLC_STATUS_CREATED;
641     }
642
643     /* Update the handle status, just in case */
644     p_vlc->i_status = VLC_STATUS_NONE;
645
646     /* Destroy mutexes */
647     vlc_mutex_destroy( &p_vlc->config_lock );
648
649     vlc_object_detach( p_vlc );
650
651     vlc_object_destroy( p_vlc );
652
653     /* Stop thread system: last one out please shut the door! */
654     vlc_threads_end( &libvlc );
655
656     return VLC_SUCCESS;
657 }
658
659 /*****************************************************************************
660  * vlc_die: ask vlc to die.
661  *****************************************************************************
662  * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
663  * task. It is your duty to call vlc_end and vlc_destroy afterwards.
664  *****************************************************************************/
665 vlc_error_t vlc_die( void )
666 {
667     return vlc_die_r( GLOBAL_VLC );
668 }
669
670 vlc_error_t vlc_die_r( vlc_t *p_vlc )
671 {
672     if( !p_vlc )
673     {
674         fprintf( stderr, "error: invalid status (!EXIST)\n" );
675         return VLC_ESTATUS;
676     }
677
678     p_vlc->b_die = VLC_TRUE;
679
680     return VLC_SUCCESS;
681 }
682
683 /*****************************************************************************
684  * vlc_status: return the current vlc status.
685  *****************************************************************************
686  * This function returns the current value of p_vlc->i_status.
687  *****************************************************************************/
688 vlc_status_t vlc_status( void )
689 {
690     return vlc_status_r( GLOBAL_VLC );
691 }
692
693 vlc_status_t vlc_status_r( vlc_t *p_vlc )
694 {
695     if( !p_vlc )
696     {
697         return VLC_STATUS_NONE;
698     }
699
700     return p_vlc->i_status;
701 }
702
703 /*****************************************************************************
704  * vlc_add_target: adds a target for playing.
705  *****************************************************************************
706  * This function adds psz_target to the current playlist. If a playlist does
707  * not exist, it will create one.
708  *****************************************************************************/
709 vlc_error_t vlc_add_target( const char *psz_target, int i_mode, int i_pos )
710 {
711     return vlc_add_target_r( GLOBAL_VLC,
712                              psz_target, i_mode, i_pos );
713 }
714
715 vlc_error_t vlc_add_target_r( vlc_t *p_vlc, const char *psz_target,
716                                             int i_mode, int i_pos )
717 {
718     vlc_error_t err;
719     playlist_t *p_playlist;
720
721     if( !p_vlc || ( p_vlc->i_status != VLC_STATUS_STOPPED
722                      && p_vlc->i_status != VLC_STATUS_RUNNING ) )
723     {
724         fprintf( stderr, "error: invalid status (!STOPPED&&!RUNNING)\n" );
725         return VLC_ESTATUS;
726     }
727
728     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
729
730     if( p_playlist == NULL )
731     {
732         msg_Dbg( p_vlc, "no playlist present, creating one" );
733         p_playlist = playlist_Create( p_vlc );
734
735         if( p_playlist == NULL )
736         {
737             return VLC_EGENERIC;
738         }
739
740         vlc_object_yield( p_playlist );
741     }
742
743     err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
744
745     vlc_object_release( p_playlist );
746
747     return err;
748 }
749
750 /*****************************************************************************
751  * vlc_set: set a vlc variable
752  *****************************************************************************
753  *
754  *****************************************************************************/
755 vlc_error_t vlc_set( const char *psz_var, const char *psz_val )
756 {
757     return vlc_set_r( GLOBAL_VLC, psz_var, psz_val );
758 }
759
760 vlc_error_t vlc_set_r( vlc_t *p_vlc, const char *psz_var, const char *psz_val )
761 {
762     module_config_t *p_config;
763
764     if( !p_vlc )
765     {
766         fprintf( stderr, "error: invalid status\n" );
767         return VLC_ESTATUS;
768     }
769
770     p_config = config_FindConfig( VLC_OBJECT(p_vlc), psz_var );
771
772     if( !p_config )
773     {
774         msg_Err( p_vlc, "option %s does not exist", psz_var );
775         return VLC_EGENERIC;
776     }
777
778     vlc_mutex_lock( p_config->p_lock );
779
780     switch( p_config->i_type )
781     {
782     case CONFIG_ITEM_BOOL:
783         if( psz_val && *psz_val )
784         {
785             if( !strcmp( psz_val, "off" ) || !strcmp( psz_val, "no" ) )
786             {
787                 p_config->i_value = VLC_FALSE;
788             }
789             else
790             {
791                 p_config->i_value = atoi( psz_val );
792             }
793         }
794         else
795         {
796             p_config->i_value = VLC_TRUE;
797         }
798         break;
799     case CONFIG_ITEM_INTEGER:
800         if( psz_val && *psz_val )
801         {
802             p_config->i_value = atoi( psz_val );
803         }
804         else
805         {
806             p_config->i_value = 0;
807         }
808         break;
809     case CONFIG_ITEM_FLOAT:
810         if( psz_val && *psz_val )
811         {
812             p_config->f_value = (float)atof( psz_val );
813         }
814         else
815         {
816             p_config->f_value = 0.0;
817         }
818         break;
819     case CONFIG_ITEM_STRING:
820     case CONFIG_ITEM_FILE:
821     case CONFIG_ITEM_MODULE:
822     default:
823         if( p_config->psz_value )
824         {
825             free( p_config->psz_value );
826         }
827
828         if( psz_val )
829         {
830             p_config->psz_value = strdup( psz_val );
831         }
832         else
833         {
834             p_config->psz_value = NULL;
835         }
836         break;
837     }
838
839     if( p_config->pf_callback )
840     {
841         vlc_mutex_unlock( p_config->p_lock );
842         p_config->pf_callback( VLC_OBJECT(p_vlc) );
843     }
844     else
845     {
846         vlc_mutex_unlock( p_config->p_lock );
847     }
848
849     return VLC_SUCCESS;
850 }
851
852 /* XXX: temporary hacks */
853
854 /*****************************************************************************
855  * vlc_play: play
856  *****************************************************************************/
857 vlc_error_t vlc_play( )
858 {
859     return vlc_play_r( GLOBAL_VLC );
860 }
861
862 vlc_error_t vlc_play_r( vlc_t *p_vlc )
863 {
864     playlist_t * p_playlist;
865
866     /* Check that the handle is valid */
867     if( !p_vlc || p_vlc->i_status != VLC_STATUS_STOPPED )
868     {
869         fprintf( stderr, "error: invalid status (!STOPPED)\n" );
870         return VLC_ESTATUS;
871     }
872
873     /* Update the handle status */
874     p_vlc->i_status = VLC_STATUS_RUNNING;
875
876     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );
877
878     if( !p_playlist )
879     {
880         return VLC_EOBJECT;
881     }
882
883     vlc_mutex_lock( &p_playlist->object_lock );
884     if( p_playlist->i_size )
885     {
886         vlc_mutex_unlock( &p_playlist->object_lock );
887         playlist_Play( p_playlist );
888     }
889     else
890     {
891         vlc_mutex_unlock( &p_playlist->object_lock );
892     }
893
894     vlc_object_release( p_playlist );
895
896     return VLC_SUCCESS;
897 }
898
899 /*****************************************************************************
900  * vlc_stop: stop
901  *****************************************************************************/
902 vlc_error_t vlc_stop( )
903 {
904     return vlc_stop_r( GLOBAL_VLC );
905 }
906
907 vlc_error_t vlc_stop_r( vlc_t *p_vlc )
908 {
909     intf_thread_t *   p_intf;
910     playlist_t    *   p_playlist;
911     vout_thread_t *   p_vout;
912     aout_instance_t * p_aout;
913
914     /* Check that the handle is valid */
915     if( !p_vlc || ( p_vlc->i_status != VLC_STATUS_STOPPED
916                      && p_vlc->i_status != VLC_STATUS_RUNNING ) )
917     {
918         fprintf( stderr, "error: invalid status (!STOPPED&&!RUNNING)\n" );
919         return VLC_ESTATUS;
920     }
921
922     /*
923      * Ask the interfaces to stop and destroy them
924      */
925     msg_Dbg( p_vlc, "removing all interfaces" );
926     while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_CHILD )) )
927     {
928         intf_StopThread( p_intf );
929         vlc_object_detach( p_intf );
930         vlc_object_release( p_intf );
931         intf_Destroy( p_intf );
932     }
933
934     /*
935      * Free playlists
936      */
937     msg_Dbg( p_vlc, "removing all playlists" );
938     while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
939                                           FIND_CHILD )) )
940     {
941         vlc_object_detach( p_playlist );
942         vlc_object_release( p_playlist );
943         playlist_Destroy( p_playlist );
944     }
945
946     /*
947      * Free video outputs
948      */
949     msg_Dbg( p_vlc, "removing all video outputs" );
950     while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
951     {
952         vlc_object_detach( p_vout );
953         vlc_object_release( p_vout );
954         vout_DestroyThread( p_vout );
955     }
956
957     /*
958      * Free audio outputs
959      */
960     msg_Dbg( p_vlc, "removing all audio outputs" );
961     while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
962     {
963         vlc_object_detach( (vlc_object_t *)p_aout );
964         vlc_object_release( (vlc_object_t *)p_aout );
965         aout_Delete( p_aout );
966     }
967
968     /* Update the handle status */
969     p_vlc->i_status = VLC_STATUS_STOPPED;
970
971     return VLC_SUCCESS;
972 }
973
974 /*****************************************************************************
975  * vlc_pause: toggle pause
976  *****************************************************************************/
977 vlc_error_t vlc_pause( )
978 {
979     return vlc_pause_r( GLOBAL_VLC );
980 }
981
982 vlc_error_t vlc_pause_r( vlc_t *p_vlc )
983 {
984     input_thread_t *p_input;
985
986     p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );
987
988     if( !p_input )
989     {
990         return VLC_EOBJECT;
991     }
992
993     input_SetStatus( p_input, INPUT_STATUS_PAUSE );
994     vlc_object_release( p_input );
995
996     return VLC_SUCCESS;
997 }
998
999 /*****************************************************************************
1000  * vlc_fullscreen: toggle fullscreen mode
1001  *****************************************************************************/
1002 vlc_error_t vlc_fullscreen( )
1003 {
1004     return vlc_fullscreen_r( GLOBAL_VLC );
1005 }
1006
1007 vlc_error_t vlc_fullscreen_r( vlc_t *p_vlc )
1008 {
1009     vout_thread_t *p_vout;
1010
1011     p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );
1012
1013     if( !p_vout )
1014     {
1015         return VLC_EOBJECT;
1016     }
1017
1018     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
1019     vlc_object_release( p_vout );
1020
1021     return VLC_SUCCESS;
1022 }
1023
1024 /* following functions are local */
1025
1026 /*****************************************************************************
1027  * GetFilenames: parse command line options which are not flags
1028  *****************************************************************************
1029  * Parse command line for input files.
1030  *****************************************************************************/
1031 static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
1032 {
1033     int i_opt;
1034
1035     /* We assume that the remaining parameters are filenames */
1036     for( i_opt = optind; i_opt < i_argc; i_opt++ )
1037     {
1038         vlc_add_target_r( p_vlc, ppsz_argv[ i_opt ],
1039                           PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
1040     }
1041
1042     return VLC_SUCCESS;
1043 }
1044
1045 /*****************************************************************************
1046  * Usage: print program usage
1047  *****************************************************************************
1048  * Print a short inline help. Message interface is initialized at this stage.
1049  *****************************************************************************/
1050 static void Usage( vlc_t *p_this, const char *psz_module_name )
1051 {
1052 #define FORMAT_STRING "      --%s%s%s%s%s%s%s %s%s\n"
1053     /* option name -------------'     | | | |  | |
1054      * <bra --------------------------' | | |  | |
1055      * option type or "" ---------------' | |  | |
1056      * ket> ------------------------------' |  | |
1057      * padding spaces ----------------------'  | |
1058      * comment --------------------------------' |
1059      * comment suffix ---------------------------'
1060      *
1061      * The purpose of having bra and ket is that we might i18n them as well.
1062      */
1063 #define LINE_START 8
1064 #define PADDING_SPACES 25
1065     vlc_list_t *p_list;
1066     module_t **pp_parser;
1067     module_config_t *p_item;
1068     char psz_spaces[PADDING_SPACES+LINE_START+1];
1069     char psz_format[sizeof(FORMAT_STRING)];
1070
1071     memset( psz_spaces, ' ', PADDING_SPACES+LINE_START );
1072     psz_spaces[PADDING_SPACES+LINE_START] = '\0';
1073
1074     strcpy( psz_format, FORMAT_STRING );
1075
1076 #ifdef WIN32
1077     ShowConsole();
1078 #endif
1079
1080     /* List all modules */
1081     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1082
1083     /* Enumerate the config for each module */
1084     for( pp_parser = (module_t **)p_list->pp_objects ;
1085          *pp_parser ;
1086          pp_parser++ )
1087     {
1088         vlc_bool_t b_help_module;
1089
1090         if( psz_module_name && strcmp( psz_module_name,
1091                                        (*pp_parser)->psz_object_name ) )
1092         {
1093             continue;
1094         }
1095
1096         /* Ignore modules without config options */
1097         if( !(*pp_parser)->i_config_items )
1098         {
1099             continue;
1100         }
1101
1102         b_help_module = !strcmp( "help", (*pp_parser)->psz_object_name );
1103
1104         /* Print module options */
1105         for( p_item = (*pp_parser)->p_config;
1106              p_item->i_type != CONFIG_HINT_END;
1107              p_item++ )
1108         {
1109             char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
1110             char *psz_suf = "", *psz_prefix = NULL;
1111             int i;
1112
1113             switch( p_item->i_type )
1114             {
1115             case CONFIG_HINT_CATEGORY:
1116             case CONFIG_HINT_USAGE:
1117                 fprintf( stderr, " %s\n", p_item->psz_text );
1118                 break;
1119
1120             case CONFIG_ITEM_STRING:
1121             case CONFIG_ITEM_FILE:
1122             case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
1123                 if( !p_item->ppsz_list )
1124                 {
1125                     psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
1126                     break;
1127                 }
1128                 else
1129                 {
1130                     psz_bra = " [";
1131                     psz_type = malloc( 1000 );
1132                     memset( psz_type, 0, 1000 );
1133                     for( i=0; p_item->ppsz_list[i]; i++ )
1134                     {
1135                         strcat( psz_type, p_item->ppsz_list[i] );
1136                         strcat( psz_type, "|" );
1137                     }
1138                     psz_type[ strlen( psz_type ) - 1 ] = '\0';
1139                     psz_ket = "]";
1140                     break;
1141                 }
1142             case CONFIG_ITEM_INTEGER:
1143                 psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
1144                 break;
1145             case CONFIG_ITEM_FLOAT:
1146                 psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
1147                 break;
1148             case CONFIG_ITEM_BOOL:
1149                 psz_bra = ""; psz_type = ""; psz_ket = "";
1150                 if( !b_help_module )
1151                 {
1152                     psz_suf = p_item->i_value ? _(" (default enabled)") :
1153                                                 _(" (default disabled)");
1154                 }
1155                 break;
1156             }
1157
1158             /* Add short option if any */
1159             if( p_item->i_short )
1160             {
1161                 psz_format[2] = '-';
1162                 psz_format[3] = p_item->i_short;
1163                 psz_format[4] = ',';
1164             }
1165             else
1166             {
1167                 psz_format[2] = ' ';
1168                 psz_format[3] = ' ';
1169                 psz_format[4] = ' ';
1170             }
1171
1172             if( psz_type )
1173             {
1174                 i = PADDING_SPACES - strlen( p_item->psz_name )
1175                      - strlen( psz_bra ) - strlen( psz_type )
1176                      - strlen( psz_ket ) - 1;
1177                 if( p_item->i_type == CONFIG_ITEM_BOOL
1178                      && !b_help_module )
1179                 {
1180                     /* If option is of type --foo-bar, we print its counterpart
1181                      * as --no-foo-bar, but if it is of type --foobar (without
1182                      * dashes in the name) we print it as --nofoobar. Both
1183                      * values are of course valid, only the display changes. */
1184                     vlc_bool_t b_dash = VLC_FALSE;
1185                     psz_prefix = p_item->psz_name;
1186                     while( *psz_prefix )
1187                     {
1188                         if( *psz_prefix++ == '-' )
1189                         {
1190                             b_dash = VLC_TRUE;
1191                             break;
1192                         }
1193                     }
1194
1195                     if( b_dash )
1196                     {
1197                         psz_prefix = ", --no-";
1198                         i -= strlen( p_item->psz_name ) + strlen( ", --no-" );
1199                     }
1200                     else
1201                     {
1202                         psz_prefix = ", --no";
1203                         i -= strlen( p_item->psz_name ) + strlen( ", --no" );
1204                     }
1205                 }
1206
1207                 if( i < 0 )
1208                 {
1209                     i = 0;
1210                     psz_spaces[i] = '\n';
1211                 }
1212                 else
1213                 {
1214                     psz_spaces[i] = '\0';
1215                 }
1216
1217                 if( p_item->i_type == CONFIG_ITEM_BOOL &&
1218                     !b_help_module )
1219                 {
1220                     fprintf( stderr, psz_format, p_item->psz_name, psz_prefix,
1221                              p_item->psz_name, psz_bra, psz_type, psz_ket,
1222                              psz_spaces, p_item->psz_text, psz_suf );
1223                 }
1224                 else
1225                 {
1226                     fprintf( stderr, psz_format, p_item->psz_name, "", "",
1227                              psz_bra, psz_type, psz_ket, psz_spaces,
1228                              p_item->psz_text, psz_suf );
1229                 }
1230                 psz_spaces[i] = ' ';
1231                 if ( p_item->ppsz_list )
1232                 {
1233                     free( psz_type );
1234                 }
1235             }
1236         }
1237     }
1238
1239     /* Release the module list */
1240     vlc_list_release( p_list );
1241
1242 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1243         fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1244         getchar();
1245 #endif
1246 }
1247
1248 /*****************************************************************************
1249  * ListModules: list the available modules with their description
1250  *****************************************************************************
1251  * Print a list of all available modules (builtins and plugins) and a short
1252  * description for each one.
1253  *****************************************************************************/
1254 static void ListModules( vlc_t *p_this )
1255 {
1256     vlc_list_t *p_list;
1257     module_t **pp_parser;
1258     char psz_spaces[22];
1259
1260     memset( psz_spaces, ' ', 22 );
1261
1262 #ifdef WIN32
1263     ShowConsole();
1264 #endif
1265
1266     /* Usage */
1267     fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
1268                      p_this->p_vlc->psz_object_name );
1269
1270     fprintf( stderr, _("[module]              [description]\n") );
1271
1272     /* List all modules */
1273     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1274
1275     /* Enumerate each module */
1276     for( pp_parser = (module_t **)p_list->pp_objects ;
1277          *pp_parser ;
1278          pp_parser++ )
1279     {
1280         int i;
1281
1282         /* Nasty hack, but right now I'm too tired to think about a nice
1283          * solution */
1284         i = 22 - strlen( (*pp_parser)->psz_object_name ) - 1;
1285         if( i < 0 ) i = 0;
1286         psz_spaces[i] = 0;
1287
1288         fprintf( stderr, "  %s%s %s\n", (*pp_parser)->psz_object_name,
1289                          psz_spaces, (*pp_parser)->psz_longname );
1290
1291         psz_spaces[i] = ' ';
1292     }
1293
1294     vlc_list_release( p_list );
1295
1296 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1297         fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1298         getchar();
1299 #endif
1300 }
1301
1302 /*****************************************************************************
1303  * Version: print complete program version
1304  *****************************************************************************
1305  * Print complete program version and build number.
1306  *****************************************************************************/
1307 static void Version( void )
1308 {
1309 #ifdef WIN32
1310     ShowConsole();
1311 #endif
1312
1313     fprintf( stderr, VERSION_MESSAGE "\n" );
1314     fprintf( stderr,
1315       _("This program comes with NO WARRANTY, to the extent permitted by "
1316         "law.\nYou may redistribute it under the terms of the GNU General "
1317         "Public License;\nsee the file named COPYING for details.\n"
1318         "Written by the VideoLAN team at Ecole Centrale, Paris.\n") );
1319
1320 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1321     fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1322     getchar();
1323 #endif
1324 }
1325
1326 /*****************************************************************************
1327  * ShowConsole: On Win32, create an output console for debug messages
1328  *****************************************************************************
1329  * This function is useful only on Win32.
1330  *****************************************************************************/
1331 #ifdef WIN32 /*  */
1332 static void ShowConsole( void )
1333 {
1334     AllocConsole();
1335     freopen( "CONOUT$", "w", stdout );
1336     freopen( "CONOUT$", "w", stderr );
1337     freopen( "CONIN$", "r", stdin );
1338     return;
1339 }
1340 #endif
1341