1 /*******************************************************************************
2 * intf_msg.c: messages interface
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
10 * If INTF_MSG_QUEUE is not defined, output is directly performed on stderr.
11 * Exported symbols are declared in intf_msg.h.
12 *******************************************************************************/
14 /*******************************************************************************
16 *******************************************************************************/
23 #include <netinet/in.h>
24 #include <sys/soundcard.h>
27 #include <X11/extensions/XShm.h>
35 #include "input_vlan.h"
37 #include "audio_output.h"
40 #include "video_output.h"
43 #include "interface.h"
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 );
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 );
61 static void FlushLockedMsg ( interface_msg_t *p_intf_msg );
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
71 *******************************************************************************/
72 int intf_InitMsg( interface_msg_t *p_intf_msg )
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 */
81 /* Log file initialization */
82 p_intf_msg->p_log_file = fopen( DEBUG_LOG, "w+" );
83 if ( !p_intf_msg->p_log_file )
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 )
101 intf_FlushMsg(); /* print all remaining messages */
105 fclose( p_intf_msg->p_log_file );
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, ... )
119 va_start( ap, psz_format );
120 QueueMsg( &p_program_data->intf_msg, INTF_MSG_STD, psz_format, ap );
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
129 *******************************************************************************/
130 void intf_ErrMsg(char *psz_format, ...)
134 va_start( ap, psz_format );
135 QueueMsg( &p_program_data->intf_msg, INTF_MSG_ERR, psz_format, ap );
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, ...)
154 va_start( ap, psz_format );
155 QueueMsg( &p_program_data->intf_msg, INTF_MSG_INTF, psz_format, ap );
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 *******************************************************************************/
168 void _intf_DbgMsg( char *psz_file, char *psz_function, int i_line,
169 char *psz_format, ...)
173 va_start( ap, psz_format );
174 QueueDbgMsg( &p_program_data->intf_msg, psz_file, psz_function, i_line,
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, ... )
190 va_start( ap, psz_format );
191 QueueMsg( &p_program_data->intf_msg, INTF_MSG_STD, psz_format, ap );
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
201 *******************************************************************************/
202 void intf_ErrMsgImm(char *psz_format, ...)
206 va_start( ap, psz_format );
207 QueueMsg( &p_program_data->intf_msg, INTF_MSG_ERR, psz_format, ap );
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
218 *******************************************************************************/
220 void _intf_DbgMsgImm( char *psz_file, char *psz_function, int i_line,
221 char *psz_format, ...)
225 va_start( ap, psz_format );
226 QueueDbgMsg( &p_program_data->intf_msg, psz_file, psz_function, i_line,
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
240 *******************************************************************************/
241 #ifdef INTF_MSG_QUEUE
242 void intf_FlushMsg( void )
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 */
250 /* following functions are local */
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)
262 char * psz_str; /* formatted message string */
263 #ifndef INTF_MSG_QUEUE
264 interface_msg_message_t msg; /* message */
267 /* Convert message to string */
268 vasprintf( &psz_str, psz_format, ap );
269 if( psz_str == NULL )
271 fprintf(stderr, "intf error: *** can not store message (%s) ***\n",
273 vfprintf(stderr, psz_format, ap );
277 #ifdef INTF_MSG_QUEUE
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
283 pthread_mutex_lock( &p_intf_msg->lock ); /* get lock */
285 if( p_intf_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
287 #ifdef DEBUG /* in debug mode, queue overflow causes a waring */
288 fprintf(stderr, "intf warning: *** message queue overflow ***\n" );
290 FlushLockedMsg( p_intf_msg );
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;
297 p_intf_msg->msg[ p_intf_msg->i_count ].date = mdate();
300 pthread_mutex_unlock( &p_intf_msg->lock ); /* give lock back */
305 * Instant mode: the message is converted and printed immediately
308 msg.psz_msg = psz_str;
310 PrintMsg( &msg ); /* print message */
311 free( psz_str ); /* free message data */
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 *******************************************************************************/
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)
326 char * psz_str; /* formatted message string */
327 #ifndef INTF_MSG_QUEUE
328 interface_msg_message_t msg; /* message */
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 );
341 #ifdef INTF_MSG_QUEUE
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
347 pthread_mutex_lock( &p_intf_msg->lock ); /* get lock */
349 if( p_intf_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
351 fprintf(stderr, "intf warning: *** message queue overflow ***\n" );
352 FlushLockedMsg( p_intf_msg );
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;
363 pthread_mutex_unlock( &p_intf_msg->lock ); /* give lock back */
368 * Instant mode: the message is converted and printed immediately
370 msg.i_type = INTF_MSG_DBG;
371 msg.psz_file = psz_file;
372 msg.psz_function = psz_function;
375 // msg.date = mdate();
377 msg.psz_msg = psz_str;
378 PrintMsg( &msg ); /* print message */
379 free( psz_str ); /* free message data */
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 )
397 for( i_index = 0; i_index < p_intf_msg->i_count; i_index++ )
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 );
404 p_intf_msg->i_count = 0;
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 *******************************************************************************/
418 static void PrintMsg( interface_msg_message_t *p_msg )
420 char psz_date[MSTRTIME_MAX_SIZE]; /* formatted time buffer */
421 char * psz_msg; /* message buffer */
425 mstrtime( psz_date, p_msg->date );
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 )
431 case INTF_MSG_STD: /* regular messages */
433 asprintf( &psz_msg, "(%s) %s", psz_date, p_msg->psz_msg );
436 case INTF_MSG_INTF: /* interface messages */
438 asprintf( &psz_msg, p_msg->psz_msg );
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,
449 /* Check if formatting function suceeded */
450 if( psz_msg == NULL )
452 fprintf( stderr, "intf error: *** can not format message (%s): %s ***\n",
453 strerror( errno ), p_msg->psz_msg );
460 switch( p_msg->i_type )
462 case INTF_MSG_STD: /* standard messages */
463 fprintf( stdout, psz_msg );
465 case INTF_MSG_ERR: /* error messages */
466 #ifndef DEBUG_LOG_ONLY
467 case INTF_MSG_DBG: /* debugging messages */
469 fprintf( stderr, psz_msg );
471 case INTF_MSG_INTF: /* interface messages */
472 intf_PrintXConsole( &p_program_data->intf_thread.xconsole, psz_msg );
477 /* Append all messages to log file */
478 fprintf( p_program_data->intf_msg.p_log_file, psz_msg );
481 /* Free formatted message */
487 static void PrintMsg( interface_msg_message_t *p_msg )
490 * Print messages on screen
492 switch( p_msg->i_type )
494 case INTF_MSG_STD: /* standard messages */
495 case INTF_MSG_DBG: /* debug messages */
496 fprintf( stdout, p_msg->psz_msg );
498 case INTF_MSG_ERR: /* error messages */
499 fprintf( stderr, p_msg->psz_msg );
501 case INTF_MSG_INTF: /* interface messages */
502 intf_PrintXConsole( &p_program_data->intf_thread.xconsole,