[4/4] move stream when the active_port changes

Submitted by Hui Wang on Nov. 5, 2018, 1:47 a.m.

Details

Message ID 20181105014716.5613-5-hui.wang@canonical.com
State Superseded
Headers show
Series "The tentative fix of the issue #185" ( rev: 1 ) in PulseAudio

Not browsing as part of any series.

Commit Message

Hui Wang Nov. 5, 2018, 1:47 a.m.
When the active port of a sink becomes unavailable, all streams from
that sink should be moved to the default sink.

When the active port of an existing sink changes state from
unavailable, all streams that have their "preferred_sink"
set to the new sink should be moved to the new sink.

Signed-off-by: Hui Wang <hui.wang@canonical.com>
---
 src/pulsecore/device-port.c | 16 ++++++++++++++++
 src/pulsecore/sink.c        | 13 +++++++++++++
 src/pulsecore/sink.h        |  1 +
 3 files changed, 30 insertions(+)

Patch hide | download patch | download mbox

diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
index 464c3f8a2..2604c9051 100644
--- a/src/pulsecore/device-port.c
+++ b/src/pulsecore/device-port.c
@@ -92,6 +92,7 @@  void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
      * be created before port objects, and then p->card could be non-NULL for
      * the whole lifecycle of pa_device_port. */
     if (p->card && p->card->linked) {
+	pa_sink *sink;
         /* A sink or source whose active port is unavailable can't be the
          * default sink/source, so port availability changes may affect the
          * default sink/source choice. */
@@ -102,6 +103,21 @@  void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
 
         pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index);
         pa_hook_fire(&p->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], p);
+
+	sink = pa_sink_get_sink_from_device_port(p);
+	if (!sink)
+	    return;
+	switch (p->direction) {
+        case PA_DIRECTION_OUTPUT:
+	    if (sink->active_port->available == PA_AVAILABLE_NO)
+		pa_sink_move_streams_from_oldsink_to_newsink(sink, p->core->default_sink, false);
+	    else
+		pa_sink_bind_preferred_stream_to_a_sink(sink);
+
+            break;
+        case PA_DIRECTION_INPUT:
+	    break;
+	}
     }
 }
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index a2a390beb..9ebc18fa1 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -3950,3 +3950,16 @@  void pa_sink_bind_preferred_stream_to_a_sink(pa_sink *s) {
            pa_sink_input_move_to(si, s, false);
     }
 }
+
+pa_sink *pa_sink_get_sink_from_device_port(pa_device_port *p) {
+    pa_sink *rs = NULL;
+    pa_sink *sink;
+    uint32_t state;
+
+    PA_IDXSET_FOREACH(sink, p->card->sinks, state)
+	if (p == pa_hashmap_get(sink->ports, p->name)) {
+	    rs = sink;
+	    break;
+	}
+    return rs;
+}
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 24e4678b1..693344ac3 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -563,4 +563,5 @@  void pa_sink_set_reference_volume_direct(pa_sink *s, const pa_cvolume *volume);
 
 void pa_sink_move_streams_from_oldsink_to_newsink(pa_sink *old_sink, pa_sink *new_sink, bool from_user);
 void pa_sink_bind_preferred_stream_to_a_sink(pa_sink *s);
+pa_sink *pa_sink_get_sink_from_device_port(pa_device_port *p);
 #endif

Comments

