In case a port has not yet been saved, which is e g often the case if a sink/source has only one port, reading volume/mute will be done without port, whereas writing volume/mute will be done with port. Work around this by setting a default port before the fixate hook, so module-device-restore can read volume/mute for the correct port. BugLink: https://bugs.launchpad.net/bugs/1289515 Signed-off-by: David Henningsson <david.henningsson at canonical.com> --- src/pulsecore/device-port.c | 27 +++++++++++++++++++++++++++ src/pulsecore/device-port.h | 2 ++ src/pulsecore/sink.c | 27 ++++++++++----------------- src/pulsecore/source.c | 28 ++++++++++------------------ 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c index 0b65d5c..8cfb117 100644 --- a/src/pulsecore/device-port.c +++ b/src/pulsecore/device-port.c @@ -176,3 +176,30 @@ void pa_device_port_set_latency_offset(pa_device_port *p, int64_t offset) { pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index); pa_hook_fire(&core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], p); } + +pa_device_port *pa_device_port_find_best(pa_hashmap *ports) +{ + void *state; + pa_device_port *p, *best = NULL; + + if (!ports) + return NULL; + + /* First run: skip unavailable ports */ + PA_HASHMAP_FOREACH(p, ports, state) { + if (p->available == PA_AVAILABLE_NO) + continue; + + if (!best || p->priority > best->priority) + best = p; + } + + /* Second run: if only unavailable ports exist, still suggest a port */ + if (!best) { + PA_HASHMAP_FOREACH(p, ports, state) + if (!best || p->priority > best->priority) + best = p; + } + + return best; +} diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h index b10d554..ef700ac 100644 --- a/src/pulsecore/device-port.h +++ b/src/pulsecore/device-port.h @@ -83,4 +83,6 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t available); void pa_device_port_set_latency_offset(pa_device_port *p, int64_t offset); +pa_device_port *pa_device_port_find_best(pa_hashmap *ports); + #endif diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 08143e9..872d447 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -235,6 +235,12 @@ pa_sink* pa_sink_new( pa_device_init_icon(data->proplist, true); pa_device_init_intended_roles(data->proplist); + if (!data->active_port) { + pa_device_port *p = pa_device_port_find_best(data->ports); + if (p) + pa_sink_new_data_set_port(data, p->name); + } + if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) { pa_xfree(s); pa_namereg_unregister(core, name); @@ -300,23 +306,10 @@ pa_sink* pa_sink_new( if ((s->active_port = pa_hashmap_get(s->ports, data->active_port))) s->save_port = data->save_port; - if (!s->active_port) { - void *state; - pa_device_port *p; - - PA_HASHMAP_FOREACH(p, s->ports, state) { - if (p->available == PA_AVAILABLE_NO) - continue; - - if (!s->active_port || p->priority > s->active_port->priority) - s->active_port = p; - } - if (!s->active_port) { - PA_HASHMAP_FOREACH(p, s->ports, state) - if (!s->active_port || p->priority > s->active_port->priority) - s->active_port = p; - } - } + /* Hopefully the active port has already been assigned in the previous call + to pa_device_port_find_best, but better safe than sorry */ + if (!s->active_port) + s->active_port = pa_device_port_find_best(s->ports); if (s->active_port) s->latency_offset = s->active_port->latency_offset; diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 2a600e2..a592506 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -222,6 +222,12 @@ pa_source* pa_source_new( pa_device_init_icon(data->proplist, false); pa_device_init_intended_roles(data->proplist); + if (!data->active_port) { + pa_device_port *p = pa_device_port_find_best(data->ports); + if (p) + pa_source_new_data_set_port(data, p->name); + } + if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) { pa_xfree(s); pa_namereg_unregister(core, name); @@ -288,24 +294,10 @@ pa_source* pa_source_new( if ((s->active_port = pa_hashmap_get(s->ports, data->active_port))) s->save_port = data->save_port; - if (!s->active_port) { - void *state; - pa_device_port *p; - - PA_HASHMAP_FOREACH(p, s->ports, state) { - if (p->available == PA_AVAILABLE_NO) - continue; - - if (!s->active_port || p->priority > s->active_port->priority) - s->active_port = p; - } - - if (!s->active_port) { - PA_HASHMAP_FOREACH(p, s->ports, state) - if (!s->active_port || p->priority > s->active_port->priority) - s->active_port = p; - } - } + /* Hopefully the active port has already been assigned in the previous call + to pa_device_port_find_best, but better safe than sorry */ + if (!s->active_port) + s->active_port = pa_device_port_find_best(s->ports); if (s->active_port) s->latency_offset = s->active_port->latency_offset; -- 1.7.9.5