summaryrefslogtreecommitdiffstats
path: root/core/mp_msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/mp_msg.c')
-rw-r--r--core/mp_msg.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/core/mp_msg.c b/core/mp_msg.c
new file mode 100644
index 0000000000..627ee04187
--- /dev/null
+++ b/core/mp_msg.c
@@ -0,0 +1,309 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MPlayer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "osdep/getch2.h"
+#include "osdep/io.h"
+
+#ifdef CONFIG_TRANSLATION
+#include <locale.h>
+#include <libintl.h>
+#endif
+
+#include "mp_msg.h"
+
+/* maximum message length of mp_msg */
+#define MSGSIZE_MAX 6144
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <io.h>
+#define hSTDOUT GetStdHandle(STD_OUTPUT_HANDLE)
+#define hSTDERR GetStdHandle(STD_ERROR_HANDLE)
+static short stdoutAttrs = 0;
+static const unsigned char ansi2win32[10] = {
+ 0,
+ FOREGROUND_RED,
+ FOREGROUND_GREEN,
+ FOREGROUND_GREEN | FOREGROUND_RED,
+ FOREGROUND_BLUE,
+ FOREGROUND_BLUE | FOREGROUND_RED,
+ FOREGROUND_BLUE | FOREGROUND_GREEN,
+ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED,
+ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED,
+ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
+};
+#endif
+
+int mp_msg_levels[MSGT_MAX]; // verbose level of this module. initialized to -2
+int mp_msg_level_all = MSGL_STATUS;
+int verbose = 0;
+int mp_msg_color = 1;
+int mp_msg_module = 0;
+int mp_msg_cancolor = 0;
+
+static int mp_msg_docolor(void) {
+ return mp_msg_cancolor && mp_msg_color;
+}
+
+void mp_msg_init(void){
+#ifdef _WIN32
+ CONSOLE_SCREEN_BUFFER_INFO cinfo;
+ long cmode = 0;
+ GetConsoleMode(hSTDOUT, &cmode);
+ cmode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
+ SetConsoleMode(hSTDOUT, cmode);
+ SetConsoleMode(hSTDERR, cmode);
+ GetConsoleScreenBufferInfo(hSTDOUT, &cinfo);
+ stdoutAttrs = cinfo.wAttributes;
+#endif
+ int i;
+ char *env = getenv("MPV_VERBOSE");
+ if (env)
+ verbose = atoi(env);
+ for(i=0;i<MSGT_MAX;i++) mp_msg_levels[i] = -2;
+ mp_msg_cancolor = isatty(fileno(stdout));
+ mp_msg_levels[MSGT_IDENTIFY] = -1; // no -identify output by default
+#ifdef CONFIG_TRANSLATION
+ textdomain("mpv");
+ char *localedir = getenv("MPV_LOCALEDIR");
+ if (localedir == NULL && strlen(MPLAYER_LOCALEDIR))
+ localedir = MPLAYER_LOCALEDIR;
+ bindtextdomain("mpv", localedir);
+ bind_textdomain_codeset("mpv", "UTF-8");
+#endif
+}
+
+int mp_msg_test(int mod, int lev)
+{
+ return lev <= (mp_msg_levels[mod] == -2 ? mp_msg_level_all + verbose : mp_msg_levels[mod]);
+}
+
+static void set_msg_color(FILE* stream, int lev)
+{
+ static const unsigned char v_colors[10] = {9, 1, 3, 15, 7, 7, 2, 8, 8, 8};
+ int c = v_colors[lev];
+#ifdef MP_ANNOY_ME
+ /* that's only a silly color test */
+ {
+ int c;
+ static int flag = 1;
+ if (flag)
+ for(c = 0; c < 24; c++)
+ printf("\033[%d;3%dm*** COLOR TEST %d ***\n", c>7, c&7, c);
+ flag = 0;
+ }
+#endif
+ if (mp_msg_docolor())
+ {
+#ifdef _WIN32
+ HANDLE *wstream = stream == stderr ? hSTDERR : hSTDOUT;
+ SetConsoleTextAttribute(wstream, ansi2win32[c] | FOREGROUND_INTENSITY);
+#else
+ fprintf(stream, "\033[%d;3%dm", c >> 3, c & 7);
+#endif
+ }
+}
+
+static void print_msg_module(FILE* stream, int mod)
+{
+ static const char *module_text[MSGT_MAX] = {
+ "GLOBAL",
+ "CPLAYER",
+ "GPLAYER",
+ "VIDEOOUT",
+ "AUDIOOUT",
+ "DEMUXER",
+ "DS",
+ "DEMUX",
+ "HEADER",
+ "AVSYNC",
+ "AUTOQ",
+ "CFGPARSER",
+ "DECAUDIO",
+ "DECVIDEO",
+ "SEEK",
+ "WIN32",
+ "OPEN",
+ "DVD",
+ "PARSEES",
+ "LIRC",
+ "STREAM",
+ "CACHE",
+ "MENCODER",
+ "XACODEC",
+ "TV",
+ "OSDEP",
+ "SPUDEC",
+ "PLAYTREE",
+ "INPUT",
+ "VFILTER",
+ "OSD",
+ "NETWORK",
+ "CPUDETECT",
+ "CODECCFG",
+ "SWS",
+ "VOBSUB",
+ "SUBREADER",
+ "AFILTER",
+ "NETST",
+ "MUXER",
+ "OSDMENU",
+ "IDENTIFY",
+ "RADIO",
+ "ASS",
+ "LOADER",
+ "STATUSLINE",
+ };
+ int c2 = (mod + 1) % 15 + 1;
+
+ if (!mp_msg_module)
+ return;
+#ifdef _WIN32
+ HANDLE *wstream = stream == stderr ? hSTDERR : hSTDOUT;
+ if (mp_msg_docolor())
+ SetConsoleTextAttribute(wstream, ansi2win32[c2&7] | FOREGROUND_INTENSITY);
+ fprintf(stream, "%9s", module_text[mod]);
+ if (mp_msg_docolor())
+ SetConsoleTextAttribute(wstream, stdoutAttrs);
+#else
+ if (mp_msg_docolor())
+ fprintf(stream, "\033[%d;3%dm", c2 >> 3, c2 & 7);
+ fprintf(stream, "%9s", module_text[mod]);
+ if (mp_msg_docolor())
+ fprintf(stream, "\033[0;37m");
+#endif
+ fprintf(stream, ": ");
+}
+
+void mp_msg_va(int mod, int lev, const char *format, va_list va)
+{
+ char tmp[MSGSIZE_MAX];
+ FILE *stream = lev == MSGL_STATUS ? stderr : stdout;
+ static int header = 1;
+ // indicates if last line printed was a status line
+ static int statusline;
+
+ if (!mp_msg_test(mod, lev)) return; // do not display
+ vsnprintf(tmp, MSGSIZE_MAX, format, va);
+ tmp[MSGSIZE_MAX-2] = '\n';
+ tmp[MSGSIZE_MAX-1] = 0;
+
+ /* A status line is normally intended to be overwritten by the next
+ * status line, and does not end with a '\n'. If we're printing a normal
+ * line instead after the status one print '\n' to change line. */
+ if (statusline && lev != MSGL_STATUS)
+ fprintf(stderr, "\n");
+ statusline = lev == MSGL_STATUS;
+
+ if (header)
+ print_msg_module(stream, mod);
+ set_msg_color(stream, lev);
+
+ size_t len = strlen(tmp);
+ header = len && (tmp[len-1] == '\n' || tmp[len-1] == '\r');
+
+ fprintf(stream, "%s", tmp);
+
+ if (mp_msg_docolor())
+ {
+#ifdef _WIN32
+ HANDLE *wstream = lev <= MSGL_WARN ? hSTDERR : hSTDOUT;
+ SetConsoleTextAttribute(wstream, stdoutAttrs);
+#else
+ fprintf(stream, "\033[0m");
+#endif
+ }
+ fflush(stream);
+}
+
+void mp_msg(int mod, int lev, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ mp_msg_va(mod, lev, format, va);
+ va_end(va);
+}
+
+char *mp_gtext(const char *string)
+{
+#ifdef CONFIG_TRANSLATION
+ /* gettext expects the global locale to be set with
+ * setlocale(LC_ALL, ""). However doing that would suck for a
+ * couple of reasons (locale stuff is badly designed and sucks in
+ * general).
+ *
+ * First, setting the locale, especially LC_CTYPE, changes the
+ * behavior of various C functions and we don't want that - we
+ * want isalpha() for example to always behave like in the C
+ * locale.
+
+ * Second, there is no way to enforce a sane character set. All
+ * strings inside MPlayer must always be in utf-8, not in the
+ * character set specified by the system locale which could be
+ * something different and completely insane. The locale system
+ * lacks any way to say "set LC_CTYPE to utf-8, ignoring the
+ * default system locale if it specifies something different". We
+ * could try to work around that flaw by leaving LC_CTYPE to the C
+ * locale and only setting LC_MESSAGES (which is the variable that
+ * must be set to tell gettext which language to translate
+ * to). However if we leave LC_MESSAGES set then things like
+ * strerror() may produce completely garbled output when they try
+ * to translate their results but then try to convert some
+ * translated non-ASCII text to the character set specified by
+ * LC_CTYPE which would still be in the C locale (this doesn't
+ * affect gettext itself because it supports specifying the
+ * character set directly with bind_textdomain_codeset()).
+ *
+ * So the only solution (at least short of trying to work around
+ * things possibly producing non-utf-8 output) is to leave all the
+ * locale variables unset. Note that this means it's not possible
+ * to get translated output from any libraries we call if they
+ * only rely on the broken locale system to specify the language
+ * to use; this is the case with libc for example.
+ *
+ * The locale changing below is rather ugly, but hard to avoid.
+ * gettext doesn't support specifying the translation target
+ * directly, only through locale.
+ * The main actual problem this could cause is interference with
+ * other threads; that could be avoided with thread-specific
+ * locale changes, but such functionality is less standard and I
+ * think it's not worth adding pre-emptively unless someone sees
+ * an actual problem case.
+ */
+ setlocale(LC_MESSAGES, "");
+ string = gettext(string);
+ setlocale(LC_MESSAGES, "C");
+#endif
+ return (char *)string;
+}
+
+void mp_tmsg(int mod, int lev, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ mp_msg_va(mod, lev, mp_gtext(format), va);
+ va_end(va);
+}