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