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