summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
Diffstat (limited to 'player')
-rw-r--r--player/client.c32
-rw-r--r--player/command.h2
2 files changed, 23 insertions, 11 deletions
diff --git a/player/client.c b/player/client.c
index 50daf45393..c4f02b84c8 100644
--- a/player/client.c
+++ b/player/client.c
@@ -107,7 +107,6 @@ struct mpv_handle {
uint64_t event_mask;
bool queued_wakeup;
- bool choke_warning;
int suspend_count;
mpv_event *events; // ringbuffer of max_events entries
@@ -115,6 +114,7 @@ struct mpv_handle {
int first_event; // events[first_event] is the first readable event
int num_events; // number of readable events
int reserved_events; // number of entries reserved for replies
+ bool choked; // recovering from queue overflow
struct observe_property **properties;
int num_properties;
@@ -541,7 +541,8 @@ static int reserve_reply(struct mpv_handle *ctx)
{
int res = MPV_ERROR_EVENT_QUEUE_FULL;
pthread_mutex_lock(&ctx->lock);
- if (ctx->reserved_events + ctx->num_events < ctx->max_events) {
+ if (ctx->reserved_events + ctx->num_events < ctx->max_events && !ctx->choked)
+ {
ctx->reserved_events++;
res = 0;
}
@@ -567,14 +568,17 @@ static int send_event(struct mpv_handle *ctx, struct mpv_event *event, bool copy
uint64_t mask = 1ULL << event->event_id;
if (ctx->property_event_masks & mask)
notify_property_events(ctx, mask);
+ int r;
if (!(ctx->event_mask & mask)) {
- pthread_mutex_unlock(&ctx->lock);
- return 0;
- }
- int r = append_event(ctx, *event, copy);
- if (r < 0 && !ctx->choke_warning) {
- mp_err(ctx->log, "Too many events queued.\n");
- ctx->choke_warning = true;
+ r = 0;
+ } else if (ctx->choked) {
+ r = -1;
+ } else {
+ r = append_event(ctx, *event, copy);
+ if (r < 0) {
+ MP_ERR(ctx, "Too many events queued.\n");
+ ctx->choked = true;
+ }
}
pthread_mutex_unlock(&ctx->lock);
return r;
@@ -729,6 +733,12 @@ mpv_event *mpv_wait_event(mpv_handle *ctx, double timeout)
while (1) {
if (ctx->queued_wakeup)
deadline = 0;
+ // Recover from overflow.
+ if (ctx->choked && !ctx->num_events) {
+ ctx->choked = false;
+ event->event_id = MPV_EVENT_QUEUE_OVERFLOW;
+ break;
+ }
// This will almost surely lead to a deadlock. (Polling is still ok.)
if (ctx->suspend_count && timeout > 0) {
MP_ERR(ctx, "attempting to wait while core is suspended");
@@ -741,10 +751,11 @@ mpv_event *mpv_wait_event(mpv_handle *ctx, double timeout)
talloc_steal(event, event->data);
break;
}
+ // If there's a changed property, generate change event (never queued).
if (gen_property_change_event(ctx))
break;
+ // Pop item from message queue, and return as event.
if (ctx->messages) {
- // Poll the log message queue. Currently we can't/don't do better.
struct mp_log_buffer_entry *msg =
mp_msg_log_buffer_read(ctx->messages);
if (msg) {
@@ -1608,6 +1619,7 @@ static const char *const event_table[] = {
[MPV_EVENT_PLAYBACK_RESTART] = "playback-restart",
[MPV_EVENT_PROPERTY_CHANGE] = "property-change",
[MPV_EVENT_CHAPTER_CHANGE] = "chapter-change",
+ [MPV_EVENT_QUEUE_OVERFLOW] = "event-queue-overflow",
};
const char *mpv_event_name(mpv_event_id event)
diff --git a/player/command.h b/player/command.h
index d4097fee6f..d6891b66cd 100644
--- a/player/command.h
+++ b/player/command.h
@@ -42,7 +42,7 @@ uint64_t mp_get_property_event_mask(const char *name);
enum {
// Must start with the first unused positive value in enum mpv_event_id
// MPV_EVENT_* and MP_EVENT_* must not overlap.
- INTERNAL_EVENT_BASE = 24,
+ INTERNAL_EVENT_BASE = 25,
MP_EVENT_CACHE_UPDATE,
MP_EVENT_WIN_RESIZE,
MP_EVENT_WIN_STATE,