]> git.sesse.net Git - vlc/blob - src/interface/main.c
* filters were using memalign but freeing p_data instead of p_data_orig.
[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.193 2002/05/19 12:57:32 gbazin Exp $
8  *
9  * Authors: Vincent Seguin <seguin@via.ecp.fr>
10  *          Samuel Hocevar <sam@zoy.org>
11  *          Gildas Bazin <gbazin@netcourrier.com>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
26  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include <signal.h>                               /* SIGHUP, SIGINT, SIGKILL */
32 #include <stdio.h>                                              /* sprintf() */
33 #include <setjmp.h>                                       /* longjmp, setjmp */
34
35 #include <videolan/vlc.h>
36
37 #ifdef HAVE_GETOPT_LONG
38 #   ifdef HAVE_GETOPT_H
39 #       include <getopt.h>                                       /* getopt() */
40 #   endif
41 #else
42 #   include "GNUgetopt/getopt.h"
43 #endif
44
45 #ifdef SYS_DARWIN
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>
50 #endif
51
52 #ifndef WIN32
53 #   include <netinet/in.h>                            /* BSD: struct in_addr */
54 #endif
55
56 #ifdef HAVE_UNISTD_H
57 #   include <unistd.h>
58 #elif defined( _MSC_VER ) && defined( _WIN32 )
59 #   include <io.h>
60 #endif
61
62 #ifdef HAVE_LOCALE_H
63 #   include <locale.h>
64 #endif
65
66 #include <errno.h>                                                 /* ENOMEM */
67 #include <stdlib.h>                                  /* getenv(), strtol(),  */
68 #include <string.h>                                            /* strerror() */
69
70 #include "netutils.h"                                 /* network_ChannelJoin */
71
72 #include "stream_control.h"
73 #include "input_ext-intf.h"
74
75 #include "intf_playlist.h"
76 #include "interface.h"
77
78 #include "audio_output.h"
79
80 #include "video.h"
81 #include "video_output.h"
82
83 /*****************************************************************************
84  * Configuration options for the main program. Each module will also separatly
85  * define its own configuration options.
86  * Look into configuration.h if you need to know more about the following
87  * macros.
88  *
89  *****************************************************************************/
90 #define __BUILTIN__
91 #define MODULE_NAME main
92 #include "modules_inner.h"                        /* for configuration stuff */
93
94
95 #define INTF_TEXT N_("interface module")
96 #define INTF_LONGTEXT N_( \
97     "This option allows you to select the interface used by vlc.\nNote that " \
98     "the default behavior is to automatically select the best module " \
99     "available.")
100
101 #define WARNING_TEXT N_("warning level (or use -v, -vv, etc...)")
102 #define WARNING_LONGTEXT N_( \
103     "Increasing the warning level will allow you to see more debug messages " \
104     "and can sometimes help you to troubleshoot a problem.")
105
106 #define STATS_TEXT N_("output statistics")
107 #define STATS_LONGTEXT N_( \
108     "Enabling the stats mode will flood your log console with various " \
109     "statistics messages.")
110
111 #define INTF_PATH_TEXT N_("interface default search path")
112 #define INTF_PATH_LONGTEXT N_( \
113     "This option allows you to set the default path that the interface will " \
114     "open when looking for a file.")
115
116 #define AOUT_TEXT N_("audio output module")
117 #define AOUT_LONGTEXT N_( \
118     "This option allows you to select the audio audio output method used by " \
119     "vlc.\nNote that the default behavior is to automatically select the " \
120     "best method available.")
121
122 #define NOAUDIO_TEXT N_("disable audio")
123 #define NOAUDIO_LONGTEXT N_( \
124     "This will completely disable the audio output. The audio decoding " \
125     "stage shouldn't even be done, so it can allow you to save some " \
126     "processing power.")
127
128 #define MONO_TEXT N_("mono audio")
129 #define MONO_LONGTEXT N_("This will force a mono audio output")
130
131 #define VOLUME_TEXT N_("audio output volume")
132 #define VOLUME_LONGTEXT N_( \
133     "You can set the default audio output volume here, in a range from 0 to " \
134     "1024.")
135
136 #define FORMAT_TEXT N_("audio output format")
137 #define FORMAT_LONGTEXT N_( \
138     "You can force the audio output format here.\n" \
139     "0 -> 16 bits signed native endian (default)\n" \
140     "1 ->  8 bits unsigned\n"                       \
141     "2 -> 16 bits signed little endian\n"           \
142     "3 -> 16 bits signed big endian\n"              \
143     "4 ->  8 bits signed\n"                         \
144     "5 -> 16 bits unsigned little endian\n"         \
145     "6 -> 16 bits unsigned big endian\n"            \
146     "7 -> mpeg2 audio (unsupported)\n"              \
147     "8 -> ac3 pass-through")
148
149 #define RATE_TEXT N_("audio output frequency (Hz)")
150 #define RATE_LONGTEXT N_( \
151     "You can force the audio output frequency here.\nCommon values are " \
152     "48000, 44100, 32000, 22050, 16000, 11025, 8000.")
153
154 #define DESYNC_TEXT N_("compensate desynchronization of audio (in ms)")
155 #define DESYNC_LONGTEXT N_( \
156     "This option allows you to delay the audio output. This can be handy if " \
157     "you notice a lag between the video and the audio.")
158
159 #define VOUT_TEXT N_("video output module")
160 #define VOUT_LONGTEXT N_( \
161     "This option allows you to select the video output method used by vlc.\n" \
162     "Note that the default behavior is to automatically select the best " \
163     "method available.")
164
165 #define NOVIDEO_TEXT N_("disable video")
166 #define NOVIDEO_LONGTEXT N_( \
167     "This will completely disable the video output. The video decoding " \
168     "stage shouldn't even be done, so it can allow you to save some " \
169     "processing power.")
170
171 #define DISPLAY_TEXT N_("display identifier")
172 #define DISPLAY_LONGTEXT N_( \
173     "This is the local display port that will be used for X11 drawing. " \
174     "For instance :0.1.")
175
176 #define WIDTH_TEXT N_("video width")
177 #define WIDTH_LONGTEXT N_( \
178     "You can enforce the video width here.\nNote that by default vlc will " \
179     "adapt to the video characteristics.")
180
181 #define HEIGHT_TEXT N_("video height")
182 #define HEIGHT_LONGTEXT N_( \
183     "You can enforce the video height here.\nNote that by default vlc will " \
184     "adapt to the video characteristics.")
185
186 #define ZOOM_TEXT N_("zoom video")
187 #define ZOOM_LONGTEXT N_( \
188     "You can zoom the video by the specified factor.")
189
190 #define GRAYSCALE_TEXT N_("grayscale video output")
191 #define GRAYSCALE_LONGTEXT N_( \
192     "Using this option, vlc will not decode the color information from the " \
193     "video (this can also allow you to save some processing power).")
194
195 #define FULLSCREEN_TEXT N_("fullscreen video output")
196 #define FULLSCREEN_LONGTEXT N_( \
197     "If this option is enabled, vlc will always start a video in fullscreen " \
198     "mode.")
199
200 #define NOOVERLAY_TEXT N_("disable hardware acceleration for the video output")
201 #define NOOVERLAY_LONGTEXT N_( \
202     "By default vlc will try to take advantage of the overlay capabilities " \
203     "of you graphics card.")
204
205 #define SPUMARGIN_TEXT N_("force SPU position")
206 #define SPUMARGIN_LONGTEXT N_( \
207     "You can use this option to place the sub-titles under the movie, " \
208     "instead of over the movie. Try several positions.")
209
210 #define FILTER_TEXT N_("video filter module")
211 #define FILTER_LONGTEXT N_( \
212     "This will allow you to add a post-processing filter to enhance the " \
213     "picture quality, for instance deinterlacing, or to clone or distort " \
214     "the video window.")
215
216 #define SERVER_PORT_TEXT N_("server port")
217 #define SERVER_PORT_LONGTEXT N_( \
218     "This is the port used for UDP streams. By default, we chose 1234.")
219
220 #define NETCHANNEL_TEXT N_("enable network channel mode")
221 #define NETCHANNEL_LONGTEXT N_( \
222     "Activate this option if you want to use the VideoLAN Channel Server.")
223
224 #define CHAN_SERV_TEXT N_("channel server address")
225 #define CHAN_SERV_LONGTEXT N_( \
226     "Indicate here the address of the VideoLAN Channel Server.")
227
228 #define CHAN_PORT_TEXT N_("channel server port")
229 #define CHAN_PORT_LONGTEXT N_( \
230     "Indicate here the port on which the VideoLAN Channel Server runs.")
231
232 #define IFACE_TEXT N_("network interface")
233 #define IFACE_LONGTEXT N_( \
234     "If you have several interfaces on your Linux machine and use the " \
235     "VLAN solution, you may indicate here which interface to use.")
236
237 #define INPUT_PROGRAM_TEXT N_("choose program (SID)")
238 #define INPUT_PROGRAM_LONGTEXT N_( \
239     "Choose the program to select by giving its Service ID.")
240
241 #define INPUT_AUDIO_TEXT N_("choose audio")
242 #define INPUT_AUDIO_LONGTEXT N_( \
243     "Give the default type of audio you want to use in a DVD.")
244
245 #define INPUT_CHAN_TEXT N_("choose channel")
246 #define INPUT_CHAN_LONGTEXT N_( \
247     "Give the stream number of the audio channel you want to use in a DVD " \
248     "(from 1 to n).")
249
250 #define INPUT_SUBT_TEXT N_("choose subtitles")
251 #define INPUT_SUBT_LONGTEXT N_( \
252     "Give the stream number of the subtitle channel you want to use in a DVD " \
253     "(from 1 to n).")
254
255 #define DVD_DEV_TEXT N_("DVD device")
256 #define DVD_DEV_LONGTEXT N_( \
257     "This is the default DVD device to use.")
258
259 #define VCD_DEV_TEXT N_("VCD device")
260 #define VCD_DEV_LONGTEXT N_( \
261     "This is the default VCD device to use.")
262
263 #define IPV6_TEXT N_("force IPv6")
264 #define IPV6_LONGTEXT N_( \
265     "If you check this box, IPv6 will be used by default for all UDP and " \
266     "HTTP connections.")
267
268 #define IPV4_TEXT N_("force IPv4")
269 #define IPV4_LONGTEXT N_( \
270     "If you check this box, IPv4 will be used by default for all UDP and " \
271     "HTTP connections.")
272
273 #define ADEC_MPEG_TEXT N_("choose MPEG audio decoder")
274 #define ADEC_MPEG_LONGTEXT N_( \
275     "This allows you to select the MPEG audio decoder you want to use. " \
276     "Common choices are builtin and mad.")
277
278 #define ADEC_AC3_TEXT N_("choose AC3 audio decoder")
279 #define ADEC_AC3_LONGTEXT N_( \
280     "This allows you to select the AC3/A52 audio decoder you want to use. " \
281     "Common choices are builtin and a52.")
282
283 #define NOMMX_TEXT N_("disable CPU's MMX support")
284 #define NOMMX_LONGTEXT N_( \
285     "If your processor supports the MMX instructions set but you don't want " \
286     "vlc to use them, you can use this option.")
287
288 #define NO3DN_TEXT N_("disable CPU's 3D Now! support")
289 #define NO3DN_LONGTEXT N_( \
290     "If your processor supports the 3D Now! instructions set but you don't " \
291     "want vlc to use them, you can use this option.")
292
293 #define NOMMXEXT_TEXT N_("disable CPU's MMX EXT support")
294 #define NOMMXEXT_LONGTEXT N_( \
295     "If your processor supports the MMX EXT instructions set but you don't " \
296     "want vlc to use them, you can use this option.")
297
298 #define NOSSE_TEXT N_("disable CPU's SSE support")
299 #define NOSSE_LONGTEXT N_( \
300     "If your processor supports the SSE instructions set but you don't want " \
301     "vlc to use them, you can use this option.")
302
303 #define NOALTIVEC_TEXT N_("disable CPU's AltiVec support")
304 #define NOALTIVEC_LONGTEXT N_( \
305     "If your processor supports the AltiVec instructions set but you don't " \
306     "want vlc to use them, you can use this option.")
307
308 #define PLAYLIST_LAUNCH_TEXT N_("launch playlist on startup")
309 #define PLAYLIST_LAUNCH_LONGTEXT N_( \
310     "If you want vlc to start playing on startup, then enable this option.")
311
312 #define PLAYLIST_ENQUEUE_TEXT N_("enqueue playlist as default")
313 #define PLAYLIST_ENQUEUE_LONGTEXT N_( \
314     "If you want vlc to add items to the playlist as you open them, then " \
315     "enable this option.")
316
317 #define PLAYLIST_LOOP_TEXT N_("loop playlist on end")
318 #define PLAYLIST_LOOP_LONGTEXT N_( \
319     "If you want vlc to keep playing the playlist indefinitely then enable " \
320     "this option.")
321
322 #define MEMCPY_TEXT N_("memory copy module")
323 #define MEMCPY_LONGTEXT N_( \
324     "You can select wich memory copy module you want to use. By default vlc " \
325     "will select the fastest one supported by your hardware.")
326
327 #define FAST_PTHREAD_TEXT N_("fast pthread on NT/2K/XP (developpers only)")
328 #define FAST_PTHREAD_LONGTEXT N_( \
329     "On Windows NT/2K/XP we use a slow but correct pthread implementation, " \
330     "you can also use this faster implementation but you might experience " \
331     "problems with it.")
332
333 /*
334  * Quick usage guide for the configuration options:
335  *
336  * MODULE_CONFIG_START
337  * MODULE_CONFIG_STOP
338  * ADD_CATEGORY_HINT( N_(text), longtext )
339  * ADD_SUBCATEGORY_HINT( N_(text), longtext )
340  * ADD_STRING( option_name, value, p_callback, N_(text), N_(longtext) )
341  * ADD_FILE( option_name, psz_value, p_callback, N_(text), N_(longtext) )
342  * ADD_MODULE( option_name, psz_value, i_capability, p_callback,
343  *             N_(text), N_(longtext) )
344  * ADD_INTEGER( option_name, i_value, p_callback, N_(text), N_(longtext) )
345  * ADD_BOOL( option_name, p_callback, N_(text), N_(longtext) )
346  */
347
348 MODULE_CONFIG_START
349
350 /* Interface options */
351 ADD_CATEGORY_HINT( N_("Interface"), NULL)
352 ADD_MODULE_WITH_SHORT  ( "intf", 'I', MODULE_CAPABILITY_INTF, NULL, NULL, INTF_TEXT, INTF_LONGTEXT )
353 ADD_INTEGER ( "warning", 0, NULL, WARNING_TEXT, WARNING_LONGTEXT )
354 ADD_BOOL    ( "stats", NULL, STATS_TEXT, STATS_LONGTEXT )
355 ADD_STRING  ( "search-path", NULL, NULL, INTF_PATH_TEXT, INTF_PATH_LONGTEXT )
356
357 /* Audio options */
358 ADD_CATEGORY_HINT( N_("Audio"), NULL)
359 ADD_MODULE_WITH_SHORT  ( "aout", 'A', MODULE_CAPABILITY_AOUT, NULL, NULL, AOUT_TEXT, AOUT_LONGTEXT )
360 ADD_BOOL    ( "noaudio", NULL, NOAUDIO_TEXT, NOAUDIO_LONGTEXT )
361 ADD_BOOL    ( "mono", NULL, MONO_TEXT, MONO_LONGTEXT )
362 ADD_INTEGER ( "volume", VOLUME_DEFAULT, NULL, VOLUME_TEXT, VOLUME_LONGTEXT )
363 ADD_INTEGER ( "rate", 44100, NULL, RATE_TEXT, RATE_LONGTEXT )
364 ADD_INTEGER ( "desync", 0, NULL, DESYNC_TEXT, DESYNC_LONGTEXT )
365 ADD_INTEGER ( "audio-format", 0, NULL, FORMAT_TEXT,
366               FORMAT_LONGTEXT )
367
368 /* Video options */
369 ADD_CATEGORY_HINT( N_("Video"), NULL )
370 ADD_MODULE_WITH_SHORT  ( "vout", 'V', MODULE_CAPABILITY_VOUT, NULL, NULL, VOUT_TEXT, VOUT_LONGTEXT )
371 ADD_BOOL    ( "novideo", NULL, NOVIDEO_TEXT, NOVIDEO_LONGTEXT )
372 ADD_INTEGER ( "width", -1, NULL, WIDTH_TEXT, WIDTH_LONGTEXT )
373 ADD_INTEGER ( "height", -1, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT )
374 ADD_FLOAT   ( "zoom", 1, NULL, ZOOM_TEXT, ZOOM_LONGTEXT )
375 ADD_BOOL    ( "grayscale", NULL, GRAYSCALE_TEXT, GRAYSCALE_LONGTEXT )
376 ADD_BOOL    ( "fullscreen", NULL, FULLSCREEN_TEXT, FULLSCREEN_LONGTEXT )
377 ADD_BOOL    ( "nooverlay", NULL, NOOVERLAY_TEXT, NOOVERLAY_LONGTEXT )
378 ADD_INTEGER ( "spumargin", -1, NULL, SPUMARGIN_TEXT, SPUMARGIN_LONGTEXT )
379 ADD_MODULE  ( "filter", MODULE_CAPABILITY_VOUT, NULL, NULL, FILTER_TEXT, FILTER_LONGTEXT )
380
381 /* Input options */
382 ADD_CATEGORY_HINT( N_("Input"), NULL )
383 ADD_INTEGER ( "server-port", 1234, NULL, SERVER_PORT_TEXT, SERVER_PORT_LONGTEXT )
384 ADD_BOOL    ( "network-channel", NULL, NETCHANNEL_TEXT, NETCHANNEL_LONGTEXT )
385 ADD_STRING  ( "channel-server", "localhost", NULL, CHAN_SERV_TEXT, CHAN_SERV_LONGTEXT )
386 ADD_INTEGER ( "channel-port", 6010, NULL, CHAN_PORT_TEXT, CHAN_PORT_LONGTEXT )
387 ADD_STRING  ( "iface", "eth0", NULL, IFACE_TEXT, IFACE_LONGTEXT )
388
389 ADD_INTEGER ( "program", 0, NULL, INPUT_PROGRAM_TEXT, INPUT_PROGRAM_LONGTEXT )
390 ADD_INTEGER ( "audio-type", -1, NULL, INPUT_AUDIO_TEXT, INPUT_AUDIO_LONGTEXT )
391 ADD_INTEGER ( "audio-channel", -1, NULL, INPUT_CHAN_TEXT, INPUT_CHAN_LONGTEXT )
392 ADD_INTEGER ( "spu-channel", -1, NULL, INPUT_SUBT_TEXT, INPUT_SUBT_LONGTEXT )
393
394 ADD_STRING  ( "dvd", DVD_DEVICE, NULL, DVD_DEV_TEXT, DVD_DEV_LONGTEXT )
395 ADD_STRING  ( "vcd", VCD_DEVICE, NULL, VCD_DEV_TEXT, VCD_DEV_LONGTEXT )
396
397 ADD_BOOL_WITH_SHORT    ( "ipv6", '6', NULL, IPV6_TEXT, IPV6_LONGTEXT )
398 ADD_BOOL_WITH_SHORT    ( "ipv4", '4', NULL, IPV4_TEXT, IPV4_LONGTEXT )
399
400 /* Decoder options */
401 ADD_CATEGORY_HINT( N_("Decoders"), NULL )
402 ADD_MODULE  ( "mpeg-adec", MODULE_CAPABILITY_DECODER, NULL, NULL, ADEC_MPEG_TEXT, ADEC_MPEG_LONGTEXT )
403 ADD_MODULE  ( "ac3-adec", MODULE_CAPABILITY_DECODER, NULL, NULL, ADEC_AC3_TEXT, ADEC_AC3_LONGTEXT )
404
405 /* CPU options */
406 ADD_CATEGORY_HINT( N_("CPU"), NULL )
407 ADD_BOOL    ( "nommx", NULL, NOMMX_TEXT, NOMMX_LONGTEXT )
408 ADD_BOOL    ( "no3dn", NULL, NO3DN_TEXT, NO3DN_LONGTEXT )
409 ADD_BOOL    ( "nommxext", NULL, NOMMXEXT_TEXT, NOMMXEXT_LONGTEXT )
410 ADD_BOOL    ( "nosse", NULL, NOSSE_TEXT, NOSSE_LONGTEXT )
411 ADD_BOOL    ( "noaltivec", NULL, NOALTIVEC_TEXT, NOALTIVEC_LONGTEXT )
412
413 /* Playlist options */
414 ADD_CATEGORY_HINT( N_("Playlist"), NULL )
415 ADD_BOOL    ( "launch-playlist", NULL, PLAYLIST_LAUNCH_TEXT, PLAYLIST_LAUNCH_LONGTEXT )
416 ADD_BOOL    ( "enqueue-playlist", NULL, PLAYLIST_ENQUEUE_TEXT, PLAYLIST_ENQUEUE_LONGTEXT )
417 ADD_BOOL    ( "loop-playlist", NULL, PLAYLIST_LOOP_TEXT, PLAYLIST_LOOP_LONGTEXT )
418
419 /* Misc options */
420 ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL )
421 ADD_MODULE  ( "memcpy", MODULE_CAPABILITY_MEMCPY, NULL, NULL, MEMCPY_TEXT, MEMCPY_LONGTEXT )
422 ADD_MODULE  ( "access", MODULE_CAPABILITY_ACCESS, NULL, NULL, "access module", "This is a legacy entry to let you configure access modules" )
423 ADD_MODULE  ( "demux", MODULE_CAPABILITY_DEMUX, NULL, NULL, "demux module", "This is a legacy entry to let you configure demux modules" )
424
425 #if defined(WIN32)
426 ADD_BOOL    ( "fast_pthread", NULL, FAST_PTHREAD_TEXT, FAST_PTHREAD_LONGTEXT )
427 #endif
428
429 MODULE_CONFIG_STOP
430
431 MODULE_INIT_START
432     SET_DESCRIPTION( N_("main program") )
433     ADD_CAPABILITY( MAIN, 100/*whatever*/ )
434 MODULE_INIT_STOP
435
436 MODULE_ACTIVATE_START
437 MODULE_ACTIVATE_STOP
438
439 MODULE_DEACTIVATE_START
440 MODULE_DEACTIVATE_STOP
441
442 /* Hack for help options */
443 static module_t help_module;
444 static module_config_t p_help_config[] =
445 {
446     { MODULE_CONFIG_ITEM_BOOL, "help", 'h', N_("print help"),
447       NULL, NULL, 0, 0, NULL, NULL, 0 },
448     { MODULE_CONFIG_ITEM_BOOL, "longhelp", 'H', N_("print detailed help"),
449       NULL, NULL, 0, 0, NULL, NULL, 0 },
450     { MODULE_CONFIG_ITEM_BOOL, "list", 'l', N_("print a list of available "
451       "modules"), NULL, NULL, 0, 0, NULL, NULL, 0 },
452     { MODULE_CONFIG_ITEM_STRING, "module", 'p', N_("print help on module "
453       "<string>"), NULL, NULL, 0, 0, NULL, &help_module.config_lock, 0 },
454     { MODULE_CONFIG_ITEM_BOOL, "version", '\0',
455       N_("print version information"), NULL, NULL, 0, 0, NULL, NULL, 0 },
456     { MODULE_CONFIG_HINT_END, NULL, '\0', NULL, NULL, NULL, 0, 0,
457       NULL, NULL, 0 }
458 };
459
460 /*****************************************************************************
461  * End configuration.
462  *****************************************************************************/
463
464 /*****************************************************************************
465  * Global variables - these are the only ones, see main.h and modules.h
466  *****************************************************************************/
467 main_t        *p_main;
468 module_bank_t *p_module_bank;
469 input_bank_t  *p_input_bank;
470 aout_bank_t   *p_aout_bank;
471 vout_bank_t   *p_vout_bank;
472
473 /*****************************************************************************
474  * Local prototypes
475  *****************************************************************************/
476 static int  GetFilenames                ( int i_argc, char *ppsz_argv[] );
477 static void Usage                       ( const char *psz_module_name );
478 static void ListModules                 ( void );
479 static void Version                     ( void );
480
481 static void InitSignalHandler           ( void );
482 static void SimpleSignalHandler         ( int i_signal );
483 static void FatalSignalHandler          ( int i_signal );
484 static void IllegalSignalHandler        ( int i_signal );
485 static u32  CPUCapabilities             ( void );
486
487 #ifdef WIN32
488 static void ShowConsole                 ( void );
489 #endif
490
491 static jmp_buf env;
492 static int     i_illegal;
493 static char   *psz_capability;
494
495 /*****************************************************************************
496  * main: parse command line, start interface and spawn threads
497  *****************************************************************************
498  * Steps during program execution are:
499  *      -configuration parsing and messages interface initialization
500  *      -opening of audio output device and some global modules
501  *      -execution of interface, which exit on error or on user request
502  *      -closing of audio output device and some global modules
503  * On error, the spawned threads are canceled, and the open devices closed.
504  *****************************************************************************/
505 int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
506 {
507     main_t        main_data;                /* root of all data - see main.h */
508     module_bank_t module_bank;
509     input_bank_t  input_bank;
510     aout_bank_t   aout_bank;
511     vout_bank_t   vout_bank;
512     char *psz_module;
513     char *p_tmp;
514     struct module_config_s *p_item;
515
516     p_main        = &main_data;               /* set up the global variables */
517     p_module_bank = &module_bank;
518     p_input_bank  = &input_bank;
519     p_aout_bank   = &aout_bank;
520     p_vout_bank   = &vout_bank;
521
522     p_main->i_warning_level = 0;
523
524     /*
525      * Support for gettext
526      */
527 #if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
528 #   if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
529     if( !setlocale( LC_MESSAGES, "" ) )
530     {
531         fprintf( stderr, "warning: unsupported locale settings\n" );
532     }
533
534     setlocale( LC_CTYPE, "" );
535 #   endif
536
537     if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
538     {
539         fprintf( stderr, "warning: no domain %s in directory %s\n",
540                  PACKAGE, LOCALEDIR );
541     }
542
543     textdomain( PACKAGE );
544 #endif
545
546     /*
547      * Initialize threads system
548      */
549     vlc_threads_init();
550
551     /*
552      * Test if our code is likely to run on this CPU
553      */
554     p_main->i_cpu_capabilities = CPUCapabilities();
555
556     /*
557      * System specific initialization code
558      */
559 #if defined( SYS_BEOS ) || defined( SYS_DARWIN ) || defined( WIN32 )
560     system_Init( &i_argc, ppsz_argv, ppsz_env );
561
562 #elif defined( SYS_LINUX )
563 #   ifdef DEBUG
564     /* Activate malloc checking routines to detect heap corruptions. */
565     putenv( "MALLOC_CHECK_=2" );
566     putenv( "GNOME_DISABLE_CRASH_DIALOG=1" );
567 #   endif
568 #endif
569
570     /*
571      * Initialize messages interface
572      */
573     intf_MsgCreate();
574
575     intf_Msg( COPYRIGHT_MESSAGE "\n" );
576
577
578     /* Get the executable name (similar to the basename command) */
579     if( i_argc > 0 )
580     {
581         p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
582         while( *p_tmp )
583         {
584             if( *p_tmp == '/' ) p_main->psz_arg0 = ++p_tmp;
585             else ++p_tmp;
586         }
587     }
588     else
589     {
590         p_main->psz_arg0 = "vlc";
591     }
592
593     /*
594      * Initialize the module bank and and load the configuration of the main
595      * module. We need to do this at this stage to be able to display a short
596      * help if required by the user. (short help == main module options)
597      */
598     module_InitBank();
599     module_LoadMain();
600
601     /* Hack: insert the help module here */
602     help_module.psz_name = "help";
603     help_module.psz_longname = _( "help module" );
604     help_module.i_config_items =
605                     sizeof(p_help_config) / sizeof(module_config_t) - 1;
606     vlc_mutex_init( &help_module.config_lock );
607     help_module.p_config = config_Duplicate( p_help_config );
608     for( p_item = help_module.p_config;
609          p_item->i_type != MODULE_CONFIG_HINT_END;
610          p_item++ )
611     {
612         p_item->p_lock = &help_module.config_lock;
613     }
614     help_module.next = p_module_bank->first;
615     p_module_bank->first = &help_module;
616     /* end hack */
617
618     if( config_LoadCmdLine( &i_argc, ppsz_argv, 1 ) )
619     {
620         intf_MsgDestroy();
621         return( errno );
622     }
623
624     /* Check for short help option */
625     if( config_GetIntVariable( "help" ) )
626     {
627         intf_Msg( _("Usage: %s [options] [parameters] [file]...\n"),
628                     p_main->psz_arg0 );
629
630         Usage( "help" );
631         Usage( "main" );
632         return( -1 );
633     }
634
635     /* Check for version option */
636     if( config_GetIntVariable( "version" ) )
637     {
638         Version();
639         return( -1 );
640     }
641
642     /* Hack: remove the help module here */
643     p_module_bank->first = help_module.next;
644     /* end hack */
645
646     /*
647      * Load the builtins and plugins into the module_bank.
648      * We have to do it before config_Load*() because this also gets the
649      * list of configuration options exported by each module and loads their
650      * default values.
651      */
652     module_LoadBuiltins();
653     module_LoadPlugins();
654     intf_WarnMsg( 2, "module: module bank initialized, found %i modules",
655                   p_module_bank->i_count );
656
657     /* Hack: insert the help module here */
658     help_module.next = p_module_bank->first;
659     p_module_bank->first = &help_module;
660     /* end hack */
661
662     /* Check for help on modules */
663     if( (p_tmp = config_GetPszVariable( "module" )) )
664     {
665         Usage( p_tmp );
666         free( p_tmp );
667         return( -1 );
668     }
669
670     /* Check for long help option */
671     if( config_GetIntVariable( "longhelp" ) )
672     {
673         Usage( NULL );
674         return( -1 );
675     }
676
677     /* Check for module list option */
678     if( config_GetIntVariable( "list" ) )
679     {
680         ListModules();
681         return( -1 );
682     }
683
684     /* Hack: remove the help module here */
685     p_module_bank->first = help_module.next;
686     /* end hack */
687
688
689     /*
690      * Override default configuration with config file settings
691      */
692     vlc_mutex_init( &p_main->config_lock );
693     p_main->psz_homedir = config_GetHomeDir();
694     config_LoadConfigFile( NULL );
695
696     /*
697      * Override configuration with command line settings
698      */
699     if( config_LoadCmdLine( &i_argc, ppsz_argv, 0 ) )
700     {
701 #ifdef WIN32
702         ShowConsole();
703         /* Pause the console because it's destroyed when we exit */
704         intf_Msg( "The command line options couldn't be loaded, check that "
705                   "they are valid.\nPress the RETURN key to continue..." );
706         getchar();
707 #endif
708         intf_MsgDestroy();
709         return( errno );
710     }
711
712
713     /*
714      * System specific configuration
715      */
716     system_Configure();
717
718     /* p_main inititalization. FIXME ? */
719     p_main->i_warning_level = config_GetIntVariable( "warning" );
720     p_main->i_desync = config_GetIntVariable( "desync" ) * (mtime_t)1000;
721     p_main->b_stats = config_GetIntVariable( "stats" );
722     p_main->b_audio = !config_GetIntVariable( "noaudio" );
723     p_main->b_stereo= !config_GetIntVariable( "mono" );
724     p_main->b_video = !config_GetIntVariable( "novideo" );
725     if( config_GetIntVariable( "nommx" ) )
726         p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMX;
727     if( config_GetIntVariable( "no3dn" ) )
728         p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_3DNOW;
729     if( config_GetIntVariable( "nommxext" ) )
730         p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_MMXEXT;
731     if( config_GetIntVariable( "nosse" ) )
732         p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_SSE;
733     if( config_GetIntVariable( "noaltivec" ) )
734         p_main->i_cpu_capabilities &= ~CPU_CAPABILITY_ALTIVEC;
735
736
737     if( p_main->b_stats )
738     {
739         char p_capabilities[200];
740         p_capabilities[0] = '\0';
741
742 #define PRINT_CAPABILITY( capability, string )                              \
743         if( p_main->i_cpu_capabilities & capability )                       \
744         {                                                                   \
745             strncat( p_capabilities, string " ",                            \
746                      sizeof(p_capabilities) - strlen(p_capabilities) );     \
747             p_capabilities[sizeof(p_capabilities) - 1] = '\0';              \
748         }
749
750         PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
751         PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
752         PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
753         PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
754         PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
755         PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
756         PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
757         PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "Altivec" );
758         PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
759         intf_StatMsg( "info: CPU has capabilities : %s", p_capabilities );
760     }
761
762     /*
763      * Initialize playlist and get commandline files
764      */
765     p_main->p_playlist = intf_PlaylistCreate();
766     if( !p_main->p_playlist )
767     {
768         intf_ErrMsg( "playlist error: playlist initialization failed" );
769         intf_MsgDestroy();
770         return( errno );
771     }
772     intf_PlaylistInit( p_main->p_playlist );
773
774     /*
775      * Get input filenames given as commandline arguments
776      */
777     GetFilenames( i_argc, ppsz_argv );
778
779     /*
780      * Initialize input, aout and vout banks
781      */
782     input_InitBank();
783     aout_InitBank();
784     vout_InitBank();
785
786     /*
787      * Choose the best memcpy module
788      */
789     psz_module = config_GetPszVariable( "memcpy" );
790     p_main->p_memcpy_module = module_Need( MODULE_CAPABILITY_MEMCPY,
791                                            psz_module, NULL );
792     if( psz_module ) free( psz_module );
793     if( p_main->p_memcpy_module == NULL )
794     {
795         intf_ErrMsg( "intf error: no suitable memcpy module, "
796                      "using libc default" );
797         p_main->pf_memcpy = memcpy;
798     }
799     else
800     {
801         p_main->pf_memcpy = p_main->p_memcpy_module->p_functions
802                                   ->memcpy.functions.memcpy.pf_memcpy;
803     }
804
805     /*
806      * Initialize shared resources and libraries
807      */
808     if( config_GetIntVariable( "network-channel" ) &&
809         network_ChannelCreate() )
810     {
811         /* On error during Channels initialization, switch off channels */
812         intf_ErrMsg( "intf error: channels initialization failed, "
813                                  "deactivating channels" );
814         config_PutIntVariable( "network-channel", 0 );
815     }
816
817     /*
818      * Try to run the interface
819      */
820     p_main->p_intf = intf_Create();
821     if( p_main->p_intf == NULL )
822     {
823         intf_ErrMsg( "intf error: interface initialization failed" );
824     }
825     else
826     {
827         /*
828          * Set signal handling policy for all threads
829          */
830         InitSignalHandler();
831
832         /*
833          * This is the main loop
834          */
835         p_main->p_intf->pf_run( p_main->p_intf );
836
837         /*
838          * Finished, destroy the interface
839          */
840         intf_Destroy( p_main->p_intf );
841
842         /*
843          * Go back into channel 0 which is the network
844          */
845         if( config_GetIntVariable( "network-channel" ) && p_main->p_channel )
846         {
847             network_ChannelJoin( COMMON_CHANNEL );
848         }
849     }
850
851     /*
852      * Free input, aout and vout banks
853      */
854     input_EndBank();
855     vout_EndBank();
856     aout_EndBank();
857
858     /*
859      * Free playlist
860      */
861     intf_PlaylistDestroy( p_main->p_playlist );
862
863     /*
864      * Free memcpy module if it was allocated
865      */
866     if( p_main->p_memcpy_module != NULL )
867     {
868         module_Unneed( p_main->p_memcpy_module );
869     }
870
871     /*
872      * Free module bank
873      */
874     module_EndBank();
875
876     /*
877      * System specific cleaning code
878      */
879     system_End();
880
881     /*
882      * Terminate messages interface and program
883      */
884     intf_WarnMsg( 1, "intf: program terminated" );
885     intf_MsgDestroy();
886
887     /*
888      * Stop threads system
889      */
890     vlc_threads_end( );
891
892     return 0;
893 }
894
895
896 /* following functions are local */
897
898 /*****************************************************************************
899  * GetFilenames: parse command line options which are not flags
900  *****************************************************************************
901  * Parse command line for input files.
902  *****************************************************************************/
903 static int GetFilenames( int i_argc, char *ppsz_argv[] )
904 {
905     int i_opt;
906
907     /* We assume that the remaining parameters are filenames */
908     for( i_opt = optind; i_opt < i_argc; i_opt++ )
909     {
910         intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
911                           ppsz_argv[ i_opt ] );
912     }
913
914     return( 0 );
915 }
916
917 /*****************************************************************************
918  * Usage: print program usage
919  *****************************************************************************
920  * Print a short inline help. Message interface is initialized at this stage.
921  *****************************************************************************/
922 static void Usage( const char *psz_module_name )
923 {
924 #define FORMAT_STRING "      --%s%s%s%s%s %s"
925     /* option name ---------------' | | | |  |
926      * <bra ------------------------' | | |  |
927      * option type or "" -------------' | |  |
928      * ket> ----------------------------' |  |
929      * padding spaces --------------------'  |
930      * comment ------------------------------'
931      *
932      * The purpose of having bra and ket is that we might i18n them as well.
933      */
934 #define LINE_START 8
935 #define PADDING_SPACES 25
936     module_t *p_module;
937     module_config_t *p_item;
938     char psz_spaces[PADDING_SPACES+LINE_START+1];
939     char psz_format[sizeof(FORMAT_STRING)];
940
941     memset( psz_spaces, ' ', PADDING_SPACES+LINE_START );
942     psz_spaces[PADDING_SPACES+LINE_START] = '\0';
943
944     strcpy( psz_format, FORMAT_STRING );
945
946 #ifdef WIN32
947     ShowConsole();
948 #endif
949
950     /* Enumerate the config of each module */
951     for( p_module = p_module_bank->first ;
952          p_module != NULL ;
953          p_module = p_module->next )
954     {
955         if( psz_module_name && strcmp( psz_module_name, p_module->psz_name ) )
956             continue;
957
958         /* ignore modules without config options */
959         if( !p_module->i_config_items ) continue;
960
961         /* print module name */
962         intf_Msg( _("%s module options:\n"), p_module->psz_name );
963
964         for( p_item = p_module->p_config;
965              p_item->i_type != MODULE_CONFIG_HINT_END;
966              p_item++ )
967         {
968             char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
969             int i;
970
971             if( p_item->i_short )
972             {
973                 psz_format[2] = '-';
974                 psz_format[3] = p_item->i_short;
975                 psz_format[4] = ',';
976             }
977             else
978             {
979                 psz_format[2] = ' ';
980                 psz_format[3] = ' ';
981                 psz_format[4] = ' ';
982             }
983
984             switch( p_item->i_type )
985             {
986             case MODULE_CONFIG_HINT_CATEGORY:
987                 intf_Msg( " %s", p_item->psz_text );
988                 break;
989
990             case MODULE_CONFIG_ITEM_STRING:
991             case MODULE_CONFIG_ITEM_FILE:
992             case MODULE_CONFIG_ITEM_MODULE: /* We could also have "=<" here */
993                 psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
994                 break;
995             case MODULE_CONFIG_ITEM_INTEGER:
996                 psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
997                 break;
998             case MODULE_CONFIG_ITEM_FLOAT:
999                 psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
1000                 break;
1001             case MODULE_CONFIG_ITEM_BOOL:
1002                 psz_bra = ""; psz_type = ""; psz_ket = "";
1003                 break;
1004             }
1005
1006             if( psz_type )
1007             {
1008                 i = PADDING_SPACES - strlen( p_item->psz_name )
1009                      - strlen( psz_bra ) - strlen( psz_type )
1010                      - strlen( psz_ket ) - 1;
1011                 if( i < 0 )
1012                 {
1013                     i = 0;
1014                     psz_spaces[i] = '\n';
1015                 }
1016                 else
1017                 {
1018                     psz_spaces[i] = '\0';
1019                 }
1020
1021                 intf_Msg( psz_format, p_item->psz_name, psz_bra, psz_type,
1022                           psz_ket, psz_spaces, p_item->psz_text );
1023                 psz_spaces[i] = ' ';
1024             }
1025         }
1026
1027         /* Yet another nasty hack.
1028          * Maybe we could use MODULE_CONFIG_ITEM_END to display tail messages
1029          * for each module?? */
1030         if( !strcmp( "main", p_module->psz_name ) )
1031         {
1032             intf_Msg( _("\nPlaylist items:"
1033                 "\n  *.mpg, *.vob                   plain MPEG-1/2 files"
1034                 "\n  [dvd:][device][@raw_device][@[title][,[chapter][,angle]]]"
1035                 "\n                                 DVD device"
1036                 "\n  [vcd:][device][@[title][,[chapter]]"
1037                 "\n                                 VCD device"
1038                 "\n  udpstream:[@[<bind address>][:<bind port>]]"
1039                 "\n                                 UDP stream sent by VLS"
1040                 "\n  vlc:loop                       loop execution of the "
1041                       "playlist"
1042                 "\n  vlc:pause                      pause execution of "
1043                       "playlist items"
1044                 "\n  vlc:quit                       quit VLC") );
1045         }
1046
1047         intf_Msg( "" );
1048
1049     }
1050
1051 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1052         intf_Msg( _("\nPress the RETURN key to continue...") );
1053         getchar();
1054 #endif
1055 }
1056
1057 /*****************************************************************************
1058  * ListModules: list the available modules with their description
1059  *****************************************************************************
1060  * Print a list of all available modules (builtins and plugins) and a short
1061  * description for each one.
1062  *****************************************************************************/
1063 static void ListModules( void )
1064 {
1065     module_t *p_module;
1066     char psz_spaces[22];
1067
1068     memset( psz_spaces, ' ', 22 );
1069
1070 #ifdef WIN32
1071     ShowConsole();
1072 #endif
1073
1074     /* Usage */
1075     intf_Msg( _("Usage: %s [options] [parameters] [file]...\n"),
1076               p_main->psz_arg0 );
1077
1078     intf_Msg( _("[module]              [description]") );
1079
1080     /* Enumerate each module */
1081     for( p_module = p_module_bank->first ;
1082          p_module != NULL ;
1083          p_module = p_module->next )
1084     {
1085         int i;
1086
1087         /* Nasty hack, but right now I'm too tired to think about a nice
1088          * solution */
1089         i = 22 - strlen( p_module->psz_name ) - 1;
1090         if( i < 0 ) i = 0;
1091         psz_spaces[i] = 0;
1092
1093         intf_Msg( "  %s%s %s", p_module->psz_name, psz_spaces,
1094                   p_module->psz_longname );
1095
1096         psz_spaces[i] = ' ';
1097
1098     }
1099
1100 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1101         intf_Msg( _("\nPress the RETURN key to continue...") );
1102         getchar();
1103 #endif
1104 }
1105
1106 /*****************************************************************************
1107  * Version: print complete program version
1108  *****************************************************************************
1109  * Print complete program version and build number.
1110  *****************************************************************************/
1111 static void Version( void )
1112 {
1113 #ifdef WIN32
1114     ShowConsole();
1115 #endif
1116
1117     intf_Msg( VERSION_MESSAGE );
1118     intf_Msg(
1119       _("This program comes with NO WARRANTY, to the extent permitted by "
1120         "law.\nYou may redistribute it under the terms of the GNU General "
1121         "Public License;\nsee the file named COPYING for details.\n"
1122         "Written by the VideoLAN team at Ecole Centrale, Paris.") );
1123
1124 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1125         intf_Msg( _("\nPress the RETURN key to continue...") );
1126         getchar();
1127 #endif
1128 }
1129
1130 /*****************************************************************************
1131  * InitSignalHandler: system signal handler initialization
1132  *****************************************************************************
1133  * Set the signal handlers. SIGTERM is not intercepted, because we need at
1134  * at least a method to kill the program when all other methods failed, and
1135  * when we don't want to use SIGKILL.
1136  *****************************************************************************/
1137 static void InitSignalHandler( void )
1138 {
1139     /* Termination signals */
1140 #ifndef WIN32
1141     signal( SIGINT,  FatalSignalHandler );
1142     signal( SIGHUP,  FatalSignalHandler );
1143     signal( SIGQUIT, FatalSignalHandler );
1144
1145     /* Other signals */
1146     signal( SIGALRM, SimpleSignalHandler );
1147     signal( SIGPIPE, SimpleSignalHandler );
1148 #endif
1149 }
1150
1151 /*****************************************************************************
1152  * SimpleSignalHandler: system signal handler
1153  *****************************************************************************
1154  * This function is called when a non fatal signal is received by the program.
1155  *****************************************************************************/
1156 static void SimpleSignalHandler( int i_signal )
1157 {
1158     /* Acknowledge the signal received */
1159     intf_WarnMsg( 0, "intf: ignoring signal %d", i_signal );
1160 }
1161
1162 /*****************************************************************************
1163  * FatalSignalHandler: system signal handler
1164  *****************************************************************************
1165  * This function is called when a fatal signal is received by the program.
1166  * It tries to end the program in a clean way.
1167  *****************************************************************************/
1168 static void FatalSignalHandler( int i_signal )
1169 {
1170     static mtime_t abort_time = 0;
1171     static volatile boolean_t b_die = 0;
1172
1173     /* Once a signal has been trapped, the termination sequence will be
1174      * armed and following signals will be ignored to avoid sending messages
1175      * to an interface having been destroyed */
1176     if( !b_die )
1177     {
1178         b_die = 1;
1179         abort_time = mdate();
1180
1181         /* Acknowledge the signal received */
1182         intf_ErrMsg( "intf error: signal %d received, exiting - do it again "
1183                      "if vlc gets stuck", i_signal );
1184
1185         /* Try to terminate everything - this is done by requesting the end
1186          * of the interface thread */
1187         p_main->p_intf->b_die = 1;
1188
1189         return;
1190     }
1191
1192     /* If user asks again 1 second later, die badly */
1193     if( mdate() > abort_time + 1000000 )
1194     {
1195 #ifndef WIN32
1196         signal( SIGINT,  SIG_IGN );
1197         signal( SIGHUP,  SIG_IGN );
1198         signal( SIGQUIT, SIG_IGN );
1199 #endif
1200
1201         intf_ErrMsg( "intf error: user insisted too much, dying badly" );
1202         exit( 1 );
1203     }
1204 }
1205
1206 /*****************************************************************************
1207  * IllegalSignalHandler: system signal handler
1208  *****************************************************************************
1209  * This function is called when an illegal instruction signal is received by
1210  * the program. We use this function to test OS and CPU capabilities
1211  *****************************************************************************/
1212 static void IllegalSignalHandler( int i_signal )
1213 {
1214     /* Acknowledge the signal received */
1215     i_illegal = 1;
1216
1217 #ifdef HAVE_SIGRELSE
1218     sigrelse( i_signal );
1219 #endif
1220
1221 #if defined( __i386__ )
1222     fprintf( stderr, "warning: your CPU has %s instructions, but not your "
1223                      "operating system.\n", psz_capability );
1224     fprintf( stderr, "         some optimizations will be disabled unless "
1225                      "you upgrade your OS\n" );
1226 #   if defined( SYS_LINUX )
1227     fprintf( stderr, "         (for instance Linux kernel 2.4.x or later)\n" );
1228 #   endif
1229 #endif
1230
1231     longjmp( env, 1 );
1232 }
1233
1234 /*****************************************************************************
1235  * CPUCapabilities: list the processors MMX support and other capabilities
1236  *****************************************************************************
1237  * This function is called to list extensions the CPU may have.
1238  *****************************************************************************/
1239 static u32 CPUCapabilities( void )
1240 {
1241     volatile u32 i_capabilities = CPU_CAPABILITY_NONE;
1242
1243 #if defined( SYS_DARWIN )
1244     struct host_basic_info hi;
1245     kern_return_t          ret;
1246     host_name_port_t       host;
1247
1248     int i_size;
1249     char *psz_name, *psz_subname;
1250
1251     i_capabilities |= CPU_CAPABILITY_FPU;
1252
1253     /* Should 'never' fail? */
1254     host = mach_host_self();
1255
1256     i_size = sizeof( hi ) / sizeof( int );
1257     ret = host_info( host, HOST_BASIC_INFO, ( host_info_t )&hi, &i_size );
1258
1259     if( ret != KERN_SUCCESS )
1260     {
1261         fprintf( stderr, "error: couldn't get CPU information\n" );
1262         return( i_capabilities );
1263     }
1264
1265     slot_name( hi.cpu_type, hi.cpu_subtype, &psz_name, &psz_subname );
1266     /* FIXME: need better way to detect newer proccessors.
1267      * could do strncmp(a,b,5), but that's real ugly */
1268     if( !strcmp(psz_name, "ppc7400") || !strcmp(psz_name, "ppc7450") )
1269     {
1270         i_capabilities |= CPU_CAPABILITY_ALTIVEC;
1271     }
1272
1273     return( i_capabilities );
1274
1275 #elif defined( __i386__ )
1276     volatile unsigned int  i_eax, i_ebx, i_ecx, i_edx;
1277     volatile boolean_t     b_amd;
1278
1279     /* Needed for x86 CPU capabilities detection */
1280 #   define cpuid( a )                      \
1281         asm volatile ( "pushl %%ebx\n\t"   \
1282                        "cpuid\n\t"         \
1283                        "movl %%ebx,%1\n\t" \
1284                        "popl %%ebx\n\t"    \
1285                      : "=a" ( i_eax ),     \
1286                        "=r" ( i_ebx ),     \
1287                        "=c" ( i_ecx ),     \
1288                        "=d" ( i_edx )      \
1289                      : "a"  ( a )          \
1290                      : "cc" );
1291
1292     i_capabilities |= CPU_CAPABILITY_FPU;
1293
1294 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1295     signal( SIGILL, IllegalSignalHandler );
1296 #   endif
1297
1298     /* test for a 486 CPU */
1299     asm volatile ( "pushl %%ebx\n\t"
1300                    "pushfl\n\t"
1301                    "popl %%eax\n\t"
1302                    "movl %%eax, %%ebx\n\t"
1303                    "xorl $0x200000, %%eax\n\t"
1304                    "pushl %%eax\n\t"
1305                    "popfl\n\t"
1306                    "pushfl\n\t"
1307                    "popl %%eax\n\t"
1308                    "movl %%ebx,%1\n\t"
1309                    "popl %%ebx\n\t"
1310                  : "=a" ( i_eax ),
1311                    "=r" ( i_ebx )
1312                  :
1313                  : "cc" );
1314
1315     if( i_eax == i_ebx )
1316     {
1317 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1318         signal( SIGILL, NULL );
1319 #   endif
1320         return( i_capabilities );
1321     }
1322
1323     i_capabilities |= CPU_CAPABILITY_486;
1324
1325     /* the CPU supports the CPUID instruction - get its level */
1326     cpuid( 0x00000000 );
1327
1328     if( !i_eax )
1329     {
1330 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1331         signal( SIGILL, NULL );
1332 #   endif
1333         return( i_capabilities );
1334     }
1335
1336     /* FIXME: this isn't correct, since some 486s have cpuid */
1337     i_capabilities |= CPU_CAPABILITY_586;
1338
1339     /* borrowed from mpeg2dec */
1340     b_amd = ( i_ebx == 0x68747541 ) && ( i_ecx == 0x444d4163 )
1341                     && ( i_edx == 0x69746e65 );
1342
1343     /* test for the MMX flag */
1344     cpuid( 0x00000001 );
1345
1346     if( ! (i_edx & 0x00800000) )
1347     {
1348 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1349         signal( SIGILL, NULL );
1350 #   endif
1351         return( i_capabilities );
1352     }
1353
1354     i_capabilities |= CPU_CAPABILITY_MMX;
1355
1356     if( i_edx & 0x02000000 )
1357     {
1358         i_capabilities |= CPU_CAPABILITY_MMXEXT;
1359
1360 #   ifdef CAN_COMPILE_SSE
1361         /* We test if OS supports the SSE instructions */
1362         psz_capability = "SSE";
1363         i_illegal = 0;
1364         if( setjmp( env ) == 0 )
1365         {
1366             /* Test a SSE instruction */
1367             __asm__ __volatile__ ( "xorps %%xmm0,%%xmm0\n" : : );
1368         }
1369
1370         if( i_illegal == 0 )
1371         {
1372             i_capabilities |= CPU_CAPABILITY_SSE;
1373         }
1374 #   endif
1375     }
1376
1377     /* test for additional capabilities */
1378     cpuid( 0x80000000 );
1379
1380     if( i_eax < 0x80000001 )
1381     {
1382 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1383         signal( SIGILL, NULL );
1384 #   endif
1385         return( i_capabilities );
1386     }
1387
1388     /* list these additional capabilities */
1389     cpuid( 0x80000001 );
1390
1391 #   ifdef CAN_COMPILE_3DNOW
1392     if( i_edx & 0x80000000 )
1393     {
1394         psz_capability = "3D Now!";
1395         i_illegal = 0;
1396         if( setjmp( env ) == 0 )
1397         {
1398             /* Test a 3D Now! instruction */
1399             __asm__ __volatile__ ( "pfadd %%mm0,%%mm0\n" "femms\n" : : );
1400         }
1401
1402         if( i_illegal == 0 )
1403         {
1404             i_capabilities |= CPU_CAPABILITY_3DNOW;
1405         }
1406     }
1407 #   endif
1408
1409     if( b_amd && ( i_edx & 0x00400000 ) )
1410     {
1411         i_capabilities |= CPU_CAPABILITY_MMXEXT;
1412     }
1413
1414 #   if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
1415     signal( SIGILL, NULL );
1416 #   endif
1417     return( i_capabilities );
1418
1419 #elif defined( __powerpc__ )
1420
1421     i_capabilities |= CPU_CAPABILITY_FPU;
1422
1423 #   ifdef CAN_COMPILE_ALTIVEC
1424     signal( SIGILL, IllegalSignalHandler );
1425
1426     psz_capability = "AltiVec";
1427     i_illegal = 0;
1428     if( setjmp( env ) == 0 )
1429     {
1430         asm volatile ("mtspr 256, %0\n\t"
1431                       "vand %%v0, %%v0, %%v0"
1432                       :
1433                       : "r" (-1));
1434     }
1435
1436     if( i_illegal == 0 )
1437     {
1438         i_capabilities |= CPU_CAPABILITY_ALTIVEC;
1439     }
1440
1441     signal( SIGILL, NULL );
1442 #   endif
1443
1444     return( i_capabilities );
1445
1446 #elif defined( __sparc__ )
1447
1448     i_capabilities |= CPU_CAPABILITY_FPU;
1449     return( i_capabilities );
1450
1451 #else
1452     /* default behaviour */
1453     return( i_capabilities );
1454
1455 #endif
1456 }
1457
1458 /*****************************************************************************
1459  * ShowConsole: On Win32, create an output console for debug messages
1460  *****************************************************************************
1461  * This function is useful only on Win32.
1462  *****************************************************************************/
1463 #ifdef WIN32 /*  */
1464 static void ShowConsole( void )
1465 {
1466     AllocConsole();
1467     freopen( "CONOUT$", "w", stdout );
1468     freopen( "CONOUT$", "w", stderr );
1469     freopen( "CONIN$", "r", stdin );
1470     return;
1471 }
1472 #endif