1 /*****************************************************************************
2 * main.c: main vlc source
3 * Includes the main() function for vlc. Parses command line, start interface
5 *****************************************************************************
6 * Copyright (C) 1998-2001 VideoLAN
7 * $Id: main.c,v 1.159 2002/03/04 22:18:25 gbazin Exp $
9 * Authors: Vincent Seguin <seguin@via.ecp.fr>
10 * Samuel Hocevar <sam@zoy.org>
11 * Gildas Bazin <gbazin@netcourrier.com>
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.
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.
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 *****************************************************************************/
28 /*****************************************************************************
30 *****************************************************************************/
31 #include <signal.h> /* SIGHUP, SIGINT, SIGKILL */
32 #include <stdio.h> /* sprintf() */
33 #include <setjmp.h> /* longjmp, setjmp */
35 #include <videolan/vlc.h>
37 #ifdef HAVE_GETOPT_LONG
39 # include <getopt.h> /* getopt() */
42 # include "GNUgetopt/getopt.h"
46 # include <mach/mach.h> /* Altivec detection */
47 # include <mach/mach_error.h> /* some day the header files||compiler *
48 will define it for us */
49 # include <mach/bootstrap.h>
53 # include <netinet/in.h> /* BSD: struct in_addr */
58 #elif defined( _MSC_VER ) && defined( _WIN32 )
66 #include <errno.h> /* ENOMEM */
67 #include <stdlib.h> /* getenv(), strtol(), */
68 #include <string.h> /* strerror() */
69 #include <fcntl.h> /* open(), O_WRONLY */
70 #include <sys/stat.h> /* S_IREAD */
72 #include "netutils.h" /* network_ChannelJoin */
74 #include "stream_control.h"
75 #include "input_ext-intf.h"
77 #include "intf_playlist.h"
78 #include "interface.h"
80 #include "audio_output.h"
83 #include "video_output.h"
87 /*****************************************************************************
88 * Configuration options for the main program. Each plugin will also separatly
89 * define its own configuration options.
90 * Look into configuration.h if you need to know more about the following
93 *****************************************************************************/
95 #define MODULE_NAME main
96 #include "modules_inner.h" /* for configuration stuff */
101 ADD_CATEGORY_HINT( text, longtext )
102 ADD_SUBCATEGORY_HINT( text, longtext )
103 ADD_STRING( option_name, value, p_callback, text, longtext )
104 ADD_FILE( option_name, psz_value, p_callback, text, longtext )
105 ADD_PLUGIN( option_name, psz_value, i_capability, p_callback, text, longtext )
106 ADD_INTEGER( option_name, i_value, p_callback, text, longtext )
107 ADD_BOOL( option_name, p_callback, text, longtext )
113 ADD_CATEGORY_HINT( "Help Options", NULL )
114 ADD_BOOL ( "help", NULL,"print help and exit (or use -h)", NULL )
115 ADD_BOOL ( "longhelp", NULL, "print long help version and exit (or use -H)",
117 ADD_BOOL ( "list", NULL, "list available plugins (or use -l)", NULL )
118 ADD_STRING ( "pluginhelp", NULL, NULL,"print help on a plugin and exit",NULL )
119 ADD_BOOL ( "version", NULL, "output version information and exit", NULL )
121 /* Interface options */
122 ADD_CATEGORY_HINT( "Interface Options", NULL)
123 ADD_PLUGIN ( INTF_METHOD_VAR, MODULE_CAPABILITY_INTF, NULL, NULL,
124 "interface method", NULL )
125 ADD_INTEGER ( INTF_WARNING_VAR, 0, NULL, "warning level (or use -v)", NULL )
126 ADD_BOOL ( INTF_STATS_VAR, NULL, "output statistics", NULL )
127 ADD_STRING ( INTF_PATH_VAR, NULL, NULL, "interface default search path", NULL)
130 ADD_CATEGORY_HINT( "Audio Options", NULL)
131 ADD_BOOL ( AOUT_NOAUDIO_VAR, NULL, "disable audio", NULL )
132 ADD_PLUGIN ( AOUT_METHOD_VAR, MODULE_CAPABILITY_AOUT, NULL, NULL,
133 "audio output method", NULL )
134 ADD_BOOL ( AOUT_MONO_VAR, NULL, "mono audio", NULL )
135 ADD_INTEGER ( AOUT_VOLUME_VAR, VOLUME_DEFAULT, NULL, "VLC output volume", NULL)
136 ADD_INTEGER ( AOUT_RATE_VAR, 44100, NULL, "VLC output frequency", NULL )
137 ADD_INTEGER ( AOUT_DESYNC_VAR, 0, NULL, "Compensate desynchronization of the "
138 "audio (in ms)", NULL )
141 ADD_CATEGORY_HINT( "Video Options", NULL )
142 ADD_BOOL ( VOUT_NOVIDEO_VAR, NULL, "disable video", NULL )
143 ADD_PLUGIN ( VOUT_METHOD_VAR, MODULE_CAPABILITY_VOUT, NULL, NULL,
144 "video output method", NULL )
145 ADD_STRING ( VOUT_DISPLAY_VAR, NULL, NULL, "display string", NULL )
146 ADD_INTEGER ( VOUT_WIDTH_VAR, 720, NULL, "display width", NULL )
147 ADD_INTEGER ( VOUT_HEIGHT_VAR, 576, NULL, "display height", NULL )
148 ADD_BOOL ( VOUT_GRAYSCALE_VAR, NULL, "grayscale output", NULL )
149 ADD_BOOL ( VOUT_FULLSCREEN_VAR, NULL, "fullscreen output", NULL )
150 ADD_BOOL ( VOUT_NOOVERLAY_VAR, NULL, "disable accelerated display", NULL )
151 ADD_PLUGIN ( VOUT_FILTER_VAR, MODULE_CAPABILITY_VOUT, NULL, NULL,
152 "video filter module", NULL )
153 ADD_INTEGER ( VOUT_SPUMARGIN_VAR, -1, NULL, "force SPU position", NULL )
156 ADD_CATEGORY_HINT( "Input Options", NULL )
157 ADD_STRING ( INPUT_METHOD_VAR, NULL, NULL, "input method", NULL )
158 ADD_INTEGER ( INPUT_PORT_VAR, 1234, NULL, "server port", NULL )
159 ADD_BOOL ( INPUT_NETWORK_CHANNEL_VAR, NULL, "enable network channel mode",
161 ADD_STRING ( INPUT_CHANNEL_SERVER_VAR, "localhost", NULL,
162 "channel server address", NULL )
163 ADD_INTEGER ( INPUT_CHANNEL_PORT_VAR, 6010, NULL, "channel server port", NULL )
164 ADD_STRING ( INPUT_IFACE_VAR, "eth0", NULL, "network interface", NULL )
166 ADD_INTEGER ( INPUT_AUDIO_VAR, -1, NULL, "choose audio", NULL )
167 ADD_INTEGER ( INPUT_CHANNEL_VAR, -1, NULL, "choose channel", NULL )
168 ADD_INTEGER ( INPUT_SUBTITLE_VAR, -1, NULL, "choose subtitles", NULL )
170 ADD_STRING ( INPUT_DVD_DEVICE_VAR, "/dev/dvd", NULL, "DVD device", NULL )
171 ADD_STRING ( INPUT_VCD_DEVICE_VAR, "/dev/cdrom", NULL, "VCD device", NULL )
173 /* Decoder options */
174 ADD_CATEGORY_HINT( "Decoders Options", NULL )
175 ADD_PLUGIN ( ADEC_MPEG_VAR, MODULE_CAPABILITY_DECODER, NULL, NULL,
176 "choose MPEG audio decoder", NULL )
177 ADD_PLUGIN ( ADEC_AC3_VAR, MODULE_CAPABILITY_DECODER, NULL, NULL,
178 "choose AC3 audio decoder", NULL )
179 ADD_INTEGER ( VDEC_SMP_VAR, 0, NULL, "use additional processors", NULL )
180 ADD_STRING ( VPAR_SYNCHRO_VAR, NULL, NULL, "force synchro algorithm "
181 "{I|I+|IP|IP+|IPB}", NULL )
184 ADD_CATEGORY_HINT( "CPU Options Options", NULL )
185 ADD_BOOL ( NOMMX_VAR, NULL, "disable CPU's MMX support", NULL )
186 ADD_BOOL ( NO3DN_VAR, NULL, "disable CPU's 3D Now! support", NULL )
187 ADD_BOOL ( NOMMXEXT_VAR, NULL, "disable CPU's MMX EXT support", NULL )
188 ADD_BOOL ( NOSSE_VAR, NULL, "disable CPU's SSE support", NULL )
189 ADD_BOOL ( NOALTIVEC_VAR, NULL, "disable CPU's AltiVec support", NULL )
191 /* Playlist options */
192 ADD_BOOL ( PLAYLIST_STARTUP_VAR, NULL, "launch playlist on startup", NULL )
193 ADD_BOOL ( PLAYLIST_ENQUEUE_VAR, NULL, "enqueue playlist as default", NULL )
194 ADD_BOOL ( PLAYLIST_LOOP_VAR, NULL, "loop on playlist end", NULL )
197 ADD_CATEGORY_HINT( "Miscellaneous Options", NULL )
198 ADD_PLUGIN ( MEMCPY_METHOD_VAR, MODULE_CAPABILITY_MEMCPY, NULL, NULL,
199 "memory copy method", NULL )
204 SET_DESCRIPTION( "Main program" )
205 ADD_CAPABILITY( MAIN, 100/*whatever*/ )
208 MODULE_ACTIVATE_START
211 MODULE_DEACTIVATE_START
212 MODULE_DEACTIVATE_STOP
213 /*****************************************************************************
215 *****************************************************************************/
217 /*****************************************************************************
218 * Global variables - these are the only ones, see main.h and modules.h
219 *****************************************************************************/
221 module_bank_t *p_module_bank;
222 input_bank_t *p_input_bank;
223 aout_bank_t *p_aout_bank;
224 vout_bank_t *p_vout_bank;
226 /*****************************************************************************
228 *****************************************************************************/
229 static int GetConfigurationFromFile ( void ){return 0;};
230 static int GetConfigurationFromCmdLine ( int *pi_argc, char *ppsz_argv[],
231 boolean_t b_ignore_errors );
232 static int GetFilenames ( int i_argc, char *ppsz_argv[] );
233 static void Usage ( const char *psz_module_name );
234 static void ListModules ( void );
235 static void Version ( void );
237 static void InitSignalHandler ( void );
238 static void SimpleSignalHandler ( int i_signal );
239 static void FatalSignalHandler ( int i_signal );
240 static void IllegalSignalHandler ( int i_signal );
241 static u32 CPUCapabilities ( void );
244 static void ShowConsole ( void );
248 static int i_illegal;
249 static char *psz_capability;
251 /*****************************************************************************
252 * main: parse command line, start interface and spawn threads
253 *****************************************************************************
254 * Steps during program execution are:
255 * -configuration parsing and messages interface initialization
256 * -opening of audio output device and some global modules
257 * -execution of interface, which exit on error or on user request
258 * -closing of audio output device and some global modules
259 * On error, the spawned threads are canceled, and the open devices closed.
260 *****************************************************************************/
261 int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
263 main_t main_data; /* root of all data - see main.h */
264 module_bank_t module_bank;
265 input_bank_t input_bank;
266 aout_bank_t aout_bank;
267 vout_bank_t vout_bank;
270 p_main = &main_data; /* set up the global variables */
271 p_module_bank = &module_bank;
272 p_input_bank = &input_bank;
273 p_aout_bank = &aout_bank;
274 p_vout_bank = &vout_bank;
276 p_main->i_warning_level = 0;
278 #if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
282 #if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
283 if( !setlocale( LC_MESSAGES, "" ) )
285 fprintf( stderr, "warning: unsupported locale.\n" );
289 if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
291 fprintf( stderr, "warning: no domain %s in directory %s\n",
292 PACKAGE, LOCALEDIR );
295 textdomain( PACKAGE );
299 * Initialize threads system
304 * Test if our code is likely to run on this CPU
306 p_main->i_cpu_capabilities = CPUCapabilities();
309 * System specific initialization code
311 #if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
312 system_Init( &i_argc, ppsz_argv, ppsz_env );
314 #elif defined( SYS_LINUX )
316 /* Activate malloc checking routines to detect heap corruptions. */
317 putenv( "MALLOC_CHECK_=2" );
322 * Initialize messages interface
326 intf_Msg( COPYRIGHT_MESSAGE "\n" );
329 /* Get the executable name (similar to the basename command) */
330 p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
333 if( *p_tmp == '/' ) p_main->psz_arg0 = ++p_tmp;
338 * Initialize the module bank and and load the configuration of the main
339 * module. We need to do this at this stage to be able to display a short
340 * help if required by the user. (short help == main module options)
345 if( GetConfigurationFromCmdLine( &i_argc, ppsz_argv, 1 ) )
351 /* Check for short help option */
352 if( config_GetIntVariable( "help" ) )
358 /* Check for version option */
359 if( config_GetIntVariable( "version" ) )
366 * Load the builtins and plugins into the module_bank.
367 * We have to do it before GetConfiguration() because this also gets the
368 * list of configuration options exported by each plugin and loads their
371 module_LoadBuiltins();
372 module_LoadPlugins();
373 intf_WarnMsg( 2, "module: module bank initialized, found %i modules",
374 p_module_bank->i_count );
376 /* Check for help on plugins */
377 if( (p_tmp = config_GetPszVariable( "pluginhelp" )) )
384 /* Check for long help option */
385 if( config_GetIntVariable( "longhelp" ) )
391 /* Check for plugin list option */
392 if( config_GetIntVariable( "list" ) )
399 * Override default configuration with config file settings
401 if( GetConfigurationFromFile() )
408 * Override configuration with command line settings
410 if( GetConfigurationFromCmdLine( &i_argc, ppsz_argv, 0 ) )
416 /* p_main inititalization. FIXME ? */
417 p_main->i_desync = (mtime_t)config_GetIntVariable( AOUT_DESYNC_VAR )
419 p_main->b_stats = config_GetIntVariable( INTF_STATS_VAR );
420 p_main->b_audio = !config_GetIntVariable( AOUT_NOAUDIO_VAR );
421 p_main->b_stereo= !config_GetIntVariable( AOUT_MONO_VAR );
422 p_main->b_video = !config_GetIntVariable( VOUT_NOVIDEO_VAR );
423 if( config_GetIntVariable( NOMMX_VAR ) )
424 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMX;
425 if( config_GetIntVariable( NO3DN_VAR ) )
426 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_3DNOW;
427 if( config_GetIntVariable( NOMMXEXT_VAR ) )
428 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMXEXT;
429 if( config_GetIntVariable( NOSSE_VAR ) )
430 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_SSE;
431 if( config_GetIntVariable( NOALTIVEC_VAR ) )
432 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_ALTIVEC;
435 if( p_main->b_stats )
437 char p_capabilities[200];
438 p_capabilities[0] = '\0';
440 #define PRINT_CAPABILITY( capability, string ) \
441 if( p_main->i_cpu_capabilities & capability ) \
443 strncat( p_capabilities, string " ", \
444 sizeof(p_capabilities) - strlen(p_capabilities) ); \
445 p_capabilities[sizeof(p_capabilities) - 1] = '\0'; \
448 PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
449 PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
450 PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
451 PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
452 PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
453 PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
454 PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
455 PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "Altivec" );
456 PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
457 intf_StatMsg( "info: CPU has capabilities : %s", p_capabilities );
461 * Initialize playlist and get commandline files
463 p_main->p_playlist = intf_PlaylistCreate();
464 if( !p_main->p_playlist )
466 intf_ErrMsg( "playlist error: playlist initialization failed" );
470 intf_PlaylistInit( p_main->p_playlist );
473 * Get input filenames given as commandline arguments
475 GetFilenames( i_argc, ppsz_argv );
478 * Initialize input, aout and vout banks
485 * Choose the best memcpy module
487 p_main->p_memcpy_module = module_Need( MODULE_CAPABILITY_MEMCPY, NULL,
489 if( p_main->p_memcpy_module == NULL )
491 intf_ErrMsg( "intf error: no suitable memcpy module, "
492 "using libc default" );
493 p_main->pf_memcpy = memcpy;
497 p_main->pf_memcpy = p_main->p_memcpy_module->p_functions
498 ->memcpy.functions.memcpy.pf_memcpy;
502 * Initialize shared resources and libraries
504 if( config_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR ) &&
505 network_ChannelCreate() )
507 /* On error during Channels initialization, switch off channels */
508 intf_ErrMsg( "intf error: channels initialization failed, "
509 "deactivating channels" );
510 config_PutIntVariable( INPUT_NETWORK_CHANNEL_VAR, 0 );
514 * Try to run the interface
516 p_main->p_intf = intf_Create();
517 if( p_main->p_intf == NULL )
519 intf_ErrMsg( "intf error: interface initialization failed" );
524 * Set signal handling policy for all threads
529 * This is the main loop
531 p_main->p_intf->pf_run( p_main->p_intf );
534 * Finished, destroy the interface
536 intf_Destroy( p_main->p_intf );
539 * Go back into channel 0 which is the network
541 if( config_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR ) )
543 network_ChannelJoin( COMMON_CHANNEL );
548 * Free input, aout and vout banks
557 intf_PlaylistDestroy( p_main->p_playlist );
560 * Free memcpy module if it was allocated
562 if( p_main->p_memcpy_module != NULL )
564 module_Unneed( p_main->p_memcpy_module );
573 * System specific cleaning code
575 #if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
581 * Terminate messages interface and program
583 intf_WarnMsg( 1, "intf: program terminated" );
587 * Stop threads system
595 /* following functions are local */
597 /*****************************************************************************
598 * GetConfigurationFromCmdLine: parse command line
599 *****************************************************************************
600 * Parse command line for configuration. If the inline help is requested, the
601 * function Usage() is called and the function returns -1 (causing main() to
603 * Now that the module_bank has been initialized, we can dynamically
604 * generate the longopts structure used by getops. We have to do it this way
605 * because we don't know (and don't want to know) in advance the configuration
606 * options used (ie. exported) by each module.
607 *****************************************************************************/
608 static int GetConfigurationFromCmdLine( int *pi_argc, char *ppsz_argv[],
609 boolean_t b_ignore_errors )
611 int i_cmd, i, i_index, i_longopts_size;
613 struct option *p_longopts;
616 const char *psz_shortopts = "hHvl";
619 /* Set default configuration and copy arguments */
620 p_main->i_argc = *pi_argc;
621 p_main->ppsz_argv = ppsz_argv;
623 p_main->p_channel = NULL;
626 /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
627 * is the PSN - process serial number (a unique PID-ish thingie)
628 * still ok for real Darwin & when run from command line */
629 if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
630 /* for example -psn_0_9306113 */
632 /* GDMF!... I can't do this or else the MacOSX window server will
633 * not pick up the PSN and not register the app and we crash...
634 * hence the following kludge otherwise we'll get confused w/ argv[1]
635 * being an input file name */
637 ppsz_argv[ 1 ] = NULL;
639 *pi_argc = *pi_argc - 1;
647 * Generate the longopts structure used by getopt_long
650 for( p_module = p_module_bank->first ;
652 p_module = p_module->next )
654 /* count the number of exported configuration options (to allocate
655 * longopts). The i_config_options we use is an approximation of the
656 * real number of options (it also includes markers like: category ...)
657 * but it is enough for our purpose */
658 i_longopts_size += p_module->i_config_options -1;
661 p_longopts = (struct option *)malloc( sizeof(struct option)
662 * (i_longopts_size + 1) );
663 if( p_longopts == NULL )
665 intf_ErrMsg( "GetConfigurationFromCmdLine error: "
666 "can't allocate p_longopts" );
670 /* Fill the longopts structure */
672 for( p_module = p_module_bank->first ;
674 p_module = p_module->next )
676 for( i = 1; i < (p_module->i_config_options -1); i++ )
678 if( (p_module->p_config[i].i_type == MODULE_CONFIG_ITEM_CATEGORY)||
679 (p_module->p_config[i].i_type ==
680 MODULE_CONFIG_ITEM_SUBCATEGORY)||
681 (p_module->p_config[i].i_type ==
682 MODULE_CONFIG_ITEM_SUBCATEGORY_END) )
684 p_longopts[i_index].name = p_module->p_config[i].psz_name;
685 p_longopts[i_index].has_arg =
686 (p_module->p_config[i].i_type == MODULE_CONFIG_ITEM_BOOL)?
687 no_argument : required_argument;
688 p_longopts[i_index].flag = 0;
689 p_longopts[i_index].val = 0;
693 /* Close the longopts structure */
694 memset( &p_longopts[i_index], 0, sizeof(struct option) );
698 * Parse the command line options
702 while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv, psz_shortopts,
703 p_longopts, &i_index ) ) != EOF )
708 /* A long option has been recognized */
710 module_config_t *p_conf;
712 /* Store the configuration option */
713 p_conf = config_FindConfig( p_longopts[i_index].name );
715 switch( p_conf->i_type )
717 case MODULE_CONFIG_ITEM_STRING:
718 case MODULE_CONFIG_ITEM_FILE:
719 case MODULE_CONFIG_ITEM_PLUGIN:
720 config_PutPszVariable( p_longopts[i_index].name, optarg );
722 case MODULE_CONFIG_ITEM_INTEGER:
723 config_PutIntVariable( p_longopts[i_index].name, atoi(optarg));
725 case MODULE_CONFIG_ITEM_BOOL:
726 config_PutIntVariable( p_longopts[i_index].name, 1 );
733 /* short options handled here for now */
737 /* General/common options */
738 case 'h': /* -h, --help */
739 config_PutIntVariable( "help", 1 );
741 case 'H': /* -H, --longhelp */
742 config_PutIntVariable( "longhelp", 1 );
744 case 'l': /* -l, --list */
745 config_PutIntVariable( "list", 1 );
747 case 'v': /* -v, --verbose */
748 p_main->i_warning_level++;
751 /* Internal error: unknown option */
754 if( !b_ignore_errors )
756 intf_ErrMsg( "intf error: unknown option `%s'",
758 intf_Msg( "Try `%s --help' for more information.\n",
761 #ifdef WIN32 /* Pause the console because it's destroyed when we exit */
762 intf_Msg( "\nPress the RETURN key to continue..." );
773 if( p_main->i_warning_level < 0 )
775 p_main->i_warning_level = 0;
782 /*****************************************************************************
783 * GetFilenames: parse command line options which are not flags
784 *****************************************************************************
785 * Parse command line for input files.
786 *****************************************************************************/
787 static int GetFilenames( int i_argc, char *ppsz_argv[] )
791 /* We assume that the remaining parameters are filenames */
792 for( i_opt = optind; i_opt < i_argc; i_opt++ )
794 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
795 ppsz_argv[ i_opt ] );
801 /*****************************************************************************
802 * Usage: print program usage
803 *****************************************************************************
804 * Print a short inline help. Message interface is initialized at this stage.
805 *****************************************************************************/
806 static void Usage( const char *psz_module_name )
812 memset( psz_spaces, 32, 30 );
819 intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
822 /* Enumerate the config of each module */
823 for( p_module = p_module_bank->first ;
825 p_module = p_module->next )
828 if( psz_module_name && strcmp( psz_module_name, p_module->psz_name ) )
831 /* print module name */
832 intf_Msg( "%s configuration:\n", p_module->psz_name );
834 for( i = 0; i < (p_module->i_config_options -1); i++ )
838 switch( p_module->p_config[i].i_type )
840 case MODULE_CONFIG_ITEM_CATEGORY:
841 intf_Msg( " %s", p_module->p_config[i].psz_text );
844 case MODULE_CONFIG_ITEM_STRING:
845 case MODULE_CONFIG_ITEM_FILE:
846 case MODULE_CONFIG_ITEM_PLUGIN:
847 /* Nasty hack, but right now I'm too tired to think about
849 j = 25 - strlen( p_module->p_config[i].psz_name )
850 - strlen(" <string>") - 1;
851 if( j < 0 ) j = 0; psz_spaces[j] = 0;
853 intf_Msg( " --%s <string>%s %s",
854 p_module->p_config[i].psz_name, psz_spaces,
855 p_module->p_config[i].psz_text );
858 case MODULE_CONFIG_ITEM_INTEGER:
859 /* Nasty hack, but right now I'm too tired to think about
861 j = 25 - strlen( p_module->p_config[i].psz_name )
862 - strlen(" <integer>") - 1;
863 if( j < 0 ) j = 0; psz_spaces[j] = 0;
865 intf_Msg( " --%s <integer>%s %s",
866 p_module->p_config[i].psz_name, psz_spaces,
867 p_module->p_config[i].psz_text );
871 /* Nasty hack, but right now I'm too tired to think about
873 j = 25 - strlen( p_module->p_config[i].psz_name ) - 1;
874 if( j < 0 ) j = 0; psz_spaces[j] = 0;
876 intf_Msg( " --%s%s %s",
877 p_module->p_config[i].psz_name, psz_spaces,
878 p_module->p_config[i].psz_text );
884 /* Yet another nasty hack.
885 * Maybe we could use MODULE_CONFIG_ITEM_END to display tail messages
886 * for each module?? */
887 if( !strcmp( "main", p_module->psz_name ) )
888 intf_Msg( "\nPlaylist items:"
889 "\n *.mpg, *.vob \tPlain MPEG-1/2 files"
890 "\n [dvd:][device][@raw_device][@[title][,[chapter][,angle]]]"
892 "\n vcd:<device> \tVCD device"
893 "\n udpstream:[<server>[:<server port>]][@[<bind address>]"
895 "\n \tUDP stream sent by VLS"
896 "\n vlc:loop \tLoop execution of the "
898 "\n vlc:pause \tPause execution of "
900 "\n vlc:quit \tQuit VLC" );
906 #ifdef WIN32 /* Pause the console because it's destroyed when we exit */
907 intf_Msg( "\nPress the RETURN key to continue..." );
912 /*****************************************************************************
913 * ListModules: list the available modules with their description
914 *****************************************************************************
915 * Print a list of all available modules (builtins and plugins) and a short
916 * description for each one.
917 *****************************************************************************/
918 static void ListModules( void )
923 memset( psz_spaces, 32, 20 );
930 intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
933 intf_Msg( "[plugin] [description]" );
935 /* Enumerate each module */
936 for( p_module = p_module_bank->first ;
938 p_module = p_module->next )
942 /* Nasty hack, but right now I'm too tired to think about a nice
944 i = 20 - strlen( p_module->psz_name ) - 1;
948 intf_Msg( " %s%s %s", p_module->psz_name, psz_spaces,
949 p_module->psz_longname );
955 #ifdef WIN32 /* Pause the console because it's destroyed when we exit */
956 intf_Msg( "\nPress the RETURN key to continue..." );
961 /*****************************************************************************
962 * Version: print complete program version
963 *****************************************************************************
964 * Print complete program version and build number.
965 *****************************************************************************/
966 static void Version( void )
971 intf_Msg( VERSION_MESSAGE
972 "This program comes with NO WARRANTY, to the extent permitted by law.\n"
973 "You may redistribute it under the terms of the GNU General Public License;\n"
974 "see the file named COPYING for details.\n"
975 "Written by the VideoLAN team at Ecole Centrale, Paris." );
976 #ifdef WIN32 /* Pause the console because it's destroyed when we exit */
977 intf_Msg( "\nPress the RETURN key to continue..." );
982 /*****************************************************************************
983 * InitSignalHandler: system signal handler initialization
984 *****************************************************************************
985 * Set the signal handlers. SIGTERM is not intercepted, because we need at
986 * at least a method to kill the program when all other methods failed, and
987 * when we don't want to use SIGKILL.
988 *****************************************************************************/
989 static void InitSignalHandler( void )
991 /* Termination signals */
993 signal( SIGINT, FatalSignalHandler );
994 signal( SIGHUP, FatalSignalHandler );
995 signal( SIGQUIT, FatalSignalHandler );
998 signal( SIGALRM, SimpleSignalHandler );
999 signal( SIGPIPE, SimpleSignalHandler );
1003 /*****************************************************************************
1004 * SimpleSignalHandler: system signal handler
1005 *****************************************************************************
1006 * This function is called when a non fatal signal is received by the program.
1007 *****************************************************************************/
1008 static void SimpleSignalHandler( int i_signal )
1010 /* Acknowledge the signal received */
1011 intf_WarnMsg( 0, "intf: ignoring signal %d", i_signal );
1014 /*****************************************************************************
1015 * FatalSignalHandler: system signal handler
1016 *****************************************************************************
1017 * This function is called when a fatal signal is received by the program.
1018 * It tries to end the program in a clean way.
1019 *****************************************************************************/
1020 static void FatalSignalHandler( int i_signal )
1022 /* Once a signal has been trapped, the termination sequence will be
1023 * armed and following signals will be ignored to avoid sending messages
1024 * to an interface having been destroyed */
1026 signal( SIGINT, SIG_IGN );
1027 signal( SIGHUP, SIG_IGN );
1028 signal( SIGQUIT, SIG_IGN );
1031 /* Acknowledge the signal received */
1032 intf_ErrMsg( "intf error: signal %d received, exiting", i_signal );
1034 /* Try to terminate everything - this is done by requesting the end of the
1035 * interface thread */
1036 p_main->p_intf->b_die = 1;
1039 /*****************************************************************************
1040 * IllegalSignalHandler: system signal handler
1041 *****************************************************************************
1042 * This function is called when an illegal instruction signal is received by
1043 * the program. We use this function to test OS and CPU capabilities
1044 *****************************************************************************/
1045 static void IllegalSignalHandler( int i_signal )
1047 /* Acknowledge the signal received */
1050 #ifdef HAVE_SIGRELSE
1051 sigrelse( i_signal );
1054 fprintf( stderr, "warning: your CPU has %s instructions, but not your "
1055 "operating system.\n", psz_capability );
1056 fprintf( stderr, " some optimizations will be disabled unless "
1057 "you upgrade your OS\n" );
1059 fprintf( stderr, " (for instance Linux kernel 2.4.x or later)" );
1065 /*****************************************************************************
1066 * CPUCapabilities: list the processors MMX support and other capabilities
1067 *****************************************************************************
1068 * This function is called to list extensions the CPU may have.
1069 *****************************************************************************/
1070 static u32 CPUCapabilities( void )
1072 volatile u32 i_capabilities = CPU_CAPABILITY_NONE;
1074 #if defined( SYS_DARWIN )
1075 struct host_basic_info hi;
1077 host_name_port_t host;
1080 char *psz_name, *psz_subname;
1082 i_capabilities |= CPU_CAPABILITY_FPU;
1084 /* Should 'never' fail? */
1085 host = mach_host_self();
1087 i_size = sizeof( hi ) / sizeof( int );
1088 ret = host_info( host, HOST_BASIC_INFO, ( host_info_t )&hi, &i_size );
1090 if( ret != KERN_SUCCESS )
1092 fprintf( stderr, "error: couldn't get CPU information\n" );
1093 return( i_capabilities );
1096 slot_name( hi.cpu_type, hi.cpu_subtype, &psz_name, &psz_subname );
1097 /* FIXME: need better way to detect newer proccessors.
1098 * could do strncmp(a,b,5), but that's real ugly */
1099 if( !strcmp(psz_name, "ppc7400") || !strcmp(psz_name, "ppc7450") )
1101 i_capabilities |= CPU_CAPABILITY_ALTIVEC;
1104 return( i_capabilities );
1106 #elif defined( __i386__ )
1107 volatile unsigned int i_eax, i_ebx, i_ecx, i_edx;
1108 volatile boolean_t b_amd;
1110 /* Needed for x86 CPU capabilities detection */
1111 # define cpuid( a ) \
1112 asm volatile ( "pushl %%ebx\n\t" \
1114 "movl %%ebx,%1\n\t" \
1123 i_capabilities |= CPU_CAPABILITY_FPU;
1125 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1126 signal( SIGILL, IllegalSignalHandler );
1129 /* test for a 486 CPU */
1130 asm volatile ( "pushl %%ebx\n\t"
1133 "movl %%eax, %%ebx\n\t"
1134 "xorl $0x200000, %%eax\n\t"
1146 if( i_eax == i_ebx )
1148 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1149 signal( SIGILL, NULL );
1151 return( i_capabilities );
1154 i_capabilities |= CPU_CAPABILITY_486;
1156 /* the CPU supports the CPUID instruction - get its level */
1157 cpuid( 0x00000000 );
1161 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1162 signal( SIGILL, NULL );
1164 return( i_capabilities );
1167 /* FIXME: this isn't correct, since some 486s have cpuid */
1168 i_capabilities |= CPU_CAPABILITY_586;
1170 /* borrowed from mpeg2dec */
1171 b_amd = ( i_ebx == 0x68747541 ) && ( i_ecx == 0x444d4163 )
1172 && ( i_edx == 0x69746e65 );
1174 /* test for the MMX flag */
1175 cpuid( 0x00000001 );
1177 if( ! (i_edx & 0x00800000) )
1179 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1180 signal( SIGILL, NULL );
1182 return( i_capabilities );
1185 i_capabilities |= CPU_CAPABILITY_MMX;
1187 if( i_edx & 0x02000000 )
1189 i_capabilities |= CPU_CAPABILITY_MMXEXT;
1191 # ifdef CAN_COMPILE_SSE
1192 /* We test if OS support the SSE instructions */
1193 psz_capability = "SSE";
1195 if( setjmp( env ) == 0 )
1197 /* Test a SSE instruction */
1198 __asm__ __volatile__ ( "xorps %%xmm0,%%xmm0\n" : : );
1201 if( i_illegal == 0 )
1203 i_capabilities |= CPU_CAPABILITY_SSE;
1208 /* test for additional capabilities */
1209 cpuid( 0x80000000 );
1211 if( i_eax < 0x80000001 )
1213 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1214 signal( SIGILL, NULL );
1216 return( i_capabilities );
1219 /* list these additional capabilities */
1220 cpuid( 0x80000001 );
1222 # ifdef CAN_COMPILE_3DNOW
1223 if( i_edx & 0x80000000 )
1225 psz_capability = "3D Now!";
1227 if( setjmp( env ) == 0 )
1229 /* Test a 3D Now! instruction */
1230 __asm__ __volatile__ ( "pfadd %%mm0,%%mm0\n" "femms\n" : : );
1233 if( i_illegal == 0 )
1235 i_capabilities |= CPU_CAPABILITY_3DNOW;
1240 if( b_amd && ( i_edx & 0x00400000 ) )
1242 i_capabilities |= CPU_CAPABILITY_MMXEXT;
1245 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1246 signal( SIGILL, NULL );
1248 return( i_capabilities );
1250 #elif defined( __powerpc__ )
1252 i_capabilities |= CPU_CAPABILITY_FPU;
1254 # ifdef CAN_COMPILE_ALTIVEC
1255 signal( SIGILL, IllegalSignalHandler );
1257 psz_capability = "AltiVec";
1259 if( setjmp( env ) == 0 )
1261 asm volatile ("mtspr 256, %0\n\t"
1262 "vand %%v0, %%v0, %%v0"
1267 if( i_illegal == 0 )
1269 i_capabilities |= CPU_CAPABILITY_ALTIVEC;
1272 signal( SIGILL, NULL );
1275 return( i_capabilities );
1278 /* default behaviour */
1279 return( i_capabilities );
1284 /*****************************************************************************
1285 * ShowConsole: On Win32, create an output console for debug messages
1286 *****************************************************************************
1287 * This function is usefull only on Win32.
1288 *****************************************************************************/
1290 static void ShowConsole( void )
1293 freopen( "CONOUT$", "w", stdout );
1294 freopen( "CONOUT$", "w", stderr );
1295 freopen( "CONIN$", "r", stdin );