summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-31 21:40:30 +0200
committerwm4 <wm4@nowhere>2013-07-31 21:46:40 +0200
commit88d79fc00df39dc0180de86c758697f5ab3e56cb (patch)
tree5764f1067cae79dad6a01dccfb241db894b67683
parentd1de1e090f91a254f066505ee5811feda4d93dde (diff)
downloadmpv-88d79fc00df39dc0180de86c758697f5ab3e56cb.tar.bz2
mpv-88d79fc00df39dc0180de86c758697f5ab3e56cb.tar.xz
mp_msg: introduce new log functions and macros
This has two goals: 1. Getting rid of global variables to make the core library-safe. 2. Getting rid of all the MSGT_* constants and the inconsistent prefixes spread throughout the source code. Both goals are not immediately reached with this commit. It's a huge transition that will take time. There are over >2500 mp_msg calls in the source, which all have to be replaced for this to work. The inconsistent prefixes are in particular annoying. Lots of code manually prefixes messages, e.g. mp_msg(MSGT_VO, MSGL_V, "[vo] ..."). Sometimes the prefixes don't even follow this convention (for example vo_direct3d.c uses "<vo_direct3d>" as prefix). This commit allows automatically adding prefixes on request, so consistency will hopefully improve. For now, this commit adds unused stuff, and behavior should not change. In mplayer.c, move the GetCpuCaps() call, because that used mp_msg() before mp_msg_init() was run.
-rw-r--r--core/mp_core.h2
-rw-r--r--core/mp_msg.c251
-rw-r--r--core/mp_msg.h35
-rw-r--r--core/mplayer.c21
-rw-r--r--core/mpv_global.h12
5 files changed, 255 insertions, 66 deletions
diff --git a/core/mp_core.h b/core/mp_core.h
index d2eb8ef296..39a05e0e3b 100644
--- a/core/mp_core.h
+++ b/core/mp_core.h
@@ -113,7 +113,9 @@ enum {
};
typedef struct MPContext {
+ struct mpv_global *global;
struct MPOpts *opts;
+ struct mp_log *log;
struct m_config *mconfig;
struct input_ctx *input;
struct osd_state *osd;
diff --git a/core/mp_msg.c b/core/mp_msg.c
index 86a544316e..e9348dbf59 100644
--- a/core/mp_msg.c
+++ b/core/mp_msg.c
@@ -21,8 +21,12 @@
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#include <assert.h>
+
+#include "talloc.h"
#include "config.h"
+#include "core/mpv_global.h"
#include "osdep/getch2.h"
#include "osdep/io.h"
@@ -39,6 +43,25 @@
bool mp_msg_stdout_in_use = 0;
+struct mp_log_root {
+ /* This should, at some point, contain all mp_msg related state, instead
+ * of having global variables (at least as long as we don't want to
+ * control the terminal, which is global anyway). But for now, there is
+ * not much. */
+ struct mpv_global *global;
+};
+
+struct mp_log {
+ struct mp_log_root *root;
+ const char *prefix;
+ const char *verbose_prefix;
+ int legacy_mod;
+};
+
+// should not exist
+static bool initialized;
+static struct mp_log *legacy_logs[MSGT_MAX];
+
/* maximum message length of mp_msg */
#define MSGSIZE_MAX 6144
@@ -74,7 +97,7 @@ static int mp_msg_docolor(void) {
return mp_msg_cancolor && mp_msg_color;
}
-void mp_msg_init(void){
+static void mp_msg_do_init(void){
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO cinfo;
DWORD cmode = 0;
@@ -121,6 +144,11 @@ int mp_msg_test(int mod, int lev)
return lev <= (mp_msg_levels[mod] == -2 ? mp_msg_level_all + verbose : mp_msg_levels[mod]);
}
+bool mp_msg_test_log(struct mp_log *log, int lev)
+{
+ return mp_msg_test(log->legacy_mod, lev);
+}
+
static void set_msg_color(FILE* stream, int lev)
{
static const int v_colors[10] = {9, 1, 3, 3, -1, -1, 2, 8, 8, 8};
@@ -153,78 +181,30 @@ static void set_msg_color(FILE* stream, int lev)
}
}
-static void print_msg_module(FILE* stream, int mod)
+static void print_msg_module(FILE* stream, struct mp_log *log)
{
- 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 mod = log->legacy_mod;
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]);
+ fprintf(stream, "%9s", log->verbose_prefix);
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]);
+ fprintf(stream, "%9s", log->verbose_prefix);
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)
+static void mp_msg_log_va(struct mp_log *log, int lev, const char *format,
+ va_list va)
{
char tmp[MSGSIZE_MAX];
FILE *stream =
@@ -233,7 +213,7 @@ void mp_msg_va(int mod, int lev, const char *format, va_list va)
// indicates if last line printed was a status line
static int statusline;
- if (!mp_msg_test(mod, lev)) return; // do not display
+ if (!mp_msg_test_log(log, lev)) return; // do not display
vsnprintf(tmp, MSGSIZE_MAX, format, va);
tmp[MSGSIZE_MAX-2] = '\n';
tmp[MSGSIZE_MAX-1] = 0;
@@ -245,9 +225,17 @@ void mp_msg_va(int mod, int lev, const char *format, va_list va)
fprintf(stderr, "\n");
statusline = lev == MSGL_STATUS;
- if (header)
- print_msg_module(stream, mod);
set_msg_color(stream, lev);
+ if (header) {
+ if (mp_msg_module) {
+ print_msg_module(stream, log);
+ set_msg_color(stream, lev);
+ } else if (lev >= MSGL_V || verbose) {
+ fprintf(stream, "[%s] ", log->verbose_prefix);
+ } else if (log->prefix) {
+ fprintf(stream, "[%s] ", log->prefix);
+ }
+ }
size_t len = strlen(tmp);
header = len && (tmp[len-1] == '\n' || tmp[len-1] == '\r');
@@ -266,6 +254,13 @@ void mp_msg_va(int mod, int lev, const char *format, va_list va)
fflush(stream);
}
+void mp_msg_va(int mod, int lev, const char *format, va_list va)
+{
+ assert(initialized);
+ assert(mod >= 0 && mod < MSGT_MAX);
+ mp_msg_log_va(legacy_logs[mod], lev, format, va);
+}
+
void mp_msg(int mod, int lev, const char *format, ...)
{
va_list va;
@@ -334,3 +329,143 @@ void mp_tmsg(int mod, int lev, const char *format, ...)
mp_msg_va(mod, lev, mp_gtext(format), va);
va_end(va);
}
+
+// legacy names
+static const char *module_text[MSGT_MAX] = {
+ "global",
+ "cplayer",
+ "gplayer",
+ "vo",
+ "ao",
+ "demuxer",
+ "ds",
+ "demux",
+ "header",
+ "avsync",
+ "autoq",
+ "cfgparser",
+ "decaudio",
+ "decvideo",
+ "seek",
+ "win32",
+ "open",
+ "dvd",
+ "parsees",
+ "lirc",
+ "stream",
+ "cache",
+ "mencoder",
+ "xacodec",
+ "tv",
+ "osdep",
+ "spudec",
+ "playtree",
+ "input",
+ "vf",
+ "osd",
+ "network",
+ "cpudetect",
+ "codeccfg",
+ "sws",
+ "vobsub",
+ "subreader",
+ "af",
+ "netst",
+ "muxer",
+ "osdmenu",
+ "identify",
+ "radio",
+ "ass",
+ "loader",
+ "statusline",
+ "teletext",
+};
+
+// Create a new log context, which uses talloc_ctx as talloc parent, and parent
+// as logical parent.
+// The name is the prefix put before the output. It's usually prefixed by the
+// parent's name. If the name starts with "/", the parent's name is not
+// prefixed (except in verbose mode), and if it starts with "!", the name is
+// printed at all (except in verbose mode).
+struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent,
+ const char *name)
+{
+ assert(parent);
+ assert(name);
+ struct mp_log *log = talloc_zero(talloc_ctx, struct mp_log);
+ log->root = parent->root;
+ if (name[0] == '!') {
+ name = &name[1];
+ } else if (name[0] == '/') {
+ name = &name[1];
+ log->prefix = talloc_strdup(log, name);
+ } else {
+ log->prefix = parent->prefix
+ ? talloc_asprintf(log, "%s/%s", parent->prefix, name)
+ : talloc_strdup(log, name);
+ }
+ log->verbose_prefix = parent->prefix
+ ? talloc_asprintf(log, "%s/%s", parent->prefix, name)
+ : talloc_strdup(log, name);
+ if (log->prefix && !log->prefix[0])
+ log->prefix = NULL;
+ if (!log->verbose_prefix[0])
+ log->verbose_prefix = "global";
+ log->legacy_mod = parent->legacy_mod;
+ for (int n = 0; n < MSGT_MAX; n++) {
+ if (module_text[n] && strcmp(name, module_text[n]) == 0) {
+ log->legacy_mod = n;
+ break;
+ }
+ }
+ return log;
+}
+
+void mp_msg_init(struct mpv_global *global)
+{
+ assert(!initialized);
+ assert(!global->log);
+
+ struct mp_log_root *root = talloc_zero(NULL, struct mp_log_root);
+ root->global = global;
+
+ struct mp_log dummy = { .root = root };
+ struct mp_log *log = mp_log_new(root, &dummy, "");
+ for (int n = 0; n < MSGT_MAX; n++) {
+ char name[80];
+ snprintf(name, sizeof(name), "!%s", module_text[n]);
+ legacy_logs[n] = mp_log_new(root, log, name);
+ }
+ mp_msg_do_init();
+
+ global->log = log;
+ initialized = true;
+}
+
+struct mpv_global *mp_log_get_global(struct mp_log *log)
+{
+ return log->root->global;
+}
+
+void mp_msg_uninit(struct mpv_global *global)
+{
+ talloc_free(global->log->root);
+ global->log = NULL;
+ initialized = false;
+}
+
+void mp_msg_log(struct mp_log *log, int lev, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ mp_msg_log_va(log, lev, format, va);
+ va_end(va);
+}
+
+void mp_tmsg_log(struct mp_log *log, int lev, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ mp_msg_log_va(log, lev, mp_gtext(format), va);
+ va_end(va);
+}
diff --git a/core/mp_msg.h b/core/mp_msg.h
index 392adcf01f..4685668f01 100644
--- a/core/mp_msg.h
+++ b/core/mp_msg.h
@@ -20,6 +20,9 @@
#define MPLAYER_MP_MSG_H
#include <stdarg.h>
+#include <stdbool.h>
+
+struct mp_log;
// defined in mplayer.c
extern int verbose;
@@ -126,10 +129,10 @@ extern int verbose;
#define MSGT_TELETEXT 46 // Teletext decoder
-#define MSGT_MAX 64
+#define MSGT_MAX 47
-void mp_msg_init(void);
int mp_msg_test(int mod, int lev);
+bool mp_msg_test_log(struct mp_log *log, int lev);
#include "config.h"
#include "core/mp_common.h"
@@ -142,6 +145,34 @@ void mp_msg(int mod, int lev, const char *format, ... ) PRINTF_ATTRIBUTE(3, 4);
void mp_tmsg(int mod, int lev, const char *format, ... ) PRINTF_ATTRIBUTE(3, 4);
#define mp_dbg mp_msg
+struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent,
+ const char *name);
+
+void mp_msg_log(struct mp_log *log, int lev, const char *format, ...)
+ PRINTF_ATTRIBUTE(3, 4);
+void mp_tmsg_log(struct mp_log *log, int lev, const char *format, ...)
+ PRINTF_ATTRIBUTE(3, 4);
+
+// Convenience macros, typically called with a pointer to a context struct
+// as first argument, which has a "struct mp_log log;" member.
+
+#define MP_MSG(obj, lev, ...) mp_msg_log((obj)->log, lev, __VA_ARGS__)
+#define MP_MSGT(obj, lev, ...) mp_msgt_log((obj)->log, lev, __VA_ARGS__)
+
+#define MP_FATAL(obj, ...) MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
+#define MP_ERR(obj, ...) MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
+#define MP_WARN(obj, ...) MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
+#define MP_INFO(obj, ...) MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
+#define MP_VERBOSE(obj, ...) MP_MSG(obj, MSGL_V, __VA_ARGS__)
+#define MP_DBG(obj, ...) MP_MSG(obj, MSGL_DGB2, __VA_ARGS__)
+#define MP_TRACE(obj, ...) MP_MSG(obj, MSGL_DGB5, __VA_ARGS__)
+
+struct mpv_global;
+void mp_msg_init(struct mpv_global *global);
+void mp_msg_uninit(struct mpv_global *global);
+
+struct mpv_global *mp_log_get_global(struct mp_log *log);
+
extern bool mp_msg_stdout_in_use;
#endif /* MPLAYER_MP_MSG_H */
diff --git a/core/mplayer.c b/core/mplayer.c
index 0238e10be3..626c95111f 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -63,6 +63,7 @@
#include <errno.h>
+#include "core/mpv_global.h"
#include "core/mp_msg.h"
#include "av_log.h"
@@ -585,6 +586,8 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx,
// must be last since e.g. mp_msg uses option values
// that will be freed by this.
+
+ mp_msg_uninit(mpctx->global);
talloc_free(mpctx);
#ifdef CONFIG_COCOA
@@ -4562,8 +4565,6 @@ static void osdep_preinit(int *p_argc, char ***p_argv)
if (enable_talloc && strcmp(enable_talloc, "1") == 0)
talloc_enable_leak_report();
- GetCpuCaps(&gCpuCaps);
-
#ifdef __MINGW32__
mp_get_converted_argv(p_argc, p_argv);
#endif
@@ -4603,10 +4604,6 @@ static int mpv_main(int argc, char *argv[])
.playlist = talloc_struct(mpctx, struct playlist, {0}),
};
- mp_msg_init();
- init_libav();
- screenshot_init(mpctx);
-
// Create the config context and register the options
mpctx->mconfig = m_config_new(mpctx, sizeof(struct MPOpts),
&mp_default_opts, mp_opts, NULL);
@@ -4616,6 +4613,18 @@ static int mpv_main(int argc, char *argv[])
struct MPOpts *opts = mpctx->opts;
+
+ mpctx->global = talloc_zero(mpctx, struct mpv_global);
+ mpctx->global->opts = opts;
+
+ // Nothing must call mp_msg() before this
+ mp_msg_init(mpctx->global);
+ mpctx->log = mp_log_new(mpctx, mpctx->global->log, "!mpv");
+
+ init_libav();
+ GetCpuCaps(&gCpuCaps);
+ screenshot_init(mpctx);
+
// Preparse the command line
m_config_preparse_command_line(mpctx->mconfig, argc, argv);
diff --git a/core/mpv_global.h b/core/mpv_global.h
new file mode 100644
index 0000000000..546c585294
--- /dev/null
+++ b/core/mpv_global.h
@@ -0,0 +1,12 @@
+#ifndef MPV_MPV_H
+#define MPV_MPV_H
+
+// This should be accessed by glue code only, never normal code.
+// The only purpose of this is to make mpv library-safe.
+// Think hard before adding new members.
+struct mpv_global {
+ struct MPOpts *opts;
+ struct mp_log *log;
+};
+
+#endif