main.c 21.3 KB
Newer Older
1
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
2
3
 * main.c: main vlc source
 * (c)1998 VideoLAN
4
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
5
6
 * Includes the main() function for vlc. Parses command line, start interface
 * and spawn threads.
7
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
8

9
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
10
 * Preamble
11
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
12
13
14
15
16
17
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Vincent Seguin's avatar
Vincent Seguin committed
18

19
#include <sys/soundcard.h>                                 /* audio_output.h */
Michel Kaempf's avatar
Michel Kaempf committed
20
21
22
23

#include "config.h"
#include "common.h"
#include "mtime.h"
24
#include "vlc_thread.h"
Michel Kaempf's avatar
Michel Kaempf committed
25
#include "input_vlan.h"
Vincent Seguin's avatar
Vincent Seguin committed
26
#include "intf_msg.h"
Michel Kaempf's avatar
Michel Kaempf committed
27
#include "interface.h"
Vincent Seguin's avatar
Vincent Seguin committed
28
29
#include "audio_output.h"
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
30

31
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
32
33
 * Command line options constants. If something is changed here, be sure that
 * GetConfiguration and Usage are also changed.
34
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
35
36
37
38
39
40
41
42

/* Long options return values - note that values corresponding to short options
 * chars, and in general any regular char, should be avoided */
#define OPT_NOAUDIO             150
#define OPT_STEREO              151
#define OPT_MONO                152

#define OPT_NOVIDEO             160
43
44
45
46
#define OPT_DISPLAY             161
#define OPT_WIDTH               162
#define OPT_HEIGHT              163
#define OPT_COLOR               164
Michel Kaempf's avatar
Michel Kaempf committed
47
48

#define OPT_NOVLANS             170
49
50
#define OPT_SERVER              171
#define OPT_PORT                172
51

Michel Kaempf's avatar
Michel Kaempf committed
52
53
/* Long options */
static const struct option longopts[] =
54
55
{
    /*  name,               has_arg,    flag,   val */
Michel Kaempf's avatar
Michel Kaempf committed
56
57

    /* General/common options */
58
59
    {   "help",             0,          0,      'h' },
    {   "version",          0,          0,      'v' },
Michel Kaempf's avatar
Michel Kaempf committed
60
61

    /* Audio options */
62
    {   "noaudio",          0,          0,      OPT_NOAUDIO },
Michel Kaempf's avatar
Michel Kaempf committed
63
    {   "stereo",           0,          0,      OPT_STEREO },
64
    {   "mono",             0,          0,      OPT_MONO },
Michel Kaempf's avatar
Michel Kaempf committed
65
66

    /* Video options */
67
68
    {   "novideo",          0,          0,      OPT_NOVIDEO },
    {   "display",          1,          0,      OPT_DISPLAY },
69
    {   "width",            1,          0,      OPT_WIDTH },
70
71
72
    {   "height",           1,          0,      OPT_HEIGHT },
    {   "grayscale",        0,          0,      'g' },
    {   "color",            0,          0,      OPT_COLOR },
Michel Kaempf's avatar
Michel Kaempf committed
73

74
    /* Input options */
Michel Kaempf's avatar
Michel Kaempf committed
75
    {   "novlans",          0,          0,      OPT_NOVLANS },
76
77
    {   "server",           1,          0,      OPT_SERVER },
    {   "port",             1,          0,      OPT_PORT },
Michel Kaempf's avatar
Michel Kaempf committed
78
79
80
81
82

    {   0,                  0,          0,      0 }
};

/* Short options */
Vincent Seguin's avatar
Vincent Seguin committed
83
static const char *psz_shortopts = "hvg";
Michel Kaempf's avatar
Michel Kaempf committed
84

85
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
86
 * Global variable program_data - this is the one and only, see main.h
87
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
88
main_t *p_main;
Michel Kaempf's avatar
Michel Kaempf committed
89

90
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
91
 * Local prototypes
92
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
93
94
static void SetDefaultConfiguration ( void );
static int  GetConfiguration        ( int i_argc, char *ppsz_argv[], char *ppsz_env[] );
Michel Kaempf's avatar
Michel Kaempf committed
95
static void Usage                   ( void );
Vincent Seguin's avatar
Vincent Seguin committed
96
static void Version                 ( void );
Vincent Seguin's avatar
Vincent Seguin committed
97

