[PATCH v2 2/2] switch-on-port-available: deactivate direction when the no ports are available for that direction

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This ensures that streams are moved away from unavailable outputs or
inputs. For example, sometimes HDMI is on a dedicated alsa card, and if
all HDMI outputs become unavailable, then the card profile will be set
to "off", and the streams will be moved somewhere else.
---

Changes in v2:
 - Don't call deactivate_direction() unconditionally.


 src/modules/module-switch-on-port-available.c | 40 ++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
index 8fd3c9e5f..c8e3d552b 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -80,7 +80,7 @@ static bool profile_good_for_output(pa_card_profile *profile, pa_device_port *po
     if (card->active_profile->max_source_channels != profile->max_source_channels)
         return false;
 
-    if (port == card->preferred_output_port)
+    if (port && port == card->preferred_output_port)
         return true;
 
     PA_IDXSET_FOREACH(sink, card->sinks, idx) {
@@ -251,6 +251,42 @@ static void switch_to_port(pa_device_port *port) {
         pa_sink_set_port(pp.sink, port->name, false);
 }
 
+static void deactivate_direction(pa_card *card, pa_direction_t direction) {
+    pa_card_profile *profile;
+    void *state;
+    pa_card_profile *best_profile = NULL;
+    const char *direction_str;
+
+    PA_HASHMAP_FOREACH(profile, card->profiles, state) {
+        switch (direction) {
+            case PA_DIRECTION_OUTPUT:
+                if (profile->n_sinks != 0)
+                    continue;
+                if (!profile_good_for_output(profile, NULL))
+                    continue;
+                break;
+
+            case PA_DIRECTION_INPUT:
+                if (profile->n_sources != 0)
+                    continue;
+                if (!profile_good_for_input(profile, NULL))
+                    continue;
+                break;
+        }
+
+        if (!best_profile || profile->priority > best_profile->priority)
+            best_profile = profile;
+    }
+
+    direction_str = direction == PA_DIRECTION_OUTPUT ? "output" : "input";
+
+    if (best_profile) {
+        pa_log_debug("Deactivating %s on card %s.", direction_str, card->name);
+        pa_card_set_profile(card, best_profile, false);
+    } else
+        pa_log_debug("Wanted to deactivate %s on card %s, but no suitable profile was found.", direction_str, card->name);
+}
+
 /* Switches away from a port, switching profiles if necessary or preferred */
 static void switch_from_port(pa_device_port *port) {
     struct port_pointers pp = find_port_pointers(port);
@@ -270,6 +306,8 @@ static void switch_from_port(pa_device_port *port) {
 
     if (best_port)
         switch_to_port(best_port);
+    else
+        deactivate_direction(port->card, port->direction);
 }
 
 
-- 
2.14.2



[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux