summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-11-18 00:44:12 +0100
committerwm4 <wm4@nowhere>2019-11-18 00:44:54 +0100
commit8c2d73f112055a9e52e5bda4934c2ac90e31def7 (patch)
treeb8d768872784e18981197dabf2639a839ba77dad
parent8e5642ff6872d94faf69c6305acdcfd788ddebba (diff)
downloadmpv-8c2d73f112055a9e52e5bda4934c2ac90e31def7.tar.bz2
mpv-8c2d73f112055a9e52e5bda4934c2ac90e31def7.tar.xz
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.
-rw-r--r--common/msg.c60
-rw-r--r--common/msg_control.h2
-rw-r--r--player/client.c29
-rw-r--r--player/loadfile.c3
-rw-r--r--player/main.c1
5 files changed, 87 insertions, 8 deletions
diff --git a/common/msg.c b/common/msg.c
index 42b03ed4e9..8b28d2c1bc 100644
--- a/common/msg.c
+++ b/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)
diff --git a/common/msg_control.h b/common/msg_control.h
index 1e41191f6f..14614abb14 100644
--- a/common/msg_control.h
+++ b/common/msg_control.h
@@ -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);
diff --git a/player/client.c b/player/client.c
index 3a1d204ce8..bc9785d04c 100644
--- a/player/client.c
+++ b/player/client.c
@@ -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 || level != ctx->messages_level) {
+ 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 (!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;
}
diff --git a/player/loadfile.c b/player/loadfile.c
index 09b7167f60..9d515b2012 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -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);
diff --git a/player/main.c b/player/main.c
index b6c9e1085d..d633871399 100644
--- a/player/main.c
+++ b/player/main.c
@@ -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) {