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