On Mon, 2018-11-05 at 09:47 +0800, Hui Wang wrote:
> When the active port of a sink becomes unavailable, all streams from
> that sink should be moved to the default sink.
> 
> When the active port of an existing sink changes state from
> unavailable, all streams that have their "preferred_sink"
> set to the new sink should be moved to the new sink.
> 
> Signed-off-by: Hui Wang <hui.wang@canonical.com>
> ---
>  src/pulsecore/device-port.c | 16 ++++++++++++++++
>  src/pulsecore/sink.c        | 13 +++++++++++++
>  src/pulsecore/sink.h        |  1 +
>  3 files changed, 30 insertions(+)
> 
> diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
> index 464c3f8a2..2604c9051 100644
> --- a/src/pulsecore/device-port.c
> +++ b/src/pulsecore/device-port.c
> @@ -92,6 +92,7 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
>       * be created before port objects, and then p->card could be non-NULL for
>       * the whole lifecycle of pa_device_port. */
>      if (p->card && p->card->linked) {
> +	pa_sink *sink;
>          /* A sink or source whose active port is unavailable can't be the
>           * default sink/source, so port availability changes may affect the
>           * default sink/source choice. */
> @@ -102,6 +103,21 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
>  
>          pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index);
>          pa_hook_fire(&p->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], p);
> +
> +	sink = pa_sink_get_sink_from_device_port(p);
> +	if (!sink)
> +	    return;
> +	switch (p->direction) {
> +        case PA_DIRECTION_OUTPUT:
> +	    if (sink->active_port->available == PA_AVAILABLE_NO)
> +		pa_sink_move_streams_from_oldsink_to_newsink(sink, p->core->default_sink, false);

This logic isn't quite right. We should move streams away from the sink
only if the active port is the same that just changed its availability
status. If the current port is something other than the port that
changed, then we should ignore the change event.

> +	    else
> +		pa_sink_bind_preferred_stream_to_a_sink(sink);
> +
> +            break;
> +        case PA_DIRECTION_INPUT:
> +	    break;
> +	}
>      }
>  }
>  
> diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
> index a2a390beb..9ebc18fa1 100644
> --- a/src/pulsecore/sink.c
> +++ b/src/pulsecore/sink.c
> @@ -3950,3 +3950,16 @@ void pa_sink_bind_preferred_stream_to_a_sink(pa_sink *s) {
>             pa_sink_input_move_to(si, s, false);
>      }
>  }
> +
> +pa_sink *pa_sink_get_sink_from_device_port(pa_device_port *p) {

This is a good helper function, but I think it would fit slightly
better in the pa_device_port namespace. So I'd rename it to
pa_device_port_get_sink().

> +    pa_sink *rs = NULL;
> +    pa_sink *sink;
> +    uint32_t state;
> +
> +    PA_IDXSET_FOREACH(sink, p->card->sinks, state)
> +	if (p == pa_hashmap_get(sink->ports, p->name)) {
> +	    rs = sink;
> +	    break;
> +	}
> +    return rs;
> +}
> diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
> index 24e4678b1..693344ac3 100644
> --- a/src/pulsecore/sink.h
> +++ b/src/pulsecore/sink.h
> @@ -563,4 +563,5 @@ void pa_sink_set_reference_volume_direct(pa_sink *s, const pa_cvolume *volume);
>  
>  void pa_sink_move_streams_from_oldsink_to_newsink(pa_sink *old_sink, pa_sink *new_sink, bool from_user);
>  void pa_sink_bind_preferred_stream_to_a_sink(pa_sink *s);
> +pa_sink *pa_sink_get_sink_from_device_port(pa_device_port *p);
>  #endif
On 2019/1/1 上午2:33, Tanu Kaskinen wrote:
> On Mon, 2018-11-05 at 09:47 +0800, Hui Wang wrote:
>> When the active port of a sink becomes unavailable, all streams from
>> that sink should be moved to the default sink.
>>
>> When the active port of an existing sink changes state from
>> unavailable, all streams that have their "preferred_sink"
>> set to the new sink should be moved to the new sink.
>>
>> Signed-off-by: Hui Wang <hui.wang@canonical.com>
>> ---
>>   src/pulsecore/device-port.c | 16 ++++++++++++++++
>>   src/pulsecore/sink.c        | 13 +++++++++++++
>>   src/pulsecore/sink.h        |  1 +
>>   3 files changed, 30 insertions(+)
>>
>> diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
>> index 464c3f8a2..2604c9051 100644
>> --- a/src/pulsecore/device-port.c
>> +++ b/src/pulsecore/device-port.c
>> @@ -92,6 +92,7 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
>>        * be created before port objects, and then p->card could be non-NULL for
>>        * the whole lifecycle of pa_device_port. */
>>       if (p->card && p->card->linked) {
>> +	pa_sink *sink;
>>           /* A sink or source whose active port is unavailable can't be the
>>            * default sink/source, so port availability changes may affect the
>>            * default sink/source choice. */
>> @@ -102,6 +103,21 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
>>   
>>           pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index);
>>           pa_hook_fire(&p->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], p);
>> +
>> +	sink = pa_sink_get_sink_from_device_port(p);
>> +	if (!sink)
>> +	    return;
>> +	switch (p->direction) {
>> +        case PA_DIRECTION_OUTPUT:
>> +	    if (sink->active_port->available == PA_AVAILABLE_NO)
>> +		pa_sink_move_streams_from_oldsink_to_newsink(sink, p->core->default_sink, false);
> This logic isn't quite right. We should move streams away from the sink
> only if the active port is the same that just changed its availability
> status. If the current port is something other than the port that
> changed, then we should ignore the change event.

I will change this part and make it follow the correct logic.

>
>> +	    else
>> +		pa_sink_bind_preferred_stream_to_a_sink(sink);
>> +
>> +            break;
>> +        case PA_DIRECTION_INPUT:
>> +	    break;
>> +	}
>>       }
>>   }
>>   
>> diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
>> index a2a390beb..9ebc18fa1 100644
>> --- a/src/pulsecore/sink.c
>> +++ b/src/pulsecore/sink.c
>> @@ -3950,3 +3950,16 @@ void pa_sink_bind_preferred_stream_to_a_sink(pa_sink *s) {
>>              pa_sink_input_move_to(si, s, false);
>>       }
>>   }
>> +
>> +pa_sink *pa_sink_get_sink_from_device_port(pa_device_port *p) {
> This is a good helper function, but I think it would fit slightly
> better in the pa_device_port namespace. So I'd rename it to
> pa_device_port_get_sink().

OK, got it.


>
>> +    pa_sink *rs = NULL;
>> +    pa_sink *sink;
>> +    uint32_t state;
>> +
>> +    PA_IDXSET_FOREACH(sink, p->card->sinks, state)
>> +	if (p == pa_hashmap_get(sink->ports, p->name)) {
>> +	    rs = sink;
>> +	    break;
>> +	}
>> +    return rs;
>> +}
>> diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
>> index 24e4678b1..693344ac3 100644
>> --- a/src/pulsecore/sink.h
>> +++ b/src/pulsecore/sink.h
>> @@ -563,4 +563,5 @@ void pa_sink_set_reference_volume_direct(pa_sink *s, const pa_cvolume *volume);
>>   
>>   void pa_sink_move_streams_from_oldsink_to_newsink(pa_sink *old_sink, pa_sink *new_sink, bool from_user);
>>   void pa_sink_bind_preferred_stream_to_a_sink(pa_sink *s);
>> +pa_sink *pa_sink_get_sink_from_device_port(pa_device_port *p);
>>   #endif