]> git.sesse.net Git - vlc/blob - src/interface/main.c
Gras de parametres en ligne de commande ou en variables d'environnement,
[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
60     /* Audio options */
61     {   "noaudio",          0,          0,      OPT_NOAUDIO },       
62     {   "stereo",           0,          0,      OPT_STEREO },
63     {   "mono",             0,          0,      OPT_MONO },      
64
65     /* Video options */
66     {   "novideo",          0,          0,      OPT_NOVIDEO },           
67     {   "display",          1,          0,      OPT_DISPLAY },  
68     {   "width",            1,          0,      OPT_WIDTH },
69     {   "height",           1,          0,      OPT_HEIGHT },                
70     {   "grayscale",        0,          0,      'g' },    
71     {   "color",            0,          0,      OPT_COLOR },                
72
73     /* Input options */
74     {   "novlans",          0,          0,      OPT_NOVLANS },
75     {   "server",           1,          0,      OPT_SERVER },
76     {   "port",             1,          0,      OPT_PORT },
77
78     {   0,                  0,          0,      0 }
79 };
80
81 /* Short options */
82 static const char *psz_shortopts = "hg";
83
84 /*******************************************************************************
85  * Global variable program_data - this is the one and only, see main.h
86  *******************************************************************************/
87 main_t *p_main;
88
89 /*******************************************************************************
90  * Local prototypes
91  *******************************************************************************/
92 static void SetDefaultConfiguration ( void );
93 static int  GetConfiguration        ( int i_argc, char *ppsz_argv[], char *ppsz_env[] );
94 static void Usage                   ( void );
95
96 static void InitSignalHandler       ( void );
97 static void SignalHandler           ( int i_signal );
98
99 /*******************************************************************************
100  * main: parse command line, start interface and spawn threads
101  *******************************************************************************
102  * Steps during program execution are:
103  *      -configuration parsing and messages interface initialization
104  *      -openning of audio output device and some global modules
105  *      -execution of interface, which exit on error or on user request
106  *      -closing of audio output device and some global modules
107  * On error, the spawned threads are cancelled, and the openned devices closed.
108  *******************************************************************************/
109 int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
110 {
111     main_t  main_data;                        /* root of all data - see main.h */
112     p_main = &main_data;                         /* set up the global variable */   
113
114     /*
115      * Read configuration, initialize messages interface and set up program
116      */    
117     p_main->p_msg = intf_MsgCreate();
118     if( !p_main->p_msg )                           /* start messages interface */
119     {
120         fprintf(stderr, "critical error: can't initialize messages interface (%s)\n",
121                 strerror(errno));
122         return(errno);
123     }
124     if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )/* parse command line */
125     {
126         intf_MsgDestroy();
127         return(errno);
128     }
129     intf_MsgImm( COPYRIGHT_MESSAGE "\n" );            /* print welcome message */
130
131     /*
132      * Initialize shared resources and libraries
133      */
134     if( main_data.b_vlans && input_VlanCreate() )
135     {
136         /* On error during vlans initialization, switch of vlans */
137         intf_Msg("Virtual LANs initialization failed : vlans management is desactivated\n");
138         main_data.b_vlans = 0;
139     }
140     
141     /*
142      * Open audio device and start aout thread
143      */
144     if( main_data.b_audio )
145     {
146         main_data.p_aout = aout_CreateThread( NULL );
147         if( main_data.p_aout == NULL )
148         {
149             /* On error during audio initialization, switch of audio */
150             intf_Msg("Audio initialization failed : audio is desactivated\n");
151             main_data.b_audio = 0;
152         }
153     }
154     
155     /*
156      * Run interface
157      */
158     main_data.p_intf = intf_Create();
159     if( main_data.p_intf != NULL )
160     {
161         InitSignalHandler();               /* prepare signals for interception */
162         intf_Run( main_data.p_intf );
163         intf_Destroy( main_data.p_intf );
164     }
165
166     /*
167      * Close audio device
168      */
169     if( main_data.b_audio )
170     {
171         aout_DestroyThread( main_data.p_aout, NULL );
172     }
173
174     /*
175      * Free shared resources and libraries
176      */
177     if( main_data.b_vlans )
178     {        
179         input_VlanDestroy();    
180     }    
181
182     /*
183      * Terminate messages interface and program
184      */
185     intf_Msg( "Program terminated.\n" );
186     intf_MsgDestroy();
187     return( 0 );
188 }
189
190 /*******************************************************************************
191  * main_GetIntVariable: get the int value of an environment variable
192  *******************************************************************************
193  * This function is used to read some default parameters in modules.
194  *******************************************************************************/
195 int main_GetIntVariable( char *psz_name, int i_default )
196 {
197     char *      psz_env;                                  /* environment value */
198     char *      psz_end;                               /* end of parsing index */
199     long int    i_value;                                              /* value */
200
201     psz_env = getenv( psz_name );
202     if( psz_env )
203     {        
204         i_value = strtol( psz_env, &psz_end, 0 );
205         if( (*psz_env != '\0') && (*psz_end == '\0') )
206         {
207             return( i_value );
208         }        
209     }   
210     return( i_default );
211 }
212
213 /*******************************************************************************
214  * main_GetPszVariable: get the string value of an environment variable
215  *******************************************************************************
216  * This function is used to read some default parameters in modules.
217  *******************************************************************************/
218 char * main_GetPszVariable( char *psz_name, char *psz_default )
219 {
220     char *psz_env;
221
222     psz_env = getenv( psz_name );
223     if( psz_env )
224     {
225         return( psz_env );
226     }
227     return( psz_default );    
228 }
229
230 /*******************************************************************************
231  * main_PutPszVariable: set the string value of an environment variable
232  *******************************************************************************
233  * This function is used to set some default parameters in modules. The use of
234  * this function will cause some memory leak: since some systems use the pointer
235  * passed to putenv to store the environment string, it can't be freed.
236  *******************************************************************************/
237 void main_PutPszVariable( char *psz_name, char *psz_value )
238 {
239     char *psz_env;
240
241     psz_env = malloc( strlen(psz_name) + strlen(psz_value) + 2 );
242     if( psz_env == NULL )
243     {
244         intf_ErrMsg("error: %s\n", strerror(ENOMEM));        
245     }
246     else
247     {
248         sprintf( psz_env, "%s=%s", psz_name, psz_value );
249         if( putenv( psz_env ) )
250         {
251             intf_ErrMsg("error: %s\n", strerror(errno));
252         }        
253     }
254 }
255
256 /*******************************************************************************
257  * main_PutIntVariable: set the integer value of an environment variable
258  *******************************************************************************
259  * This function is used to set some default parameters in modules. The use of
260  * this function will cause some memory leak: since some systems use the pointer
261  * passed to putenv to store the environment string, it can't be freed.
262  *******************************************************************************/
263 void main_PutIntVariable( char *psz_name, int i_value )
264 {
265     char psz_value[ 256 ];                                 /* buffer for value */    
266
267     sprintf(psz_value, "%d", i_value );        
268     main_PutPszVariable( psz_name, psz_value );    
269 }
270
271 /* following functions are local */
272
273 /*******************************************************************************
274  * SetDefaultConfiguration: set default options
275  *******************************************************************************
276  * This function is called by GetConfiguration before command line is parsed.
277  * It sets all the default values required later by the program. At this stage,
278  * most structure are not yet allocated, so initialization must be done using
279  * environment.
280  *******************************************************************************/
281 static void SetDefaultConfiguration( void )
282 {
283     /*
284      * All features are activated by default
285      */
286     p_main->b_audio  = 1;
287     p_main->b_video  = 1;
288     p_main->b_vlans  = 1;
289 }
290
291 /*******************************************************************************
292  * GetConfiguration: parse command line
293  *******************************************************************************
294  * Parse command line and configuration file for configuration. If the inline
295  * help is requested, the function Usage() is called and the function returns
296  * -1 (causing main() to exit). The messages interface is initialized at this 
297  * stage, but most structures are not allocated, so only environment should
298  * be used.
299  *******************************************************************************/
300 static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
301 {
302     int c, i_opt;
303
304     /* Set default configuration and copy arguments */
305     p_main->i_argc    = i_argc;
306     p_main->ppsz_argv = ppsz_argv;
307     p_main->ppsz_env  = ppsz_env;    
308     SetDefaultConfiguration();
309
310     /* Parse command line options */
311     opterr = 0;
312     while( ( c = getopt_long( i_argc, ppsz_argv, psz_shortopts, longopts, 0 ) ) != EOF )
313     {
314         switch( c )
315         {
316         /* General/common options */   
317         case 'h':                                                /* -h, --help */
318             Usage();
319             return( -1 );
320             break;
321
322         /* Audio options */
323         case OPT_NOAUDIO:                                        /* --noaudio */
324             p_main->b_audio = 0;
325             break;
326         case OPT_STEREO:                                          /* --stereo */
327             main_PutIntVariable( AOUT_STEREO_VAR, 1 );
328             break;
329         case OPT_MONO:                                              /* --mono */
330             main_PutIntVariable( AOUT_STEREO_VAR, 0 );
331             break;
332
333         /* Video options */
334         case OPT_NOVIDEO:                                         /* --novideo */
335             p_main->b_video = 0;
336             break;       
337         case OPT_DISPLAY:                                         /* --display */
338             main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
339             break;            
340         case OPT_WIDTH:                                             /* --width */
341             main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
342             break;            
343         case OPT_HEIGHT:                                           /* --height */            
344             main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );            
345             break;            
346             
347         case 'g':                                           /* -g, --grayscale */
348             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
349             break;            
350         case OPT_COLOR:                                             /* --color */
351             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
352             break;            
353
354         /* Input options */
355         case OPT_NOVLANS:                                         /* --novlans */
356             p_main->b_vlans = 0;
357             break;      
358         case OPT_SERVER:                                           /* --server */
359             main_PutPszVariable( INPUT_SERVER_VAR, optarg );
360             break;            
361         case OPT_PORT:                                               /* --port */
362             main_PutPszVariable( INPUT_PORT_VAR, optarg );
363             break;            
364             
365         /* Internal error: unknown option */
366         case '?':                          
367         default:
368             intf_ErrMsg("intf error: unknown option '%s'\n", ppsz_argv[optind - 1]);
369             return( EINVAL );
370             break;
371         }
372     }
373
374     /* Parse command line parameters - no check is made for these options */
375     for( i_opt = optind; i_opt < i_argc; i_opt++ )
376     {
377         putenv( ppsz_argv[ i_opt ] );
378     }
379     return( 0 );
380 }
381
382 /*******************************************************************************
383  * Usage: print program usage
384  *******************************************************************************
385  * Print a short inline help. Message interface is initialized at this stage.
386  *******************************************************************************/
387 static void Usage( void )
388 {
389     intf_Msg(COPYRIGHT_MESSAGE "\n");
390
391     /* Usage */
392     intf_Msg("usage: vlc [options...] [parameters]\n" );
393
394     /* Options */
395     intf_Msg("Options:\n" \
396              "  -h, --help                        \tprint usage\n" \
397              "  --noaudio                         \tdisable audio\n" \
398              "  --stereo, --mono                  \tstereo/mono audio\n" \
399              "  --novideo                         \tdisable video\n" \
400              "  --display <display>               \tdisplay string\n" \
401              "  --width <w>, --height <h>         \tdisplay dimensions\n" \
402              "  -g, --grayscale, --color          \tgrayscale/color video\n" \
403              "  --novlans                         \tdisable vlans\n" \
404              "  --server <host>, --port <port>    \tvideo server adress\n" \
405              );
406
407     /* Interface parameters */
408     intf_Msg("Interface parameters:\n" \
409              "  " INTF_INIT_SCRIPT_VAR "=<filename>             \tinitialization script\n" \
410              );
411
412     /* Audio parameters */
413     intf_Msg("Audio parameters:\n" \
414              "  " AOUT_DSP_VAR "=<filename>              \tdsp device path\n" \
415              "  " AOUT_STEREO_VAR "={1|0}                \tstereo or mono output\n" \
416              "  " AOUT_RATE_VAR "=<rate>             \toutput rate\n" \
417              );
418
419     /* Video parameters */
420     intf_Msg("Video parameters:\n" \
421              "  " VOUT_DISPLAY_VAR "=<display name>      \tdisplay used\n" \
422              "  " VOUT_WIDTH_VAR "=<width>               \tdisplay width\n" \
423              "  " VOUT_HEIGHT_VAR "=<height>             \tdislay height\n" \
424              "  " VOUT_FB_DEV_VAR "=<filename>           \tframebuffer device path\n" \
425              "  " VOUT_GRAYSCALE_VAR "={1|0}             \tgrayscale or color output\n" \
426              ); 
427
428     /* Input parameters */
429     intf_Msg("Input parameters:\n" \
430              "  " INPUT_SERVER_VAR "=<hostname>          \tvideo server\n" \
431              "  " INPUT_PORT_VAR "=<port>            \tvideo server port\n" \
432              "  " INPUT_IFACE_VAR "=<interface>          \tnetwork interface\n" \
433              "  " INPUT_VLAN_SERVER_VAR "=<hostname>     \tvlan server\n" \
434              "  " INPUT_VLAN_PORT_VAR "=<port>           \tvlan server port\n" \
435              );
436
437     /* Interfaces keys */
438     intf_Msg("Interface keys: most interfaces accept the following commands:\n" \
439              "  [esc], q                          \tquit\n" \
440              "  +, -, m                           \tchange volume, mute\n" \
441              "  g, G, c                           \tchange gamma, toggle grayscale\n" \
442              "  0 - 9                             \tselect channel\n" \
443              "  [space]                           \ttoggle info printing\n" \
444              );    
445 }
446
447 /*******************************************************************************
448  * InitSignalHandler: system signal handler initialization
449  *******************************************************************************
450  * Set the signal handlers. SIGTERM is not intercepted, because we need at
451  * at least a method to kill the program when all other methods failed, and 
452  * when we don't want to use SIGKILL.
453  *******************************************************************************/
454 static void InitSignalHandler( void )
455 {
456     /* Termination signals */
457     signal( SIGHUP,  SignalHandler );
458     signal( SIGINT,  SignalHandler );
459     signal( SIGQUIT, SignalHandler );
460 }
461
462 /*******************************************************************************
463  * SignalHandler: system signal handler
464  *******************************************************************************
465  * This function is called when a signal is received by the program. It tries to
466  * end the program in a clean way.
467  *******************************************************************************/
468 static void SignalHandler( int i_signal )
469 {
470     /* Once a signal has been trapped, the termination sequence will be armed and 
471      * following signals will be ignored to avoid sending messages to an interface
472      * having been destroyed */
473     signal( SIGHUP,  SIG_IGN );
474     signal( SIGINT,  SIG_IGN );
475     signal( SIGQUIT, SIG_IGN );
476
477     /* Acknowledge the signal received */
478     intf_ErrMsgImm("intf: signal %d received\n", i_signal );
479
480     /* Try to terminate everything - this is done by requesting the end of the 
481      * interface thread */
482     p_main->p_intf->b_die = 1;
483 }
484
485
486