mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
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.
This commit is contained in:
137
common/msg.c
137
common/msg.c
@@ -22,10 +22,15 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#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;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
|
||||
}
|
||||
|
||||
int mp_msg_test(int mod, int lev)
|
||||
static bool match_mod(const char *name, bstr mod)
|
||||
{
|
||||
if (mp_msg_mute)
|
||||
if (bstr_equals0(mod, "all"))
|
||||
return true;
|
||||
// Path prefix matches
|
||||
bstr b = bstr0(name);
|
||||
return bstr_eatstart(&b, mod) && (bstr_eatstart0(&b, "/") || !b.len);
|
||||
}
|
||||
|
||||
static void update_loglevel(struct mp_log *log)
|
||||
{
|
||||
pthread_mutex_lock(&mp_msg_lock);
|
||||
log->level = 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;
|
||||
}
|
||||
|
||||
12
common/msg.h
12
common/msg.h
@@ -31,6 +31,10 @@ struct mp_log;
|
||||
extern int verbose;
|
||||
extern bool mp_msg_mute;
|
||||
extern bool mp_msg_stdout_in_use;
|
||||
extern int mp_smode; // slave mode compatibility glue
|
||||
|
||||
// A mp_log instance that never outputs anything.
|
||||
extern struct mp_log *const mp_null_log;
|
||||
|
||||
// Verbosity levels.
|
||||
#define MSGL_FATAL 0 // will exit/abort (note: msg.c doesn't exit or abort)
|
||||
@@ -44,18 +48,19 @@ extern bool mp_msg_stdout_in_use;
|
||||
#define MSGL_DBG3 8 // ...
|
||||
#define MSGL_DBG4 9 // ....
|
||||
#define MSGL_DBG5 10 // .....
|
||||
#define MSGL_SMODE 11 // old slave mode (-identify)
|
||||
|
||||
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_msg_log_va(struct mp_log *log, int lev, const char *format, va_list va);
|
||||
|
||||
// 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__)
|
||||
@@ -64,6 +69,7 @@ void mp_msg_log(struct mp_log *log, int lev, const char *format, ...)
|
||||
#define MP_VERBOSE(obj, ...) MP_MSG(obj, MSGL_V, __VA_ARGS__)
|
||||
#define MP_DBG(obj, ...) MP_MSG(obj, MSGL_DBG2, __VA_ARGS__)
|
||||
#define MP_TRACE(obj, ...) MP_MSG(obj, MSGL_DBG5, __VA_ARGS__)
|
||||
#define MP_SMODE(obj, ...) MP_MSG(obj, MSGL_SMODE, __VA_ARGS__)
|
||||
|
||||
#define mp_fatal(log, ...) mp_msg_log(log, MSGL_FATAL, __VA_ARGS__)
|
||||
#define mp_err(log, ...) mp_msg_log(log, MSGL_ERR, __VA_ARGS__)
|
||||
@@ -76,9 +82,13 @@ void mp_msg_log(struct mp_log *log, int lev, const char *format, ...)
|
||||
struct mpv_global;
|
||||
void mp_msg_init(struct mpv_global *global);
|
||||
void mp_msg_uninit(struct mpv_global *global);
|
||||
void mp_msg_update_msglevels(struct mpv_global *global);
|
||||
|
||||
struct mpv_global *mp_log_get_global(struct mp_log *log);
|
||||
|
||||
struct bstr;
|
||||
int mp_msg_split_msglevel(struct bstr *s, struct bstr *out_mod, int *out_level);
|
||||
|
||||
// --- Legacy
|
||||
|
||||
// Note: using mp_msg_log or the MP_ERR/... macros is preferred.
|
||||
|
||||
Reference in New Issue
Block a user