Michel Kaempf's avatar
Michel Kaempf committed
98
99
static void InitSignalHandler       ( void );
static void SignalHandler           ( int i_signal );
100
static int  TestMMX                 ( void );
Michel Kaempf's avatar
Michel Kaempf committed
101

102
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
103
 * main: parse command line, start interface and spawn threads
104
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
105
106
 * Steps during program execution are:
 *      -configuration parsing and messages interface initialization
Vincent Seguin's avatar
Vincent Seguin committed
107
 *      -openning of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
108
 *      -execution of interface, which exit on error or on user request
Vincent Seguin's avatar
Vincent Seguin committed
109
 *      -closing of audio output device and some global modules
Michel Kaempf's avatar
Michel Kaempf committed
110
 * On error, the spawned threads are cancelled, and the openned devices closed.
111
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
112
113
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
114
115
    main_t  main_data;                      /* root of all data - see main.h */
    p_main = &main_data;                       /* set up the global variable */
Vincent Seguin's avatar
Vincent Seguin committed
116

Michel Kaempf's avatar
Michel Kaempf committed
117
118
    /*
     * Read configuration, initialize messages interface and set up program
119
     */
120
121
122
123
124
125
126
#ifdef HAVE_MMX
    if( !TestMMX() )
    {
        fprintf( stderr, "Sorry, this program needs an MMX processor. Please run the non-MMX version.\n" );
	return(0);
    }
#endif
Vincent Seguin's avatar
Vincent Seguin committed
127
    p_main->p_msg = intf_MsgCreate();
128
    if( !p_main->p_msg )                         /* start messages interface */
Michel Kaempf's avatar
Michel Kaempf committed
129
    {
Vincent Seguin's avatar
Vincent Seguin committed
130
        fprintf(stderr, "critical error: can't initialize messages interface (%s)\n",
Michel Kaempf's avatar
Michel Kaempf committed
131
132
133
                strerror(errno));
        return(errno);
    }
Vincent Seguin's avatar
Vincent Seguin committed
134
    if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )/* parse command line */
Michel Kaempf's avatar
Michel Kaempf committed
135
    {
Vincent Seguin's avatar
Vincent Seguin committed
136
        intf_MsgDestroy();
Michel Kaempf's avatar
Michel Kaempf committed
137
138
        return(errno);
    }
139
    intf_MsgImm( COPYRIGHT_MESSAGE "\n" );          /* print welcome message */
Michel Kaempf's avatar
Michel Kaempf committed
140
141
142
143

    /*
     * Initialize shared resources and libraries
     */
Vincent Seguin's avatar
Vincent Seguin committed
144
    if( main_data.b_vlans && input_VlanCreate() )
Michel Kaempf's avatar
Michel Kaempf committed
145
146
    {
        /* On error during vlans initialization, switch of vlans */
Vincent Seguin's avatar
Vincent Seguin committed
147
148
        intf_Msg("Virtual LANs initialization failed : vlans management is desactivated\n");
        main_data.b_vlans = 0;
Michel Kaempf's avatar
Michel Kaempf committed
149
    }
150

Michel Kaempf's avatar
Michel Kaempf committed
151
    /*
Vincent Seguin's avatar
Vincent Seguin committed
152
     * Open audio device and start aout thread
Michel Kaempf's avatar
Michel Kaempf committed
153
     */
Vincent Seguin's avatar
Vincent Seguin committed
154
155
156
157
158
159
160
161
162
    if( main_data.b_audio )
    {
        main_data.p_aout = aout_CreateThread( NULL );
	if( main_data.p_aout == NULL )
	{
	    /* On error during audio initialization, switch of audio */
            intf_Msg("Audio initialization failed : audio is desactivated\n");
            main_data.b_audio = 0;
	}
Michel Kaempf's avatar
Michel Kaempf committed
163
    }
164

Michel Kaempf's avatar
Michel Kaempf committed
165
166
167
    /*
     * Run interface
     */
Vincent Seguin's avatar
Vincent Seguin committed
168
169
170
171
172
173
174
    main_data.p_intf = intf_Create();
    if( main_data.p_intf != NULL )
    {
	InitSignalHandler();               /* prepare signals for interception */
 	intf_Run( main_data.p_intf );
	intf_Destroy( main_data.p_intf );
    }
Michel Kaempf's avatar
Michel Kaempf committed
175

Michel Kaempf's avatar
Michel Kaempf committed
176
    /*
Michel Kaempf's avatar
Michel Kaempf committed
177
178
     * Close audio device
     */
