diff options
Diffstat (limited to 'meta/recipes-multimedia/pulseaudio/pulseaudio/0001-Revert-module-switch-on-port-available-Route-to-pref.patch')
-rw-r--r-- | meta/recipes-multimedia/pulseaudio/pulseaudio/0001-Revert-module-switch-on-port-available-Route-to-pref.patch | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-Revert-module-switch-on-port-available-Route-to-pref.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-Revert-module-switch-on-port-available-Route-to-pref.patch new file mode 100644 index 0000000000..1c1e2fbdbc --- /dev/null +++ b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-Revert-module-switch-on-port-available-Route-to-pref.patch @@ -0,0 +1,268 @@ +From b8b9b3da94a0c27090ceba243fdf54fb518c5489 Mon Sep 17 00:00:00 2001 +From: Tanu Kaskinen <tanuk@iki.fi> +Date: Mon, 1 Feb 2016 15:34:59 +0200 +Subject: [PATCH] Revert "module-switch-on-port-available: Route to preferred + profile" + +This reverts commit e87100d41ef6d14f8dc7f803582191d9f8d8f183. + +The reverted commit had some unwanted consequences: +https://bugs.freedesktop.org/show_bug.cgi?id=93903 +https://bugs.freedesktop.org/show_bug.cgi?id=93946 + +The first regression has a fix here: +https://patchwork.freedesktop.org/patch/72053/ + +The second regression, however, doesn't have a fix yet. Therefore, +it's best to revert the offending patch for now. + +Upstream-Status: Inappropriate [Upstream plans to fix the issues +properly.] + +Signed-off-by: Tanu Kaskinen <tanuk@iki.fi> +--- + src/modules/module-switch-on-port-available.c | 172 ++++++++++---------------- + 1 file changed, 67 insertions(+), 105 deletions(-) + +diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c +index 5dd9786..8de68a3 100644 +--- a/src/modules/module-switch-on-port-available.c ++++ b/src/modules/module-switch-on-port-available.c +@@ -74,25 +74,22 @@ static bool profile_good_for_input(pa_card_profile *profile) { + static int try_to_switch_profile(pa_device_port *port) { + pa_card_profile *best_profile = NULL, *profile; + void *state; +- unsigned best_prio = 0; + +- pa_log_debug("Finding best profile for port %s, preferred = %s", +- port->name, pa_strnull(port->preferred_profile)); ++ pa_log_debug("Finding best profile"); + + PA_HASHMAP_FOREACH(profile, port->profiles, state) { + bool good = false; +- const char *name; +- unsigned prio = profile->priority; ++ ++ if (best_profile && best_profile->priority >= profile->priority) ++ continue; + + /* We make a best effort to keep other direction unchanged */ + switch (port->direction) { + case PA_DIRECTION_OUTPUT: +- name = profile->output_name; + good = profile_good_for_output(profile); + break; + + case PA_DIRECTION_INPUT: +- name = profile->input_name; + good = profile_good_for_input(profile); + break; + } +@@ -100,15 +97,7 @@ static int try_to_switch_profile(pa_device_port *port) { + if (!good) + continue; + +- /* Give a high bonus in case this is the preferred profile */ +- if (port->preferred_profile && pa_streq(name ? name : profile->name, port->preferred_profile)) +- prio += 1000000; +- +- if (best_profile && best_prio >= prio) +- continue; +- + best_profile = profile; +- best_prio = prio; + } + + if (!best_profile) { +@@ -124,125 +113,98 @@ static int try_to_switch_profile(pa_device_port *port) { + return 0; + } + +-struct port_pointers { +- pa_device_port *port; +- pa_sink *sink; +- pa_source *source; +- bool is_possible_profile_active; +- bool is_preferred_profile_active; +- bool is_port_active; +-}; +- +-static const char* profile_name_for_dir(pa_card_profile *cp, pa_direction_t dir) { +- if (dir == PA_DIRECTION_OUTPUT && cp->output_name) +- return cp->output_name; +- if (dir == PA_DIRECTION_INPUT && cp->input_name) +- return cp->input_name; +- return cp->name; +-} +- +-static struct port_pointers find_port_pointers(pa_device_port *port) { +- struct port_pointers pp = { .port = port }; ++static void find_sink_and_source(pa_card *card, pa_device_port *port, pa_sink **si, pa_source **so) { ++ pa_sink *sink = NULL; ++ pa_source *source = NULL; + uint32_t state; +- pa_card *card; +- +- pa_assert(port); +- pa_assert_se(card = port->card); + + switch (port->direction) { + case PA_DIRECTION_OUTPUT: +- PA_IDXSET_FOREACH(pp.sink, card->sinks, state) +- if (port == pa_hashmap_get(pp.sink->ports, port->name)) ++ PA_IDXSET_FOREACH(sink, card->sinks, state) ++ if (port == pa_hashmap_get(sink->ports, port->name)) + break; + break; + + case PA_DIRECTION_INPUT: +- PA_IDXSET_FOREACH(pp.source, card->sources, state) +- if (port == pa_hashmap_get(pp.source->ports, port->name)) ++ PA_IDXSET_FOREACH(source, card->sources, state) ++ if (port == pa_hashmap_get(source->ports, port->name)) + break; + break; + } + +- pp.is_possible_profile_active = +- card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name); +- pp.is_preferred_profile_active = pp.is_possible_profile_active && (!port->preferred_profile || +- pa_safe_streq(port->preferred_profile, profile_name_for_dir(card->active_profile, port->direction))); +- pp.is_port_active = (pp.sink && pp.sink->active_port == port) || (pp.source && pp.source->active_port == port); +- +- return pp; ++ *si = sink; ++ *so = source; + } + +-/* Switches to a port, switching profiles if necessary or preferred */ +-static bool switch_to_port(pa_device_port *port) { +- struct port_pointers pp = find_port_pointers(port); ++static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) { ++ pa_card* card; ++ pa_sink *sink; ++ pa_source *source; ++ bool is_active_profile, is_active_port; + +- if (pp.is_port_active) +- return true; /* Already selected */ ++ if (port->available == PA_AVAILABLE_UNKNOWN) ++ return PA_HOOK_OK; + +- pa_log_debug("Trying to switch to port %s", port->name); +- if (!pp.is_preferred_profile_active) { +- if (try_to_switch_profile(port) < 0) { +- if (pp.is_possible_profile_active) +- return false; +- } +- else +- /* Now that profile has changed, our sink and source pointers must be updated */ +- pp = find_port_pointers(port); +- } ++ card = port->card; + +- if (pp.source) +- pa_source_set_port(pp.source, port->name, false); +- if (pp.sink) +- pa_sink_set_port(pp.sink, port->name, false); +- return true; +-} ++ if (!card) { ++ pa_log_warn("Port %s does not have a card", port->name); ++ return PA_HOOK_OK; ++ } + +-/* Switches away from a port, switching profiles if necessary or preferred */ +-static bool switch_from_port(pa_device_port *port) { +- struct port_pointers pp = find_port_pointers(port); +- pa_device_port *p, *best_port = NULL; +- void *state; ++ if (pa_idxset_size(card->sinks) == 0 && pa_idxset_size(card->sources) == 0) ++ /* This card is not initialized yet. We'll handle it in ++ sink_new / source_new callbacks later. */ ++ return PA_HOOK_OK; + +- if (!pp.is_port_active) +- return true; /* Already deselected */ ++ find_sink_and_source(card, port, &sink, &source); + +- /* Try to find a good enough port to switch to */ +- PA_HASHMAP_FOREACH(p, port->card->ports, state) +- if (p->direction == port->direction && p != port && p->available != PA_AVAILABLE_NO && +- (!best_port || best_port->priority < p->priority)) +- best_port = p; ++ is_active_profile = card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name); ++ is_active_port = (sink && sink->active_port == port) || (source && source->active_port == port); + +- pa_log_debug("Trying to switch away from port %s, found %s", port->name, best_port ? best_port->name : "no better option"); ++ if (port->available == PA_AVAILABLE_NO && !is_active_port) ++ return PA_HOOK_OK; + +- if (best_port) +- return switch_to_port(best_port); ++ if (port->available == PA_AVAILABLE_YES) { ++ if (is_active_port) ++ return PA_HOOK_OK; + +- return false; +-} ++ if (!is_active_profile) { ++ if (try_to_switch_profile(port) < 0) ++ return PA_HOOK_OK; + ++ pa_assert(card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name)); + +-static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) { +- pa_assert(port); ++ /* Now that profile has changed, our sink and source pointers must be updated */ ++ find_sink_and_source(card, port, &sink, &source); ++ } + +- if (!port->card) { +- pa_log_warn("Port %s does not have a card", port->name); +- return PA_HOOK_OK; ++ if (source) ++ pa_source_set_port(source, port->name, false); ++ if (sink) ++ pa_sink_set_port(sink, port->name, false); + } + +- if (pa_idxset_size(port->card->sinks) == 0 && pa_idxset_size(port->card->sources) == 0) +- /* This card is not initialized yet. We'll handle it in +- sink_new / source_new callbacks later. */ +- return PA_HOOK_OK; ++ if (port->available == PA_AVAILABLE_NO) { ++ if (sink) { ++ pa_device_port *p2 = pa_device_port_find_best(sink->ports); ++ ++ if (p2 && p2->available != PA_AVAILABLE_NO) ++ pa_sink_set_port(sink, p2->name, false); ++ else { ++ /* Maybe try to switch to another profile? */ ++ } ++ } + +- switch (port->available) { +- case PA_AVAILABLE_YES: +- switch_to_port(port); +- break; +- case PA_AVAILABLE_NO: +- switch_from_port(port); +- break; +- default: +- break; ++ if (source) { ++ pa_device_port *p2 = pa_device_port_find_best(source->ports); ++ ++ if (p2 && p2->available != PA_AVAILABLE_NO) ++ pa_source_set_port(source, p2->name, false); ++ else { ++ /* Maybe try to switch to another profile? */ ++ } ++ } + } + + return PA_HOOK_OK; +-- +2.7.0 + |