1 /*
2 * This file is part of MPlayer.
3 *
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.
8 *
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.
13 *
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.
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <string.h>
23
24 #include "config.h"
25 #include "libavutil/avstring.h"
26 #include "osdep/getch2.h"
27
28 #ifdef CONFIG_ICONV
29 #include <iconv.h>
30 #include <errno.h>
31 #endif
32
33 #include "mp_msg.h"
34
35 /* maximum message length of mp_msg */
36 #define MSGSIZE_MAX 3072
37
38 int mp_msg_levels[MSGT_MAX]; // verbose level of this module. initialized to -2
39 int mp_msg_level_all = MSGL_STATUS;
40 int verbose = 0;
41 int mp_msg_color = 0;
42 int mp_msg_module = 0;
43 #ifdef CONFIG_ICONV
44 char *mp_msg_charset = NULL;
45 // only used to simplify freeing get_term_charset
46 // result, even when it was overwritten by command-line options.
47 char *term_charset_ptr_to_free = NULL;
48 static char *old_charset = NULL;
49 static iconv_t msgiconv;
50 static iconv_t inv_msgiconv = (iconv_t)(-1);
51 #endif
52
filename_recode(const char * filename)53 const char* filename_recode(const char* filename)
54 {
55 #if !defined(CONFIG_ICONV) || !defined(MSG_CHARSET)
56 return filename;
57 #else
58 static char recoded_filename[MSGSIZE_MAX];
59 size_t filename_len, max_path;
60 char* precoded;
61 if (!mp_msg_charset ||
62 !av_strcasecmp(mp_msg_charset, MSG_CHARSET) ||
63 !av_strcasecmp(mp_msg_charset, "noconv"))
64 return filename;
65 if (inv_msgiconv == (iconv_t)(-1)) {
66 inv_msgiconv = iconv_open(MSG_CHARSET, mp_msg_charset);
67 if (inv_msgiconv == (iconv_t)(-1))
68 return filename;
69 }
70 filename_len = strlen(filename);
71 max_path = MSGSIZE_MAX - 4;
72 precoded = recoded_filename;
73 if (iconv(inv_msgiconv, &filename, &filename_len,
74 &precoded, &max_path) == (size_t)(-1) && errno == E2BIG) {
75 precoded[0] = precoded[1] = precoded[2] = '.';
76 precoded += 3;
77 }
78 *precoded = '\0';
79 return recoded_filename;
80 #endif
81 }
82
mp_msg_init(void)83 void mp_msg_init(void){
84 int i;
85 char *env = getenv("MPLAYER_VERBOSE");
86 if (env)
87 verbose = atoi(env);
88 for(i=0;i<MSGT_MAX;i++) mp_msg_levels[i] = -2;
89 mp_msg_levels[MSGT_IDENTIFY] = -1; // no -identify output by default
90 #ifdef CONFIG_ICONV
91 mp_msg_charset = getenv("MPLAYER_CHARSET");
92 if (!mp_msg_charset) {
93 free(term_charset_ptr_to_free); // could assert that is is NULL instead
94 mp_msg_charset = term_charset_ptr_to_free = get_term_charset();
95 }
96 #endif
97 }
98
mp_msg_uninit(void)99 void mp_msg_uninit(void)
100 {
101 #ifdef CONFIG_ICONV
102 if (old_charset) {
103 free(old_charset);
104 iconv_close(msgiconv);
105 }
106 if (inv_msgiconv != (iconv_t)(-1)) iconv_close(inv_msgiconv);
107 free(term_charset_ptr_to_free);
108 term_charset_ptr_to_free = NULL;
109 #endif
110 }
111
mp_msg_test(int mod,int lev)112 int mp_msg_test(int mod, int lev)
113 {
114 return lev <= (mp_msg_levels[mod] == -2 ? mp_msg_level_all + verbose : mp_msg_levels[mod]);
115 }
116
set_msg_color(FILE * stream,int lev)117 static void set_msg_color(FILE* stream, int lev)
118 {
119 static const unsigned char v_colors[10] = {9, 1, 3, 15, 7, 2, 2, 8, 8, 8};
120 int c = v_colors[lev];
121 #ifdef MP_ANNOY_ME
122 /* that's only a silly color test */
123 {
124 int c;
125 static int flag = 1;
126 if (flag)
127 for(c = 0; c < 24; c++)
128 printf("\033[%d;3%dm*** COLOR TEST %d ***\n", c>7, c&7, c);
129 flag = 0;
130 }
131 #endif
132 if (mp_msg_color)
133 fprintf(stream, "\033[%d;3%dm", c >> 3, c & 7);
134 }
135
print_msg_module(FILE * stream,int mod)136 static void print_msg_module(FILE* stream, int mod)
137 {
138 static const char *module_text[MSGT_MAX] = {
139 "GLOBAL",
140 "CPLAYER",
141 "GPLAYER",
142 "VIDEOOUT",
143 "AUDIOOUT",
144 "DEMUXER",
145 "DS",
146 "DEMUX",
147 "HEADER",
148 "AVSYNC",
149 "AUTOQ",
150 "CFGPARSER",
151 "DECAUDIO",
152 "DECVIDEO",
153 "SEEK",
154 "WIN32",
155 "OPEN",
156 "DVD",
157 "PARSEES",
158 "LIRC",
159 "STREAM",
160 "CACHE",
161 "MENCODER",
162 "XACODEC",
163 "TV",
164 "OSDEP",
165 "SPUDEC",
166 "PLAYTREE",
167 "INPUT",
168 "VFILTER",
169 "OSD",
170 "NETWORK",
171 "CPUDETECT",
172 "CODECCFG",
173 "SWS",
174 "VOBSUB",
175 "SUBREADER",
176 "AFILTER",
177 "NETST",
178 "MUXER",
179 "OSDMENU",
180 "IDENTIFY",
181 "RADIO",
182 "ASS",
183 "LOADER",
184 "STATUSLINE",
185 };
186 int c2 = (mod + 1) % 15 + 1;
187
188 if (!mp_msg_module)
189 return;
190 if (mp_msg_color)
191 fprintf(stream, "\033[%d;3%dm", c2 >> 3, c2 & 7);
192 fprintf(stream, "%9s", module_text[mod]);
193 if (mp_msg_color)
194 fprintf(stream, "\033[0;37m");
195 fprintf(stream, ": ");
196 }
197
mp_msg(int mod,int lev,const char * format,...)198 void mp_msg(int mod, int lev, const char *format, ... ){
199 va_list va;
200 va_start(va, format);
201 mp_msg_va(mod, lev, format, va);
202 va_end(va);
203 }
204
mp_msg_va(int mod,int lev,const char * format,va_list va)205 void mp_msg_va(int mod, int lev, const char *format, va_list va){
206 char tmp[MSGSIZE_MAX];
207 FILE *stream = lev <= MSGL_WARN ? stderr : stdout;
208 static int header = 1;
209 // indicates if last line printed was a status line
210 static int statusline;
211 size_t len;
212
213 if (!mp_msg_test(mod, lev)) return; // do not display
214 vsnprintf(tmp, MSGSIZE_MAX, format, va);
215 tmp[MSGSIZE_MAX-2] = '\n';
216 tmp[MSGSIZE_MAX-1] = 0;
217
218 #if defined(CONFIG_ICONV) && defined(MSG_CHARSET)
219 if (mp_msg_charset && av_strcasecmp(mp_msg_charset, "noconv")) {
220 char tmp2[MSGSIZE_MAX];
221 size_t inlen = strlen(tmp), outlen = MSGSIZE_MAX;
222 char *in = tmp, *out = tmp2;
223 if (!old_charset || strcmp(old_charset, mp_msg_charset)) {
224 if (old_charset) {
225 free(old_charset);
226 iconv_close(msgiconv);
227 }
228 msgiconv = iconv_open(mp_msg_charset, MSG_CHARSET);
229 old_charset = strdup(mp_msg_charset);
230 }
231 if (msgiconv == (iconv_t)(-1)) {
232 fprintf(stderr,"iconv: conversion from %s to %s unsupported\n"
233 ,MSG_CHARSET,mp_msg_charset);
234 }else{
235 memset(tmp2, 0, MSGSIZE_MAX);
236 while (iconv(msgiconv, &in, &inlen, &out, &outlen) == -1) {
237 if (!inlen || !outlen)
238 break;
239 *out++ = *in++;
240 outlen--; inlen--;
241 }
242 strncpy(tmp, tmp2, MSGSIZE_MAX);
243 tmp[MSGSIZE_MAX-1] = 0;
244 tmp[MSGSIZE_MAX-2] = '\n';
245 }
246 }
247 #endif
248
249 // as a status line normally is intended to be overwitten by next status line
250 // output a '\n' to get a normal message on a separate line
251 if (statusline && lev != MSGL_STATUS) fprintf(stream, "\n");
252 statusline = lev == MSGL_STATUS;
253
254 if (header)
255 print_msg_module(stream, mod);
256 set_msg_color(stream, lev);
257 len = strlen(tmp);
258 header = len && (tmp[len-1] == '\n' || tmp[len-1] == '\r');
259
260 fprintf(stream, "%s", tmp);
261 if (mp_msg_color)
262 fprintf(stream, "\033[0m");
263 fflush(stream);
264 }
265