Vincent Seguin's avatar
Vincent Seguin committed
179
    if( main_data.b_audio )
Michel Kaempf's avatar
Michel Kaempf committed
180
    {
Vincent Seguin's avatar
Vincent Seguin committed
181
        aout_DestroyThread( main_data.p_aout, NULL );
Michel Kaempf's avatar
Michel Kaempf committed
182
    }
Michel Kaempf's avatar
Michel Kaempf committed
183
184
185
186

    /*
     * Free shared resources and libraries
     */
Vincent Seguin's avatar
Vincent Seguin committed
187
    if( main_data.b_vlans )
188
189
190
    {
        input_VlanDestroy();
    }
Michel Kaempf's avatar
Michel Kaempf committed
191
192
193
194

    /*
     * Terminate messages interface and program
     */
Vincent Seguin's avatar
Vincent Seguin committed
195
196
    intf_Msg( "Program terminated.\n" );
    intf_MsgDestroy();
Michel Kaempf's avatar
Michel Kaempf committed
197
198
199
    return( 0 );
}

200
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
201
 * main_GetIntVariable: get the int value of an environment variable
202
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
203
 * This function is used to read some default parameters in modules.
204
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
205
206
int main_GetIntVariable( char *psz_name, int i_default )
{
207
208
209
    char *      psz_env;                                /* environment value */
    char *      psz_end;                             /* end of parsing index */
    long int    i_value;                                            /* value */
Vincent Seguin's avatar
Vincent Seguin committed
210
211
212

    psz_env = getenv( psz_name );
    if( psz_env )
213
    {
214
215
216
217
        i_value = strtol( psz_env, &psz_end, 0 );
        if( (*psz_env != '\0') && (*psz_end == '\0') )
        {
            return( i_value );
218
        }
Vincent Seguin's avatar
Vincent Seguin committed
219
220
221
222
    }	
    return( i_default );
}

223
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
224
 * main_GetPszVariable: get the string value of an environment variable
225
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
226
 * This function is used to read some default parameters in modules.
227
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
228
229
230
231
232
233
234
char * main_GetPszVariable( char *psz_name, char *psz_default )
{
    char *psz_env;

    psz_env = getenv( psz_name );
    if( psz_env )
    {
235
        return( psz_env );
Vincent Seguin's avatar
Vincent Seguin committed
236
    }
237
    return( psz_default );
Vincent Seguin's avatar
Vincent Seguin committed
238
239
}

240
/*****************************************************************************
241
 * main_PutPszVariable: set the string value of an environment variable
242
 *****************************************************************************
243
244
245
 * This function is used to set some default parameters in modules. The use of
 * this function will cause some memory leak: since some systems use the pointer
 * passed to putenv to store the environment string, it can't be freed.
246
 *****************************************************************************/
247
248
249
250
251
252
253
void main_PutPszVariable( char *psz_name, char *psz_value )
{
    char *psz_env;

    psz_env = malloc( strlen(psz_name) + strlen(psz_value) + 2 );
    if( psz_env == NULL )
    {
254
        intf_ErrMsg("error: %s\n", strerror(ENOMEM));
255
256
257
258
259
260
261
    }
    else
    {
        sprintf( psz_env, "%s=%s", psz_name, psz_value );
        if( putenv( psz_env ) )
        {
            intf_ErrMsg("error: %s\n", strerror(errno));
262
        }
263
264
265
    }
}

266
/*****************************************************************************
267
 * main_PutIntVariable: set the integer value of an environment variable
268
 *****************************************************************************
269
270
271
 * This function is used to set some default parameters in modules. The use of
 * this function will cause some memory leak: since some systems use the pointer
 * passed to putenv to store the environment string, it can't be freed.
272
 *****************************************************************************/
273
274
void main_PutIntVariable( char *psz_name, int i_value )
{
275
    char psz_value[ 256 ];                               /* buffer for value */
276

277
278
    sprintf(psz_value, "%d", i_value );
    main_PutPszVariable( psz_name, psz_value );
279
280
}

Michel Kaempf's avatar
Michel Kaempf committed
281
282
/* following functions are local */

283
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
284
 * SetDefaultConfiguration: set default options
285
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
286
 * This function is called by GetConfiguration before command line is parsed.
Vincent Seguin's avatar
Vincent Seguin committed
287
288
289
 * It sets all the default values required later by the program. At this stage,
 * most structure are not yet allocated, so initialization must be done using
 * environment.
