]> git.sesse.net Git - vlc/blob - src/interface/intf_msg.c
Fin du remplacement des pthread + ajout du frame rate dans display.c.
[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 <stdio.h>
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <netinet/in.h>
23 #include <sys/soundcard.h>
24 #include <sys/uio.h>
25 #include <X11/Xlib.h>
26 #include <X11/extensions/XShm.h>
27
28 #include "config.h"
29 #include "common.h"
30 #include "mtime.h"
31 #include "vlc_thread.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     vlc_mutex_init( &p_intf_msg->lock );                     /* 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     vlc_mutex_lock( &p_program_data->intf_msg.lock );              /* get lock */
245     FlushLockedMsg( &p_program_data->intf_msg );             /* flush messages */
246     vlc_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     vlc_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     vlc_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 #ifdef DEBUG
310     msg.date = mdate();
311 #endif
312     PrintMsg( &msg );                                         /* print message */
313     free( psz_str );                                      /* free message data */    
314
315 #endif
316 }
317
318 /*******************************************************************************
319  * QueueDbgMsg: add a message to a queue with debugging informations
320  *******************************************************************************
321  * This function is the same as QueueMsg, except that it is only defined when
322  * DEBUG is define, and require additionnal debugging informations.
323  *******************************************************************************/
324 #ifdef DEBUG
325 static void QueueDbgMsg(interface_msg_t *p_intf_msg, char *psz_file, char *psz_function,
326                      int i_line, char *psz_format, va_list ap)
327 {
328     char *                          psz_str;       /* formatted message string */
329 #ifndef INTF_MSG_QUEUE
330     interface_msg_message_t         msg;                            /* message */
331 #endif
332
333     /* Convert message to string */   
334     vasprintf( &psz_str, psz_format, ap );    
335     if( psz_str == NULL )
336     {                    /* critical error: not enough memory to store message */
337         fprintf(stderr, "intf error: *** can not store message (%s) ***\n", strerror(errno) );
338         fprintf(stderr, INTF_MSG_DBG_FORMAT, psz_file, psz_function, i_line );
339         vfprintf(stderr, psz_format, ap );
340         exit( errno );
341     }
342
343 #ifdef INTF_MSG_QUEUE
344
345     /* 
346      * Queue mode: the queue is flushed if it is full, then the message is
347      * queued. A lock is required on queue to avoid indexes corruption 
348      */
349     vlc_mutex_lock( &p_intf_msg->lock );                           /* get lock */
350     
351     if( p_intf_msg->i_count == INTF_MSG_QSIZE )       /* flush queue if needed */
352     {  
353         fprintf(stderr, "intf warning: *** message queue overflow ***\n" );
354         FlushLockedMsg( p_intf_msg );
355     }
356     
357     /* Queue message */
358     p_intf_msg->msg[ p_intf_msg->i_count ].i_type =         INTF_MSG_DBG;    
359     p_intf_msg->msg[ p_intf_msg->i_count ].date =           mdate();
360     p_intf_msg->msg[ p_intf_msg->i_count ].psz_file =       psz_file;
361     p_intf_msg->msg[ p_intf_msg->i_count ].psz_function =   psz_function;
362     p_intf_msg->msg[ p_intf_msg->i_count ].i_line =         i_line;
363     p_intf_msg->msg[ p_intf_msg->i_count++ ].psz_msg =      psz_str;    
364
365     vlc_mutex_unlock( &p_intf_msg->lock );                  /* give lock back */
366
367 #else
368
369     /* 
370      * Instant mode: the message is converted and printed immediately 
371      */
372     msg.i_type =        INTF_MSG_DBG; 
373     msg.psz_file =      psz_file;
374     msg.psz_function =  psz_function;
375     msg.i_line =        i_line;
376 #ifdef DEBUG
377 //    msg.date =          mdate();
378 #endif
379     msg.psz_msg =       psz_str;
380     PrintMsg( &msg );                                         /* print message */
381     free( psz_str );                                      /* free message data */    
382
383 #endif
384 }
385 #endif
386
387 /*******************************************************************************
388  * FlushLockedMsg                                                        (ok ?)
389  *******************************************************************************
390  * Print all messages remaining in queue. MESSAGE QUEUE MUST BE LOCKED, since
391  * this function does not check the lock. This function is only defined if
392  * INTF_MSG_QUEUE is defined.
393  *******************************************************************************/
394 #ifdef INTF_MSG_QUEUE
395 static void FlushLockedMsg ( interface_msg_t *p_intf_msg )
396 {
397     int i_index;
398
399     for( i_index = 0; i_index < p_intf_msg->i_count; i_index++ )
400     {
401         /* Print message and free message data */
402         PrintMsg( &p_intf_msg->msg[i_index] );      
403         free( p_intf_msg->msg[i_index].psz_msg );
404     }
405     
406     p_intf_msg->i_count = 0;
407 }
408 #endif
409
410 /*******************************************************************************
411  * PrintMsg: print a message                                              (ok ?)
412  *******************************************************************************
413  * Print a single message. The message data is not freed. This function exists
414  * in two version. The DEBUG version prints a date with each message, and is
415  * able to log messages (if DEBUG_LOG is defined).
416  * The normal one just prints messages to the screen.
417  *******************************************************************************/
418 #ifdef DEBUG
419
420 static void PrintMsg( interface_msg_message_t *p_msg )
421 {
422     char    psz_date[MSTRTIME_MAX_SIZE];              /* formatted time buffer */
423     char *  psz_msg;                                         /* message buffer */
424     
425
426     /* Computes date */
427     mstrtime( psz_date, p_msg->date );    
428
429     /* Format message - the message is formatted here because in case the log
430      * file is used, it avoids another format string parsing */
431     switch( p_msg->i_type )
432     {
433     case INTF_MSG_STD:                                     /* regular messages */
434     case INTF_MSG_ERR:
435         asprintf( &psz_msg, "(%s) %s", psz_date, p_msg->psz_msg );
436         break;
437
438     case INTF_MSG_INTF:                                  /* interface messages */
439     case INTF_MSG_DBG:
440         asprintf( &psz_msg, p_msg->psz_msg );
441         break;
442 #if 0        
443     case INTF_MSG_DBG:                                       /* debug messages */
444         asprintf( &psz_msg, "(%s) " INTF_MSG_DBG_FORMAT "%s", 
445                   psz_date, p_msg->psz_file, p_msg->psz_function, p_msg->i_line, 
446                   p_msg->psz_msg );            
447         break;                
448 #endif
449     }
450  
451     /* Check if formatting function suceeded */
452     if( psz_msg == NULL )
453     {
454         fprintf( stderr, "intf error: *** can not format message (%s): %s ***\n", 
455                  strerror( errno ), p_msg->psz_msg );        
456         return;        
457     }
458
459     /*
460      * Print messages
461      */
462     switch( p_msg->i_type )
463     {
464     case INTF_MSG_STD:                                    /* standard messages */
465         fprintf( stdout, psz_msg );
466         break;
467     case INTF_MSG_ERR:                                       /* error messages */
468 #ifndef DEBUG_LOG_ONLY
469     case INTF_MSG_DBG:                                   /* debugging messages */
470 #endif
471         fprintf( stderr, psz_msg );
472         break;
473     case INTF_MSG_INTF:                                  /* interface messages */
474         intf_PrintXConsole( &p_program_data->intf_thread.xconsole, psz_msg );
475         break;
476     }
477     
478 #ifdef DEBUG_LOG
479     /* Append all messages to log file */
480     fprintf( p_program_data->intf_msg.p_log_file, psz_msg );
481 #endif
482
483     /* Free formatted message */
484     free( psz_msg );    
485 }
486
487 #else
488
489 static void PrintMsg( interface_msg_message_t *p_msg )
490 {
491     /*
492      * Print messages on screen 
493      */
494     switch( p_msg->i_type )
495     {
496     case INTF_MSG_STD:                                    /* standard messages */
497     case INTF_MSG_DBG:                                       /* debug messages */
498         fprintf( stdout, p_msg->psz_msg );
499         break;
500     case INTF_MSG_ERR:                                       /* error messages */
501         fprintf( stderr, p_msg->psz_msg );
502         break;
503     case INTF_MSG_INTF:                                  /* interface messages */
504         intf_PrintXConsole( &p_program_data->intf_thread.xconsole, 
505                             p_msg->psz_msg );
506         break;
507     } 
508 }
509
510 #endif