diff --git a/audio/out/ao.c b/audio/out/ao.c index 73131020c0..fa6cc9e76d 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -444,10 +444,14 @@ int ao_query_and_reset_events(struct ao *ao, int events) return atomic_fetch_and(&ao->events_, ~(unsigned)events) & events; } -void ao_add_events(struct ao *ao, int events) +// Returns events that were set by this calls. +int ao_add_events(struct ao *ao, int events) { - atomic_fetch_or(&ao->events_, events); - ao->wakeup_cb(ao->wakeup_ctx); + unsigned prev_events = atomic_fetch_or(&ao->events_, events); + unsigned new = events & ~prev_events; + if (new) + ao->wakeup_cb(ao->wakeup_ctx); + return new; } // Request that the player core destroys and recreates the AO. Fully thread-safe. @@ -462,12 +466,13 @@ void ao_hotplug_event(struct ao *ao) ao_add_events(ao, AO_EVENT_HOTPLUG); } -void ao_underrun_event(struct ao *ao) +// Returns whether this call actually set a new underrun flag. +bool ao_underrun_event(struct ao *ao) { - // Racy check, but it's just for the message. - if (!(atomic_load(&ao->events_) & AO_EVENT_UNDERRUN)) + bool new_underrun = ao_add_events(ao, AO_EVENT_UNDERRUN); + if (new_underrun) MP_WARN(ao, "Device underrun detected.\n"); - ao_add_events(ao, AO_EVENT_UNDERRUN); + return new_underrun; } bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, diff --git a/audio/out/ao.h b/audio/out/ao.h index f6b984ff30..eb9e29dacb 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -110,7 +110,7 @@ void ao_resume(struct ao *ao); void ao_drain(struct ao *ao); bool ao_eof_reached(struct ao *ao); int ao_query_and_reset_events(struct ao *ao, int events); -void ao_add_events(struct ao *ao, int events); +int ao_add_events(struct ao *ao, int events); void ao_unblock(struct ao *ao); void ao_request_reload(struct ao *ao); void ao_hotplug_event(struct ao *ao); diff --git a/audio/out/internal.h b/audio/out/internal.h index d1d7482ec1..7d1d744991 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -211,7 +211,7 @@ struct pollfd; int ao_wait_poll(struct ao *ao, struct pollfd *fds, int num_fds, pthread_mutex_t *lock); void ao_wakeup_poll(struct ao *ao); -void ao_underrun_event(struct ao *ao); +bool ao_underrun_event(struct ao *ao); bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map);