From b021d038c2217903e511ca3673d5f2f1b996c4d4 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 9 Nov 2014 09:58:44 +0100 Subject: audio/out: make ao_request_reload() idempotent This is what you would expect. Before this commit, each ao_request_reload() call would just queue a reload command, and then recreate the AO for the number of times the function was called. Instead of sending a command, introduce some sort of event retrieval mechanism. At least for the reload case, use atomics, because we're too lazy to setup an extra mutex. --- audio/out/ao.c | 23 ++++++++++++++++------- audio/out/ao.h | 6 ++++++ audio/out/internal.h | 5 +++-- player/audio.c | 5 +++++ player/command.c | 7 +------ 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/audio/out/ao.c b/audio/out/ao.c index baf6db1e45..b92a78ff26 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -397,6 +397,22 @@ bool ao_eof_reached(struct ao *ao) return ao->api->get_eof ? ao->api->get_eof(ao) : true; } +// Query the AO_EVENT_*s as requested by the events parameter, and return them. +int ao_query_and_reset_events(struct ao *ao, int events) +{ + int actual_events = 0; + if (atomic_load(&ao->request_reload)) // don't need to reset it + actual_events |= AO_EVENT_RELOAD; + return actual_events & events; +} + +// Request that the player core destroys and recreates the AO. +void ao_request_reload(struct ao *ao) +{ + atomic_store(&ao->request_reload, true); + mp_input_wakeup(ao->input_ctx); +} + bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map) { @@ -409,13 +425,6 @@ bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, return mp_chmap_sel_get_def(s, map, num); } -// Request that the player core destroys and recreates the AO. -void ao_request_reload(struct ao *ao) -{ - const char *cmd[] = {"ao_reload", NULL}; - mp_input_run_cmd(ao->input_ctx, cmd); -} - // --- The following functions just return immutable information. void ao_get_format(struct ao *ao, struct mp_audio *format) diff --git a/audio/out/ao.h b/audio/out/ao.h index 3d811fe8d3..f1c922ae69 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -46,6 +46,10 @@ enum aocontrol { // data might be written again, instead of closing the AO. #define AOPLAY_FINAL_CHUNK 1 +enum { + AO_EVENT_RELOAD = 1, +}; + typedef struct ao_control_vol { float left; float right; @@ -85,6 +89,8 @@ void ao_pause(struct ao *ao); 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_request_reload(struct ao *ao); struct ao_device_list *ao_get_device_list(struct mpv_global *global); void ao_print_devices(struct mpv_global *global, struct mp_log *log); diff --git a/audio/out/internal.h b/audio/out/internal.h index 8ba789f603..fbea763306 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -22,6 +22,7 @@ #include #include +#include "osdep/atomics.h" #include "audio/out/ao.h" /* global data used by ao.c and ao drivers */ @@ -55,6 +56,8 @@ struct ao { // Used during init: if init fails, redirect to this ao char *redirect; + atomic_bool request_reload; + int buffer; double def_buffer; void *api_priv; @@ -186,8 +189,6 @@ bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map, int num); -void ao_request_reload(struct ao *ao); - // Add a deep copy of e to the list. // Call from ao_driver->list_devs callback only. void ao_device_list_add(struct ao_device_list *list, struct ao *ao, diff --git a/player/audio.c b/player/audio.c index 8df6053da1..fb3f571cdf 100644 --- a/player/audio.c +++ b/player/audio.c @@ -434,6 +434,11 @@ static void do_fill_audio_out_buffers(struct MPContext *mpctx, double endpts) struct MPOpts *opts = mpctx->opts; struct dec_audio *d_audio = mpctx->d_audio; + if (mpctx->ao && ao_query_and_reset_events(mpctx->ao, AO_EVENT_RELOAD)) { + ao_reset(mpctx->ao); + uninit_audio_out(mpctx); + } + if (!d_audio) return; diff --git a/player/command.c b/player/command.c index 7df0c8a6c3..1968e6d5e5 100644 --- a/player/command.c +++ b/player/command.c @@ -1462,12 +1462,7 @@ static void reload_audio_output(struct MPContext *mpctx) { if (!mpctx->ao) return; - ao_reset(mpctx->ao); - uninit_audio_out(mpctx); - // This normally recreates the AO, although there are situations when AO - // creation is delayed; for example if there are no audio packets around, - // and the audio format is yet unknown. - reinit_audio_chain(mpctx); + ao_request_reload(mpctx->ao); } static int mp_property_audio_device(void *ctx, struct m_property *prop, -- cgit v1.2.3