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