]> git.sesse.net Git - vlc/blob - src/interface/main.c
Le retour du demoronifier qui n'est pas content.
[vlc] / src / interface / main.c
1 /*****************************************************************************
2  * main.c: main vlc source
3  * (c)1998 VideoLAN
4  *****************************************************************************
5  * Includes the main() function for vlc. Parses command line, start interface
6  * and spawn threads.
7  *****************************************************************************/
8
9 /*****************************************************************************
10  * Preamble
11  *****************************************************************************/
12 #include <errno.h>
13 #include <getopt.h>
14 #include <signal.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include "config.h"
20 #include "common.h"
21 #include "mtime.h"
22 #include "vlc_thread.h"
23 #include "input_vlan.h"
24 #include "intf_msg.h"
25 #include "interface.h"
26 #include "audio_output.h"
27 #include "main.h"
28
29 /*****************************************************************************
30  * Command line options constants. If something is changed here, be sure that
31  * GetConfiguration and Usage are also changed.
32  *****************************************************************************/
33
34 /* Long options return values - note that values corresponding to short options
35  * chars, and in general any regular char, should be avoided */
36 #define OPT_NOAUDIO             150
37 #define OPT_AOUT                151
38 #define OPT_STEREO              152
39 #define OPT_MONO                153
40
41 #define OPT_NOVIDEO             160
42 #define OPT_VOUT                161
43 #define OPT_DISPLAY             162
44 #define OPT_WIDTH               163
45 #define OPT_HEIGHT              164
46 #define OPT_COLOR               165
47
48 #define OPT_NOVLANS             170
49 #define OPT_SERVER              171
50 #define OPT_PORT                172
51
52 /* Usage fashion */
53 #define SHORT_HELP                0
54 #define LONG_HELP                 1
55
56 /* Long options */
57 static const struct option longopts[] =
58 {
59     /*  name,               has_arg,    flag,   val */
60
61     /* General/common options */
62     {   "help",             0,          0,      'h' },
63     {   "longhelp",         0,          0,      'H' },
64     {   "version",          0,          0,      'v' },
65
66     /* Audio options */
67     {   "noaudio",          0,          0,      OPT_NOAUDIO },
68     {   "aout",             1,          0,      OPT_AOUT },
69     {   "stereo",           0,          0,      OPT_STEREO },
70     {   "mono",             0,          0,      OPT_MONO },
71
72     /* Video options */
73     {   "novideo",          0,          0,      OPT_NOVIDEO },
74     {   "vout",             1,          0,      OPT_VOUT },
75     {   "display",          1,          0,      OPT_DISPLAY },
76     {   "width",            1,          0,      OPT_WIDTH },
77     {   "height",           1,          0,      OPT_HEIGHT },
78     {   "grayscale",        0,          0,      'g' },
79     {   "color",            0,          0,      OPT_COLOR },
80
81     /* Input options */
82     {   "novlans",          0,          0,      OPT_NOVLANS },
83     {   "server",           1,          0,      OPT_SERVER },
84     {   "port",             1,          0,      OPT_PORT },
85
86     {   0,                  0,          0,      0 }
87 };
88
89 /* Short options */
90 static const char *psz_shortopts = "hHvg";
91
92 /*****************************************************************************
93  * Global variable program_data - this is the one and only, see main.h
94  *****************************************************************************/
95 main_t *p_main;
96
97 /*****************************************************************************
98  * Local prototypes
99  *****************************************************************************/
100 static void SetDefaultConfiguration ( void );
101 static int  GetConfiguration        ( int i_argc, char *ppsz_argv[], char *ppsz_env[] );
102 static void Usage                   ( int i_fashion );
103 static void Version                 ( void );
104
105 static void InitSignalHandler       ( void );
106 static void SignalHandler           ( int i_signal );
107 static int  TestMMX                 ( void );
108
109 /*****************************************************************************
110  * main: parse command line, start interface and spawn threads
111  *****************************************************************************
112  * Steps during program execution are:
113  *      -configuration parsing and messages interface initialization
114  *      -openning of audio output device and some global modules
115  *      -execution of interface, which exit on error or on user request
116  *      -closing of audio output device and some global modules
117  * On error, the spawned threads are cancelled, and the open devices closed.
118  *****************************************************************************/
119 int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
120 {
121     main_t  main_data;                      /* root of all data - see main.h */
122     p_main = &main_data;                       /* set up the global variable */
123
124     /*
125      * Read configuration, initialize messages interface and set up program
126      */
127 #ifdef HAVE_MMX
128     if( !TestMMX() )
129     {
130         fprintf( stderr, "Sorry, this program needs an MMX processor. Please run the non-MMX version.\n" );
131         return( 1 );
132     }
133 #endif
134     p_main->p_msg = intf_MsgCreate();
135     if( !p_main->p_msg )                         /* start messages interface */
136     {
137         fprintf(stderr, "critical error: can't initialize messages interface (%s)\n",
138                 strerror(errno));
139         return(errno);
140     }
141     if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )  /* parse cmd line */
142     {
143         intf_MsgDestroy();
144         return(errno);
145     }
146     intf_MsgImm( COPYRIGHT_MESSAGE "\n" );          /* print welcome message */
147
148     /*
149      * Initialize shared resources and libraries
150      */
151     if( main_data.b_vlans && input_VlanCreate() )
152     {
153         /* On error during vlans initialization, switch of vlans */
154         intf_Msg("Virtual LANs initialization failed : vlans management is deactivated\n");
155         main_data.b_vlans = 0;
156     }
157
158     /*
159      * Open audio device and start aout thread
160      */
161     if( main_data.b_audio )
162     {
163         main_data.p_aout = aout_CreateThread( NULL );
164         if( main_data.p_aout == NULL )
165         {
166             /* On error during audio initialization, switch of audio */
167             intf_Msg("Audio initialization failed : audio is deactivated\n");
168             main_data.b_audio = 0;
169         }
170     }
171
172     /*
173      * Run interface
174      */
175     main_data.p_intf = intf_Create();
176     if( main_data.p_intf != NULL )
177     {
178         InitSignalHandler();             /* prepare signals for interception */
179         intf_Run( main_data.p_intf );
180         intf_Destroy( main_data.p_intf );
181     }
182
183     /*
184      * Close audio device
185      */
186     if( main_data.b_audio )
187     {
188         aout_DestroyThread( main_data.p_aout, NULL );
189     }
190
191     /*
192      * Free shared resources and libraries
193      */
194     if( main_data.b_vlans )
195     {
196         input_VlanDestroy();
197     }
198
199     /*
200      * Terminate messages interface and program
201      */
202     intf_Msg( "Program terminated.\n" );
203     intf_MsgDestroy();
204     return( 0 );
205 }
206
207 /*****************************************************************************
208  * main_GetIntVariable: get the int value of an environment variable
209  *****************************************************************************
210  * This function is used to read some default parameters in modules.
211  *****************************************************************************/
212 int main_GetIntVariable( char *psz_name, int i_default )
213 {
214     char *      psz_env;                                /* environment value */
215     char *      psz_end;                             /* end of parsing index */
216     long int    i_value;                                            /* value */
217
218     psz_env = getenv( psz_name );
219     if( psz_env )
220     {
221         i_value = strtol( psz_env, &psz_end, 0 );
222         if( (*psz_env != '\0') && (*psz_end == '\0') )
223         {
224             return( i_value );
225         }
226     }
227     return( i_default );
228 }
229
230 /*****************************************************************************
231  * main_GetPszVariable: get the string value of an environment variable
232  *****************************************************************************
233  * This function is used to read some default parameters in modules.
234  *****************************************************************************/
235 char * main_GetPszVariable( char *psz_name, char *psz_default )
236 {
237     char *psz_env;
238
239     psz_env = getenv( psz_name );
240     if( psz_env )
241     {
242         return( psz_env );
243     }
244     return( psz_default );
245 }
246
247 /*****************************************************************************
248  * main_PutPszVariable: set the string value of an environment variable
249  *****************************************************************************
250  * This function is used to set some default parameters in modules. The use of
251  * this function will cause some memory leak: since some systems use the pointer
252  * passed to putenv to store the environment string, it can't be freed.
253  *****************************************************************************/
254 void main_PutPszVariable( char *psz_name, char *psz_value )
255 {
256     char *psz_env;
257
258     psz_env = malloc( strlen(psz_name) + strlen(psz_value) + 2 );
259     if( psz_env == NULL )
260     {
261         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
262     }
263     else
264     {
265         sprintf( psz_env, "%s=%s", psz_name, psz_value );
266         if( putenv( psz_env ) )
267         {
268             intf_ErrMsg("error: %s\n", strerror(errno));
269         }
270     }
271 }
272
273 /*****************************************************************************
274  * main_PutIntVariable: set the integer value of an environment variable
275  *****************************************************************************
276  * This function is used to set some default parameters in modules. The use of
277  * this function will cause some memory leak: since some systems use the pointer
278  * passed to putenv to store the environment string, it can't be freed.
279  *****************************************************************************/
280 void main_PutIntVariable( char *psz_name, int i_value )
281 {
282     char psz_value[ 256 ];                               /* buffer for value */
283
284     sprintf(psz_value, "%d", i_value );
285     main_PutPszVariable( psz_name, psz_value );
286 }
287
288 /* following functions are local */
289
290 /*****************************************************************************
291  * SetDefaultConfiguration: set default options
292  *****************************************************************************
293  * This function is called by GetConfiguration before command line is parsed.
294  * It sets all the default values required later by the program. At this stage,
295  * most structure are not yet allocated, so initialization must be done using
296  * environment.
297  *****************************************************************************/
298 static void SetDefaultConfiguration( void )
299 {
300     /*
301      * All features are activated by default
302      */
303     p_main->b_audio  = 1;
304     p_main->b_video  = 1;
305     p_main->b_vlans  = 1;
306 }
307
308 /*****************************************************************************
309  * GetConfiguration: parse command line
310  *****************************************************************************
311  * Parse command line and configuration file for configuration. If the inline
312  * help is requested, the function Usage() is called and the function returns
313  * -1 (causing main() to exit). The messages interface is initialized at this
314  * stage, but most structures are not allocated, so only environment should
315  * be used.
316  *****************************************************************************/
317 static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
318 {
319     int c, i_opt;
320
321     /* Set default configuration and copy arguments */
322     p_main->i_argc    = i_argc;
323     p_main->ppsz_argv = ppsz_argv;
324     p_main->ppsz_env  = ppsz_env;
325     SetDefaultConfiguration();
326
327     /* Parse command line options */
328     opterr = 0;
329     while( ( c = getopt_long( i_argc, ppsz_argv, psz_shortopts, longopts, 0 ) ) != EOF )
330     {
331         switch( c )
332         {
333         /* General/common options */
334         case 'h':                                              /* -h, --help */
335             Usage( SHORT_HELP );
336             return( -1 );
337             break;
338         case 'H':                                          /* -H, --longhelp */
339             Usage( LONG_HELP );
340             return( -1 );
341             break;
342         case 'v':                                           /* -v, --version */
343             Version();
344             return( -1 );
345             break;
346
347         /* Audio options */
348         case OPT_NOAUDIO:                                       /* --noaudio */
349             p_main->b_audio = 0;
350             break;
351         case OPT_AOUT:                                             /* --aout */
352             main_PutPszVariable( AOUT_METHOD_VAR, optarg );
353             break;
354         case OPT_STEREO:                                         /* --stereo */
355             main_PutIntVariable( AOUT_STEREO_VAR, 1 );
356             break;
357         case OPT_MONO:                                             /* --mono */
358             main_PutIntVariable( AOUT_STEREO_VAR, 0 );
359             break;
360
361         /* Video options */
362         case OPT_NOVIDEO:                                       /* --novideo */
363             p_main->b_video = 0;
364             break;
365         case OPT_VOUT:                                             /* --vout */
366             main_PutPszVariable( VOUT_METHOD_VAR, optarg );
367             break;
368         case OPT_DISPLAY:                                       /* --display */
369             main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
370             break;
371         case OPT_WIDTH:                                           /* --width */
372             main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
373             break;
374         case OPT_HEIGHT:                                         /* --height */
375             main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );
376             break;
377
378         case 'g':                                         /* -g, --grayscale */
379             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
380             break;
381         case OPT_COLOR:                                           /* --color */
382             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
383             break;
384
385         /* Input options */
386         case OPT_NOVLANS:                                       /* --novlans */
387             p_main->b_vlans = 0;
388             break;
389         case OPT_SERVER:                                         /* --server */
390             main_PutPszVariable( INPUT_SERVER_VAR, optarg );
391             break;
392         case OPT_PORT:                                             /* --port */
393             main_PutPszVariable( INPUT_PORT_VAR, optarg );
394             break;
395
396         /* Internal error: unknown option */
397         case '?':
398         default:
399             intf_ErrMsg("intf error: unknown option '%s'\n", ppsz_argv[optind - 1]);
400             return( EINVAL );
401             break;
402         }
403     }
404
405     /* Parse command line parameters - no check is made for these options */
406     for( i_opt = optind; i_opt < i_argc; i_opt++ )
407     {
408         putenv( ppsz_argv[ i_opt ] );
409     }
410     return( 0 );
411 }
412
413 /*****************************************************************************
414  * Usage: print program usage
415  *****************************************************************************
416  * Print a short inline help. Message interface is initialized at this stage.
417  *****************************************************************************/
418 static void Usage( int i_fashion )
419 {
420     intf_Msg(COPYRIGHT_MESSAGE "\n");
421
422     /* Usage */
423     intf_Msg("usage: vlc [options...] [parameters]\n" );
424
425     /* Options */
426     intf_Msg("Options:\n" \
427              "  -h, --help, -H, --longhelp        \tprint short/long usage\n" \
428              "  -v, --version                     \tprint version information\n"\
429              "  --noaudio, --novideo              \tdisable audio/video\n" \
430              "  --aout {" AUDIO_OPTIONS "}            \taudio output method\n"\
431              "  --stereo, --mono                  \tstereo/mono audio\n" \
432              "  --vout {" VIDEO_OPTIONS "}            \tvideo output method\n"\
433              "  --display <display>               \tdisplay string\n" \
434              "  --width <w>, --height <h>         \tdisplay dimensions\n" \
435              "  -g, --grayscale, --color          \tgrayscale/color video\n" \
436              "  --novlans                         \tdisable vlans\n" \
437              "  --server <host>, --port <port>    \tvideo server adress\n" \
438              );
439
440     if( i_fashion == SHORT_HELP )
441         return;
442
443     /* Interface parameters */
444     intf_Msg("Interface parameters:\n" \
445              "  " INTF_INIT_SCRIPT_VAR "=<filename>             \tinitialization script\n" \
446              "  " INTF_CHANNELS_VAR "=<filename>            \tchannels list\n"\
447              );
448
449     /* Audio parameters */
450     intf_Msg("Audio parameters:\n" \
451              "  " AOUT_METHOD_VAR "=<method name>        \taudio method (" AUDIO_OPTIONS ")\n" \
452              "  " AOUT_DSP_VAR "=<filename>              \tdsp device path\n" \
453              "  " AOUT_STEREO_VAR "={1|0}                \tstereo or mono output\n" \
454              "  " AOUT_RATE_VAR "=<rate>             \toutput rate\n" \
455              );
456
457     /* Video parameters */
458     intf_Msg("Video parameters:\n" \
459              "  " VOUT_METHOD_VAR "=<method name>        \tdisplay method (" VIDEO_OPTIONS ")\n" \
460              "  " VOUT_DISPLAY_VAR "=<display name>      \tdisplay used\n" \
461              "  " VOUT_WIDTH_VAR "=<width>               \tdisplay width\n" \
462              "  " VOUT_HEIGHT_VAR "=<height>             \tdislay height\n" \
463              "  " VOUT_FB_DEV_VAR "=<filename>           \tframebuffer device path\n" \
464              "  " VOUT_GRAYSCALE_VAR "={1|0}             \tgrayscale or color output\n" \
465              );
466
467     /* Input parameters */
468     intf_Msg("Input parameters:\n" \
469              "  " INPUT_SERVER_VAR "=<hostname>          \tvideo server\n" \
470              "  " INPUT_PORT_VAR "=<port>            \tvideo server port\n" \
471              "  " INPUT_IFACE_VAR "=<interface>          \tnetwork interface\n"\
472              "  " INPUT_VLAN_SERVER_VAR "=<hostname>     \tvlan server\n" \
473              "  " INPUT_VLAN_PORT_VAR "=<port>           \tvlan server port\n"\
474              );
475 }
476
477 /*****************************************************************************
478  * Version: print complete program version
479  *****************************************************************************
480  * Print complete program version and build number.
481  *****************************************************************************/
482 static void Version( void )
483 {
484     intf_Msg(VERSION_MESSAGE "\n\n");
485     intf_Msg("This is free software; see the documentation or contact <videolan@via.ecp.fr>\n" \
486              "for use and copying conditions.\n" \
487              "\n" \
488              "This software is protected by the international copyright laws, and is\n" \
489              "provided without any warranty, including the implied warranties of\n" \
490              "merchantibility and fitness for a particular purpose.\n" \
491             );
492 }
493
494 /*****************************************************************************
495  * InitSignalHandler: system signal handler initialization
496  *****************************************************************************
497  * Set the signal handlers. SIGTERM is not intercepted, because we need at
498  * at least a method to kill the program when all other methods failed, and
499  * when we don't want to use SIGKILL.
500  *****************************************************************************/
501 static void InitSignalHandler( void )
502 {
503     /* Termination signals */
504     signal( SIGHUP,  SignalHandler );
505     signal( SIGINT,  SignalHandler );
506     signal( SIGQUIT, SignalHandler );
507 }
508
509 /*****************************************************************************
510  * SignalHandler: system signal handler
511  *****************************************************************************
512  * This function is called when a signal is received by the program. It tries to
513  * end the program in a clean way.
514  *****************************************************************************/
515 static void SignalHandler( int i_signal )
516 {
517     /* Once a signal has been trapped, the termination sequence will be armed and
518      * following signals will be ignored to avoid sending messages to an interface
519      * having been destroyed */
520     signal( SIGHUP,  SIG_IGN );
521     signal( SIGINT,  SIG_IGN );
522     signal( SIGQUIT, SIG_IGN );
523
524     /* Acknowledge the signal received */
525     intf_ErrMsgImm("intf: signal %d received\n", i_signal );
526
527     /* Try to terminate everything - this is done by requesting the end of the
528      * interface thread */
529     p_main->p_intf->b_die = 1;
530 }
531
532 #ifdef HAVE_MMX
533 /*****************************************************************************
534  * TestMMX: tests if the processor has MMX support.
535  *****************************************************************************
536  * This function is called if HAVE_MMX is enabled, to check whether the
537  * cpu really supports MMX.
538  *****************************************************************************/
539 static int TestMMX( void )
540 {
541     int i_reg, i_dummy = 0;
542
543     /* test for a 386 cpu */
544     asm volatile ( "pushfl
545                     popl %%eax
546                     movl %%eax, %%ecx
547                     xorl $0x40000, %%eax
548                     pushl %%eax
549                     popfl
550                     pushfl
551                     popl %%eax
552                     xorl %%ecx, %%eax
553                     andl $0x40000, %%eax"
554                  : "=a" ( i_reg ) );
555
556     if( !i_reg )
557         return( 0 );
558
559     /* test for a 486 cpu */
560     asm volatile ( "movl %%ecx, %%eax
561                     xorl $0x200000, %%eax
562                     pushl %%eax
563                     popfl
564                     pushfl
565                     popl %%eax
566                     xorl %%ecx, %%eax
567                     pushl %%ecx
568                     popfl
569                     andl $0x200000, %%eax"
570                  : "=a" ( i_reg ) );
571
572     if( !i_reg )
573         return( 0 );
574
575     /* the cpu supports the CPUID instruction - get its level */
576     asm volatile ( "cpuid"
577                  : "=a" ( i_reg ),
578                    "=b" ( i_dummy ),
579                    "=c" ( i_dummy ),
580                    "=d" ( i_dummy )
581                  : "a"  ( 0 ),       /* level 0 */
582                    "b"  ( i_dummy ) ); /* buggy compiler shouldn't complain */
583
584     /* this shouldn't happen on a normal cpu */
585     if( !i_reg )
586         return( 0 );
587
588     /* test for the MMX flag */
589     asm volatile ( "cpuid
590                     andl $0x00800000, %%edx" /* X86_FEATURE_MMX */
591                  : "=a" ( i_dummy ),
592                    "=b" ( i_dummy ),
593                    "=c" ( i_dummy ),
594                    "=d" ( i_reg )
595                  : "a"  ( 1 ),       /* level 1 */
596                    "b"  ( i_dummy ) ); /* buggy compiler shouldn't complain */
597
598     if( !i_reg )
599         return( 0 );
600
601     return( 1 );
602 }
603 #endif