]> git.sesse.net Git - vlc/blob - src/interface/intf_msg.c
* Le video_decoder a desormais une structure qui tourne (copier-coller de
[vlc] / src / interface / intf_msg.c
1 /*******************************************************************************
2  * intf_msg.c: messages interface
3  * (c)1998 VideoLAN
4  *******************************************************************************
5  * This library provides basic functions for threads to interact with user
6  * interface, such as message output. If INTF_MSG_QUEUE is defined (which is the
7  * defaul), messages are not printed directly by threads, to bypass console 
8  * limitations and slow printf() calls, but sent to a queue and printed later by
9  * interface thread. 
10  * If INTF_MSG_QUEUE is not defined, output is directly performed on stderr.
11  * Exported symbols are declared in intf_msg.h.
12  *******************************************************************************/
13
14 /*******************************************************************************
15  * Preamble
16  *******************************************************************************/
17 #include <errno.h>
18 #include <pthread.h>
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <netinet/in.h>
24 #include <sys/soundcard.h>
25 #include <sys/uio.h>
26 #include <X11/Xlib.h>
27 #include <X11/extensions/XShm.h>
28
29 #include "config.h"
30 #include "common.h"
31 #include "mtime.h"
32 #include "debug.h"
33
34 #include "input.h"
35 #include "input_vlan.h"
36
37 #include "audio_output.h"
38
39 #include "video.h"
40 #include "video_output.h"
41
42 #include "xconsole.h"
43 #include "interface.h"
44 #include "intf_msg.h"
45
46 #include "pgm_data.h"
47
48 /*
49  * Local prototypes
50  */
51
52 static void QueueMsg        ( interface_msg_t *p_intf_msg, int i_type,
53                               char *psz_format, va_list ap );
54 static void PrintMsg        ( interface_msg_message_t *p_msg );
55 #ifdef DEBUG
56 static void QueueDbgMsg     ( interface_msg_t *p_intf_msg, char *psz_file, 
57                               char *psz_function, int i_line, 
58                               char *psz_format, va_list ap );
59 #endif
60 #ifdef INTF_MSG_QUEUE
61 static void FlushLockedMsg  ( interface_msg_t *p_intf_msg );
62 #endif
63
64 /*******************************************************************************
65  * intf_InitMsg: initialize messages interface                            (ok ?)
66  *******************************************************************************
67  * This functions has to be called before any call to other intf_*Msg functions.
68  * It set up the locks and the message queue if it is used. On error, 
69  * it returns errno (without printing its own error messages) and free all 
70  * alocated resources.
71  *******************************************************************************/
72 int intf_InitMsg( interface_msg_t *p_intf_msg )
73 {
74 #ifdef INTF_MSG_QUEUE
75     /* Message queue initialization */
76     pthread_mutex_init( &p_intf_msg->lock, NULL );           /* intialize lock */
77     p_intf_msg->i_count = 0;                                 /* queue is empty */
78 #endif
79
80 #ifdef DEBUG_LOG
81     /* Log file initialization */
82     p_intf_msg->p_log_file = fopen( DEBUG_LOG, "w+" );
83     if ( !p_intf_msg->p_log_file )
84     {        
85         return( errno );
86     }    
87 #endif
88
89     return( 0 );
90 }
91
92 /*******************************************************************************
93  * intf_TerminateMsg: free resources allocated by intf_InitMsg            (ok ?)
94  *******************************************************************************
95  * This functions prints all messages remaining in queue, then free all the 
96  * resources allocated by intf_InitMsg.
97  * No other messages interface functions should be called after this one.
98  *******************************************************************************/
99 void intf_TerminateMsg( interface_msg_t *p_intf_msg )
100 {
101     intf_FlushMsg();                           /* print all remaining messages */
102
103 #ifdef DEBUG_LOG
104     /* Close log file */
105     fclose( p_intf_msg->p_log_file );
106 #endif
107 }
108
109 /*******************************************************************************
110  * intf_Msg: print a message                                              (ok ?)
111  *******************************************************************************
112  * This function queue a message for later printing, or print it immediately
113  * if the queue isn't used.
114  *******************************************************************************/
115 void intf_Msg( char *psz_format, ... )
116 {
117     va_list ap;
118
119     va_start( ap, psz_format );
120     QueueMsg( &p_program_data->intf_msg, INTF_MSG_STD, psz_format, ap );
121     va_end( ap );
122 }
123  
124 /*******************************************************************************
125  * intf_ErrMsg : print an error message                                   (ok ?)
126  *******************************************************************************
127  * This function is the same as intf_Msg, except that it prints its messages
128  * on stderr.
129  *******************************************************************************/ 
130 void intf_ErrMsg(char *psz_format, ...)
131 {
132     va_list ap;
133
134     va_start( ap, psz_format );
135     QueueMsg( &p_program_data->intf_msg, INTF_MSG_ERR, psz_format, ap );
136     va_end( ap );
137 }
138
139 /*******************************************************************************
140  * intf_IntfMsg : print an interface message                              (ok ?)
141  *******************************************************************************
142  * In opposition to all other intf_*Msg function, this function does not print
143  * it's message on default terminal (stdout or stderr), but send it to 
144  * interface (in fact to the X11 console). This means that the interface MUST
145  * be initialized and a X11 console openned before this function is used, and
146  * that once the console is closed, this call is vorbidden.
147  * Practically, only the interface thread itself should call this function, and 
148  * flush all messages before intf_CloseX11Console() is called.
149  *******************************************************************************/
150 void intf_IntfMsg(char *psz_format, ...)
151 {
152     va_list ap;
153
154     va_start( ap, psz_format );
155     QueueMsg( &p_program_data->intf_msg, INTF_MSG_INTF, psz_format, ap );
156     va_end( ap );
157 }
158
159 /*******************************************************************************
160  * _intf_DbgMsg: print a debugging message                                (ok ?)
161  *******************************************************************************
162  * This function prints a debugging message. Compared to other intf_*Msg 
163  * functions, it is only defined if DEBUG is defined and require a file name,
164  * a function name and a line number as additionnal debugging informations. It
165  * also prints a debugging header for each received line.
166  *******************************************************************************/ 
167 #ifdef DEBUG
168 void _intf_DbgMsg( char *psz_file, char *psz_function, int i_line, 
169                    char *psz_format, ...)
170 {
171     va_list ap;
172
173     va_start( ap, psz_format );
174     QueueDbgMsg( &p_program_data->intf_msg, psz_file, psz_function, i_line, 
175                  psz_format, ap );
176     va_end( ap );
177 }
178 #endif
179
180 /*******************************************************************************
181  * intf_ErrMsgImm: print a message                                        (ok ?)
182  *******************************************************************************
183  * This function prints a message immediately. If the queue is used, all 
184  * waiting messages are also printed.
185  *******************************************************************************/
186 void intf_MsgImm( char *psz_format, ... )
187 {
188     va_list ap;
189
190     va_start( ap, psz_format );
191     QueueMsg( &p_program_data->intf_msg, INTF_MSG_STD, psz_format, ap );
192     va_end( ap );
193     intf_FlushMsg();
194 }
195  
196 /*******************************************************************************
197  * intf_ErrMsgImm: print an error message immediately                     (ok ?)
198  *******************************************************************************
199  * This function is the same as intf_MsgImm, except that it prints its message
200  * on stderr.
201  *******************************************************************************/
202 void intf_ErrMsgImm(char *psz_format, ...)
203 {
204     va_list ap;
205
206     va_start( ap, psz_format );
207     QueueMsg( &p_program_data->intf_msg, INTF_MSG_ERR, psz_format, ap );
208     va_end( ap );
209     intf_FlushMsg();
210 }
211
212 /*******************************************************************************
213  * _intf_DbgMsgImm: print a debugging message immediately                 (ok ?)
214  *******************************************************************************
215  * This function is the same as intf_DbgMsgImm, except that it prints its
216  * message immediately. It should only be called through the macro 
217  * intf_DbgMsgImm().
218  *******************************************************************************/
219 #ifdef DEBUG
220 void _intf_DbgMsgImm( char *psz_file, char *psz_function, int i_line, 
221                       char *psz_format, ...)
222 {
223     va_list ap;
224
225     va_start( ap, psz_format );
226     QueueDbgMsg( &p_program_data->intf_msg, psz_file, psz_function, i_line, 
227                  psz_format, ap );
228     va_end( ap );
229     intf_FlushMsg();
230 }
231 #endif
232
233 /*******************************************************************************
234  * intf_FlushMsg                                                          (ok ?)
235  *******************************************************************************
236  * Print all messages remaining in queue: get lock and call FlushLockedMsg.
237  * This function does nothing if the message queue isn't used.
238  * This function is only implemented if message queue is used. If not, it is an
239  * empty macro.
240  *******************************************************************************/
241 #ifdef INTF_MSG_QUEUE
242 void intf_FlushMsg( void )
243 {
244     pthread_mutex_lock( &p_program_data->intf_msg.lock );          /* get lock */
245     FlushLockedMsg( &p_program_data->intf_msg );             /* flush messages */
246     pthread_mutex_unlock( &p_program_data->intf_msg.lock );  /* give lock back */
247 }
248 #endif
249
250 /* following functions are local */
251
252 /*******************************************************************************
253  * QueueMsg: add a message to a queue                                    (ok ?)
254  *******************************************************************************
255  * This function provide basic functionnalities to other intf_*Msg functions.
256  * It add a message to a queue (after having printed all stored messages if it
257  * is full. If the message can't be converted to string in memory, it exit the  
258  * program. If the queue is not used, it prints the message immediately.
259  *******************************************************************************/
260 static void QueueMsg(interface_msg_t *p_intf_msg, int i_type, char *psz_format, va_list ap)
261 {
262     char *                          psz_str;       /* formatted message string */
263 #ifndef INTF_MSG_QUEUE
264     interface_msg_message_t         msg;                            /* message */
265 #endif
266
267     /* Convert message to string */   
268     vasprintf( &psz_str, psz_format, ap );
269     if( psz_str == NULL )
270     {
271         fprintf(stderr, "intf error: *** can not store message (%s) ***\n", 
272                 strerror(errno) );
273         vfprintf(stderr, psz_format, ap );
274         exit( errno );
275     }
276
277 #ifdef INTF_MSG_QUEUE
278
279     /* 
280      * Queue mode: the queue is flushed if it is full, then the message is
281      * queued. A lock is required on queue to avoid indexes corruption 
282      */
283     pthread_mutex_lock( &p_intf_msg->lock );                        /* get lock */
284     
285     if( p_intf_msg->i_count == INTF_MSG_QSIZE )        /* flush queue if needed */
286     {  
287 #ifdef DEBUG                   /* in debug mode, queue overflow causes a waring */
288         fprintf(stderr, "intf warning: *** message queue overflow ***\n" );
289 #endif
290         FlushLockedMsg( p_intf_msg );
291     }
292     
293     /* Queue message - if DEBUG if defined, the message is dated */
294     p_intf_msg->msg[ p_intf_msg->i_count ].i_type =     i_type;
295     p_intf_msg->msg[ p_intf_msg->i_count++ ].psz_msg =  psz_str;    
296 #ifdef DEBUG
297     p_intf_msg->msg[ p_intf_msg->i_count ].date =       mdate();
298 #endif
299
300     pthread_mutex_unlock( &p_intf_msg->lock );               /* give lock back */
301
302 #else
303
304     /* 
305      * Instant mode: the message is converted and printed immediately 
306      */
307     msg.i_type = i_type; 
308     msg.psz_msg = psz_str;
309     msg.date = mdate();
310     PrintMsg( &msg );                                         /* print message */
311     free( psz_str );                                      /* free message data */    
312
313 #endif
314 }
315
316 /*******************************************************************************
317  * QueueDbgMsg: add a message to a queue with debugging informations
318  *******************************************************************************
319  * This function is the same as QueueMsg, except that it is only defined when
320  * DEBUG is define, and require additionnal debugging informations.
321  *******************************************************************************/
322 #ifdef DEBUG
323 static void QueueDbgMsg(interface_msg_t *p_intf_msg, char *psz_file, char *psz_function,
324                      int i_line, char *psz_format, va_list ap)
325 {
326     char *                          psz_str;       /* formatted message string */
327 #ifndef INTF_MSG_QUEUE
328     interface_msg_message_t         msg;                            /* message */
329 #endif
330
331     /* Convert message to string */   
332     vasprintf( &psz_str, psz_format, ap );    
333     if( psz_str == NULL )
334     {                    /* critical error: not enough memory to store message */
335         fprintf(stderr, "intf error: *** can not store message (%s) ***\n", strerror(errno) );
336         fprintf(stderr, INTF_MSG_DBG_FORMAT, psz_file, psz_function, i_line );
337         vfprintf(stderr, psz_format, ap );
338         exit( errno );
339     }
340
341 #ifdef INTF_MSG_QUEUE
342
343     /* 
344      * Queue mode: the queue is flushed if it is full, then the message is
345      * queued. A lock is required on queue to avoid indexes corruption 
346      */
347     pthread_mutex_lock( &p_intf_msg->lock );                       /* get lock */
348     
349     if( p_intf_msg->i_count == INTF_MSG_QSIZE )       /* flush queue if needed */
350     {  
351         fprintf(stderr, "intf warning: *** message queue overflow ***\n" );
352         FlushLockedMsg( p_intf_msg );
353     }
354     
355     /* Queue message */
356     p_intf_msg->msg[ p_intf_msg->i_count ].i_type =         INTF_MSG_DBG;    
357     p_intf_msg->msg[ p_intf_msg->i_count ].date =           mdate();
358     p_intf_msg->msg[ p_intf_msg->i_count ].psz_file =       psz_file;
359     p_intf_msg->msg[ p_intf_msg->i_count ].psz_function =   psz_function;
360     p_intf_msg->msg[ p_intf_msg->i_count ].i_line =         i_line;
361     p_intf_msg->msg[ p_intf_msg->i_count++ ].psz_msg =      psz_str;    
362
363     pthread_mutex_unlock( &p_intf_msg->lock );               /* give lock back */
364
365 #else
366
367     /* 
368      * Instant mode: the message is converted and printed immediately 
369      */
370     msg.i_type =        INTF_MSG_DBG; 
371     msg.psz_file =      psz_file;
372     msg.psz_function =  psz_function;
373     msg.i_line =        i_line;
374 #ifdef DEBUG
375 //    msg.date =          mdate();
376 #endif
377     msg.psz_msg =       psz_str;
378     PrintMsg( &msg );                                         /* print message */
379     free( psz_str );                                      /* free message data */    
380
381 #endif
382 }
383 #endif
384
385 /*******************************************************************************
386  * FlushLockedMsg                                                        (ok ?)
387  *******************************************************************************
388  * Print all messages remaining in queue. MESSAGE QUEUE MUST BE LOCKED, since
389  * this function does not check the lock. This function is only defined if
390  * INTF_MSG_QUEUE is defined.
391  *******************************************************************************/
392 #ifdef INTF_MSG_QUEUE
393 static void FlushLockedMsg ( interface_msg_t *p_intf_msg )
394 {
395     int i_index;
396
397     for( i_index = 0; i_index < p_intf_msg->i_count; i_index++ )
398     {
399         /* Print message and free message data */
400         PrintMsg( &p_intf_msg->msg[i_index] );      
401         free( p_intf_msg->msg[i_index].psz_msg );
402     }
403     
404     p_intf_msg->i_count = 0;
405 }
406 #endif
407
408 /*******************************************************************************
409  * PrintMsg: print a message                                              (ok ?)
410  *******************************************************************************
411  * Print a single message. The message data is not freed. This function exists
412  * in two version. The DEBUG version prints a date with each message, and is
413  * able to log messages (if DEBUG_LOG is defined).
414  * The normal one just prints messages to the screen.
415  *******************************************************************************/
416 #ifdef DEBUG
417
418 static void PrintMsg( interface_msg_message_t *p_msg )
419 {
420     char    psz_date[MSTRTIME_MAX_SIZE];              /* formatted time buffer */
421     char *  psz_msg;                                         /* message buffer */
422     
423
424     /* Computes date */
425     mstrtime( psz_date, p_msg->date );    
426
427     /* Format message - the message is formatted here because in case the log
428      * file is used, it avoids another format string parsing */
429     switch( p_msg->i_type )
430     {
431     case INTF_MSG_STD:                                     /* regular messages */
432     case INTF_MSG_ERR:
433         asprintf( &psz_msg, "(%s) %s", psz_date, p_msg->psz_msg );
434         break;
435
436     case INTF_MSG_INTF:                                  /* interface messages */
437     case INTF_MSG_DBG:
438         asprintf( &psz_msg, p_msg->psz_msg );
439         break;
440 #if 0        
441     case INTF_MSG_DBG:                                       /* debug messages */
442         asprintf( &psz_msg, "(%s) " INTF_MSG_DBG_FORMAT "%s", 
443                   psz_date, p_msg->psz_file, p_msg->psz_function, p_msg->i_line, 
444                   p_msg->psz_msg );            
445         break;                
446 #endif
447     }
448  
449     /* Check if formatting function suceeded */
450     if( psz_msg == NULL )
451     {
452         fprintf( stderr, "intf error: *** can not format message (%s): %s ***\n", 
453                  strerror( errno ), p_msg->psz_msg );        
454         return;        
455     }
456
457     /*
458      * Print messages
459      */
460     switch( p_msg->i_type )
461     {
462     case INTF_MSG_STD:                                    /* standard messages */
463         fprintf( stdout, psz_msg );
464         break;
465     case INTF_MSG_ERR:                                       /* error messages */
466 #ifndef DEBUG_LOG_ONLY
467     case INTF_MSG_DBG:                                   /* debugging messages */
468 #endif
469         fprintf( stderr, psz_msg );
470         break;
471     case INTF_MSG_INTF:                                  /* interface messages */
472         intf_PrintXConsole( &p_program_data->intf_thread.xconsole, psz_msg );
473         break;
474     }
475     
476 #ifdef DEBUG_LOG
477     /* Append all messages to log file */
478     fprintf( p_program_data->intf_msg.p_log_file, psz_msg );
479 #endif
480
481     /* Free formatted message */
482     free( psz_msg );    
483 }
484
485 #else
486
487 static void PrintMsg( interface_msg_message_t *p_msg )
488 {
489     /*
490      * Print messages on screen 
491      */
492     switch( p_msg->i_type )
493     {
494     case INTF_MSG_STD:                                    /* standard messages */
495     case INTF_MSG_DBG:                                       /* debug messages */
496         fprintf( stdout, p_msg->psz_msg );
497         break;
498     case INTF_MSG_ERR:                                       /* error messages */
499         fprintf( stderr, p_msg->psz_msg );
500         break;
501     case INTF_MSG_INTF:                                  /* interface messages */
502         intf_PrintXConsole( &p_program_data->intf_thread.xconsole, 
503                             p_msg->psz_msg );
504         break;
505     } 
506 }
507
508 #endif