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