]> git.sesse.net Git - vlc/blob - src/interface/main.c
0272ed43ccadccc379446ee83af51efebd75a5cd
[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, 1999, 2000 VideoLAN
7  * $Id: main.c,v 1.104 2001/06/14 20:21:04 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 "defs.h"
31
32 #include <signal.h>                               /* SIGHUP, SIGINT, SIGKILL */
33 #include <stdio.h>                                              /* sprintf() */
34 #include <setjmp.h>                                       /* longjmp, setjmp */
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_DARWIN1_3
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 #endif
58
59 #include <errno.h>                                                 /* ENOMEM */
60 #include <stdlib.h>                                  /* getenv(), strtol(),  */
61 #include <string.h>                                            /* strerror() */
62
63 #include "config.h"
64 #include "common.h"
65 #include "debug.h"
66 #include "threads.h"
67 #include "mtime.h"
68 #include "tests.h"                                              /* TestCPU() */
69 #include "modules.h"
70
71 #include "stream_control.h"
72 #include "input_ext-intf.h"
73
74 #include "intf_msg.h"
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 #ifdef SYS_BEOS
84 #   include "beos_specific.h"
85 #endif
86
87 #ifdef SYS_DARWIN1_3
88 #   include "darwin_specific.h"
89 #endif
90
91 #include "netutils.h"                                 /* network_ChannelJoin */
92
93 #include "main.h"
94
95 /*****************************************************************************
96  * Command line options constants. If something is changed here, be sure that
97  * GetConfiguration and Usage are also changed.
98  *****************************************************************************/
99
100 /* Long options return values - note that values corresponding to short options
101  * chars, and in general any regular char, should be avoided */
102 #define OPT_NOAUDIO             150
103 #define OPT_STEREO              151
104 #define OPT_MONO                152
105 #define OPT_SPDIF               153
106
107 #define OPT_NOVIDEO             160
108 #define OPT_DISPLAY             161
109 #define OPT_WIDTH               162
110 #define OPT_HEIGHT              163
111 #define OPT_COLOR               164
112 #define OPT_FULLSCREEN          165
113 #define OPT_OVERLAY             166
114
115 #define OPT_CHANNELS            170
116 #define OPT_SERVER              171
117 #define OPT_PORT                172
118 #define OPT_BROADCAST           173
119
120 #define OPT_INPUT               180
121 #define OPT_MOTION              181
122 #define OPT_IDCT                182
123 #define OPT_YUV                 183
124 #define OPT_DOWNMIX             184
125 #define OPT_IMDCT               185
126
127 #define OPT_SYNCHRO             190
128 #define OPT_WARNING             191
129 #define OPT_VERSION             192
130
131 /* Usage fashion */
132 #define USAGE                     0
133 #define SHORT_HELP                1
134 #define LONG_HELP                 2
135
136 /* Needed for x86 CPU capabilities detection */
137 #define cpuid( a )                 \
138     asm volatile ( "cpuid"         \
139                  : "=a" ( i_eax ), \
140                    "=b" ( i_ebx ), \
141                    "=c" ( i_ecx ), \
142                    "=d" ( i_edx )  \
143                  : "a"  ( a )      \
144                  : "cc" );
145
146 /* Long options */
147 static const struct option longopts[] =
148 {
149     /*  name,               has_arg,    flag,   val */
150
151     /* General/common options */
152     {   "help",             0,          0,      'h' },
153     {   "longhelp",         0,          0,      'H' },
154     {   "version",          0,          0,      OPT_VERSION },
155
156     /* Interface options */
157     {   "intf",             1,          0,      'I' },
158     {   "warning",          1,          0,      OPT_WARNING },
159
160     /* Audio options */
161     {   "noaudio",          0,          0,      OPT_NOAUDIO },
162     {   "aout",             1,          0,      'A' },
163     {   "stereo",           0,          0,      OPT_STEREO },
164     {   "mono",             0,          0,      OPT_MONO },
165     {   "spdif",            0,          0,      OPT_SPDIF },
166     {   "downmix",          1,          0,      OPT_DOWNMIX },
167     {   "imdct",            1,          0,      OPT_IMDCT },
168
169     /* Video options */
170     {   "novideo",          0,          0,      OPT_NOVIDEO },
171     {   "vout",             1,          0,      'V' },
172     {   "display",          1,          0,      OPT_DISPLAY },
173     {   "width",            1,          0,      OPT_WIDTH },
174     {   "height",           1,          0,      OPT_HEIGHT },
175     {   "grayscale",        0,          0,      'g' },
176     {   "color",            0,          0,      OPT_COLOR },
177     {   "motion",           1,          0,      OPT_MOTION },
178     {   "idct",             1,          0,      OPT_IDCT },
179     {   "yuv",              1,          0,      OPT_YUV },
180     {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
181     {   "overlay",          0,          0,      OPT_OVERLAY },
182
183     /* DVD options */
184     {   "dvdtitle",         1,          0,      't' },
185     {   "dvdchapter",       1,          0,      'T' },
186     {   "dvdangle",         1,          0,      'u' },
187     {   "dvdaudio",         1,          0,      'a' },
188     {   "dvdchannel",       1,          0,      'c' },
189     {   "dvdsubtitle",      1,          0,      's' },
190     
191     /* Input options */
192     {   "input",            1,          0,      OPT_INPUT },
193     {   "server",           1,          0,      OPT_SERVER },
194     {   "port",             1,          0,      OPT_PORT },
195     {   "broadcast",        1,          0,      OPT_BROADCAST },
196     {   "channels",         0,          0,      OPT_CHANNELS },
197
198     /* Synchro options */
199     {   "synchro",          1,          0,      OPT_SYNCHRO },
200     {   0,                  0,          0,      0 }
201 };
202
203 /* Short options */
204 static const char *psz_shortopts = "hHvgt:T:u:a:s:c:I:A:V:";
205
206 /*****************************************************************************
207  * Global variable program_data - these are the only ones, see main.h and
208  * modules.h
209  *****************************************************************************/
210 main_t        *p_main;
211 module_bank_t *p_module_bank;
212 aout_bank_t   *p_aout_bank;
213 vout_bank_t   *p_vout_bank;
214
215 /*****************************************************************************
216  * Local prototypes
217  *****************************************************************************/
218 static int  GetConfiguration        ( int *pi_argc, char *ppsz_argv[],
219                                       char *ppsz_env[] );
220 static int  GetFilenames            ( int i_argc, char *ppsz_argv[] );
221 static void Usage                   ( int i_fashion );
222 static void Version                 ( void );
223
224 static void InitSignalHandler       ( void );
225 static void SimpleSignalHandler     ( int i_signal );
226 static void FatalSignalHandler      ( int i_signal );
227 static void InstructionSignalHandler( int i_signal );
228 static int  CPUCapabilities         ( void );
229 static jmp_buf env;
230 static int  i_illegal;
231
232 /*****************************************************************************
233  * main: parse command line, start interface and spawn threads
234  *****************************************************************************
235  * Steps during program execution are:
236  *      -configuration parsing and messages interface initialization
237  *      -opening of audio output device and some global modules
238  *      -execution of interface, which exit on error or on user request
239  *      -closing of audio output device and some global modules
240  * On error, the spawned threads are canceled, and the open devices closed.
241  *****************************************************************************/
242 int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
243 {
244     main_t        main_data;                /* root of all data - see main.h */
245     module_bank_t module_bank;
246     aout_bank_t   aout_bank;
247     vout_bank_t   vout_bank;
248
249     p_main        = &main_data;               /* set up the global variables */
250     p_module_bank = &module_bank;
251     p_aout_bank   = &aout_bank;
252     p_vout_bank   = &vout_bank;
253
254     /*
255      * Initialize threads system
256      */
257     vlc_threads_init( );
258
259     /*
260      * Test if our code is likely to run on this CPU 
261      */
262     p_main->i_cpu_capabilities = CPUCapabilities();
263     
264 #if defined( __pentium__ ) || defined( __pentiumpro__ )
265     if( ! TestCPU( CPU_CAPABILITY_586 ) )
266     {
267         fprintf( stderr, "error: this program needs a Pentium CPU,\n"
268                          "please try a version without Pentium support\n" );
269         return( 1 );
270     }
271 #endif
272
273     /*
274      * System specific initialization code
275      */
276 #if defined( SYS_BEOS ) || defined( SYS_DARWIN1_3 )
277     system_Init( &i_argc, ppsz_argv, ppsz_env );
278 #endif
279
280     /*
281      * Initialize messages interface
282      */
283     p_main->p_msg = intf_MsgCreate();
284     if( !p_main->p_msg )                         /* start messages interface */
285     {
286         fprintf( stderr, "error: can't initialize messages interface (%s)\n",
287                  strerror(errno) );
288         return( errno );
289     }
290
291     intf_MsgImm( COPYRIGHT_MESSAGE );
292
293     /*
294      * Read configuration
295      */
296     if( GetConfiguration( &i_argc, ppsz_argv, ppsz_env ) ) /* parse cmd line */
297     {
298         intf_MsgDestroy();
299         return( errno );
300     }
301
302     /*
303      * Initialize playlist and get commandline files
304      */
305     p_main->p_playlist = intf_PlaylistCreate();
306     if( !p_main->p_playlist )
307     {
308         intf_ErrMsg( "playlist error: playlist initialization failed" );
309         intf_MsgDestroy();
310         return( errno );
311     }
312     intf_PlaylistInit( p_main->p_playlist );
313
314     /*
315      * Get input filenames given as commandline arguments
316      */
317     GetFilenames( i_argc, ppsz_argv );
318
319     /*
320      * Initialize module, aout and vout banks
321      */
322     module_InitBank();
323     aout_InitBank();
324     vout_InitBank();
325
326     /*
327      * Initialize shared resources and libraries
328      */
329     if( main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
330                              INPUT_NETWORK_CHANNEL_DEFAULT ) &&
331         network_ChannelCreate() )
332     {
333         /* On error during Channels initialization, switch off channels */
334         intf_Msg( "Channels initialization failed : "
335                   "Channel management is deactivated" );
336         main_PutIntVariable( INPUT_NETWORK_CHANNEL_VAR, 0 );
337     }
338
339     /*
340      * Try to run the interface
341      */
342     p_main->p_intf = intf_Create();
343     if( p_main->p_intf == NULL )
344     {
345         intf_ErrMsg( "intf error: interface initialization failed" );
346     }
347     else
348     {
349         /*
350          * Set signal handling policy for all threads
351          */
352         InitSignalHandler();
353
354         /*
355          * This is the main loop
356          */
357         p_main->p_intf->pf_run( p_main->p_intf );
358
359         /*
360          * Finished, destroy the interface
361          */
362         intf_Destroy( p_main->p_intf );
363
364         /*
365          * Go back into channel 0 which is the network
366          */
367         if( main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
368                                  INPUT_NETWORK_CHANNEL_DEFAULT ) )
369         {
370             network_ChannelJoin( COMMON_CHANNEL );
371         }
372     }
373
374     /*
375      * Free module, aout and vout banks
376      */
377     vout_EndBank();
378     aout_EndBank();
379     module_EndBank();
380
381     /*
382      * Free playlist
383      */
384     intf_PlaylistDestroy( p_main->p_playlist );
385
386     /*
387      * System specific cleaning code
388      */
389 #if defined( SYS_BEOS ) || defined( SYS_DARWIN1_3 )
390     system_End();
391 #endif
392
393
394     /*
395      * Terminate messages interface and program
396      */
397     intf_Msg( "intf: program terminated" );
398     intf_MsgDestroy();
399
400     /*
401      * Stop threads system
402      */
403     vlc_threads_end( );
404
405     return 0;
406 }
407
408 /*****************************************************************************
409  * main_GetIntVariable: get the int value of an environment variable
410  *****************************************************************************
411  * This function is used to read some default parameters in modules.
412  *****************************************************************************/
413 int main_GetIntVariable( char *psz_name, int i_default )
414 {
415     char *      psz_env;                                /* environment value */
416     char *      psz_end;                             /* end of parsing index */
417     long int    i_value;                                            /* value */
418
419     psz_env = getenv( psz_name );
420     if( psz_env )
421     {
422         i_value = strtol( psz_env, &psz_end, 0 );
423         if( (*psz_env != '\0') && (*psz_end == '\0') )
424         {
425             return( i_value );
426         }
427     }
428     return( i_default );
429 }
430
431 /*****************************************************************************
432  * main_GetPszVariable: get the string value of an environment variable
433  *****************************************************************************
434  * This function is used to read some default parameters in modules.
435  *****************************************************************************/
436 char * main_GetPszVariable( char *psz_name, char *psz_default )
437 {
438     char *psz_env;
439
440     psz_env = getenv( psz_name );
441     if( psz_env )
442     {
443         return( psz_env );
444     }
445     return( psz_default );
446 }
447
448 /*****************************************************************************
449  * main_PutPszVariable: set the string value of an environment variable
450  *****************************************************************************
451  * This function is used to set some default parameters in modules. The use of
452  * this function will cause some memory leak: since some systems use the pointer
453  * passed to putenv to store the environment string, it can't be freed.
454  *****************************************************************************/
455 void main_PutPszVariable( char *psz_name, char *psz_value )
456 {
457     char *psz_env;
458
459     psz_env = malloc( strlen(psz_name) + strlen(psz_value) + 2 );
460     if( psz_env == NULL )
461     {
462         intf_ErrMsg( "intf error: cannot create psz_env (%s)",
463                      strerror(ENOMEM) );
464     }
465     else
466     {
467         sprintf( psz_env, "%s=%s", psz_name, psz_value );
468         if( putenv( psz_env ) )
469         {
470             intf_ErrMsg( "intf error: cannot putenv (%s)", strerror(errno) );
471         }
472     }
473 }
474
475 /*****************************************************************************
476  * main_PutIntVariable: set the integer value of an environment variable
477  *****************************************************************************
478  * This function is used to set some default parameters in modules. The use of
479  * this function will cause some memory leak: since some systems use the pointer
480  * passed to putenv to store the environment string, it can't be freed.
481  *****************************************************************************/
482 void main_PutIntVariable( char *psz_name, int i_value )
483 {
484     char psz_value[ 256 ];                               /* buffer for value */
485
486     sprintf( psz_value, "%d", i_value );
487     main_PutPszVariable( psz_name, psz_value );
488 }
489
490 /* following functions are local */
491
492 /*****************************************************************************
493  * GetConfiguration: parse command line
494  *****************************************************************************
495  * Parse command line and configuration file for configuration. If the inline
496  * help is requested, the function Usage() is called and the function returns
497  * -1 (causing main() to exit). The messages interface is initialized at this
498  * stage, but most structures are not allocated, so only environment should
499  * be used.
500  *****************************************************************************/
501 static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
502 {
503     int   i_cmd;
504     char *p_tmp;
505
506     /* Set default configuration and copy arguments */
507     p_main->i_argc    = *pi_argc;
508     p_main->ppsz_argv = ppsz_argv;
509     p_main->ppsz_env  = ppsz_env;
510
511     p_main->b_audio     = 1;
512     p_main->b_video     = 1;
513
514     p_main->i_warning_level = 0;
515
516     p_main->p_channel = NULL;
517
518     /* Get the executable name (similar to the basename command) */
519     p_main->psz_arg0 = p_tmp = ppsz_argv[ 0 ];
520     while( *p_tmp )
521     {
522         if( *p_tmp == '/' )
523         {
524             p_main->psz_arg0 = ++p_tmp;
525         }
526         else
527         {
528             ++p_tmp;
529         }
530     }
531
532 #ifdef SYS_DARWIN1_3
533     /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
534      * is the PSN - process serial number (a unique PID-ish thingie)
535      * still ok for real Darwin & when run from command line */
536     if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
537                                         /* for example -psn_0_9306113 */
538     {
539         /* GDMF!... I can't do this or else the MacOSX window server will
540          * not pick up the PSN and not register the app and we crash...
541          * hence the following kludge otherwise we'll get confused w/ argv[1]
542          * being an input file name */
543 #if 0
544         ppsz_argv[ 1 ] = NULL;
545 #endif
546         *pi_argc = *pi_argc - 1;
547         pi_argc--;
548         return( 0 );
549     }
550 #endif
551
552     /* Parse command line options */
553     opterr = 0;
554     while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv,
555                                    psz_shortopts, longopts, 0 ) ) != EOF )
556     {
557         switch( i_cmd )
558         {
559         /* General/common options */
560         case 'h':                                              /* -h, --help */
561             Usage( SHORT_HELP );
562             return( -1 );
563             break;
564         case 'H':                                          /* -H, --longhelp */
565             Usage( LONG_HELP );
566             return( -1 );
567             break;
568         case OPT_VERSION:                                       /* --version */
569             Version();
570             return( -1 );
571             break;
572         case 'v':                                           /* -v, --verbose */
573             p_main->i_warning_level++;
574             break;
575
576         /* Interface warning messages level */
577         case 'I':                                              /* -I, --intf */
578             main_PutPszVariable( INTF_METHOD_VAR, optarg );
579             break;
580         case OPT_WARNING:                                       /* --warning */
581             intf_ErrMsg( "intf error: `--warning' is deprecated, use `-v'" );
582             p_main->i_warning_level = atoi(optarg);
583             break;
584
585         /* Audio options */
586         case OPT_NOAUDIO:                                       /* --noaudio */
587             p_main->b_audio = 0;
588             break;
589         case 'A':                                              /* -A, --aout */
590             main_PutPszVariable( AOUT_METHOD_VAR, optarg );
591             break;
592         case OPT_STEREO:                                         /* --stereo */
593             main_PutIntVariable( AOUT_STEREO_VAR, 1 );
594             break;
595         case OPT_MONO:                                             /* --mono */
596             main_PutIntVariable( AOUT_STEREO_VAR, 0 );
597             break;
598         case OPT_SPDIF:                                           /* --spdif */
599             main_PutIntVariable( AOUT_SPDIF_VAR, 1 );
600             break;
601         case OPT_DOWNMIX:                                       /* --downmix */
602             main_PutPszVariable( DOWNMIX_METHOD_VAR, optarg );
603             break;
604         case OPT_IMDCT:                                           /* --imdct */
605             main_PutPszVariable( IMDCT_METHOD_VAR, optarg );
606             break;
607
608         /* Video options */
609         case OPT_NOVIDEO:                                       /* --novideo */
610             p_main->b_video = 0;
611             break;
612         case 'V':                                              /* -V, --vout */
613             main_PutPszVariable( VOUT_METHOD_VAR, optarg );
614             break;
615         case OPT_DISPLAY:                                       /* --display */
616             main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
617             break;
618         case OPT_WIDTH:                                           /* --width */
619             main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
620             break;
621         case OPT_HEIGHT:                                         /* --height */
622             main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );
623             break;
624         case 'g':                                         /* -g, --grayscale */
625             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
626             break;
627         case OPT_COLOR:                                           /* --color */
628             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
629             break;
630         case OPT_FULLSCREEN:                                 /* --fullscreen */
631             main_PutIntVariable( VOUT_FULLSCREEN_VAR, 1 );
632             break;
633         case OPT_OVERLAY:                                       /* --overlay */
634             main_PutIntVariable( VOUT_OVERLAY_VAR, 1 );
635             break;
636         case OPT_MOTION:                                         /* --motion */
637             main_PutPszVariable( MOTION_METHOD_VAR, optarg );
638             break;
639         case OPT_IDCT:                                             /* --idct */
640             main_PutPszVariable( IDCT_METHOD_VAR, optarg );
641             break;
642         case OPT_YUV:                                               /* --yuv */
643             main_PutPszVariable( YUV_METHOD_VAR, optarg );
644             break;
645
646         /* DVD options */
647         case 't':
648             main_PutIntVariable( INPUT_TITLE_VAR, atoi(optarg) );
649             break;
650         case 'T':
651             main_PutIntVariable( INPUT_CHAPTER_VAR, atoi(optarg) );
652             break;
653         case 'u':
654             main_PutIntVariable( INPUT_ANGLE_VAR, atoi(optarg) );
655             break;
656         case 'a':
657             if ( ! strcmp(optarg, "ac3") )
658                 main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_AC3 );
659             else if ( ! strcmp(optarg, "lpcm") )
660                 main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_LPCM );
661             else if ( ! strcmp(optarg, "mpeg") )
662                 main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_MPEG );
663             else
664                 main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_NOAUDIO );
665             break;
666         case 'c':
667             main_PutIntVariable( INPUT_CHANNEL_VAR, atoi(optarg) );
668             break;
669         case 's':
670             main_PutIntVariable( INPUT_SUBTITLE_VAR, atoi(optarg) );
671             break;
672
673         /* Input options */
674         case OPT_INPUT:                                           /* --input */
675             main_PutPszVariable( INPUT_METHOD_VAR, optarg );
676             break;
677         case OPT_CHANNELS:                                     /* --channels */
678             main_PutIntVariable( INPUT_NETWORK_CHANNEL_VAR, 1 );
679             break;
680         case OPT_SERVER:                                         /* --server */
681             main_PutPszVariable( INPUT_SERVER_VAR, optarg );
682             break;
683         case OPT_PORT:                                             /* --port */
684             main_PutPszVariable( INPUT_PORT_VAR, optarg );
685             break;
686         case OPT_BROADCAST:                                   /* --broadcast */
687             main_PutIntVariable( INPUT_BROADCAST_VAR, 1 );
688             main_PutPszVariable( INPUT_BCAST_ADDR_VAR, optarg );
689             break;
690
691         /* Synchro options */
692         case OPT_SYNCHRO:                                      
693             main_PutPszVariable( VPAR_SYNCHRO_VAR, optarg );
694             break;
695             
696         /* Internal error: unknown option */
697         case '?':
698         default:
699             intf_ErrMsg( "intf error: unknown option `%s'",
700                          ppsz_argv[optind - 1] );
701             Usage( USAGE );
702             return( EINVAL );
703             break;
704         }
705     }
706
707     if( p_main->i_warning_level < 0 )
708     {
709         p_main->i_warning_level = 0;
710     }
711
712     return( 0 );
713 }
714
715 /*****************************************************************************
716  * GetFilenames: parse command line options which are not flags
717  *****************************************************************************
718  * Parse command line for input files.
719  *****************************************************************************/
720 static int GetFilenames( int i_argc, char *ppsz_argv[] )
721 {
722     int i_opt;
723
724     /* We assume that the remaining parameters are filenames */
725     for( i_opt = optind; i_opt < i_argc; i_opt++ )
726     {
727         intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
728                           ppsz_argv[ i_opt ] );
729     }
730
731     return( 0 );
732 }
733
734 /*****************************************************************************
735  * Usage: print program usage
736  *****************************************************************************
737  * Print a short inline help. Message interface is initialized at this stage.
738  *****************************************************************************/
739 static void Usage( int i_fashion )
740 {
741     /* Usage */
742     intf_MsgImm( "Usage: %s [options] [parameters] [file]...",
743                  p_main->psz_arg0 );
744
745     if( i_fashion == USAGE )
746     {
747         intf_MsgImm( "Try `%s --help' for more information.",
748                      p_main->psz_arg0 );
749         return;
750     }
751
752     /* Options */
753     intf_MsgImm( "\nOptions:"
754           "\n  -I, --intf <module>            \tinterface method"
755           "\n  -v, --verbose                  \tverbose mode (cumulative)"
756           "\n"
757           "\n      --noaudio                  \tdisable audio"
758           "\n  -A, --aout <module>            \taudio output method"
759           "\n      --stereo, --mono           \tstereo/mono audio"
760           "\n      --spdif                    \tAC3 pass-through mode"
761           "\n      --downmix <module>         \tAC3 downmix method"
762           "\n      --imdct <module>           \tAC3 IMDCT method"
763           "\n"
764           "\n      --novideo                  \tdisable video"
765           "\n  -V, --vout <module>            \tvideo output method"
766           "\n      --display <display>        \tdisplay string"
767           "\n      --width <w>, --height <h>  \tdisplay dimensions"
768           "\n  -g, --grayscale                \tgrayscale output"
769           "\n      --fullscreen               \tfullscreen output"
770           "\n      --overlay                  \taccelerated display"
771           "\n      --color                    \tcolor output"
772           "\n      --motion <module>          \tmotion compensation method"
773           "\n      --idct <module>            \tIDCT method"
774           "\n      --yuv <module>             \tYUV method"
775           "\n      --synchro <type>           \tforce synchro algorithm"
776           "\n"
777           "\n  -t, --dvdtitle <num>           \tchoose DVD title"
778           "\n  -T, --dvdchapter <num>         \tchoose DVD chapter"
779           "\n  -u, --dvdangle <num>           \tchoose DVD angle"
780           "\n  -a, --dvdaudio <type>          \tchoose DVD audio type"
781           "\n  -c, --dvdchannel <channel>     \tchoose DVD audio channel"
782           "\n  -s, --dvdsubtitle <channel>    \tchoose DVD subtitle channel"
783           "\n"
784           "\n      --input                    \tinput method"
785           "\n      --channels                 \tenable channels"
786           "\n      --server <host>            \tvideo server address"
787           "\n      --port <port>              \tvideo server port"
788           "\n      --broadcast                \tlisten to a broadcast"
789           "\n"
790           "\n  -h, --help                     \tprint help and exit"
791           "\n  -H, --longhelp                 \tprint long help and exit"
792           "\n      --version                  \toutput version information and exit" );
793
794     if( i_fashion == SHORT_HELP )
795         return;
796
797     /* Interface parameters */
798     intf_MsgImm( "\nInterface parameters:"
799         "\n  " INTF_METHOD_VAR "=<method name>          \tinterface method"
800         "\n  " INTF_INIT_SCRIPT_VAR "=<filename>               \tinitialization script"
801         "\n  " INTF_CHANNELS_VAR "=<filename>            \tchannels list" );
802
803     /* Audio parameters */
804     intf_MsgImm( "\nAudio parameters:"
805         "\n  " AOUT_METHOD_VAR "=<method name>        \taudio method"
806         "\n  " AOUT_DSP_VAR "=<filename>              \tdsp device path"
807         "\n  " AOUT_STEREO_VAR "={1|0}                \tstereo or mono output"
808         "\n  " AOUT_SPDIF_VAR "={1|0}                 \tAC3 pass-through mode"
809         "\n  " DOWNMIX_METHOD_VAR "=<method name>     \tAC3 downmix method"
810         "\n  " IMDCT_METHOD_VAR "=<method name>       \tAC3 IMDCT method"
811         "\n  " AOUT_RATE_VAR "=<rate>             \toutput rate" );
812
813     /* Video parameters */
814     intf_MsgImm( "\nVideo parameters:"
815         "\n  " VOUT_METHOD_VAR "=<method name>        \tdisplay method"
816         "\n  " VOUT_DISPLAY_VAR "=<display name>      \tdisplay used"
817         "\n  " VOUT_WIDTH_VAR "=<width>               \tdisplay width"
818         "\n  " VOUT_HEIGHT_VAR "=<height>             \tdislay height"
819         "\n  " VOUT_FB_DEV_VAR "=<filename>           \tframebuffer device path"
820         "\n  " VOUT_GRAYSCALE_VAR "={1|0}             \tgrayscale or color output"
821         "\n  " VOUT_FULLSCREEN_VAR "={1|0}            \tfullscreen"
822         "\n  " VOUT_OVERLAY_VAR "={1|0}               \toverlay"
823         "\n  " MOTION_METHOD_VAR "=<method name>      \tmotion compensation method"
824         "\n  " IDCT_METHOD_VAR "=<method name>        \tIDCT method"
825         "\n  " YUV_METHOD_VAR "=<method name>         \tYUV method"
826         "\n  " VPAR_SYNCHRO_VAR "={I|I+|IP|IP+|IPB}   \tsynchro algorithm" );
827
828     /* DVD parameters */
829     intf_MsgImm( "\nDVD parameters:"
830         "\n  " INPUT_DVD_DEVICE_VAR "=<device>           \tDVD device"
831         "\n  " INPUT_TITLE_VAR "=<title>             \ttitle number"
832         "\n  " INPUT_CHAPTER_VAR "=<chapter>         \tchapter number"
833         "\n  " INPUT_ANGLE_VAR "=<angle>             \tangle number"
834         "\n  " INPUT_AUDIO_VAR "={ac3|lpcm|mpeg|off} \taudio type"
835         "\n  " INPUT_CHANNEL_VAR "=[0-15]            \taudio channel"
836         "\n  " INPUT_SUBTITLE_VAR "=[0-31]           \tsubtitle channel" );
837
838     /* Input parameters */
839     intf_MsgImm( "\nInput parameters:"
840         "\n  " INPUT_SERVER_VAR "=<hostname>         \tvideo server"
841         "\n  " INPUT_PORT_VAR "=<port>               \tvideo server port"
842         "\n  " INPUT_IFACE_VAR "=<interface>         \tnetwork interface"
843         "\n  " INPUT_BCAST_ADDR_VAR "=<addr>         \tbroadcast mode"
844         "\n  " INPUT_CHANNEL_SERVER_VAR "=<hostname> \tchannel server"
845         "\n  " INPUT_CHANNEL_PORT_VAR "=<port>       \tchannel server port" );
846
847 }
848
849 /*****************************************************************************
850  * Version: print complete program version
851  *****************************************************************************
852  * Print complete program version and build number.
853  *****************************************************************************/
854 static void Version( void )
855 {
856     intf_MsgImm( VERSION_MESSAGE
857         "This program comes with NO WARRANTY, to the extent permitted by law.\n"
858         "You may redistribute it under the terms of the GNU General Public License;\n"
859         "see the file named COPYING for details.\n"
860         "Written by the VideoLAN team at Ecole Centrale, Paris." );
861 }
862
863 /*****************************************************************************
864  * InitSignalHandler: system signal handler initialization
865  *****************************************************************************
866  * Set the signal handlers. SIGTERM is not intercepted, because we need at
867  * at least a method to kill the program when all other methods failed, and
868  * when we don't want to use SIGKILL.
869  *****************************************************************************/
870 static void InitSignalHandler( void )
871 {
872     /* Termination signals */
873 #ifndef WIN32
874     signal( SIGINT,  FatalSignalHandler );
875     signal( SIGHUP,  FatalSignalHandler );
876     signal( SIGQUIT, FatalSignalHandler );
877
878     /* Other signals */
879     signal( SIGALRM, SimpleSignalHandler );
880     signal( SIGPIPE, SimpleSignalHandler );
881 #endif
882 }
883
884
885 /*****************************************************************************
886  * SimpleSignalHandler: system signal handler
887  *****************************************************************************
888  * This function is called when a non fatal signal is received by the program.
889  *****************************************************************************/
890 static void SimpleSignalHandler( int i_signal )
891 {
892     /* Acknowledge the signal received */
893     intf_WarnMsg( 0, "intf: ignoring signal %d", i_signal );
894 }
895
896
897 /*****************************************************************************
898  * FatalSignalHandler: system signal handler
899  *****************************************************************************
900  * This function is called when a fatal signal is received by the program.
901  * It tries to end the program in a clean way.
902  *****************************************************************************/
903 static void FatalSignalHandler( int i_signal )
904 {
905     /* Once a signal has been trapped, the termination sequence will be
906      * armed and following signals will be ignored to avoid sending messages
907      * to an interface having been destroyed */
908 #ifndef WIN32
909     signal( SIGINT,  SIG_IGN );
910     signal( SIGHUP,  SIG_IGN );
911     signal( SIGQUIT, SIG_IGN );
912 #endif
913
914     /* Acknowledge the signal received */
915     intf_ErrMsgImm( "intf error: signal %d received, exiting", i_signal );
916
917     /* Try to terminate everything - this is done by requesting the end of the
918      * interface thread */
919     p_main->p_intf->b_die = 1;
920 }
921
922 /*****************************************************************************
923  * InstructionSignalHandler: system signal handler
924  *****************************************************************************
925  * This function is called when a illegal instruction signal is received by
926  * the program.
927  * We use this function to test OS and CPU_Capabilities
928  *****************************************************************************/
929 static void InstructionSignalHandler( int i_signal )
930 {
931     /* Once a signal has been trapped, the termination sequence will be
932      * armed and following signals will be ignored to avoid sending messages
933      * to an interface having been destroyed */
934
935     /* Acknowledge the signal received */
936     fprintf( stderr, "illegal instruction : optimization disabled\n" );
937
938     i_illegal = 1;
939     
940 #ifdef HAVE_SIGRELSE
941     sigrelse( i_signal );
942 #endif
943     longjmp( env, 1 );
944 }
945
946 /*****************************************************************************
947  * CPUCapabilities: list the processors MMX support and other capabilities
948  *****************************************************************************
949  * This function is called to list extensions the CPU may have.
950  *****************************************************************************/
951 static int CPUCapabilities( void )
952 {
953     volatile int i_capabilities = CPU_CAPABILITY_NONE;
954
955 #if defined( SYS_BEOS )
956     i_capabilities |= CPU_CAPABILITY_486
957                       | CPU_CAPABILITY_586
958                       | CPU_CAPABILITY_MMX;
959
960     return( i_capabilities );
961
962 #elif defined( SYS_DARWIN1_3 )
963     struct host_basic_info hi;
964     kern_return_t          ret;
965     host_name_port_t       host;
966
967     int i_size;
968     char *psz_name, *psz_subname;
969
970     /* Should 'never' fail? */
971     host = mach_host_self();
972
973     i_size = sizeof( hi ) / sizeof( int );
974     ret = host_info( host, HOST_BASIC_INFO, ( host_info_t )&hi, &i_size );
975
976     if( ret != KERN_SUCCESS )
977     {
978         intf_ErrMsg( "error: couldn't get CPU information" );
979         return( i_capabilities );
980     }
981
982     slot_name( hi.cpu_type, hi.cpu_subtype, &psz_name, &psz_subname );
983     /* FIXME: need better way to detect newer proccessors.
984      * could do strncmp(a,b,5), but that's real ugly */
985     if( strcmp(psz_name, "ppc7400") || strcmp(psz_name, "ppc7450") )
986     {
987         i_capabilities |= CPU_CAPABILITY_ALTIVEC;
988     }
989
990     return( i_capabilities );
991
992 #elif defined( __i386__ )
993     volatile unsigned int  i_eax, i_ebx, i_ecx, i_edx;
994     volatile boolean_t     b_amd;
995
996     signal( SIGILL, InstructionSignalHandler );
997     
998     /* test for a 486 CPU */
999     asm volatile ( "pushfl\n\t"
1000                    "popl %%eax\n\t"
1001                    "movl %%eax, %%ebx\n\t"
1002                    "xorl $0x200000, %%eax\n\t"
1003                    "pushl %%eax\n\t"
1004                    "popfl\n\t"
1005                    "pushfl\n\t"
1006                    "popl %%eax"
1007                  : "=a" ( i_eax ),
1008                    "=b" ( i_ebx )
1009                  :
1010                  : "cc" );
1011
1012     if( i_eax == i_ebx )
1013     {
1014         signal( SIGILL, NULL );     
1015         return( i_capabilities );
1016     }
1017
1018     i_capabilities |= CPU_CAPABILITY_486;
1019
1020     /* the CPU supports the CPUID instruction - get its level */
1021     cpuid( 0x00000000 );
1022
1023     if( !i_eax )
1024     {
1025         signal( SIGILL, NULL );     
1026         return( i_capabilities );
1027     }
1028
1029     /* FIXME: this isn't correct, since some 486s have cpuid */
1030     i_capabilities |= CPU_CAPABILITY_586;
1031
1032     /* borrowed from mpeg2dec */
1033     b_amd = ( i_ebx == 0x68747541 ) && ( i_ecx == 0x444d4163 )
1034                     && ( i_edx == 0x69746e65 );
1035
1036     /* test for the MMX flag */
1037     cpuid( 0x00000001 );
1038
1039     if( ! (i_edx & 0x00800000) )
1040     {
1041         signal( SIGILL, NULL );     
1042         return( i_capabilities );
1043     }
1044
1045     i_capabilities |= CPU_CAPABILITY_MMX;
1046
1047     if( i_edx & 0x02000000 )
1048     {
1049         i_capabilities |= CPU_CAPABILITY_MMXEXT;
1050
1051         /* We test if OS support the SSE instructions */
1052         i_illegal = 0;
1053         if( setjmp( env ) == 0 )
1054         {
1055             /* Test a SSE instruction */
1056             __asm__ __volatile__ ( "xorps %%xmm0,%%xmm0\n" : : );
1057         }
1058
1059         if( i_illegal == 0 )
1060         {
1061             i_capabilities |= CPU_CAPABILITY_SSE;
1062         }
1063     }
1064     
1065     /* test for additional capabilities */
1066     cpuid( 0x80000000 );
1067
1068     if( i_eax < 0x80000001 )
1069     {
1070         signal( SIGILL, NULL );     
1071         return( i_capabilities );
1072     }
1073
1074     /* list these additional capabilities */
1075     cpuid( 0x80000001 );
1076
1077     if( i_edx & 0x80000000 )
1078     {
1079         i_illegal = 0;
1080         if( setjmp( env ) == 0 )
1081         {
1082             /* Test a 3D Now! instruction */
1083             __asm__ __volatile__ ( "pfadd %%mm0,%%mm0\n" "femms\n" : : );
1084         }
1085
1086         if( i_illegal == 0 ) 
1087         {
1088             i_capabilities |= CPU_CAPABILITY_3DNOW;
1089         }
1090     }
1091
1092     if( b_amd && ( i_edx & 0x00400000 ) )
1093     {
1094         i_capabilities |= CPU_CAPABILITY_MMXEXT;
1095     }
1096
1097     signal( SIGILL, NULL );     
1098     return( i_capabilities );
1099
1100 #else
1101     /* default behaviour */
1102     return( i_capabilities );
1103
1104 #endif
1105 }
1106