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.165 2002/03/19 00:30:44 sam 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 */
99 #define INTF_TEXT "interface method"
100 #define INTF_LONGTEXT "This option allows you to select the interface used by"\
101 " vlc.\nNote that the default behaviour is to" \
102 " automatically select the best method available"
104 #define WARNING_TEXT "warning level (or use -v, -vv, etc...)"
105 #define WARNING_LONGTEXT "Increasing the warning level will allow you to see" \
106 " more debug messages and can sometimes help you to" \
107 " troubleshoot a problem"
109 #define STATS_TEXT "output statistics"
110 #define STATS_LONGTEXT "Enabling the stats mode will flood your log console" \
111 " with various statistics messages"
113 #define INTF_PATH_TEXT "interface default search path"
114 #define INTF_PATH_LONGTEXT "This option allows you to set the default path" \
115 "that the interface will open when looking for a" \
118 #define AOUT_TEXT "audio output method"
119 #define AOUT_LONGTEXT "This option allows you to select the audio" \
120 " audio output method used by vlc.\nNote that the" \
121 " default behaviour is to automatically select the best"\
124 #define NOAUDIO_TEXT "disable audio"
125 #define NOAUDIO_LONGTEXT "This will completely disable the audio output. The" \
126 " audio decoding stage shouldn't even be done, so it"\
127 " can allow you to save some processing power"
129 #define MONO_TEXT "mono audio"
130 #define MONO_LONGTEXT "This will force a mono audio output"
132 #define VOLUME_TEXT "audio output volume"
133 #define VOLUME_LONGTEXT "You can set the default audio output volume here," \
134 " in a range from 0 to 1024"
136 #define FORMAT_TEXT "audio output format"
137 #define FORMAT_LONGTEXT "You can force the audio output format here.\n" \
138 "0 -> 16 bits signed native endian (default)\n" \
139 "1 -> 8 bits unsigned\n" \
140 "2 -> 16 bits signed little endian\n" \
141 "3 -> 16 bits signed big endian\n" \
142 "4 -> 8 bits signed\n" \
143 "5 -> 16 bits unsigned little endian\n" \
144 "6 -> 16 bits unsigned big endian\n" \
145 "7 -> mpeg2 audio (unsupported)\n" \
146 "8 -> ac3 pass-through"
148 #define RATE_TEXT "audio output frequency (Hz)"
149 #define RATE_LONGTEXT "You can force the audio output frequency here.\n" \
150 "Common values are 48000, 44100, 32000, 22050," \
151 " 16000, 11025, 8000"
153 #define DESYNC_TEXT "Compensate desynchronization of audio (in ms)"
154 #define DESYNC_LONGTEXT "This option allows you to delay the audio output." \
155 "This can be handy if you notice a lag between the" \
156 " video and the audio"
158 #define VOUT_TEXT "video output method"
159 #define VOUT_LONGTEXT "This option allows you to select the video output" \
160 "method used by vlc.\nNote that the default behaviour" \
161 "is to automatically select the best method available"
163 #define NOVIDEO_TEXT "disable video"
164 #define NOVIDEO_LONGTEXT "This will completely disable the video output. The" \
165 "video decoding stage shouldn't even be done, so it" \
166 "can allow you to save some processing power"
168 #define DISPLAY_TEXT "display identifier"
169 #define DISPLAY_LONGTEXT NULL
171 #define WIDTH_TEXT "video width"
172 #define WIDTH_LONGTEXT "You can enforce the video width here.\nNote" \
173 "that by default vlc will adapt to the video properties"
175 #define HEIGHT_TEXT "video height"
176 #define HEIGHT_LONGTEXT NULL
178 #define GRAYSCALE_TEXT "grayscale video output"
179 #define GRAYSCALE_LONGTEXT NULL
181 #define FULLSCREEN_TEXT "fullscreen video output"
182 #define FULLSCREEN_LONGTEXT NULL
184 #define NOOVERLAY_TEXT "disable accelerated display"
185 #define NOOVERLAY_LONGTEXT NULL
187 #define SPUMARGIN_TEXT "force SPU position"
188 #define SPUMARGIN_LONGTEXT NULL
190 #define FILTER_TEXT "video filter module"
191 #define FILTER_LONGTEXT NULL
193 #define INPUT_TEXT "input method"
194 #define INPUT_LONGTEXT NULL
196 #define SERVER_PORT_TEXT "server port"
197 #define SERVER_PORT_LONGTEXT NULL
199 #define NETCHANNEL_TEXT "enable network channel mode"
200 #define NETCHANNEL_LONGTEXT NULL
202 #define CHAN_SERV_TEXT "channel server address"
203 #define CHAN_SERV_LONGTEXT NULL
205 #define CHAN_PORT_TEXT "channel server port"
206 #define CHAN_PORT_LONGTEXT NULL
208 #define IFACE_TEXT "network interface"
209 #define IFACE_LONGTEXT NULL
211 #define INPUT_AUDIO_TEXT "choose audio"
212 #define INPUT_AUDIO_LONGTEXT NULL
214 #define INPUT_CHAN_TEXT "choose channel"
215 #define INPUT_CHAN_LONGTEXT NULL
217 #define INPUT_SUBT_TEXT "choose subtitles"
218 #define INPUT_SUBT_LONGTEXT NULL
220 #define DVD_DEV_TEXT "DVD device"
221 #define DVD_DEV_LONGTEXT NULL
223 #define VCD_DEV_TEXT "VCD device"
224 #define VCD_DEV_LONGTEXT NULL
226 #define IPV6_TEXT "force IPv6"
227 #define IPV6_LONGTEXT NULL
229 #define IPV4_TEXT "force IPv4"
230 #define IPV4_LONGTEXT NULL
232 #define ADEC_MPEG_TEXT "choose MPEG audio decoder"
233 #define ADEC_MPEG_LONGTEXT NULL
235 #define ADEC_AC3_TEXT "choose AC3 audio decoder"
236 #define ADEC_AC3_LONGTEXT NULL
238 #define VDEC_SMP_TEXT "use additional processors"
239 #define VDEC_SMP_LONGTEXT NULL
241 #define VPAR_SYNCHRO_TEXT "force synchro algorithm {I|I+|IP|IP+|IPB}"
242 #define VPAR_SYNCHRO_LONGTEXT NULL
244 #define NOMMX_TEXT "disable CPU's MMX support"
245 #define NOMMX_LONGTEXT NULL
247 #define NO3DN_TEXT "disable CPU's 3D Now! support"
248 #define NO3DN_LONGTEXT NULL
250 #define NOMMXEXT_TEXT "disable CPU's MMX EXT support"
251 #define NOMMXEXT_LONGTEXT NULL
253 #define NOSSE_TEXT "disable CPU's SSE support"
254 #define NOSSE_LONGTEXT NULL
256 #define NOALTIVEC_TEXT "disable CPU's AltiVec support"
257 #define NOALTIVEC_LONGTEXT NULL
259 #define PLAYLIST_LAUNCH_TEXT "launch playlist on startup"
260 #define PLAYLIST_LAUNCH_LONGTEXT NULL
262 #define PLAYLIST_ENQUEUE_TEXT "enqeue playlist as default"
263 #define PLAYLIST_ENQUEUE_LONGTEXT NULL
265 #define PLAYLIST_LOOP_TEXT "loop playlist on end"
266 #define PLAYLIST_LOOP_LONGTEXT NULL
268 #define MEMCPY_TEXT "memory copy method"
269 #define MEMCPY_LONGTEXT NULL
274 ADD_CATEGORY_HINT( text, longtext )
275 ADD_SUBCATEGORY_HINT( text, longtext )
276 ADD_STRING( option_name, value, p_callback, text, longtext )
277 ADD_FILE( option_name, psz_value, p_callback, text, longtext )
278 ADD_PLUGIN( option_name, psz_value, i_capability, p_callback, text, longtext )
279 ADD_INTEGER( option_name, i_value, p_callback, text, longtext )
280 ADD_BOOL( option_name, p_callback, text, longtext )
285 /* Interface options */
286 ADD_CATEGORY_HINT( "Interface", NULL)
287 ADD_PLUGIN ( "intf", MODULE_CAPABILITY_INTF, NULL, NULL, INTF_TEXT, INTF_LONGTEXT )
288 ADD_INTEGER ( "warning", 0, NULL, WARNING_TEXT, WARNING_LONGTEXT )
289 ADD_BOOL ( "stats", NULL, STATS_TEXT, STATS_LONGTEXT )
290 ADD_STRING ( "search_path", NULL, NULL, INTF_PATH_TEXT, INTF_PATH_LONGTEXT )
293 ADD_CATEGORY_HINT( "Audio", NULL)
294 ADD_PLUGIN ( "aout", MODULE_CAPABILITY_AOUT, NULL, NULL, AOUT_TEXT, AOUT_LONGTEXT )
295 ADD_BOOL ( "noaudio", NULL, NOAUDIO_TEXT, NOAUDIO_LONGTEXT )
296 ADD_BOOL ( "mono", NULL, MONO_TEXT, MONO_LONGTEXT )
297 ADD_INTEGER ( "volume", VOLUME_DEFAULT, NULL, VOLUME_TEXT, VOLUME_LONGTEXT )
298 ADD_INTEGER ( "rate", 44100, NULL, RATE_TEXT, RATE_LONGTEXT )
299 ADD_INTEGER ( "desync", 0, NULL, DESYNC_TEXT, DESYNC_LONGTEXT )
300 ADD_INTEGER ( "aout_format", 0, NULL, FORMAT_TEXT,
304 ADD_CATEGORY_HINT( "Video", NULL )
305 ADD_PLUGIN ( "vout", MODULE_CAPABILITY_VOUT, NULL, NULL, VOUT_TEXT, VOUT_LONGTEXT )
306 ADD_BOOL ( "novideo", NULL, NOVIDEO_TEXT, NOVIDEO_LONGTEXT )
307 ADD_STRING ( "display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT )
308 ADD_INTEGER ( "width", 720, NULL, WIDTH_TEXT, WIDTH_LONGTEXT )
309 ADD_INTEGER ( "height", 576, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT )
310 ADD_BOOL ( "grayscale", NULL, GRAYSCALE_TEXT, GRAYSCALE_LONGTEXT )
311 ADD_BOOL ( "fullscreen", NULL, FULLSCREEN_TEXT, FULLSCREEN_LONGTEXT )
312 ADD_BOOL ( "nooverlay", NULL, NOOVERLAY_TEXT, NOOVERLAY_LONGTEXT )
313 ADD_INTEGER ( "spumargin", -1, NULL, SPUMARGIN_TEXT, SPUMARGIN_LONGTEXT )
314 ADD_PLUGIN ( "filter", MODULE_CAPABILITY_VOUT, NULL, NULL, FILTER_TEXT, FILTER_LONGTEXT )
317 ADD_CATEGORY_HINT( "Input", NULL )
318 ADD_STRING ( "input", NULL, NULL, INPUT_TEXT, INPUT_LONGTEXT )
319 ADD_INTEGER ( "server_port", 1234, NULL, SERVER_PORT_TEXT, SERVER_PORT_LONGTEXT )
320 ADD_BOOL ( "network_channel", NULL, NETCHANNEL_TEXT, NETCHANNEL_LONGTEXT )
321 ADD_STRING ( "channel_server", "localhost", NULL, CHAN_SERV_TEXT, CHAN_SERV_LONGTEXT )
322 ADD_INTEGER ( "channel_port", 6010, NULL, CHAN_PORT_TEXT, CHAN_PORT_LONGTEXT )
323 ADD_STRING ( "iface", "eth0", NULL, IFACE_TEXT, IFACE_LONGTEXT )
325 ADD_INTEGER ( "input_audio", -1, NULL, INPUT_AUDIO_TEXT, INPUT_AUDIO_LONGTEXT )
326 ADD_INTEGER ( "input_channel", -1, NULL, INPUT_CHAN_TEXT, INPUT_CHAN_LONGTEXT )
327 ADD_INTEGER ( "input_subtitle", -1, NULL, INPUT_SUBT_TEXT, INPUT_SUBT_LONGTEXT )
329 ADD_STRING ( "dvd_device", "/dev/dvd", NULL, DVD_DEV_TEXT, DVD_DEV_LONGTEXT )
330 ADD_STRING ( "vcd_device", "/dev/cdrom", NULL, VCD_DEV_TEXT, VCD_DEV_LONGTEXT )
331 ADD_BOOL ( "ipv6", NULL, IPV6_TEXT, IPV6_LONGTEXT )
332 ADD_BOOL ( "ipv4", NULL, IPV4_TEXT, IPV4_LONGTEXT )
334 /* Decoder options */
335 ADD_CATEGORY_HINT( "Decoders", NULL )
336 ADD_PLUGIN ( "mpeg_adec", MODULE_CAPABILITY_DECODER, NULL, NULL, ADEC_MPEG_TEXT, ADEC_MPEG_LONGTEXT )
337 ADD_PLUGIN ( "ac3_adec", MODULE_CAPABILITY_DECODER, NULL, NULL, ADEC_AC3_TEXT, ADEC_AC3_LONGTEXT )
338 ADD_INTEGER ( "vdec_smp", 0, NULL, VDEC_SMP_TEXT, VDEC_SMP_LONGTEXT )
339 ADD_STRING ( "vpar_synchro", NULL, NULL, VPAR_SYNCHRO_TEXT, VPAR_SYNCHRO_LONGTEXT )
342 ADD_CATEGORY_HINT( "CPU", NULL )
343 ADD_BOOL ( "nommx", NULL, NOMMX_TEXT, NOMMX_LONGTEXT )
344 ADD_BOOL ( "no3dn", NULL, NO3DN_TEXT, NO3DN_LONGTEXT )
345 ADD_BOOL ( "nommxext", NULL, NOMMXEXT_TEXT, NOMMXEXT_LONGTEXT )
346 ADD_BOOL ( "nosse", NULL, NOSSE_TEXT, NOSSE_LONGTEXT )
347 ADD_BOOL ( "noaltivec", NULL, NOALTIVEC_TEXT, NOALTIVEC_LONGTEXT )
349 /* Playlist options */
350 ADD_CATEGORY_HINT( "Playlist", NULL )
351 ADD_BOOL ( "playlist_launch", NULL, PLAYLIST_LAUNCH_TEXT, PLAYLIST_LAUNCH_LONGTEXT )
352 ADD_BOOL ( "playlist_enqueue", NULL, PLAYLIST_ENQUEUE_TEXT, PLAYLIST_ENQUEUE_LONGTEXT )
353 ADD_BOOL ( "playlist_loop", NULL, PLAYLIST_LOOP_TEXT, PLAYLIST_LOOP_LONGTEXT )
356 ADD_CATEGORY_HINT( "Miscellaneous", NULL )
357 ADD_PLUGIN ( "memcpy", MODULE_CAPABILITY_MEMCPY, NULL, NULL, MEMCPY_TEXT, MEMCPY_LONGTEXT )
362 SET_DESCRIPTION( "Main program" )
363 ADD_CAPABILITY( MAIN, 100/*whatever*/ )
366 MODULE_ACTIVATE_START
369 MODULE_DEACTIVATE_START
370 MODULE_DEACTIVATE_STOP
372 /* Hack for help options */
373 static module_t help_module;
374 static module_config_t p_help_config[] = {
375 { MODULE_CONFIG_ITEM_BOOL, "help", "print help (or use -h)",
376 NULL, NULL, 0, NULL, NULL, 0 },
377 { MODULE_CONFIG_ITEM_BOOL, "longhelp", "print detailed help (or use -H)",
378 NULL, NULL, 0, NULL, NULL, 0 },
379 { MODULE_CONFIG_ITEM_BOOL, "list", "print a list of available plugins "
380 "(or use -l)", NULL, NULL, 0, NULL, NULL, 0 },
381 { MODULE_CONFIG_ITEM_STRING, "plugin", "print help on plugin (or use -p)",
382 NULL, NULL, 0, NULL, &help_module.config_lock, 0 },
383 { MODULE_CONFIG_ITEM_BOOL, "version", "print version information",
384 NULL, NULL, 0, NULL, NULL, 0 },
385 { MODULE_CONFIG_HINT_END, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 } };
388 /*****************************************************************************
390 *****************************************************************************/
392 /*****************************************************************************
393 * Global variables - these are the only ones, see main.h and modules.h
394 *****************************************************************************/
396 module_bank_t *p_module_bank;
397 input_bank_t *p_input_bank;
398 aout_bank_t *p_aout_bank;
399 vout_bank_t *p_vout_bank;
401 /*****************************************************************************
403 *****************************************************************************/
404 static int GetConfigurationFromCmdLine ( int *pi_argc, char *ppsz_argv[],
405 boolean_t b_ignore_errors );
406 static int GetFilenames ( int i_argc, char *ppsz_argv[] );
407 static void Usage ( const char *psz_module_name );
408 static void ListModules ( void );
409 static void Version ( void );
411 static void InitSignalHandler ( void );
412 static void SimpleSignalHandler ( int i_signal );
413 static void FatalSignalHandler ( int i_signal );
414 static void IllegalSignalHandler ( int i_signal );
415 static u32 CPUCapabilities ( void );
418 static void ShowConsole ( void );
422 static int i_illegal;
423 static char *psz_capability;
425 /*****************************************************************************
426 * main: parse command line, start interface and spawn threads
427 *****************************************************************************
428 * Steps during program execution are:
429 * -configuration parsing and messages interface initialization
430 * -opening of audio output device and some global modules
431 * -execution of interface, which exit on error or on user request
432 * -closing of audio output device and some global modules
433 * On error, the spawned threads are canceled, and the open devices closed.
434 *****************************************************************************/
435 int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
437 main_t main_data; /* root of all data - see main.h */
438 module_bank_t module_bank;
439 input_bank_t input_bank;
440 aout_bank_t aout_bank;
441 vout_bank_t vout_bank;
445 p_main = &main_data; /* set up the global variables */
446 p_module_bank = &module_bank;
447 p_input_bank = &input_bank;
448 p_aout_bank = &aout_bank;
449 p_vout_bank = &vout_bank;
451 p_main->i_warning_level = 0;
453 #if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
457 #if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
458 if( !setlocale( LC_MESSAGES, "" ) )
460 fprintf( stderr, "warning: unsupported locale.\n" );
464 if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
466 fprintf( stderr, "warning: no domain %s in directory %s\n",
467 PACKAGE, LOCALEDIR );
470 textdomain( PACKAGE );
474 * Initialize threads system
479 * Test if our code is likely to run on this CPU
481 p_main->i_cpu_capabilities = CPUCapabilities();
484 * System specific initialization code
486 #if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
487 system_Init( &i_argc, ppsz_argv, ppsz_env );
489 #elif defined( SYS_LINUX )
491 /* Activate malloc checking routines to detect heap corruptions. */
492 putenv( "MALLOC_CHECK_=2" );
493 putenv( "GNOME_DISABLE_CRASH_DIALOG=1" );
498 * Initialize messages interface
502 intf_Msg( COPYRIGHT_MESSAGE "\n" );
505 /* Get the executable name (similar to the basename command) */
506 p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
509 if( *p_tmp == '/' ) p_main->psz_arg0 = ++p_tmp;
514 * Initialize the module bank and and load the configuration of the main
515 * module. We need to do this at this stage to be able to display a short
516 * help if required by the user. (short help == main module options)
521 /* Hack: insert the help module here */
522 help_module.psz_name = "help";
523 help_module.i_config_lines = sizeof(p_help_config) /
524 sizeof(module_config_t);
525 help_module.i_config_items = help_module.i_config_lines - 1;
526 vlc_mutex_init( &help_module.config_lock );
527 help_module.p_config = p_help_config;
528 help_module.next = p_module_bank->first;
529 p_module_bank->first = &help_module;
532 if( GetConfigurationFromCmdLine( &i_argc, ppsz_argv, 1 ) )
538 /* Check for short help option */
539 if( config_GetIntVariable( "help" ) )
541 intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
549 /* Check for version option */
550 if( config_GetIntVariable( "version" ) )
556 /* Hack: remove the help module here */
557 p_module_bank->first = help_module.next;
561 * Load the builtins and plugins into the module_bank.
562 * We have to do it before GetConfiguration() because this also gets the
563 * list of configuration options exported by each plugin and loads their
566 module_LoadBuiltins();
567 module_LoadPlugins();
568 intf_WarnMsg( 2, "module: module bank initialized, found %i modules",
569 p_module_bank->i_count );
571 /* Hack: insert the help module here */
572 help_module.next = p_module_bank->first;
573 p_module_bank->first = &help_module;
576 /* Check for help on plugins */
577 if( (p_tmp = config_GetPszVariable( "plugin" )) )
584 /* Check for long help option */
585 if( config_GetIntVariable( "longhelp" ) )
591 /* Check for plugin list option */
592 if( config_GetIntVariable( "list" ) )
598 /* Hack: remove the help module here */
599 p_module_bank->first = help_module.next;
604 * Override default configuration with config file settings
606 vlc_mutex_init( &p_main->config_lock );
607 config_LoadConfigFile( NULL );
610 * Override configuration with command line settings
612 if( GetConfigurationFromCmdLine( &i_argc, ppsz_argv, 0 ) )
619 /* p_main inititalization. FIXME ? */
620 p_main->i_desync = (mtime_t)config_GetIntVariable( "desync" )
622 p_main->b_stats = config_GetIntVariable( "stats" );
623 p_main->b_audio = !config_GetIntVariable( "noaudio" );
624 p_main->b_stereo= !config_GetIntVariable( "mono" );
625 p_main->b_video = !config_GetIntVariable( "novideo" );
626 if( config_GetIntVariable( "nommx" ) )
627 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMX;
628 if( config_GetIntVariable( "no3dn" ) )
629 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_3DNOW;
630 if( config_GetIntVariable( "nommxext" ) )
631 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMXEXT;
632 if( config_GetIntVariable( "nosse" ) )
633 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_SSE;
634 if( config_GetIntVariable( "noaltivec" ) )
635 p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_ALTIVEC;
638 if( p_main->b_stats )
640 char p_capabilities[200];
641 p_capabilities[0] = '\0';
643 #define PRINT_CAPABILITY( capability, string ) \
644 if( p_main->i_cpu_capabilities & capability ) \
646 strncat( p_capabilities, string " ", \
647 sizeof(p_capabilities) - strlen(p_capabilities) ); \
648 p_capabilities[sizeof(p_capabilities) - 1] = '\0'; \
651 PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
652 PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
653 PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
654 PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
655 PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
656 PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
657 PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
658 PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "Altivec" );
659 PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
660 intf_StatMsg( "info: CPU has capabilities : %s", p_capabilities );
664 * Initialize playlist and get commandline files
666 p_main->p_playlist = intf_PlaylistCreate();
667 if( !p_main->p_playlist )
669 intf_ErrMsg( "playlist error: playlist initialization failed" );
673 intf_PlaylistInit( p_main->p_playlist );
676 * Get input filenames given as commandline arguments
678 GetFilenames( i_argc, ppsz_argv );
681 * Initialize input, aout and vout banks
688 * Choose the best memcpy module
690 psz_plugin = config_GetPszVariable( "memcpy" );
691 p_main->p_memcpy_module = module_Need( MODULE_CAPABILITY_MEMCPY, NULL,
693 if( psz_plugin ) free( psz_plugin );
694 if( p_main->p_memcpy_module == NULL )
696 intf_ErrMsg( "intf error: no suitable memcpy module, "
697 "using libc default" );
698 p_main->pf_memcpy = memcpy;
702 p_main->pf_memcpy = p_main->p_memcpy_module->p_functions
703 ->memcpy.functions.memcpy.pf_memcpy;
707 * Initialize shared resources and libraries
709 if( config_GetIntVariable( "network_channel" ) &&
710 network_ChannelCreate() )
712 /* On error during Channels initialization, switch off channels */
713 intf_ErrMsg( "intf error: channels initialization failed, "
714 "deactivating channels" );
715 config_PutIntVariable( "network_channel", 0 );
719 * Try to run the interface
721 p_main->p_intf = intf_Create();
722 if( p_main->p_intf == NULL )
724 intf_ErrMsg( "intf error: interface initialization failed" );
729 * Set signal handling policy for all threads
734 * This is the main loop
736 p_main->p_intf->pf_run( p_main->p_intf );
739 * Finished, destroy the interface
741 intf_Destroy( p_main->p_intf );
744 * Go back into channel 0 which is the network
746 if( config_GetIntVariable( "network_channel" ) )
748 network_ChannelJoin( COMMON_CHANNEL );
753 * Free input, aout and vout banks
762 intf_PlaylistDestroy( p_main->p_playlist );
765 * Free memcpy module if it was allocated
767 if( p_main->p_memcpy_module != NULL )
769 module_Unneed( p_main->p_memcpy_module );
778 * System specific cleaning code
780 #if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
786 * Terminate messages interface and program
788 intf_WarnMsg( 1, "intf: program terminated" );
792 * Stop threads system
800 /* following functions are local */
802 /*****************************************************************************
803 * GetConfigurationFromCmdLine: parse command line
804 *****************************************************************************
805 * Parse command line for configuration. If the inline help is requested, the
806 * function Usage() is called and the function returns -1 (causing main() to
808 * Now that the module_bank has been initialized, we can dynamically
809 * generate the longopts structure used by getops. We have to do it this way
810 * because we don't know (and don't want to know) in advance the configuration
811 * options used (ie. exported) by each module.
812 *****************************************************************************/
813 static int GetConfigurationFromCmdLine( int *pi_argc, char *ppsz_argv[],
814 boolean_t b_ignore_errors )
816 int i_cmd, i, i_index, i_longopts_size;
818 struct option *p_longopts;
821 const char *psz_shortopts = "hHvlp:";
823 /* Set default configuration and copy arguments */
824 p_main->i_argc = *pi_argc;
825 p_main->ppsz_argv = ppsz_argv;
827 p_main->p_channel = NULL;
830 /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
831 * is the PSN - process serial number (a unique PID-ish thingie)
832 * still ok for real Darwin & when run from command line */
833 if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
834 /* for example -psn_0_9306113 */
836 /* GDMF!... I can't do this or else the MacOSX window server will
837 * not pick up the PSN and not register the app and we crash...
838 * hence the following kludge otherwise we'll get confused w/ argv[1]
839 * being an input file name */
841 ppsz_argv[ 1 ] = NULL;
843 *pi_argc = *pi_argc - 1;
851 * Generate the longopts structure used by getopt_long
854 for( p_module = p_module_bank->first;
856 p_module = p_module->next )
858 /* count the number of exported configuration options (to allocate
860 i_longopts_size += p_module->i_config_items;
863 p_longopts = (struct option *)malloc( sizeof(struct option)
864 * (i_longopts_size + 1) );
865 if( p_longopts == NULL )
867 intf_ErrMsg( "GetConfigurationFromCmdLine error: "
868 "can't allocate p_longopts" );
872 /* Fill the longopts structure */
874 for( p_module = p_module_bank->first ;
876 p_module = p_module->next )
878 for( i = 0; i < p_module->i_config_lines; i++ )
880 if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
883 p_longopts[i_index].name = p_module->p_config[i].psz_name;
884 p_longopts[i_index].has_arg =
885 (p_module->p_config[i].i_type == MODULE_CONFIG_ITEM_BOOL)?
886 no_argument : required_argument;
887 p_longopts[i_index].flag = 0;
888 p_longopts[i_index].val = 0;
892 /* Close the longopts structure */
893 memset( &p_longopts[i_index], 0, sizeof(struct option) );
897 * Parse the command line options
901 while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv, psz_shortopts,
902 p_longopts, &i_index ) ) != EOF )
907 /* A long option has been recognized */
909 module_config_t *p_conf;
911 /* Store the configuration option */
912 p_conf = config_FindConfig( p_longopts[i_index].name );
914 switch( p_conf->i_type )
916 case MODULE_CONFIG_ITEM_STRING:
917 case MODULE_CONFIG_ITEM_FILE:
918 case MODULE_CONFIG_ITEM_PLUGIN:
919 config_PutPszVariable( p_longopts[i_index].name, optarg );
921 case MODULE_CONFIG_ITEM_INTEGER:
922 config_PutIntVariable( p_longopts[i_index].name, atoi(optarg));
924 case MODULE_CONFIG_ITEM_BOOL:
925 config_PutIntVariable( p_longopts[i_index].name, 1 );
932 /* short options handled here for now */
936 /* General/common options */
937 case 'h': /* -h, --help */
938 config_PutIntVariable( "help", 1 );
940 case 'H': /* -H, --longhelp */
941 config_PutIntVariable( "longhelp", 1 );
943 case 'l': /* -l, --list */
944 config_PutIntVariable( "list", 1 );
946 case 'p': /* -p, --plugin */
947 config_PutPszVariable( "plugin", optarg );
949 case 'v': /* -v, --verbose */
950 p_main->i_warning_level++;
953 /* Internal error: unknown option */
957 if( !b_ignore_errors )
959 intf_ErrMsg( "intf error: unknown option `%s'",
960 ppsz_argv[optind-1] );
961 intf_Msg( "Try `%s --help' for more information.\n",
964 #ifdef WIN32 /* Pause the console because it's destroyed when we exit */
965 intf_Msg( "\nPress the RETURN key to continue..." );
975 if( p_main->i_warning_level < 0 )
977 p_main->i_warning_level = 0;
984 /*****************************************************************************
985 * GetFilenames: parse command line options which are not flags
986 *****************************************************************************
987 * Parse command line for input files.
988 *****************************************************************************/
989 static int GetFilenames( int i_argc, char *ppsz_argv[] )
993 /* We assume that the remaining parameters are filenames */
994 for( i_opt = optind; i_opt < i_argc; i_opt++ )
996 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
997 ppsz_argv[ i_opt ] );
1003 /*****************************************************************************
1004 * Usage: print program usage
1005 *****************************************************************************
1006 * Print a short inline help. Message interface is initialized at this stage.
1007 *****************************************************************************/
1008 static void Usage( const char *psz_module_name )
1012 char psz_spaces[30];
1014 memset( psz_spaces, 32, 30 );
1020 /* Enumerate the config of each module */
1021 for( p_module = p_module_bank->first ;
1023 p_module = p_module->next )
1026 if( psz_module_name && strcmp( psz_module_name, p_module->psz_name ) )
1029 /* ignore plugins without config options */
1030 if( !p_module->i_config_items ) continue;
1032 /* print module name */
1033 intf_Msg( "%s options:\n", p_module->psz_name );
1035 for( i = 0; i < p_module->i_config_lines; i++ )
1039 switch( p_module->p_config[i].i_type )
1041 case MODULE_CONFIG_HINT_CATEGORY:
1042 intf_Msg( " %s", p_module->p_config[i].psz_text );
1045 case MODULE_CONFIG_ITEM_STRING:
1046 case MODULE_CONFIG_ITEM_FILE:
1047 case MODULE_CONFIG_ITEM_PLUGIN:
1048 /* Nasty hack, but right now I'm too tired to think about
1049 * a nice solution */
1050 j = 25 - strlen( p_module->p_config[i].psz_name )
1051 - strlen(" <string>") - 1;
1052 if( j < 0 ) j = 0; psz_spaces[j] = 0;
1054 intf_Msg( " --%s <string>%s %s",
1055 p_module->p_config[i].psz_name, psz_spaces,
1056 p_module->p_config[i].psz_text );
1059 case MODULE_CONFIG_ITEM_INTEGER:
1060 /* Nasty hack, but right now I'm too tired to think about
1061 * a nice solution */
1062 j = 25 - strlen( p_module->p_config[i].psz_name )
1063 - strlen(" <integer>") - 1;
1064 if( j < 0 ) j = 0; psz_spaces[j] = 0;
1066 intf_Msg( " --%s <integer>%s %s",
1067 p_module->p_config[i].psz_name, psz_spaces,
1068 p_module->p_config[i].psz_text );
1071 case MODULE_CONFIG_ITEM_BOOL:
1072 /* Nasty hack, but right now I'm too tired to think about
1073 * a nice solution */
1074 j = 25 - strlen( p_module->p_config[i].psz_name ) - 1;
1075 if( j < 0 ) j = 0; psz_spaces[j] = 0;
1077 intf_Msg( " --%s%s %s",
1078 p_module->p_config[i].psz_name, psz_spaces,
1079 p_module->p_config[i].psz_text );
1085 /* Yet another nasty hack.
1086 * Maybe we could use MODULE_CONFIG_ITEM_END to display tail messages
1087 * for each module?? */
1088 if( !strcmp( "main", p_module->psz_name ) )
1089 intf_Msg( "\nPlaylist items:"
1090 "\n *.mpg, *.vob \tPlain MPEG-1/2 files"
1091 "\n [dvd:][device][@raw_device][@[title][,[chapter][,angle]]]"
1093 "\n [vcd:][device][@[title][,[chapter]]"
1095 "\n udpstream:[<server>[:<server port>]][@[<bind address>]"
1097 "\n \tUDP stream sent by VLS"
1098 "\n vlc:loop \tLoop execution of the "
1100 "\n vlc:pause \tPause execution of "
1102 "\n vlc:quit \tQuit VLC" );
1108 #ifdef WIN32 /* Pause the console because it's destroyed when we exit */
1109 intf_Msg( "\nPress the RETURN key to continue..." );
1114 /*****************************************************************************
1115 * ListModules: list the available modules with their description
1116 *****************************************************************************
1117 * Print a list of all available modules (builtins and plugins) and a short
1118 * description for each one.
1119 *****************************************************************************/
1120 static void ListModules( void )
1123 char psz_spaces[20];
1125 memset( psz_spaces, 32, 20 );
1132 intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
1135 intf_Msg( "[plugin] [description]" );
1137 /* Enumerate each module */
1138 for( p_module = p_module_bank->first ;
1140 p_module = p_module->next )
1144 /* Nasty hack, but right now I'm too tired to think about a nice
1146 i = 20 - strlen( p_module->psz_name ) - 1;
1150 intf_Msg( " %s%s %s", p_module->psz_name, psz_spaces,
1151 p_module->psz_longname );
1157 #ifdef WIN32 /* Pause the console because it's destroyed when we exit */
1158 intf_Msg( "\nPress the RETURN key to continue..." );
1163 /*****************************************************************************
1164 * Version: print complete program version
1165 *****************************************************************************
1166 * Print complete program version and build number.
1167 *****************************************************************************/
1168 static void Version( void )
1173 intf_Msg( VERSION_MESSAGE
1174 "This program comes with NO WARRANTY, to the extent permitted by law.\n"
1175 "You may redistribute it under the terms of the GNU General Public License;\n"
1176 "see the file named COPYING for details.\n"
1177 "Written by the VideoLAN team at Ecole Centrale, Paris." );
1178 #ifdef WIN32 /* Pause the console because it's destroyed when we exit */
1179 intf_Msg( "\nPress the RETURN key to continue..." );
1184 /*****************************************************************************
1185 * InitSignalHandler: system signal handler initialization
1186 *****************************************************************************
1187 * Set the signal handlers. SIGTERM is not intercepted, because we need at
1188 * at least a method to kill the program when all other methods failed, and
1189 * when we don't want to use SIGKILL.
1190 *****************************************************************************/
1191 static void InitSignalHandler( void )
1193 /* Termination signals */
1195 signal( SIGINT, FatalSignalHandler );
1196 signal( SIGHUP, FatalSignalHandler );
1197 signal( SIGQUIT, FatalSignalHandler );
1200 signal( SIGALRM, SimpleSignalHandler );
1201 signal( SIGPIPE, SimpleSignalHandler );
1205 /*****************************************************************************
1206 * SimpleSignalHandler: system signal handler
1207 *****************************************************************************
1208 * This function is called when a non fatal signal is received by the program.
1209 *****************************************************************************/
1210 static void SimpleSignalHandler( int i_signal )
1212 /* Acknowledge the signal received */
1213 intf_WarnMsg( 0, "intf: ignoring signal %d", i_signal );
1216 /*****************************************************************************
1217 * FatalSignalHandler: system signal handler
1218 *****************************************************************************
1219 * This function is called when a fatal signal is received by the program.
1220 * It tries to end the program in a clean way.
1221 *****************************************************************************/
1222 static void FatalSignalHandler( int i_signal )
1224 /* Once a signal has been trapped, the termination sequence will be
1225 * armed and following signals will be ignored to avoid sending messages
1226 * to an interface having been destroyed */
1228 signal( SIGINT, SIG_IGN );
1229 signal( SIGHUP, SIG_IGN );
1230 signal( SIGQUIT, SIG_IGN );
1233 /* Acknowledge the signal received */
1234 intf_ErrMsg( "intf error: signal %d received, exiting", i_signal );
1236 /* Try to terminate everything - this is done by requesting the end of the
1237 * interface thread */
1238 p_main->p_intf->b_die = 1;
1241 /*****************************************************************************
1242 * IllegalSignalHandler: system signal handler
1243 *****************************************************************************
1244 * This function is called when an illegal instruction signal is received by
1245 * the program. We use this function to test OS and CPU capabilities
1246 *****************************************************************************/
1247 static void IllegalSignalHandler( int i_signal )
1249 /* Acknowledge the signal received */
1252 #ifdef HAVE_SIGRELSE
1253 sigrelse( i_signal );
1256 fprintf( stderr, "warning: your CPU has %s instructions, but not your "
1257 "operating system.\n", psz_capability );
1258 fprintf( stderr, " some optimizations will be disabled unless "
1259 "you upgrade your OS\n" );
1261 fprintf( stderr, " (for instance Linux kernel 2.4.x or later)" );
1267 /*****************************************************************************
1268 * CPUCapabilities: list the processors MMX support and other capabilities
1269 *****************************************************************************
1270 * This function is called to list extensions the CPU may have.
1271 *****************************************************************************/
1272 static u32 CPUCapabilities( void )
1274 volatile u32 i_capabilities = CPU_CAPABILITY_NONE;
1276 #if defined( SYS_DARWIN )
1277 struct host_basic_info hi;
1279 host_name_port_t host;
1282 char *psz_name, *psz_subname;
1284 i_capabilities |= CPU_CAPABILITY_FPU;
1286 /* Should 'never' fail? */
1287 host = mach_host_self();
1289 i_size = sizeof( hi ) / sizeof( int );
1290 ret = host_info( host, HOST_BASIC_INFO, ( host_info_t )&hi, &i_size );
1292 if( ret != KERN_SUCCESS )
1294 fprintf( stderr, "error: couldn't get CPU information\n" );
1295 return( i_capabilities );
1298 slot_name( hi.cpu_type, hi.cpu_subtype, &psz_name, &psz_subname );
1299 /* FIXME: need better way to detect newer proccessors.
1300 * could do strncmp(a,b,5), but that's real ugly */
1301 if( !strcmp(psz_name, "ppc7400") || !strcmp(psz_name, "ppc7450") )
1303 i_capabilities |= CPU_CAPABILITY_ALTIVEC;
1306 return( i_capabilities );
1308 #elif defined( __i386__ )
1309 volatile unsigned int i_eax, i_ebx, i_ecx, i_edx;
1310 volatile boolean_t b_amd;
1312 /* Needed for x86 CPU capabilities detection */
1313 # define cpuid( a ) \
1314 asm volatile ( "pushl %%ebx\n\t" \
1316 "movl %%ebx,%1\n\t" \
1325 i_capabilities |= CPU_CAPABILITY_FPU;
1327 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1328 signal( SIGILL, IllegalSignalHandler );
1331 /* test for a 486 CPU */
1332 asm volatile ( "pushl %%ebx\n\t"
1335 "movl %%eax, %%ebx\n\t"
1336 "xorl $0x200000, %%eax\n\t"
1348 if( i_eax == i_ebx )
1350 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1351 signal( SIGILL, NULL );
1353 return( i_capabilities );
1356 i_capabilities |= CPU_CAPABILITY_486;
1358 /* the CPU supports the CPUID instruction - get its level */
1359 cpuid( 0x00000000 );
1363 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1364 signal( SIGILL, NULL );
1366 return( i_capabilities );
1369 /* FIXME: this isn't correct, since some 486s have cpuid */
1370 i_capabilities |= CPU_CAPABILITY_586;
1372 /* borrowed from mpeg2dec */
1373 b_amd = ( i_ebx == 0x68747541 ) && ( i_ecx == 0x444d4163 )
1374 && ( i_edx == 0x69746e65 );
1376 /* test for the MMX flag */
1377 cpuid( 0x00000001 );
1379 if( ! (i_edx & 0x00800000) )
1381 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1382 signal( SIGILL, NULL );
1384 return( i_capabilities );
1387 i_capabilities |= CPU_CAPABILITY_MMX;
1389 if( i_edx & 0x02000000 )
1391 i_capabilities |= CPU_CAPABILITY_MMXEXT;
1393 # ifdef CAN_COMPILE_SSE
1394 /* We test if OS support the SSE instructions */
1395 psz_capability = "SSE";
1397 if( setjmp( env ) == 0 )
1399 /* Test a SSE instruction */
1400 __asm__ __volatile__ ( "xorps %%xmm0,%%xmm0\n" : : );
1403 if( i_illegal == 0 )
1405 i_capabilities |= CPU_CAPABILITY_SSE;
1410 /* test for additional capabilities */
1411 cpuid( 0x80000000 );
1413 if( i_eax < 0x80000001 )
1415 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1416 signal( SIGILL, NULL );
1418 return( i_capabilities );
1421 /* list these additional capabilities */
1422 cpuid( 0x80000001 );
1424 # ifdef CAN_COMPILE_3DNOW
1425 if( i_edx & 0x80000000 )
1427 psz_capability = "3D Now!";
1429 if( setjmp( env ) == 0 )
1431 /* Test a 3D Now! instruction */
1432 __asm__ __volatile__ ( "pfadd %%mm0,%%mm0\n" "femms\n" : : );
1435 if( i_illegal == 0 )
1437 i_capabilities |= CPU_CAPABILITY_3DNOW;
1442 if( b_amd && ( i_edx & 0x00400000 ) )
1444 i_capabilities |= CPU_CAPABILITY_MMXEXT;
1447 # if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1448 signal( SIGILL, NULL );
1450 return( i_capabilities );
1452 #elif defined( __powerpc__ )
1454 i_capabilities |= CPU_CAPABILITY_FPU;
1456 # ifdef CAN_COMPILE_ALTIVEC
1457 signal( SIGILL, IllegalSignalHandler );
1459 psz_capability = "AltiVec";
1461 if( setjmp( env ) == 0 )
1463 asm volatile ("mtspr 256, %0\n\t"
1464 "vand %%v0, %%v0, %%v0"
1469 if( i_illegal == 0 )
1471 i_capabilities |= CPU_CAPABILITY_ALTIVEC;
1474 signal( SIGILL, NULL );
1477 return( i_capabilities );
1480 /* default behaviour */
1481 return( i_capabilities );
1486 /*****************************************************************************
1487 * ShowConsole: On Win32, create an output console for debug messages
1488 *****************************************************************************
1489 * This function is usefull only on Win32.
1490 *****************************************************************************/
1492 static void ShowConsole( void )
1495 freopen( "CONOUT$", "w", stdout );
1496 freopen( "CONOUT$", "w", stderr );
1497 freopen( "CONIN$", "r", stdin );