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