From 6a8fc3f5e38f93c36d18ad8407d4f3f345d893db Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 18 Dec 2013 19:04:30 +0100 Subject: msg: change --msglevel, reduce legacy glue Basically, reimplement --msglevel. Instead of making the new msg code use the legacy code, make the legacy code use the reimplemented functionality. The handling of the deprecated --identify switch changes. It temporarily stops working; this will be fixed in later commits. The actual sub-options syntax (like --msglevel-vo=...) goes away, but I bet nobody knew about this or used this anyway. --- common/msg.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 112 insertions(+), 25 deletions(-) (limited to 'common/msg.c') diff --git a/common/msg.c b/common/msg.c index 9c90512798..390794b4cd 100644 --- a/common/msg.c +++ b/common/msg.c @@ -22,10 +22,15 @@ #include #include #include +#include #include "talloc.h" +#include "bstr/bstr.h" +#include "compat/atomics.h" +#include "common/common.h" #include "common/global.h" +#include "options/options.h" #include "osdep/terminal.h" #include "osdep/io.h" @@ -40,24 +45,32 @@ struct mp_log_root { * control the terminal, which is global anyway). But for now, there is * not much. */ struct mpv_global *global; + char *msglevels; // protected by mp_msg_lock + /* This is incremented every time the msglevels must be reloaded. + * (This is perhaps better than maintaining a globally accessible and + * synchronized mp_log tree.) */ + int64_t reload_counter; }; struct mp_log { struct mp_log_root *root; const char *prefix; const char *verbose_prefix; - int legacy_mod; + int level; + int64_t reload_counter; }; +// Protects some (not all) state in mp_log_root +static pthread_mutex_t mp_msg_lock = PTHREAD_MUTEX_INITIALIZER; + // should not exist static bool initialized; static struct mp_log *legacy_logs[MSGT_MAX]; bool mp_msg_stdout_in_use; -int mp_msg_levels[MSGT_MAX]; // verbose level of this module. initialized to -2 -int mp_msg_level_all = MSGL_STATUS; int verbose; bool mp_msg_mute; +int mp_smode; int mp_msg_color = 1; int mp_msg_module; int mp_msg_cancolor; @@ -67,31 +80,57 @@ static int header = 1; // indicates if last line printed was a status line static int statusline; -static void mp_msg_do_init(void){ - int i; +static const struct mp_log null_log = {0}; +struct mp_log *const mp_null_log = (struct mp_log *)&null_log; + +static void mp_msg_do_init(void) +{ char *env = getenv("MPV_VERBOSE"); if (env) verbose = atoi(env); - for(i=0;ilevel = MSGL_STATUS + verbose; // default log level + // Stupid exception for the remains of -identify + if (match_mod(log->verbose_prefix, bstr0("identify"))) + log->level = -1; + bstr s = bstr0(log->root->msglevels); + bstr mod; + int level; + while (mp_msg_split_msglevel(&s, &mod, &level) > 0) { + if (match_mod(log->verbose_prefix, mod)) + log->level = level; + } + log->reload_counter = log->root->reload_counter; + pthread_mutex_unlock(&mp_msg_lock); +} + +bool mp_msg_test_log(struct mp_log *log, int lev) +{ + if (mp_msg_mute || !log->root) return false; if (lev == MSGL_STATUS) { // skip status line output if stderr is a tty but in background if (terminal_in_background()) return false; } - 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); + mp_memory_barrier(); + if (log->reload_counter != log->root->reload_counter) + update_loglevel(log); + return lev <= log->level || (mp_smode && lev == MSGL_SMODE); } static int mp_msg_docolor(void) @@ -101,13 +140,12 @@ static int mp_msg_docolor(void) 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}; + static const int v_colors[] = {9, 1, 3, 3, -1, -1, 2, 8, 8, 8, 9}; if (mp_msg_docolor()) terminal_set_foreground_color(stream, v_colors[lev]); } -static void mp_msg_log_va(struct mp_log *log, int lev, const char *format, - va_list va) +void mp_msg_log_va(struct mp_log *log, int lev, const char *format, va_list va) { char tmp[MSGSIZE_MAX]; FILE *stream = @@ -161,6 +199,13 @@ void mp_msg(int mod, int lev, const char *format, ...) va_end(va); } +int mp_msg_test(int mod, int lev) +{ + assert(initialized); + assert(mod >= 0 && mod < MSGT_MAX); + return mp_msg_test_log(legacy_logs[mod], lev); +} + // legacy names static const char *module_text[MSGT_MAX] = { "global", @@ -224,6 +269,8 @@ struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent, assert(parent); assert(name); struct mp_log *log = talloc_zero(talloc_ctx, struct mp_log); + if (!parent->root) + return log; // same as null_log log->root = parent->root; if (name[0] == '!') { name = &name[1]; @@ -242,13 +289,6 @@ struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent, 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; } @@ -259,6 +299,7 @@ void mp_msg_init(struct mpv_global *global) struct mp_log_root *root = talloc_zero(NULL, struct mp_log_root); root->global = global; + root->reload_counter = 1; struct mp_log dummy = { .root = root }; struct mp_log *log = mp_log_new(root, &dummy, ""); @@ -278,6 +319,17 @@ struct mpv_global *mp_log_get_global(struct mp_log *log) return log->root->global; } +void mp_msg_update_msglevels(struct mpv_global *global) +{ + struct mp_log_root *root = global->log->root; + pthread_mutex_lock(&mp_msg_lock); + talloc_free(root->msglevels); + root->msglevels = talloc_strdup(root, global->opts->msglevels); + mp_atomic_add_and_fetch(&root->reload_counter, 1); + mp_memory_barrier(); + pthread_mutex_unlock(&mp_msg_lock); +} + void mp_msg_uninit(struct mpv_global *global) { talloc_free(global->log->root); @@ -292,3 +344,38 @@ void mp_msg_log(struct mp_log *log, int lev, const char *format, ...) mp_msg_log_va(log, lev, format, va); va_end(va); } + +static const char *level_names[] = { + [MSGL_FATAL] = "fatal", + [MSGL_ERR] = "error", + [MSGL_WARN] = "warn", + [MSGL_INFO] = "info", + [MSGL_STATUS] = "status", + [MSGL_V] = "v", + [MSGL_DBG2] = "debug", + [MSGL_DBG5] = "trace", +}; + +int mp_msg_split_msglevel(struct bstr *s, struct bstr *out_mod, int *out_level) +{ + if (s->len == 0) + return 0; + bstr elem, rest; + bstr_split_tok(*s, ":", &elem, &rest); + bstr mod, level; + if (!bstr_split_tok(elem, "=", &mod, &level) || mod.len == 0) + return -1; + int ilevel = -1; + for (int n = 0; n < MP_ARRAY_SIZE(level_names); n++) { + if (level_names[n] && bstr_equals0(level, level_names[n])) { + ilevel = n; + break; + } + } + if (ilevel < 0 && !bstr_equals0(level, "no")) + return -1; + *s = rest; + *out_mod = mod; + *out_level = ilevel; + return 1; +} -- cgit v1.2.3