]> git.sesse.net Git - vlc/blob - src/libvlc.c
3bdf946f4c2b390a69a5b2a39395cb99d2217a19
[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.16 2002/07/18 01:00:41 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 (!CREATED)\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     /*
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_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( vlc_t *p_vlc )
519 {
520     /* Check that the handle is valid */
521     if( !p_vlc || p_vlc->i_status != VLC_STATUS_STOPPED )
522     {
523         fprintf( stderr, "error: invalid status (!STOPPED)\n" );
524         return VLC_ESTATUS;
525     }
526
527     /* Update the handle status */
528     p_vlc->i_status = VLC_STATUS_RUNNING;
529
530     return VLC_SUCCESS;
531 }
532
533 /*****************************************************************************
534  * vlc_add_intf: add an interface
535  *****************************************************************************
536  * This function opens an interface plugin and runs it. If b_block is set
537  * to 0, vlc_add_intf will return immediately and let the interface run in a
538  * separate thread. If b_block is set to 1, vlc_add_intf will continue until
539  * user requests to quit.
540  *****************************************************************************/
541 vlc_error_t vlc_add_intf( vlc_t *p_vlc, const char *psz_module,
542                                         vlc_bool_t b_block )
543 {
544     vlc_error_t err;
545     intf_thread_t *p_intf;
546     char *psz_oldmodule = NULL;
547
548     /* Check that the handle is valid */
549     if( !p_vlc || p_vlc->i_status != VLC_STATUS_RUNNING )
550     {
551         fprintf( stderr, "error: invalid status (!RUNNING)\n" );
552         return VLC_ESTATUS;
553     }
554
555     if( psz_module )
556     {
557         psz_oldmodule = config_GetPsz( p_vlc, "intf" );
558         config_PutPsz( p_vlc, "intf", psz_module );
559     }
560
561     /* Try to create the interface */
562     p_intf = intf_Create( p_vlc );
563
564     if( psz_module )
565     {
566         config_PutPsz( p_vlc, "intf", psz_oldmodule );
567         if( psz_oldmodule )
568         {
569             free( psz_oldmodule );
570         }
571     }
572
573     if( p_intf == NULL )
574     {
575         msg_Err( p_vlc, "interface initialization failed" );
576         return VLC_EGENERIC;
577     }
578
579     /* Try to run the interface */
580     p_intf->b_block = b_block;
581     err = intf_RunThread( p_intf );
582     if( err )
583     {
584         vlc_object_detach_all( p_intf );
585         intf_Destroy( p_intf );
586         return err;
587     }
588
589     return VLC_SUCCESS;
590 }
591
592 /*****************************************************************************
593  * vlc_stop: stop playing.
594  *****************************************************************************
595  * This function requests the interface threads to finish, waits for their
596  * termination, and destroys their structure.
597  *****************************************************************************/
598 vlc_error_t vlc_stop( vlc_t *p_vlc )
599 {
600     intf_thread_t *p_intf;
601     playlist_t    *p_playlist;
602     vout_thread_t *p_vout;
603     aout_thread_t *p_aout;
604
605     /* Check that the handle is valid */
606     if( !p_vlc || p_vlc->i_status != VLC_STATUS_RUNNING )
607     {
608         fprintf( stderr, "error: invalid status (!RUNNING)\n" );
609         return VLC_ESTATUS;
610     }
611
612     /*
613      * Ask the interfaces to stop and destroy them
614      */
615     msg_Dbg( p_vlc, "removing all interfaces" );
616     while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_CHILD )) )
617     {
618         intf_StopThread( p_intf );
619         vlc_object_detach_all( p_intf );
620         vlc_object_release( p_intf );
621         intf_Destroy( p_intf );
622     }
623
624     /*
625      * Free playlists
626      */
627     msg_Dbg( p_vlc, "removing all playlists" );
628     while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
629                                           FIND_CHILD )) )
630     {
631         vlc_object_detach_all( p_playlist );
632         vlc_object_release( p_playlist );
633         playlist_Destroy( p_playlist );
634     }
635
636     /*
637      * Free video outputs
638      */
639     msg_Dbg( p_vlc, "removing all video outputs" );
640     while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
641     {
642         vlc_object_detach_all( p_vout );
643         vlc_object_release( p_vout );
644         vout_DestroyThread( p_vout );
645     }
646
647     /*
648      * Free audio outputs
649      */
650     msg_Dbg( p_vlc, "removing all audio outputs" );
651     while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
652     {
653         vlc_object_detach_all( p_aout );
654         vlc_object_release( p_aout );
655         aout_DestroyThread( p_aout );
656     }
657
658     /* Update the handle status */
659     p_vlc->i_status = VLC_STATUS_STOPPED;
660
661     return VLC_SUCCESS;
662 }
663
664 /*****************************************************************************
665  * vlc_end: uninitialize everything.
666  *****************************************************************************
667  * This function uninitializes every vlc component that was activated in
668  * vlc_init: audio and video outputs, playlist, module bank and message queue.
669  *****************************************************************************/
670 vlc_error_t vlc_end( vlc_t *p_vlc )
671 {
672     /* Check that the handle is valid */
673     if( !p_vlc || p_vlc->i_status != VLC_STATUS_STOPPED )
674     {
675         fprintf( stderr, "error: invalid status (!STOPPED)\n" );
676         return VLC_ESTATUS;
677     }
678
679     /*
680      * Go back into channel 0 which is the network
681      */
682     if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
683     {
684         network_ChannelJoin( p_vlc, COMMON_CHANNEL );
685     }
686
687     /*
688      * Free allocated memory
689      */
690     if( p_vlc->p_memcpy_module != NULL )
691     {
692         module_Unneed( p_vlc->p_memcpy_module );
693     }
694
695     free( p_vlc->psz_homedir );
696
697     /*
698      * Free module bank
699      */
700     module_EndBank( p_vlc );
701
702     /*
703      * System specific cleaning code
704      */
705     system_End( p_vlc );
706
707     /*
708      * Terminate messages interface and program
709      */
710     msg_Destroy( p_vlc );
711
712     /* Update the handle status */
713     p_vlc->i_status = VLC_STATUS_CREATED;
714
715     return VLC_SUCCESS;
716 }
717
718 /*****************************************************************************
719  * vlc_destroy: free allocated resources.
720  *****************************************************************************
721  * This function frees the previously allocated vlc_t structure.
722  *****************************************************************************/
723 vlc_error_t vlc_destroy( vlc_t *p_vlc )
724 {
725     int i_index;
726
727     /* Check that the handle is valid */
728     if( !p_vlc || p_vlc->i_status != VLC_STATUS_CREATED )
729     {
730         fprintf( stderr, "error: invalid status (!CREATED)\n" );
731         return VLC_ESTATUS;
732     }
733
734     /* Update the handle status, just in case */
735     p_vlc->i_status = VLC_STATUS_NONE;
736
737     /* Remove our structure from the global list */
738     vlc_mutex_lock( p_vlc->p_global_lock );
739     for( i_index = 0 ; i_index < i_vlc ; i_index++ )
740     {
741         if( pp_vlc[ i_index ] == p_vlc )
742         {
743             break;
744         }
745     }
746
747     if( i_index == i_vlc )
748     {
749         fprintf( stderr, "error: trying to unregister %p which is not in "
750                          "the list\n", p_vlc );
751         vlc_mutex_unlock( p_vlc->p_global_lock );
752         vlc_object_destroy( p_vlc );
753         return VLC_EGENERIC;
754     }
755
756     for( i_index++ ; i_index < i_vlc ; i_index++ )
757     {
758         pp_vlc[ i_index - 1 ] = pp_vlc[ i_index ];
759     }
760
761     i_vlc--;
762     if( i_vlc )
763     {
764         pp_vlc = realloc( pp_vlc, i_vlc * sizeof( vlc_t * ) );
765     }
766     else
767     {
768         free( pp_vlc );
769         pp_vlc = NULL;
770     }
771     vlc_mutex_unlock( p_vlc->p_global_lock );
772
773     /* Stop thread system: last one out please shut the door! */
774     vlc_threads_end( p_vlc );
775
776     /* Destroy mutexes */
777     vlc_mutex_destroy( &p_vlc->structure_lock );
778     vlc_mutex_destroy( &p_vlc->config_lock );
779
780     vlc_object_destroy( p_vlc );
781
782     return VLC_SUCCESS;
783 }
784
785 vlc_status_t vlc_status( vlc_t *p_vlc )
786 {
787     if( !p_vlc )
788     {
789         return VLC_STATUS_NONE;
790     }
791
792     return p_vlc->i_status;
793 }
794
795 vlc_error_t vlc_add_target( vlc_t *p_vlc, const char *psz_target,
796                                           int i_mode, int i_pos )
797 {
798     vlc_error_t err;
799     playlist_t *p_playlist;
800
801     if( !p_vlc || ( p_vlc->i_status != VLC_STATUS_STOPPED
802                      && p_vlc->i_status != VLC_STATUS_RUNNING ) )
803     {
804         fprintf( stderr, "error: invalid status (!STOPPED&&!RUNNING)\n" );
805         return VLC_ESTATUS;
806     }
807
808     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
809
810     if( p_playlist == NULL )
811     {
812         msg_Dbg( p_vlc, "no playlist present, creating one" );
813         p_playlist = playlist_Create( p_vlc );
814
815         if( p_playlist == NULL )
816         {
817             return VLC_EGENERIC;
818         }
819
820         vlc_object_yield( p_playlist );
821     }
822
823     err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
824
825     vlc_object_release( p_playlist );
826
827     return err;
828 }
829
830 /* following functions are local */
831
832 /*****************************************************************************
833  * GetFilenames: parse command line options which are not flags
834  *****************************************************************************
835  * Parse command line for input files.
836  *****************************************************************************/
837 static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
838 {
839     int i_opt;
840
841     /* We assume that the remaining parameters are filenames */
842     for( i_opt = optind; i_opt < i_argc; i_opt++ )
843     {
844         vlc_add_target( p_vlc, ppsz_argv[ i_opt ],
845                         PLAYLIST_APPEND, PLAYLIST_END );
846     }
847
848     return VLC_SUCCESS;
849 }
850
851 /*****************************************************************************
852  * Usage: print program usage
853  *****************************************************************************
854  * Print a short inline help. Message interface is initialized at this stage.
855  *****************************************************************************/
856 static void Usage( vlc_t *p_this, const char *psz_module_name )
857 {
858 #define FORMAT_STRING "      --%s%s%s%s%s%s%s %s%s\n"
859     /* option name -------------'     | | | |  | |
860      * <bra --------------------------' | | |  | |
861      * option type or "" ---------------' | |  | |
862      * ket> ------------------------------' |  | |
863      * padding spaces ----------------------'  | |
864      * comment --------------------------------' |
865      * comment suffix ---------------------------'
866      *
867      * The purpose of having bra and ket is that we might i18n them as well.
868      */
869 #define LINE_START 8
870 #define PADDING_SPACES 25
871     module_t *p_module;
872     module_config_t *p_item;
873     char psz_spaces[PADDING_SPACES+LINE_START+1];
874     char psz_format[sizeof(FORMAT_STRING)];
875
876     memset( psz_spaces, ' ', PADDING_SPACES+LINE_START );
877     psz_spaces[PADDING_SPACES+LINE_START] = '\0';
878
879     strcpy( psz_format, FORMAT_STRING );
880
881 #ifdef WIN32
882     ShowConsole();
883 #endif
884
885     /* Enumerate the config for each module */
886     for( p_module = p_this->p_vlc->module_bank.first ;
887          p_module != NULL ;
888          p_module = p_module->next )
889     {
890         vlc_bool_t b_help_module = !strcmp( "help", p_module->psz_object_name );
891
892         if( psz_module_name && strcmp( psz_module_name,
893                                        p_module->psz_object_name ) )
894         {
895             continue;
896         }
897
898         /* Ignore modules without config options */
899         if( !p_module->i_config_items )
900         {
901             continue;
902         }
903
904         /* Print module name */
905         fprintf( stderr, _("%s module options:\n\n"),
906                          p_module->psz_object_name );
907
908         for( p_item = p_module->p_config;
909              p_item->i_type != CONFIG_HINT_END;
910              p_item++ )
911         {
912             char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
913             char *psz_suf = "", *psz_prefix = NULL;
914             int i;
915
916             switch( p_item->i_type )
917             {
918             case CONFIG_HINT_CATEGORY:
919             case CONFIG_HINT_USAGE:
920                 fprintf( stderr, " %s\n", p_item->psz_text );
921                 break;
922
923             case CONFIG_ITEM_STRING:
924             case CONFIG_ITEM_FILE:
925             case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
926                 psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
927                 break;
928             case CONFIG_ITEM_INTEGER:
929                 psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
930                 break;
931             case CONFIG_ITEM_FLOAT:
932                 psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
933                 break;
934             case CONFIG_ITEM_BOOL:
935                 psz_bra = ""; psz_type = ""; psz_ket = "";
936                 if( !b_help_module )
937                 {
938                     psz_suf = p_item->i_value ? _(" (default enabled)") :
939                                                 _(" (default disabled)");
940                 }
941                 break;
942             }
943
944             /* Add short option */
945             if( p_item->i_short )
946             {
947                 psz_format[2] = '-';
948                 psz_format[3] = p_item->i_short;
949                 psz_format[4] = ',';
950             }
951             else
952             {
953                 psz_format[2] = ' ';
954                 psz_format[3] = ' ';
955                 psz_format[4] = ' ';
956             }
957
958             if( psz_type )
959             {
960                 i = PADDING_SPACES - strlen( p_item->psz_name )
961                      - strlen( psz_bra ) - strlen( psz_type )
962                      - strlen( psz_ket ) - 1;
963                 if( p_item->i_type == CONFIG_ITEM_BOOL
964                      && !b_help_module )
965                 {
966                     vlc_bool_t b_dash = VLC_FALSE;
967                     psz_prefix = p_item->psz_name;
968                     while( *psz_prefix )
969                     {
970                         if( *psz_prefix++ == '-' )
971                         {
972                             b_dash = VLC_TRUE;
973                             break;
974                         }
975                     }
976
977                     if( b_dash )
978                     {
979                         psz_prefix = ", --no-";
980                         i -= strlen( p_item->psz_name ) + strlen( ", --no-" );
981                     }
982                     else
983                     {
984                         psz_prefix = ", --no";
985                         i -= strlen( p_item->psz_name ) + strlen( ", --no" );
986                     }
987                 }
988
989                 if( i < 0 )
990                 {
991                     i = 0;
992                     psz_spaces[i] = '\n';
993                 }
994                 else
995                 {
996                     psz_spaces[i] = '\0';
997                 }
998
999                 if( p_item->i_type == CONFIG_ITEM_BOOL &&
1000                     !b_help_module )
1001                 {
1002                     fprintf( stderr, psz_format, p_item->psz_name, psz_prefix,
1003                              p_item->psz_name, psz_bra, psz_type, psz_ket,
1004                              psz_spaces, p_item->psz_text, psz_suf );
1005                 }
1006                 else
1007                 {
1008                     fprintf( stderr, psz_format, p_item->psz_name, "", "",
1009                              psz_bra, psz_type, psz_ket, psz_spaces,
1010                              p_item->psz_text, psz_suf );
1011                 }
1012                 psz_spaces[i] = ' ';
1013             }
1014         }
1015
1016         fprintf( stderr, "\n" );
1017
1018     }
1019
1020 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1021         fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1022         getchar();
1023 #endif
1024 }
1025
1026 /*****************************************************************************
1027  * ListModules: list the available modules with their description
1028  *****************************************************************************
1029  * Print a list of all available modules (builtins and plugins) and a short
1030  * description for each one.
1031  *****************************************************************************/
1032 static void ListModules( vlc_t *p_this )
1033 {
1034     module_t *p_module;
1035     char psz_spaces[22];
1036
1037     memset( psz_spaces, ' ', 22 );
1038
1039 #ifdef WIN32
1040     ShowConsole();
1041 #endif
1042
1043     /* Usage */
1044     fprintf( stderr, _("Usage: %s [options] [parameters] [file]...\n\n"),
1045                      p_this->p_vlc->psz_object_name );
1046
1047     fprintf( stderr, _("[module]              [description]\n") );
1048
1049     /* Enumerate each module */
1050     for( p_module = p_this->p_vlc->module_bank.first ;
1051          p_module != NULL ;
1052          p_module = p_module->next )
1053     {
1054         int i;
1055
1056         /* Nasty hack, but right now I'm too tired to think about a nice
1057          * solution */
1058         i = 22 - strlen( p_module->psz_object_name ) - 1;
1059         if( i < 0 ) i = 0;
1060         psz_spaces[i] = 0;
1061
1062         fprintf( stderr, "  %s%s %s\n", p_module->psz_object_name, psz_spaces,
1063                   p_module->psz_longname );
1064
1065         psz_spaces[i] = ' ';
1066
1067     }
1068
1069 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1070         fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1071         getchar();
1072 #endif
1073 }
1074
1075 /*****************************************************************************
1076  * Version: print complete program version
1077  *****************************************************************************
1078  * Print complete program version and build number.
1079  *****************************************************************************/
1080 static void Version( void )
1081 {
1082 #ifdef WIN32
1083     ShowConsole();
1084 #endif
1085
1086     fprintf( stderr, VERSION_MESSAGE "\n" );
1087     fprintf( stderr,
1088       _("This program comes with NO WARRANTY, to the extent permitted by "
1089         "law.\nYou may redistribute it under the terms of the GNU General "
1090         "Public License;\nsee the file named COPYING for details.\n"
1091         "Written by the VideoLAN team at Ecole Centrale, Paris.\n") );
1092
1093 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1094     fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1095     getchar();
1096 #endif
1097 }
1098
1099 /*****************************************************************************
1100  * Build: print information about the vlc build
1101  *****************************************************************************
1102  * Print the ./configure command line and other information.
1103  *****************************************************************************/
1104 static void Build( void )
1105 {
1106 #ifdef WIN32
1107     ShowConsole();
1108 #endif
1109
1110     fprintf( stderr, "configured with %s\n", CONFIGURE_LINE );
1111
1112 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1113     fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1114     getchar();
1115 #endif
1116 }
1117
1118 /*****************************************************************************
1119  * ShowConsole: On Win32, create an output console for debug messages
1120  *****************************************************************************
1121  * This function is useful only on Win32.
1122  *****************************************************************************/
1123 #ifdef WIN32 /*  */
1124 static void ShowConsole( void )
1125 {
1126     AllocConsole();
1127     freopen( "CONOUT$", "w", stdout );
1128     freopen( "CONOUT$", "w", stderr );
1129     freopen( "CONIN$", "r", stdin );
1130     return;
1131 }
1132 #endif
1133
1134 #ifndef WIN32
1135 /*****************************************************************************
1136  * InitSignalHandler: system signal handler initialization
1137  *****************************************************************************
1138  * Set the signal handlers. SIGTERM is not intercepted, because we need at
1139  * at least a method to kill the program when all other methods failed, and
1140  * when we don't want to use SIGKILL.
1141  *****************************************************************************/
1142 static void InitSignalHandler( void )
1143 {
1144     /* Termination signals */
1145     signal( SIGINT,  FatalSignalHandler );
1146     signal( SIGHUP,  FatalSignalHandler );
1147     signal( SIGQUIT, FatalSignalHandler );
1148
1149     /* Other signals */
1150     signal( SIGALRM, SimpleSignalHandler );
1151     signal( SIGPIPE, SimpleSignalHandler );
1152 }
1153
1154 /*****************************************************************************
1155  * SimpleSignalHandler: system signal handler
1156  *****************************************************************************
1157  * This function is called when a non fatal signal is received by the program.
1158  *****************************************************************************/
1159 static void SimpleSignalHandler( int i_signal )
1160 {
1161     int i_index;
1162
1163     /* Acknowledge the signal received and warn all the p_vlc structures */
1164     vlc_mutex_lock( &global_lock );
1165     for( i_index = 0 ; i_index < i_vlc ; i_index++ )
1166     {
1167         msg_Warn( pp_vlc[ i_index ], "ignoring signal %d", i_signal );
1168     }
1169     vlc_mutex_unlock( &global_lock );
1170 }
1171
1172 /*****************************************************************************
1173  * FatalSignalHandler: system signal handler
1174  *****************************************************************************
1175  * This function is called when a fatal signal is received by the program.
1176  * It tries to end the program in a clean way.
1177  *****************************************************************************/
1178 static void FatalSignalHandler( int i_signal )
1179 {
1180     static mtime_t abort_time = 0;
1181     static volatile vlc_bool_t b_die = VLC_FALSE;
1182     int i_index;
1183
1184     /* Once a signal has been trapped, the termination sequence will be
1185      * armed and following signals will be ignored to avoid sending messages
1186      * to an interface having been destroyed */
1187
1188     if( !b_die )
1189     {
1190         b_die = VLC_TRUE;
1191         abort_time = mdate();
1192
1193         fprintf( stderr, "signal %d received, terminating libvlc - do it "
1194                          "again in case your process gets stuck\n", i_signal );
1195
1196         /* Try to terminate everything - this is done by requesting the end of
1197          * all the p_vlc structures */
1198         for( i_index = 0 ; i_index < i_vlc ; i_index++ )
1199         {
1200             /* Acknowledge the signal received */
1201             pp_vlc[ i_index ]->b_die = VLC_TRUE;
1202         }
1203     }
1204     else if( mdate() > abort_time + 1000000 )
1205     {
1206         /* If user asks again 1 second later, die badly */
1207         signal( SIGINT,  SIG_IGN );
1208         signal( SIGHUP,  SIG_IGN );
1209         signal( SIGQUIT, SIG_IGN );
1210
1211         fprintf( stderr, "user insisted too much, dying badly\n" );
1212
1213         exit( 1 );
1214     }
1215 }
1216 #endif
1217