mirror of https://github.com/mpv-player/mpv
player: remove mechanisms for better logging with repl.lua
As preparation for making repl.lua part of the core (maybe), add some mechanisms which are supposed to improve its behavior. Add a silent mode. Calling mpv_request_log_messages() with the log level name prefixed with "silent:" will disable logging from the API user's perspective. But it will keep the log buffer, and record new messages, without returning them to the user. If logging is enabled again by requesting the same log level without "silent:" prefix, the buffered log messages are returned to the user at once. This is not documented, because it's far too messy and special as that I'd want anyone to rely on this behavior, but it will be perfectly fine for an internal script. Another thing is that we record early startup messages. The goal is to make the repl.lua script show option and config parsing file errors. This works only with the special "terminal-default" log level. In addition, reduce the "terminal-default" capacity to only 100 log messages. If this is going to be enabled by default, it shouldn't use too much resources.
This commit is contained in:
parent
8e5642ff68
commit
8c2d73f112
60
common/msg.c
60
common/msg.c
|
@ -43,6 +43,8 @@
|
|||
#include "msg.h"
|
||||
#include "msg_control.h"
|
||||
|
||||
#define TERM_BUF 100
|
||||
|
||||
struct mp_log_root {
|
||||
struct mpv_global *global;
|
||||
// --- protected by mp_msg_lock
|
||||
|
@ -58,6 +60,7 @@ struct mp_log_root {
|
|||
bool force_stderr;
|
||||
struct mp_log_buffer **buffers;
|
||||
int num_buffers;
|
||||
struct mp_log_buffer *early_buffer;
|
||||
FILE *log_file;
|
||||
FILE *stats_file;
|
||||
char *log_path;
|
||||
|
@ -85,6 +88,7 @@ struct mp_log_buffer {
|
|||
struct mp_log_root *root;
|
||||
struct mp_ring *ring;
|
||||
int level;
|
||||
atomic_bool silent;
|
||||
void (*wakeup_cb)(void *ctx);
|
||||
void *wakeup_cb_ctx;
|
||||
};
|
||||
|
@ -323,7 +327,7 @@ static void write_msg_to_buffers(struct mp_log *log, int lev, char *text)
|
|||
};
|
||||
}
|
||||
mp_ring_write(buffer->ring, (unsigned char *)&entry, sizeof(entry));
|
||||
if (buffer->wakeup_cb)
|
||||
if (buffer->wakeup_cb && !atomic_load(&buffer->silent))
|
||||
buffer->wakeup_cb(buffer->wakeup_cb_ctx);
|
||||
}
|
||||
}
|
||||
|
@ -548,6 +552,9 @@ bool mp_msg_has_log_file(struct mpv_global *global)
|
|||
void mp_msg_uninit(struct mpv_global *global)
|
||||
{
|
||||
struct mp_log_root *root = global->log->root;
|
||||
if (root->early_buffer)
|
||||
mp_msg_log_buffer_destroy(root->early_buffer);
|
||||
assert(root->num_buffers == 0);
|
||||
if (root->stats_file)
|
||||
fclose(root->stats_file);
|
||||
talloc_free(root->stats_path);
|
||||
|
@ -559,6 +566,32 @@ void mp_msg_uninit(struct mpv_global *global)
|
|||
global->log = NULL;
|
||||
}
|
||||
|
||||
void mp_msg_set_early_logging(struct mpv_global *global, bool enable)
|
||||
{
|
||||
struct mp_log_root *root = global->log->root;
|
||||
pthread_mutex_lock(&mp_msg_lock);
|
||||
|
||||
if (enable != !!root->early_buffer) {
|
||||
if (enable) {
|
||||
pthread_mutex_unlock(&mp_msg_lock);
|
||||
struct mp_log_buffer *buf =
|
||||
mp_msg_log_buffer_new(global, TERM_BUF, MP_LOG_BUFFER_MSGL_TERM,
|
||||
NULL, NULL);
|
||||
pthread_mutex_lock(&mp_msg_lock);
|
||||
assert(!root->early_buffer); // no concurrent calls to this function
|
||||
root->early_buffer = buf;
|
||||
} else {
|
||||
struct mp_log_buffer *buf = root->early_buffer;
|
||||
root->early_buffer = NULL;
|
||||
pthread_mutex_unlock(&mp_msg_lock);
|
||||
mp_msg_log_buffer_destroy(buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mp_msg_lock);
|
||||
}
|
||||
|
||||
struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
|
||||
int size, int level,
|
||||
void (*wakeup_cb)(void *ctx),
|
||||
|
@ -568,6 +601,21 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
|
|||
|
||||
pthread_mutex_lock(&mp_msg_lock);
|
||||
|
||||
if (level == MP_LOG_BUFFER_MSGL_TERM) {
|
||||
size = TERM_BUF;
|
||||
|
||||
// The first thing which creates a terminal-level log buffer gets the
|
||||
// early log buffer, if it exists. This is supposed to enable a script
|
||||
// to grab log messages from before it was initialized. It's OK that
|
||||
// this works only for 1 script and only once.
|
||||
if (root->early_buffer) {
|
||||
struct mp_log_buffer *buffer = root->early_buffer;
|
||||
root->early_buffer = NULL;
|
||||
pthread_mutex_unlock(&mp_msg_lock);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
struct mp_log_buffer *buffer = talloc_ptrtype(NULL, buffer);
|
||||
*buffer = (struct mp_log_buffer) {
|
||||
.root = root,
|
||||
|
@ -587,6 +635,13 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
|
|||
return buffer;
|
||||
}
|
||||
|
||||
void mp_msg_log_buffer_set_silent(struct mp_log_buffer *buffer, bool silent)
|
||||
{
|
||||
pthread_mutex_lock(&mp_msg_lock);
|
||||
atomic_store(&buffer->silent, silent);
|
||||
pthread_mutex_unlock(&mp_msg_lock);
|
||||
}
|
||||
|
||||
void mp_msg_log_buffer_destroy(struct mp_log_buffer *buffer)
|
||||
{
|
||||
if (!buffer)
|
||||
|
@ -607,6 +662,7 @@ void mp_msg_log_buffer_destroy(struct mp_log_buffer *buffer)
|
|||
found:
|
||||
|
||||
while (1) {
|
||||
atomic_store(&buffer->silent, false);
|
||||
struct mp_log_buffer_entry *e = mp_msg_log_buffer_read(buffer);
|
||||
if (!e)
|
||||
break;
|
||||
|
@ -622,6 +678,8 @@ found:
|
|||
// Thread-safety: one buffer can be read by a single thread only.
|
||||
struct mp_log_buffer_entry *mp_msg_log_buffer_read(struct mp_log_buffer *buffer)
|
||||
{
|
||||
if (atomic_load(&buffer->silent))
|
||||
return NULL;
|
||||
void *ptr = NULL;
|
||||
int read = mp_ring_read(buffer->ring, (unsigned char *)&ptr, sizeof(ptr));
|
||||
if (read == 0)
|
||||
|
|
|
@ -11,6 +11,7 @@ void mp_msg_update_msglevels(struct mpv_global *global, struct MPOpts *opts);
|
|||
void mp_msg_force_stderr(struct mpv_global *global, bool force_stderr);
|
||||
bool mp_msg_has_status_line(struct mpv_global *global);
|
||||
bool mp_msg_has_log_file(struct mpv_global *global);
|
||||
void mp_msg_set_early_logging(struct mpv_global *global, bool enable);
|
||||
|
||||
void mp_msg_flush_status_line(struct mp_log *log);
|
||||
|
||||
|
@ -30,6 +31,7 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
|
|||
void *wakeup_cb_ctx);
|
||||
void mp_msg_log_buffer_destroy(struct mp_log_buffer *buffer);
|
||||
struct mp_log_buffer_entry *mp_msg_log_buffer_read(struct mp_log_buffer *buffer);
|
||||
void mp_msg_log_buffer_set_silent(struct mp_log_buffer *buffer, bool silent);
|
||||
|
||||
int mp_msg_find_level(const char *s);
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ struct mpv_handle {
|
|||
bool fuzzy_initialized; // see scripting.c wait_loaded()
|
||||
bool is_weak; // can not keep core alive on its own
|
||||
struct mp_log_buffer *messages;
|
||||
int messages_level;
|
||||
};
|
||||
|
||||
static bool gen_log_message_event(struct mpv_handle *ctx);
|
||||
|
@ -1703,29 +1704,43 @@ static void msg_wakeup(void *p)
|
|||
wakeup_client(ctx);
|
||||
}
|
||||
|
||||
// Undocumented: if min_level starts with "silent:", then log messages are not
|
||||
// returned to the API user, but are stored until logging is enabled normally
|
||||
// again by calling this without "silent:". (Using a different level will
|
||||
// flush it, though.)
|
||||
int mpv_request_log_messages(mpv_handle *ctx, const char *min_level)
|
||||
{
|
||||
bstr blevel = bstr0(min_level);
|
||||
bool silent = bstr_eatstart0(&blevel, "silent:");
|
||||
|
||||
int level = -1;
|
||||
for (int n = 0; n < MSGL_MAX + 1; n++) {
|
||||
if (mp_log_levels[n] && strcmp(min_level, mp_log_levels[n]) == 0) {
|
||||
if (mp_log_levels[n] && bstr_equals0(blevel, mp_log_levels[n])) {
|
||||
level = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strcmp(min_level, "terminal-default") == 0)
|
||||
if (bstr_equals0(blevel, "terminal-default"))
|
||||
level = MP_LOG_BUFFER_MSGL_TERM;
|
||||
|
||||
if (level < 0 && strcmp(min_level, "no") != 0)
|
||||
return MPV_ERROR_INVALID_PARAMETER;
|
||||
|
||||
pthread_mutex_lock(&ctx->lock);
|
||||
mp_msg_log_buffer_destroy(ctx->messages);
|
||||
ctx->messages = NULL;
|
||||
if (level >= 0) {
|
||||
int size = level >= MSGL_V ? 10000 : 1000;
|
||||
ctx->messages = mp_msg_log_buffer_new(ctx->mpctx->global, size, level,
|
||||
msg_wakeup, ctx);
|
||||
if (level < 0 || level != ctx->messages_level) {
|
||||
mp_msg_log_buffer_destroy(ctx->messages);
|
||||
ctx->messages = NULL;
|
||||
}
|
||||
if (level >= 0) {
|
||||
if (!ctx->messages) {
|
||||
int size = level >= MSGL_V ? 10000 : 1000;
|
||||
ctx->messages = mp_msg_log_buffer_new(ctx->mpctx->global, size,
|
||||
level, msg_wakeup, ctx);
|
||||
ctx->messages_level = level;
|
||||
}
|
||||
mp_msg_log_buffer_set_silent(ctx->messages, silent);
|
||||
}
|
||||
wakeup_client(ctx);
|
||||
pthread_mutex_unlock(&ctx->lock);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "client.h"
|
||||
#include "common/msg.h"
|
||||
#include "common/msg_control.h"
|
||||
#include "common/global.h"
|
||||
#include "options/path.h"
|
||||
#include "options/m_config.h"
|
||||
|
@ -1766,6 +1767,8 @@ void mp_play_files(struct MPContext *mpctx)
|
|||
mp_wakeup_core(mpctx); // avoid lost wakeups during waiting
|
||||
MP_VERBOSE(mpctx, "Done loading scripts.\n");
|
||||
}
|
||||
// After above is finished; but even if it's skipped.
|
||||
mp_msg_set_early_logging(mpctx->global, false);
|
||||
|
||||
prepare_playlist(mpctx, mpctx->playlist);
|
||||
|
||||
|
|
|
@ -345,6 +345,7 @@ int mp_initialize(struct MPContext *mpctx, char **options)
|
|||
}
|
||||
|
||||
mp_init_paths(mpctx->global, opts);
|
||||
mp_msg_set_early_logging(mpctx->global, true);
|
||||
mp_update_logging(mpctx, true);
|
||||
|
||||
if (options) {
|
||||
|
|
Loading…
Reference in New Issue