]> git.sesse.net Git - vlc/blob - src/misc/messages.c
8452a5a99d12badd17d259300a0489f65cdbe94a
[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 #include <unistd.h>
38
39 #include <vlc_common.h>
40 #include <vlc_interface.h>
41 #include <vlc_charset.h>
42 #include "../libvlc.h"
43
44 /**
45  * Emit a log message.
46  * \param obj VLC object emitting the message or NULL
47  * \param type VLC_MSG_* message type (info, error, warning or debug)
48  * \param module name of module from which the message come
49  *               (normally MODULE_STRING)
50  * \param format printf-like message format
51  */
52 void vlc_Log (vlc_object_t *obj, int type, const char *module,
53               const char *format, ... )
54 {
55     va_list args;
56
57     va_start (args, format);
58     vlc_vaLog (obj, type, module, format, args);
59     va_end (args);
60 }
61
62 #ifdef _WIN32
63 static void Win32DebugOutputMsg (void *, int , const vlc_log_t *,
64                                  const char *, va_list);
65 #endif
66
67 /**
68  * Emit a log message. This function is the variable argument list equivalent
69  * to vlc_Log().
70  */
71 void vlc_vaLog (vlc_object_t *obj, int type, const char *module,
72                 const char *format, va_list args)
73 {
74     if (obj != NULL && obj->i_flags & OBJECT_FLAGS_QUIET)
75         return;
76
77     /* Get basename from the module filename */
78     char *p = strrchr(module, '/');
79     if (p != NULL)
80         module = p;
81     p = strchr(module, '.');
82
83     size_t modlen = (p != NULL) ? (p - module) : 1;
84     char modulebuf[modlen + 1];
85     if (p != NULL)
86     {
87         memcpy(modulebuf, module, modlen);
88         modulebuf[modlen] = '\0';
89         module = modulebuf;
90     }
91
92     /* Fill message information fields */
93     vlc_log_t msg;
94
95     msg.i_object_id = (uintptr_t)obj;
96     msg.psz_object_type = (obj != NULL) ? obj->psz_object_type : "generic";
97     msg.psz_module = module;
98     msg.psz_header = NULL;
99
100     for (vlc_object_t *o = obj; o != NULL; o = o->p_parent)
101         if (o->psz_header != NULL)
102         {
103             msg.psz_header = o->psz_header;
104             break;
105         }
106
107     /* Pass message to the callback */
108     libvlc_priv_t *priv = obj ? libvlc_priv (obj->p_libvlc) : NULL;
109
110 #ifdef _WIN32
111     va_list ap;
112
113     va_copy (ap, args);
114     Win32DebugOutputMsg (priv ? &priv->log.verbose : NULL, type, &msg, format, ap);
115     va_end (ap);
116 #endif
117
118     if (priv) {
119         vlc_rwlock_rdlock (&priv->log.lock);
120         priv->log.cb (priv->log.opaque, type, &msg, format, args);
121         vlc_rwlock_unlock (&priv->log.lock);
122     }
123 }
124
125 static const char msg_type[4][9] = { "", " error", " warning", " debug" };
126 #define COL(x,y)  "\033[" #x ";" #y "m"
127 #define RED     COL(31,1)
128 #define GREEN   COL(32,1)
129 #define YELLOW  COL(0,33)
130 #define WHITE   COL(0,1)
131 #define GRAY    "\033[0m"
132 static const char msg_color[4][8] = { WHITE, RED, YELLOW, GRAY };
133
134 /* Display size of a pointer */
135 static const int ptr_width = 2 * /* hex digits */ sizeof(uintptr_t);
136
137 static void PrintColorMsg (void *d, int type, const vlc_log_t *p_item,
138                            const char *format, va_list ap)
139 {
140     FILE *stream = stderr;
141     int verbose = (intptr_t)d;
142
143     if (verbose < 0 || verbose < (type - VLC_MSG_ERR))
144         return;
145
146     int canc = vlc_savecancel ();
147
148     flockfile (stream);
149     utf8_fprintf (stream, "["GREEN"%0*"PRIxPTR""GRAY"] ", ptr_width, p_item->i_object_id);
150     if (p_item->psz_header != NULL)
151         utf8_fprintf (stream, "[%s] ", p_item->psz_header);
152     utf8_fprintf (stream, "%s %s%s: %s", p_item->psz_module,
153                   p_item->psz_object_type, msg_type[type], msg_color[type]);
154     utf8_vfprintf (stream, format, ap);
155     fputs (GRAY"\n", stream);
156 #if defined (_WIN32) || defined (__OS2__)
157     fflush (stream);
158 #endif
159     funlockfile (stream);
160     vlc_restorecancel (canc);
161 }
162
163 static void PrintMsg (void *d, int type, const vlc_log_t *p_item,
164                       const char *format, va_list ap)
165 {
166     FILE *stream = stderr;
167     int verbose = (intptr_t)d;
168
169     if (verbose < 0 || verbose < (type - VLC_MSG_ERR))
170         return;
171
172     int canc = vlc_savecancel ();
173
174     flockfile (stream);
175     utf8_fprintf (stream, "[%0*"PRIxPTR"] ", ptr_width, p_item->i_object_id);
176     if (p_item->psz_header != NULL)
177         utf8_fprintf (stream, "[%s] ", p_item->psz_header);
178     utf8_fprintf (stream, "%s %s%s: ", p_item->psz_module,
179                   p_item->psz_object_type, msg_type[type]);
180     utf8_vfprintf (stream, format, ap);
181     putc_unlocked ('\n', stream);
182 #if defined (_WIN32) || defined (__OS2__)
183     fflush (stream);
184 #endif
185     funlockfile (stream);
186     vlc_restorecancel (canc);
187 }
188
189 #ifdef _WIN32
190 static void Win32DebugOutputMsg (void* d, int type, const vlc_log_t *p_item,
191                                  const char *format, va_list dol)
192 {
193     VLC_UNUSED(p_item);
194
195     const signed char *pverbose = d;
196     if (pverbose && (*pverbose < 0 || *pverbose < (type - VLC_MSG_ERR)))
197         return;
198
199     va_list dol2;
200     va_copy (dol2, dol);
201     int msg_len = vsnprintf(NULL, 0, format, dol2);
202     va_end (dol2);
203
204     if(msg_len <= 0)
205         return;
206
207     char *msg = malloc(msg_len + 1 + 1);
208     if (!msg)
209         return;
210
211     msg_len = vsnprintf(msg, msg_len+1, format, dol);
212     if (msg_len > 0){
213         if(msg[msg_len-1] != '\n'){
214             msg[msg_len] = '\n';
215             msg[msg_len + 1] = '\0';
216         }
217         char* psz_msg = NULL;
218         if(asprintf(&psz_msg, "%s %s%s: %s", p_item->psz_module,
219                     p_item->psz_object_type, msg_type[type], msg) > 0) {
220             wchar_t* wmsg = ToWide(psz_msg);
221             OutputDebugStringW(wmsg);
222             free(wmsg);
223             free(psz_msg);
224         }
225     }
226     free(msg);
227 }
228 #endif
229
230 /**
231  * Sets the message logging callback.
232  * \param cb message callback, or NULL to reset
233  * \param data data pointer for the message callback
234  */
235 void vlc_LogSet (libvlc_int_t *vlc, vlc_log_cb cb, void *opaque)
236 {
237     libvlc_priv_t *priv = libvlc_priv (vlc);
238
239     if (cb == NULL)
240     {
241 #if defined (HAVE_ISATTY) && !defined (_WIN32)
242         if (isatty (STDERR_FILENO) && var_InheritBool (vlc, "color"))
243             cb = PrintColorMsg;
244         else
245 #endif
246             cb = PrintMsg;
247         opaque = (void *)(intptr_t)priv->log.verbose;
248     }
249
250     vlc_rwlock_wrlock (&priv->log.lock);
251     priv->log.cb = cb;
252     priv->log.opaque = opaque;
253     vlc_rwlock_unlock (&priv->log.lock);
254
255     /* Announce who we are */
256     msg_Dbg (vlc, "VLC media player - %s", VERSION_MESSAGE);
257     msg_Dbg (vlc, "%s", COPYRIGHT_MESSAGE);
258     msg_Dbg (vlc, "revision %s", psz_vlc_changeset);
259     msg_Dbg (vlc, "configured with %s", CONFIGURE_LINE);
260 }
261
262 void vlc_LogInit (libvlc_int_t *vlc)
263 {
264     libvlc_priv_t *priv = libvlc_priv (vlc);
265     const char *str;
266
267     if (var_InheritBool (vlc, "quiet"))
268         priv->log.verbose = -1;
269     else
270     if ((str = getenv ("VLC_VERBOSE")) != NULL)
271         priv->log.verbose = atoi (str);
272     else
273         priv->log.verbose = var_InheritInteger (vlc, "verbose");
274
275     vlc_rwlock_init (&priv->log.lock);
276     vlc_LogSet (vlc, NULL, NULL);
277 }
278
279 void vlc_LogDeinit (libvlc_int_t *vlc)
280 {
281     libvlc_priv_t *priv = libvlc_priv (vlc);
282
283     vlc_rwlock_destroy (&priv->log.lock);
284 }