Ignore svn changes up to r30559
[mplayer/kovensky.git] / mp_msg.c
blob3fed6973319ff8c811359c00120aae50263fab15
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"
26 #ifdef CONFIG_TRANSLATION
27 #include <locale.h>
28 #include <libintl.h>
29 #endif
31 #ifdef CONFIG_ICONV
32 #include <iconv.h>
33 #include <errno.h>
34 /**
35 * \brief gets the name of the system's terminal character set
36 * \return a malloced string indicating the system charset
38 * Be warned that this function on many systems is in no way thread-safe
39 * since it modifies global data
41 char* get_term_charset(void);
42 #endif
44 #include "mp_msg.h"
46 /* maximum message length of mp_msg */
47 #define MSGSIZE_MAX 3072
49 int mp_msg_levels[MSGT_MAX]; // verbose level of this module. initialized to -2
50 int mp_msg_level_all = MSGL_STATUS;
51 int verbose = 0;
52 int mp_msg_color = 0;
53 int mp_msg_module = 0;
54 #ifdef CONFIG_ICONV
55 char *mp_msg_charset = NULL;
56 static char *old_charset = NULL;
57 static iconv_t msgiconv;
58 #endif
60 const char* filename_recode(const char* filename)
62 #if !defined(CONFIG_ICONV) || !defined(MSG_CHARSET)
63 return filename;
64 #else
65 static iconv_t inv_msgiconv = (iconv_t)(-1);
66 static char recoded_filename[MSGSIZE_MAX];
67 size_t filename_len, max_path;
68 char* precoded;
69 if (!mp_msg_charset ||
70 !strcasecmp(mp_msg_charset, MSG_CHARSET) ||
71 !strcasecmp(mp_msg_charset, "noconv"))
72 return filename;
73 if (inv_msgiconv == (iconv_t)(-1)) {
74 inv_msgiconv = iconv_open(MSG_CHARSET, mp_msg_charset);
75 if (inv_msgiconv == (iconv_t)(-1))
76 return filename;
78 filename_len = strlen(filename);
79 max_path = MSGSIZE_MAX - 4;
80 precoded = recoded_filename;
81 if (iconv(inv_msgiconv, &filename, &filename_len,
82 &precoded, &max_path) == (size_t)(-1) && errno == E2BIG) {
83 precoded[0] = precoded[1] = precoded[2] = '.';
84 precoded += 3;
86 *precoded = '\0';
87 return recoded_filename;
88 #endif
91 void mp_msg_init(void){
92 int i;
93 char *env = getenv("MPLAYER_VERBOSE");
94 if (env)
95 verbose = atoi(env);
96 for(i=0;i<MSGT_MAX;i++) mp_msg_levels[i] = -2;
97 mp_msg_levels[MSGT_IDENTIFY] = -1; // no -identify output by default
98 #ifdef CONFIG_ICONV
99 mp_msg_charset = getenv("MPLAYER_CHARSET");
100 if (!mp_msg_charset)
101 mp_msg_charset = get_term_charset();
102 #endif
103 #ifdef CONFIG_TRANSLATION
104 textdomain("mplayer");
105 char *localedir = getenv("MPLAYER_LOCALEDIR");
106 if (localedir == NULL && strlen(MPLAYER_LOCALEDIR))
107 localedir = MPLAYER_LOCALEDIR;
108 bindtextdomain("mplayer", localedir);
109 bind_textdomain_codeset("mplayer", "UTF-8");
110 #endif
113 int mp_msg_test(int mod, int lev)
115 return lev <= (mp_msg_levels[mod] == -2 ? mp_msg_level_all + verbose : mp_msg_levels[mod]);
118 static void set_msg_color(FILE* stream, int lev)
120 static const unsigned char v_colors[10] = {9, 1, 3, 15, 7, 2, 2, 8, 8, 8};
121 int c = v_colors[lev];
122 #ifdef MP_ANNOY_ME
123 /* that's only a silly color test */
125 int c;
126 static int flag = 1;
127 if (flag)
128 for(c = 0; c < 24; c++)
129 printf("\033[%d;3%dm*** COLOR TEST %d ***\n", c>7, c&7, c);
130 flag = 0;
132 #endif
133 if (mp_msg_color)
134 fprintf(stream, "\033[%d;3%dm", c >> 3, c & 7);
137 static void print_msg_module(FILE* stream, int mod)
139 static const char *module_text[MSGT_MAX] = {
140 "GLOBAL",
141 "CPLAYER",
142 "GPLAYER",
143 "VIDEOOUT",
144 "AUDIOOUT",
145 "DEMUXER",
146 "DS",
147 "DEMUX",
148 "HEADER",
149 "AVSYNC",
150 "AUTOQ",
151 "CFGPARSER",
152 "DECAUDIO",
153 "DECVIDEO",
154 "SEEK",
155 "WIN32",
156 "OPEN",
157 "DVD",
158 "PARSEES",
159 "LIRC",
160 "STREAM",
161 "CACHE",
162 "MENCODER",
163 "XACODEC",
164 "TV",
165 "OSDEP",
166 "SPUDEC",
167 "PLAYTREE",
168 "INPUT",
169 "VFILTER",
170 "OSD",
171 "NETWORK",
172 "CPUDETECT",
173 "CODECCFG",
174 "SWS",
175 "VOBSUB",
176 "SUBREADER",
177 "AFILTER",
178 "NETST",
179 "MUXER",
180 "OSDMENU",
181 "IDENTIFY",
182 "RADIO",
183 "ASS",
184 "LOADER",
185 "STATUSLINE",
187 int c2 = (mod + 1) % 15 + 1;
189 if (!mp_msg_module)
190 return;
191 if (mp_msg_color)
192 fprintf(stream, "\033[%d;3%dm", c2 >> 3, c2 & 7);
193 fprintf(stream, "%9s", module_text[mod]);
194 if (mp_msg_color)
195 fprintf(stream, "\033[0;37m");
196 fprintf(stream, ": ");
199 void mp_msg_va(int mod, int lev, const char *format, va_list va)
201 char tmp[MSGSIZE_MAX];
202 FILE *stream = lev <= MSGL_WARN ? stderr : stdout;
203 static int header = 1;
205 if (!mp_msg_test(mod, lev)) return; // do not display
206 vsnprintf(tmp, MSGSIZE_MAX, format, va);
207 tmp[MSGSIZE_MAX-2] = '\n';
208 tmp[MSGSIZE_MAX-1] = 0;
210 #if defined(CONFIG_ICONV) && defined(MSG_CHARSET)
211 if (mp_msg_charset && strcasecmp(mp_msg_charset, "noconv")) {
212 char tmp2[MSGSIZE_MAX];
213 size_t inlen = strlen(tmp), outlen = MSGSIZE_MAX;
214 char *in = tmp, *out = tmp2;
215 if (!old_charset || strcmp(old_charset, mp_msg_charset)) {
216 if (old_charset) {
217 free(old_charset);
218 iconv_close(msgiconv);
220 msgiconv = iconv_open(mp_msg_charset, MSG_CHARSET);
221 old_charset = strdup(mp_msg_charset);
223 if (msgiconv == (iconv_t)(-1)) {
224 fprintf(stderr,"iconv: conversion from %s to %s unsupported\n"
225 ,MSG_CHARSET,mp_msg_charset);
226 }else{
227 memset(tmp2, 0, MSGSIZE_MAX);
228 while (iconv(msgiconv, &in, &inlen, &out, &outlen) == -1) {
229 if (!inlen || !outlen)
230 break;
231 *out++ = *in++;
232 outlen--; inlen--;
234 strncpy(tmp, tmp2, MSGSIZE_MAX);
235 tmp[MSGSIZE_MAX-1] = 0;
236 tmp[MSGSIZE_MAX-2] = '\n';
239 #endif
241 if (header)
242 print_msg_module(stream, mod);
243 set_msg_color(stream, lev);
244 header = tmp[strlen(tmp)-1] == '\n' || tmp[strlen(tmp)-1] == '\r';
246 fprintf(stream, "%s", tmp);
247 fflush(stream);
250 void mp_msg(int mod, int lev, const char *format, ...)
252 va_list va;
253 va_start(va, format);
254 mp_msg_va(mod, lev, format, va);
255 va_end(va);
258 char *mp_gtext(const char *string)
260 #ifdef CONFIG_TRANSLATION
261 /* gettext expects the global locale to be set with
262 * setlocale(LC_ALL, ""). However doing that would suck for a
263 * couple of reasons (locale stuff is badly designed and sucks in
264 * general).
266 * First setting the locale, especially LC_CTYPE, changes the
267 * behavior of various C functions and we don't want that - we
268 * want isalpha() for example to always behave like in the C
269 * locale.
271 * Second, there is no way to enforce a sane character set. All
272 * strings inside MPlayer must always be in utf-8, not in the
273 * character set specified by the system locale which could be
274 * something different and completely insane. The locale system
275 * lacks any way to say "set LC_CTYPE to utf-8, ignoring the
276 * default system locale if it specifies something different". We
277 * could try to work around that flaw by leaving LC_CTYPE to the C
278 * locale and only setting LC_MESSAGES (which is the variable that
279 * must be set to tell gettext which language to translate
280 * to). However if we leave LC_MESSAGES set then things like
281 * strerror() may produce completely garbled output when they try
282 * to translate their results but then try to convert some
283 * translated non-ASCII text to the character set specified by
284 * LC_CTYPE which would still be in the C locale (this doesn't
285 * affect gettext itself because it supports specifying the
286 * character set directly with bind_textdomain_codeset()).
288 * So the only solution (at leat short of trying to work around
289 * things possibly producing non-utf-8 output) is to leave all the
290 * locale variables unset. Note that this means it's not possible
291 * to get translated output from any libraries we call if they
292 * only rely on the broken locale system to specify the language
293 * to use; this is the case with libc for example.
295 * The locale changing below is rather ugly, but hard to avoid.
296 * gettext doesn't support specifying the translation target
297 * directly, only through locale.
298 * The main actual problem this could cause is interference with
299 * other threads; that could be avoided with thread-specific
300 * locale changes, but such functionality is less standard and I
301 * think it's not worth adding pre-emptively unless someone sees
302 * an actual problem case.
304 setlocale(LC_MESSAGES, "");
305 string = gettext(string);
306 setlocale(LC_MESSAGES, "C");
307 #endif
308 return string;
311 void mp_tmsg(int mod, int lev, const char *format, ...)
313 va_list va;
314 va_start(va, format);
315 mp_msg_va(mod, lev, mp_gtext(format), va);
316 va_end(va);