290
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
291
static void SetDefaultConfiguration( void )
Michel Kaempf's avatar
Michel Kaempf committed
292
293
{
    /*
Vincent Seguin's avatar
Vincent Seguin committed
294
     * All features are activated by default
Michel Kaempf's avatar
Michel Kaempf committed
295
     */
Vincent Seguin's avatar
Vincent Seguin committed
296
297
298
    p_main->b_audio  = 1;
    p_main->b_video  = 1;
    p_main->b_vlans  = 1;
Michel Kaempf's avatar
Michel Kaempf committed
299
300
}

301
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
302
 * GetConfiguration: parse command line
303
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
304
305
 * Parse command line and configuration file for configuration. If the inline
 * help is requested, the function Usage() is called and the function returns
306
 * -1 (causing main() to exit). The messages interface is initialized at this
Vincent Seguin's avatar
Vincent Seguin committed
307
308
 * stage, but most structures are not allocated, so only environment should
 * be used.
309
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
310
static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
Michel Kaempf's avatar
Michel Kaempf committed
311
{
Vincent Seguin's avatar
Vincent Seguin committed
312
    int c, i_opt;
Michel Kaempf's avatar
Michel Kaempf committed
313
314

    /* Set default configuration and copy arguments */
Vincent Seguin's avatar
Vincent Seguin committed
315
316
    p_main->i_argc    = i_argc;
    p_main->ppsz_argv = ppsz_argv;
317
    p_main->ppsz_env  = ppsz_env;
Vincent Seguin's avatar
Vincent Seguin committed
318
    SetDefaultConfiguration();
Michel Kaempf's avatar
Michel Kaempf committed
319

Vincent Seguin's avatar
Vincent Seguin committed
320
    /* Parse command line options */
Michel Kaempf's avatar
Michel Kaempf committed
321
322
323
324
325
    opterr = 0;
    while( ( c = getopt_long( i_argc, ppsz_argv, psz_shortopts, longopts, 0 ) ) != EOF )
    {
        switch( c )
        {
326
327
        /* General/common options */
        case 'h':                                              /* -h, --help */
Michel Kaempf's avatar
Michel Kaempf committed
328
329
330
            Usage();
            return( -1 );
            break;
331
        case 'v':                                           /* -v, --version */
Vincent Seguin's avatar
Vincent Seguin committed
332
333
            Version();
            return( -1 );
334
            break;
Michel Kaempf's avatar
Michel Kaempf committed
335
336

        /* Audio options */
337
        case OPT_NOAUDIO:                                       /* --noaudio */
Vincent Seguin's avatar
Vincent Seguin committed
338
	    p_main->b_audio = 0;
Michel Kaempf's avatar
Michel Kaempf committed
339
            break;
340
        case OPT_STEREO:                                         /* --stereo */
341
            main_PutIntVariable( AOUT_STEREO_VAR, 1 );
Michel Kaempf's avatar
Michel Kaempf committed
342
            break;
343
        case OPT_MONO:                                             /* --mono */
344
            main_PutIntVariable( AOUT_STEREO_VAR, 0 );
Michel Kaempf's avatar
Michel Kaempf committed
345
346
347
            break;

        /* Video options */
348
        case OPT_NOVIDEO:                                       /* --novideo */
Vincent Seguin's avatar
Vincent Seguin committed
349
            p_main->b_video = 0;
350
351
            break;
        case OPT_DISPLAY:                                       /* --display */
352
            main_PutPszVariable( VOUT_DISPLAY_VAR, optarg );
353
354
            break;
        case OPT_WIDTH:                                           /* --width */
355
            main_PutPszVariable( VOUT_WIDTH_VAR, optarg );
356
357
358
359
360
361
            break;
        case OPT_HEIGHT:                                         /* --height */
            main_PutPszVariable( VOUT_HEIGHT_VAR, optarg );
            break;

        case 'g':                                         /* -g, --grayscale */
362
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 1 );
363
364
            break;
        case OPT_COLOR:                                           /* --color */
365
            main_PutIntVariable( VOUT_GRAYSCALE_VAR, 0 );
366
            break;
Michel Kaempf's avatar
Michel Kaempf committed
367

368
        /* Input options */
369
        case OPT_NOVLANS:                                       /* --novlans */
Vincent Seguin's avatar
Vincent Seguin committed
370
            p_main->b_vlans = 0;
371
372
            break;
        case OPT_SERVER:                                         /* --server */
373
            main_PutPszVariable( INPUT_SERVER_VAR, optarg );
374
375
            break;
        case OPT_PORT:                                             /* --port */
376
            main_PutPszVariable( INPUT_PORT_VAR, optarg );
377
378
            break;
	
Michel Kaempf's avatar
Michel Kaempf committed
379
        /* Internal error: unknown option */
380
        case '?':
Michel Kaempf's avatar
Michel Kaempf committed
381
382
383
384
385
386
387
        default:
            intf_ErrMsg("intf error: unknown option '%s'\n", ppsz_argv[optind - 1]);
            return( EINVAL );
            break;
        }
    }

