1 /*****************************************************************************
2 * intf_msg.c: messages interface
3 * This library provides basic functions for threads to interact with user
4 * interface, such as message output. See config.h for output configuration.
5 *****************************************************************************
6 * Copyright (C) 1998, 1999, 2000 VideoLAN
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public
21 * License along with this program; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
31 #include <errno.h> /* errno */
32 #include <fcntl.h> /* O_CREAT, O_TRUNC, O_WRONLY, O_SYNC */
33 #include <stdio.h> /* required */
34 #include <stdarg.h> /* va_list for BSD */
35 #include <stdlib.h> /* malloc() */
36 #include <string.h> /* strerror() */
37 #include <unistd.h> /* close(), write() */
45 #include "interface.h"
46 #include "intf_console.h"
50 /*****************************************************************************
52 *****************************************************************************
53 * Store a single message. Messages have a maximal size of INTF_MSG_MSGSIZE.
54 * If DEBUG is defined, messages have a date field and debug messages are
55 * printed with a date to allow more precise profiling.
56 *****************************************************************************/
59 int i_type; /* message type, see below */
60 char * psz_msg; /* the message itself */
63 /* Debugging informations - in DEBUG mode, debug messages have calling
64 * location informations printed */
65 mtime_t date; /* date of the message */
66 char * psz_file; /* file in which the function was called */
67 char * psz_function; /* function from which the function was called */
68 int i_line; /* line at which the function was called */
73 #define INTF_MSG_STD 0 /* standard message */
74 #define INTF_MSG_ERR 1 /* error message */
75 #define INTF_MSG_INTF 2 /* interface message */
76 #define INTF_MSG_DBG 3 /* debug message */
78 /*****************************************************************************
80 *****************************************************************************
81 * Store all data requiered by messages interfaces. It has a single reference
83 *****************************************************************************/
84 typedef struct intf_msg_s
88 vlc_mutex_t lock; /* message queue lock */
89 int i_count; /* number of messages stored */
90 intf_msg_item_t msg[INTF_MSG_QSIZE]; /* message queue */
95 int i_log_file; /* log file */
98 #if !defined(INTF_MSG_QUEUE) && !defined(DEBUG_LOG)
99 /* If neither messages queue, neither log file is used, then the structure
100 * is empty. However, empty structures are not allowed in C. Therefore, a
101 * dummy integer is used to fill it. */
102 int i_dummy; /* unused filler */
106 /*****************************************************************************
108 *****************************************************************************/
110 static void QueueMsg ( intf_msg_t *p_msg, int i_type,
111 char *psz_format, va_list ap );
112 static void PrintMsg ( intf_msg_item_t *p_msg );
114 static void QueueDbgMsg ( intf_msg_t *p_msg, char *psz_file,
115 char *psz_function, int i_line,
116 char *psz_format, va_list ap );
118 #ifdef INTF_MSG_QUEUE
119 static void FlushLockedMsg ( intf_msg_t *p_msg );
123 /*****************************************************************************
124 * intf_MsgCreate: initialize messages interface (ok ?)
125 *****************************************************************************
126 * This functions has to be called before any call to other intf_*Msg functions.
127 * It set up the locks and the message queue if it is used.
128 *****************************************************************************/
129 p_intf_msg_t intf_MsgCreate( void )
133 /* Allocate structure */
134 p_msg = malloc( sizeof( intf_msg_t ) );
141 #ifdef INTF_MSG_QUEUE
142 /* Message queue initialization */
143 vlc_mutex_init( &p_msg->lock ); /* intialize lock */
144 p_msg->i_count = 0; /* queue is empty */
148 /* Log file initialization - on failure, file pointer will be null,
149 * and no log will be issued, but this is not considered as an
151 p_msg->i_log_file = open( DEBUG_LOG, O_CREAT | O_TRUNC |
164 /*****************************************************************************
165 * intf_MsgDestroy: free resources allocated by intf_InitMsg (ok ?)
166 *****************************************************************************
167 * This functions prints all messages remaining in queue, then free all the
168 * resources allocated by intf_InitMsg.
169 * No other messages interface functions should be called after this one.
170 *****************************************************************************/
171 void intf_MsgDestroy( void )
173 intf_FlushMsg(); /* print all remaining messages */
176 /* Close log file if any */
177 if( p_main->p_msg->i_log_file >= 0 )
179 close( p_main->p_msg->i_log_file );
184 free( p_main->p_msg );
187 /*****************************************************************************
188 * intf_Msg: print a message (ok ?)
189 *****************************************************************************
190 * This function queue a message for later printing, or print it immediately
191 * if the queue isn't used.
192 *****************************************************************************/
193 void intf_Msg( char *psz_format, ... )
197 va_start( ap, psz_format );
198 QueueMsg( p_main->p_msg, INTF_MSG_STD, psz_format, ap );
202 /*****************************************************************************
203 * intf_ErrMsg : print an error message (ok ?)
204 *****************************************************************************
205 * This function is the same as intf_Msg, except that it prints its messages
207 *****************************************************************************/
208 void intf_ErrMsg( char *psz_format, ...)
212 va_start( ap, psz_format );
213 QueueMsg( p_main->p_msg, INTF_MSG_ERR, psz_format, ap );
217 /*****************************************************************************
218 * intf_IntfMsg : print an interface message (ok ?)
219 *****************************************************************************
220 * In opposition to all other intf_*Msg function, this function does not print
221 * it's message on default terminal (stdout or stderr), but send it to
222 * interface (in fact to the X11 console). This means that the interface MUST
223 * be initialized and a X11 console openned before this function is used, and
224 * that once the console is closed, this call is vorbidden.
225 * Practically, only the interface thread itself should call this function, and
226 * flush all messages before intf_CloseX11Console() is called.
227 *****************************************************************************/
228 void intf_IntfMsg(char *psz_format, ...)
232 va_start( ap, psz_format );
233 QueueMsg( p_main->p_msg, INTF_MSG_INTF, psz_format, ap );
237 /*****************************************************************************
238 * _intf_DbgMsg: print a debugging message (ok ?)
239 *****************************************************************************
240 * This function prints a debugging message. Compared to other intf_*Msg
241 * functions, it is only defined if DEBUG is defined and require a file name,
242 * a function name and a line number as additionnal debugging informations. It
243 * also prints a debugging header for each received line.
244 *****************************************************************************/
246 void _intf_DbgMsg( char *psz_file, char *psz_function, int i_line,
247 char *psz_format, ...)
251 va_start( ap, psz_format );
252 QueueDbgMsg( p_main->p_msg, psz_file, psz_function, i_line,
258 /*****************************************************************************
259 * intf_ErrMsgImm: print a message (ok ?)
260 *****************************************************************************
261 * This function prints a message immediately. If the queue is used, all
262 * waiting messages are also printed.
263 *****************************************************************************/
264 void intf_MsgImm( char *psz_format, ... )
268 va_start( ap, psz_format );
269 QueueMsg( p_main->p_msg, INTF_MSG_STD, psz_format, ap );
274 /*****************************************************************************
275 * intf_ErrMsgImm: print an error message immediately (ok ?)
276 *****************************************************************************
277 * This function is the same as intf_MsgImm, except that it prints its message
279 *****************************************************************************/
280 void intf_ErrMsgImm(char *psz_format, ...)
284 va_start( ap, psz_format );
285 QueueMsg( p_main->p_msg, INTF_MSG_ERR, psz_format, ap );
290 /*****************************************************************************
291 * _intf_DbgMsgImm: print a debugging message immediately (ok ?)
292 *****************************************************************************
293 * This function is the same as intf_DbgMsgImm, except that it prints its
294 * message immediately. It should only be called through the macro
296 *****************************************************************************/
298 void _intf_DbgMsgImm( char *psz_file, char *psz_function, int i_line,
299 char *psz_format, ...)
303 va_start( ap, psz_format );
304 QueueDbgMsg( p_main->p_msg, psz_file, psz_function, i_line,
311 /*****************************************************************************
312 * intf_FlushMsg (ok ?)
313 *****************************************************************************
314 * Print all messages remaining in queue: get lock and call FlushLockedMsg.
315 * This function does nothing if the message queue isn't used.
316 * This function is only implemented if message queue is used. If not, it is an
318 *****************************************************************************/
319 #ifdef INTF_MSG_QUEUE
320 void intf_FlushMsg( void )
322 vlc_mutex_lock( &p_main->p_msg->lock ); /* get lock */
323 FlushLockedMsg( p_main->p_msg ); /* flush messages */
324 vlc_mutex_unlock( &p_main->p_msg->lock ); /* give lock back */
328 /* following functions are local */
330 /*****************************************************************************
331 * QueueMsg: add a message to a queue
332 *****************************************************************************
333 * This function provide basic functionnalities to other intf_*Msg functions.
334 * It add a message to a queue (after having printed all stored messages if it
335 * is full. If the message can't be converted to string in memory, it exit the
336 * program. If the queue is not used, it prints the message immediately.
337 *****************************************************************************/
338 static void QueueMsg( intf_msg_t *p_msg, int i_type, char *psz_format, va_list ap )
340 char * psz_str; /* formatted message string */
341 intf_msg_item_t * p_msg_item; /* pointer to message */
343 #ifndef INTF_MSG_QUEUE /*..................................... instant mode ...*/
344 intf_msg_item_t msg_item; /* message */
345 p_msg_item = &msg_item;
346 #endif /*......................................................................*/
349 * Convert message to string
352 psz_str = (char*) malloc( strlen(psz_format) + INTF_MAX_MSG_SIZE );
353 vsprintf( psz_str, psz_format, ap );
355 vasprintf( &psz_str, psz_format, ap );
357 if( psz_str == NULL )
359 fprintf(stderr, "warning: can't store following message (%s): ",
361 vfprintf(stderr, psz_format, ap );
365 #ifdef INTF_MSG_QUEUE /*........................................ queue mode ...*/
366 vlc_mutex_lock( &p_msg->lock ); /* get lock */
367 if( p_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
369 #ifdef DEBUG /* in debug mode, queue overflow causes a warning */
370 fprintf(stderr, "warning: message queue overflow\n" );
372 FlushLockedMsg( p_msg );
374 p_msg_item = p_msg->msg + p_msg->i_count++; /* select message */
375 #endif /*................................................ end of queue mode ...*/
378 * Fill message information fields
380 p_msg_item->i_type = i_type;
381 p_msg_item->psz_msg = psz_str;
383 #ifdef INTF_MSG_QUEUE /*........................................... queue mode */
384 vlc_mutex_unlock( &p_msg->lock ); /* give lock back */
385 #else /*......................................................... instant mode */
386 PrintMsg( p_msg_item ); /* print message */
387 free( psz_str ); /* free message data */
388 #endif /*......................................................................*/
391 /*****************************************************************************
392 * QueueDbgMsg: add a message to a queue with debugging informations
393 *****************************************************************************
394 * This function is the same as QueueMsg, except that it is only defined when
395 * DEBUG is define, and require additionnal debugging informations.
396 *****************************************************************************/
398 static void QueueDbgMsg(intf_msg_t *p_msg, char *psz_file, char *psz_function,
399 int i_line, char *psz_format, va_list ap)
401 char * psz_str; /* formatted message string */
402 intf_msg_item_t * p_msg_item; /* pointer to message */
404 #ifndef INTF_MSG_QUEUE /*..................................... instant mode ...*/
405 intf_msg_item_t msg_item; /* message */
406 p_msg_item = &msg_item;
407 #endif /*......................................................................*/
410 * Convert message to string
413 psz_str = (char*) malloc( INTF_MAX_MSG_SIZE );
414 vsprintf( psz_str, psz_format, ap );
416 vasprintf( &psz_str, psz_format, ap );
418 if( psz_str == NULL )
420 fprintf(stderr, "warning: can't store following message (%s): ",
422 fprintf(stderr, INTF_MSG_DBG_FORMAT, psz_file, psz_function, i_line );
423 vfprintf(stderr, psz_format, ap );
427 #ifdef INTF_MSG_QUEUE /*........................................ queue mode ...*/
428 vlc_mutex_lock( &p_msg->lock ); /* get lock */
429 if( p_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
431 #ifdef DEBUG /* in debug mode, queue overflow causes a warning */
432 fprintf(stderr, "warning: message queue overflow\n" );
434 FlushLockedMsg( p_msg );
436 p_msg_item = p_msg->msg + p_msg->i_count++; /* select message */
437 #endif /*................................................ end of queue mode ...*/
440 * Fill message information fields
442 p_msg_item->i_type = INTF_MSG_DBG;
443 p_msg_item->psz_msg = psz_str;
444 p_msg_item->psz_file = psz_file;
445 p_msg_item->psz_function = psz_function;
446 p_msg_item->i_line = i_line;
447 p_msg_item->date = mdate();
449 #ifdef INTF_MSG_QUEUE /*........................................... queue mode */
450 vlc_mutex_unlock( &p_msg->lock ); /* give lock back */
451 #else /*......................................................... instant mode */
452 PrintMsg( p_msg_item ); /* print message */
453 free( psz_str ); /* free message data */
454 #endif /*......................................................................*/
458 /*****************************************************************************
459 * FlushLockedMsg (ok ?)
460 *****************************************************************************
461 * Print all messages remaining in queue. MESSAGE QUEUE MUST BE LOCKED, since
462 * this function does not check the lock. This function is only defined if
463 * INTF_MSG_QUEUE is defined.
464 *****************************************************************************/
465 #ifdef INTF_MSG_QUEUE
466 static void FlushLockedMsg ( intf_msg_t *p_msg )
470 for( i_index = 0; i_index < p_msg->i_count; i_index++ )
472 /* Print message and free message data */
473 PrintMsg( &p_msg->msg[i_index] );
474 free( p_msg->msg[i_index].psz_msg );
481 /*****************************************************************************
482 * PrintMsg: print a message (ok ?)
483 *****************************************************************************
484 * Print a single message. The message data is not freed. This function exists
485 * in two version. The DEBUG version prints a date with each message, and is
486 * able to log messages (if DEBUG_LOG is defined).
487 * The normal one just prints messages to the screen.
488 *****************************************************************************/
491 static void PrintMsg( intf_msg_item_t *p_msg )
493 char psz_date[MSTRTIME_MAX_SIZE]; /* formatted time buffer */
494 char * psz_msg; /* message buffer */
496 /* Format message - the message is formatted here because in case the log
497 * file is used, it avoids another format string parsing */
498 switch( p_msg->i_type )
500 case INTF_MSG_STD: /* regular messages */
502 asprintf( &psz_msg, "%s", p_msg->psz_msg );
505 case INTF_MSG_INTF: /* interface messages */
506 asprintf( &psz_msg, "%s", p_msg->psz_msg );
509 case INTF_MSG_DBG: /* debug messages */
510 mstrtime( psz_date, p_msg->date );
511 asprintf( &psz_msg, "(%s) " INTF_MSG_DBG_FORMAT "%s",
512 psz_date, p_msg->psz_file, p_msg->psz_function, p_msg->i_line,
517 /* Check if formatting function suceeded */
518 if( psz_msg == NULL )
520 fprintf( stderr, "error: can not format message (%s): %s\n",
521 strerror( errno ), p_msg->psz_msg );
528 switch( p_msg->i_type )
530 case INTF_MSG_STD: /* standard messages */
531 fprintf( stdout, psz_msg );
533 case INTF_MSG_ERR: /* error messages */
534 #ifndef DEBUG_LOG_ONLY
535 case INTF_MSG_DBG: /* debugging messages */
537 fprintf( stderr, psz_msg );
539 case INTF_MSG_INTF: /* interface messages */
540 intf_ConsolePrint( p_main->p_intf->p_console, psz_msg );
545 /* Append all messages to log file */
546 if( p_main->p_msg->i_log_file >= 0 )
548 write( p_main->p_msg->i_log_file, psz_msg, strlen( psz_msg ) );
552 /* Free formatted message */
558 static void PrintMsg( intf_msg_item_t *p_msg )
561 * Print messages on screen
563 switch( p_msg->i_type )
565 case INTF_MSG_STD: /* standard messages */
566 case INTF_MSG_DBG: /* debug messages */
567 fprintf( stdout, p_msg->psz_msg );
569 case INTF_MSG_ERR: /* error messages */
570 fprintf( stderr, p_msg->psz_msg );
572 case INTF_MSG_INTF: /* interface messages */
573 intf_ConsolePrint( p_main->p_intf->p_console, p_msg->psz_msg );