]> git.sesse.net Git - vlc/blob - src/interface/main.c
* ALL: got rid of *_Probe functions because most of them were duplicates
[vlc] / src / interface / main.c
1 /*****************************************************************************
2  * main.c: main vlc source
3  * Includes the main() function for vlc. Parses command line, start interface
4  * and spawn threads.
5  *****************************************************************************
6  * Copyright (C) 1998-2001 VideoLAN
7  * $Id: main.c,v 1.151 2002/02/15 13:32:54 sam Exp $
8  *
9  * Authors: Vincent Seguin <seguin@via.ecp.fr>
10  *          Samuel Hocevar <sam@zoy.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <signal.h>                               /* SIGHUP, SIGINT, SIGKILL */
31 #include <stdio.h>                                              /* sprintf() */
32 #include <setjmp.h>                                       /* longjmp, setjmp */
33
34 #include <videolan/vlc.h>
35
36 #ifdef HAVE_GETOPT_LONG
37 #   ifdef HAVE_GETOPT_H
38 #       include <getopt.h>                                       /* getopt() */
39 #   endif
40 #else
41 #   include "GNUgetopt/getopt.h"
42 #endif
43
44 #ifdef SYS_DARWIN
45 #   include <mach/mach.h>                               /* Altivec detection */
46 #   include <mach/mach_error.h>       /* some day the header files||compiler *
47                                                        will define it for us */
48 #   include <mach/bootstrap.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 <errno.h>                                                 /* ENOMEM */
66 #include <stdlib.h>                                  /* getenv(), strtol(),  */
67 #include <string.h>                                            /* strerror() */
68 #include <fcntl.h>                                       /* open(), O_WRONLY */
69 #include <sys/stat.h>                                             /* S_IREAD */
70
71 #include "netutils.h"                                 /* network_ChannelJoin */
72
73 #include "stream_control.h"
74 #include "input_ext-intf.h"
75
76 #include "intf_playlist.h"
77 #include "interface.h"
78
79 #include "audio_output.h"
80
81 #include "video.h"
82 #include "video_output.h"
83
84 #include "debug.h"
85
86 /*****************************************************************************
87  * Command line options constants. If something is changed here, be sure that
88  * GetConfiguration and Usage are also changed.
89  *****************************************************************************/
90
91 /* Long options return values - note that values corresponding to short options
92  * chars, and in general any regular char, should be avoided */
93 #define OPT_NOAUDIO             150
94 #define OPT_STEREO              151
95 #define OPT_MONO                152
96 #define OPT_SPDIF               153
97 #define OPT_VOLUME              154
98 #define OPT_DESYNC              155
99
100 #define OPT_NOVIDEO             160
101 #define OPT_DISPLAY             161
102 #define OPT_WIDTH               162
103 #define OPT_HEIGHT              163
104 #define OPT_COLOR               164
105 #define OPT_FULLSCREEN          165
106 #define OPT_NOOVERLAY           166
107 #define OPT_XVADAPTOR           167
108 #define OPT_SMP                 168
109 #define OPT_SPUMARGIN           169
110
111 #define OPT_CHANNELS            170
112 #define OPT_SERVER              171
113 #define OPT_PORT                172
114 #define OPT_BROADCAST           173
115 #define OPT_CHANNELSERVER       174
116
117 #define OPT_INPUT               180
118 #define OPT_MOTION              181
119 #define OPT_IDCT                182
120 #define OPT_YUV                 183
121 #define OPT_DOWNMIX             184
122 #define OPT_IMDCT               185
123 #define OPT_MEMCPY              186
124 #define OPT_FILTER              187
125 #define OPT_DVDCSS_METHOD       188
126 #define OPT_DVDCSS_VERBOSE      189
127
128 #define OPT_SYNCHRO             190
129 #define OPT_WARNING             191
130 #define OPT_VERSION             192
131 #define OPT_STDOUT              193
132 #define OPT_STATS               194
133
134 #define OPT_MPEG_ADEC           200
135 #define OPT_AC3_ADEC            201
136
137 #define OPT_NOMMX               210
138 #define OPT_NO3DNOW             211
139 #define OPT_NOMMXEXT            212
140 #define OPT_NOSSE               213
141 #define OPT_NOALTIVEC           214
142
143 /* Usage fashion */
144 #define USAGE                     0
145 #define SHORT_HELP                1
146 #define LONG_HELP                 2
147
148 /* Long options */
149 static const struct option longopts[] =
150 {
151     /*  name,               has_arg,    flag,   val */
152
153     /* General/common options */
154     {   "help",             0,          0,      'h' },
155     {   "longhelp",         0,          0,      'H' },
156     {   "version",          0,          0,      OPT_VERSION },
157
158     /* Interface options */
159     {   "intf",             1,          0,      'I' },
160     {   "warning",          1,          0,      OPT_WARNING },
161     {   "stdout",           1,          0,      OPT_STDOUT },
162     {   "stats",            0,          0,      OPT_STATS },
163
164     /* Audio options */
165     {   "noaudio",          0,          0,      OPT_NOAUDIO },
166     {   "aout",             1,          0,      'A' },
167     {   "stereo",           0,          0,      OPT_STEREO },
168     {   "mono",             0,          0,      OPT_MONO },
169     {   "spdif",            0,          0,      OPT_SPDIF },
170     {   "downmix",          1,          0,      OPT_DOWNMIX },
171     {   "imdct",            1,          0,      OPT_IMDCT },
172     {   "volume",           1,          0,      OPT_VOLUME },
173     {   "desync",           1,          0,      OPT_DESYNC },
174
175     /* Video options */
176     {   "novideo",          0,          0,      OPT_NOVIDEO },
177     {   "vout",             1,          0,      'V' },
178     {   "display",          1,          0,      OPT_DISPLAY },
179     {   "width",            1,          0,      OPT_WIDTH },
180     {   "height",           1,          0,      OPT_HEIGHT },
181     {   "grayscale",        0,          0,      'g' },
182     {   "color",            0,          0,      OPT_COLOR },
183     {   "motion",           1,          0,      OPT_MOTION },
184     {   "idct",             1,          0,      OPT_IDCT },
185     {   "yuv",              1,          0,      OPT_YUV },
186     {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
187     {   "nooverlay",        0,          0,      OPT_NOOVERLAY },
188     {   "xvadaptor",        1,          0,      OPT_XVADAPTOR },
189     {   "smp",              1,          0,      OPT_SMP },
190     {   "spumargin",        1,          0,      OPT_SPUMARGIN },
191
192     /* DVD options */
193     {   "dvdtitle",         1,          0,      't' },
194     {   "dvdchapter",       1,          0,      'T' },
195     {   "dvdangle",         1,          0,      'u' },
196     {   "dvdaudio",         1,          0,      'a' },
197     {   "dvdchannel",       1,          0,      'c' },
198     {   "dvdsubtitle",      1,          0,      's' },
199     {   "dvdcss-method",    1,          0,      OPT_DVDCSS_METHOD },
200     {   "dvdcss-verbose",   1,          0,      OPT_DVDCSS_VERBOSE },
201
202     /* Input options */
203     {   "input",            1,          0,      OPT_INPUT },
204     {   "channels",         0,          0,      OPT_CHANNELS },
205     {   "channelserver",    1,          0,      OPT_CHANNELSERVER },
206
207     /* Misc options */
208     {   "synchro",          1,          0,      OPT_SYNCHRO },
209     {   "memcpy",           1,          0,      OPT_MEMCPY },
210     {   "filter",           1,          0,      OPT_FILTER },
211
212     /* Decoder options */
213     {   "mpeg_adec",        1,          0,      OPT_MPEG_ADEC },
214     {   "ac3_adec",         1,          0,      OPT_AC3_ADEC },
215
216     /* CPU options */
217     {   "nommx",            0,          0,      OPT_NOMMX },
218     {   "no3dnow",          0,          0,      OPT_NO3DNOW },
219     {   "nommxext",         0,          0,      OPT_NOMMXEXT },
220     {   "nosse",            0,          0,      OPT_NOSSE },
221     {   "noaltivec",        0,          0,      OPT_NOALTIVEC },
222
223     {   0,                  0,          0,      0 }
224 };
225
226 /* Short options */
227 static const char *psz_shortopts = "hHvgt:T:u:a:s:c:I:A:V:";
228
229 /*****************************************************************************
230  * Global variables - these are the only ones, see main.h and modules.h
231  *****************************************************************************/
232 main_t        *p_main;
233 module_bank_t *p_module_bank;
234 input_bank_t  *p_input_bank;
235 aout_bank_t   *p_aout_bank;
236 vout_bank_t   *p_vout_bank;
237
238 /*****************************************************************************
239  * Local prototypes
240  *****************************************************************************/
241 static int  GetConfiguration        ( int *pi_argc, char *ppsz_argv[],
242                                       char *ppsz_env[] );
243 static int  GetFilenames            ( int i_argc, char *ppsz_argv[] );
244 static void Usage                   ( int i_fashion );
245 static void Version                 ( void );
246
247 static void InitSignalHandler       ( void );
248 static void SimpleSignalHandler     ( int i_signal );
249 static void FatalSignalHandler      ( int i_signal );
250 static void IllegalSignalHandler    ( int i_signal );
251 static u32  CPUCapabilities         ( void );
252
253 static int  RedirectSTDOUT          ( void );
254 static void ShowConsole             ( void );
255
256 static jmp_buf env;
257 static int     i_illegal;
258 static char   *psz_capability;
259
260 /*****************************************************************************
261  * main: parse command line, start interface and spawn threads
262  *****************************************************************************
263  * Steps during program execution are:
264  *      -configuration parsing and messages interface initialization
265  *      -opening of audio output device and some global modules
266  *      -execution of interface, which exit on error or on user request
267  *      -closing of audio output device and some global modules
268  * On error, the spawned threads are canceled, and the open devices closed.
269  *****************************************************************************/
270 int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
271 {
272     main_t        main_data;                /* root of all data - see main.h */
273     module_bank_t module_bank;
274     input_bank_t  input_bank;
275     aout_bank_t   aout_bank;
276     vout_bank_t   vout_bank;
277
278     p_main        = &main_data;               /* set up the global variables */
279     p_module_bank = &module_bank;
280     p_input_bank  = &input_bank;
281     p_aout_bank   = &aout_bank;
282     p_vout_bank   = &vout_bank;
283
284 #if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
285     /*
286      * Support for getext
287      */
288 #if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
289     if( !setlocale( LC_MESSAGES, "" ) )
290     {
291         fprintf( stderr, "warning: unsupported locale.\n" );
292     }
293 #endif
294
295     if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
296     {
297         fprintf( stderr, "warning: no domain %s in directory %s\n",
298                  PACKAGE, LOCALEDIR );
299     }
300
301     textdomain( PACKAGE );
302 #endif
303
304     /*
305      * Initialize threads system
306      */
307     vlc_threads_init( );
308
309     /*
310      * Test if our code is likely to run on this CPU
311      */
312     p_main->i_cpu_capabilities = CPUCapabilities();
313
314     /*
315      * System specific initialization code
316      */
317 #if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
318     system_Init( &i_argc, ppsz_argv, ppsz_env );
319
320 #elif defined( SYS_LINUX )
321 #   ifdef DEBUG
322     /* Activate malloc checking routines to detect heap corruptions. */
323     main_PutIntVariable( "MALLOC_CHECK_", 2 );
324 #   endif
325 #endif
326
327     /*
328      * Initialize messages interface
329      */
330     p_main->p_msg = intf_MsgCreate();
331     if( !p_main->p_msg )                         /* start messages interface */
332     {
333         fprintf( stderr, "error: can't initialize messages interface (%s)\n",
334                  strerror(errno) );
335         return( errno );
336     }
337
338     intf_MsgImm( COPYRIGHT_MESSAGE "\n" );
339
340     /*
341      * Read configuration
342      */
343     if( GetConfiguration( &i_argc, ppsz_argv, ppsz_env ) ) /* parse cmd line */
344     {
345         intf_MsgDestroy();
346         return( errno );
347     }
348
349     /*
350      * Redirect the standard output if required by the user, and on Win32 we
351      * also open a console to display the debug messages.
352      */
353     RedirectSTDOUT();
354
355     if( p_main->b_stats )
356     {
357         char          p_capabilities[200];
358         p_capabilities[0] = '\0';
359
360 #define PRINT_CAPABILITY( capability, string )                              \
361         if( p_main->i_cpu_capabilities & capability )                       \
362         {                                                                   \
363             strncat( p_capabilities, string " ",                            \
364                      sizeof(p_capabilities) - strlen(p_capabilities) );     \
365             p_capabilities[sizeof(p_capabilities) - 1] = '\0';              \
366         }
367
368         PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
369         PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
370         PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
371         PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
372         PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
373         PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
374         PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
375         PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "Altivec" );
376         PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
377         intf_StatMsg( "info: CPU has capabilities : %s", p_capabilities );
378     }
379
380     /*
381      * Initialize playlist and get commandline files
382      */
383     p_main->p_playlist = intf_PlaylistCreate();
384     if( !p_main->p_playlist )
385     {
386         intf_ErrMsg( "playlist error: playlist initialization failed" );
387         intf_MsgDestroy();
388         return( errno );
389     }
390     intf_PlaylistInit( p_main->p_playlist );
391
392     /*
393      * Get input filenames given as commandline arguments
394      */
395     GetFilenames( i_argc, ppsz_argv );
396
397     /*
398      * Initialize module, input, aout and vout banks
399      */
400     module_InitBank();
401     input_InitBank();
402     aout_InitBank();
403     vout_InitBank();
404
405     /*
406      * Choose the best memcpy module
407      */
408     p_main->p_memcpy_module = module_Need( MODULE_CAPABILITY_MEMCPY, NULL,
409                                            NULL );
410     if( p_main->p_memcpy_module == NULL )
411     {
412         intf_ErrMsg( "intf error: no suitable memcpy module, "
413                      "using libc default" );
414         p_main->pf_memcpy = memcpy;
415     }
416     else
417     {
418         p_main->pf_memcpy = p_main->p_memcpy_module->p_functions
419                                   ->memcpy.functions.memcpy.pf_memcpy;
420     }
421
422     /*
423      * Initialize shared resources and libraries
424      */
425     if( main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
426                              INPUT_NETWORK_CHANNEL_DEFAULT ) &&
427         network_ChannelCreate() )
428     {
429         /* On error during Channels initialization, switch off channels */
430         intf_ErrMsg( "intf error: channels initialization failed, " 
431                                  "deactivating channels" );
432         main_PutIntVariable( INPUT_NETWORK_CHANNEL_VAR, 0 );
433     }
434
435     /*
436      * Try to run the interface
437      */
438     p_main->p_intf = intf_Create();
439     if( p_main->p_intf == NULL )
440     {
441         intf_ErrMsg( "intf error: interface initialization failed" );
442     }
443     else
444     {
445         /*
446          * Set signal handling policy for all threads
447          */
448         InitSignalHandler();
449
450         /*
451          * This is the main loop
452          */
453         p_main->p_intf->pf_run( p_main->p_intf );
454
455         /*
456          * Finished, destroy the interface
457          */
458         intf_Destroy( p_main->p_intf );
459
460         /*
461          * Go back into channel 0 which is the network
462          */
463         if( main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
464                                  INPUT_NETWORK_CHANNEL_DEFAULT ) )
465         {
466             network_ChannelJoin( COMMON_CHANNEL );
467         }
468     }
469
470     /*
471      * Free input, aout and vout banks
472      */
473     input_EndBank();
474     vout_EndBank();
475     aout_EndBank();
476
477     /*
478      * Free playlist
479      */
480     intf_PlaylistDestroy( p_main->p_playlist );
481
482     /*
483      * Free memcpy module if it was allocated
484      */
485     if( p_main->p_memcpy_module != NULL )
486     {
487         module_Unneed( p_main->p_memcpy_module );
488     }
489
490     /*
491      * Free module bank
492      */
493     module_EndBank();
494
495     /*
496      * System specific cleaning code
497      */
498 #if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
499     system_End();
500 #endif
501
502
503     /*
504      * Terminate messages interface and program
505      */
506     intf_WarnMsg( 1, "intf: program terminated" );
507     intf_MsgDestroy();
508
509     /*
510      * Stop threads system
511      */
512     vlc_threads_end( );
513
514     return 0;
515 }
516
517 /*****************************************************************************
518  * main_GetIntVariable: get the int value of an environment variable
519  *****************************************************************************
520  * This function is used to read some default parameters in modules.
521  *****************************************************************************/
522 int main_GetIntVariable( char *psz_name, int i_default )
523 {
524     char *      psz_env;                                /* environment value */
525     char *      psz_end;                             /* end of parsing index */
526     long int    i_value;                                            /* value */
527
528     psz_env = getenv( psz_name );
529     if( psz_env )
530     {
531         i_value = strtol( psz_env, &psz_end, 0 );
532         if( (*psz_env != '\0') && (*psz_end == '\0') )
533         {
534             return( i_value );
535         }
536     }
537     return( i_default );
538 }
539
540 /*****************************************************************************
541  * main_GetPszVariable: get the string value of an environment variable
542  *****************************************************************************
543  * This function is used to read some default parameters in modules.
544  *****************************************************************************/
545 char * main_GetPszVariable( char *psz_name, char *psz_default )
546 {
547     char *psz_env;
548
549     psz_env = getenv( psz_name );
550     if( psz_env )
551     {
552         return( psz_env );
553     }
554     return( psz_default );
555 }
556
557 /*****************************************************************************
558  * main_PutPszVariable: set the string value of an environment variable
559  *****************************************************************************
560  * This function is used to set some default parameters in modules. The use of
561  * this function will cause some memory leak: since some systems use the pointer
562  * passed to putenv to store the environment string, it can't be freed.
563  *****************************************************************************/
564 void main_PutPszVariable( char *psz_name, char *psz_value )
565 {
566     char *psz_env;
567
568     psz_env = malloc( strlen(psz_name) + strlen(psz_value) + 2 );
569     if( psz_env == NULL )
570     {
571         intf_ErrMsg( "intf error: cannot create psz_env (%s)",
572                      strerror(ENOMEM) );
573     }
574     else
575     {
576         sprintf( psz_env, "%s=%s", psz_name, psz_value );
577         if( putenv( psz_env ) )
578         {
579             intf_ErrMsg( "intf error: cannot putenv (%s)", strerror(errno) );
580         }
581     }
582 }
583
584 /*****************************************************************************
585  * main_PutIntVariable: set the integer value of an environment variable
586  *****************************************************************************
587  * This function is used to set some default parameters in modules. The use of
588  * this function will cause some memory leak: since some systems use the pointer
589  * passed to putenv to store the environment string, it can't be freed.
590  *****************************************************************************/
591 void main_PutIntVariable( char *psz_name, int i_value )
592 {
593     char psz_value[ 256 ];                               /* buffer for value */
594
595     sprintf( psz_value, "%d", i_value );
596     main_PutPszVariable( psz_name, psz_value );
597 }
598
599 /* following functions are local */
600
601 /*****************************************************************************
602  * GetConfiguration: parse command line
603  *****************************************************************************
604  * Parse command line and configuration file for configuration. If the inline
605  * help is requested, the function Usage() is called and the function returns
606  * -1 (causing main() to exit). The messages interface is initialized at this
607  * stage, but most structures are not allocated, so only environment should
608  * be used.
609  *****************************************************************************/
610 static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
611 {
612     int   i_cmd;
613     char *p_tmp;
614
615     /* Set default configuration and copy arguments */
616     p_main->i_argc    = *pi_argc;
617     p_main->ppsz_argv = ppsz_argv;
618     p_main->ppsz_env  = ppsz_env;
619
620     p_main->b_audio     = 1;
621     p_main->b_video     = 1;
622
623     p_main->i_warning_level = 0;
624     p_main->b_stats = 0;
625     p_main->i_desync = 0; /* No desynchronization by default */
626
627     p_main->p_channel = NULL;
628
629     /* Get the executable name (similar to the basename command) */
630     p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
631     while( *p_tmp )
632     {
633         if( *p_tmp == '/' )
634         {
635             p_main->psz_arg0 = ++p_tmp;
636         }
637         else
638         {
639             ++p_tmp;
640         }
641     }
642
643 #ifdef SYS_DARWIN
644     /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
645      * is the PSN - process serial number (a unique PID-ish thingie)
646      * still ok for real Darwin & when run from command line */
647     if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
648                                         /* for example -psn_0_9306113 */
649     {
650         /* GDMF!... I can't do this or else the MacOSX window server will
651          * not pick up the PSN and not register the app and we crash...
652          * hence the following kludge otherwise we'll get confused w/ argv[1]
653          * being an input file name */
654 #if 0
655         ppsz_argv[ 1 ] = NULL;
656 #endif
657         *pi_argc = *pi_argc - 1;
658         pi_argc--;
659         return( 0 );
660     }
661 #endif
662
663     /* Parse command line options */
664     opterr = 0;
665     while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv,
666                                    psz_shortopts, longopts, 0 ) ) != EOF )
667     {
668         switch( i_cmd )
669         {
670         /* General/common options */
671         case 'h':                                              /* -h, --help */
672             ShowConsole();
673             RedirectSTDOUT();
674             Usage( SHORT_HELP );
675 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
676             if( strcmp( "", main_GetPszVariable( INTF_STDOUT_VAR,
677                                                  INTF_STDOUT_DEFAULT ) ) == 0 )
678             {
679                 /* No stdout redirection has been asked for */
680                 intf_MsgImm( "\nPress the RETURN key to continue..." );
681                 getchar();
682             }
683 #endif
684             return( -1 );
685             break;
686         case 'H':                                          /* -H, --longhelp */
687             ShowConsole();
688             RedirectSTDOUT();
689             Usage( LONG_HELP );
690 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
691             if( strcmp( "", main_GetPszVariable( INTF_STDOUT_VAR,
692                                                  INTF_STDOUT_DEFAULT ) ) == 0 )
693             {
694                 /* No stdout redirection has been asked for */
695                 intf_MsgImm( "\nPress the RETURN key to continue..." );
696                 getchar();
697             }
698 #endif
699             return( -1 );
700             break;
701         case OPT_VERSION:                                       /* --version */
702             ShowConsole();
703             RedirectSTDOUT();
704             Version();
705 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
706             if( strcmp( "", main_GetPszVariable( INTF_STDOUT_VAR,
707                                                  INTF_STDOUT_DEFAULT ) ) == 0 )
708             {
709                 /* No stdout redirection has been asked for */
710                 intf_MsgImm( "\nPress the RETURN key to continue..." );
711                 getchar();
712             }
713 #endif
714             return( -1 );
715             break;
716         case 'v':                                           /* -v, --verbose */
717             p_main->i_warning_level++;
718             break;
719
720         /* Interface warning messages level */
721         case 'I':                                              /* -I, --intf */
722             main_PutPszVariable( INTF_METHOD_VAR, optarg );
723             break;
724         case OPT_WARNING:                                       /* --warning */
725             intf_ErrMsg( "intf error: `--warning' is deprecated, use `-v'" );
726             p_main->i_warning_level = atoi(optarg);
727             break;
728
729         case OPT_STDOUT:                                         /* --stdout */
730             main_PutPszVariable( INTF_STDOUT_VAR, optarg );
731             break;
732
733         case OPT_STATS:
734             p_main->b_stats = 1;
735             break;
736
737         /* Audio options */
738         case OPT_NOAUDIO:                                       /* --noaudio */
739             p_main->b_audio = 0;
740             break;
741         case 'A':                                              /* -A, --aout */
742             main_PutPszVariable( AOUT_METHOD_VAR, optarg );
743             break;
744         case OPT_STEREO:                                         /* --stereo */
745             main_PutIntVariable( AOUT_STEREO_VAR, 1 );
746             break;
747         case OPT_MONO:                                             /* --mono */
748             main_PutIntVariable( AOUT_STEREO_VAR, 0 );
749             break;
750         case OPT_SPDIF:                                           /* --spdif */
751             main_PutIntVariable( AOUT_SPDIF_VAR, 1 );
752             break;
753         case OPT_DOWNMIX:                                       /* --downmix */
754             main_PutPszVariable( DOWNMIX_METHOD_VAR, optarg );
755             break;
756         case OPT_IMDCT:                                           /* --imdct */
757             main_PutPszVariable( IMDCT_METHOD_VAR, optarg );
758             break;
759         case OPT_VOLUME:                                         /* --volume */
760             main_PutIntVariable( AOUT_VOLUME_VAR, atoi(optarg) );
761             break;
762         case OPT_DESYNC:                                         /* --desync */
763             p_main->i_desync = (mtime_t)atoi(optarg) * (mtime_t)1000;
764             break;
765
766         /* Video options */
767         case OPT_NOVIDEO:                                       /* --novideo */
768             p_main->b_video = 0;
769             break;
770         case 'V':                                              /* -V, --vout */
771             main_PutPszVariable( VOUT_METHOD_VAR, optarg );
772             break;
773         case OPT_DISPLAY:                                       /* --display */
774             main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
775             break;
776         case OPT_WIDTH:                                           /* --width */
777             main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
778             break;
779         case OPT_HEIGHT:                                         /* --height */
780             main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );
781             break;
782         case 'g':                                         /* -g, --grayscale */
783             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
784             break;
785         case OPT_COLOR:                                           /* --color */
786             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
787             break;
788         case OPT_FULLSCREEN:                                 /* --fullscreen */
789             main_PutIntVariable( VOUT_FULLSCREEN_VAR, 1 );
790             break;
791         case OPT_NOOVERLAY:                                   /* --nooverlay */
792             main_PutIntVariable( VOUT_NOOVERLAY_VAR, 1 );
793             break;
794         case OPT_XVADAPTOR:                                   /* --xvadaptor */
795             main_PutIntVariable( VOUT_XVADAPTOR_VAR, atoi(optarg) );
796             break;
797         case OPT_MOTION:                                         /* --motion */
798             main_PutPszVariable( MOTION_METHOD_VAR, optarg );
799             break;
800         case OPT_IDCT:                                             /* --idct */
801             main_PutPszVariable( IDCT_METHOD_VAR, optarg );
802             break;
803         case OPT_YUV:                                               /* --yuv */
804             main_PutPszVariable( YUV_METHOD_VAR, optarg );
805             break;
806         case OPT_SMP:                                               /* --smp */
807             main_PutIntVariable( VDEC_SMP_VAR, atoi(optarg) );
808             break;
809         case OPT_SPUMARGIN:                                   /* --spumargin */
810             main_PutIntVariable( VOUT_SPUMARGIN_VAR, atoi(optarg) );
811             break;
812
813         /* DVD options */
814         case 't':                                              /* --dvdtitle */
815             main_PutIntVariable( INPUT_TITLE_VAR, atoi(optarg) );
816             break;
817         case 'T':                                            /* --dvdchapter */
818             main_PutIntVariable( INPUT_CHAPTER_VAR, atoi(optarg) );
819             break;
820         case 'u':                                              /* --dvdangle */
821             main_PutIntVariable( INPUT_ANGLE_VAR, atoi(optarg) );
822             break;
823         case 'a':                                              /* --dvdaudio */
824             if ( ! strcmp(optarg, "ac3") )
825                 main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_AC3 );
826             else if ( ! strcmp(optarg, "lpcm") )
827                 main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_LPCM );
828             else if ( ! strcmp(optarg, "mpeg") )
829                 main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_MPEG );
830             else
831                 main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_NOAUDIO );
832             break;
833         case 'c':                                            /* --dvdchannel */
834             main_PutIntVariable( INPUT_CHANNEL_VAR, atoi(optarg) );
835             break;
836         case 's':                                           /* --dvdsubtitle */
837             main_PutIntVariable( INPUT_SUBTITLE_VAR, atoi(optarg) );
838             break;
839         case OPT_DVDCSS_METHOD:                           /* --dvdcss-method */
840             main_PutPszVariable( "DVDCSS_METHOD", optarg );
841             break;
842         case OPT_DVDCSS_VERBOSE:                         /* --dvdcss-verbose */
843             main_PutPszVariable( "DVDCSS_VERBOSE", optarg );
844             break;
845
846         /* Input options */
847         case OPT_INPUT:                                           /* --input */
848             main_PutPszVariable( INPUT_METHOD_VAR, optarg );
849             break;
850         case OPT_CHANNELS:                                     /* --channels */
851             main_PutIntVariable( INPUT_NETWORK_CHANNEL_VAR, 1 );
852             break;
853         case OPT_CHANNELSERVER:                           /* --channelserver */
854             main_PutPszVariable( INPUT_CHANNEL_SERVER_VAR, optarg );
855             break;
856
857         /* Misc options */
858         case OPT_SYNCHRO:
859             main_PutPszVariable( VPAR_SYNCHRO_VAR, optarg );
860             break;
861         case OPT_MEMCPY:
862             main_PutPszVariable( MEMCPY_METHOD_VAR, optarg );
863             break;
864         case OPT_FILTER:                                         /* --filter */
865             main_PutPszVariable( VOUT_FILTER_VAR, optarg );
866             break;
867
868         /* Decoder options */
869         case OPT_MPEG_ADEC:
870             main_PutPszVariable( ADEC_MPEG_VAR, optarg );
871             break;
872
873         case OPT_AC3_ADEC:
874             main_PutPszVariable( ADEC_AC3_VAR, optarg );
875             break;
876
877         /* CPU options */
878         case OPT_NOMMX:
879             p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMX;
880             break;
881
882         case OPT_NO3DNOW:
883             p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_3DNOW;
884             break;
885
886         case OPT_NOMMXEXT:
887             p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMXEXT;
888             break;
889
890         case OPT_NOSSE:
891             p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_SSE;
892             break;
893
894         case OPT_NOALTIVEC:
895             p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_ALTIVEC;
896             break;
897
898         /* Internal error: unknown option */
899         case '?':
900         default:
901             ShowConsole();
902             RedirectSTDOUT();
903             intf_ErrMsg( "intf error: unknown option `%s'",
904                          ppsz_argv[optind] );
905             Usage( USAGE );
906 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
907             if( strcmp( "", main_GetPszVariable( INTF_STDOUT_VAR,
908                                                  INTF_STDOUT_DEFAULT ) ) == 0 )
909             {
910                 /* No stdout redirection has been asked for */
911                 intf_MsgImm( "\nPress the RETURN key to continue..." );
912                 getchar();
913             }
914 #endif
915             return( EINVAL );
916             break;
917         }
918     }
919
920     if( p_main->i_warning_level < 0 )
921     {
922         p_main->i_warning_level = 0;
923     }
924
925     return( 0 );
926 }
927
928 /*****************************************************************************
929  * GetFilenames: parse command line options which are not flags
930  *****************************************************************************
931  * Parse command line for input files.
932  *****************************************************************************/
933 static int GetFilenames( int i_argc, char *ppsz_argv[] )
934 {
935     int i_opt;
936
937     /* We assume that the remaining parameters are filenames */
938     for( i_opt = optind; i_opt < i_argc; i_opt++ )
939     {
940         intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
941                           ppsz_argv[ i_opt ] );
942     }
943
944     return( 0 );
945 }
946
947 /*****************************************************************************
948  * Usage: print program usage
949  *****************************************************************************
950  * Print a short inline help. Message interface is initialized at this stage.
951  *****************************************************************************/
952 static void Usage( int i_fashion )
953 {
954     /* Usage */
955     intf_MsgImm( "Usage: %s [options] [parameters] [file]...",
956                  p_main->psz_arg0 );
957
958     if( i_fashion == USAGE )
959     {
960         intf_MsgImm( "Try `%s --help' for more information.",
961                      p_main->psz_arg0 );
962         return;
963     }
964
965     /* Options */
966     intf_MsgImm( "\nOptions:"
967           "\n  -I, --intf <module>            \tinterface method"
968           "\n  -v, --verbose                  \tverbose mode (cumulative)"
969           "\n      --stdout <filename>        \tredirect console stdout"
970           "\n      --memcpy <module>          \tmemcpy method"
971           "\n"
972           "\n      --noaudio                  \tdisable audio"
973           "\n  -A, --aout <module>            \taudio output method"
974           "\n      --stereo, --mono           \tstereo/mono audio"
975           "\n      --spdif                    \tAC3 pass-through mode"
976           "\n      --downmix <module>         \tAC3 downmix method"
977           "\n      --imdct <module>           \tAC3 IMDCT method"
978           "\n      --volume [0..1024]         \tVLC output volume"
979           "\n      --desync <time in ms>      \tCompensate desynchronization of the audio"
980           "\n"
981           "\n      --novideo                  \tdisable video"
982           "\n  -V, --vout <module>            \tvideo output method"
983           "\n      --display <display>        \tdisplay string"
984           "\n      --width <w>, --height <h>  \tdisplay dimensions"
985           "\n  -g, --grayscale                \tgrayscale output"
986           "\n      --fullscreen               \tfullscreen output"
987           "\n      --nooverlay                \tdisable accelerated display"
988           "\n      --xvadaptor <adaptor>      \tXVideo adaptor"
989           "\n      --color                    \tcolor output"
990           "\n      --motion <module>          \tmotion compensation method"
991           "\n      --idct <module>            \tIDCT method"
992           "\n      --yuv <module>             \tYUV method"
993           "\n      --synchro <type>           \tforce synchro algorithm"
994           "\n      --smp <number of threads>  \tuse several processors"
995           "\n      --spumargin <m>            \tforce SPU position"
996           "\n      --filter <module>          \tvideo filter module"
997           "\n"
998           "\n  -t, --dvdtitle <num>           \tchoose DVD title"
999           "\n  -T, --dvdchapter <num>         \tchoose DVD chapter"
1000           "\n  -u, --dvdangle <num>           \tchoose DVD angle"
1001           "\n  -a, --dvdaudio <type>          \tchoose DVD audio type"
1002           "\n  -c, --dvdchannel <channel>     \tchoose DVD audio channel"
1003           "\n  -s, --dvdsubtitle <channel>    \tchoose DVD subtitle channel"
1004           "\n      --dvdcss-method <method>   \tselect dvdcss decryption method"
1005           "\n      --dvdcss-verbose <level>   \tselect dvdcss verbose level"
1006           "\n"
1007           "\n      --input                    \tinput method"
1008           "\n      --channels                 \tenable channels"
1009           "\n      --channelserver <host>     \tchannel server address"
1010           "\n"
1011           "\n      --mpeg_adec <builtin|mad>  \tchoose MPEG audio decoder"
1012           "\n      --ac3_adec <builtin|a52>   \tchoose AC3 audio decoder"
1013           "\n"
1014           "\n      --nommx                    \tdisable CPU's MMX support"
1015           "\n      --no3dnow                  \tdisable CPU's 3D Now! support"
1016           "\n      --nommxext                 \tdisable CPU's MMX EXT support"
1017           "\n      --nosse                    \tdisable CPU's SSE support"
1018           "\n      --noaltivec                \tdisable CPU's AltiVec support"
1019           "\n"
1020           "\n  -h, --help                     \tprint help and exit"
1021           "\n  -H, --longhelp                 \tprint long help and exit"
1022           "\n      --version                  \toutput version information and exit"
1023           "\n\nPlaylist items:"
1024           "\n  *.mpg, *.vob                   \tPlain MPEG-1/2 files"
1025           "\n  dvd:<device>[@<raw device>]    \tDVD device"
1026           "\n  vcd:<device>                   \tVCD device"
1027           "\n  udpstream:[<server>[:<server port>]][@[<bind address>][:<bind port>]]"
1028           "\n                                 \tUDP stream sent by VLS"
1029           "\n  vlc:loop                       \tLoop execution of the playlist"
1030           "\n  vlc:pause                      \tPause execution of playlist items"
1031           "\n  vlc:quit                       \tQuit VLC");
1032
1033     if( i_fashion == SHORT_HELP )
1034         return;
1035
1036     /* Interface parameters */
1037     intf_MsgImm( "\nInterface parameters:"
1038         "\n  " INTF_METHOD_VAR "=<method name>        \tinterface method"
1039         "\n  " INTF_INIT_SCRIPT_VAR "=<filename>              \tinitialization script"
1040         "\n  " INTF_CHANNELS_VAR "=<filename>         \tchannels list"
1041         "\n  " INTF_STDOUT_VAR "=<filename>           \tredirect console stdout"
1042         "\n  " MEMCPY_METHOD_VAR "=<method name>      \tmemcpy method" );
1043
1044     /* Audio parameters */
1045     intf_MsgImm( "\nAudio parameters:"
1046         "\n  " AOUT_METHOD_VAR "=<method name>        \taudio method"
1047         "\n  " AOUT_DSP_VAR "=<filename>              \tdsp device path"
1048         "\n  " AOUT_STEREO_VAR "={1|0}                \tstereo or mono output"
1049         "\n  " AOUT_SPDIF_VAR "={1|0}                 \tAC3 pass-through mode"
1050         "\n  " DOWNMIX_METHOD_VAR "=<method name>     \tAC3 downmix method"
1051         "\n  " IMDCT_METHOD_VAR "=<method name>       \tAC3 IMDCT method"
1052         "\n  " AOUT_VOLUME_VAR "=[0..1024]            \tVLC output volume"
1053         "\n  " AOUT_RATE_VAR "=<rate>                 \toutput rate" );
1054
1055     /* Video parameters */
1056     intf_MsgImm( "\nVideo parameters:"
1057         "\n  " VOUT_METHOD_VAR "=<method name>        \tdisplay method"
1058         "\n  " VOUT_DISPLAY_VAR "=<display name>      \tdisplay used"
1059         "\n  " VOUT_WIDTH_VAR "=<width>               \tdisplay width"
1060         "\n  " VOUT_HEIGHT_VAR "=<height>             \tdislay height"
1061         "\n  " VOUT_FB_DEV_VAR "=<filename>           \tframebuffer device path"
1062         "\n  " VOUT_GRAYSCALE_VAR "={1|0}             \tgrayscale or color output"
1063         "\n  " VOUT_FULLSCREEN_VAR "={1|0}            \tfullscreen"
1064         "\n  " VOUT_NOOVERLAY_VAR "={1|0}             \tnooverlay"
1065         "\n  " VOUT_XVADAPTOR_VAR "=<adaptor>         \tXVideo adaptor"
1066         "\n  " MOTION_METHOD_VAR "=<method name>      \tmotion compensation method"
1067         "\n  " IDCT_METHOD_VAR "=<method name>        \tIDCT method"
1068         "\n  " YUV_METHOD_VAR "=<method name>         \tYUV method"
1069         "\n  " VPAR_SYNCHRO_VAR "={I|I+|IP|IP+|IPB}   \tsynchro algorithm"
1070         "\n  " VDEC_SMP_VAR "=<number of threads>     \tuse several processors"
1071         "\n  " VOUT_FILTER_VAR "=<method name>        \tvideo filter method"
1072         "\n  " VOUT_SPUMARGIN_VAR "=<margin>          \tforce SPU margin" );
1073
1074     /* DVD parameters */
1075     intf_MsgImm( "\nDVD parameters:"
1076         "\n  " INPUT_DVD_DEVICE_VAR "=<device>        \tDVD device"
1077         "\n  " INPUT_TITLE_VAR "=<title>              \ttitle number"
1078         "\n  " INPUT_CHAPTER_VAR "=<chapter>          \tchapter number"
1079         "\n  " INPUT_ANGLE_VAR "=<angle>              \tangle number"
1080         "\n  " INPUT_AUDIO_VAR "={ac3|lpcm|mpeg|off}  \taudio type"
1081         "\n  " INPUT_CHANNEL_VAR "=[0-15]             \taudio channel"
1082         "\n  " INPUT_SUBTITLE_VAR "=[0-31]            \tsubtitle channel" );
1083
1084     /* Input parameters */
1085     intf_MsgImm( "\nInput parameters:"
1086         "\n  " INPUT_IFACE_VAR "=<interface>          \tnetwork interface"
1087         "\n  " INPUT_CHANNEL_SERVER_VAR "=<hostname>  \tchannel server"
1088         "\n  " INPUT_CHANNEL_PORT_VAR "=<port>        \tchannel server port" );
1089
1090     /* Decoder parameters */
1091     intf_MsgImm( "\nDecoder parameters:"
1092         "\n  " ADEC_MPEG_VAR "=<builtin|mad>          \tMPEG audio decoder"
1093         "\n  " ADEC_AC3_VAR "=<builtin|a52>           \tAC3 audio decoder" );
1094 }
1095
1096 /*****************************************************************************
1097  * Version: print complete program version
1098  *****************************************************************************
1099  * Print complete program version and build number.
1100  *****************************************************************************/
1101 static void Version( void )
1102 {
1103     intf_MsgImm( VERSION_MESSAGE
1104         "This program comes with NO WARRANTY, to the extent permitted by law.\n"
1105         "You may redistribute it under the terms of the GNU General Public License;\n"
1106         "see the file named COPYING for details.\n"
1107         "Written by the VideoLAN team at Ecole Centrale, Paris." );
1108 }
1109
1110 /*****************************************************************************
1111  * InitSignalHandler: system signal handler initialization
1112  *****************************************************************************
1113  * Set the signal handlers. SIGTERM is not intercepted, because we need at
1114  * at least a method to kill the program when all other methods failed, and
1115  * when we don't want to use SIGKILL.
1116  *****************************************************************************/
1117 static void InitSignalHandler( void )
1118 {
1119     /* Termination signals */
1120 #ifndef WIN32
1121     signal( SIGINT,  FatalSignalHandler );
1122     signal( SIGHUP,  FatalSignalHandler );
1123     signal( SIGQUIT, FatalSignalHandler );
1124
1125     /* Other signals */
1126     signal( SIGALRM, SimpleSignalHandler );
1127     signal( SIGPIPE, SimpleSignalHandler );
1128 #endif
1129 }
1130
1131 /*****************************************************************************
1132  * SimpleSignalHandler: system signal handler
1133  *****************************************************************************
1134  * This function is called when a non fatal signal is received by the program.
1135  *****************************************************************************/
1136 static void SimpleSignalHandler( int i_signal )
1137 {
1138     /* Acknowledge the signal received */
1139     intf_WarnMsg( 0, "intf: ignoring signal %d", i_signal );
1140 }
1141
1142 /*****************************************************************************
1143  * FatalSignalHandler: system signal handler
1144  *****************************************************************************
1145  * This function is called when a fatal signal is received by the program.
1146  * It tries to end the program in a clean way.
1147  *****************************************************************************/
1148 static void FatalSignalHandler( int i_signal )
1149 {
1150     /* Once a signal has been trapped, the termination sequence will be
1151      * armed and following signals will be ignored to avoid sending messages
1152      * to an interface having been destroyed */
1153 #ifndef WIN32
1154     signal( SIGINT,  SIG_IGN );
1155     signal( SIGHUP,  SIG_IGN );
1156     signal( SIGQUIT, SIG_IGN );
1157 #endif
1158
1159     /* Acknowledge the signal received */
1160     intf_ErrMsgImm( "intf error: signal %d received, exiting", i_signal );
1161
1162     /* Try to terminate everything - this is done by requesting the end of the
1163      * interface thread */
1164     p_main->p_intf->b_die = 1;
1165 }
1166
1167 /*****************************************************************************
1168  * IllegalSignalHandler: system signal handler
1169  *****************************************************************************
1170  * This function is called when a illegal instruction signal is received by
1171  * the program. We use this function to test OS and CPU capabilities
1172  *****************************************************************************/
1173 static void IllegalSignalHandler( int i_signal )
1174 {
1175     /* Acknowledge the signal received */
1176     i_illegal = 1;
1177
1178 #ifdef HAVE_SIGRELSE
1179     sigrelse( i_signal );
1180 #endif
1181
1182     fprintf( stderr, "warning: your CPU has %s instructions, but not your "
1183                      "operating system.\n", psz_capability );
1184     fprintf( stderr, "         some optimizations will be disabled unless "
1185                      "you upgrade your OS\n" );
1186 #ifdef SYS_LINUX
1187     fprintf( stderr, "         (for instance Linux kernel 2.4.x or later)" );
1188 #endif
1189
1190     longjmp( env, 1 );
1191 }
1192
1193 /*****************************************************************************
1194  * CPUCapabilities: list the processors MMX support and other capabilities
1195  *****************************************************************************
1196  * This function is called to list extensions the CPU may have.
1197  *****************************************************************************/
1198 static u32 CPUCapabilities( void )
1199 {
1200     volatile u32 i_capabilities = CPU_CAPABILITY_NONE;
1201
1202 #if defined( SYS_DARWIN )
1203     struct host_basic_info hi;
1204     kern_return_t          ret;
1205     host_name_port_t       host;
1206
1207     int i_size;
1208     char *psz_name, *psz_subname;
1209
1210     i_capabilities |= CPU_CAPABILITY_FPU;
1211
1212     /* Should 'never' fail? */
1213     host = mach_host_self();
1214
1215     i_size = sizeof( hi ) / sizeof( int );
1216     ret = host_info( host, HOST_BASIC_INFO, ( host_info_t )&hi, &i_size );
1217
1218     if( ret != KERN_SUCCESS )
1219     {
1220         fprintf( stderr, "error: couldn't get CPU information\n" );
1221         return( i_capabilities );
1222     }
1223
1224     slot_name( hi.cpu_type, hi.cpu_subtype, &psz_name, &psz_subname );
1225     /* FIXME: need better way to detect newer proccessors.
1226      * could do strncmp(a,b,5), but that's real ugly */
1227     if( !strcmp(psz_name, "ppc7400") || !strcmp(psz_name, "ppc7450") )
1228     {
1229         i_capabilities |= CPU_CAPABILITY_ALTIVEC;
1230     }
1231
1232     return( i_capabilities );
1233
1234 #elif defined( __i386__ )
1235     volatile unsigned int  i_eax, i_ebx, i_ecx, i_edx;
1236     volatile boolean_t     b_amd;
1237
1238     /* Needed for x86 CPU capabilities detection */
1239 #   define cpuid( a )                      \
1240         asm volatile ( "pushl %%ebx\n\t"   \
1241                        "cpuid\n\t"         \
1242                        "movl %%ebx,%1\n\t" \
1243                        "popl %%ebx\n\t"    \
1244                      : "=a" ( i_eax ),     \
1245                        "=r" ( i_ebx ),     \
1246                        "=c" ( i_ecx ),     \
1247                        "=d" ( i_edx )      \
1248                      : "a"  ( a )          \
1249                      : "cc" );
1250
1251     i_capabilities |= CPU_CAPABILITY_FPU;
1252
1253 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1254     signal( SIGILL, IllegalSignalHandler );
1255 #   endif
1256
1257     /* test for a 486 CPU */
1258     asm volatile ( "pushl %%ebx\n\t"
1259                    "pushfl\n\t"
1260                    "popl %%eax\n\t"
1261                    "movl %%eax, %%ebx\n\t"
1262                    "xorl $0x200000, %%eax\n\t"
1263                    "pushl %%eax\n\t"
1264                    "popfl\n\t"
1265                    "pushfl\n\t"
1266                    "popl %%eax\n\t"
1267                    "movl %%ebx,%1\n\t"
1268                    "popl %%ebx\n\t"
1269                  : "=a" ( i_eax ),
1270                    "=r" ( i_ebx )
1271                  :
1272                  : "cc" );
1273
1274     if( i_eax == i_ebx )
1275     {
1276 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1277         signal( SIGILL, NULL );
1278 #   endif
1279         return( i_capabilities );
1280     }
1281
1282     i_capabilities |= CPU_CAPABILITY_486;
1283
1284     /* the CPU supports the CPUID instruction - get its level */
1285     cpuid( 0x00000000 );
1286
1287     if( !i_eax )
1288     {
1289 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1290         signal( SIGILL, NULL );
1291 #   endif
1292         return( i_capabilities );
1293     }
1294
1295     /* FIXME: this isn't correct, since some 486s have cpuid */
1296     i_capabilities |= CPU_CAPABILITY_586;
1297
1298     /* borrowed from mpeg2dec */
1299     b_amd = ( i_ebx == 0x68747541 ) && ( i_ecx == 0x444d4163 )
1300                     && ( i_edx == 0x69746e65 );
1301
1302     /* test for the MMX flag */
1303     cpuid( 0x00000001 );
1304
1305     if( ! (i_edx & 0x00800000) )
1306     {
1307 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1308         signal( SIGILL, NULL );
1309 #   endif
1310         return( i_capabilities );
1311     }
1312
1313     i_capabilities |= CPU_CAPABILITY_MMX;
1314
1315     if( i_edx & 0x02000000 )
1316     {
1317         i_capabilities |= CPU_CAPABILITY_MMXEXT;
1318
1319 #   ifdef CAN_COMPILE_SSE
1320         /* We test if OS support the SSE instructions */
1321         psz_capability = "SSE";
1322         i_illegal = 0;
1323         if( setjmp( env ) == 0 )
1324         {
1325             /* Test a SSE instruction */
1326             __asm__ __volatile__ ( "xorps %%xmm0,%%xmm0\n" : : );
1327         }
1328
1329         if( i_illegal == 0 )
1330         {
1331             i_capabilities |= CPU_CAPABILITY_SSE;
1332         }
1333 #   endif
1334     }
1335
1336     /* test for additional capabilities */
1337     cpuid( 0x80000000 );
1338
1339     if( i_eax < 0x80000001 )
1340     {
1341 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1342         signal( SIGILL, NULL );
1343 #   endif
1344         return( i_capabilities );
1345     }
1346
1347     /* list these additional capabilities */
1348     cpuid( 0x80000001 );
1349
1350 #   ifdef CAN_COMPILE_3DNOW
1351     if( i_edx & 0x80000000 )
1352     {
1353         psz_capability = "3D Now!";
1354         i_illegal = 0;
1355         if( setjmp( env ) == 0 )
1356         {
1357             /* Test a 3D Now! instruction */
1358             __asm__ __volatile__ ( "pfadd %%mm0,%%mm0\n" "femms\n" : : );
1359         }
1360
1361         if( i_illegal == 0 )
1362         {
1363             i_capabilities |= CPU_CAPABILITY_3DNOW;
1364         }
1365     }
1366 #   endif
1367
1368     if( b_amd && ( i_edx & 0x00400000 ) )
1369     {
1370         i_capabilities |= CPU_CAPABILITY_MMXEXT;
1371     }
1372
1373 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1374     signal( SIGILL, NULL );
1375 #   endif
1376     return( i_capabilities );
1377
1378 #elif defined( __powerpc__ )
1379
1380     i_capabilities |= CPU_CAPABILITY_FPU;
1381
1382 #   ifdef CAN_COMPILE_ALTIVEC
1383     signal( SIGILL, IllegalSignalHandler );
1384
1385     psz_capability = "AltiVec";
1386     i_illegal = 0;
1387     if( setjmp( env ) == 0 )
1388     {
1389         asm volatile ("mtspr 256, %0\n\t"
1390                       "vand %%v0, %%v0, %%v0"
1391                       :
1392                       : "r" (-1));
1393     }
1394
1395     if( i_illegal == 0 )
1396     {
1397         i_capabilities |= CPU_CAPABILITY_ALTIVEC;
1398     }
1399
1400     signal( SIGILL, NULL );
1401 #   endif
1402
1403     return( i_capabilities );
1404
1405 #else
1406     /* default behaviour */
1407     return( i_capabilities );
1408
1409 #endif
1410 }
1411
1412 /*****************************************************************************
1413  * RedirectSTDOUT: redirect stdout and stderr to a file
1414  *****************************************************************************
1415  * This function will redirect stdout and stderr to a file if the user has
1416  * specified so.
1417  *****************************************************************************/
1418 static int RedirectSTDOUT( void )
1419 {
1420     int  i_fd;
1421     char *psz_filename;
1422
1423     psz_filename = main_GetPszVariable( INTF_STDOUT_VAR, INTF_STDOUT_DEFAULT );
1424
1425     if( *psz_filename )
1426     {
1427         ShowConsole();
1428         i_fd = open( psz_filename, O_CREAT | O_TRUNC | O_RDWR,
1429                                    S_IREAD | S_IWRITE );
1430         if( dup2( i_fd, fileno(stdout) ) == -1 )
1431         {
1432             intf_ErrMsg( "warning: unable to redirect stdout" );
1433         }
1434
1435         if( dup2( i_fd, fileno(stderr) ) == -1 )
1436         {
1437             intf_ErrMsg( "warning: unable to redirect stderr" );
1438         }
1439
1440         close( i_fd );
1441     }
1442     else
1443     {
1444         /* No stdout redirection has been asked so open a console */
1445         if( p_main->i_warning_level )
1446         {
1447             ShowConsole();
1448         }
1449
1450     }
1451
1452     return 0;
1453 }
1454
1455 /*****************************************************************************
1456  * ShowConsole: On Win32, create an output console for debug messages
1457  *****************************************************************************
1458  * This function is usefull only on Win32.
1459  *****************************************************************************/
1460 static void ShowConsole( void )
1461 {
1462 #ifdef WIN32 /*  */
1463     AllocConsole();
1464     freopen( "CONOUT$", "w", stdout );
1465     freopen( "CONOUT$", "w", stderr );
1466     freopen( "CONIN$", "r", stdin );
1467 #endif
1468     return;
1469 }