Vincent Seguin's avatar
Vincent Seguin committed
388
389
390
391
392
    /* Parse command line parameters - no check is made for these options */
    for( i_opt = optind; i_opt < i_argc; i_opt++ )
    {
	putenv( ppsz_argv[ i_opt ] );
    }
Michel Kaempf's avatar
Michel Kaempf committed
393
394
395
    return( 0 );
}

396
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
397
 * Usage: print program usage
398
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
399
 * Print a short inline help. Message interface is initialized at this stage.
400
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
401
402
static void Usage( void )
{
Vincent Seguin's avatar
Vincent Seguin committed
403
404
    intf_Msg(COPYRIGHT_MESSAGE "\n");

Vincent Seguin's avatar
Vincent Seguin committed
405
    /* Usage */
406
    intf_Msg("usage: vlc [options...] [parameters]\n" );
Vincent Seguin's avatar
Vincent Seguin committed
407
408

    /* Options */
Vincent Seguin's avatar
Vincent Seguin committed
409
    intf_Msg("Options:\n" \
410
411
             "  -h, --help, -v, --version         \tprint usage or version\n" \
             "  --noaudio, --novideo              \tdisable audio/video\n" \
412
413
414
415
416
417
             "  --stereo, --mono                  \tstereo/mono audio\n" \
             "  --display <display>               \tdisplay string\n" \
             "  --width <w>, --height <h>         \tdisplay dimensions\n" \
             "  -g, --grayscale, --color          \tgrayscale/color video\n" \
             "  --novlans                         \tdisable vlans\n" \
             "  --server <host>, --port <port>    \tvideo server adress\n" \
Michel Kaempf's avatar
Michel Kaempf committed
418
419
             );

Vincent Seguin's avatar
Vincent Seguin committed
420
421
    /* Interface parameters */
    intf_Msg("Interface parameters:\n" \
422
	     "  " INTF_INIT_SCRIPT_VAR "=<filename>             \tinitialization script\n" \
423
             "  " INTF_CHANNELS_VAR "=<filename>            \tchannels list\n"\
Vincent Seguin's avatar
Vincent Seguin committed
424
425
426
427
	     );

    /* Audio parameters */
    intf_Msg("Audio parameters:\n" \
428
429
430
             "  " AOUT_DSP_VAR "=<filename>              \tdsp device path\n" \
             "  " AOUT_STEREO_VAR "={1|0}                \tstereo or mono output\n" \
             "  " AOUT_RATE_VAR "=<rate>             \toutput rate\n" \
Vincent Seguin's avatar
Vincent Seguin committed
431
432
433
434
	     );

    /* Video parameters */
    intf_Msg("Video parameters:\n" \
435
436
437
438
439
             "  " VOUT_DISPLAY_VAR "=<display name>      \tdisplay used\n" \
             "  " VOUT_WIDTH_VAR "=<width>               \tdisplay width\n" \
             "  " VOUT_HEIGHT_VAR "=<height>             \tdislay height\n" \
             "  " VOUT_FB_DEV_VAR "=<filename>           \tframebuffer device path\n" \
             "  " VOUT_GRAYSCALE_VAR "={1|0}             \tgrayscale or color output\n" \
440
	     );
Vincent Seguin's avatar
Vincent Seguin committed
441

442
443
444
445
446
447
    /* Input parameters */
    intf_Msg("Input parameters:\n" \
             "  " INPUT_SERVER_VAR "=<hostname>          \tvideo server\n" \
             "  " INPUT_PORT_VAR "=<port>            \tvideo server port\n" \
	     "  " INPUT_IFACE_VAR "=<interface>          \tnetwork interface\n" \
             "  " INPUT_VLAN_SERVER_VAR "=<hostname>     \tvlan server\n" \
448
             "  " INPUT_VLAN_PORT_VAR "=<port>           \tvlan server port\n"\
Vincent Seguin's avatar
Vincent Seguin committed
449
	     );
Michel Kaempf's avatar
Michel Kaempf committed
450
451
}

