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