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