On 2014-05-28 10:42, Hui Wang wrote: > Recently met a problem: when I disconnect the bluetooth headset, the > pulseaudio automatically switch the sound to sink of HDMI output > instead of the sink of internal speaker even though there is no HDMI > cable connected. > > To fix this problem, I want to change the rule of selecting the target > sink(same rules apply to the source selecting): > If the sinks have the port with PA_AVAILABLE_YES, we will choose the > one from them with a highest priority port. If all sinks don't have > the port with PA_AVAILABLE_YES, we will choose the one with a highest > priority port. Thanks for the patch. I think it would be better to construct a new hashmap with all ports (of all relevant sinks) and then call find_best on the new hashmap. That would give a better handling of e g PA_AVAILABLE_UNKNOWN than what you're suggesting. Also some types of sinks do not have ports at all. Your patch introduces a regression in this case because they are no longer considered valid to switch to. (The same reasoning applies to sources.) > > Signed-off-by: Hui Wang <hui.wang at canonical.com> > --- > src/modules/module-rescue-streams.c | 80 +++++++++++++++++++++++++------------ > 1 file changed, 54 insertions(+), 26 deletions(-) > > diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c > index 7035a35..8a4c8d6 100644 > --- a/src/modules/module-rescue-streams.c > +++ b/src/modules/module-rescue-streams.c > @@ -53,33 +53,47 @@ struct userdata { > }; > > static pa_sink* find_evacuation_sink(pa_core *c, pa_sink_input *i, pa_sink *skip) { > - pa_sink *target, *def; > + pa_sink *target, *best_target = NULL; > + pa_device_port *port, *best_port = NULL; > uint32_t idx; > > pa_assert(c); > pa_assert(i); > > - def = pa_namereg_get_default_sink(c); > - > - if (def && def != skip && pa_sink_input_may_move_to(i, def)) > - return def; > - > PA_IDXSET_FOREACH(target, c->sinks, idx) { > - if (target == def) > - continue; > - > if (target == skip) > continue; > > if (!PA_SINK_IS_LINKED(pa_sink_get_state(target))) > continue; > > - if (pa_sink_input_may_move_to(i, target)) > - return target; > + if (!pa_sink_input_may_move_to(i, target)) > + continue; > + > + port = pa_device_port_find_best(target->ports); > + if (!port) > + continue; > + > + if (!best_target) { > + best_target = target; > + best_port = port; > + continue; > + } > + > + if (best_port->available != port->available && best_port->available == PA_AVAILABLE_YES) > + continue; > + > + if (best_port->available == port->available && best_port->priority > port->priority) > + continue; > + > + best_target = target; > + best_port = port; > } > > - pa_log_debug("No evacuation sink found."); > - return NULL; > + if(!best_target) > + pa_log_debug("No evacuation sink found."); > + > + return best_target; > } > > static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, void* userdata) { > @@ -141,21 +155,14 @@ static pa_hook_result_t sink_input_move_fail_hook_callback(pa_core *c, pa_sink_i > } > > static pa_source* find_evacuation_source(pa_core *c, pa_source_output *o, pa_source *skip) { > - pa_source *target, *def; > + pa_source *target, *best_target = NULL; > + pa_device_port *port, *best_port = NULL; > uint32_t idx; > > pa_assert(c); > pa_assert(o); > > - def = pa_namereg_get_default_source(c); > - > - if (def && def != skip && pa_source_output_may_move_to(o, def)) > - return def; > - > PA_IDXSET_FOREACH(target, c->sources, idx) { > - if (target == def) > - continue; > - > if (target == skip) > continue; > > @@ -165,12 +172,33 @@ static pa_source* find_evacuation_source(pa_core *c, pa_source_output *o, pa_sou > if (!PA_SOURCE_IS_LINKED(pa_source_get_state(target))) > continue; > > - if (pa_source_output_may_move_to(o, target)) > - return target; > + if (!pa_source_output_may_move_to(o, target)) > + continue; > + > + port = pa_device_port_find_best(target->ports); > + if (!port) > + continue; > + > + if (!best_target) { > + best_target = target; > + best_port = port; > + continue; > + } > + > + if (best_port->available != port->available && best_port->available == PA_AVAILABLE_YES) > + continue; > + > + if (best_port->available == port->available && best_port->priority > port->priority) > + continue; > + > + best_target = target; > + best_port = port; > } > > - pa_log_debug("No evacuation source found."); > - return NULL; > + if (!best_target) > + pa_log_debug("No evacuation source found."); > + > + return best_target; > } > > static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, void* userdata) { > -- David Henningsson, Canonical Ltd. https://launchpad.net/~diwic