summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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) {