Fix vf_tcdump's compilation
[mplayer/kovensky.git] / mp_msg.c
blob6e40e0038e05ffea54a62e89574f1dc624e77cec
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <string.h>
24 #include "config.h"
25 #include "osdep/getch2.h"
27 #ifdef CONFIG_TRANSLATION
28 #include <locale.h>
29 #include <libintl.h>
30 #endif
32 #ifdef CONFIG_ICONV
33 #include <iconv.h>
34 #include <errno.h>
35 #endif
37 #include "mp_msg.h"
39 #ifdef _WIN32
40 #define WIN32_LEAN_AND_MEAN
41 #include <windows.h>
42 #include <io.h>
43 short stdoutAttrs = 0;
44 HANDLE hConOut = INVALID_HANDLE_VALUE;
45 static const unsigned char ansi2win32[10]=
48 FOREGROUND_RED,
49 FOREGROUND_GREEN,
50 FOREGROUND_GREEN | FOREGROUND_RED,
51 FOREGROUND_BLUE,
52 FOREGROUND_BLUE | FOREGROUND_RED,
53 FOREGROUND_BLUE | FOREGROUND_GREEN,
54 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED,
55 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED,
56 FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
58 #endif
60 /* maximum message length of mp_msg */
61 #define MSGSIZE_MAX 3072
63 int mp_msg_levels[MSGT_MAX]; // verbose level of this module. initialized to -2
64 int mp_msg_level_all = MSGL_STATUS;
65 int verbose = 0;
66 int mp_msg_color = 0;
67 int mp_msg_module = 0;
68 #ifdef CONFIG_ICONV
69 char *mp_msg_charset = NULL;
70 static char *old_charset = NULL;
71 static iconv_t msgiconv;
72 #endif
74 const char* filename_recode(const char* filename)
76 #if !defined(CONFIG_ICONV) || !defined(MSG_CHARSET)
77 return filename;
78 #else
79 static iconv_t inv_msgiconv = (iconv_t)(-1);
80 static char recoded_filename[MSGSIZE_MAX];
81 size_t filename_len, max_path;
82 char* precoded;
83 if (!mp_msg_charset ||
84 !strcasecmp(mp_msg_charset, MSG_CHARSET) ||
85 !strcasecmp(mp_msg_charset, "noconv"))
86 return filename;
87 if (inv_msgiconv == (iconv_t)(-1)) {
88 inv_msgiconv = iconv_open(MSG_CHARSET, mp_msg_charset);
89 if (inv_msgiconv == (iconv_t)(-1))
90 return filename;
92 filename_len = strlen(filename);
93 max_path = MSGSIZE_MAX - 4;
94 precoded = recoded_filename;
95 if (iconv(inv_msgiconv, &filename, &filename_len,
96 &precoded, &max_path) == (size_t)(-1) && errno == E2BIG) {
97 precoded[0] = precoded[1] = precoded[2] = '.';
98 precoded += 3;
100 *precoded = '\0';
101 return recoded_filename;
102 #endif
105 void mp_msg_init(void){
106 int i;
107 char *env = getenv("MPLAYER_VERBOSE");
108 if (env)
109 verbose = atoi(env);
110 for(i=0;i<MSGT_MAX;i++) mp_msg_levels[i] = -2;
111 mp_msg_levels[MSGT_IDENTIFY] = -1; // no -identify output by default
112 #ifdef CONFIG_ICONV
113 mp_msg_charset = getenv("MPLAYER_CHARSET");
114 if (!mp_msg_charset)
115 mp_msg_charset = get_term_charset();
116 #endif
117 #ifdef CONFIG_TRANSLATION
118 textdomain("mplayer");
119 char *localedir = getenv("MPLAYER_LOCALEDIR");
120 if (localedir == NULL && strlen(MPLAYER_LOCALEDIR))
121 localedir = MPLAYER_LOCALEDIR;
122 bindtextdomain("mplayer", localedir);
123 bind_textdomain_codeset("mplayer", "UTF-8");
124 #endif
125 #ifdef _WIN32
127 CONSOLE_SCREEN_BUFFER_INFO cinfo;
128 long cmode = 0;
130 hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
131 if ((hConOut == NULL) || (hConOut == INVALID_HANDLE_VALUE))
133 hConOut = NULL;
134 fprintf(stderr, "Cannot get Console handle of stdout\n");
135 return;
138 GetConsoleMode(hConOut, &cmode);
139 cmode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
140 SetConsoleMode(hConOut, cmode);
142 GetConsoleScreenBufferInfo(hConOut, &cinfo);
143 stdoutAttrs = cinfo.wAttributes;
145 #endif
148 int mp_msg_test(int mod, int lev)
150 return lev <= (mp_msg_levels[mod] == -2 ? mp_msg_level_all + verbose : mp_msg_levels[mod]);
153 static void set_msg_color(FILE* stream, int lev)
155 static const unsigned char v_colors[10] = {9, 1, 3, 15, 7, 2, 2, 8, 8, 8};
156 int c = v_colors[lev];
157 #ifdef MP_ANNOY_ME
158 /* that's only a silly color test */
160 int c;
161 static int flag = 1;
162 if (flag)
163 for(c = 0; c < 24; c++)
164 printf("\033[%d;3%dm*** COLOR TEST %d ***\n", c>7, c&7, c);
165 flag = 0;
167 #endif
169 #ifdef _WIN32
170 if (mp_msg_color)
171 SetConsoleTextAttribute(hConOut, ansi2win32[c] | FOREGROUND_INTENSITY);
172 #else
173 if (mp_msg_color)
174 fprintf(stream, "\033[%d;3%dm", c >> 3, c & 7);
175 #endif
178 static void print_msg_module(FILE* stream, int mod)
180 static const char *module_text[MSGT_MAX] = {
181 "GLOBAL",
182 "CPLAYER",
183 "GPLAYER",
184 "VIDEOOUT",
185 "AUDIOOUT",
186 "DEMUXER",
187 "DS",
188 "DEMUX",
189 "HEADER",
190 "AVSYNC",
191 "AUTOQ",
192 "CFGPARSER",
193 "DECAUDIO",
194 "DECVIDEO",
195 "SEEK",
196 "WIN32",
197 "OPEN",
198 "DVD",
199 "PARSEES",
200 "LIRC",
201 "STREAM",
202 "CACHE",
203 "MENCODER",
204 "XACODEC",
205 "TV",
206 "OSDEP",
207 "SPUDEC",
208 "PLAYTREE",
209 "INPUT",
210 "VFILTER",
211 "OSD",
212 "NETWORK",
213 "CPUDETECT",
214 "CODECCFG",
215 "SWS",
216 "VOBSUB",
217 "SUBREADER",
218 "AFILTER",
219 "NETST",
220 "MUXER",
221 "OSDMENU",
222 "IDENTIFY",
223 "RADIO",
224 "ASS",
225 "LOADER",
226 "STATUSLINE",
228 int c2 = (mod + 1) % 15 + 1;
229 if (!mp_msg_module)
230 return;
231 #ifdef _WIN32
232 if (mp_msg_color)
233 SetConsoleTextAttribute(hConOut, ansi2win32[c2&7] | FOREGROUND_INTENSITY);
234 fprintf(stream, "%9s", module_text[mod]);
235 if (mp_msg_color)
236 SetConsoleTextAttribute(hConOut, stdoutAttrs);
237 #else
238 if (mp_msg_color)
239 fprintf(stream, "\033[%d;3%dm", c2 >> 3, c2 & 7);
240 fprintf(stream, "%9s", module_text[mod]);
241 if (mp_msg_color)
242 fprintf(stream, "\033[0;37m");
243 #endif
244 fprintf(stream, ": ");
247 void mp_msg_va(int mod, int lev, const char *format, va_list va)
249 char tmp[MSGSIZE_MAX];
250 FILE *stream = lev <= MSGL_WARN ? stderr : stdout;
251 static int header = 1;
253 if (!mp_msg_test(mod, lev)) return; // do not display
254 vsnprintf(tmp, MSGSIZE_MAX, format, va);
255 tmp[MSGSIZE_MAX-2] = '\n';
256 tmp[MSGSIZE_MAX-1] = 0;
258 #if defined(CONFIG_ICONV) && defined(MSG_CHARSET)
259 if (mp_msg_charset && strcasecmp(mp_msg_charset, "noconv")) {
260 char tmp2[MSGSIZE_MAX];
261 size_t inlen = strlen(tmp), outlen = MSGSIZE_MAX;
262 char *in = tmp, *out = tmp2;
263 if (!old_charset || strcmp(old_charset, mp_msg_charset)) {
264 if (old_charset) {
265 free(old_charset);
266 iconv_close(msgiconv);
268 msgiconv = iconv_open(mp_msg_charset, MSG_CHARSET);
269 old_charset = strdup(mp_msg_charset);
271 if (msgiconv == (iconv_t)(-1)) {
272 fprintf(stderr,"iconv: conversion from %s to %s unsupported\n"
273 ,MSG_CHARSET,mp_msg_charset);
274 }else{
275 memset(tmp2, 0, MSGSIZE_MAX);
276 while (iconv(msgiconv, &in, &inlen, &out, &outlen) == -1) {
277 if (!inlen || !outlen)
278 break;
279 *out++ = *in++;
280 outlen--; inlen--;
282 strncpy(tmp, tmp2, MSGSIZE_MAX);
283 tmp[MSGSIZE_MAX-1] = 0;
284 tmp[MSGSIZE_MAX-2] = '\n';
287 #endif
289 if (header)
290 print_msg_module(stream, mod);
291 set_msg_color(stream, lev);
292 header = tmp[strlen(tmp)-1] == '\n' || tmp[strlen(tmp)-1] == '\r';
294 fprintf(stream, "%s", tmp);
295 if (mp_msg_color)
296 fprintf(stream, "\033[0m");
297 fflush(stream);
300 void mp_msg(int mod, int lev, const char *format, ...)
302 va_list va;
303 va_start(va, format);
304 mp_msg_va(mod, lev, format, va);
305 va_end(va);
308 char *mp_gtext(const char *string)
310 #ifdef CONFIG_TRANSLATION
311 /* gettext expects the global locale to be set with
312 * setlocale(LC_ALL, ""). However doing that would suck for a
313 * couple of reasons (locale stuff is badly designed and sucks in
314 * general).
316 * First setting the locale, especially LC_CTYPE, changes the
317 * behavior of various C functions and we don't want that - we
318 * want isalpha() for example to always behave like in the C
319 * locale.
321 * Second, there is no way to enforce a sane character set. All
322 * strings inside MPlayer must always be in utf-8, not in the
323 * character set specified by the system locale which could be
324 * something different and completely insane. The locale system
325 * lacks any way to say "set LC_CTYPE to utf-8, ignoring the
326 * default system locale if it specifies something different". We
327 * could try to work around that flaw by leaving LC_CTYPE to the C
328 * locale and only setting LC_MESSAGES (which is the variable that
329 * must be set to tell gettext which language to translate
330 * to). However if we leave LC_MESSAGES set then things like
331 * strerror() may produce completely garbled output when they try
332 * to translate their results but then try to convert some
333 * translated non-ASCII text to the character set specified by
334 * LC_CTYPE which would still be in the C locale (this doesn't
335 * affect gettext itself because it supports specifying the
336 * character set directly with bind_textdomain_codeset()).
338 * So the only solution (at leat short of trying to work around
339 * things possibly producing non-utf-8 output) is to leave all the
340 * locale variables unset. Note that this means it's not possible
341 * to get translated output from any libraries we call if they
342 * only rely on the broken locale system to specify the language
343 * to use; this is the case with libc for example.
345 * The locale changing below is rather ugly, but hard to avoid.
346 * gettext doesn't support specifying the translation target
347 * directly, only through locale.
348 * The main actual problem this could cause is interference with
349 * other threads; that could be avoided with thread-specific
350 * locale changes, but such functionality is less standard and I
351 * think it's not worth adding pre-emptively unless someone sees
352 * an actual problem case.
354 setlocale(LC_MESSAGES, "");
355 string = gettext(string);
356 setlocale(LC_MESSAGES, "C");
357 #endif
358 return string;
361 void mp_tmsg(int mod, int lev, const char *format, ...)
363 va_list va;
364 va_start(va, format);
365 mp_msg_va(mod, lev, mp_gtext(format), va);
366 va_end(va);