]> git.sesse.net Git - vlc/blob - src/interface/main.c
. autod�tection des plugins
[vlc] / src / interface / main.c
1 /*****************************************************************************
2  * main.c: main vlc source
3  * Includes the main() function for vlc. Parses command line, start interface
4  * and spawn threads.
5  *****************************************************************************
6  * Copyright (C) 1998, 1999, 2000 VideoLAN
7  *
8  * Authors:
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include "defs.h"
29
30 #include <signal.h>                               /* SIGHUP, SIGINT, SIGKILL */
31 #include <getopt.h>                                              /* getopt() */
32 #include <stdio.h>                                              /* sprintf() */
33
34 #include <errno.h>                                                 /* ENOMEM */
35 #include <stdlib.h>                                  /* getenv(), strtol(),  */
36 #include <string.h>                                            /* strerror() */
37
38 #include "config.h"
39 #include "common.h"
40 #include "threads.h"
41 #include "mtime.h"
42 #include "tests.h"                                              /* TestMMX() */
43 #include "plugins.h"
44 #include "playlist.h"
45 #include "input_vlan.h"
46 #include "input_ps.h"
47
48 #include "intf_msg.h"
49 #include "interface.h"
50
51 #include "audio_output.h"
52
53 #ifdef SYS_BEOS
54 #include "beos_specific.h"
55 #endif
56
57 #include "main.h"
58
59 /*****************************************************************************
60  * Command line options constants. If something is changed here, be sure that
61  * GetConfiguration and Usage are also changed.
62  *****************************************************************************/
63
64 /* Long options return values - note that values corresponding to short options
65  * chars, and in general any regular char, should be avoided */
66 #define OPT_NOAUDIO             150
67 #define OPT_AOUT                151
68 #define OPT_STEREO              152
69 #define OPT_MONO                153
70
71 #define OPT_NOVIDEO             160
72 #define OPT_VOUT                161
73 #define OPT_DISPLAY             162
74 #define OPT_WIDTH               163
75 #define OPT_HEIGHT              164
76 #define OPT_COLOR               165
77 #define OPT_YUV                 166
78
79 #define OPT_NOVLANS             170
80 #define OPT_SERVER              171
81 #define OPT_PORT                172
82
83 /* Usage fashion */
84 #define USAGE                     0
85 #define SHORT_HELP                1
86 #define LONG_HELP                 2
87
88 /* Long options */
89 static const struct option longopts[] =
90 {
91     /*  name,               has_arg,    flag,   val */
92
93     /* General/common options */
94     {   "help",             0,          0,      'h' },
95     {   "longhelp",         0,          0,      'H' },
96     {   "version",          0,          0,      'v' },
97
98     /* Audio options */
99     {   "noaudio",          0,          0,      OPT_NOAUDIO },
100     {   "aout",             1,          0,      OPT_AOUT },
101     {   "stereo",           0,          0,      OPT_STEREO },
102     {   "mono",             0,          0,      OPT_MONO },
103
104     /* Video options */
105     {   "novideo",          0,          0,      OPT_NOVIDEO },
106     {   "vout",             1,          0,      OPT_VOUT },
107     {   "display",          1,          0,      OPT_DISPLAY },
108     {   "width",            1,          0,      OPT_WIDTH },
109     {   "height",           1,          0,      OPT_HEIGHT },
110     {   "grayscale",        0,          0,      'g' },
111     {   "color",            0,          0,      OPT_COLOR },
112     {   "yuv",              1,          0,      OPT_YUV },
113
114     /* DVD options */
115     {   "dvdaudio",         1,          0,      'a' },
116     {   "dvdchannel",       1,          0,      'c' },
117     {   "dvdsubtitle",      1,          0,      's' },
118     
119     /* Input options */
120     {   "novlans",          0,          0,      OPT_NOVLANS },
121     {   "server",           1,          0,      OPT_SERVER },
122     {   "port",             1,          0,      OPT_PORT },
123
124     {   0,                  0,          0,      0 }
125 };
126
127 /* Short options */
128 static const char *psz_shortopts = "hHvga:s:c:";
129
130 /*****************************************************************************
131  * Global variable program_data - this is the one and only, see main.h
132  *****************************************************************************/
133 main_t *p_main;
134
135 /*****************************************************************************
136  * Local prototypes
137  *****************************************************************************/
138 static void SetDefaultConfiguration ( void );
139 static int  GetConfiguration        ( int i_argc, char *ppsz_argv[],
140                                       char *ppsz_env[] );
141 static void Usage                   ( int i_fashion );
142 static void Version                 ( void );
143
144 static void InitSignalHandler       ( void );
145 static void SignalHandler           ( int i_signal );
146 #ifdef HAVE_MMX
147 static int  TestMMX                 ( void );
148 #endif
149
150 /*****************************************************************************
151  * main: parse command line, start interface and spawn threads
152  *****************************************************************************
153  * Steps during program execution are:
154  *      -configuration parsing and messages interface initialization
155  *      -opening of audio output device and some global modules
156  *      -execution of interface, which exit on error or on user request
157  *      -closing of audio output device and some global modules
158  * On error, the spawned threads are canceled, and the open devices closed.
159  *****************************************************************************/
160 int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
161 {
162     main_t  main_data;                      /* root of all data - see main.h */
163
164     p_main = &main_data;                       /* set up the global variable */
165
166     /*
167      * System specific initialization code
168      */
169 #ifdef SYS_BEOS
170     beos_Create();
171 #endif
172
173     /*
174      * Test if our code is likely to run on this CPU 
175      */
176 #ifdef HAVE_MMX
177     if( !TestMMX() )
178     {
179         fprintf( stderr, "Sorry, this program needs an MMX processor. "
180                          "Please run the non-MMX version.\n" );
181         return( 1 );
182     }
183 #endif
184
185     /*
186      * Initialize messages interface
187      */
188     p_main->p_msg = intf_MsgCreate();
189     if( !p_main->p_msg )                         /* start messages interface */
190     {
191         fprintf( stderr, "error: can't initialize messages interface (%s)\n",
192                 strerror(errno) );
193         return( errno );
194     }
195
196     /*
197      * Read configuration
198      */
199     if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )  /* parse cmd line */
200     {
201         intf_MsgDestroy();
202         return( errno );
203     }
204
205     /*
206      * Initialize playlist and get commandline files
207      */
208     p_main->p_playlist = playlist_Create( );
209     if( !p_main->p_playlist )
210     {
211         intf_Msg( "Playlist initialization failed\n" );
212         intf_MsgDestroy();
213         return( errno );
214     }
215     playlist_Init( p_main->p_playlist, optind );
216
217     /*
218      * Initialize plugin bank
219      */
220     p_main->p_bank = bank_Create( );
221     if( !p_main->p_bank )
222     {
223         intf_Msg( "Plugin bank initialization failed\n" );
224         playlist_Destroy( p_main->p_playlist );
225         intf_MsgDestroy();
226         return( errno );
227     }
228     bank_Init( p_main->p_bank );
229
230     /*
231      * Initialize shared resources and libraries
232      */
233     if( p_main->b_vlans && input_VlanCreate() )
234     {
235         /* On error during vlans initialization, switch off vlans */
236         intf_Msg( "Virtual LANs initialization failed : "
237                   "vlans management is deactivated\n" );
238         p_main->b_vlans = 0;
239     }
240
241     /*
242      * Open audio device and start aout thread
243      */
244     if( p_main->b_audio )
245     {
246         p_main->p_aout = aout_CreateThread( NULL );
247         if( p_main->p_aout == NULL )
248         {
249             /* On error during audio initialization, switch off audio */
250             intf_Msg( "Audio initialization failed : audio is deactivated\n" );
251             p_main->b_audio = 0;
252         }
253     }
254
255     /*
256      * Run interface
257      */
258     p_main->p_intf = intf_Create();
259     if( p_main->p_intf != NULL )
260     {
261         InitSignalHandler();             /* prepare signals for interception */
262
263         /*
264          * This is the main loop
265          */
266         intf_Run( p_main->p_intf );
267
268         intf_Destroy( p_main->p_intf );
269     }
270
271     /*
272      * Close audio device
273      */
274     if( p_main->b_audio )
275     {
276         aout_DestroyThread( p_main->p_aout, NULL );
277     }
278
279     /*
280      * Free shared resources and libraries
281      */
282     if( p_main->b_vlans )
283     {
284         input_VlanDestroy();
285     }
286
287     /*
288      * Free plugin bank
289      */
290     bank_Destroy( p_main->p_bank );
291
292     /*
293      * Free playlist
294      */
295     playlist_Destroy( p_main->p_playlist );
296
297 #ifdef SYS_BEOS
298     /*
299      * System specific cleaning code
300      */
301     beos_Destroy();
302 #endif
303
304     /*
305      * Terminate messages interface and program
306      */
307     intf_Msg( "Program terminated.\n" );
308     intf_MsgDestroy();
309
310     return( 0 );
311 }
312
313 /*****************************************************************************
314  * main_GetIntVariable: get the int value of an environment variable
315  *****************************************************************************
316  * This function is used to read some default parameters in modules.
317  *****************************************************************************/
318 int main_GetIntVariable( char *psz_name, int i_default )
319 {
320     char *      psz_env;                                /* environment value */
321     char *      psz_end;                             /* end of parsing index */
322     long int    i_value;                                            /* value */
323
324     psz_env = getenv( psz_name );
325     if( psz_env )
326     {
327         i_value = strtol( psz_env, &psz_end, 0 );
328         if( (*psz_env != '\0') && (*psz_end == '\0') )
329         {
330             return( i_value );
331         }
332     }
333     return( i_default );
334 }
335
336 /*****************************************************************************
337  * main_GetPszVariable: get the string value of an environment variable
338  *****************************************************************************
339  * This function is used to read some default parameters in modules.
340  *****************************************************************************/
341 char * main_GetPszVariable( char *psz_name, char *psz_default )
342 {
343     char *psz_env;
344
345     psz_env = getenv( psz_name );
346     if( psz_env )
347     {
348         return( psz_env );
349     }
350     return( psz_default );
351 }
352
353 /*****************************************************************************
354  * main_PutPszVariable: set the string value of an environment variable
355  *****************************************************************************
356  * This function is used to set some default parameters in modules. The use of
357  * this function will cause some memory leak: since some systems use the pointer
358  * passed to putenv to store the environment string, it can't be freed.
359  *****************************************************************************/
360 void main_PutPszVariable( char *psz_name, char *psz_value )
361 {
362     char *psz_env;
363
364     psz_env = malloc( strlen(psz_name) + strlen(psz_value) + 2 );
365     if( psz_env == NULL )
366     {
367         intf_ErrMsg( "error: %s\n", strerror(ENOMEM) );
368     }
369     else
370     {
371         sprintf( psz_env, "%s=%s", psz_name, psz_value );
372         if( putenv( psz_env ) )
373         {
374             intf_ErrMsg( "error: %s\n", strerror(errno) );
375         }
376     }
377 }
378
379 /*****************************************************************************
380  * main_PutIntVariable: set the integer value of an environment variable
381  *****************************************************************************
382  * This function is used to set some default parameters in modules. The use of
383  * this function will cause some memory leak: since some systems use the pointer
384  * passed to putenv to store the environment string, it can't be freed.
385  *****************************************************************************/
386 void main_PutIntVariable( char *psz_name, int i_value )
387 {
388     char psz_value[ 256 ];                               /* buffer for value */
389
390     sprintf( psz_value, "%d", i_value );
391     main_PutPszVariable( psz_name, psz_value );
392 }
393
394 /* following functions are local */
395
396 /*****************************************************************************
397  * SetDefaultConfiguration: set default options
398  *****************************************************************************
399  * This function is called by GetConfiguration before command line is parsed.
400  * It sets all the default values required later by the program. At this stage,
401  * most structure are not yet allocated, so initialization must be done using
402  * environment.
403  *****************************************************************************/
404 static void SetDefaultConfiguration( void )
405 {
406     /*
407      * All features are activated by default
408      */
409     p_main->b_audio  = 1;
410     p_main->b_video  = 1;
411     p_main->b_vlans  = 1;
412 }
413
414 /*****************************************************************************
415  * GetConfiguration: parse command line
416  *****************************************************************************
417  * Parse command line and configuration file for configuration. If the inline
418  * help is requested, the function Usage() is called and the function returns
419  * -1 (causing main() to exit). The messages interface is initialized at this
420  * stage, but most structures are not allocated, so only environment should
421  * be used.
422  *****************************************************************************/
423 static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
424 {
425     int c, i_opt;
426     char * p_pointer;
427
428     /* Set default configuration and copy arguments */
429     p_main->i_argc    = i_argc;
430     p_main->ppsz_argv = ppsz_argv;
431     p_main->ppsz_env  = ppsz_env;
432     SetDefaultConfiguration();
433
434     intf_MsgImm( COPYRIGHT_MESSAGE "\n" );
435
436     /* Get the executable name */
437     p_main->psz_arg0 = p_pointer = ppsz_argv[ 0 ];
438     while( *p_pointer )
439     {
440         if( *p_pointer == '/' )
441         {
442             p_main->psz_arg0 = ++p_pointer;
443         }
444         else
445         {
446             ++p_pointer;
447         }
448     }
449
450     /* Parse command line options */
451     opterr = 0;
452     while( ( c = getopt_long( i_argc, ppsz_argv, psz_shortopts, longopts, 0 ) ) != EOF )
453     {
454         switch( c )
455         {
456         /* General/common options */
457         case 'h':                                              /* -h, --help */
458             Usage( SHORT_HELP );
459             return( -1 );
460             break;
461         case 'H':                                          /* -H, --longhelp */
462             Usage( LONG_HELP );
463             return( -1 );
464             break;
465         case 'v':                                           /* -v, --version */
466             Version();
467             return( -1 );
468             break;
469
470         /* Audio options */
471         case OPT_NOAUDIO:                                       /* --noaudio */
472             p_main->b_audio = 0;
473             break;
474         case OPT_AOUT:                                             /* --aout */
475             main_PutPszVariable( AOUT_METHOD_VAR, optarg );
476             break;
477         case OPT_STEREO:                                         /* --stereo */
478             main_PutIntVariable( AOUT_STEREO_VAR, 1 );
479             break;
480         case OPT_MONO:                                             /* --mono */
481             main_PutIntVariable( AOUT_STEREO_VAR, 0 );
482             break;
483
484         /* Video options */
485         case OPT_NOVIDEO:                                       /* --novideo */
486             p_main->b_video = 0;
487             break;
488         case OPT_VOUT:                                             /* --vout */
489             main_PutPszVariable( VOUT_METHOD_VAR, optarg );
490             break;
491         case OPT_DISPLAY:                                       /* --display */
492             main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
493             break;
494         case OPT_WIDTH:                                           /* --width */
495             main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
496             break;
497         case OPT_HEIGHT:                                         /* --height */
498             main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );
499             break;
500
501         case 'g':                                         /* -g, --grayscale */
502             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
503             break;
504         case OPT_COLOR:                                           /* --color */
505             main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
506             break;
507         case OPT_YUV:                                               /* --yuv */
508             main_PutPszVariable( YUV_METHOD_VAR, optarg );
509             break;
510
511         /* DVD options */
512         case 'a':
513             if ( ! strcmp(optarg, "mpeg") )
514                 main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_MPEG );
515             else if ( ! strcmp(optarg, "lpcm") )
516                 main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_LPCM );
517             else if ( ! strcmp(optarg, "off") )
518                 main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_NOAUDIO );
519             else
520                 main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_AC3 );
521             break;
522         case 'c':
523             main_PutIntVariable( INPUT_DVD_CHANNEL_VAR, atoi(optarg) );
524             break;
525         case 's':
526             main_PutIntVariable( INPUT_DVD_SUBTITLE_VAR, atoi(optarg) );
527             break;
528
529         /* Input options */
530         case OPT_NOVLANS:                                       /* --novlans */
531             p_main->b_vlans = 0;
532             break;
533         case OPT_SERVER:                                         /* --server */
534             main_PutPszVariable( INPUT_SERVER_VAR, optarg );
535             break;
536         case OPT_PORT:                                             /* --port */
537             main_PutPszVariable( INPUT_PORT_VAR, optarg );
538             break;
539
540         /* Internal error: unknown option */
541         case '?':
542         default:
543             intf_ErrMsg( "intf error: unknown option `%s'\n", ppsz_argv[optind - 1] );
544             Usage( USAGE );
545             return( EINVAL );
546             break;
547         }
548     }
549
550     /* Parse command line parameters - no check is made for these options */
551     for( i_opt = optind; i_opt < i_argc; i_opt++ )
552     {
553         putenv( ppsz_argv[ i_opt ] );
554     }
555     return( 0 );
556 }
557
558 /*****************************************************************************
559  * Usage: print program usage
560  *****************************************************************************
561  * Print a short inline help. Message interface is initialized at this stage.
562  *****************************************************************************/
563 static void Usage( int i_fashion )
564 {
565     /* Usage */
566     intf_Msg( "Usage: %s [options] [parameters] [file]...\n",
567               p_main->psz_arg0 );
568
569     if( i_fashion == USAGE )
570     {
571         intf_Msg( "Try `%s --help' for more information.\n",
572                   p_main->psz_arg0 );
573         return;
574     }
575
576     /* Options */
577     intf_Msg( "\n"
578               "Options:\n"
579               "      --noaudio                  \tdisable audio\n"
580               "      --aout <plugin>            \taudio output method\n"
581               "      --stereo, --mono           \tstereo/mono audio\n"
582               "\n"
583               "      --novideo                  \tdisable video\n"
584               "      --vout <plugin>            \tvideo output method\n"
585               "      --display <display>        \tdisplay string\n"
586               "      --width <w>, --height <h>  \tdisplay dimensions\n"
587               "  -g, --grayscale                \tgrayscale output\n"
588               "      --color                    \tcolor output\n"
589               "\n"
590               "  -a, --dvdaudio                 \tchoose DVD audio type\n"
591               "  -c, --dvdchannel               \tchoose DVD audio channel\n"
592               "  -s, --dvdsubtitle              \tchoose DVD subtitle channel\n"
593               "\n"
594               "      --novlans                  \tdisable vlans\n"
595               "      --server <host>            \tvideo server address\n"
596               "      --port <port>              \tvideo server port\n"
597               "\n"
598               "  -h, --help                     \tprint help and exit\n"
599               "  -H, --longhelp                 \tprint long help and exit\n"
600               "  -v, --version                  \toutput version information and exit\n" );
601
602     if( i_fashion == SHORT_HELP )
603         return;
604
605     /* Interface parameters */
606     intf_Msg( "\n"
607               "Interface parameters:\n"
608               "  " INTF_INIT_SCRIPT_VAR "=<filename>             \tinitialization script\n"
609               "  " INTF_CHANNELS_VAR "=<filename>            \tchannels list\n" );
610
611     /* Audio parameters */
612     intf_Msg( "\n"
613               "Audio parameters:\n"
614               "  " AOUT_METHOD_VAR "=<method name>        \taudio method\n"
615               "  " AOUT_DSP_VAR "=<filename>              \tdsp device path\n"
616               "  " AOUT_STEREO_VAR "={1|0}                \tstereo or mono output\n"
617               "  " AOUT_RATE_VAR "=<rate>             \toutput rate\n" );
618
619     /* Video parameters */
620     intf_Msg( "\n"
621               "Video parameters:\n"
622               "  " VOUT_METHOD_VAR "=<method name>        \tdisplay method\n"
623               "  " VOUT_DISPLAY_VAR "=<display name>      \tdisplay used\n"
624               "  " VOUT_WIDTH_VAR "=<width>               \tdisplay width\n"
625               "  " VOUT_HEIGHT_VAR "=<height>             \tdislay height\n"
626               "  " VOUT_FB_DEV_VAR "=<filename>           \tframebuffer device path\n"
627               "  " VOUT_GRAYSCALE_VAR "={1|0}             \tgrayscale or color output\n" );
628
629     /* DVD parameters */
630     intf_Msg( "\n"
631               "DVD parameters:\n"
632               "  " INPUT_DVD_AUDIO_VAR "={ac3|lpcm|mpeg|off} \taudio type\n"
633               "  " INPUT_DVD_CHANNEL_VAR "=[0-15]            \taudio channel\n"
634               "  " INPUT_DVD_SUBTITLE_VAR "=[0-31]           \tsubtitle channel\n" );
635
636     /* Input parameters */
637     intf_Msg( "\n"
638               "Input parameters:\n"
639               "  " INPUT_SERVER_VAR "=<hostname>          \tvideo server\n"
640               "  " INPUT_PORT_VAR "=<port>            \tvideo server port\n"
641               "  " INPUT_IFACE_VAR "=<interface>          \tnetwork interface\n"
642               "  " INPUT_VLAN_SERVER_VAR "=<hostname>     \tvlan server\n"
643               "  " INPUT_VLAN_PORT_VAR "=<port>           \tvlan server port\n" );
644 }
645
646 /*****************************************************************************
647  * Version: print complete program version
648  *****************************************************************************
649  * Print complete program version and build number.
650  *****************************************************************************/
651 static void Version( void )
652 {
653     intf_Msg( VERSION_MESSAGE
654               "This program comes with NO WARRANTY, to the extent permitted by law.\n"
655               "You may redistribute it under the terms of the GNU General Public License;\n"
656               "see the file named COPYING for details.\n"
657               "Written by the VideoLAN team at Ecole Centrale, Paris.\n" );
658
659 }
660
661 /*****************************************************************************
662  * InitSignalHandler: system signal handler initialization
663  *****************************************************************************
664  * Set the signal handlers. SIGTERM is not intercepted, because we need at
665  * at least a method to kill the program when all other methods failed, and
666  * when we don't want to use SIGKILL.
667  *****************************************************************************/
668 static void InitSignalHandler( void )
669 {
670     /* Termination signals */
671     signal( SIGHUP,  SignalHandler );
672     signal( SIGINT,  SignalHandler );
673     signal( SIGQUIT, SignalHandler );
674 }
675
676 /*****************************************************************************
677  * SignalHandler: system signal handler
678  *****************************************************************************
679  * This function is called when a signal is received by the program. It tries to
680  * end the program in a clean way.
681  *****************************************************************************/
682 static void SignalHandler( int i_signal )
683 {
684     /* Once a signal has been trapped, the termination sequence will be armed and
685      * following signals will be ignored to avoid sending messages to an interface
686      * having been destroyed */
687     signal( SIGHUP,  SIG_IGN );
688     signal( SIGINT,  SIG_IGN );
689     signal( SIGQUIT, SIG_IGN );
690
691     /* Acknowledge the signal received */
692     intf_ErrMsgImm("intf: signal %d received\n", i_signal );
693
694     /* Try to terminate everything - this is done by requesting the end of the
695      * interface thread */
696     p_main->p_intf->b_die = 1;
697 }
698