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