Re: Audio APP (sink-input) bind to the sink with only unplugged hdmi-audio ports on it

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

 



The tentative fix of this problem like this:

When a port is unplugged, it is caught by module-switch-on-port-available.c, here we check if the sink of this port is default_sink or not, if it is default_sink, it means the sink of this port is still the highest priority one, no need to move sink-inputs, otherwise, try to move all sink-inputs of this sink to default_sink temporarily.

To restore the sink-inputs to its original sink, it depends on module-stream-restore.c, but we don't let it restore unconditionally, if the target sink has at least one port with avaialbe_yes/unknow, let it restore.

So supposing one sink has speaker, the other sink has hdmi-audio, when unplugging the hdmi cable, the audio will route to speaker, after plugging the hdmi cable again, when app build new sink-input, it will restore the sound to original sink.




diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index 228e9e4..2dd825f 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1424,6 +1424,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3  static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
     char *name;
     struct entry *e;
+    bool good = 0;

     pa_assert(c);
     pa_assert(new_data);
@@ -1450,6 +1451,21 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
                 s = pa_idxset_first(card->sinks, NULL);
         }

+       /* if all ports on this sink are all available_no, we don't set this sink temporarily */
+       if (s) {
+         pa_device_port *i;
+          void *state_p;
+         PA_HASHMAP_FOREACH(i, s->ports, state_p) {
+           if (i->available != PA_AVAILABLE_NO) {
+             good = 1;
+             break;
+           }
+         }
+       }
+
+       if (!good)
+         s = NULL;
+
         /* It might happen that a stream and a sink are set up at the
            same time, in which case we want to make sure we don't
            interfere with that */
diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
index 321db36..acd3252 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -272,6 +272,63 @@ static void switch_from_port(pa_device_port *port) {
         switch_to_port(best_port);
 }

+/* This function refers to sink_put_hook_callback() in the module-switch-on-connect.c */ +static void move_input_to_default_sink(pa_core *c, pa_sink *ori_sink, pa_sink *new_sink)
+{
+    pa_sink_input *i;
+    uint32_t idx;
+
+    /* Now move all old inputs over */
+    if (pa_idxset_size(ori_sink->inputs) <= 0) {
+       pa_log_debug("No sink inputs to move away.");
+       return;
+    }
+
+    PA_IDXSET_FOREACH(i, ori_sink->inputs, idx) {
+      /* don't check i->save_sink here, since we have to move input temporarily */
+       if (!PA_SINK_INPUT_IS_LINKED(i->state))
+           continue;
+
+       if (pa_sink_input_move_to(i, new_sink, false) < 0)
+           pa_log_info("Failed to move sink input %u \"%s\" to %s.", i->index, + pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), new_sink->name);
+       else
+           pa_log_info("Successfully moved sink input %u \"%s\" to %s.", i->index, + pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), new_sink->name);
+    }
+}
+
+static void check_and_move_sink_inputs_to_default_sink(pa_core *c, pa_device_port *port)
+{
+    struct port_pointers pp = find_port_pointers(port);
+    pa_sink *def_sink, *p_sink = pp.sink;
+
+    switch (port->direction) {
+    case PA_DIRECTION_OUTPUT:
+       def_sink = c->default_sink;
+
+       /* check if there is better sinks to move to, before here,the default_sink is already +           re-selected when the port is changing unavailble, if p_sink equals default_sink, +          it means there is no better sinks to replace the sink containing this port */
+       if (p_sink != def_sink) {
+           void *state_p;
+           pa_device_port *i;
+
+           /* check if all ports on this sink are available_no, if not, don't need to move the input */
+           PA_HASHMAP_FOREACH(i, p_sink->ports, state_p) {
+             if (i->available != PA_AVAILABLE_NO)
+               return;
+           }
+
+           /* now the default sink is the best sink already */
+           move_input_to_default_sink(c, pp.sink, def_sink);
+       }
+       break;
+
+    case PA_DIRECTION_INPUT:
+       break;
+    }
+}

 static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
     pa_assert(port);
@@ -295,6 +352,7 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port
         break;
     case PA_AVAILABLE_NO:
         switch_from_port(port);
+       check_and_move_sink_inputs_to_default_sink(c, port);
         break;
     default:
         break;



On 2018年09月30日 15:03, Hui Wang wrote:
This issue is also reported to: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/579

Recently we found a weird issue on many laptops with the ubuntu 18.04, it uses the pulseaudio-11.1 (I guess the PA of the latest version also has this problem). The issue is like this:

1. boot the system up without plugging a hdmi monitor
2. run an audio app to play sound (e.g. $speaker-test)
3. the sound outputs from analog-speaker
4. plug a monitor with audio capability (through DP or HDMI port)
5. the sound still outputs from analog-speaker
6. open sound-setting (gnome-control-center --> choose sound), you will
   see two output devies: speaker and HDMI audio
7. choose HDMI audio, the sound will switch to HDIM audio from speaker
   (pa will remember speaker-test prefer to use hdmi-audio sink)
8. unplug the monitor, the default-sink is switching to analog-speaker,
   but the sound of speaker-test still route to hdmi-audio sink
9. run other sound apps, they all route sound to default sink
   (analog-speaker), but speaker-test always routes to hdmi-audio sink,
   as a result, speaker-test can't output sound anymore unless we
   replug a monitor with audio capability then the speaker-test output
   from hdmi-audio again.
10. if we want the speaker-test to route to analog-speaker, two ways:
   run pacmd move-sink-input or plug a monitor, after two audio devices
   (hdmi audio and speaker) show up in the sound-setting, select
   analog-speaker manually.

This issue only happens on the laptops with 2 audio cards, analog devices on one card, hdmi audio on the other card. This kind of laptops are very common, like I+A (Intel graphic + Amd Graphic), I+N(Intel + Nvidia), and A AMD.

This issue will not happen on the laptops with only Intel graphic card, since both analog and hdmi audio belong to one sound card. When hdmi monitor is unplugged, the hdmi sink will be removed from PA, then all sink-inputs will route to the only left sink: analog-sink.

This issue will not happen on BT or USB audio. Unlike hdmi audio, BT and USB audio cards will be removed totally from PA when they are unpluged/unconnected, so they don't have this issue as well.

The root cause of this issue is although the hdmi monitor is unplugged, the hdmi-sink still exists, and sink-input is selected by user to bind to this sink, so the pa doesn't care about if this sink has valid port or not, it bind the sink-input to this sink unconditionally.

Maybe we could improve it like this: if the user selected sink only has available_no ports, the pa will switch all sink-inputs of this sink to other sinks (like default_sink) temporarily, once the selected sink has availble ports, all sink-inputs switch back to this sink.

Any good ideas?

Thanks,

Hui.


_______________________________________________
pulseaudio-discuss mailing list
pulseaudio-discuss@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


_______________________________________________
pulseaudio-discuss mailing list
pulseaudio-discuss@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss




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

  Powered by Linux