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. See config.h for output configuration.
7 *******************************************************************************/
9 /*******************************************************************************
11 *******************************************************************************/
23 #include "vlc_thread.h"
25 #include "interface.h"
26 #include "intf_console.h"
29 /*******************************************************************************
31 *******************************************************************************
32 * Store a single message. Messages have a maximal size of INTF_MSG_MSGSIZE.
33 * If DEBUG is defined, messages have a date field and debug messages are
34 * printed with a date to allow more precise profiling.
35 *******************************************************************************/
38 int i_type; /* message type, see below */
39 char * psz_msg; /* the message itself */
42 /* Debugging informations - in DEBUG mode, debug messages have calling
43 * location informations printed */
44 mtime_t date; /* date of the message */
45 char * psz_file; /* file in which the function was called */
46 char * psz_function; /* function from which the function was called */
47 int i_line; /* line at which the function was called */
52 #define INTF_MSG_STD 0 /* standard message */
53 #define INTF_MSG_ERR 1 /* error message */
54 #define INTF_MSG_INTF 2 /* interface message */
55 #define INTF_MSG_DBG 3 /* debug message */
57 /*******************************************************************************
59 *******************************************************************************
60 * Store all data requiered by messages interfaces. It has a single reference
62 *******************************************************************************/
63 typedef struct intf_msg_s
67 vlc_mutex_t lock; /* message queue lock */
68 int i_count; /* number of messages stored */
69 intf_msg_item_t msg[INTF_MSG_QSIZE]; /* message queue */
74 int i_log_file; /* log file */
77 #if !defined(INTF_MSG_QUEUE) && !defined(DEBUG_LOG)
78 /* If neither messages queue, neither log file is used, then the structure
79 * is empty. However, empty structures are not allowed in C. Therefore, a
80 * dummy integer is used to fill it. */
81 int i_dummy; /* unused filler */
85 /*****************************************************************************
87 *****************************************************************************/
89 static void QueueMsg ( intf_msg_t *p_msg, int i_type,
90 char *psz_format, va_list ap );
91 static void PrintMsg ( intf_msg_item_t *p_msg );
93 static void QueueDbgMsg ( intf_msg_t *p_msg, char *psz_file,
94 char *psz_function, int i_line,
95 char *psz_format, va_list ap );
98 static void FlushLockedMsg ( intf_msg_t *p_msg );
102 /*******************************************************************************
103 * intf_MsgCreate: initialize messages interface (ok ?)
104 *******************************************************************************
105 * This functions has to be called before any call to other intf_*Msg functions.
106 * It set up the locks and the message queue if it is used.
107 *******************************************************************************/
108 p_intf_msg_t intf_MsgCreate( void )
112 /* Allocate structure */
113 p_msg = malloc( sizeof( intf_msg_t ) );
120 #ifdef INTF_MSG_QUEUE
121 /* Message queue initialization */
122 vlc_mutex_init( &p_msg->lock ); /* intialize lock */
123 p_msg->i_count = 0; /* queue is empty */
127 /* Log file initialization - on failure, file pointer will be null,
128 * and no log will be issued, but this is not considered as an
130 p_msg->i_log_file = open( DEBUG_LOG,
131 O_CREAT | O_TRUNC | O_SYNC | O_WRONLY,
138 /*******************************************************************************
139 * intf_MsgDestroy: free resources allocated by intf_InitMsg (ok ?)
140 *******************************************************************************
141 * This functions prints all messages remaining in queue, then free all the
142 * resources allocated by intf_InitMsg.
143 * No other messages interface functions should be called after this one.
144 *******************************************************************************/
145 void intf_MsgDestroy( void )
147 intf_FlushMsg(); /* print all remaining messages */
150 /* Close log file if any */
151 if( p_main->p_msg->i_log_file >= 0 )
153 close( p_main->p_msg->i_log_file );
158 free( p_main->p_msg );
161 /*******************************************************************************
162 * intf_Msg: print a message (ok ?)
163 *******************************************************************************
164 * This function queue a message for later printing, or print it immediately
165 * if the queue isn't used.
166 *******************************************************************************/
167 void intf_Msg( char *psz_format, ... )
171 va_start( ap, psz_format );
172 QueueMsg( p_main->p_msg, INTF_MSG_STD, psz_format, ap );
176 /*******************************************************************************
177 * intf_ErrMsg : print an error message (ok ?)
178 *******************************************************************************
179 * This function is the same as intf_Msg, except that it prints its messages
181 *******************************************************************************/
182 void intf_ErrMsg( char *psz_format, ...)
186 va_start( ap, psz_format );
187 QueueMsg( p_main->p_msg, INTF_MSG_ERR, psz_format, ap );
191 /*******************************************************************************
192 * intf_IntfMsg : print an interface message (ok ?)
193 *******************************************************************************
194 * In opposition to all other intf_*Msg function, this function does not print
195 * it's message on default terminal (stdout or stderr), but send it to
196 * interface (in fact to the X11 console). This means that the interface MUST
197 * be initialized and a X11 console openned before this function is used, and
198 * that once the console is closed, this call is vorbidden.
199 * Practically, only the interface thread itself should call this function, and
200 * flush all messages before intf_CloseX11Console() is called.
201 *******************************************************************************/
202 void intf_IntfMsg(char *psz_format, ...)
206 va_start( ap, psz_format );
207 QueueMsg( p_main->p_msg, INTF_MSG_INTF, psz_format, ap );
211 /*******************************************************************************
212 * _intf_DbgMsg: print a debugging message (ok ?)
213 *******************************************************************************
214 * This function prints a debugging message. Compared to other intf_*Msg
215 * functions, it is only defined if DEBUG is defined and require a file name,
216 * a function name and a line number as additionnal debugging informations. It
217 * also prints a debugging header for each received line.
218 *******************************************************************************/
220 void _intf_DbgMsg( char *psz_file, char *psz_function, int i_line,
221 char *psz_format, ...)
225 va_start( ap, psz_format );
226 QueueDbgMsg( p_main->p_msg, psz_file, psz_function, i_line,
232 /*******************************************************************************
233 * intf_ErrMsgImm: print a message (ok ?)
234 *******************************************************************************
235 * This function prints a message immediately. If the queue is used, all
236 * waiting messages are also printed.
237 *******************************************************************************/
238 void intf_MsgImm( char *psz_format, ... )
242 va_start( ap, psz_format );
243 QueueMsg( p_main->p_msg, INTF_MSG_STD, psz_format, ap );
248 /*******************************************************************************
249 * intf_ErrMsgImm: print an error message immediately (ok ?)
250 *******************************************************************************
251 * This function is the same as intf_MsgImm, except that it prints its message
253 *******************************************************************************/
254 void intf_ErrMsgImm(char *psz_format, ...)
258 va_start( ap, psz_format );
259 QueueMsg( p_main->p_msg, INTF_MSG_ERR, psz_format, ap );
264 /*******************************************************************************
265 * _intf_DbgMsgImm: print a debugging message immediately (ok ?)
266 *******************************************************************************
267 * This function is the same as intf_DbgMsgImm, except that it prints its
268 * message immediately. It should only be called through the macro
270 *******************************************************************************/
272 void _intf_DbgMsgImm( char *psz_file, char *psz_function, int i_line,
273 char *psz_format, ...)
277 va_start( ap, psz_format );
278 QueueDbgMsg( p_main->p_msg, psz_file, psz_function, i_line,
285 /*******************************************************************************
286 * intf_FlushMsg (ok ?)
287 *******************************************************************************
288 * Print all messages remaining in queue: get lock and call FlushLockedMsg.
289 * This function does nothing if the message queue isn't used.
290 * This function is only implemented if message queue is used. If not, it is an
292 *******************************************************************************/
293 #ifdef INTF_MSG_QUEUE
294 void intf_FlushMsg( void )
296 vlc_mutex_lock( &p_main->p_msg->lock ); /* get lock */
297 FlushLockedMsg( p_main->p_msg ); /* flush messages */
298 vlc_mutex_unlock( &p_main->p_msg->lock ); /* give lock back */
302 /* following functions are local */
304 /*******************************************************************************
305 * QueueMsg: add a message to a queue
306 *******************************************************************************
307 * This function provide basic functionnalities to other intf_*Msg functions.
308 * It add a message to a queue (after having printed all stored messages if it
309 * is full. If the message can't be converted to string in memory, it exit the
310 * program. If the queue is not used, it prints the message immediately.
311 *******************************************************************************/
312 static void QueueMsg( intf_msg_t *p_msg, int i_type, char *psz_format, va_list ap )
314 char * psz_str; /* formatted message string */
315 intf_msg_item_t * p_msg_item; /* pointer to message */
317 #ifndef INTF_MSG_QUEUE /*..................................... instant mode ...*/
318 intf_msg_item_t msg_item; /* message */
319 p_msg_item = &msg_item;
320 #endif /*......................................................................*/
323 * Convert message to string
325 vasprintf( &psz_str, psz_format, ap );
326 if( psz_str == NULL )
328 fprintf(stderr, "warning: can't store following message (%s): ",
330 vfprintf(stderr, psz_format, ap );
334 #ifdef INTF_MSG_QUEUE /*........................................ queue mode ...*/
335 vlc_mutex_lock( &p_msg->lock ); /* get lock */
336 if( p_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
338 #ifdef DEBUG /* in debug mode, queue overflow causes a warning */
339 fprintf(stderr, "warning: message queue overflow\n" );
341 FlushLockedMsg( p_msg );
343 p_msg_item = p_msg->msg + p_msg->i_count++; /* select message */
344 #endif /*................................................ end of queue mode ...*/
347 * Fill message information fields
349 p_msg_item->i_type = i_type;
350 p_msg_item->psz_msg = psz_str;
352 #ifdef INTF_MSG_QUEUE /*........................................... queue mode */
353 vlc_mutex_unlock( &p_msg->lock ); /* give lock back */
354 #else /*......................................................... instant mode */
355 PrintMsg( p_msg_item ); /* print message */
356 free( psz_str ); /* free message data */
357 #endif /*......................................................................*/
360 /*******************************************************************************
361 * QueueDbgMsg: add a message to a queue with debugging informations
362 *******************************************************************************
363 * This function is the same as QueueMsg, except that it is only defined when
364 * DEBUG is define, and require additionnal debugging informations.
365 *******************************************************************************/
367 static void QueueDbgMsg(intf_msg_t *p_msg, char *psz_file, char *psz_function,
368 int i_line, char *psz_format, va_list ap)
370 char * psz_str; /* formatted message string */
371 intf_msg_item_t * p_msg_item; /* pointer to message */
373 #ifndef INTF_MSG_QUEUE /*..................................... instant mode ...*/
374 intf_msg_item_t msg_item; /* message */
375 p_msg_item = &msg_item;
376 #endif /*......................................................................*/
379 * Convert message to string
381 vasprintf( &psz_str, psz_format, ap );
382 if( psz_str == NULL )
384 fprintf(stderr, "warning: can't store following message (%s): ",
386 fprintf(stderr, INTF_MSG_DBG_FORMAT, psz_file, psz_function, i_line );
387 vfprintf(stderr, psz_format, ap );
391 #ifdef INTF_MSG_QUEUE /*........................................ queue mode ...*/
392 vlc_mutex_lock( &p_msg->lock ); /* get lock */
393 if( p_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
395 #ifdef DEBUG /* in debug mode, queue overflow causes a warning */
396 fprintf(stderr, "warning: message queue overflow\n" );
398 FlushLockedMsg( p_msg );
400 p_msg_item = p_msg->msg + p_msg->i_count++; /* select message */
401 #endif /*................................................ end of queue mode ...*/
404 * Fill message information fields
406 p_msg_item->i_type = INTF_MSG_DBG;
407 p_msg_item->psz_msg = psz_str;
408 p_msg_item->psz_file = psz_file;
409 p_msg_item->psz_function = psz_function;
410 p_msg_item->i_line = i_line;
411 p_msg_item->date = mdate();
413 #ifdef INTF_MSG_QUEUE /*........................................... queue mode */
414 vlc_mutex_unlock( &p_msg->lock ); /* give lock back */
415 #else /*......................................................... instant mode */
416 PrintMsg( p_msg_item ); /* print message */
417 free( psz_str ); /* free message data */
418 #endif /*......................................................................*/
422 /*******************************************************************************
423 * FlushLockedMsg (ok ?)
424 *******************************************************************************
425 * Print all messages remaining in queue. MESSAGE QUEUE MUST BE LOCKED, since
426 * this function does not check the lock. This function is only defined if
427 * INTF_MSG_QUEUE is defined.
428 *******************************************************************************/
429 #ifdef INTF_MSG_QUEUE
430 static void FlushLockedMsg ( intf_msg_t *p_msg )
434 for( i_index = 0; i_index < p_msg->i_count; i_index++ )
436 /* Print message and free message data */
437 PrintMsg( &p_msg->msg[i_index] );
438 free( p_msg->msg[i_index].psz_msg );
445 /*******************************************************************************
446 * PrintMsg: print a message (ok ?)
447 *******************************************************************************
448 * Print a single message. The message data is not freed. This function exists
449 * in two version. The DEBUG version prints a date with each message, and is
450 * able to log messages (if DEBUG_LOG is defined).
451 * The normal one just prints messages to the screen.
452 *******************************************************************************/
455 static void PrintMsg( intf_msg_item_t *p_msg )
457 char psz_date[MSTRTIME_MAX_SIZE]; /* formatted time buffer */
458 char * psz_msg; /* message buffer */
460 /* Format message - the message is formatted here because in case the log
461 * file is used, it avoids another format string parsing */
462 switch( p_msg->i_type )
464 case INTF_MSG_STD: /* regular messages */
466 asprintf( &psz_msg, "%s", p_msg->psz_msg );
469 case INTF_MSG_INTF: /* interface messages */
470 asprintf( &psz_msg, "%s", p_msg->psz_msg );
473 case INTF_MSG_DBG: /* debug messages */
474 mstrtime( psz_date, p_msg->date );
475 asprintf( &psz_msg, "(%s) " INTF_MSG_DBG_FORMAT "%s",
476 psz_date, p_msg->psz_file, p_msg->psz_function, p_msg->i_line,
481 /* Check if formatting function suceeded */
482 if( psz_msg == NULL )
484 fprintf( stderr, "error: can not format message (%s): %s\n",
485 strerror( errno ), p_msg->psz_msg );
492 switch( p_msg->i_type )
494 case INTF_MSG_STD: /* standard messages */
495 fprintf( stdout, psz_msg );
497 case INTF_MSG_ERR: /* error messages */
498 #ifndef DEBUG_LOG_ONLY
499 case INTF_MSG_DBG: /* debugging messages */
501 fprintf( stderr, psz_msg );
503 case INTF_MSG_INTF: /* interface messages */
504 intf_ConsolePrint( p_main->p_intf->p_console, psz_msg );
509 /* Append all messages to log file */
510 if( p_main->p_msg->i_log_file >= 0 )
512 write( p_main->p_msg->i_log_file, psz_msg, strlen( psz_msg ) );
516 /* Free formatted message */
522 static void PrintMsg( intf_msg_item_t *p_msg )
525 * Print messages on screen
527 switch( p_msg->i_type )
529 case INTF_MSG_STD: /* standard messages */
530 case INTF_MSG_DBG: /* debug messages */
531 fprintf( stdout, p_msg->psz_msg );
533 case INTF_MSG_ERR: /* error messages */
534 fprintf( stderr, p_msg->psz_msg );
536 case INTF_MSG_INTF: /* interface messages */
537 intf_ConsolePrint( p_main->p_intf->p_console, p_msg->psz_msg );