summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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