diff options
Diffstat (limited to 'player')
-rw-r--r-- | player/client.c | 32 | ||||
-rw-r--r-- | player/command.h | 2 |
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, |