]> git.sesse.net Git - vlc/blob - src/interface/intf_msg.c
Removed unused files.
[vlc] / src / interface / intf_msg.c
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
7  * $Id: intf_msg.c,v 1.33 2001/04/30 15:01:00 massiot Exp $
8  *
9  * Authors: Vincent Seguin <seguin@via.ecp.fr>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include "defs.h"
30
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() */
38
39 #include "config.h"
40 #include "common.h"
41 #include "threads.h"
42 #include "mtime.h"
43
44 #include "intf_msg.h"
45 #include "interface.h"
46
47 #include "main.h"
48
49 #ifdef WIN32
50 #define snprintf _snprintf         /* snprintf not defined in mingw32 (bug?) */
51 #endif
52
53 /*****************************************************************************
54  * intf_msg_item_t
55  *****************************************************************************
56  * Store a single message. Messages have a maximal size of INTF_MSG_MSGSIZE.
57  * If TRACE is defined, messages have a date field and debug messages are
58  * printed with a date to allow more precise profiling.
59  *****************************************************************************/
60 typedef struct
61 {
62     int     i_type;                               /* message type, see below */
63     char *  psz_msg;                                   /* the message itself */
64
65 #ifdef TRACE
66     /* Debugging informations - in TRACE mode, debug messages have calling
67      * location informations printed */
68     mtime_t date;                                     /* date of the message */
69     char *  psz_file;               /* file in which the function was called */
70     char *  psz_function;     /* function from which the function was called */
71     int     i_line;                 /* line at which the function was called */
72 #endif
73 } intf_msg_item_t;
74
75 /* Message types */
76 #define INTF_MSG_STD    0                                /* standard message */
77 #define INTF_MSG_ERR    1                                   /* error message */
78 #define INTF_MSG_DBG    3                                   /* debug message */
79 #define INTF_MSG_WARN   4                                  /* warning message*/
80
81
82 /*****************************************************************************
83  * intf_msg_t
84  *****************************************************************************
85  * Store all data requiered by messages interfaces. It has a single reference
86  * int p_main.
87  *****************************************************************************/
88 typedef struct intf_msg_s
89 {
90 #ifdef INTF_MSG_QUEUE
91     /* Message queue */
92     vlc_mutex_t             lock;                      /* message queue lock */
93     int                     i_count;            /* number of messages stored */
94     intf_msg_item_t         msg[INTF_MSG_QSIZE];            /* message queue */
95 #endif
96
97 #ifdef TRACE_LOG
98     /* Log file */
99     FILE *                  p_log_file;                          /* log file */
100 #endif
101
102 #if !defined(INTF_MSG_QUEUE) && !defined(TRACE_LOG)
103     /* If neither messages queue, neither log file is used, then the structure
104      * is empty. However, empty structures are not allowed in C. Therefore, a
105      * dummy integer is used to fill it. */
106     int                     i_dummy;                        /* unused filler */
107 #endif
108 } intf_msg_t;
109
110 /*****************************************************************************
111  * Local prototypes
112  *****************************************************************************/
113
114 static void QueueMsg        ( intf_msg_t *p_msg, int i_type,
115                               char *psz_format, va_list ap );
116 static void PrintMsg        ( intf_msg_item_t *p_msg );
117 #ifdef TRACE
118 static void QueueDbgMsg     ( intf_msg_t *p_msg, char *psz_file,
119                               char *psz_function, int i_line,
120                               char *psz_format, va_list ap );
121 #endif
122 #ifdef INTF_MSG_QUEUE
123 static void FlushLockedMsg  ( intf_msg_t *p_msg );
124 #endif
125
126
127 /*****************************************************************************
128  * intf_MsgCreate: initialize messages interface                         (ok ?)
129  *****************************************************************************
130  * This functions has to be called before any call to other intf_*Msg functions.
131  * It set up the locks and the message queue if it is used.
132  *****************************************************************************/
133 p_intf_msg_t intf_MsgCreate( void )
134 {
135     p_intf_msg_t p_msg;
136
137     /* Allocate structure */
138     p_msg = malloc( sizeof( intf_msg_t ) );
139     if( p_msg == NULL )
140     {
141         errno = ENOMEM;
142     }
143     else
144     {
145 #ifdef INTF_MSG_QUEUE
146     /* Message queue initialization */
147     vlc_mutex_init( &p_msg->lock );                        /* intialize lock */
148     p_msg->i_count = 0;                                    /* queue is empty */
149 #endif
150
151     
152 #ifdef TRACE_LOG
153         /* Log file initialization - on failure, file pointer will be null,
154          * and no log will be issued, but this is not considered as an
155          * error */
156         p_msg->p_log_file = fopen( TRACE_LOG, "w" );
157 #endif
158     }
159     return( p_msg );
160 }
161
162 /*****************************************************************************
163  * intf_MsgDestroy: free resources allocated by intf_InitMsg            (ok ?)
164  *****************************************************************************
165  * This functions prints all messages remaining in queue, then free all the
166  * resources allocated by intf_InitMsg.
167  * No other messages interface functions should be called after this one.
168  *****************************************************************************/
169 void intf_MsgDestroy( void )
170 {
171     intf_FlushMsg();                         /* print all remaining messages */
172
173 #ifdef TRACE_LOG
174     /* Close log file if any */
175     if( p_main->p_msg->p_log_file != NULL )
176     {
177         fclose( p_main->p_msg->p_log_file );
178     }
179 #endif
180
181 #ifdef INTF_MSG_QUEUE
182     /* destroy lock */
183     vlc_mutex_destroy( &p_main->p_msg->lock );
184 #endif
185     
186     /* Free structure */
187     free( p_main->p_msg );
188 }
189
190 /*****************************************************************************
191  * intf_Msg: print a message                                             (ok ?)
192  *****************************************************************************
193  * This function queue a message for later printing, or print it immediately
194  * if the queue isn't used.
195  *****************************************************************************/
196 void intf_Msg( char *psz_format, ... )
197 {
198     va_list ap;
199
200     va_start( ap, psz_format );
201     QueueMsg( p_main->p_msg, INTF_MSG_STD, psz_format, ap );
202     va_end( ap );
203 }
204
205 /*****************************************************************************
206  * intf_ErrMsg : print an error message                                  (ok ?)
207  *****************************************************************************
208  * This function is the same as intf_Msg, except that it prints its messages
209  * on stderr.
210  *****************************************************************************/
211 void intf_ErrMsg( char *psz_format, ... )
212 {
213     va_list ap;
214
215     va_start( ap, psz_format );
216     QueueMsg( p_main->p_msg, INTF_MSG_ERR, psz_format, ap );
217     va_end( ap );
218 }
219
220 /*****************************************************************************
221  * intf_WarnMsg : print a warning message
222  *****************************************************************************
223  * This function is the same as intf_Msg, except that it concerns warning
224  * messages for testing purpose.
225  *****************************************************************************/
226 void intf_WarnMsg( int i_level, char *psz_format, ... )
227 {
228     va_list ap;
229     
230     if( i_level >= p_main->i_warning_level )
231     {
232         va_start( ap, psz_format );
233         QueueMsg( p_main->p_msg, INTF_MSG_WARN, psz_format, ap );
234         va_end( ap );
235     }
236 }
237
238
239 /*****************************************************************************
240  * _intf_DbgMsg: print a debugging message                               (ok ?)
241  *****************************************************************************
242  * This function prints a debugging message. Compared to other intf_*Msg
243  * functions, it is only defined if TRACE is defined and require a file name,
244  * a function name and a line number as additionnal debugging informations. It
245  * also prints a debugging header for each received line.
246  *****************************************************************************/
247 #ifdef TRACE
248 void _intf_DbgMsg( char *psz_file, char *psz_function, int i_line,
249                    char *psz_format, ...)
250 {
251     va_list ap;
252
253     va_start( ap, psz_format );
254     QueueDbgMsg( p_main->p_msg, psz_file, psz_function, i_line,
255                  psz_format, ap );
256     va_end( ap );
257 }
258 #endif
259
260 /*****************************************************************************
261  * intf_MsgImm: print a message                                          (ok ?)
262  *****************************************************************************
263  * This function prints a message immediately. If the queue is used, all
264  * waiting messages are also printed.
265  *****************************************************************************/
266 void intf_MsgImm( char *psz_format, ... )
267 {
268     va_list ap;
269
270     va_start( ap, psz_format );
271     QueueMsg( p_main->p_msg, INTF_MSG_STD, psz_format, ap );
272     va_end( ap );
273     intf_FlushMsg();
274 }
275
276 /*****************************************************************************
277  * intf_ErrMsgImm: print an error message immediately                    (ok ?)
278  *****************************************************************************
279  * This function is the same as intf_MsgImm, except that it prints its message
280  * on stderr.
281  *****************************************************************************/
282 void intf_ErrMsgImm(char *psz_format, ...)
283 {
284     va_list ap;
285
286     va_start( ap, psz_format );
287     QueueMsg( p_main->p_msg, INTF_MSG_ERR, psz_format, ap );
288     va_end( ap );
289     intf_FlushMsg();
290 }
291
292 /*****************************************************************************
293  * intf_WarnMsgImm : print a warning message
294  *****************************************************************************
295  * This function is the same as intf_MsgImm, except that it concerns warning
296  * messages for testing purpose.
297  *****************************************************************************/
298 void intf_WarnMsgImm( int i_level, char *psz_format, ... )
299 {
300     va_list ap;
301
302     if( i_level >= p_main->i_warning_level )
303     {
304         va_start( ap, psz_format );
305         QueueMsg( p_main->p_msg, INTF_MSG_WARN, psz_format, ap );
306         va_end( ap );
307     }
308     intf_FlushMsg();
309 }
310
311
312
313 /*****************************************************************************
314  * _intf_DbgMsgImm: print a debugging message immediately                (ok ?)
315  *****************************************************************************
316  * This function is the same as intf_DbgMsgImm, except that it prints its
317  * message immediately. It should only be called through the macro
318  * intf_DbgMsgImm().
319  *****************************************************************************/
320 #ifdef TRACE
321 void _intf_DbgMsgImm( char *psz_file, char *psz_function, int i_line,
322                       char *psz_format, ...)
323 {
324     va_list ap;
325
326     va_start( ap, psz_format );
327     QueueDbgMsg( p_main->p_msg, psz_file, psz_function, i_line,
328                  psz_format, ap );
329     va_end( ap );
330     intf_FlushMsg();
331 }
332 #endif
333
334 /*****************************************************************************
335  * intf_WarnHexDump : print a hexadecimal dump of a memory area
336  *****************************************************************************
337  * This is convenient for debugging purposes.
338  *****************************************************************************/
339 void intf_WarnHexDump( int i_level, void *p_data, int i_size )
340 {
341     int   i_index = 0;
342     int   i_subindex;
343     char  p_string[75];
344     u8   *p_area = (u8 *)p_data;
345
346     intf_WarnMsg( i_level, "hexdump: dumping %i bytes at address %p",
347                            i_size, p_data );
348
349     while( i_index < i_size )
350     {
351         i_subindex = 0;
352
353         while( ( i_subindex < 24 ) && ( i_index + i_subindex < i_size ) )
354         {
355             sprintf( p_string + 3 * i_subindex, "%.2x ",
356                      p_area[ i_index + i_subindex ] );
357
358             i_subindex++;
359         }
360
361         /* -1 here is safe because we know we printed at least one */
362         p_string[ 3 * i_subindex - 1 ] = '\0';
363         intf_WarnMsg( i_level, "0x%.4x: %s", i_index, p_string );
364
365         i_index += 24;
366     }
367
368     intf_WarnMsg( i_level, "hexdump: %i bytes dumped", i_size );
369 }
370
371 /*****************************************************************************
372  * intf_FlushMsg                                                        (ok ?)
373  *****************************************************************************
374  * Print all messages remaining in queue: get lock and call FlushLockedMsg.
375  * This function does nothing if the message queue isn't used.
376  * This function is only implemented if message queue is used. If not, it is
377  * an empty macro.
378  *****************************************************************************/
379 #ifdef INTF_MSG_QUEUE
380 void intf_FlushMsg( void )
381 {
382     vlc_mutex_lock( &p_main->p_msg->lock );                      /* get lock */
383     FlushLockedMsg( p_main->p_msg );                       /* flush messages */
384     vlc_mutex_unlock( &p_main->p_msg->lock );              /* give lock back */
385 }
386 #endif
387
388 /* following functions are local */
389
390 /*****************************************************************************
391  * QueueMsg: add a message to a queue
392  *****************************************************************************
393  * This function provide basic functionnalities to other intf_*Msg functions.
394  * It add a message to a queue (after having printed all stored messages if it
395  * is full. If the message can't be converted to string in memory, it exit the
396  * program. If the queue is not used, it prints the message immediately.
397  *****************************************************************************/
398 static void QueueMsg( intf_msg_t *p_msg, int i_type, char *psz_format, va_list ap )
399 {
400     char *                  psz_str;             /* formatted message string */
401     intf_msg_item_t *       p_msg_item;                /* pointer to message */
402
403 #ifndef INTF_MSG_QUEUE /*................................... instant mode ...*/
404     intf_msg_item_t         msg_item;                             /* message */
405     p_msg_item =           &msg_item;
406 #endif /*....................................................................*/
407
408     /*
409      * Convert message to string
410      */
411 #ifdef HAVE_VASPRINTF
412     vasprintf( &psz_str, psz_format, ap );
413 #else
414     psz_str = (char*) malloc( strlen(psz_format) + INTF_MAX_MSG_SIZE );
415 #endif
416     if( psz_str == NULL )
417     {
418         fprintf(stderr, "warning: can't store following message (%s): ",
419                 strerror(errno) );
420         vfprintf(stderr, psz_format, ap );
421         fprintf(stderr, "\n" );
422         exit( errno );
423     }
424 #ifdef HAVE_VASPRINTF
425 #else
426     vsprintf( psz_str, psz_format, ap );
427 #endif
428
429 #ifdef INTF_MSG_QUEUE /*...................................... queue mode ...*/
430     vlc_mutex_lock( &p_msg->lock );                              /* get lock */
431     if( p_msg->i_count == INTF_MSG_QSIZE )          /* flush queue if needed */
432     {
433 #ifdef DEBUG               /* in debug mode, queue overflow causes a warning */
434         fprintf(stderr, "warning: message queue overflow\n" );
435 #endif
436         FlushLockedMsg( p_msg );
437     }
438     p_msg_item = p_msg->msg + p_msg->i_count++;            /* select message */
439 #endif /*.............................................. end of queue mode ...*/
440
441     /*
442      * Fill message information fields
443      */
444     p_msg_item->i_type =     i_type;
445     p_msg_item->psz_msg =    psz_str;
446 #ifdef TRACE    
447     p_msg_item->date =       mdate();
448 #endif
449
450 #ifdef INTF_MSG_QUEUE /*......................................... queue mode */
451     vlc_mutex_unlock( &p_msg->lock );                      /* give lock back */
452 #else /*....................................................... instant mode */
453     PrintMsg( p_msg_item );                                 /* print message */
454     free( psz_str );                                    /* free message data */
455 #endif /*....................................................................*/
456 }
457
458 /*****************************************************************************
459  * QueueDbgMsg: add a message to a queue with debugging informations
460  *****************************************************************************
461  * This function is the same as QueueMsg, except that it is only defined when
462  * TRACE is define, and require additionnal debugging informations.
463  *****************************************************************************/
464 #ifdef TRACE
465 static void QueueDbgMsg(intf_msg_t *p_msg, char *psz_file, char *psz_function,
466                         int i_line, char *psz_format, va_list ap)
467 {
468     char *                  psz_str;             /* formatted message string */
469     intf_msg_item_t *       p_msg_item;                /* pointer to message */
470
471 #ifndef INTF_MSG_QUEUE /*................................... instant mode ...*/
472     intf_msg_item_t         msg_item;                             /* message */
473     p_msg_item =           &msg_item;
474 #endif /*....................................................................*/
475
476     /*
477      * Convert message to string
478      */
479 #ifdef HAVE_VASPRINTF
480     vasprintf( &psz_str, psz_format, ap );
481 #else
482     psz_str = (char*) malloc( INTF_MAX_MSG_SIZE );
483     vsprintf( psz_str, psz_format, ap );
484 #endif
485     if( psz_str == NULL )
486     {
487         fprintf(stderr, "warning: can't store following message (%s): ",
488                 strerror(errno) );
489         fprintf(stderr, INTF_MSG_DBG_FORMAT, psz_file, psz_function, i_line );
490         vfprintf(stderr, psz_format, ap );
491         fprintf(stderr, "\n" );
492         exit( errno );
493     }
494
495 #ifdef INTF_MSG_QUEUE /*...................................... queue mode ...*/
496     vlc_mutex_lock( &p_msg->lock );                              /* get lock */
497     if( p_msg->i_count == INTF_MSG_QSIZE )          /* flush queue if needed */
498     {
499         fprintf(stderr, "warning: message queue overflow\n" );
500         FlushLockedMsg( p_msg );
501     }
502     p_msg_item = p_msg->msg + p_msg->i_count++;            /* select message */
503 #endif /*.............................................. end of queue mode ...*/
504
505     /*
506      * Fill message information fields
507      */
508     p_msg_item->i_type =       INTF_MSG_DBG;
509     p_msg_item->psz_msg =      psz_str;
510     p_msg_item->psz_file =     psz_file;
511     p_msg_item->psz_function = psz_function;
512     p_msg_item->i_line =       i_line;
513     p_msg_item->date =         mdate();
514
515 #ifdef INTF_MSG_QUEUE /*......................................... queue mode */
516     vlc_mutex_unlock( &p_msg->lock );                      /* give lock back */
517 #else /*....................................................... instant mode */
518     PrintMsg( p_msg_item );                                 /* print message */
519     free( psz_str );                                    /* free message data */
520 #endif /*....................................................................*/
521 }
522 #endif
523
524 /*****************************************************************************
525  * FlushLockedMsg                                                       (ok ?)
526  *****************************************************************************
527  * Print all messages remaining in queue. MESSAGE QUEUE MUST BE LOCKED, since
528  * this function does not check the lock. This function is only defined if
529  * INTF_MSG_QUEUE is defined.
530  *****************************************************************************/
531 #ifdef INTF_MSG_QUEUE
532 static void FlushLockedMsg ( intf_msg_t *p_msg )
533 {
534     int i_index;
535
536     for( i_index = 0; i_index < p_msg->i_count; i_index++ )
537     {
538         /* Print message and free message data */
539         PrintMsg( &p_msg->msg[i_index] );
540         free( p_msg->msg[i_index].psz_msg );
541     }
542
543     p_msg->i_count = 0;
544 }
545 #endif
546
547 /*****************************************************************************
548  * PrintMsg: print a message                                             (ok ?)
549  *****************************************************************************
550  * Print a single message. The message data is not freed. This function exists
551  * in two version. The TRACE version prints a date with each message, and is
552  * able to log messages (if TRACE_LOG is defined).
553  * The normal one just prints messages to the screen.
554  *****************************************************************************/
555 #ifdef TRACE
556
557 static void PrintMsg( intf_msg_item_t *p_msg )
558 {
559     char    psz_date[MSTRTIME_MAX_SIZE];            /* formatted time buffer */
560     int     i_msg_len = MSTRTIME_MAX_SIZE + strlen(p_msg->psz_msg) + 200;
561     char   *psz_msg;                                       /* message buffer */
562
563     psz_msg = malloc( sizeof( char ) * i_msg_len );
564
565     /* Check if allocation succeeded */
566     if( psz_msg == NULL )
567     {
568         fprintf( stderr, "error: not enough memory for message %s\n",
569                  p_msg->psz_msg );
570         return;
571     }
572
573     /* Format message - the message is formatted here because in case the log
574      * file is used, it avoids another format string parsing */
575     switch( p_msg->i_type )
576     {
577     case INTF_MSG_STD:                                   /* regular messages */
578     case INTF_MSG_ERR:
579         snprintf( psz_msg, i_msg_len, "%s", p_msg->psz_msg );
580         break;
581
582     case INTF_MSG_WARN:                                   /* Warning message */
583         mstrtime( psz_date, p_msg->date );
584         snprintf( psz_msg, i_msg_len, "(%s) %s",
585                   psz_date, p_msg->psz_msg );
586
587         break;
588         
589     case INTF_MSG_DBG:                                     /* debug messages */
590         mstrtime( psz_date, p_msg->date );
591         snprintf( psz_msg, i_msg_len, "(%s) " INTF_MSG_DBG_FORMAT "%s",
592                   psz_date, p_msg->psz_file, p_msg->psz_function, p_msg->i_line,
593                   p_msg->psz_msg );
594         break;
595     }
596
597     /*
598      * Print messages
599      */
600     switch( p_msg->i_type )
601     {
602     case INTF_MSG_STD:                                  /* standard messages */
603         fprintf( stdout, "%s\n", psz_msg );
604         break;
605     case INTF_MSG_ERR:                                     /* error messages */
606     case INTF_MSG_WARN:
607 #ifndef TRACE_LOG_ONLY
608     case INTF_MSG_DBG:                                 /* debugging messages */
609 #endif
610         fprintf( stderr, "%s\n", psz_msg );
611         break;
612     }
613
614 #ifdef TRACE_LOG
615     /* Append all messages to log file */
616     if( p_main->p_msg->p_log_file != NULL )
617     {
618         fwrite( psz_msg, strlen( psz_msg ), 1, p_main->p_msg->p_log_file );
619         fwrite( "\n", 1, 1, p_main->p_msg->p_log_file );
620     }
621 #endif
622
623     /* Free the message */
624     free( psz_msg );
625 }
626
627 #else
628
629 static void PrintMsg( intf_msg_item_t *p_msg )
630 {
631     /*
632      * Print messages on screen
633      */
634     switch( p_msg->i_type )
635     {
636     case INTF_MSG_STD:                                  /* standard messages */
637     case INTF_MSG_DBG:                                     /* debug messages */
638         fprintf( stdout, "%s\n", p_msg->psz_msg );
639         break;
640     case INTF_MSG_ERR:                                     /* error messages */
641     case INTF_MSG_WARN:
642         fprintf( stderr, "%s\n", p_msg->psz_msg );        /* warning message */
643         break;
644     }
645 }
646
647 #endif
648