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