summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-10-10 18:33:55 +0200
committerwm4 <wm4@nowhere>2014-10-10 18:42:43 +0200
commitf432a584b9814e0caeb977d5e6e69136da6fa430 (patch)
treea73a10f159ad3ff6a7e30e1d8b49f5eaa4e895f8 /audio
parenta25e936540269b3d3889b569543b820ee556e6ba (diff)
downloadmpv-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.c39
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,