]> git.sesse.net Git - vlc/blob - src/misc/messages.c
msg: remove %m hack
[vlc] / src / misc / messages.c
1 /*****************************************************************************
2  * messages.c: messages interface
3  * This library provides an interface to the message queue to be used by other
4  * modules, especially intf modules. See vlc_config.h for output configuration.
5  *****************************************************************************
6  * Copyright (C) 1998-2005 VLC authors and VideoLAN
7  * $Id$
8  *
9  * Authors: Vincent Seguin <seguin@via.ecp.fr>
10  *          Samuel Hocevar <sam@zoy.org>
11  *
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU Lesser General Public License as published by
14  * the Free Software Foundation; either version 2.1 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <stdlib.h>
36 #include <stdarg.h>                                       /* va_list for BSD */
37
38 #include <vlc_common.h>
39 #include <vlc_interface.h>
40 #include <vlc_charset.h>
41 #include "../libvlc.h"
42
43 /**
44  * Emit a log message.
45  * \param obj VLC object emitting the message or NULL
46  * \param type VLC_MSG_* message type (info, error, warning or debug)
47  * \param module name of module from which the message come
48  *               (normally MODULE_STRING)
49  * \param format printf-like message format
50  */
51 void vlc_Log (vlc_object_t *obj, int type, const char *module,
52               const char *format, ... )
53 {
54     va_list args;
55
56     va_start (args, format);
57     vlc_vaLog (obj, type, module, format, args);
58     va_end (args);
59 }
60
61 #ifdef _WIN32
62 static void Win32DebugOutputMsg (void *, int , const vlc_log_t *,
63                                  const char *, va_list);
64 #endif
65
66 /**
67  * Emit a log message. This function is the variable argument list equivalent
68  * to vlc_Log().
69  */
70 void vlc_vaLog (vlc_object_t *obj, int type, const char *module,
71                 const char *format, va_list args)
72 {
73     if (obj != NULL && obj->i_flags & OBJECT_FLAGS_QUIET)
74         return;
75
76     /* Get basename from the module filename */
77     char *p = strrchr(module, '/');
78     if (p != NULL)
79         module = p;
80     p = strchr(module, '.');
81
82     size_t modlen = (p != NULL) ? (p - module) : 1;
83     char modulebuf[modlen + 1];
84     if (p != NULL)
85     {
86         memcpy(modulebuf, module, modlen);
87         modulebuf[modlen] = '\0';
88         module = modulebuf;
89     }
90
91     /* Fill message information fields */
92     vlc_log_t msg;
93
94     msg.i_object_id = (uintptr_t)obj;
95     msg.psz_object_type = (obj != NULL) ? obj->psz_object_type : "generic";
96     msg.psz_module = module;
97     msg.psz_header = NULL;
98
99     for (vlc_object_t *o = obj; o != NULL; o = o->p_parent)
100         if (o->psz_header != NULL)
101         {
102             msg.psz_header = o->psz_header;
103             break;
104         }
105
106     /* Pass message to the callback */
107     libvlc_priv_t *priv = obj ? libvlc_priv (obj->p_libvlc) : NULL;
108
109 #ifdef _WIN32
110     va_list ap;
111
112     va_copy (ap, args);
113     Win32DebugOutputMsg (priv ? &priv->log.verbose : NULL, type, &msg, format, ap);
114     va_end (ap);
115 #endif
116
117     if (priv) {
118         vlc_rwlock_rdlock (&priv->log.lock);
119         priv->log.cb (priv->log.opaque, type, &msg, format, args);
120         vlc_rwlock_unlock (&priv->log.lock);
121     }
122 }
123
124 static const char msg_type[4][9] = { "", " error", " warning", " debug" };
125 #define COL(x,y)  "\033[" #x ";" #y "m"
126 #define RED     COL(31,1)
127 #define GREEN   COL(32,1)
128 #define YELLOW  COL(0,33)
129 #define WHITE   COL(0,1)
130 #define GRAY    "\033[0m"
131 static const char msg_color[4][8] = { WHITE, RED, YELLOW, GRAY };
132
133 /* Display size of a pointer */
134 static const int ptr_width = 2 * /* hex digits */ sizeof(uintptr_t);
135
136 static void PrintColorMsg (void *d, int type, const vlc_log_t *p_item,
137                            const char *format, va_list ap)
138 {
139     FILE *stream = stderr;
140     int verbose = (intptr_t)d;
141
142     if (verbose < 0 || verbose < (type - VLC_MSG_ERR))
143         return;
144
145     int canc = vlc_savecancel ();
146
147     flockfile (stream);
148     utf8_fprintf (stream, "["GREEN"%0*"PRIxPTR""GRAY"] ", ptr_width, p_item->i_object_id);
149     if (p_item->psz_header != NULL)
150         utf8_fprintf (stream, "[%s] ", p_item->psz_header);
151     utf8_fprintf (stream, "%s %s%s: %s", p_item->psz_module,
152                   p_item->psz_object_type, msg_type[type], msg_color[type]);
153     utf8_vfprintf (stream, format, ap);
154     fputs (GRAY"\n", stream);
155 #if defined (_WIN32) || defined (__OS2__)
156     fflush (stream);
157 #endif
158     funlockfile (stream);
159     vlc_restorecancel (canc);
160 }
161
162 static void PrintMsg (void *d, int type, const vlc_log_t *p_item,
163                       const char *format, va_list ap)
164 {
165     FILE *stream = stderr;
166     int verbose = (intptr_t)d;
167
168     if (verbose < 0 || verbose < (type - VLC_MSG_ERR))
169         return;
170
171     int canc = vlc_savecancel ();
172
173     flockfile (stream);
174     utf8_fprintf (stream, "[%0*"PRIxPTR"] ", ptr_width, p_item->i_object_id);
175     if (p_item->psz_header != NULL)
176         utf8_fprintf (stream, "[%s] ", p_item->psz_header);
177     utf8_fprintf (stream, "%s %s%s: ", p_item->psz_module,
178                   p_item->psz_object_type, msg_type[type]);
179     utf8_vfprintf (stream, format, ap);
180     putc_unlocked ('\n', stream);
181 #if defined (_WIN32) || defined (__OS2__)
182     fflush (stream);
183 #endif
184     funlockfile (stream);
185     vlc_restorecancel (canc);
186 }
187
188 #ifdef _WIN32
189 static void Win32DebugOutputMsg (void* d, int type, const vlc_log_t *p_item,
190                                  const char *format, va_list dol)
191 {
192     VLC_UNUSED(p_item);
193
194     const signed char *pverbose = d;
195     if (pverbose && (*pverbose < 0 || *pverbose < (type - VLC_MSG_ERR)))
196         return;
197
198     va_list dol2;
199     va_copy (dol2, dol);
200     int msg_len = vsnprintf(NULL, 0, format, dol2);
201     va_end (dol2);
202
203     if(msg_len <= 0)
204         return;
205
206     char *msg = malloc(msg_len + 1 + 1);
207     if (!msg)
208         return;
209
210     msg_len = vsnprintf(msg, msg_len+1, format, dol);
211     if (msg_len > 0){
212         if(msg[msg_len-1] != '\n'){
213             msg[msg_len] = '\n';
214             msg[msg_len + 1] = '\0';
215         }
216         char* psz_msg = NULL;
217         if(asprintf(&psz_msg, "%s %s%s: %s", p_item->psz_module,
218                     p_item->psz_object_type, msg_type[type], msg) > 0) {
219             wchar_t* wmsg = ToWide(psz_msg);
220             OutputDebugStringW(wmsg);
221             free(wmsg);
222             free(psz_msg);
223         }
224     }
225     free(msg);
226 }
227 #endif
228
229 /**
230  * Sets the message logging callback.
231  * \param cb message callback, or NULL to reset
232  * \param data data pointer for the message callback
233  */
234 void vlc_LogSet (libvlc_int_t *vlc, vlc_log_cb cb, void *opaque)
235 {
236     libvlc_priv_t *priv = libvlc_priv (vlc);
237
238     if (cb == NULL)
239     {
240 #if defined (HAVE_ISATTY) && !defined (_WIN32)
241         if (isatty (STDERR_FILENO) && var_InheritBool (vlc, "color"))
242             cb = PrintColorMsg;
243         else
244 #endif
245             cb = PrintMsg;
246         opaque = (void *)(intptr_t)priv->log.verbose;
247     }
248
249     vlc_rwlock_wrlock (&priv->log.lock);
250     priv->log.cb = cb;
251     priv->log.opaque = opaque;
252     vlc_rwlock_unlock (&priv->log.lock);
253
254     /* Announce who we are */
255     msg_Dbg (vlc, "VLC media player - %s", VERSION_MESSAGE);
256     msg_Dbg (vlc, "%s", COPYRIGHT_MESSAGE);
257     msg_Dbg (vlc, "revision %s", psz_vlc_changeset);
258     msg_Dbg (vlc, "configured with %s", CONFIGURE_LINE);
259 }
260
261 void vlc_LogInit (libvlc_int_t *vlc)
262 {
263     libvlc_priv_t *priv = libvlc_priv (vlc);
264     const char *str;
265
266     if (var_InheritBool (vlc, "quiet"))
267         priv->log.verbose = -1;
268     else
269     if ((str = getenv ("VLC_VERBOSE")) != NULL)
270         priv->log.verbose = atoi (str);
271     else
272         priv->log.verbose = var_InheritInteger (vlc, "verbose");
273
274     vlc_rwlock_init (&priv->log.lock);
275     vlc_LogSet (vlc, NULL, NULL);
276 }
277
278 void vlc_LogDeinit (libvlc_int_t *vlc)
279 {
280     libvlc_priv_t *priv = libvlc_priv (vlc);
281
282     vlc_rwlock_destroy (&priv->log.lock);
283 }