]> git.sesse.net Git - vlc/blob - src/interface/main.c
A tout kass�.
[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 #define OPT_RATE                153
42
43 #define OPT_NOVIDEO             160
44 #define OPT_XDGA                161
45 #define OPT_XSHM                162
46 #define OPT_XNOSHM              163
47 #define OPT_XNODGA              164
48
49 #define OPT_NOVLANS             170
50 #define OPT_VLAN_SERVER         171
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
68     /* VLAN management options */
69     {   "novlans",          0,          0,      OPT_NOVLANS },
70
71     {   0,                  0,          0,      0 }
72 };
73
74 /* Short options */
75 static const char *psz_shortopts = "h";
76
77 /*******************************************************************************
78  * Global variable program_data - this is the one and only, see main.h
79  *******************************************************************************/
80 main_t *p_main;
81
82 /*******************************************************************************
83  * Local prototypes
84  *******************************************************************************/
85 static void SetDefaultConfiguration ( void );
86 static int  GetConfiguration        ( int i_argc, char *ppsz_argv[], char *ppsz_env[] );
87 static void Usage                   ( void );
88
89 static void InitSignalHandler       ( void );
90 static void SignalHandler           ( int i_signal );
91
92 /*******************************************************************************
93  * main: parse command line, start interface and spawn threads
94  *******************************************************************************
95  * Steps during program execution are:
96  *      -configuration parsing and messages interface initialization
97  *      -openning of audio output device and some global modules
98  *      -execution of interface, which exit on error or on user request
99  *      -closing of audio output device and some global modules
100  * On error, the spawned threads are cancelled, and the openned devices closed.
101  *******************************************************************************/
102 int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
103 {
104     main_t  main_data;                        /* root of all data - see main.h */
105     p_main = &main_data;                         /* set up the global variable */   
106
107     /*
108      * Read configuration, initialize messages interface and set up program
109      */    
110     p_main->p_msg = intf_MsgCreate();
111     if( !p_main->p_msg )                           /* start messages interface */
112     {
113         fprintf(stderr, "critical error: can't initialize messages interface (%s)\n",
114                 strerror(errno));
115         return(errno);
116     }
117     if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )/* parse command line */
118     {
119         intf_MsgDestroy();
120         return(errno);
121     }
122     intf_MsgImm( COPYRIGHT_MESSAGE );                 /* print welcome message */
123
124     /*
125      * Initialize shared resources and libraries
126      */
127     if( main_data.b_vlans && input_VlanCreate() )
128     {
129         /* On error during vlans initialization, switch of vlans */
130         intf_Msg("Virtual LANs initialization failed : vlans management is desactivated\n");
131         main_data.b_vlans = 0;
132     }
133     
134     /*
135      * Open audio device and start aout thread
136      */
137     if( main_data.b_audio )
138     {
139         main_data.p_aout = aout_CreateThread( NULL );
140         if( main_data.p_aout == NULL )
141         {
142             /* On error during audio initialization, switch of audio */
143             intf_Msg("Audio initialization failed : audio is desactivated\n");
144             main_data.b_audio = 0;
145         }
146     }
147     
148     /*
149      * Run interface
150      */
151     main_data.p_intf = intf_Create();
152     if( main_data.p_intf != NULL )
153     {
154         InitSignalHandler();               /* prepare signals for interception */
155         intf_Run( main_data.p_intf );
156         intf_Destroy( main_data.p_intf );
157     }
158
159     /*
160      * Close audio device
161      */
162     if( main_data.b_audio )
163     {
164         aout_DestroyThread( main_data.p_aout, NULL );
165     }
166
167     /*
168      * Free shared resources and libraries
169      */
170     if( main_data.b_vlans )
171     {        
172         input_VlanDestroy();    
173     }    
174
175     /*
176      * Terminate messages interface and program
177      */
178     intf_Msg( "Program terminated.\n" );
179     intf_MsgDestroy();
180     return( 0 );
181 }
182
183 /*******************************************************************************
184  * main_GetIntVariable: get the int value of an environment variable
185  *******************************************************************************
186  * This function is used to read some default parameters in modules.
187  *******************************************************************************/
188 int main_GetIntVariable( char *psz_name, int i_default )
189 {
190     char *psz_env;
191
192     psz_env = getenv( psz_name );
193     if( psz_env )
194     {
195         psz_env = strchr( psz_env, '=' );
196         if( psz_env )
197         {
198             return( atoi( psz_env + 1) );
199         }
200     }   
201     
202     return( i_default );
203 }
204
205 /*******************************************************************************
206  * main_GetPszVariable: get the string value of an environment variable
207  *******************************************************************************
208  * This function is used to read some default parameters in modules.
209  *******************************************************************************/
210 char * main_GetPszVariable( char *psz_name, char *psz_default )
211 {
212     char *psz_env;
213
214     psz_env = getenv( psz_name );
215     if( psz_env )
216     {
217         psz_env = strchr( psz_env, '=' );
218         if( psz_env )
219         {
220             return( psz_env + 1 );
221         }
222     }
223
224     return( psz_default );    
225 }
226
227 /* following functions are local */
228
229 /*******************************************************************************
230  * SetDefaultConfiguration: set default options
231  *******************************************************************************
232  * This function is called by GetConfiguration before command line is parsed.
233  * It sets all the default values required later by the program. At this stage,
234  * most structure are not yet allocated, so initialization must be done using
235  * environment.
236  *******************************************************************************/
237 static void SetDefaultConfiguration( void )
238 {
239     /*
240      * All features are activated by default
241      */
242     p_main->b_audio  = 1;
243     p_main->b_video  = 1;
244     p_main->b_vlans  = 1;
245
246     /*
247      * Audio output thread configuration 
248      */
249
250     // ?? initialization using structures is no more available, use putenv/getenv
251     // instead.
252
253    
254
255     /*
256      * Video output thread configuration
257      */
258     //    p_data->vout_cfg.i_properties =         0;
259
260     /* VLAN management */
261     /*???    p_data->cfg.b_vlans =                   0;    
262     p_data->cfg.psz_input_vlan_server =     VLAN_DEFAULT_SERVER;
263     p_data->cfg.i_input_vlan_server_port =  VLAN_DEFAULT_SERVER_PORT;    
264     */
265 }
266
267 /*******************************************************************************
268  * GetConfiguration: parse command line
269  *******************************************************************************
270  * Parse command line and configuration file for configuration. If the inline
271  * help is requested, the function Usage() is called and the function returns
272  * -1 (causing main() to exit). The messages interface is initialized at this 
273  * stage, but most structures are not allocated, so only environment should
274  * be used.
275  *******************************************************************************/
276 static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
277 {
278     int c, i_opt;
279
280     /* Set default configuration and copy arguments */
281     p_main->i_argc    = i_argc;
282     p_main->ppsz_argv = ppsz_argv;
283     p_main->ppsz_env  = ppsz_env;    
284     SetDefaultConfiguration();
285
286     /* Parse command line options */
287     opterr = 0;
288     while( ( c = getopt_long( i_argc, ppsz_argv, psz_shortopts, longopts, 0 ) ) != EOF )
289     {
290         switch( c )
291         {
292         /* General/common options */   
293         case 'h':                                                /* -h, --help */
294             Usage();
295             return( -1 );
296             break;
297
298         /* Audio options */
299         case OPT_NOAUDIO:                                        /* --noaudio */
300             p_main->b_audio = 0;
301             break;
302         case OPT_STEREO:                                          /* --stereo */            
303             // ?? should be replaced by a putenv
304             //p_main->p_aout->dsp.b_stereo = 1;
305             break;
306         case OPT_MONO:                                              /* --mono */
307             // ?? should be replaced by a putenv
308             //p_main->p_aout->dsp.b_stereo = 0;
309             break;
310
311         /* Video options */
312         case OPT_NOVIDEO:                                         /* --novideo */
313             p_main->b_video = 0;
314             break;       
315
316         /* VLAN management options */
317         case OPT_NOVLANS:                                         /* --novlans */
318             p_main->b_vlans = 0;
319             break;      
320             
321         /* Internal error: unknown option */
322         case '?':                          
323         default:
324             intf_ErrMsg("intf error: unknown option '%s'\n", ppsz_argv[optind - 1]);
325             return( EINVAL );
326             break;
327         }
328     }
329
330     /* Parse command line parameters - no check is made for these options */
331     for( i_opt = optind; i_opt < i_argc; i_opt++ )
332     {
333         putenv( ppsz_argv[ i_opt ] );
334     }
335     return( 0 );
336 }
337
338 /*******************************************************************************
339  * Usage: print program usage
340  *******************************************************************************
341  * Print a short inline help. Message interface is initialized at this stage.
342  *******************************************************************************/
343 static void Usage( void )
344 {
345     intf_Msg(COPYRIGHT_MESSAGE);
346     /* Usage */
347     intf_Msg("usage: vlc [options...] [parameters]\n" \
348              "  parameters can be passed using environment variables\n" \
349              "  example: vlan_server=vlan-server.via.ecp.fr:1234\n" \
350              );
351
352     /* Options */
353     intf_Msg("Options:" \
354              "  -h, --help                      print usage\n" \
355              "  --noaudio                       disable audio\n" \
356              "  --stereo                        enable stereo\n" \
357              "  --mono                          disable stereo\n"
358              "  --novideo                       disable video\n" \
359              "  --novlans                       disable vlans\n" \
360              );
361
362     /* Interface parameters */
363     intf_Msg("Interface parameters:\n" \
364              "  " INTF_INIT_SCRIPT_VAR "=<filename>             initialization script\n" \
365              );
366
367     /* Audio parameters */
368     intf_Msg("Audio parameters:\n" \
369              "  " AOUT_DSP_VAR "=<filename>              dsp device path\n" \
370              "  " AOUT_STEREO_VAR "={1|0}                stereo or mono output\n" \
371              "  " AOUT_RATE_VAR "=<rate>                 output rate\n" \
372              );
373
374     /* Video parameters */
375     intf_Msg("Video parameters:\n" \
376              ); 
377
378     /* Vlan parameters */
379     intf_Msg("VLANs (Virtual Local Aera Networks) parameters:\n" \
380              "  vlan_server=<host>[:<port>]     VLANs server address and port\n" \
381              );
382 }
383
384 /*******************************************************************************
385  * InitSignalHandler: system signal handler initialization
386  *******************************************************************************
387  * Set the signal handlers. SIGTERM is not intercepted, because we need at
388  * at least a method to kill the program when all other methods failed, and 
389  * when we don't want to use SIGKILL.
390  *******************************************************************************/
391 static void InitSignalHandler( void )
392 {
393     /* Termination signals */
394     signal( SIGHUP,  SignalHandler );
395     signal( SIGINT,  SignalHandler );
396     signal( SIGQUIT, SignalHandler );
397 }
398
399 /*******************************************************************************
400  * SignalHandler: system signal handler
401  *******************************************************************************
402  * This function is called when a signal is received by the program. It tries to
403  * end the program in a clean way.
404  *******************************************************************************/
405 static void SignalHandler( int i_signal )
406 {
407     /* Once a signal has been trapped, the termination sequence will be armed and 
408      * following signals will be ignored to avoid sending messages to an interface
409      * having been destroyed */
410     signal( SIGHUP,  SIG_IGN );
411     signal( SIGINT,  SIG_IGN );
412     signal( SIGQUIT, SIG_IGN );
413
414     /* Acknowledge the signal received */
415     intf_ErrMsgImm("intf: signal %d received\n", i_signal );
416
417     /* Try to terminate everything - this is done by requesting the end of the 
418      * interface thread */
419     p_main->p_intf->b_die = 1;
420 }
421
422
423