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:
wm4 2019-11-18 00:44:12 +01:00
parent 8e5642ff68
commit 8c2d73f112
5 changed files with 88 additions and 9 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {