blob: 1c1e2fbdbc01dc11848032a64ff2533863fe4767 [file] [log] [blame]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001From b8b9b3da94a0c27090ceba243fdf54fb518c5489 Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanuk@iki.fi>
3Date: Mon, 1 Feb 2016 15:34:59 +0200
4Subject: [PATCH] Revert "module-switch-on-port-available: Route to preferred
5 profile"
6
7This reverts commit e87100d41ef6d14f8dc7f803582191d9f8d8f183.
8
9The reverted commit had some unwanted consequences:
10https://bugs.freedesktop.org/show_bug.cgi?id=93903
11https://bugs.freedesktop.org/show_bug.cgi?id=93946
12
13The first regression has a fix here:
14https://patchwork.freedesktop.org/patch/72053/
15
16The second regression, however, doesn't have a fix yet. Therefore,
17it's best to revert the offending patch for now.
18
19Upstream-Status: Inappropriate [Upstream plans to fix the issues
20properly.]
21
22Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
23---
24 src/modules/module-switch-on-port-available.c | 172 ++++++++++----------------
25 1 file changed, 67 insertions(+), 105 deletions(-)
26
27diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
28index 5dd9786..8de68a3 100644
29--- a/src/modules/module-switch-on-port-available.c
30+++ b/src/modules/module-switch-on-port-available.c
31@@ -74,25 +74,22 @@ static bool profile_good_for_input(pa_card_profile *profile) {
32 static int try_to_switch_profile(pa_device_port *port) {
33 pa_card_profile *best_profile = NULL, *profile;
34 void *state;
35- unsigned best_prio = 0;
36
37- pa_log_debug("Finding best profile for port %s, preferred = %s",
38- port->name, pa_strnull(port->preferred_profile));
39+ pa_log_debug("Finding best profile");
40
41 PA_HASHMAP_FOREACH(profile, port->profiles, state) {
42 bool good = false;
43- const char *name;
44- unsigned prio = profile->priority;
45+
46+ if (best_profile && best_profile->priority >= profile->priority)
47+ continue;
48
49 /* We make a best effort to keep other direction unchanged */
50 switch (port->direction) {
51 case PA_DIRECTION_OUTPUT:
52- name = profile->output_name;
53 good = profile_good_for_output(profile);
54 break;
55
56 case PA_DIRECTION_INPUT:
57- name = profile->input_name;
58 good = profile_good_for_input(profile);
59 break;
60 }
61@@ -100,15 +97,7 @@ static int try_to_switch_profile(pa_device_port *port) {
62 if (!good)
63 continue;
64
65- /* Give a high bonus in case this is the preferred profile */
66- if (port->preferred_profile && pa_streq(name ? name : profile->name, port->preferred_profile))
67- prio += 1000000;
68-
69- if (best_profile && best_prio >= prio)
70- continue;
71-
72 best_profile = profile;
73- best_prio = prio;
74 }
75
76 if (!best_profile) {
77@@ -124,125 +113,98 @@ static int try_to_switch_profile(pa_device_port *port) {
78 return 0;
79 }
80
81-struct port_pointers {
82- pa_device_port *port;
83- pa_sink *sink;
84- pa_source *source;
85- bool is_possible_profile_active;
86- bool is_preferred_profile_active;
87- bool is_port_active;
88-};
89-
90-static const char* profile_name_for_dir(pa_card_profile *cp, pa_direction_t dir) {
91- if (dir == PA_DIRECTION_OUTPUT && cp->output_name)
92- return cp->output_name;
93- if (dir == PA_DIRECTION_INPUT && cp->input_name)
94- return cp->input_name;
95- return cp->name;
96-}
97-
98-static struct port_pointers find_port_pointers(pa_device_port *port) {
99- struct port_pointers pp = { .port = port };
100+static void find_sink_and_source(pa_card *card, pa_device_port *port, pa_sink **si, pa_source **so) {
101+ pa_sink *sink = NULL;
102+ pa_source *source = NULL;
103 uint32_t state;
104- pa_card *card;
105-
106- pa_assert(port);
107- pa_assert_se(card = port->card);
108
109 switch (port->direction) {
110 case PA_DIRECTION_OUTPUT:
111- PA_IDXSET_FOREACH(pp.sink, card->sinks, state)
112- if (port == pa_hashmap_get(pp.sink->ports, port->name))
113+ PA_IDXSET_FOREACH(sink, card->sinks, state)
114+ if (port == pa_hashmap_get(sink->ports, port->name))
115 break;
116 break;
117
118 case PA_DIRECTION_INPUT:
119- PA_IDXSET_FOREACH(pp.source, card->sources, state)
120- if (port == pa_hashmap_get(pp.source->ports, port->name))
121+ PA_IDXSET_FOREACH(source, card->sources, state)
122+ if (port == pa_hashmap_get(source->ports, port->name))
123 break;
124 break;
125 }
126
127- pp.is_possible_profile_active =
128- card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name);
129- pp.is_preferred_profile_active = pp.is_possible_profile_active && (!port->preferred_profile ||
130- pa_safe_streq(port->preferred_profile, profile_name_for_dir(card->active_profile, port->direction)));
131- pp.is_port_active = (pp.sink && pp.sink->active_port == port) || (pp.source && pp.source->active_port == port);
132-
133- return pp;
134+ *si = sink;
135+ *so = source;
136 }
137
138-/* Switches to a port, switching profiles if necessary or preferred */
139-static bool switch_to_port(pa_device_port *port) {
140- struct port_pointers pp = find_port_pointers(port);
141+static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
142+ pa_card* card;
143+ pa_sink *sink;
144+ pa_source *source;
145+ bool is_active_profile, is_active_port;
146
147- if (pp.is_port_active)
148- return true; /* Already selected */
149+ if (port->available == PA_AVAILABLE_UNKNOWN)
150+ return PA_HOOK_OK;
151
152- pa_log_debug("Trying to switch to port %s", port->name);
153- if (!pp.is_preferred_profile_active) {
154- if (try_to_switch_profile(port) < 0) {
155- if (pp.is_possible_profile_active)
156- return false;
157- }
158- else
159- /* Now that profile has changed, our sink and source pointers must be updated */
160- pp = find_port_pointers(port);
161- }
162+ card = port->card;
163
164- if (pp.source)
165- pa_source_set_port(pp.source, port->name, false);
166- if (pp.sink)
167- pa_sink_set_port(pp.sink, port->name, false);
168- return true;
169-}
170+ if (!card) {
171+ pa_log_warn("Port %s does not have a card", port->name);
172+ return PA_HOOK_OK;
173+ }
174
175-/* Switches away from a port, switching profiles if necessary or preferred */
176-static bool switch_from_port(pa_device_port *port) {
177- struct port_pointers pp = find_port_pointers(port);
178- pa_device_port *p, *best_port = NULL;
179- void *state;
180+ if (pa_idxset_size(card->sinks) == 0 && pa_idxset_size(card->sources) == 0)
181+ /* This card is not initialized yet. We'll handle it in
182+ sink_new / source_new callbacks later. */
183+ return PA_HOOK_OK;
184
185- if (!pp.is_port_active)
186- return true; /* Already deselected */
187+ find_sink_and_source(card, port, &sink, &source);
188
189- /* Try to find a good enough port to switch to */
190- PA_HASHMAP_FOREACH(p, port->card->ports, state)
191- if (p->direction == port->direction && p != port && p->available != PA_AVAILABLE_NO &&
192- (!best_port || best_port->priority < p->priority))
193- best_port = p;
194+ is_active_profile = card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name);
195+ is_active_port = (sink && sink->active_port == port) || (source && source->active_port == port);
196
197- pa_log_debug("Trying to switch away from port %s, found %s", port->name, best_port ? best_port->name : "no better option");
198+ if (port->available == PA_AVAILABLE_NO && !is_active_port)
199+ return PA_HOOK_OK;
200
201- if (best_port)
202- return switch_to_port(best_port);
203+ if (port->available == PA_AVAILABLE_YES) {
204+ if (is_active_port)
205+ return PA_HOOK_OK;
206
207- return false;
208-}
209+ if (!is_active_profile) {
210+ if (try_to_switch_profile(port) < 0)
211+ return PA_HOOK_OK;
212
213+ pa_assert(card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name));
214
215-static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
216- pa_assert(port);
217+ /* Now that profile has changed, our sink and source pointers must be updated */
218+ find_sink_and_source(card, port, &sink, &source);
219+ }
220
221- if (!port->card) {
222- pa_log_warn("Port %s does not have a card", port->name);
223- return PA_HOOK_OK;
224+ if (source)
225+ pa_source_set_port(source, port->name, false);
226+ if (sink)
227+ pa_sink_set_port(sink, port->name, false);
228 }
229
230- if (pa_idxset_size(port->card->sinks) == 0 && pa_idxset_size(port->card->sources) == 0)
231- /* This card is not initialized yet. We'll handle it in
232- sink_new / source_new callbacks later. */
233- return PA_HOOK_OK;
234+ if (port->available == PA_AVAILABLE_NO) {
235+ if (sink) {
236+ pa_device_port *p2 = pa_device_port_find_best(sink->ports);
237+
238+ if (p2 && p2->available != PA_AVAILABLE_NO)
239+ pa_sink_set_port(sink, p2->name, false);
240+ else {
241+ /* Maybe try to switch to another profile? */
242+ }
243+ }
244
245- switch (port->available) {
246- case PA_AVAILABLE_YES:
247- switch_to_port(port);
248- break;
249- case PA_AVAILABLE_NO:
250- switch_from_port(port);
251- break;
252- default:
253- break;
254+ if (source) {
255+ pa_device_port *p2 = pa_device_port_find_best(source->ports);
256+
257+ if (p2 && p2->available != PA_AVAILABLE_NO)
258+ pa_source_set_port(source, p2->name, false);
259+ else {
260+ /* Maybe try to switch to another profile? */
261+ }
262+ }
263 }
264
265 return PA_HOOK_OK;
266--
2672.7.0
268