diff options
-rw-r--r-- | common/msg.c | 60 | ||||
-rw-r--r-- | common/msg_control.h | 2 | ||||
-rw-r--r-- | player/client.c | 29 | ||||
-rw-r--r-- | player/loadfile.c | 3 | ||||
-rw-r--r-- | player/main.c | 1 |
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) { |