diff options
author | wm4 <wm4@nowhere> | 2014-10-10 18:33:55 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-10-10 18:42:43 +0200 |
commit | f432a584b9814e0caeb977d5e6e69136da6fa430 (patch) | |
tree | a73a10f159ad3ff6a7e30e1d8b49f5eaa4e895f8 /audio | |
parent | a25e936540269b3d3889b569543b820ee556e6ba (diff) | |
download | mpv-f432a584b9814e0caeb977d5e6e69136da6fa430.tar.bz2 mpv-f432a584b9814e0caeb977d5e6e69136da6fa430.tar.xz |
ao_pulse: implement AO device listing API
While conceptually this sink stuff in PulseAudio does just the right
thing, actually listing the sinks is unbelievable complicated. Not only
is the idea that listing them should happen asynchronously completely
bullshit (who the fuck runs the PulseAudio server on a separate
computer), but the way this is done is full of bullshit too. Why
separate callbacks for each device? Why this obtuse mainloop shit?
Especially the mainloop shit makes it actively worse than doing things
manually with pthread primitives, and the reason for that (different
mainloop implementations for GUIs?) is laughable too. It's like they
chose the most complicated API possible just because they attempted
to "abstract" basic mechanisms in order to handle "everything". While
I don't claim to design the best APIs, this API is fucking terrible
without any excuse. (End of rant.)
Diffstat (limited to 'audio')
-rw-r--r-- | audio/out/ao_pulse.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c index 1ecb2707fb..e1f339f20b 100644 --- a/audio/out/ao_pulse.c +++ b/audio/out/ao_pulse.c @@ -359,7 +359,7 @@ static int init(struct ao *ao) pa_proplist *proplist = NULL; pa_format_info *format = NULL; struct priv *priv = ao->priv; - char *sink = priv->cfg_sink && priv->cfg_sink[0] ? priv->cfg_sink : NULL; + char *sink = priv->cfg_sink && priv->cfg_sink[0] ? priv->cfg_sink : ao->device; if (pa_init_boilerplate(ao) < 0) return -1; @@ -728,6 +728,42 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg) } } +struct sink_cb_ctx { + struct ao *ao; + struct ao_device_list *list; +}; + +static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol, void *ud) +{ + struct sink_cb_ctx *ctx = ud; + struct priv *priv = ctx->ao->priv; + + if (eol) { + pa_threaded_mainloop_signal(priv->mainloop, 0); // wakeup waitop() + return; + } + + struct ao_device_desc entry = {.name = i->name, .desc = i->description}; + ao_device_list_add(ctx->list, ctx->ao, &entry); +} + +static void list_devs(struct ao *ao, struct ao_device_list *list) +{ + struct priv *priv = ao->priv; + bool need_uninit = !priv->mainloop; + struct sink_cb_ctx ctx = {ao, list}; + + if (need_uninit && pa_init_boilerplate(ao) < 0) + return; + + pa_threaded_mainloop_lock(priv->mainloop); + waitop(priv, pa_context_get_sink_info_list(priv->context, sink_info_cb, &ctx)); + + if (need_uninit) + uninit(ao); +} + + #define OPT_BASE_STRUCT struct priv const struct ao_driver audio_out_pulse = { @@ -745,6 +781,7 @@ const struct ao_driver audio_out_pulse = { .drain = drain, .wait = wait_audio, .wakeup = wakeup, + .list_devs = list_devs, .priv_size = sizeof(struct priv), .priv_defaults = &(const struct priv) { .cfg_buffer = 250, |