452
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
453
 * Version: print complete program version
454
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
455
 * Print complete program version and build number.
456
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
457
458
459
460
461
462
463
464
465
466
static void Version( void )
{
    intf_Msg(VERSION_MESSAGE "\n\n");
    intf_Msg("This is free software; see the documentation or contact <videolan@via.ecp.fr>\n" \
             "for use and copying conditions.\n" \
             "\n" \
             "This software is protected by the international copyright laws, and is\n" \
             "provided without any warranty, including the implied warranties of\n" \
             "merchantibility and fitness for a particular purpose.\n" \
            );
467
}
Vincent Seguin's avatar
Vincent Seguin committed
468

469
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
470
 * InitSignalHandler: system signal handler initialization
471
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
472
 * Set the signal handlers. SIGTERM is not intercepted, because we need at
473
 * at least a method to kill the program when all other methods failed, and
Michel Kaempf's avatar
Michel Kaempf committed
474
 * when we don't want to use SIGKILL.
475
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
476
477
static void InitSignalHandler( void )
{
Vincent Seguin's avatar
Vincent Seguin committed
478
479
480
481
    /* Termination signals */
    signal( SIGHUP,  SignalHandler );
    signal( SIGINT,  SignalHandler );
    signal( SIGQUIT, SignalHandler );
Michel Kaempf's avatar
Michel Kaempf committed
482
483
}

484
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
485
 * SignalHandler: system signal handler
486
 *****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
487
488
 * This function is called when a signal is received by the program. It tries to
 * end the program in a clean way.
489
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
490
491
static void SignalHandler( int i_signal )
{
492
    /* Once a signal has been trapped, the termination sequence will be armed and
Vincent Seguin's avatar
Vincent Seguin committed
493
494
495
496
497
498
499
500
501
     * following signals will be ignored to avoid sending messages to an interface
     * having been destroyed */
    signal( SIGHUP,  SIG_IGN );
    signal( SIGINT,  SIG_IGN );
    signal( SIGQUIT, SIG_IGN );

    /* Acknowledge the signal received */
    intf_ErrMsgImm("intf: signal %d received\n", i_signal );

502
    /* Try to terminate everything - this is done by requesting the end of the
Vincent Seguin's avatar
Vincent Seguin committed
503
504
505
506
     * interface thread */
    p_main->p_intf->b_die = 1;
}

507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
#ifdef HAVE_MMX
/*****************************************************************************
 * TestMMX: tests if the processor has MMX support.
 *****************************************************************************
 * This function is called if HAVE_MMX is enabled, to check whether the
 * cpu really supports MMX.
 *****************************************************************************/
static int TestMMX( void )
{
    int reg, dummy;

    /* test for a 386 cpu */
    asm volatile ( "pushfl
                    popl %%eax
                    movl %%eax, %%ecx
                    xorl $0x40000, %%eax
                    pushl %%eax
                    popfl
                    pushfl
                    popl %%eax
                    xorl %%ecx, %%eax
                    andl $0x40000, %%eax"
                 : "=a" ( reg ) );
    
    if( !reg )
        return( 0 );

    /* test for a 486 cpu */
    asm volatile ( "movl %%ecx, %%eax
                    xorl $0x200000, %%eax
                    pushl %%eax
                    popfl
                    pushfl
                    popl %%eax
                    xorl %%ecx, %%eax
                    pushl %%ecx 
                    popfl
                    andl $0x200000, %%eax"
                 : "=a" ( reg ) );
    
    if( !reg )
        return( 0 );

    /* the cpu supports the CPUID instruction - get its level */
    asm volatile ( "cpuid"
                 : "=a" ( reg ),
                   "=b" ( dummy ),
                   "=c" ( dummy ),
                   "=d" ( dummy )
                 : "a"  ( 0 ) ); /* level 0 */

    /* this shouldn't happen on a normal cpu */
    if( !reg )
        return( 0 );

    /* test for the MMX flag */
    asm volatile ( "cpuid
                    andl $0x00800000, %%edx" /* X86_FEATURE_MMX */
                 : "=a" ( dummy ),
                   "=b" ( dummy ),
                   "=c" ( dummy ),
                   "=d" ( reg )
                 : "a"  ( 1 ) ); /* level 1 */

    if( !reg )
        return( 0 );

    return( 1 );
}
#endif