[pulseaudio-discuss] [PATCH] switch-on-port-available: check and change default sink or source

2017-04-26 Thread Hui Wang
Suppose your machine has two sound cards as below:

Card#0(HDA INTEL HDMI)-> Sink#0(hdmi-stereo)->hdmi-output(priority: 5900)
Card#1(HDA INTEL PCH)->Sink#1(analog-stereo)->headphones(priority: 9000)

If neither hdmi cable nor headphone plug into the machine, the default
sink will randomly be Sink#0 or Sink#1, let us assume it is Sink#1,
then users plug hdmi cable into the machine, the port hdmi-output will
change to the state PA_AVAILABLE_YES, so the Sink#0 has a port with
state YES, while the Sink#1 still has a port with state NO, in this
situation it is reasonable to change the default_sink to Sink#0, but
current code can't do that.

Let us suppose another situation, both hdmi cable and headphone are
plugged into the machine, and the Sink#0 is the default sink, if users
unplug the hdmi cable, the port hdmi-output is changed to NO while
the port headphone is still kept YES, in this situation it is
reasonable to switch the default_sink to Sink#1, but current code
can't do that.

This issue also applies to the pa_source as well.

If there is only one sound card and both Sink#0 and Sink#1 belong to
this card (latest Intel platform like skylake or kabylake only
has one sound card), there is no issue. It looks like the current
switch-on-port-available can't handle multiple sound cards well.

To fix it, adding a function to check and change default sink or
source after executing switch_to_port() or switch_from_port().

Signed-off-by: Hui Wang 
---
 src/modules/module-switch-on-port-available.c | 145 ++
 1 file changed, 145 insertions(+)

diff --git a/src/modules/module-switch-on-port-available.c 
b/src/modules/module-switch-on-port-available.c
index b9a0f3b..e1113ea 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "module-switch-on-port-available-symdef.h"
 
@@ -272,6 +273,148 @@ static bool switch_from_port(pa_device_port *port) {
 return false;
 }
 
+/* This function refers to sink_put_hook_callback() in the 
module-switch-on-connect.c */
+static void move_to_new_default_sink(pa_core *c, pa_sink *ori_sink, pa_sink 
*new_sink)
+{
+pa_sink_input *i;
+uint32_t idx;
+
+pa_namereg_set_default_sink(c, new_sink);
+/* 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) {
+   if (i->save_sink || !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);
+}
+}
+
+/* This function refers to source_put_hook_callback() in the 
module-switch-on-connect.c */
+static void move_to_new_default_source(pa_core *c, pa_source *ori_src, 
pa_source *new_src)
+{
+pa_source_output *o;
+uint32_t idx;
+
+pa_namereg_set_default_source(c, new_src);
+
+/* Now move all old outputs over */
+if (pa_idxset_size(ori_src->outputs) <= 0) {
+   pa_log_debug("No source outputs to move away.");
+   return;
+}
+
+PA_IDXSET_FOREACH(o, ori_src->outputs, idx) {
+if (o->save_source || !PA_SOURCE_OUTPUT_IS_LINKED(o->state))
+continue;
+
+if (pa_source_output_move_to(o, new_src, false) < 0)
+pa_log_info("Failed to move source output %u \"%s\" to %s.", 
o->index,
+pa_strnull(pa_proplist_gets(o->proplist, 
PA_PROP_APPLICATION_NAME)), new_src->name);
+else
+pa_log_info("Successfully moved source output %u \"%s\" to %s.", 
o->index,
+pa_strnull(pa_proplist_gets(o->proplist, 
PA_PROP_APPLICATION_NAME)), new_src->name);
+}
+}
+
+/*
+  When a port changes to PA_AVAILABLE_YES, the original code tries to set it to
+  be the active_port in its own sink/source. After that we also need to check 
if
+  its sink/source is the default_sink/source or not, if it is not, it is 
possible
+  that all ports in the default_sink/source are in the state PA_AVAILABLE_NO,
+  in that case it is reasonable to replace the default_sink/source with this 
sink/source.
+  To do so, we will check the conditions as below:
+   - the default_sink/source doesn't have active_port
+   - the active_port of default_sink/source is in the s

[pulseaudio-discuss] [PATCH] switch-on-port-available: check and change default sink or source

2017-04-26 Thread Hui Wang
Suppose your machine has two sound cards as below:

Card#0(HDA INTEL HDMI)-> Sink#0(hdmi-stereo)->hdmi-output(priority: 5900)
Card#1(HDA INTEL PCH)->Sink#1(analog-stereo)->headphones(priority: 9000)

If neither hdmi cable nor headphone plug into the machine, the default
sink will randomly be Sink#0 or Sink#1, let us assume it is Sink#1,
then users plug hdmi cable into the machine, the port hdmi-output will
change to the state PA_AVAILABLE_YES, so the Sink#0 has a port with
state YES, while the Sink#1 still has a port with state NO, in this
situation it is reasonable to change the default_sink to Sink#0, but
current code can't do that.

Let us suppose another situation, both hdmi cable and headphone are
plugged into the machine, and the Sink#0 is the default sink, if users
unplug the hdmi cable, the port hdmi-output is changed to NO while
the port headphone is still kept YES, in this situation it is
reasonable to switch the default_sink to Sink#1, but current code
can't do that.

This issue also applies to the pa_source as well.

If there is only one sound card and both Sink#0 and Sink#1 belong to
this card (latest Intel platform like skylake or kabylake only
has one sound card), there is no issue. It looks like the current
switch-on-port-available can't handle multiple sound cards well.

To fix it, adding a function to check and change default sink or
source after executing switch_to_port() or switch_from_port().

Signed-off-by: Hui Wang 
---
 src/modules/module-switch-on-port-available.c | 145 ++
 1 file changed, 145 insertions(+)

diff --git a/src/modules/module-switch-on-port-available.c 
b/src/modules/module-switch-on-port-available.c
index b9a0f3b..e1113ea 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "module-switch-on-port-available-symdef.h"
 
@@ -272,6 +273,148 @@ static bool switch_from_port(pa_device_port *port) {
 return false;
 }
 
+/* This function refers to sink_put_hook_callback() in the 
module-switch-on-connect.c */
+static void move_to_new_default_sink(pa_core *c, pa_sink *ori_sink, pa_sink 
*new_sink)
+{
+pa_sink_input *i;
+uint32_t idx;
+
+pa_namereg_set_default_sink(c, new_sink);
+/* 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) {
+   if (i->save_sink || !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);
+}
+}
+
+/* This function refers to source_put_hook_callback() in the 
module-switch-on-connect.c */
+static void move_to_new_default_source(pa_core *c, pa_source *ori_src, 
pa_source *new_src)
+{
+pa_source_output *o;
+uint32_t idx;
+
+pa_namereg_set_default_source(c, new_src);
+
+/* Now move all old outputs over */
+if (pa_idxset_size(ori_src->outputs) <= 0) {
+   pa_log_debug("No source outputs to move away.");
+   return;
+}
+
+PA_IDXSET_FOREACH(o, ori_src->outputs, idx) {
+if (o->save_source || !PA_SOURCE_OUTPUT_IS_LINKED(o->state))
+continue;
+
+if (pa_source_output_move_to(o, new_src, false) < 0)
+pa_log_info("Failed to move source output %u \"%s\" to %s.", 
o->index,
+pa_strnull(pa_proplist_gets(o->proplist, 
PA_PROP_APPLICATION_NAME)), new_src->name);
+else
+pa_log_info("Successfully moved source output %u \"%s\" to %s.", 
o->index,
+pa_strnull(pa_proplist_gets(o->proplist, 
PA_PROP_APPLICATION_NAME)), new_src->name);
+}
+}
+
+/*
+  When a port changes to PA_AVAILABLE_YES, the original code tries to set it to
+  be the active_port in its own sink/source. After that we also need to check 
if
+  its sink/source is the default_sink/source or not, if it is not, it is 
possible
+  that all ports in the default_sink/source are in the state PA_AVAILABLE_NO,
+  in that case it is reasonable to replace the default_sink/source with this 
sink/source.
+  To do so, we will check the conditions as below:
+   - the default_sink/source doesn't have active_port
+   - the active_port of default_sink/source is in the s

Re: [pulseaudio-discuss] [PATCH] switch-on-port-available: check and change default sink or source

2017-04-27 Thread Hui Wang

Hello Tanu,

Could you please take a look at this patch, you are the maintainer and 
recently contributed couple of commits to 
module-switch-on-port-available.c. :-)


Thanks in advance.
Hui.






On 04/27/2017 11:20 AM, Hui Wang wrote:

Suppose your machine has two sound cards as below:

Card#0(HDA INTEL HDMI)-> Sink#0(hdmi-stereo)->hdmi-output(priority: 5900)
Card#1(HDA INTEL PCH)->Sink#1(analog-stereo)->headphones(priority: 9000)

If neither hdmi cable nor headphone plug into the machine, the default
sink will randomly be Sink#0 or Sink#1, let us assume it is Sink#1,
then users plug hdmi cable into the machine, the port hdmi-output will
change to the state PA_AVAILABLE_YES, so the Sink#0 has a port with
state YES, while the Sink#1 still has a port with state NO, in this
situation it is reasonable to change the default_sink to Sink#0, but
current code can't do that.

Let us suppose another situation, both hdmi cable and headphone are
plugged into the machine, and the Sink#0 is the default sink, if users
unplug the hdmi cable, the port hdmi-output is changed to NO while
the port headphone is still kept YES, in this situation it is
reasonable to switch the default_sink to Sink#1, but current code
can't do that.

This issue also applies to the pa_source as well.

If there is only one sound card and both Sink#0 and Sink#1 belong to
this card (latest Intel platform like skylake or kabylake only
has one sound card), there is no issue. It looks like the current
switch-on-port-available can't handle multiple sound cards well.

To fix it, adding a function to check and change default sink or
source after executing switch_to_port() or switch_from_port().

Signed-off-by: Hui Wang 
---
  src/modules/module-switch-on-port-available.c | 145 ++
  1 file changed, 145 insertions(+)

diff --git a/src/modules/module-switch-on-port-available.c 
b/src/modules/module-switch-on-port-available.c
index b9a0f3b..e1113ea 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -26,6 +26,7 @@
  #include 
  #include 
  #include 
+#include 
  
  #include "module-switch-on-port-available-symdef.h"
  
@@ -272,6 +273,148 @@ static bool switch_from_port(pa_device_port *port) {

  return false;
  }
  
+/* This function refers to sink_put_hook_callback() in the module-switch-on-connect.c */

+static void move_to_new_default_sink(pa_core *c, pa_sink *ori_sink, pa_sink 
*new_sink)
+{
+pa_sink_input *i;
+uint32_t idx;
+
+pa_namereg_set_default_sink(c, new_sink);
+/* 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) {
+   if (i->save_sink || !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);
+}
+}
+
+/* This function refers to source_put_hook_callback() in the 
module-switch-on-connect.c */
+static void move_to_new_default_source(pa_core *c, pa_source *ori_src, 
pa_source *new_src)
+{
+pa_source_output *o;
+uint32_t idx;
+
+pa_namereg_set_default_source(c, new_src);
+
+/* Now move all old outputs over */
+if (pa_idxset_size(ori_src->outputs) <= 0) {
+   pa_log_debug("No source outputs to move away.");
+   return;
+}
+
+PA_IDXSET_FOREACH(o, ori_src->outputs, idx) {
+if (o->save_source || !PA_SOURCE_OUTPUT_IS_LINKED(o->state))
+continue;
+
+if (pa_source_output_move_to(o, new_src, false) < 0)
+pa_log_info("Failed to move source output %u \"%s\" to %s.", 
o->index,
+pa_strnull(pa_proplist_gets(o->proplist, 
PA_PROP_APPLICATION_NAME)), new_src->name);
+else
+pa_log_info("Successfully moved source output %u \"%s\" to %s.", 
o->index,
+pa_strnull(pa_proplist_gets(o->proplist, 
PA_PROP_APPLICATION_NAME)), new_src->name);
+}
+}
+
+/*
+  When a port changes to PA_AVAILABLE_YES, the original code tries to set it to
+  be the active_port in its own sink/source. After that we also need to check 
if
+  its sink/source is the default_sink/source or not, if it is not, it is 
possible
+  that all ports in the default_sink/source are in the state PA_AVAILABLE_NO,
+  in that cas

Re: [pulseaudio-discuss] [PATCH] switch-on-port-available: check and change default sink or source

2017-05-01 Thread Hui Wang

On 04/29/2017 09:04 PM, Tanu Kaskinen wrote:

On Fri, 2017-04-28 at 12:21 +0800, Hui Wang wrote:

Hello Tanu,

Could you please take a look at this patch, you are the maintainer and
recently contributed couple of commits to
module-switch-on-port-available.c. :-)

Well, I'm trying to concentrate on preparing for the release, so I
don't do patch reviews much at the moment. Now that I read the commit
message, I have some comments, though.


On 04/27/2017 11:20 AM, Hui Wang wrote:

Suppose your machine has two sound cards as below:

Card#0(HDA INTEL HDMI)-> Sink#0(hdmi-stereo)->hdmi-output(priority: 5900)
Card#1(HDA INTEL PCH)->Sink#1(analog-stereo)->headphones(priority: 9000)

If neither hdmi cable nor headphone plug into the machine, the default
sink will randomly be Sink#0 or Sink#1, let us assume it is Sink#1,
then users plug hdmi cable into the machine, the port hdmi-output will
change to the state PA_AVAILABLE_YES, so the Sink#0 has a port with
state YES, while the Sink#1 still has a port with state NO, in this
situation it is reasonable to change the default_sink to Sink#0, but
current code can't do that.

This problem should be fixed by these two patches:
https://patchwork.freedesktop.org/patch/139179/
https://patchwork.freedesktop.org/patch/139178/

The patches have been reviewed, but I haven't yet pushed them. I'm not
sure if they'll be in the next release or not (I need to ask Georg and
Arun if they want to grant a freeze exception for these patches).


Let us suppose another situation, both hdmi cable and headphone are
plugged into the machine, and the Sink#0 is the default sink, if users
unplug the hdmi cable, the port hdmi-output is changed to NO while
the port headphone is still kept YES, in this situation it is
reasonable to switch the default_sink to Sink#1, but current code
can't do that.

This should be fixed too by those two patches mentioned above.

Good to know that, look forward to those patches being merged to the 
mainline. :-)


Thank you for your comment and thank you for your patches.

Cheers,
Hui.


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


Re: [pulseaudio-discuss] [PATCH] switch-on-port-available: check and change default sink or source

2017-05-02 Thread Hui Wang

On 05/02/2017 09:27 PM, Tanu Kaskinen wrote:

On Tue, 2017-05-02 at 08:55 +0800, Hui Wang wrote:

On 04/29/2017 09:04 PM, Tanu Kaskinen wrote:

On Fri, 2017-04-28 at 12:21 +0800, Hui Wang wrote:

Hello Tanu,

Could you please take a look at this patch, you are the maintainer and
recently contributed couple of commits to
module-switch-on-port-available.c. :-)

Well, I'm trying to concentrate on preparing for the release, so I
don't do patch reviews much at the moment. Now that I read the commit
message, I have some comments, though.


On 04/27/2017 11:20 AM, Hui Wang wrote:

Suppose your machine has two sound cards as below:

Card#0(HDA INTEL HDMI)-> Sink#0(hdmi-stereo)->hdmi-output(priority: 5900)
Card#1(HDA INTEL PCH)->Sink#1(analog-stereo)->headphones(priority: 9000)

If neither hdmi cable nor headphone plug into the machine, the default
sink will randomly be Sink#0 or Sink#1, let us assume it is Sink#1,
then users plug hdmi cable into the machine, the port hdmi-output will
change to the state PA_AVAILABLE_YES, so the Sink#0 has a port with
state YES, while the Sink#1 still has a port with state NO, in this
situation it is reasonable to change the default_sink to Sink#0, but
current code can't do that.

This problem should be fixed by these two patches:
https://patchwork.freedesktop.org/patch/139179/
https://patchwork.freedesktop.org/patch/139178/

The patches have been reviewed, but I haven't yet pushed them. I'm not
sure if they'll be in the next release or not (I need to ask Georg and
Arun if they want to grant a freeze exception for these patches).


Let us suppose another situation, both hdmi cable and headphone are
plugged into the machine, and the Sink#0 is the default sink, if users
unplug the hdmi cable, the port hdmi-output is changed to NO while
the port headphone is still kept YES, in this situation it is
reasonable to switch the default_sink to Sink#1, but current code
can't do that.

This should be fixed too by those two patches mentioned above.


Good to know that, look forward to those patches being merged to the
mainline. :-)

Thank you for your comment and thank you for your patches.

I pushed the patches to master now. I hope they solve your problems!

Today I tested the latest master branch (already including your two 
patches), seems it did not fix the problem. Below is my testing detail:


Install ubuntu 16.04 on my laptop.
clone the latest pulseaudio source code, checkout master branch
build the source code: ./autogen.sh;make
kill the existing pulseaudio and run the latest pulseaudio: pulseaudio 
--kill && ./src/pulseaudio -vvvnF ./src/default.pa -p $(pwd)/src


On this machine, we have sound cards, sinks and ports like below:

Card#0(HDA INTEL HDMI)-> Sink#0(hdmi-stereo)->hdmi-output(priority: 5900)
Card#1(HDA INTEL PCH)->Sink#1(analog-stereo)->headphones(priority: 9000)

with the new pulseaudio, I can only see one sink (analog-stereo) through pactl 
list sinks at the beginning.

After I plug the HDMI cable (headphone is not plugged), I can see two sinks via 
pactl list sinks, but the default sink is still the analog-stereo, here I 
expect the default sink is hdmi-stereo since the headphone is not plugged yet.

Then I plug the headphone, and I select the hdmi (hdmi is also plugged in) as 
the default sink, after a while I unplug the hdmi cable, here I expect the 
default sink is back to analog-stereo since headphone is still plugged, but the 
default sink did not switch to analog-stereo. BTW after I unplug the hdmi 
cable, I can still see two sinks.

Cheers,
Hui.


 


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


[pulseaudio-discuss] [PATCH] alsa: make headset-mic scanned earlier than headphone-mic

2017-05-15 Thread Hui Wang
On some Dell machines with realtek codec, they have a headset audio
jack which supports headphone, headset and pure microphone, but this
audio jack can only detect something is plugged in but doesn't have
capabilites to distinguish what is plugged in. So we need to apply the
fixup similar to ALC298_FIXUP_DELL1_MIC_NO_PRESENCE to the kernel
driver. When something is plugged in, a pop-up dialogue shows up and
users can select what is plugged in.

On some Dell machines (especially desktop computers), they have no
internal microphone, if users plug a headphone and select the
headphone, the headphone is supposed to work, but there is no sound
can be played via headphone.

Through debugging, I found the root cause has something to do with
the active_port of pa-source, since there is no internal microphone,
and there is no other available input devices, the headphone-mic and
headset-mic will be the candidates to be the active_port, and they
have the same priority and headphone-mic is scanned earlier than
headset-mic, so the headphone-mic is set to be the active_port. After
users select the headphone, the function alc_update_headset_mode()
in the kernel driver will be called, in this function it will check
what is the default input device for that jack, if it is
headphone-mic, that means users want this jack to work as a pure
microphone jack, then it will configure the codec and the jack is
changed to be a mic-in jack. As a result even users plug and select
the headphone, but this jack can't work with headphone.

A simple fix for this issue is to exchange the position of
headphone-mic and headset-mic, then the headset-mic will be the
active_port of pa-source if there is no internal microphone and no
other available input devices.

Signed-off-by: Hui Wang 
---
 src/modules/alsa/mixer/profile-sets/default.conf | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/modules/alsa/mixer/profile-sets/default.conf 
b/src/modules/alsa/mixer/profile-sets/default.conf
index f412058..16ee567 100644
--- a/src/modules/alsa/mixer/profile-sets/default.conf
+++ b/src/modules/alsa/mixer/profile-sets/default.conf
@@ -112,7 +112,7 @@ priority = 2
 device-strings = front:%f
 channel-map = left,right
 paths-output = analog-output analog-output-lineout analog-output-speaker 
analog-output-headphones analog-output-headphones-2
-paths-input = analog-input-front-mic analog-input-rear-mic 
analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic 
analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner 
analog-input-fm analog-input-mic-line analog-input-headphone-mic 
analog-input-headset-mic
+paths-input = analog-input-front-mic analog-input-rear-mic 
analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic 
analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner 
analog-input-fm analog-input-mic-line analog-input-headset-mic 
analog-input-headphone-mic
 priority = 10
 
 [Mapping analog-surround-21]
-- 
1.9.1

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


Re: [pulseaudio-discuss] [PATCH] switch-on-port-available: check and change default sink or source

2017-05-16 Thread Hui Wang

On 05/03/2017 06:51 PM, Tanu Kaskinen wrote:

On Wed, 2017-05-03 at 11:23 +0800, Hui Wang wrote:

Today I tested the latest master branch (already including your two
patches), seems it did not fix the problem. Below is my testing detail:

Install ubuntu 16.04 on my laptop.
clone the latest pulseaudio source code, checkout master branch
build the source code: ./autogen.sh;make
kill the existing pulseaudio and run the latest pulseaudio: pulseaudio
--kill && ./src/pulseaudio -vvvnF ./src/default.pa -p $(pwd)/src

On this machine, we have sound cards, sinks and ports like below:

Card#0(HDA INTEL HDMI)-> Sink#0(hdmi-stereo)->hdmi-output(priority: 5900)
Card#1(HDA INTEL PCH)->Sink#1(analog-stereo)->headphones(priority: 9000)

No speaker port at all on the PCH card?

Sorry for late response, just came back from a vacation.

I removed the speaker from the kernel driver intentionally for debugging 
another audio bug.


But it does not matter, if I don't remove the speaker, the Sink#1 has 
the speaker on it, and the default sink is Sink#1, after plugging the 
HDMI cable, the default sink is still Sink#1, it is expected since 
Sink#1 has an available port which has higher priority than HDMI port, 
then I select the HDMI to be the default sink manually, now the default 
sink is Sink#0. After that I unplug the HDMI cable, the Sink#1 is 
expected to be the default sink since the Sink#0 has no available ports 
on it, but the default sink doesn't switch back to Sink#1.




with the new pulseaudio, I can only see one sink (analog-stereo)
through pactl list sinks at the beginning.

After I plug the HDMI cable (headphone is not plugged), I can see two
sinks via pactl list sinks, but the default sink is still the analog-
stereo, here I expect the default sink is hdmi-stereo since the
headphone is not plugged yet.

That's what I'd expect too. Is the headphone port marked as unavailable
as it should?

Yes, it is marked "not available".

Then I plug the headphone, and I select the hdmi (hdmi is also
plugged in) as the default sink, after a while I unplug the hdmi
cable, here I expect the default sink is back to analog-stereo since
headphone is still plugged, but the default sink did not switch to
analog-stereo. BTW after I unplug the hdmi cable, I can still see two
sinks.

The default sink is set in pa_core_update_default_sink() in
src/pulsecore/core.c. That function uses the compare_sinks() function,
and the first thing compare_sinks() does is to check if one of the
compared sinks has an unavailable port active. Can you figure out what
goes wrong? Is pa_core_update_default_sink() not called when you plug
in or unplug things, or does pa_core_update_default_sink() really
choose a sink whose active port is unavailable?
Through debugging, I found the function pa_core_update_default_sink() is 
not called when unplug the HDMI cable in the situation above.



The good news is after applying your new patch "[PATCH] sink, source: 
update the default sink/source on port switches", the issue is fixed. 
The function pa_core_update_default_sink() is called when 
plugging/unplugging some audio output devices, and the default_sink is 
changed as expected.


Thank you for your patches. :-)

Thanks,
Hui.


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


Re: [pulseaudio-discuss] [PATCH] alsa: make headset-mic scanned earlier than headphone-mic

2017-05-18 Thread Hui Wang

Hello Tanu,

Could you please help take a look at this patch? This patch really fix 
an issue on some Dell machines (with realtek codec and has no internal 
microphone on them), And I think this minor change will not introduce 
regression, it is pretty safe.


Thanks in advance.
Hui.

On 05/16/2017 11:21 AM, Hui Wang wrote:

On some Dell machines with realtek codec, they have a headset audio
jack which supports headphone, headset and pure microphone, but this
audio jack can only detect something is plugged in but doesn't have
capabilites to distinguish what is plugged in. So we need to apply the
fixup similar to ALC298_FIXUP_DELL1_MIC_NO_PRESENCE to the kernel
driver. When something is plugged in, a pop-up dialogue shows up and
users can select what is plugged in.

On some Dell machines (especially desktop computers), they have no
internal microphone, if users plug a headphone and select the
headphone, the headphone is supposed to work, but there is no sound
can be played via headphone.

Through debugging, I found the root cause has something to do with
the active_port of pa-source, since there is no internal microphone,
and there is no other available input devices, the headphone-mic and
headset-mic will be the candidates to be the active_port, and they
have the same priority and headphone-mic is scanned earlier than
headset-mic, so the headphone-mic is set to be the active_port. After
users select the headphone, the function alc_update_headset_mode()
in the kernel driver will be called, in this function it will check
what is the default input device for that jack, if it is
headphone-mic, that means users want this jack to work as a pure
microphone jack, then it will configure the codec and the jack is
changed to be a mic-in jack. As a result even users plug and select
the headphone, but this jack can't work with headphone.

A simple fix for this issue is to exchange the position of
headphone-mic and headset-mic, then the headset-mic will be the
active_port of pa-source if there is no internal microphone and no
other available input devices.

Signed-off-by: Hui Wang 
---
  src/modules/alsa/mixer/profile-sets/default.conf | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/modules/alsa/mixer/profile-sets/default.conf 
b/src/modules/alsa/mixer/profile-sets/default.conf
index f412058..16ee567 100644
--- a/src/modules/alsa/mixer/profile-sets/default.conf
+++ b/src/modules/alsa/mixer/profile-sets/default.conf
@@ -112,7 +112,7 @@ priority = 2
  device-strings = front:%f
  channel-map = left,right
  paths-output = analog-output analog-output-lineout analog-output-speaker 
analog-output-headphones analog-output-headphones-2
-paths-input = analog-input-front-mic analog-input-rear-mic 
analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic 
analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner 
analog-input-fm analog-input-mic-line analog-input-headphone-mic 
analog-input-headset-mic
+paths-input = analog-input-front-mic analog-input-rear-mic 
analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic 
analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner 
analog-input-fm analog-input-mic-line analog-input-headset-mic 
analog-input-headphone-mic
  priority = 10
  
  [Mapping analog-surround-21]



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


Re: [pulseaudio-discuss] [PATCH] alsa: make headset-mic scanned earlier than headphone-mic

2017-05-22 Thread Hui Wang

On 05/20/2017 10:51 PM, Tanu Kaskinen wrote:

On Fri, 2017-05-19 at 09:29 +0800, Hui Wang wrote:

Hello Tanu,

Could you please help take a look at this patch? This patch really fix
an issue on some Dell machines (with realtek codec and has no internal
microphone on them), And I think this minor change will not introduce
regression, it is pretty safe.

The patch only changes the order in which headset-mic and headphone-mic
are listed, and that order should not have any real impact on anything.
There's clearly a bug somewhere, but the bug can't be that the paths
are listed in the wrong order, since the order should not matter.
Yes, you are right. In theory, the headset-mic and headphone-mic have 
the same priority, so exchanging their order should not have any real 
impact on anything.


But in practice, this bug exposes that in some situation( when there are 
only headphone-mic and headset-mic, and neither of them is plugged in.), 
the headphone-mic is not suitable to be the default active_port.  So do 
you think if it is acceptable that I don't exchange their order, I just 
adjust their priorities to make the headset-mic's priority a bit higher 
than headphone-mic's?





If the port must not be headphone-mic when the user chooses headphones
in the UI, couldn't the UI program tell pulseaudio to switch to
headset-mic?

Yes, the UI program could do that. If it is not allowed to adjust their 
priorities, we have to change the UI program.



Thanks,
Hui.

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


Re: [pulseaudio-discuss] [PATCH] alsa: make headset-mic scanned earlier than headphone-mic

2017-05-23 Thread Hui Wang

On 05/23/2017 04:20 PM, Tanu Kaskinen wrote:

On Tue, 2017-05-23 at 11:04 +0800, Hui Wang wrote:

On 05/20/2017 10:51 PM, Tanu Kaskinen wrote:

On Fri, 2017-05-19 at 09:29 +0800, Hui Wang wrote:

Hello Tanu,

Could you please help take a look at this patch? This patch really fix
an issue on some Dell machines (with realtek codec and has no internal
microphone on them), And I think this minor change will not introduce
regression, it is pretty safe.

The patch only changes the order in which headset-mic and headphone-mic
are listed, and that order should not have any real impact on anything.
There's clearly a bug somewhere, but the bug can't be that the paths
are listed in the wrong order, since the order should not matter.

Yes, you are right. In theory, the headset-mic and headphone-mic have
the same priority, so exchanging their order should not have any real
impact on anything.

But in practice, this bug exposes that in some situation( when there are
only headphone-mic and headset-mic, and neither of them is plugged in.),
the headphone-mic is not suitable to be the default active_port.  So do
you think if it is acceptable that I don't exchange their order, I just
adjust their priorities to make the headset-mic's priority a bit higher
than headphone-mic's?

If I understand correctly, headphones and headsets only work with the
headset-mic port, and microphones only work with the headphone-mic
port. Since it's more likely that a user plugs in headphones or a
headset than a microphone, I think it's ok to make the headset-mic
priority a bit higher than headphone-mic.
There is only one audio jack, users can plug headphone, headset or 
microphone into it.  On some Dell machines which has realtek codec, the 
codec/audio jack can't distinguish from hardware perspective what 
devices the user plugged in, so users need to do a choice from UI program:


When user plug in a headphone and select the headphone,  the UI program 
will set the headphone to be the active_port of pa_sink, and kernel 
audio driver (patch_reaktek) will configure the codec to make that audio 
jack work as a headphone jack


When user plug in a headset and select the headset-mic, the UI program 
will set the headphone to be the active_port of pa_sink and set the 
headset-mic to be the active_port of pa_source,  and kernel driver will 
configure the audio jack to be the headset jack



When user plug in a microphone and select the headphone-mic, the UI 
program will set the headphone-mic to be the active_port of pa_source, 
and kernel driver will configure the audio jack to be the microphone 
jack, then this jack can't work with headphone.




However, that still doesn't fix the bug properly, I think. What if the
user plugs in a microphone and selects it in the UI? What will make
pulseaudio switch to the headphone-mic?
The UI program will do that. The UI program will call 
pa_context_set_source_port_by_index() to do that.

  What will make pulseaudio
switch to the headset-mic port if headphones or a headset is plugged in
later?
This problem does not exist, since there is only one physical jack, if 
user want to plug headset or headphone, he need to unplug the microphone 
first. After user plug in the headphone or headset, the UI program will 
call pa_context_set_source/sink_port_by_index() to set active port 
according to user's choice.





It sounds like the kernel might be buggy too. Why does it have to
disable headphone output if pulseaudio's active source port happens to
be headphone-mic?
It is not a bug, some realtek codec can configure a port (pins) to be 
input or output,  that means a physical jack can be configured as 
headphone jack or microphone jack.


When headphone-mic is active source port, the audio driver only disable 
the headphone shared the same port with this headphone-mic, the kernel 
driver doesn't disable other headphones.

The kernel seems to select from two mic modes:
headset or microphone, but I don't understand why it doesn't have a
mode for no mic input at all, which could be used when headphones are
plugged in.

For most cases (almost 99.999% cases), the output choice and input 
choice doesn't impact each other. This problem only happens on some dell 
machines, which has realtek codec, and has a physical audio jack to 
support headphone, headset or microphone, and the codec has no hardware 
ability to distinguish devices.



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


Re: [pulseaudio-discuss] [PATCH] alsa: make headset-mic scanned earlier than headphone-mic

2017-05-23 Thread Hui Wang

On 05/23/2017 07:35 PM, Tanu Kaskinen wrote:

On Tue, 2017-05-23 at 17:36 +0800, Hui Wang wrote:

On 05/23/2017 04:20 PM, Tanu Kaskinen wrote:

On Tue, 2017-05-23 at 11:04 +0800, Hui Wang wrote:

On 05/20/2017 10:51 PM, Tanu Kaskinen wrote:

On Fri, 2017-05-19 at 09:29 +0800, Hui Wang wrote:

Hello Tanu,

Could you please help take a look at this patch? This patch really fix
an issue on some Dell machines (with realtek codec and has no internal
microphone on them), And I think this minor change will not introduce
regression, it is pretty safe.

The patch only changes the order in which headset-mic and headphone-mic
are listed, and that order should not have any real impact on anything.
There's clearly a bug somewhere, but the bug can't be that the paths
are listed in the wrong order, since the order should not matter.

Yes, you are right. In theory, the headset-mic and headphone-mic have
the same priority, so exchanging their order should not have any real
impact on anything.

But in practice, this bug exposes that in some situation( when there are
only headphone-mic and headset-mic, and neither of them is plugged in.),
the headphone-mic is not suitable to be the default active_port.  So do
you think if it is acceptable that I don't exchange their order, I just
adjust their priorities to make the headset-mic's priority a bit higher
than headphone-mic's?

If I understand correctly, headphones and headsets only work with the
headset-mic port, and microphones only work with the headphone-mic
port. Since it's more likely that a user plugs in headphones or a
headset than a microphone, I think it's ok to make the headset-mic
priority a bit higher than headphone-mic.

There is only one audio jack, users can plug headphone, headset or
microphone into it.  On some Dell machines which has realtek codec, the
codec/audio jack can't distinguish from hardware perspective what
devices the user plugged in, so users need to do a choice from UI program:

When user plug in a headphone and select the headphone,  the UI program
will set the headphone to be the active_port of pa_sink, and kernel
audio driver (patch_reaktek) will configure the codec to make that audio
jack work as a headphone jack

What makes the kernel do that? Does the kernel rely only on the mixer
settings set by pulseaudio to figure out how to configure the jack?
Which mixer elements affect the kernel's decision?


It depends on the mixer  "Capture Source".

In the kernel, the function alc_update_headset_mode() in the 
$kernel_dir/sound/pci/hda/patch_realtek.c will handle it.



When user plug in a headset and select the headset-mic, the UI program
will set the headphone to be the active_port of pa_sink and set the
headset-mic to be the active_port of pa_source,  and kernel driver will
configure the audio jack to be the headset jack


When user plug in a microphone and select the headphone-mic, the UI
program will set the headphone-mic to be the active_port of pa_source,
and kernel driver will configure the audio jack to be the microphone
jack, then this jack can't work with headphone.


However, that still doesn't fix the bug properly, I think. What if the
user plugs in a microphone and selects it in the UI? What will make
pulseaudio switch to the headphone-mic?

The UI program will do that. The UI program will call
pa_context_set_source_port_by_index() to do that.

   What will make pulseaudio
switch to the headset-mic port if headphones or a headset is plugged in
later?

This problem does not exist, since there is only one physical jack, if
user want to plug headset or headphone, he need to unplug the microphone
first. After user plug in the headphone or headset, the UI program will
call pa_context_set_source/sink_port_by_index() to set active port
according to user's choice.

But isn't it so that if the user selects headphones, the UI program
won't change the source port? So if the user first had a microphone
plugged in, and then unplugged that and plugged in headphones instead,
the headphones won't work, because the headphone-mic port is still
active.

Yes, you are right, this is another issue I did not think about before. 
Because most of the machines (laptop) have internal microphone, and 
after the headphone-mic is unplugged, the input source will switch to 
internal microphone automatically, so this issue has not exposed.


I admit that UI program has some problems, it should not only take care 
of output devices when users select headphone. The UI program needs to 
be improved.


BTW, I just did a test, increased the headset-mic's priority to 88, and 
keep the headphone-mic's priority to 87, after booting up, the default 
input active_port is headset-mic (that is expected), I plug a microphone 
and select "headphone-mic" from UI program, the input active_port is 
headphone-mic now, then I unplug the headphone-mic, the 

Re: [pulseaudio-discuss] [PATCH] alsa: make headset-mic scanned earlier than headphone-mic

2017-05-24 Thread Hui Wang



keep the headphone-mic's priority to 87, after booting up, the default
input active_port is headset-mic (that is expected), I plug a microphone
and select "headphone-mic" from UI program, the input active_port is
headphone-mic now, then I unplug the headphone-mic, the input
active_port is  changed back to headset-mic. So changing priority really
can fix these two issues.

Do both ports change availability status from "no" to "unknown" when
anything is plugged in? That would explain why increasing the headset-
mic priority fixes both issues.

Yes, it works in the way as you guess.

I guess you'll write a patch for increasing the port priority. I would
strongly recommend changing the UI program as well, but that's up to
you.
I will write a patch to increase port priority first, later I will 
improve the UI program.



Thanks,
Hui.


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


[pulseaudio-discuss] [PATCH] alsa: make priority of the port headset-mic higher than headphone-mic

2017-05-24 Thread Hui Wang
There are two reasons for this change:

1. If it is a Dell desktop machine with the realtek codec, and there
is no internal microphone on it, there is one physical audio jack
which can support headphone, headset and microphone, but this audio
jack does not have hardware capability to distinguish what is plugged
in, after users plug in a headphone and select headphone from UI
program, the headphone can't output any sound. There are many reasons
for this issue, one of them is the active_port of pa_source is set
to headphone-mic, that means the kernel audio driver will configure
this audio jack to be a microphone jack instead of headphone jack.
If we make the priority of headset-mic a bit higher than headphone-mic,
the headset-mic will be the active_port of pa_source unless users
select the headphone-mic on purpose, then this issue will be fixed.

2. Nowadays, the headset is more popular than traditional microphone,
It is highly possible that users plug in a headset instead of
microphone, it makes sense to make the headset-mic's priority higher
than headphone-mic's.

Signed-off-by: Hui Wang 
---
 src/modules/alsa/mixer/paths/analog-input-headset-mic.conf | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf 
b/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf
index b669bc4..579db6b 100644
--- a/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf
+++ b/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf
@@ -18,7 +18,7 @@
 ; See analog-output.conf.common for an explanation on the directives
 
 [General]
-priority = 87
+priority = 88
 description-key = analog-input-microphone-headset
 
 [Jack Headset Mic]
-- 
1.9.1

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


[pulseaudio-discuss] [PATCH] alsa-mixer: Add support for usb audio in the Dell dock TB16

2017-05-26 Thread Hui Wang
There are one headset jack on the front panel of TB16, through this
jack, we have one stereo headphone output (hw:%f,0,0) and one mono
headset-mic input (hw:%f,0,0); and there is one speaker output jack
(hw:%f,1,0) on the rear panel of TB16.

The detail information of the Dell dock TB16:
http://www.dell.com/support/article/sg/en/sgbsdt1/SLN301105

Signed-off-by: Hui Wang 
---
 .../alsa/mixer/profile-sets/90-pulseaudio.rules|  1 +
 .../profile-sets/dell-dock-tb16-usb-audio.conf | 55 ++
 2 files changed, 56 insertions(+)
 create mode 100644 
src/modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf

diff --git a/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules 
b/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules
index 70e34e6..805a05b 100644
--- a/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules
+++ b/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules
@@ -98,5 +98,6 @@ ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1021", 
ENV{PULSE_PROFILE_SET}="nativ
 ATTRS{idVendor}=="0763", ATTRS{idProduct}=="2012", 
ENV{PULSE_PROFILE_SET}="maudio-fasttrack-pro.conf"
 ATTRS{idVendor}=="045e", ATTRS{idProduct}=="02bb", 
ENV{PULSE_PROFILE_SET}="kinect-audio.conf"
 ATTRS{idVendor}=="041e", ATTRS{idProduct}=="322c", 
ENV{PULSE_PROFILE_SET}="sb-omni-surround-5.1.conf"
+ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4014", 
ENV{PULSE_PROFILE_SET}="dell-dock-tb16-usb-audio.conf"
 
 LABEL="pulseaudio_end"
diff --git a/src/modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf 
b/src/modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf
new file mode 100644
index 000..1186552
--- /dev/null
+++ b/src/modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf
@@ -0,0 +1,55 @@
+# This file is part of PulseAudio.
+#
+# PulseAudio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# PulseAudio is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
+
+; Dell Dock TB16 USB audio
+;
+; This card has two stereo pairs of output, One Mono input.
+;
+; See default.conf for an explanation on the directives used here.
+
+[General]
+auto-profiles = no
+
+[Mapping analog-stereo-headphone]
+description = Headphone
+device-strings = hw:%f,0,0
+channel-map = left,right
+direction = output
+
+[Mapping analog-stereo-speaker]
+description = Speaker
+device-strings = hw:%f,1,0
+channel-map = left,right
+direction = output
+
+[Mapping analog-stereo-mic]
+description = Headset-Mic
+device-strings = hw:%f,0,0
+channel-map = left,right
+direction = input
+
+
+[Profile output:analog-stereo-speaker]
+description = Speaker
+output-mappings = analog-stereo-speaker
+priority = 60
+skip-probe = yes
+
+[Profile output:analog-stereo-headphone+input:analog-stereo-mic]
+description = Headset
+output-mappings = analog-stereo-headphone
+input-mappings = analog-stereo-mic
+priority = 80
+skip-probe = yes
-- 
2.7.4

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


[pulseaudio-discuss] [PATCH] rescue-streams: try to find best one using availability and priority

2014-05-28 Thread Hui Wang
Recently met a problem: when I disconnect the bluetooth headset, the
pulseaudio automatically switch the sound to sink of HDMI output
instead of the sink of internal speaker even though there is no HDMI
cable connected.

To fix this problem, I want to change the rule of selecting the target
sink(same rules apply to the source selecting):
If the sinks have the port with PA_AVAILABLE_YES, we will choose the
one from them with a highest priority port. If all sinks don't have
the port with PA_AVAILABLE_YES, we will choose the one with a highest
priority port.

Signed-off-by: Hui Wang 
---
 src/modules/module-rescue-streams.c | 80 +
 1 file changed, 54 insertions(+), 26 deletions(-)

diff --git a/src/modules/module-rescue-streams.c 
b/src/modules/module-rescue-streams.c
index 7035a35..8a4c8d6 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -53,33 +53,47 @@ struct userdata {
 };
 
 static pa_sink* find_evacuation_sink(pa_core *c, pa_sink_input *i, pa_sink 
*skip) {
-pa_sink *target, *def;
+pa_sink *target, *best_target = NULL;
+pa_device_port *port, *best_port = NULL;
 uint32_t idx;
 
 pa_assert(c);
 pa_assert(i);
 
-def = pa_namereg_get_default_sink(c);
-
-if (def && def != skip && pa_sink_input_may_move_to(i, def))
-return def;
-
 PA_IDXSET_FOREACH(target, c->sinks, idx) {
-if (target == def)
-continue;
-
 if (target == skip)
 continue;
 
 if (!PA_SINK_IS_LINKED(pa_sink_get_state(target)))
 continue;
 
-if (pa_sink_input_may_move_to(i, target))
-return target;
+if (!pa_sink_input_may_move_to(i, target))
+continue;
+
+port = pa_device_port_find_best(target->ports);
+if (!port)
+   continue;
+
+   if (!best_target) {
+   best_target = target;
+best_port = port;
+continue;
+   }
+
+   if (best_port->available != port->available && best_port->available == 
PA_AVAILABLE_YES)
+   continue;
+
+   if (best_port->available == port->available && best_port->priority > 
port->priority)
+   continue;
+
+best_target = target;
+best_port = port;
 }
 
-pa_log_debug("No evacuation sink found.");
-return NULL;
+if(!best_target)
+pa_log_debug("No evacuation sink found.");
+
+return best_target;
 }
 
 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
@@ -141,21 +155,14 @@ static pa_hook_result_t 
sink_input_move_fail_hook_callback(pa_core *c, pa_sink_i
 }
 
 static pa_source* find_evacuation_source(pa_core *c, pa_source_output *o, 
pa_source *skip) {
-pa_source *target, *def;
+pa_source *target, *best_target = NULL;
+pa_device_port *port, *best_port = NULL;
 uint32_t idx;
 
 pa_assert(c);
 pa_assert(o);
 
-def = pa_namereg_get_default_source(c);
-
-if (def && def != skip && pa_source_output_may_move_to(o, def))
-return def;
-
 PA_IDXSET_FOREACH(target, c->sources, idx) {
-if (target == def)
-continue;
-
 if (target == skip)
 continue;
 
@@ -165,12 +172,33 @@ static pa_source* find_evacuation_source(pa_core *c, 
pa_source_output *o, pa_sou
 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(target)))
 continue;
 
-if (pa_source_output_may_move_to(o, target))
-return target;
+if (!pa_source_output_may_move_to(o, target))
+continue;
+
+port = pa_device_port_find_best(target->ports);
+if (!port)
+   continue;
+
+   if (!best_target) {
+   best_target = target;
+best_port = port;
+continue;
+   }
+
+   if (best_port->available != port->available && best_port->available == 
PA_AVAILABLE_YES)
+   continue;
+
+   if (best_port->available == port->available && best_port->priority > 
port->priority)
+   continue;
+
+best_target = target;
+best_port = port;
 }
 
-pa_log_debug("No evacuation source found.");
-return NULL;
+if (!best_target)
+pa_log_debug("No evacuation source found.");
+
+return best_target;
 }
 
 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source 
*source, void* userdata) {
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [V2 PATCH] rescue-streams: try to find best one using availability and priority

2014-05-29 Thread Hui Wang
Recently met a problem: when I disconnect the bluetooth headset, the
pulseaudio automatically switch the sound to sink of HDMI output
instead of the sink of internal speaker even though there is no HDMI
cable connected.

To fix this problem, I want to change the rule of selecting the target
sink(same rules apply to the source selecting):
construct a new hashmap with all ports (of all relevant sinks) and
then call find_best on the new hashmap to find the best port, finally
find the corresponding sink using the best port.

Signed-off-by: Hui Wang 
---
 src/modules/module-rescue-streams.c | 95 +++--
 1 file changed, 71 insertions(+), 24 deletions(-)

diff --git a/src/modules/module-rescue-streams.c 
b/src/modules/module-rescue-streams.c
index 7035a35..eb40f90 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -52,34 +52,77 @@ struct userdata {
 *source_output_move_fail_slot;
 };
 
+static pa_source* find_source_from_port(pa_core *c, pa_device_port *port) {
+pa_source *target;
+uint32_t idx;
+
+if (!port)
+return NULL;
+
+PA_IDXSET_FOREACH(target, c->sources, idx)
+   if (port == pa_hashmap_get(target->ports, port->name))
+   return target;
+
+return NULL;
+}
+
+static pa_sink* find_sink_from_port(pa_core *c, pa_device_port *port) {
+pa_sink *target;
+uint32_t idx;
+
+if (!port)
+return NULL;
+
+PA_IDXSET_FOREACH(target, c->sinks, idx)
+   if (port == pa_hashmap_get(target->ports, port->name))
+   return target;
+
+return NULL;
+}
+
+static void build_group_ports(pa_hashmap *g_ports, pa_hashmap *s_ports) {
+void *state;
+pa_device_port *p;
+
+if (!g_ports || !s_ports)
+return;
+
+PA_HASHMAP_FOREACH(p, s_ports, state)
+pa_hashmap_put(g_ports, p->name, p);
+}
+
 static pa_sink* find_evacuation_sink(pa_core *c, pa_sink_input *i, pa_sink 
*skip) {
-pa_sink *target, *def;
+pa_sink *target;
 uint32_t idx;
+pa_hashmap *all_ports;
+pa_device_port *best_port;
 
 pa_assert(c);
 pa_assert(i);
 
-def = pa_namereg_get_default_sink(c);
-
-if (def && def != skip && pa_sink_input_may_move_to(i, def))
-return def;
+all_ports = pa_hashmap_new(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func);
 
 PA_IDXSET_FOREACH(target, c->sinks, idx) {
-if (target == def)
-continue;
-
 if (target == skip)
 continue;
 
 if (!PA_SINK_IS_LINKED(pa_sink_get_state(target)))
 continue;
 
-if (pa_sink_input_may_move_to(i, target))
-return target;
+if (!pa_sink_input_may_move_to(i, target))
+continue;
+
+   build_group_ports(all_ports, target->ports);
 }
 
-pa_log_debug("No evacuation sink found.");
-return NULL;
+best_port = pa_device_port_find_best(all_ports);
+if(!best_port)
+   pa_log_debug("No evacuation sink found.");
+
+pa_hashmap_free(all_ports);
+
+target = find_sink_from_port(c, best_port);
+return target;
 }
 
 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
@@ -141,21 +184,17 @@ static pa_hook_result_t 
sink_input_move_fail_hook_callback(pa_core *c, pa_sink_i
 }
 
 static pa_source* find_evacuation_source(pa_core *c, pa_source_output *o, 
pa_source *skip) {
-pa_source *target, *def;
+pa_source *target;
 uint32_t idx;
+pa_hashmap *all_ports;
+pa_device_port *best_port;
 
 pa_assert(c);
 pa_assert(o);
 
-def = pa_namereg_get_default_source(c);
-
-if (def && def != skip && pa_source_output_may_move_to(o, def))
-return def;
+all_ports = pa_hashmap_new(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func);
 
 PA_IDXSET_FOREACH(target, c->sources, idx) {
-if (target == def)
-continue;
-
 if (target == skip)
 continue;
 
@@ -165,12 +204,20 @@ static pa_source* find_evacuation_source(pa_core *c, 
pa_source_output *o, pa_sou
 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(target)))
 continue;
 
-if (pa_source_output_may_move_to(o, target))
-return target;
+if (!pa_source_output_may_move_to(o, target))
+continue;
+
+   build_group_ports(all_ports, target->ports);
 }
 
-pa_log_debug("No evacuation source found.");
-return NULL;
+best_port = pa_device_port_find_best(all_ports);
+if(!best_port)
+pa_log_debug("No evacuation source found.");
+
+pa_hashmap_free(all_ports);
+
+target = find_source_from_port(c, best_port);
+return target;
 }
 
 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source 
*source, void* userdata) {
-- 
1.8.1.2

___
pulseaudio-di

[pulseaudio-discuss] [V3 PATCH] rescue-streams: try to find best one using availability and priority

2014-06-05 Thread Hui Wang
Recently met a problem: when I disconnect the bluetooth headset, the
pulseaudio automatically switch the sound to sink of HDMI output
instead of the sink of internal speaker even though there is no HDMI
cable connected.

To fix this problem, I want to change the rule of selecting the target
sink if the default sink is not available. (same rules apply to the
source selecting):
construct a new hashmap with all ports (of all relevant sinks) and
then call find_best on the new hashmap to find the best port, finally
find the corresponding sink using the best port.

Signed-off-by: Hui Wang 
---
diff Vs V2:
1) The default sink is not the root cause for this problem, so
i don't remove it in this version.

2) Use pa_idxset_trivial_* funcs to replace pa_idxset_string_* funcs
and use port pointers as key rather than the name

3) fix the wrong indentation

4) add a fallback sink in case the sink has no ports.

 src/modules/module-rescue-streams.c | 99 +
 1 file changed, 89 insertions(+), 10 deletions(-)

diff --git a/src/modules/module-rescue-streams.c 
b/src/modules/module-rescue-streams.c
index 7035a35..265711c 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -52,9 +52,56 @@ struct userdata {
 *source_output_move_fail_slot;
 };
 
+static pa_source* find_source_from_port(pa_core *c, pa_device_port *port) {
+pa_source *target;
+uint32_t idx;
+void *state;
+pa_device_port *p;
+
+if (!port)
+return NULL;
+
+PA_IDXSET_FOREACH(target, c->sources, idx)
+PA_HASHMAP_FOREACH(p, target->ports, state)
+if (port == p)
+return target;
+
+return NULL;
+}
+
+static pa_sink* find_sink_from_port(pa_core *c, pa_device_port *port) {
+pa_sink *target;
+uint32_t idx;
+void *state;
+pa_device_port *p;
+
+if (!port)
+return NULL;
+
+PA_IDXSET_FOREACH(target, c->sinks, idx)
+PA_HASHMAP_FOREACH(p, target->ports, state)
+if (port == p)
+return target;
+
+return NULL;
+}
+
+static void build_group_ports(pa_hashmap *g_ports, pa_hashmap *s_ports) {
+void *state;
+pa_device_port *p;
+
+if (!g_ports || !s_ports)
+return;
+
+PA_HASHMAP_FOREACH(p, s_ports, state)
+pa_hashmap_put(g_ports, p, p);
+}
+
 static pa_sink* find_evacuation_sink(pa_core *c, pa_sink_input *i, pa_sink 
*skip) {
-pa_sink *target, *def;
+pa_sink *target, *def, *fb_sink = NULL;
 uint32_t idx;
+pa_hashmap *all_ports;
+pa_device_port *best_port;
 
 pa_assert(c);
 pa_assert(i);
@@ -64,6 +111,8 @@ static pa_sink* find_evacuation_sink(pa_core *c, 
pa_sink_input *i, pa_sink *skip
 if (def && def != skip && pa_sink_input_may_move_to(i, def))
 return def;
 
+all_ports = pa_hashmap_new(pa_idxset_trivial_hash_func, 
pa_idxset_trivial_compare_func);
+
 PA_IDXSET_FOREACH(target, c->sinks, idx) {
 if (target == def)
 continue;
@@ -74,12 +123,25 @@ static pa_sink* find_evacuation_sink(pa_core *c, 
pa_sink_input *i, pa_sink *skip
 if (!PA_SINK_IS_LINKED(pa_sink_get_state(target)))
 continue;
 
-if (pa_sink_input_may_move_to(i, target))
-return target;
+if (!pa_sink_input_may_move_to(i, target))
+continue;
+
+fb_sink = target;
+
+build_group_ports(all_ports, target->ports);
 }
 
-pa_log_debug("No evacuation sink found.");
-return NULL;
+best_port = pa_device_port_find_best(all_ports);
+
+pa_hashmap_free(all_ports);
+
+if(!best_port) {
+   pa_log_debug("No evacuation sink found.");
+target = fb_sink;
+} else
+   target = find_sink_from_port(c, best_port);
+
+return target;
 }
 
 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
@@ -141,8 +203,10 @@ static pa_hook_result_t 
sink_input_move_fail_hook_callback(pa_core *c, pa_sink_i
 }
 
 static pa_source* find_evacuation_source(pa_core *c, pa_source_output *o, 
pa_source *skip) {
-pa_source *target, *def;
+pa_source *target, *def, *fb_source = NULL;
 uint32_t idx;
+pa_hashmap *all_ports;
+pa_device_port *best_port;
 
 pa_assert(c);
 pa_assert(o);
@@ -152,6 +216,8 @@ static pa_source* find_evacuation_source(pa_core *c, 
pa_source_output *o, pa_sou
 if (def && def != skip && pa_source_output_may_move_to(o, def))
 return def;
 
+all_ports = pa_hashmap_new(pa_idxset_trivial_hash_func, 
pa_idxset_trivial_compare_func);
+
 PA_IDXSET_FOREACH(target, c->sources, idx) {
 if (target == def)
 continue;
@@ -165,12 +231,25 @@ static pa_source* find_evacuation_source(pa_core *c, 
pa_source_output *o, pa_sou
 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(target)))
 continue;
 
-if (pa

[pulseaudio-discuss] [PATCH] module-switch-on-connect: add an argument for conditionally connecting

2014-09-15 Thread Hui Wang
On a machine without fixed connecting audio devices like internal
microphone or internal speaker, and when there is no external audio
devices plugging in, the default source/sink is alsa_input/alsa_output
and there is no input devices/output devices listed in the gnome
sound-setting.

Under this situation, if we connect a bluetooth headset, the gnome
sound-setting will list bluez input/output devices, but they are not
active devices by default. This looks very weird that sound-setting
lists only one input device and one output device, but they are not
active. To change this situation, we add an argument, the policy is
if a new source/sink is connected and current default source/sink's
active_port is AVAILABLE_NO, we let the new added one switch to
default one.

BugLink: http://bugs.launchpad.net/bugs/1369476
Signed-off-by: Hui Wang 
---
 src/modules/module-switch-on-connect.c | 21 -
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/modules/module-switch-on-connect.c 
b/src/modules/module-switch-on-connect.c
index d9275d3..658f0141 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -38,11 +38,15 @@
 #include "module-switch-on-connect-symdef.h"
 
 PA_MODULE_AUTHOR("Michael Terry");
-PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it");
+PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it or 
conditionally switch to it");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(true);
+PA_MODULE_USAGE(
+"switch_on_unavailable= "
+);
 
 static const char* const valid_modargs[] = {
+"switch_on_unavailable",
 NULL,
 };
 
@@ -50,6 +54,7 @@ struct userdata {
 pa_hook_slot
 *sink_put_slot,
 *source_put_slot;
+bool switch_on_unavailable;
 };
 
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
@@ -57,9 +62,11 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 uint32_t idx;
 pa_sink *def;
 const char *s;
+struct userdata *u = userdata;
 
 pa_assert(c);
 pa_assert(sink);
+pa_assert(userdata);
 
 /* Don't want to run during startup or shutdown */
 if (c->state != PA_CORE_RUNNING)
@@ -77,6 +84,10 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 if (def == sink)
 return PA_HOOK_OK;
 
+if (u->switch_on_unavailable)
+if (def->active_port && def->active_port->available != PA_AVAILABLE_NO)
+return PA_HOOK_OK;
+
 /* Actually do the switch to the new sink */
 pa_namereg_set_default_sink(c, sink);
 
@@ -106,9 +117,11 @@ static pa_hook_result_t source_put_hook_callback(pa_core 
*c, pa_source *source,
 uint32_t idx;
 pa_source *def;
 const char *s;
+struct userdata *u = userdata;
 
 pa_assert(c);
 pa_assert(source);
+pa_assert(userdata);
 
 /* Don't want to run during startup or shutdown */
 if (c->state != PA_CORE_RUNNING)
@@ -130,6 +143,10 @@ static pa_hook_result_t source_put_hook_callback(pa_core 
*c, pa_source *source,
 if (def == source)
 return PA_HOOK_OK;
 
+if (u->switch_on_unavailable)
+if (def->active_port && def->active_port->available != PA_AVAILABLE_NO)
+return PA_HOOK_OK;
+
 /* Actually do the switch to the new source */
 pa_namereg_set_default_source(c, source);
 
@@ -171,6 +188,8 @@ int pa__init(pa_module*m) {
 u->sink_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], 
PA_HOOK_LATE+30, (pa_hook_cb_t) sink_put_hook_callback, u);
 u->source_put_slot = 
pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+20, 
(pa_hook_cb_t) source_put_hook_callback, u);
 
+pa_modargs_get_value_boolean(ma, "switch_on_unavailable", 
&u->switch_on_unavailable);
+
 pa_modargs_free(ma);
 return 0;
 }
-- 
1.9.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [V2 PATCH] module-switch-on-connect: add an argument for conditionally connecting

2014-09-17 Thread Hui Wang
On a machine without fixed connecting audio devices like internal
microphone or internal speaker, and when there is no external audio
devices plugging in, the default source/sink is alsa_input/alsa_output
and there is no input devices/output devices listed in the gnome
sound-setting.

Under this situation, if we connect a bluetooth headset, the gnome
sound-setting will list bluez input/output devices, but they are not
active devices by default. This looks very weird that sound-setting
lists only one input device and one output device, but they are not
active. To change this situation, we add an argument, the policy is
if a new source/sink is connected and current default source/sink's
active_port is AVAILABLE_NO, we let the new added one switch to
default one.

BugLink: http://bugs.launchpad.net/bugs/1369476
Signed-off-by: Hui Wang 
---
Diff vs v1:
  1. change the argument name to only_from_unavailable
  2. fix the logic to if no active_port, it will not switch
  3. add return value check for pa_modargs_get_value_boolean()

 src/modules/module-switch-on-connect.c | 22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/modules/module-switch-on-connect.c 
b/src/modules/module-switch-on-connect.c
index d9275d3..3f1b0a4 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -38,11 +38,15 @@
 #include "module-switch-on-connect-symdef.h"
 
 PA_MODULE_AUTHOR("Michael Terry");
-PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it");
+PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it or 
conditionally switch to it");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(true);
+PA_MODULE_USAGE(
+"only_from_unavailable= "
+);
 
 static const char* const valid_modargs[] = {
+"only_from_unavailable",
 NULL,
 };
 
@@ -50,6 +54,7 @@ struct userdata {
 pa_hook_slot
 *sink_put_slot,
 *source_put_slot;
+bool only_from_unavailable;
 };
 
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
@@ -57,9 +62,11 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 uint32_t idx;
 pa_sink *def;
 const char *s;
+struct userdata *u = userdata;
 
 pa_assert(c);
 pa_assert(sink);
+pa_assert(userdata);
 
 /* Don't want to run during startup or shutdown */
 if (c->state != PA_CORE_RUNNING)
@@ -77,6 +84,10 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 if (def == sink)
 return PA_HOOK_OK;
 
+if (u->only_from_unavailable)
+if (!def->active_port || def->active_port->available != 
PA_AVAILABLE_NO)
+return PA_HOOK_OK;
+
 /* Actually do the switch to the new sink */
 pa_namereg_set_default_sink(c, sink);
 
@@ -106,9 +117,11 @@ static pa_hook_result_t source_put_hook_callback(pa_core 
*c, pa_source *source,
 uint32_t idx;
 pa_source *def;
 const char *s;
+struct userdata *u = userdata;
 
 pa_assert(c);
 pa_assert(source);
+pa_assert(userdata);
 
 /* Don't want to run during startup or shutdown */
 if (c->state != PA_CORE_RUNNING)
@@ -130,6 +143,10 @@ static pa_hook_result_t source_put_hook_callback(pa_core 
*c, pa_source *source,
 if (def == source)
 return PA_HOOK_OK;
 
+if (u->only_from_unavailable)
+if (!def->active_port || def->active_port->available != 
PA_AVAILABLE_NO)
+return PA_HOOK_OK;
+
 /* Actually do the switch to the new source */
 pa_namereg_set_default_source(c, source);
 
@@ -171,6 +188,9 @@ int pa__init(pa_module*m) {
 u->sink_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], 
PA_HOOK_LATE+30, (pa_hook_cb_t) sink_put_hook_callback, u);
 u->source_put_slot = 
pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+20, 
(pa_hook_cb_t) source_put_hook_callback, u);
 
+if (pa_modargs_get_value_boolean(ma, "only_from_unavailable", 
&u->only_from_unavailable) < 0)
+   pa_log_warn("Fail to get a boolean value for only_from_unavailable, 
then regard only_from_unvailable=false");
+
 pa_modargs_free(ma);
 return 0;
 }
-- 
1.9.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [V3 PATCH] module-switch-on-connect: add an argument for conditionally connecting

2014-09-21 Thread Hui Wang
On a machine without fixed connecting audio devices like internal
microphone or internal speaker, and when there is no external audio
devices plugging in, the default source/sink is alsa_input/alsa_output
and there is no input devices/output devices listed in the gnome
sound-setting.

Under this situation, if we connect a bluetooth headset, the gnome
sound-setting will list bluez input/output devices, but they are not
active devices by default. This looks very weird that sound-setting
lists only one input device and one output device, but they are not
active. To change this situation, we add an argument, the policy is
if a new source/sink is connected and current default source/sink's
active_port is AVAILABLE_NO, we let the new added one switch to
default one.

BugLink: http://bugs.launchpad.net/bugs/1369476
Signed-off-by: Hui Wang 
---
In the V3:
if the get_value_boolean fails, release the resource and return -1

 src/modules/module-switch-on-connect.c | 32 +++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/src/modules/module-switch-on-connect.c 
b/src/modules/module-switch-on-connect.c
index d9275d3..66f3f9b 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -38,11 +38,15 @@
 #include "module-switch-on-connect-symdef.h"
 
 PA_MODULE_AUTHOR("Michael Terry");
-PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it");
+PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it or 
conditionally switch to it");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(true);
+PA_MODULE_USAGE(
+"only_from_unavailable= "
+);
 
 static const char* const valid_modargs[] = {
+"only_from_unavailable",
 NULL,
 };
 
@@ -50,6 +54,7 @@ struct userdata {
 pa_hook_slot
 *sink_put_slot,
 *source_put_slot;
+bool only_from_unavailable;
 };
 
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
@@ -57,9 +62,11 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 uint32_t idx;
 pa_sink *def;
 const char *s;
+struct userdata *u = userdata;
 
 pa_assert(c);
 pa_assert(sink);
+pa_assert(userdata);
 
 /* Don't want to run during startup or shutdown */
 if (c->state != PA_CORE_RUNNING)
@@ -77,6 +84,10 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 if (def == sink)
 return PA_HOOK_OK;
 
+if (u->only_from_unavailable)
+if (!def->active_port || def->active_port->available != 
PA_AVAILABLE_NO)
+return PA_HOOK_OK;
+
 /* Actually do the switch to the new sink */
 pa_namereg_set_default_sink(c, sink);
 
@@ -106,9 +117,11 @@ static pa_hook_result_t source_put_hook_callback(pa_core 
*c, pa_source *source,
 uint32_t idx;
 pa_source *def;
 const char *s;
+struct userdata *u = userdata;
 
 pa_assert(c);
 pa_assert(source);
+pa_assert(userdata);
 
 /* Don't want to run during startup or shutdown */
 if (c->state != PA_CORE_RUNNING)
@@ -130,6 +143,10 @@ static pa_hook_result_t source_put_hook_callback(pa_core 
*c, pa_source *source,
 if (def == source)
 return PA_HOOK_OK;
 
+if (u->only_from_unavailable)
+if (!def->active_port || def->active_port->available != 
PA_AVAILABLE_NO)
+return PA_HOOK_OK;
+
 /* Actually do the switch to the new source */
 pa_namereg_set_default_source(c, source);
 
@@ -171,8 +188,21 @@ int pa__init(pa_module*m) {
 u->sink_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], 
PA_HOOK_LATE+30, (pa_hook_cb_t) sink_put_hook_callback, u);
 u->source_put_slot = 
pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+20, 
(pa_hook_cb_t) source_put_hook_callback, u);
 
+if (pa_modargs_get_value_boolean(ma, "only_from_unavailable", 
&u->only_from_unavailable) < 0) {
+   pa_log ("Failed to get a boolean value for only_from_unavailable.");
+   goto fail;
+}
+
 pa_modargs_free(ma);
 return 0;
+
+fail:
+if (ma)
+pa_modargs_free(ma);
+
+pa__done(m);
+
+return -1;
 }
 
 void pa__done(pa_module*m) {
-- 
1.9.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [V4 PATCH] module-switch-on-connect: add an argument for conditionally connecting

2014-09-21 Thread Hui Wang
On a machine without fixed connecting audio devices like internal
microphone or internal speaker, and when there is no external audio
devices plugging in, the default source/sink is alsa_input/alsa_output
and there is no input devices/output devices listed in the gnome
sound-setting.

Under this situation, if we connect a bluetooth headset, the gnome
sound-setting will list bluez input/output devices, but they are not
active devices by default. This looks very weird that sound-setting
lists only one input device and one output device, but they are not
active. To change this situation, we add an argument, the policy is
if a new source/sink is connected and current default source/sink's
active_port is AVAILABLE_NO, we let the new added one switch to
default one.

BugLink: http://bugs.launchpad.net/bugs/1369476
Signed-off-by: Hui Wang 
---
In the V3:
if the get_value_boolean fails, release the resource and return -1

 src/modules/module-switch-on-connect.c | 32 +++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/src/modules/module-switch-on-connect.c 
b/src/modules/module-switch-on-connect.c
index d9275d3..90b86d1 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -38,11 +38,15 @@
 #include "module-switch-on-connect-symdef.h"
 
 PA_MODULE_AUTHOR("Michael Terry");
-PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it");
+PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it or 
conditionally switch to it");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(true);
+PA_MODULE_USAGE(
+"only_from_unavailable= "
+);
 
 static const char* const valid_modargs[] = {
+"only_from_unavailable",
 NULL,
 };
 
@@ -50,6 +54,7 @@ struct userdata {
 pa_hook_slot
 *sink_put_slot,
 *source_put_slot;
+bool only_from_unavailable;
 };
 
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
@@ -57,9 +62,11 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 uint32_t idx;
 pa_sink *def;
 const char *s;
+struct userdata *u = userdata;
 
 pa_assert(c);
 pa_assert(sink);
+pa_assert(userdata);
 
 /* Don't want to run during startup or shutdown */
 if (c->state != PA_CORE_RUNNING)
@@ -77,6 +84,10 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 if (def == sink)
 return PA_HOOK_OK;
 
+if (u->only_from_unavailable)
+if (!def->active_port || def->active_port->available != 
PA_AVAILABLE_NO)
+return PA_HOOK_OK;
+
 /* Actually do the switch to the new sink */
 pa_namereg_set_default_sink(c, sink);
 
@@ -106,9 +117,11 @@ static pa_hook_result_t source_put_hook_callback(pa_core 
*c, pa_source *source,
 uint32_t idx;
 pa_source *def;
 const char *s;
+struct userdata *u = userdata;
 
 pa_assert(c);
 pa_assert(source);
+pa_assert(userdata);
 
 /* Don't want to run during startup or shutdown */
 if (c->state != PA_CORE_RUNNING)
@@ -130,6 +143,10 @@ static pa_hook_result_t source_put_hook_callback(pa_core 
*c, pa_source *source,
 if (def == source)
 return PA_HOOK_OK;
 
+if (u->only_from_unavailable)
+if (!def->active_port || def->active_port->available != 
PA_AVAILABLE_NO)
+return PA_HOOK_OK;
+
 /* Actually do the switch to the new source */
 pa_namereg_set_default_source(c, source);
 
@@ -171,8 +188,21 @@ int pa__init(pa_module*m) {
 u->sink_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], 
PA_HOOK_LATE+30, (pa_hook_cb_t) sink_put_hook_callback, u);
 u->source_put_slot = 
pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+20, 
(pa_hook_cb_t) source_put_hook_callback, u);
 
+if (pa_modargs_get_value_boolean(ma, "only_from_unavailable", 
&u->only_from_unavailable) < 0) {
+   pa_log("Failed to get a boolean value for only_from_unavailable.");
+   goto fail;
+}
+
 pa_modargs_free(ma);
 return 0;
+
+fail:
+if (ma)
+pa_modargs_free(ma);
+
+pa__done(m);
+
+return -1;
 }
 
 void pa__done(pa_module*m) {
-- 
1.9.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [V4 PATCH] module-switch-on-connect: add an argument for conditionally connecting

2014-09-25 Thread Hui Wang

On 09/26/2014 12:13 AM, Raymond Yau wrote:



>>
>> >
>> > On a machine without fixed connecting audio devices like internal
>> > microphone or internal speaker, and when there is no external audio
>> > devices plugging in, the default source/sink is 
alsa_input/alsa_output

>> > and there is no input devices/output devices listed in the gnome
>> > sound-setting.

https://launchpadlibrarian.net/184055917/PulseList.txt

Seem line in is active port when all ports are not available
Pulseaudio won't switch away from line in but gnome won't show line in 
since it is not plugged


ports:
analog-input-microphone-front: Front Microphone (priority 8500, 
latency offset 0 usec, available: no)

properties:
device.icon_name = "audio-input-microphone"
analog-input-microphone-rear: Rear Microphone (priority 8200, latency 
offset 0 usec, available: no)

properties:
device.icon_name = "audio-input-microphone"
analog-input-linein: Line In (priority 8100, latency offset 0 usec, 
available: no)

properties:

active port: 

Yes, in this situation, the default-source->active_port->available=no, 
if you use this module and pass "only_from_unavailable=yes", when 
connect bluetooth headset, the default source will automatically switch 
to bluez-source.


In this situation, if you plug something in the line-in jack, the 
default-source->active_port-available=yes, and if you pass 
"only_from_unavailable=yes", the default source will not switch.


https://launchpadlibrarian.net/184417469/alsa2.txt



___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH] module-switch-on-port-available: make the output more accurate

2014-09-25 Thread Hui Wang
It is possible that the chosen active_port doesn't equal
new_data->active_port, using p->name is more accurate.

Please refer to sink_new_hook_callback()

Signed-off-by: Hui Wang 
---
 src/modules/module-switch-on-port-available.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/modules/module-switch-on-port-available.c 
b/src/modules/module-switch-on-port-available.c
index b0938d5..7397bcc 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -264,8 +264,7 @@ static pa_hook_result_t source_new_hook_callback(pa_core 
*c, pa_source_new_data
 pa_device_port *p = new_sink_source(new_data->ports, 
new_data->active_port);
 
 if (p) {
-pa_log_debug("Switching initial port for source '%s' to '%s'", 
new_data->name,
- new_data->active_port);
+pa_log_debug("Switching initial port for source '%s' to '%s'", 
new_data->name, p->name);
 pa_source_new_data_set_port(new_data, p->name);
 }
 return PA_HOOK_OK;
-- 
1.9.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [V4 PATCH] module-switch-on-connect: add an argument for conditionally connecting

2014-09-28 Thread Hui Wang

On 09/28/2014 05:50 PM, Tanu Kaskinen wrote:

On Sun, 2014-09-28 at 12:41 +0300, Tanu Kaskinen wrote:

On Mon, 2014-09-22 at 11:50 +0800, Hui Wang wrote:

On a machine without fixed connecting audio devices like internal
microphone or internal speaker, and when there is no external audio
devices plugging in, the default source/sink is alsa_input/alsa_output
and there is no input devices/output devices listed in the gnome
sound-setting.

How can the default source/sink be alsa_input/alsa_output if there are
no alsa devices?

Answering myself: probably you meant that there are alsa devices, but
they are currently all unavailable.


Yes, and below is an example:

  * index: 2
name: 
driver: 
flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY 
DYNAMIC_LATENCY

state: SUSPENDED
suspend cause: IDLE
priority: 9959
volume: 0:  21% 1:  21%
0: -40.50 dB 1: -40.50 dB
balance 0.00
base volume:  13%
 -52.50 dB
volume steps: 65537
muted: no
current latency: 0.00 ms
max rewind: 0 KiB
sample spec: s16le 2ch 44100Hz
channel map: front-left,front-right
 Stereo
used by: 0
linked by: 0
configured latency: 0.00 ms; range is 0.50 .. 371.52 ms
card: 1 
module: 6
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "92HD89E2 Analog"
alsa.id = "92HD89E2 Analog"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "1"
alsa.card_name = "HD-Audio Generic"
alsa.long_card_name = "HD-Audio Generic at 0xfeb4 irq 16"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-:00:14.2"
sysfs.path = "/devices/pci:00/:00:14.2/sound/card1"
device.bus = "pci"
device.vendor.id = "1022"
device.vendor.name = "Advanced Micro Devices, Inc. [AMD]"
device.product.id = "780d"
device.product.name = "FCH Azalia Controller"
device.form_factor = "internal"
device.string = "front:1"
device.buffering.buffer_size = "65536"
device.buffering.fragment_size = "32768"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "Analog Stereo"
device.description = "Built-in Audio Analog Stereo"
alsa.mixer_name = "IDT 92HD89E2"
alsa.components = "HDA:111d76c7,103c2b17,00100102"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
ports:
analog-input-microphone-front: Front Microphone (priority 8500, 
latency offset 0 usec, available: no)

properties:
device.icon_name = "audio-input-microphone"
analog-input-microphone-rear: Rear Microphone (priority 8200, 
latency offset 0 usec, available: no)

properties:
device.icon_name = "audio-input-microphone"
analog-input-linein: Line In (priority 8100, latency offset 0 
usec, available: no)

properties:

active port: 






Under this situation, if we connect a bluetooth headset, the gnome
sound-setting will list bluez input/output devices, but they are not
active devices by default. This looks very weird that sound-setting
lists only one input device and one output device, but they are not
active. To change this situation, we add an argument, the policy is
if a new source/sink is connected and current default source/sink's
active_port is AVAILABLE_NO, we let the new added one switch to
default one.

Surely it doesn't make any sense to have the default sink/source point
to non-existing devices if there are other devices available. To me this
seems like something to fix in the core than working around in modules.

I happen to have some code that improves the core default device
tracking. I can submit a patch next week. It might fix your issue too.

My code doesn't take the port availability into account (perhaps it
should, I'm not sure), so probably it won't fix your problem.



___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] ThinkPad T-510 audio output mute LED non-workingness

2015-03-30 Thread Hui Wang

On 03/31/2015 05:54 AM, Glenn Golden wrote:

HW: ThinkPad T-510, x86_64
SW: Arch Linux (synched within a week) kernel = 3.19.2, PA 6.0

On the above setup, the mic mute function (invoked via pavucontrol) works as
expected: Click the mute icon, it mutes the mic input, indicates the muted
state by greying out the pavucontrol mic gain control, and illuminates the
little LED on the mic mute button.

But the analogous functionality for muting audio output only does the
first two things, and has no effect on the mute LED. (The LED is always off.)

 From googling around, I'm pretty sure that these two particular LEDs are not
directly under user control (e.g. via ACPI) but are somehow bound to the
mute/unmute functionality in the snd-hda-intel driver. This understanding is
based on kernel posts like this:

 https://bugzilla.kernel.org/show_bug.cgi?id=49391

and other similar ones.

Before filing a ticket with the kernel guys, wanted to ask if this
function-LED binding is in any way under control of pulseaudio itself?
In other words, I guess what I'm asking is whether pulseaudio just tells
the driver to "mute the audio", and the driver sets the LED state accordingly,
or whether pulse tells the driver separately to "mute the audio" and also
"turn on the LED".
According to my understanding, it should be the former one,  PA tells 
the driver to "mute the audio", and the driver sets the LED accordingly.

Knowing the answer to this, I can post a more informative ticket to the
kernel guys. (Or maybe the fix is even in pulseaudio itself?)
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH] tests: add tolerant variation for comparing the rewind result

2015-05-24 Thread Hui Wang
On 32bits OS, this test case fails. The reason is when rewinding to
the middle of a block, some of float parameters in the saved_state
are stored in the memory from FPU registers, and those parameters will
be used for next time to process data with lfe. Here if FPU register
is over 32bits, the storing from FPU register to memory will introduce
some variation, and this small variation will introduce small
variation to the rewinding result.

So adding the tolerant variation for comparing the rewind result, make
this test case can work on both 64bits OS and 32bits OS.

Signed-off-by: Hui Wang 
---
I wrote a simple testcase to show the variation exists on 32bits OS.
When compile this test case on 64bits OS, it will not fail when running
it; while on 32bits OS if you just compile it without "-O2", this
testcase still pass without any variation, but if you add "-O2" when
compiling it, you will see variation when you running it.
http://pastebin.ubuntu.com/11342537/

 src/tests/lfe-filter-test.c | 24 ++--
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/src/tests/lfe-filter-test.c b/src/tests/lfe-filter-test.c
index 2c6d597..50636a9 100644
--- a/src/tests/lfe-filter-test.c
+++ b/src/tests/lfe-filter-test.c
@@ -37,6 +37,7 @@ static uint8_t *ori_sample_ptr;
 
 #define ONE_BLOCK_SAMPLES 4096
 #define TOTAL_SAMPLES 8192
+#define TOLERANT_VARIATION 1
 
 static void save_data_block(struct lfe_filter_test *lft, void *d, pa_memblock 
*blk) {
 uint8_t *dst = d, *src;
@@ -63,15 +64,26 @@ static pa_memblock* generate_data_block(struct 
lfe_filter_test *lft, int start)
 static int compare_data_block(struct lfe_filter_test *lft, void *a, void *b) {
 int ret = 0;
 uint32_t i;
-uint32_t fz = pa_frame_size(lft->ss);
-uint8_t *r = a, *u = b;
 
-for (i = 0; i < ONE_BLOCK_SAMPLES * fz; i++) {
-if (*r++ != *u++) {
-pa_log_error("lfe-filter-test: test failed, the output data in the 
position 0x%x of a block does not equal!\n", i);
-ret = -1;
+switch (lft->ss->format) {
+case PA_SAMPLE_S16NE:
+case PA_SAMPLE_S16RE: {
+uint16_t *r = a, *u = b;
+for (i = 0; i < ONE_BLOCK_SAMPLES; i++) {
+uint16_t va = *r++, vb = *u++;
+uint16_t var = (va >= vb) ? (va - vb) : (vb - va);
+if (var > TOLERANT_VARIATION) {
+pa_log_error("lfe-filter-test: test failed, the output 
data in the position 0x%x of a block does not equal!\n", i);
+ret = -1;
+break;
+}
+}
 break;
 }
+default:
+pa_log_error("lfe-filter-test: not a suppported sample format yet 
in this testcase!\n");
+ret = -1;
+break;
 }
 return ret;
 }
-- 
1.9.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH] tests: Remove a redundant mempool_new from resampler-test

2015-05-24 Thread Hui Wang
Signed-off-by: Hui Wang 
---
 src/tests/resampler-test.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c
index 751d2dc..9832a31 100644
--- a/src/tests/resampler-test.c
+++ b/src/tests/resampler-test.c
@@ -330,8 +330,6 @@ int main(int argc, char *argv[]) {
 if (!getenv("MAKE_CHECK"))
 pa_log_set_level(PA_LOG_INFO);
 
-pa_assert_se(pool = pa_mempool_new(false, 0));
-
 a.channels = b.channels = 1;
 a.rate = b.rate = 44100;
 a.format = b.format = PA_SAMPLE_S16LE;
-- 
1.9.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [V2 PATCH] tests: add tolerant variation for comparing the rewind result

2015-05-25 Thread Hui Wang
On 32bits OS, this test case fails. The reason is when rewinding to
the middle of a block, some of float parameters in the saved_state
are stored in the memory from FPU registers, and those parameters will
be used for next time to process data with lfe. Here if FPU register
is over 32bits, the storing from FPU register to memory will introduce
some variation, and this small variation will introduce small
variation to the rewinding result.

So adding the tolerant variation for comparing the rewind result, make
this test case can work on both 64bits OS and 32bits OS.

Signed-off-by: Hui Wang 
---
 src/tests/lfe-filter-test.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/tests/lfe-filter-test.c b/src/tests/lfe-filter-test.c
index 2c6d597..81682cb 100644
--- a/src/tests/lfe-filter-test.c
+++ b/src/tests/lfe-filter-test.c
@@ -37,6 +37,7 @@ static uint8_t *ori_sample_ptr;
 
 #define ONE_BLOCK_SAMPLES 4096
 #define TOTAL_SAMPLES 8192
+#define TOLERANT_VARIATION 1
 
 static void save_data_block(struct lfe_filter_test *lft, void *d, pa_memblock 
*blk) {
 uint8_t *dst = d, *src;
@@ -63,11 +64,12 @@ static pa_memblock* generate_data_block(struct 
lfe_filter_test *lft, int start)
 static int compare_data_block(struct lfe_filter_test *lft, void *a, void *b) {
 int ret = 0;
 uint32_t i;
-uint32_t fz = pa_frame_size(lft->ss);
-uint8_t *r = a, *u = b;
+uint16_t *r = a, *u = b;
+
+pa_assert_se(lft->ss->format == PA_SAMPLE_S16NE);
 
-for (i = 0; i < ONE_BLOCK_SAMPLES * fz; i++) {
-if (*r++ != *u++) {
+for (i = 0; i < ONE_BLOCK_SAMPLES; i++) {
+if (abs(*r++ - *u++) > TOLERANT_VARIATION) {
 pa_log_error("lfe-filter-test: test failed, the output data in the 
position 0x%x of a block does not equal!\n", i);
 ret = -1;
 break;
-- 
1.9.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH] build-sys: add the Dell dock TB16 configuration

2017-11-12 Thread Hui Wang
Signed-off-by: Hui Wang 
---
Forgot to add this to build sys with the commit 60c0edd5.

 src/Makefile.am | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index e610db7..0348250 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1312,7 +1312,8 @@ dist_alsaprofilesets_DATA = \

modules/alsa/mixer/profile-sets/native-instruments-korecontroller.conf \
modules/alsa/mixer/profile-sets/kinect-audio.conf \
modules/alsa/mixer/profile-sets/sb-omni-surround-5.1.conf \
-   
modules/alsa/mixer/profile-sets/steelseries-arctis-usb-audio.conf
+   
modules/alsa/mixer/profile-sets/steelseries-arctis-usb-audio.conf \
+   modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf
 
 if HAVE_UDEV
 dist_udevrules_DATA = \
-- 
2.7.4

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


[pulseaudio-discuss] Audio APP (sink-input) bind to the sink with only unplugged hdmi-audio ports on it

2018-09-30 Thread Hui Wang
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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


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

2018-09-30 Thread Hui Wang
 
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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss



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


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

2018-09-30 Thread Hui Wang

On 2018年09月30日 18:30, Tanu Kaskinen wrote:

On Sun, 2018-09-30 at 15:03 +0800, 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?

The plan has been to do the following (but I haven't found the time to
implement it):

Streams currently have a "save_sink" flag that tells whether the
current sink should be remembered and restored by module-stream-
restore. That flag should be replaced with a "preferred_sink" string
that is set when the user moves the stream. module-stream-restore
should remember and restore that string.

When the user moves a stream to the current default sink, the
"preferred_sink" string should be set to NULL and module-stream-restore
should clear the routing for that stream in the stream database. From
that point on the stream will be always routed to the default sink.

When a stream is created, module-stream-restore should set the
"preferred_sink" string and if that sink exists, the core should set
that sink as the initial routing for the new stream.

When the default sink changes, the streams from the old default sink
should be moved to the new default sink, unless the "preferred_sink"
string is set to the old default sink and the active port of the old
default sink is not unavailable. This should be done by the core.

When the active port of a sink becomes unavailable, all streams from
that sink should be moved to the default sink. This should be done by
the core.

When a new sink appears or 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. This should be
done by the core.

As a result, module-stream-restore doesn't need to move streams any
more, it only needs to manage the "preferred_sink" variables. Some
other modules can perhaps be simplified as well.

The same logic should of course be implemented for capture streams as
well.

Would you be willing to implement this?

Got it, I will take some time to understand your plan first, then have a 
try to implement it.


Thanks,

Hui.


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


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

2018-10-02 Thread Hui Wang

On 2018年10月02日 18:50, Georg Chini wrote:

On 02.10.2018 11:49, Tanu Kaskinen wrote:

On Mon, 2018-10-01 at 10:18 +0800, Hui Wang wrote:

On 2018年09月30日 18:30, Tanu Kaskinen wrote:

On Sun, 2018-09-30 at 15:03 +0800, 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?

The plan has been to do the following (but I haven't found the time to
implement it):

Streams currently have a "save_sink" flag that tells whether the
current sink should be remembered and restored by module-stream-
restore. That flag should be replaced with a "preferred_sink" string
that is set when the user moves the stream. module-stream-restore
should remember and restore that string.

When the user moves a stream to the current default sink, the
"preferred_sink" string should be set to NULL and 
module-stream-restore

should clear the routing for that stream in the stream database. From
that point on the stream will be always routed to the default sink.

When a stream is created, module-stream-restore should set the
"preferred_sink" string and if that sink exists, the core should set
that sink as the initial routing for the new stream.

When the default sink changes, the streams from the old default sink
should be moved to the new default sink, unless the "preferred_sink"
string is set to the old default sink and the active port of the old
default sink is not unavailable. This should be done by the core.

When the active port of a sink becomes unavailable, all streams from
that sink should be moved to the default sink. This should be done by
the core.

When a new sink appears or 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. This should be
done by the core.

As a result, module-stream-restore doesn't need to move streams any
more, it only needs to manage the "preferred_sink" variables. Some
other modules can perhaps be simplified as well.

The same logic should of course be implemented for capture streams as
well.

Would you be willing to implement this?

Got it, I will take some time to un

[pulseaudio-discuss] [PATCH 0/4] The tentative fix of the issue #185

2018-11-04 Thread Hui Wang
This is a tentative fix of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/185

The patch is implemented based on Tanu's design:
https://lists.freedesktop.org/archives/pulseaudio-discuss/2018-October/030531.html

So far, the patches only cover the sink and sink_input, don't touch
the source and source_output yet. Based on these patches, I tested the switch
between HDMI output and speaker, it worked as expected. If the way of changing
sink/sink_input is basically correct and is worth to apply to the
source/source_output, I will continue to write patches for them too.


Hui Wang (4):
  change bool save_sink to char *preferred_sink
  move stream after default sink is changed.
  move streams to new appeared sinks if they prefer these sinks
  move stream when the active_port changes

 src/modules/dbus/iface-core.c   |  2 +-
 src/modules/module-default-device-restore.c |  2 +-
 src/modules/module-device-manager.c |  2 +-
 src/modules/module-intended-roles.c |  2 +-
 src/modules/module-stream-restore.c | 47 
 src/modules/module-switch-on-connect.c  | 28 +--
 src/pulsecore/cli-command.c |  2 +-
 src/pulsecore/core.c|  9 ++-
 src/pulsecore/core.h|  4 +-
 src/pulsecore/device-port.c | 18 -
 src/pulsecore/protocol-native.c |  2 +-
 src/pulsecore/sink-input.c  | 25 +--
 src/pulsecore/sink-input.h  |  7 +-
 src/pulsecore/sink.c| 83 -
 src/pulsecore/sink.h|  3 +
 15 files changed, 172 insertions(+), 64 deletions(-)

-- 
2.17.1

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


[pulseaudio-discuss] [PATCH 3/4] move streams to new appeared sinks if they prefer these sinks

2018-11-04 Thread Hui Wang
When a new sink appears, all streams that have their "preferred_sink"
set to the new sink should be moved to the new sink.

Signed-off-by: Hui Wang 
---
 src/pulsecore/sink.c | 31 +++
 src/pulsecore/sink.h |  1 +
 2 files changed, 32 insertions(+)

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 63a3456e7..a2a390beb 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -722,6 +722,8 @@ void pa_sink_put(pa_sink* s) {
 /* This function must be called after the PA_CORE_HOOK_SINK_PUT hook,
  * because module-switch-on-connect needs to know the old default sink */
 pa_core_update_default_sink(s->core, false);
+
+pa_sink_bind_preferred_stream_to_a_sink(s);
 }
 
 /* Called from main context */
@@ -3919,3 +3921,32 @@ void 
pa_sink_move_streams_from_oldsink_to_newsink(pa_sink *old_sink, pa_sink *ne
 
 return;
 }
+
+void pa_sink_bind_preferred_stream_to_a_sink(pa_sink *s) {
+pa_sink_input *si;
+uint32_t idx;
+pa_core *c;
+
+if (!s)
+   return;
+
+c = s->core;
+PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
+if (si->sink == s)
+continue;
+
+/* Skip this sink input if it is connecting a filter sink to
+ * the master */
+if (si->origin_sink)
+continue;
+
+/* 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 */
+   if (!PA_SINK_INPUT_IS_LINKED(si->state))
+continue;
+
+if (si->preferred_sink != NULL && pa_streq(si->preferred_sink, 
s->name))
+   pa_sink_input_move_to(si, s, false);
+}
+}
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index f207a094c..24e4678b1 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -562,4 +562,5 @@ void pa_sink_set_reference_volume_direct(pa_sink *s, const 
pa_cvolume *volume);
 pa_assert(pa_thread_mq_get() || !PA_SINK_IS_LINKED((s)->state))
 
 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);
 #endif
-- 
2.17.1

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


[pulseaudio-discuss] [PATCH 1/4] change bool save_sink to char *preferred_sink

2018-11-04 Thread Hui Wang
And don't move the stream in the module-stream-restore anymore,
And the preferred_sink is only set when user is calling the
move_to() and the module-stream-restore maintains the saving and
deleting of preferred_sink.

If the target of move_to() is default_sink, preferred_sink will be
cleared and the entry->device will be cleared too from database.

Signed-off-by: Hui Wang 
---
 src/modules/module-device-manager.c|  2 +-
 src/modules/module-intended-roles.c|  2 +-
 src/modules/module-stream-restore.c| 47 +-
 src/modules/module-switch-on-connect.c |  2 +-
 src/pulsecore/sink-input.c | 25 +++---
 src/pulsecore/sink-input.h |  7 ++--
 6 files changed, 59 insertions(+), 26 deletions(-)

diff --git a/src/modules/module-device-manager.c 
b/src/modules/module-device-manager.c
index 15fd2..36e71584e 100644
--- a/src/modules/module-device-manager.c
+++ b/src/modules/module-device-manager.c
@@ -657,7 +657,7 @@ static void route_sink_input(struct userdata *u, 
pa_sink_input *si) {
 pa_assert(u->do_routing);
 
 /* Don't override user or application routing requests. */
-if (si->save_sink || si->sink_requested_by_application)
+if (si->preferred_sink != NULL || si->sink_requested_by_application)
 return;
 
 /* Skip this if it is already in the process of being moved anyway */
diff --git a/src/modules/module-intended-roles.c 
b/src/modules/module-intended-roles.c
index adee51c20..98e4c241f 100644
--- a/src/modules/module-intended-roles.c
+++ b/src/modules/module-intended-roles.c
@@ -175,7 +175,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, struct
 if (si->sink == sink)
 continue;
 
-if (si->save_sink)
+if (si->preferred_sink != NULL)
 continue;
 
 /* Skip this if it is already in the process of being moved
diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index 228e9e447..276957c25 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1311,19 +1311,29 @@ static void subscribe_callback(pa_core *c, 
pa_subscription_event_type_t t, uint3
 mute_updated = !created_new_entry && (!old->muted_valid || 
entry->muted != old->muted);
 }
 
-if (sink_input->save_sink) {
+if (sink_input->preferred_sink != NULL || !created_new_entry) {
 pa_xfree(entry->device);
-entry->device = pa_xstrdup(sink_input->sink->name);
-entry->device_valid = true;
 
-device_updated = !created_new_entry && (!old->device_valid || 
!pa_streq(entry->device, old->device));
-if (sink_input->sink->card) {
+   if (sink_input->preferred_sink != NULL) {
+   entry->device = pa_xstrdup(sink_input->preferred_sink);
+   entry->device_valid = true;
+   } else {
+   entry->device = NULL;
+   entry->device_valid = false;
+   }
+
+device_updated = !created_new_entry && (!old->device_valid || 
!entry->device_valid || !pa_streq(entry->device, old->device));
+
+   if (entry->device_valid == false) {
+pa_xfree(entry->card);
+entry->card = NULL;
+entry->card_valid = false;
+   } else if (sink_input->sink->card) {
 pa_xfree(entry->card);
 entry->card = pa_xstrdup(sink_input->sink->card->name);
 entry->card_valid = true;
 }
 }
-
 } else {
 pa_source_output *source_output;
 
@@ -1641,7 +1651,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core 
*c, pa_sink *sink, struct
 if (si->sink == sink)
 continue;
 
-if (si->save_sink)
+if (si->preferred_sink != NULL)
 continue;
 
 /* Skip this if it is already in the process of being moved
@@ -1665,7 +1675,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core 
*c, pa_sink *sink, struct
 
 if ((e = entry_read(u, name))) {
 if (e->device_valid && pa_streq(e->device, sink->name))
-pa_sink_input_move_to(si, sink, true);
+   si->preferred_sink = pa_xstrdup(sink->name);
 
 entry_free(e);
 }
@@ -1764,8 +1774,10 @@ static pa_hook_result_t 
sink_unlink_hook_callback(pa_core *c, pa_sink *sink, str
 
 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) &&
 d != sink &&
-PA_SINK_IS_LINKED(d->state))
-pa_sink_input_move_to(si, d, true);
+PA_SINK_IS_LINKED(d->state)) {
+   pa_xfree(si->preferred_si

[pulseaudio-discuss] [PATCH 2/4] move stream after default sink is changed.

2018-11-04 Thread Hui Wang
When default sink changes, the stream should be moved to new
default_sink too. If it is user to call change default function,
all stream will move to new default sink unconditionally; if it
is not, will check if stream binds to old_default_sink and the
active_port staus of old_default_sink, then it will move the
stream conditionally.

Signed-off-by: Hui Wang 
---
 src/modules/dbus/iface-core.c   |  2 +-
 src/modules/module-default-device-restore.c |  2 +-
 src/modules/module-switch-on-connect.c  | 28 ++-
 src/pulsecore/cli-command.c |  2 +-
 src/pulsecore/core.c|  9 +++--
 src/pulsecore/core.h|  4 +--
 src/pulsecore/device-port.c |  2 +-
 src/pulsecore/protocol-native.c |  2 +-
 src/pulsecore/sink.c| 39 +++--
 src/pulsecore/sink.h|  1 +
 10 files changed, 52 insertions(+), 39 deletions(-)

diff --git a/src/modules/dbus/iface-core.c b/src/modules/dbus/iface-core.c
index 5229c0467..9763480d2 100644
--- a/src/modules/dbus/iface-core.c
+++ b/src/modules/dbus/iface-core.c
@@ -721,7 +721,7 @@ static void handle_set_fallback_sink(DBusConnection *conn, 
DBusMessage *msg, DBu
 return;
 }
 
-pa_core_set_configured_default_sink(c->core, 
pa_dbusiface_device_get_sink(fallback_sink)->name);
+pa_core_set_configured_default_sink(c->core, 
pa_dbusiface_device_get_sink(fallback_sink)->name, true);
 
 pa_dbus_send_empty_reply(conn, msg);
 }
diff --git a/src/modules/module-default-device-restore.c 
b/src/modules/module-default-device-restore.c
index c4dbad99f..33e74c071 100644
--- a/src/modules/module-default-device-restore.c
+++ b/src/modules/module-default-device-restore.c
@@ -69,7 +69,7 @@ static void load(struct userdata *u) {
 pa_log_warn("Invalid sink name: %s", ln);
 else {
 pa_log_info("Restoring default sink '%s'.", ln);
-pa_core_set_configured_default_sink(u->core, ln);
+pa_core_set_configured_default_sink(u->core, ln, false);
 }
 
 } else if (errno != ENOENT)
diff --git a/src/modules/module-switch-on-connect.c 
b/src/modules/module-switch-on-connect.c
index faa0f289f..4f01c701f 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -54,9 +54,6 @@ struct userdata {
 };
 
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
-pa_sink_input *i;
-uint32_t idx;
-pa_sink *old_default_sink;
 const char *s;
 struct userdata *u = userdata;
 
@@ -85,7 +82,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 
 /* No default sink, nothing to move away, just set the new default */
 if (!c->default_sink) {
-pa_core_set_configured_default_sink(c, sink->name);
+pa_core_set_configured_default_sink(c, sink->name, false);
 return PA_HOOK_OK;
 }
 
@@ -100,29 +97,8 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 return PA_HOOK_OK;
 }
 
-old_default_sink = c->default_sink;
-
 /* Actually do the switch to the new sink */
-pa_core_set_configured_default_sink(c, sink->name);
-
-/* Now move all old inputs over */
-if (pa_idxset_size(old_default_sink->inputs) <= 0) {
-pa_log_debug("No sink inputs to move away.");
-return PA_HOOK_OK;
-}
-
-PA_IDXSET_FOREACH(i, old_default_sink->inputs, idx) {
-if (i->preferred_sink != NULL || !PA_SINK_INPUT_IS_LINKED(i->state))
-continue;
-
-if (pa_sink_input_move_to(i, 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)), 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)), sink->name);
-}
-
+pa_core_set_configured_default_sink(c, sink->name, false);
 return PA_HOOK_OK;
 }
 
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 5205349bd..cc7addaa1 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -1036,7 +1036,7 @@ static int pa_cli_command_sink_default(pa_core *c, 
pa_tokenizer *t, pa_strbuf *b
 }
 
 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
-pa_core_set_configured_default_sink(c, s->name);
+pa_core_set_configured_default_sink(c, s->name, true);
 else
 pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
 
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 

[pulseaudio-discuss] [PATCH 4/4] move stream when the active_port changes

2018-11-04 Thread Hui Wang
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 
---
 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);
+   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
-- 
2.17.1

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


Re: [pulseaudio-discuss] [PATCH 2/4] move stream after default sink is changed.

2018-12-14 Thread Hui Wang

On 2018/12/13 下午5:16, Tanu Kaskinen wrote:

On Mon, 2018-11-05 at 09:47 +0800, Hui Wang wrote:

When default sink changes, the stream should be moved to new
default_sink too.

Except if the stream's preferred sink is the old default sink.


If it is user to call change default function,
all stream will move to new default sink unconditionally; if it
is not, will check if stream binds to old_default_sink and the
active_port staus of old_default_sink, then it will move the
stream conditionally.

Why does it matter if the default sink changed due to user request or
some other reason? I don't think streams should be moved
unconditionally when the user changes the default sink.


Supposing  the sink0 is hdmi, sink1 is analog-speaker,  and a music is 
playing on sink0 (default_sink is sink0),  if users select the 
analog-speaker from UI (gnome-sound-setting), the sink1 is default_sink 
now, and the music should be played on sink1.  If the streams don't move 
to new default_sink unconditionally, I have no idea how to let music be 
played on sink1 here.



For the rest comments, I will fix them as suggested.


Thanks.




I think it would be logical to not care about the port unavailability
in this patch, because there's a separate patch for handling that.


diff --git a/src/modules/module-switch-on-connect.c 
b/src/modules/module-switch-on-connect.c
index faa0f289f..4f01c701f 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -100,29 +97,8 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
  return PA_HOOK_OK;
  }
  
-old_default_sink = c->default_sink;

-
  /* Actually do the switch to the new sink */

This comment isn't very helpful any more (not sure how helpful it was
before either), I'd remove it.


-pa_core_set_configured_default_sink(c, sink->name);
-
-/* Now move all old inputs over */
-if (pa_idxset_size(old_default_sink->inputs) <= 0) {
-pa_log_debug("No sink inputs to move away.");
-return PA_HOOK_OK;
-}
-
-PA_IDXSET_FOREACH(i, old_default_sink->inputs, idx) {
-if (i->preferred_sink != NULL || !PA_SINK_INPUT_IS_LINKED(i->state))
-continue;
-
-if (pa_sink_input_move_to(i, 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)), 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)), sink->name);
-}
-
+pa_core_set_configured_default_sink(c, sink->name, false);
  return PA_HOOK_OK;
  }
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 566367f9e..63a3456e7 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -3886,3 +3886,36 @@ void pa_sink_set_reference_volume_direct(pa_sink *s, 
const pa_cvolume *volume) {
  pa_subscription_post(s->core, 
PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
  pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], s);
  }
+
+void pa_sink_move_streams_from_oldsink_to_newsink(pa_sink *old_sink, pa_sink 
*new_sink, bool from_user) {

I think "pa_sink_move_streams_to_default_sink" would be a better name
for the function. It would also be good to have a comment explaining
when the function is used and which streams are not moved (that could
go to the header file).


+pa_sink_input *i;
+uint32_t idx;
+pa_device_port *o_active_p;
+
+if (old_sink == new_sink)
+   return;
+
+if (old_sink == NULL)
+   return;

It doesn't make sense to call this function with NULL, so this check
should be an assertion instead.


+
+o_active_p = old_sink->active_port;

Note that not all sinks have ports, so this can be NULL.

Since we only care about the availability of the active port, I'd add a
"old_sink_is_unavailable" boolean to be used inside the loop.


+if (pa_idxset_size(old_sink->inputs) > 0) {
+   PA_IDXSET_FOREACH(i, old_sink->inputs, idx) {
+   if (!PA_SINK_INPUT_IS_LINKED(i->state))
+   continue;
+
+   if (!from_user && i->preferred_sink != NULL && 
pa_safe_streq(old_sink->name, i->preferred_sink))

No need to check if i->preferred_sink is NULL, because pa_safe_streq()
checks that anyway.


+   if (o_active_p->available != PA_AVAILABLE_NO)
+   continue;
+
+   if (pa_sink_input_move_to(i, new_sink, from_user) < 0)
+   pa_log_info("Failed to move sink input %u \"%s\" to %s.", 
i

Re: [pulseaudio-discuss] [PATCH 1/4] change bool save_sink to char *preferred_sink

2018-12-15 Thread Hui Wang

On 2018/12/12 下午9:39, Tanu Kaskinen wrote:

Thanks for working on this! Sorry for slow review, I hope I'll be much
quicker to comment on subsequent iterations.

On Mon, 2018-11-05 at 09:47 +0800, Hui Wang wrote:

And don't move the stream in the module-stream-restore anymore,
And the preferred_sink is only set when user is calling the
move_to() and the module-stream-restore maintains the saving and
deleting of preferred_sink.

If the target of move_to() is default_sink, preferred_sink will be
cleared and the entry->device will be cleared too from database.

Can you split this so that the first patch only changes save_sink to
preferred_sink, without any changes in behaviour? That is, put the
"don't move the stream in the module-stream-restore" and "if the target
of move_to() is default_sink" logic into separate patches.

Also replace tabs with spaces.

OK, got it, will addressed all comments.

Signed-off-by: Hui Wang 

[...]

  }
  }
@@ -2176,9 +2190,10 @@ static int extension_cb(pa_native_protocol *p, pa_module 
*m, pa_native_connectio
  
  entry->muted = muted;

  entry->muted_valid = true;
-
-entry->device = pa_xstrdup(device);
-entry->device_valid = device && !!entry->device[0];
+   if (device && !pa_streq(device, m->core->default_sink->name) && 
!pa_streq(device, m->core->default_source->name)) {
+   entry->device = pa_xstrdup(device);
+   entry->device_valid = device && !!entry->device[0];
+   }

What's the goal here? The client tries to change an entry in the
stream-restore database, why should that change be ignored if the
current default sink happens to be the same as the new device? Maybe
you intended to set entry->device to NULL in this case. But I don't
think that's necessary either - if the client wants to unset the
device, it can just give NULL as the device name. I don't think you
need to change anything here.

By the way, m->core->default_sink can be NULL, so that would have to be
checked if this code was kept.


Actually I didn't change this part first, but I remember the stream bond 
did not work as expected, after changed as above, it worked as expected.


Supposing sink0 is hdmi, and is playing a music over sink0, sink1 is 
speaker,  after I unplugged the hdmi cable, the music is switched to 
speaker,  but music->preferred_sink is still sink0-hdmi, after I plug 
the hdmi cable again, the music should be switched back to sink0-hdmi.  
I remember after I unplugged the cable, a user-space app call 
extension_cb to set the music->preferred_sink to be sink1-speaker 
(default_sink), then the music can't be switched back to hdmi anymore.


I will test it again, if it is really not needed, I will drop these code.


Thanks,

Hui.


  
  if (entry->device_valid && !pa_namereg_is_valid_name(entry->device)) {

  entry_free(entry);



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


[pulseaudio-discuss] [PATCH] alsa-mixer: Adding Jack of Front Headphone Front and Surround

2018-12-20 Thread Hui Wang
We have 2 HP desktop models which have one front headphone Jack and
one front headset Jack, in the Linux kernel, these two jacks are
named "Front Headphone Front Jack" and "Front Headphone Surround
Jack", now adding them into the pathes conf file.

Without this change, if users plug a headset or headphone, the
path of headphone will not be activated, and users can't see
headphones from UI like gnome-control-center.

Signed-off-by: Hui Wang 
---
For alsa-info.txt of one of machines, please access:
https://pastebin.ubuntu.com/p/CjCGySMpM5/

 .../alsa/mixer/paths/analog-input-headset-mic.conf| 6 ++
 .../alsa/mixer/paths/analog-output-headphones.conf| 6 ++
 .../alsa/mixer/paths/analog-output-speaker-always.conf| 8 
 src/modules/alsa/mixer/paths/analog-output-speaker.conf   | 8 
 4 files changed, 28 insertions(+)

diff --git a/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf 
b/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf
index 579db6bb7..bc687b6e4 100644
--- a/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf
+++ b/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf
@@ -35,6 +35,12 @@ state.plugged = unknown
 [Jack Front Headphone]
 state.plugged = unknown
 
+[Jack Front Headphone Front]
+state.plugged = unknown
+
+[Jack Front Headphone Surround]
+state.plugged = unknown
+
 [Jack Headphone Mic]
 state.plugged = unknown
 
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf 
b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
index d2147c50f..2d751607c 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
@@ -40,6 +40,12 @@ required-any = any
 state.plugged = unknown
 state.unplugged = unknown
 
+[Jack Front Headphone Front]
+required-any = any
+
+[Jack Front Headphone Surround]
+required-any = any
+
 [Jack Headphone]
 required-any = any
 
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf 
b/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
index 71f356dce..c9374e471 100644
--- a/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
@@ -33,6 +33,14 @@ state.unplugged = unknown
 state.plugged = no
 state.unplugged = unknown
 
+[Jack Front Headphone Front]
+state.plugged = no
+state.unplugged = unknown
+
+[Jack Front Headphone Surround]
+state.plugged = no
+state.unplugged = unknown
+
 [Jack Line Out]
 state.plugged = no
 state.unplugged = unknown
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf 
b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
index 9f4dac414..536630d0a 100644
--- a/src/modules/alsa/mixer/paths/analog-output-speaker.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
@@ -36,6 +36,14 @@ state.unplugged = unknown
 state.plugged = no
 state.unplugged = unknown
 
+[Jack Front Headphone Front]
+state.plugged = no
+state.unplugged = unknown
+
+[Jack Front Headphone Surround]
+state.plugged = no
+state.unplugged = unknown
+
 [Jack Line Out]
 state.plugged = no
 state.unplugged = unknown
-- 
2.17.1

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


Re: [pulseaudio-discuss] [PATCH 1/4] change bool save_sink to char *preferred_sink

2018-12-25 Thread Hui Wang

On 2018/12/23 上午3:06, Tanu Kaskinen wrote:

On Sat, 2018-12-15 at 16:47 +0800, Hui Wang wrote:

On 2018/12/12 下午9:39, Tanu Kaskinen wrote:

Thanks for working on this! Sorry for slow review, I hope I'll be much
quicker to comment on subsequent iterations.

On Mon, 2018-11-05 at 09:47 +0800, Hui Wang wrote:

And don't move the stream in the module-stream-restore anymore,
And the preferred_sink is only set when user is calling the
move_to() and the module-stream-restore maintains the saving and
deleting of preferred_sink.

If the target of move_to() is default_sink, preferred_sink will be
cleared and the entry->device will be cleared too from database.

Can you split this so that the first patch only changes save_sink to
preferred_sink, without any changes in behaviour? That is, put the
"don't move the stream in the module-stream-restore" and "if the target
of move_to() is default_sink" logic into separate patches.

Also replace tabs with spaces.

OK, got it, will addressed all comments.

Signed-off-by: Hui Wang 

[...]

   }
   }
@@ -2176,9 +2190,10 @@ static int extension_cb(pa_native_protocol *p, pa_module 
*m, pa_native_connectio
   
   entry->muted = muted;

   entry->muted_valid = true;
-
-entry->device = pa_xstrdup(device);
-entry->device_valid = device && !!entry->device[0];
+   if (device && !pa_streq(device, m->core->default_sink->name) && 
!pa_streq(device, m->core->default_source->name)) {
+   entry->device = pa_xstrdup(device);
+   entry->device_valid = device && !!entry->device[0];
+   }

What's the goal here? The client tries to change an entry in the
stream-restore database, why should that change be ignored if the
current default sink happens to be the same as the new device? Maybe
you intended to set entry->device to NULL in this case. But I don't
think that's necessary either - if the client wants to unset the
device, it can just give NULL as the device name. I don't think you
need to change anything here.

By the way, m->core->default_sink can be NULL, so that would have to be
checked if this code was kept.

Actually I didn't change this part first, but I remember the stream bond
did not work as expected, after changed as above, it worked as expected.

Supposing sink0 is hdmi, and is playing a music over sink0, sink1 is
speaker,  after I unplugged the hdmi cable, the music is switched to
speaker,  but music->preferred_sink is still sink0-hdmi, after I plug
the hdmi cable again, the music should be switched back to sink0-hdmi.
I remember after I unplugged the cable, a user-space app call
extension_cb to set the music->preferred_sink to be sink1-speaker
(default_sink), then the music can't be switched back to hdmi anymore.

I will test it again, if it is really not needed, I will drop these code.

I would guess that it's gnome-control-center that sets the device to
speakers when you select speakers as the output. gnome-control-center
updates the routing in all stream-restore entries. Once these patches
are merged (and once a new release is made), gnome-control-center can
be fixed to not mess with the stream-restore database any more. I
believe the current gnome-control-center behaviour is a workaround for
the fact that PulseAudio hasn't so far automatically moved streams when
the default sink changes.

Yes, it is gnome-control-center. OK, will drop this part.


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


Re: [pulseaudio-discuss] [PATCH 2/4] move stream after default sink is changed.

2018-12-25 Thread Hui Wang

On 2018/12/23 上午2:57, Tanu Kaskinen wrote:

On Sat, 2018-12-15 at 14:48 +0800, Hui Wang wrote:

On 2018/12/13 下午5:16, Tanu Kaskinen wrote:

On Mon, 2018-11-05 at 09:47 +0800, Hui Wang wrote:

When default sink changes, the stream should be moved to new
default_sink too.

Except if the stream's preferred sink is the old default sink.


If it is user to call change default function,
all stream will move to new default sink unconditionally; if it
is not, will check if stream binds to old_default_sink and the
active_port staus of old_default_sink, then it will move the
stream conditionally.

Why does it matter if the default sink changed due to user request or
some other reason? I don't think streams should be moved
unconditionally when the user changes the default sink.

Supposing  the sink0 is hdmi, sink1 is analog-speaker,  and a music is
playing on sink0 (default_sink is sink0),  if users select the
analog-speaker from UI (gnome-sound-setting), the sink1 is default_sink
now, and the music should be played on sink1.  If the streams don't move
to new default_sink unconditionally, I have no idea how to let music be
played on sink1 here.

I don't see what the problem is - streams should by default move to the
new default sink, but if the user has at some point manually moved a
stream to sink0, making sink0 the preferred sink, then that stream
shouldn't be moved automatically. If the user doesn't want to keep that
old setting any more, they can move the stream manually to sink1, and
since sink1 is the default sink at this point, the preferred_sink will
be unset, so that stream will from then on behave like all other
streams.

OK, got it.  thanks.


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


Re: [pulseaudio-discuss] [PATCH] alsa-mixer: Adding Jack of Front Headphone Front and Surround

2019-01-02 Thread Hui Wang

On 2018/12/31 下午9:46, Tanu Kaskinen wrote:

On Fri, 2018-12-21 at 11:05 +0800, Hui Wang wrote:

We have 2 HP desktop models which have one front headphone Jack and
one front headset Jack, in the Linux kernel, these two jacks are
named "Front Headphone Front Jack" and "Front Headphone Surround
Jack", now adding them into the pathes conf file.

How do the kcontrols map to physical connectors? Is there only one
physical connector or two? How do different kinds of devices
(headphones, headsets, stand-alone mics) change the state of the two
kcontrols?
There are 2 physical connectors/jacks, one is the pure headphone jack, 
the other is the headset jack (headphone + mic).


For the headphone jack, the kcontrols are:  'Front Headphone Surround 
Jack' and 'Headphone Playback Volume' index 1


For the headset jack, the kcontrols are: 'Front Headphone Front Jack',  
'Headphone Playback Volume' index 0, 'Mic Jack' and 'Mic Boost Volume'


If we plug a headphone in either of the two jacks, the 'Surround Jack' 
or 'Front Jack' will be true. If we plug a headset in the headset jack, 
the 'Front Jack' and 'Mic Jack' will be true.


This is not the Dell machine, most Dell machines can't detect mic of 
headset, so we add headset-mic, headphone-mic for them.  This HP machine 
can detect mic of headset jack, and it doesn't support stand-alone mics too.





I think at least the headset-mic path configuration in your patch is
incorrect, but I don't know how it should be configured before knowing
how the two kcontrols behave.


After reading your comments above,  I think you are right.  And I think 
I shouldn't touch analog-input-headset-mic.conf in the patch, since this 
is a HP machine, and the headset jack of this machine has capability to 
detect the mic on the headset and the kcontrols are "Mic Jack" and 
"Headphone Front Jack". It is different from the Dell machines.




(A sidenote: it would be awesome to have some documentation that
explains what combinations of headphone/headset/mic jacks exist in the
wild and how those combinations map to physical connectors. The details
of the headphone/headset/mic jack detection mess are impossible to
remember.)

It is not easy to fully understand this part, need to study it bit by 
bit.  :-)




Without this change, if users plug a headset or headphone, the
path of headphone will not be activated, and users can't see
headphones from UI like gnome-control-center.

Signed-off-by: Hui Wang 
---
For alsa-info.txt of one of machines, please access:
https://pastebin.ubuntu.com/p/CjCGySMpM5/

  .../alsa/mixer/paths/analog-input-headset-mic.conf| 6 ++
  .../alsa/mixer/paths/analog-output-headphones.conf| 6 ++
  .../alsa/mixer/paths/analog-output-speaker-always.conf| 8 
  src/modules/alsa/mixer/paths/analog-output-speaker.conf   | 8 
  4 files changed, 28 insertions(+)

diff --git a/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf 
b/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf
index 579db6bb7..bc687b6e4 100644
--- a/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf
+++ b/src/modules/alsa/mixer/paths/analog-input-headset-mic.conf
@@ -35,6 +35,12 @@ state.plugged = unknown
  [Jack Front Headphone]
  state.plugged = unknown
  
+[Jack Front Headphone Front]

+state.plugged = unknown
+
+[Jack Front Headphone Surround]
+state.plugged = unknown
+
  [Jack Headphone Mic]
  state.plugged = unknown
  
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf b/src/modules/alsa/mixer/paths/analog-output-headphones.conf

index d2147c50f..2d751607c 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
@@ -40,6 +40,12 @@ required-any = any
  state.plugged = unknown
  state.unplugged = unknown
  
+[Jack Front Headphone Front]

+required-any = any
+
+[Jack Front Headphone Surround]
+required-any = any
+
  [Jack Headphone]
  required-any = any
  
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf b/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf

index 71f356dce..c9374e471 100644
--- a/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
@@ -33,6 +33,14 @@ state.unplugged = unknown
  state.plugged = no
  state.unplugged = unknown
  
+[Jack Front Headphone Front]

+state.plugged = no
+state.unplugged = unknown
+
+[Jack Front Headphone Surround]
+state.plugged = no
+state.unplugged = unknown
+
  [Jack Line Out]
  state.plugged = no
  state.unplugged = unknown
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf 
b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
index 9f4dac414..536630d0a 100644
--- a/src/modules/alsa/m

Re: [pulseaudio-discuss] [PATCH 3/4] move streams to new appeared sinks if they prefer these sinks

2019-01-02 Thread Hui Wang

On 2019/1/1 上午2:10, Tanu Kaskinen wrote:

On Mon, 2018-12-31 at 20:01 +0200, Tanu Kaskinen wrote:

On Mon, 2018-11-05 at 09:47 +0800, Hui Wang wrote:

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 63a3456e7..a2a390beb 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -722,6 +722,8 @@ void pa_sink_put(pa_sink* s) {
  /* This function must be called after the PA_CORE_HOOK_SINK_PUT hook,
   * because module-switch-on-connect needs to know the old default sink */
  pa_core_update_default_sink(s->core, false);
+
+pa_sink_bind_preferred_stream_to_a_sink(s);
  }
  
  /* Called from main context */

@@ -3919,3 +3921,32 @@ void 
pa_sink_move_streams_from_oldsink_to_newsink(pa_sink *old_sink, pa_sink *ne
  
  return;

  }
+
+void pa_sink_bind_preferred_stream_to_a_sink(pa_sink *s) {

"Bind" is new terminology, and I'd like to avoid introducing new
terminology if possible. Also, "preferred stream" as a term doesn't
really make sense. So some better name for the function would be
desirable, but I can't immediately think of any obvious names... The
function is about moving streams to a sink that just became available.
"Move" and "streams" should be included in the name... Maybe
"pa_sink_move_streams_to_newly_available_sink()"? I also suggest moving
it away from the pa_sink namespace, because the function operates on
streams, not on a sink.

That last sentence can be objected to - the function takes the sink as
an argument, so it can be said to operate on the sink. But then the
verb should be something that the sink does, like "take" ("move" is
something that streams do). So pa_sink_take_streams()? Or
pa_sink_take_streams_that_prefer_it()? I don't know. My weak preference
at this point is pa_core_move_streams_to_newly_available_sink(). It's
quite descriptive, but unfortunately lacks the distinction that only
those streams that prefer the newly available sink are moved.

Understand what you mean here, will have a try to provide a new function 
name and address the rest comments of this patch.


Thanks.



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


Re: [pulseaudio-discuss] [PATCH 4/4] move stream when the active_port changes

2019-01-02 Thread Hui Wang

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 
---
  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



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


[pulseaudio-discuss] [PATCH v2 0/2] Handle two Headphone Jacks with the same name

2019-01-13 Thread Hui Wang
Although the patchset tries to add index support, the objective is 100%
compatible with the past. If there is no kcontrols with "index != 0", we
don't need to change any conf files, the pulseaudio will work as before.

The name of "Front Headphone Surround" and "Front Headphone Front" are
not good, I plan to submit a patch to the kernel to change the name to
"Front Headphone" with index 0 and "Front Headphone" with index 1, since
the patch for the kernel is not submitted yet, here I don't send the patch
to change ${path}.conf, but to be easy to review, I paste an example of
changing the ${path}.conf after the kernel patch is merged:


--- a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
@@ -40,6 +40,18 @@ override-map.2 = all-left,all-right
 switch = off
 volume = off
 
+[Jack Front Headphone@1]
+required-any = any
+index = 1
+
+[Element Headphone@1]
+required-any = any
+index = 1
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
 ; This profile path is intended to control the second headphones, not
 ; the first headphones. But it should not hurt if we leave the
 ; headphone jack enabled nonetheless.
@@ -56,7 +68,7 @@ switch = off
 volume = off
 
 [Element Headphone2]
-required = any
+required-any = any
 switch = mute
 volume = merge
 override-map.1 = all


--- a/src/modules/alsa/mixer/paths/analog-output-speaker.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
@@ -32,6 +32,11 @@ state.unplugged = unknown
 state.plugged = no
 state.unplugged = unknown
 
+[Jack Front Headphone@1]
+index = 1
+state.plugged = no
+state.unplugged = unknown
+
 [Jack Front Headphone]
 state.plugged = no
 state.unplugged = unknown


Hui Wang (2):
  alsa-mixer: Add alsa index number support for Element and Jack
  alsa-mixer: set different strings to name and alsa-name for jack and
element

 src/modules/alsa/alsa-mixer.c | 99 +++
 src/modules/alsa/alsa-mixer.h |  6 +-
 src/modules/alsa/alsa-ucm.c   |  2 +-
 src/modules/alsa/alsa-util.c  |  4 +-
 src/modules/alsa/alsa-util.h  |  2 +-
 .../mixer/paths/analog-output.conf.common |  6 ++
 src/modules/alsa/module-alsa-card.c   |  4 +-
 7 files changed, 95 insertions(+), 28 deletions(-)

-- 
2.17.1

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


[pulseaudio-discuss] [PATCH v2 1/2] alsa-mixer: Add alsa index number support for Element and Jack

2019-01-13 Thread Hui Wang
We have met a couple of machines which have two Kcontrols with the
exact same names and with the different index numbers, for example:
  (1 physical headphone jack + 1 physical headset jack on front panel)
  - Simple mixer control 'Headphone',0 (volume and switch)
  - Simple mixer control 'Headphone',1 (volume and switch)
  (1 physical mic jack + 1 physical headset jack on front panel)
  - iface=CARD,name='Mic Jack' index 0
  - iface=CARD,name='Mic Jack' index 1

To let pulseaudio treat them as different Jacks or differnt Elements,
we introduce index to the pa_alsa_jack and pa_alsa_element.

When probing jacks or elements, we add index as a parameter.

Signed-off-by: Hui Wang 
---
 src/modules/alsa/alsa-mixer.c | 59 ++-
 src/modules/alsa/alsa-mixer.h |  2 +
 src/modules/alsa/alsa-ucm.c   |  2 +-
 src/modules/alsa/alsa-util.c  |  4 +-
 src/modules/alsa/alsa-util.h  |  2 +-
 .../mixer/paths/analog-output.conf.common |  5 ++
 src/modules/alsa/module-alsa-card.c   |  4 +-
 7 files changed, 59 insertions(+), 19 deletions(-)

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 91dfc66ee..e32ec5cd7 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -718,11 +718,11 @@ static pa_volume_t from_alsa_volume(long v, long min, 
long max) {
 return (pa_volume_t) round(((double) (v - min) * PA_VOLUME_NORM) / 
(double) (max - min));
 }
 
-#define SELEM_INIT(sid, name)   \
+#define SELEM_INIT(sid, name, index)   \
 do {\
 snd_mixer_selem_id_alloca(&(sid));  \
 snd_mixer_selem_id_set_name((sid), (name)); \
-snd_mixer_selem_id_set_index((sid), 0); \
+snd_mixer_selem_id_set_index((sid), index); \
 } while(false)
 
 static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const 
pa_channel_map *cm, pa_cvolume *v) {
@@ -737,7 +737,7 @@ static int element_get_volume(pa_alsa_element *e, 
snd_mixer_t *m, const pa_chann
 pa_assert(cm);
 pa_assert(v);
 
-SELEM_INIT(sid, e->alsa_name);
+SELEM_INIT(sid, e->alsa_name, e->index);
 if (!(me = snd_mixer_find_selem(m, sid))) {
 pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
 return -1;
@@ -902,7 +902,7 @@ static int element_get_switch(pa_alsa_element *e, 
snd_mixer_t *m, bool *b) {
 pa_assert(e);
 pa_assert(b);
 
-SELEM_INIT(sid, e->alsa_name);
+SELEM_INIT(sid, e->alsa_name, e->index);
 if (!(me = snd_mixer_find_selem(m, sid))) {
 pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
 return -1;
@@ -1066,7 +1066,7 @@ static int element_set_volume(pa_alsa_element *e, 
snd_mixer_t *m, const pa_chann
 pa_assert(v);
 pa_assert(pa_cvolume_compatible_with_channel_map(v, cm));
 
-SELEM_INIT(sid, e->alsa_name);
+SELEM_INIT(sid, e->alsa_name, e->index);
 if (!(me = snd_mixer_find_selem(m, sid))) {
 pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
 return -1;
@@ -1256,7 +1256,7 @@ static int element_set_switch(pa_alsa_element *e, 
snd_mixer_t *m, bool b) {
 pa_assert(m);
 pa_assert(e);
 
-SELEM_INIT(sid, e->alsa_name);
+SELEM_INIT(sid, e->alsa_name, e->index);
 if (!(me = snd_mixer_find_selem(m, sid))) {
 pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
 return -1;
@@ -1307,7 +1307,7 @@ static int element_set_constant_volume(pa_alsa_element 
*e, snd_mixer_t *m) {
 pa_assert(m);
 pa_assert(e);
 
-SELEM_INIT(sid, e->alsa_name);
+SELEM_INIT(sid, e->alsa_name, e->index);
 if (!(me = snd_mixer_find_selem(m, sid))) {
 pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
 return -1;
@@ -1734,7 +1734,7 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t 
*m) {
 pa_assert(e);
 pa_assert(e->path);
 
-SELEM_INIT(sid, e->alsa_name);
+SELEM_INIT(sid, e->alsa_name, e->index);
 
 if (!(me = snd_mixer_find_selem(m, sid))) {
 
@@ -1837,7 +1837,7 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping 
*mapping, snd_mixer_t *m)
 j->append_pcm_to_name = false;
 }
 
-has_control = pa_alsa_mixer_find(m, j->alsa_name, 0) != NULL;
+has_control = pa_alsa_mixer_find(m, j->alsa_name, 0, j->index) != NULL;
 pa_alsa_jack_set_has_control(j, has_control);
 
 if (j->has_control) {
@@ -1959,6 +1959,36 @@ finish:
 return o;
 }
 
+static int element_parse_index(pa_config_parser_state *state) {
+pa_alsa_path *p;
+pa_alsa_element *e;
+pa_alsa_jack *j;
+uint32_t ind;
+
+pa_assert

[pulseaudio-discuss] [PATCH v2 2/2] alsa-mixer: set different strings to name and alsa-name for jack and element

2019-01-13 Thread Hui Wang
It is possible that we set more than one jacks or elements with the same name
and different index in a {path}.conf, the current code will only generate
one pa_alsa_jack or pa_alsa_element for them regardless of the difference
of index number.

To fix it, we change the rule of naming an element or a jack, let us use
the element as an example, if the index of this element is 0, we don't
set index for it in the {path}.conf and set the element name to 
as before, if the index number is 1, we should set the "index = 1" for
this element in the {path}.conf and set the element name to @1, then
in the alsa-mixer.c, the "@1" will be set to the element->name, and
the "" will be set to the element->alsa_name, we generated the new
element based on the element->name, then this issue is fixed.

Signed-off-by: Hui Wang 
---
 src/modules/alsa/alsa-mixer.c | 40 +++
 src/modules/alsa/alsa-mixer.h |  4 +-
 .../mixer/paths/analog-output.conf.common |  3 +-
 3 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index e32ec5cd7..b4933e07f 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -100,6 +100,8 @@ static inline int 
vgfix_get_playback_dB_range(snd_mixer_elem_t *a, long *b, long
 
 #endif
 
+#define SEC_NAME_INDEX_DELIMITER "@"
+
 static int setting_select(pa_alsa_setting *s, snd_mixer_t *m);
 
 struct description_map {
@@ -109,13 +111,17 @@ struct description_map {
 
 pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *name) {
 pa_alsa_jack *jack;
+char *tmp_name;
+const char *split_state = NULL;
 
 pa_assert(name);
 
 jack = pa_xnew0(pa_alsa_jack, 1);
 jack->path = path;
 jack->name = pa_xstrdup(name);
-jack->alsa_name = pa_sprintf_malloc("%s Jack", name);
+tmp_name = pa_split(name, SEC_NAME_INDEX_DELIMITER, &split_state);
+jack->alsa_name = pa_sprintf_malloc("%s Jack", tmp_name);
+pa_xfree(tmp_name);
 jack->state_unplugged = PA_AVAILABLE_NO;
 jack->state_plugged = PA_AVAILABLE_YES;
 jack->ucm_devices = pa_dynarray_new(NULL);
@@ -657,6 +663,7 @@ static void element_free(pa_alsa_element *e) {
 if (e->db_fix)
 decibel_fix_free(e->db_fix);
 
+pa_xfree(e->name);
 pa_xfree(e->alsa_name);
 pa_xfree(e);
 }
@@ -1820,6 +1827,8 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping 
*mapping, snd_mixer_t *m)
 
 if (j->append_pcm_to_name) {
 char *new_name;
+char *tmp_name;
+const char *split_state = NULL;
 
 if (!mapping) {
 /* This could also be an assertion, because this should never
@@ -1831,7 +1840,9 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping 
*mapping, snd_mixer_t *m)
 return -1;
 }
 
-new_name = pa_sprintf_malloc("%s,pcm=%i Jack", j->name, 
mapping->hw_device_index);
+tmp_name = pa_split(j->name, SEC_NAME_INDEX_DELIMITER, &split_state);
+new_name = pa_sprintf_malloc("%s,pcm=%i Jack", tmp_name, 
mapping->hw_device_index);
+pa_xfree(tmp_name);
 pa_xfree(j->alsa_name);
 j->alsa_name = new_name;
 j->append_pcm_to_name = false;
@@ -1855,6 +1866,8 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping 
*mapping, snd_mixer_t *m)
 
 static pa_alsa_element* element_get(pa_alsa_path *p, const char *section, bool 
prefixed) {
 pa_alsa_element *e;
+char *tmp_name;
+const char *split_state = NULL;
 
 pa_assert(p);
 pa_assert(section);
@@ -1870,16 +1883,19 @@ static pa_alsa_element* element_get(pa_alsa_path *p, 
const char *section, bool p
 if (strchr(section, ':'))
 return NULL;
 
-if (p->last_element && pa_streq(p->last_element->alsa_name, section))
+if (p->last_element && pa_streq(p->last_element->name, section))
 return p->last_element;
 
 PA_LLIST_FOREACH(e, p->elements)
-if (pa_streq(e->alsa_name, section))
+if (pa_streq(e->name, section))
 goto finish;
 
 e = pa_xnew0(pa_alsa_element, 1);
 e->path = p;
-e->alsa_name = pa_xstrdup(section);
+e->name = pa_xstrdup(section);
+tmp_name = pa_split(section, SEC_NAME_INDEX_DELIMITER, &split_state);
+e->alsa_name = pa_xstrdup(tmp_name);
+pa_xfree(tmp_name);
 e->direction = p->direction;
 e->volume_limit = -1;
 
@@ -2692,6 +2708,8 @@ fail:
 pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t 
direction) {
 pa_alsa_path *p;
 pa_alsa_element *e;
+char *tmp_name;
+const char *split_state = NULL;
 
 pa_assert(element);
 
@@ -2702,7 +2720,10 @@ pa_alsa_path *pa_alsa_path_synthesize(const char 

[pulseaudio-discuss] [PATCH v2 0/8] Change the bool sink_save to char *preferred_sink

2019-01-16 Thread Hui Wang
This is based on Tanu's design:
https://lists.freedesktop.org/archives/pulseaudio-discuss/2018-October/030531.html

And this is only for sink-input and sink, not for source-output and source.

In the V2, I addressed all comments of V1 and split the big patch into small 
patches
as suggested by Tanu. It will be easy to review in the future.

The 0007 and 0008 are not in the design of the above, I guess the 0007 is
needed but am not sure. The 0008 is a workaround for current
gnome-control-center.


Hui Wang (8):
  sink-input: change bool save_sink to char *preferred_sink
  sink-input: add a new API pa_sink_input_set_preferred_sink
  sink-input: clear the preferred_sink if it is default_sink
  core: move sink-inputs conditionally when update default_sink
  sink: move streams to new appeared sinks if they prefer these sinks
  device-port: moving streams due to changing the status of active_port
  sink: move the streams to the default_sink when the sink is unlinked
  stream-restore: skip entries setting action from gnome-control-center

 src/modules/dbus/iface-core.c   |   2 +-
 src/modules/module-default-device-restore.c |   2 +-
 src/modules/module-device-manager.c |   8 +-
 src/modules/module-intended-roles.c |   2 +-
 src/modules/module-stream-restore.c | 151 +---
 src/modules/module-switch-on-connect.c  |  27 +---
 src/pulsecore/cli-command.c |   2 +-
 src/pulsecore/core.c|  38 -
 src/pulsecore/core.h|   6 +-
 src/pulsecore/device-port.c |  32 -
 src/pulsecore/device-port.h |   2 +
 src/pulsecore/protocol-native.c |   2 +-
 src/pulsecore/sink-input.c  |  42 +-
 src/pulsecore/sink-input.h  |  19 ++-
 src/pulsecore/sink.c|  40 +-
 src/pulsecore/sink.h|   6 +
 16 files changed, 209 insertions(+), 172 deletions(-)

-- 
2.17.1

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


[pulseaudio-discuss] [PATCH v2 2/8] sink-input: add a new API pa_sink_input_set_preferred_sink

2019-01-16 Thread Hui Wang
If the sink here is NULL, that means users want to clear the
preferred_sink and move the sink-input to the default_sink, otherwise
set the preferred_sink to the sink->name and move the sink-input to
the sink. After that fire the sink_input_change event.

After adding this API, we can use this API to simplify the entry_apply
in the module-stream-restore.c.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 10 ++
 src/pulsecore/sink-input.c  | 14 ++
 src/pulsecore/sink-input.h  |  2 ++
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index a8c6a42c5..366f1a5a8 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1953,18 +1953,12 @@ static void entry_apply(struct userdata *u, const char 
*name, struct entry *e) {
preferred_sink is cleared as the user may have 
specifically
removed the sink element from the rule. */
 pa_xfree(si->preferred_sink);
-si->preferred_sink = NULL;
-/* This is cheating a bit. The sink input itself has not 
changed
-   but the rules governing its routing have, so we fire 
this event
-   such that other routing modules (e.g. 
module-device-manager)
-   will pick up the change and reapply their routing */
-pa_subscription_post(si->core, 
PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, si->index);
+pa_sink_input_set_preferred_sink(si, NULL);
 }
 } else if ((s = pa_namereg_get(u->core, e->device, 
PA_NAMEREG_SINK))) {
 pa_log_info("Restoring device for stream %s.", name);
-pa_sink_input_move_to(si, s, true);
 pa_xfree(si->preferred_sink);
-si->preferred_sink = pa_xstrdup(s->name);
+pa_sink_input_set_preferred_sink(si, s);
 }
 }
 }
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index f41eacf07..4dbc0cdef 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -2416,3 +2416,17 @@ void pa_sink_input_set_reference_ratio(pa_sink_input *i, 
const pa_cvolume *ratio
  pa_cvolume_snprint_verbose(old_ratio_str, 
sizeof(old_ratio_str), &old_ratio, &i->channel_map, true),
  pa_cvolume_snprint_verbose(new_ratio_str, 
sizeof(new_ratio_str), ratio, &i->channel_map, true));
 }
+
+/* Called from the main thread. */
+void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s) {
+pa_assert(i);
+
+if (s) {
+i->preferred_sink = pa_xstrdup(s->name);
+pa_sink_input_move_to(i, s, true);
+} else {
+i->preferred_sink = NULL;
+pa_sink_input_move_to(i, i->core->default_sink, true);
+}
+pa_subscription_post(i->core, 
PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+}
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 76140a2db..b67d3c1c3 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -460,6 +460,8 @@ void pa_sink_input_set_volume_direct(pa_sink_input *i, 
const pa_cvolume *volume)
  * i->reference_ratio and logs a message if the value changes. */
 void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume 
*ratio);
 
+void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s);
+
 #define pa_sink_input_assert_io_context(s) \
 pa_assert(pa_thread_mq_get() || !PA_SINK_INPUT_IS_LINKED((s)->state))
 
-- 
2.17.1

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


[pulseaudio-discuss] [PATCH v2 1/8] sink-input: change bool save_sink to char *preferred_sink

2019-01-16 Thread Hui Wang
The finial objective is to store the preferred sink name in the
sink-input struct, and use module-stream-restore to save and restore
it.

This patch just replaces the save_sink with preferred_sink, and tries
to keep the original logic.

Signed-off-by: Hui Wang 
---
 src/modules/module-device-manager.c|  8 
 src/modules/module-intended-roles.c|  2 +-
 src/modules/module-stream-restore.c| 15 +--
 src/modules/module-switch-on-connect.c |  2 +-
 src/pulsecore/sink-input.c | 24 +++-
 src/pulsecore/sink-input.h | 17 -
 6 files changed, 46 insertions(+), 22 deletions(-)

diff --git a/src/modules/module-device-manager.c 
b/src/modules/module-device-manager.c
index 15fd2..cba3a4ebc 100644
--- a/src/modules/module-device-manager.c
+++ b/src/modules/module-device-manager.c
@@ -656,14 +656,14 @@ static void route_sink_input(struct userdata *u, 
pa_sink_input *si) {
 pa_assert(u);
 pa_assert(u->do_routing);
 
-/* Don't override user or application routing requests. */
-if (si->save_sink || si->sink_requested_by_application)
-return;
-
 /* Skip this if it is already in the process of being moved anyway */
 if (!si->sink)
 return;
 
+/* Don't override user or application routing requests. */
+if (pa_safe_streq(si->sink->name, si->preferred_sink) || 
si->sink_requested_by_application)
+return;
+
 auto_filtered_prop = pa_proplist_gets(si->proplist, 
"module-device-manager.auto_filtered");
 if (auto_filtered_prop)
 auto_filtered = (pa_parse_boolean(auto_filtered_prop) == 1);
diff --git a/src/modules/module-intended-roles.c 
b/src/modules/module-intended-roles.c
index adee51c20..5596faf1f 100644
--- a/src/modules/module-intended-roles.c
+++ b/src/modules/module-intended-roles.c
@@ -175,7 +175,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, struct
 if (si->sink == sink)
 continue;
 
-if (si->save_sink)
+if (pa_safe_streq(si->sink->name, si->preferred_sink))
 continue;
 
 /* Skip this if it is already in the process of being moved
diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index 6c7b4c75b..a8c6a42c5 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1311,9 +1311,9 @@ static void subscribe_callback(pa_core *c, 
pa_subscription_event_type_t t, uint3
 mute_updated = !created_new_entry && (!old->muted_valid || 
entry->muted != old->muted);
 }
 
-if (sink_input->save_sink) {
+if (sink_input->preferred_sink != NULL) {
 pa_xfree(entry->device);
-entry->device = pa_xstrdup(sink_input->sink->name);
+entry->device = pa_xstrdup(sink_input->preferred_sink);
 entry->device_valid = true;
 
 device_updated = !created_new_entry && (!old->device_valid || 
!pa_streq(entry->device, old->device));
@@ -1646,7 +1646,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core 
*c, pa_sink *sink, struct
 if (si->sink == sink)
 continue;
 
-if (si->save_sink)
+if (pa_safe_streq(si->sink->name, si->preferred_sink))
 continue;
 
 /* Skip this if it is already in the process of being moved
@@ -1947,12 +1947,13 @@ static void entry_apply(struct userdata *u, const char 
*name, struct entry *e) {
 
 if (u->restore_device) {
 if (!e->device_valid) {
-if (si->save_sink) {
+if (si->preferred_sink != NULL) {
 pa_log_info("Ensuring device is not saved for stream %s.", 
name);
 /* If the device is not valid we should make sure the
-   save flag is cleared as the user may have specifically
+   preferred_sink is cleared as the user may have 
specifically
removed the sink element from the rule. */
-si->save_sink = false;
+pa_xfree(si->preferred_sink);
+si->preferred_sink = NULL;
 /* This is cheating a bit. The sink input itself has not 
changed
but the rules governing its routing have, so we fire 
this event
such that other routing modules (e.g. 
module-device-manager)
@@ -1962,6 +1963,8 @@ static void entry_apply(struct userdata *u, const char 
*name, struct entry *e) {
 } else if ((s = pa_namereg_get(u->core, e->device, 
PA_NAMEREG_SINK))) {
 pa_log_info("Restoring device for stream %s.", name);
 pa_sink_input_move_to(si, s, true);
+pa_xfree(si->pref

[pulseaudio-discuss] [PATCH v2 4/8] core: move sink-inputs conditionally when update default_sink

2019-01-16 Thread Hui Wang
When the default sink changes, the streams from the old default sink
should be moved to the new default sink, unless the preferred_sink
string is set to the old default sink and the active port of the old
default sink is not unavailable

Signed-off-by: Hui Wang 
---
 src/modules/dbus/iface-core.c   |  2 +-
 src/modules/module-default-device-restore.c |  2 +-
 src/modules/module-switch-on-connect.c  | 27 ++--
 src/pulsecore/cli-command.c |  2 +-
 src/pulsecore/core.c| 10 --
 src/pulsecore/core.h|  4 +--
 src/pulsecore/device-port.c |  2 +-
 src/pulsecore/protocol-native.c |  2 +-
 src/pulsecore/sink.c| 35 +++--
 src/pulsecore/sink.h|  6 
 10 files changed, 54 insertions(+), 38 deletions(-)

diff --git a/src/modules/dbus/iface-core.c b/src/modules/dbus/iface-core.c
index 5229c0467..9763480d2 100644
--- a/src/modules/dbus/iface-core.c
+++ b/src/modules/dbus/iface-core.c
@@ -721,7 +721,7 @@ static void handle_set_fallback_sink(DBusConnection *conn, 
DBusMessage *msg, DBu
 return;
 }
 
-pa_core_set_configured_default_sink(c->core, 
pa_dbusiface_device_get_sink(fallback_sink)->name);
+pa_core_set_configured_default_sink(c->core, 
pa_dbusiface_device_get_sink(fallback_sink)->name, true);
 
 pa_dbus_send_empty_reply(conn, msg);
 }
diff --git a/src/modules/module-default-device-restore.c 
b/src/modules/module-default-device-restore.c
index c4dbad99f..33e74c071 100644
--- a/src/modules/module-default-device-restore.c
+++ b/src/modules/module-default-device-restore.c
@@ -69,7 +69,7 @@ static void load(struct userdata *u) {
 pa_log_warn("Invalid sink name: %s", ln);
 else {
 pa_log_info("Restoring default sink '%s'.", ln);
-pa_core_set_configured_default_sink(u->core, ln);
+pa_core_set_configured_default_sink(u->core, ln, false);
 }
 
 } else if (errno != ENOENT)
diff --git a/src/modules/module-switch-on-connect.c 
b/src/modules/module-switch-on-connect.c
index f0cb29a7c..3ceac8b4f 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -54,9 +54,6 @@ struct userdata {
 };
 
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
-pa_sink_input *i;
-uint32_t idx;
-pa_sink *old_default_sink;
 const char *s;
 struct userdata *u = userdata;
 
@@ -88,7 +85,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 
 /* No default sink, nothing to move away, just set the new default */
 if (!c->default_sink) {
-pa_core_set_configured_default_sink(c, sink->name);
+pa_core_set_configured_default_sink(c, sink->name, false);
 return PA_HOOK_OK;
 }
 
@@ -103,28 +100,8 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 return PA_HOOK_OK;
 }
 
-old_default_sink = c->default_sink;
-
 /* Actually do the switch to the new sink */
-pa_core_set_configured_default_sink(c, sink->name);
-
-/* Now move all old inputs over */
-if (pa_idxset_size(old_default_sink->inputs) <= 0) {
-pa_log_debug("No sink inputs to move away.");
-return PA_HOOK_OK;
-}
-
-PA_IDXSET_FOREACH(i, old_default_sink->inputs, idx) {
-if (pa_safe_streq(i->sink->name, i->preferred_sink) || 
!PA_SINK_INPUT_IS_LINKED(i->state))
-continue;
-
-if (pa_sink_input_move_to(i, 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)), 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)), sink->name);
-}
+pa_core_set_configured_default_sink(c, sink->name, false);
 
 return PA_HOOK_OK;
 }
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 5205349bd..cc7addaa1 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -1036,7 +1036,7 @@ static int pa_cli_command_sink_default(pa_core *c, 
pa_tokenizer *t, pa_strbuf *b
 }
 
 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
-pa_core_set_configured_default_sink(c, s->name);
+pa_core_set_configured_default_sink(c, s->name, true);
 else
 pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
 
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index cc4a6f38b..084a9f54b 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsec

[pulseaudio-discuss] [PATCH v2 3/8] sink-input: clear the preferred_sink if it is default_sink

2019-01-16 Thread Hui Wang
When the user moves a stream to the current default sink, the
preferred_sink should be set to NULL and module-stream-restore
should clear the routing for that stream in the stream database. From
that point on the stream will be always routed to the default sink.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 19 ++-
 src/pulsecore/sink-input.c  |  6 +-
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index 366f1a5a8..142d1e3b4 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1311,13 +1311,22 @@ static void subscribe_callback(pa_core *c, 
pa_subscription_event_type_t t, uint3
 mute_updated = !created_new_entry && (!old->muted_valid || 
entry->muted != old->muted);
 }
 
-if (sink_input->preferred_sink != NULL) {
+if (sink_input->preferred_sink != NULL || !created_new_entry) {
 pa_xfree(entry->device);
-entry->device = pa_xstrdup(sink_input->preferred_sink);
-entry->device_valid = true;
+if (sink_input->preferred_sink != NULL) {
+entry->device = pa_xstrdup(sink_input->preferred_sink);
+entry->device_valid = true;
+} else {
+entry->device = NULL;
+entry->device_valid = false;
+}
 
-device_updated = !created_new_entry && (!old->device_valid || 
!pa_streq(entry->device, old->device));
-if (sink_input->sink->card) {
+device_updated = !created_new_entry && 
!pa_safe_streq(entry->device, old->device);
+if (entry->device_valid == false) {
+pa_xfree(entry->card);
+entry->card = NULL;
+entry->card_valid = false;
+} else {
 pa_xfree(entry->card);
 entry->card = pa_xstrdup(sink_input->sink->card->name);
 entry->card_valid = true;
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 4dbc0cdef..f87c1f49f 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -1925,8 +1925,12 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink 
*dest, bool save) {
save the preferred_sink */
 if (save) {
 pa_xfree(i->preferred_sink);
-i->preferred_sink = pa_xstrdup(dest->name);
+if (dest == dest->core->default_sink)
+i->preferred_sink = NULL;
+else
+i->preferred_sink = pa_xstrdup(dest->name);
 }
+
 pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
 
 PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
-- 
2.17.1

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


[pulseaudio-discuss] [PATCH v2 5/8] sink: move streams to new appeared sinks if they prefer these sinks

2019-01-16 Thread Hui Wang
When a new sink appears, all streams that have their preferred_sink
set to the new sink should be moved to the new sink.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 53 -
 src/pulsecore/core.c| 28 +++
 src/pulsecore/core.h|  2 ++
 src/pulsecore/sink.c|  2 ++
 4 files changed, 32 insertions(+), 53 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index 142d1e3b4..c7a5f228a 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -95,7 +95,6 @@ struct userdata {
 *sink_input_fixate_hook_slot,
 *source_output_new_hook_slot,
 *source_output_fixate_hook_slot,
-*sink_put_hook_slot,
 *source_put_hook_slot,
 *sink_unlink_hook_slot,
 *source_unlink_hook_slot,
@@ -1639,57 +1638,6 @@ static pa_hook_result_t 
source_output_fixate_hook_callback(pa_core *c, pa_source
 return PA_HOOK_OK;
 }
 
-static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, 
struct userdata *u) {
-pa_sink_input *si;
-uint32_t idx;
-
-pa_assert(c);
-pa_assert(sink);
-pa_assert(u);
-pa_assert(u->on_hotplug && u->restore_device);
-
-PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
-char *name;
-struct entry *e;
-
-if (si->sink == sink)
-continue;
-
-if (pa_safe_streq(si->sink->name, si->preferred_sink))
-continue;
-
-/* Skip this if it is already in the process of being moved
- * anyway */
-if (!si->sink)
-continue;
-
-/* Skip this sink input if it is connecting a filter sink to
- * the master */
-if (si->origin_sink)
-continue;
-
-/* 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 */
-if (!PA_SINK_INPUT_IS_LINKED(si->state))
-continue;
-
-if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", 
IDENTIFICATION_PROPERTY)))
-continue;
-
-if ((e = entry_read(u, name))) {
-if (e->device_valid && pa_streq(e->device, sink->name))
-pa_sink_input_move_to(si, sink, true);
-
-entry_free(e);
-}
-
-pa_xfree(name);
-}
-
-return PA_HOOK_OK;
-}
-
 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source 
*source, struct userdata *u) {
 pa_source_output *so;
 uint32_t idx;
@@ -2467,7 +2415,6 @@ int pa__init(pa_module*m) {
 
 if (restore_device && on_hotplug) {
 /* A little bit earlier than module-intended-roles ... */
-pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PUT], 
PA_HOOK_LATE, (pa_hook_cb_t) sink_put_hook_callback, u);
 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], 
PA_HOOK_LATE, (pa_hook_cb_t) source_put_hook_callback, u);
 }
 
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 084a9f54b..a66f3212f 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -517,6 +517,34 @@ void pa_core_rttime_restart(pa_core *c, pa_time_event *e, 
pa_usec_t usec) {
 c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, true));
 }
 
+void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, 
pa_sink *s) {
+pa_sink_input *si;
+uint32_t idx;
+
+pa_assert(c);
+pa_assert(s);
+
+PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
+if (si->sink == s)
+continue;
+
+/* Skip this sink input if it is connecting a filter sink to
+ * the master */
+if (si->origin_sink)
+continue;
+
+/* 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 */
+if (!PA_SINK_INPUT_IS_LINKED(si->state))
+continue;
+
+if (pa_safe_streq(si->preferred_sink, s->name))
+pa_sink_input_move_to(si, s, false);
+}
+
+}
+
 /* Helper macro to reduce repetition in pa_suspend_cause_to_string().
  * Parameters:
  *   char *p: the current position in the write buffer
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 82573f001..b61124854 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -278,4 +278,6 @@ static const size_t PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE =
  * provided buffer. The same buffer is the return value of this function. */
 const char *pa_suspend_cause_to_string(pa_suspend_cause_t cause, char 
buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE]);
 
+void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, 
pa_sink *s);
+
 #endif
dif

[pulseaudio-discuss] [PATCH v2 6/8] device-port: moving streams due to changing the status of active_port

2019-01-16 Thread Hui Wang
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 a sink changes state from unavailable, all
streams that have their preferred_sink set to this sink should be moved
to this sink.

Signed-off-by: Hui Wang 
---
 src/pulsecore/device-port.c | 30 ++
 src/pulsecore/device-port.h |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
index 464c3f8a2..49de33b9e 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,22 @@ 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_device_port_get_sink(p);
+if (!sink)
+return;
+if (p != sink->active_port)
+return;
+switch (p->direction) {
+case PA_DIRECTION_OUTPUT:
+if (sink->active_port->available == PA_AVAILABLE_NO)
+pa_sink_move_streams_to_default_sink(p->core, sink, false);
+else
+
pa_core_move_streams_to_newly_available_preferred_sink(p->core, sink);
+break;
+case PA_DIRECTION_INPUT:
+break;
+}
 }
 }
 
@@ -224,3 +241,16 @@ pa_device_port *pa_device_port_find_best(pa_hashmap *ports)
 
 return best;
 }
+
+pa_sink *pa_device_port_get_sink(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/device-port.h b/src/pulsecore/device-port.h
index fbdce1aa0..41988e5bb 100644
--- a/src/pulsecore/device-port.h
+++ b/src/pulsecore/device-port.h
@@ -87,4 +87,6 @@ void pa_device_port_set_preferred_profile(pa_device_port *p, 
const char *new_pp)
 
 pa_device_port *pa_device_port_find_best(pa_hashmap *ports);
 
+pa_sink *pa_device_port_get_sink(pa_device_port *p);
+
 #endif
-- 
2.17.1

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


[pulseaudio-discuss] [PATCH v2 8/8] stream-restore: skip entries setting action from gnome-control-center

2019-01-16 Thread Hui Wang
When users select an output device from gnome-control-center UI, the
sink of this output device will be set to the configured_default_sink
and the default_sink, these actions are expected, but after these
actions, the gnome-control-center will call extension_cb() to modify
the entries in the database, let all stream entries to bind the sink
users select, this is not correct since the sink is default_sink now.

This is a temp fix for this issue, after gnome-control-center fixes
this problem, this patch should be reverted.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index fd3acb5bd..b2691d384 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -2053,7 +2053,7 @@ static int extension_cb(pa_native_protocol *p, pa_module 
*m, pa_native_connectio
 }
 
 while (!pa_tagstruct_eof(t)) {
-const char *name, *device;
+const char *name, *device, *client_name;
 bool muted;
 struct entry *entry;
 #ifdef HAVE_DBUS
@@ -2094,7 +2094,17 @@ static int extension_cb(pa_native_protocol *p, pa_module 
*m, pa_native_connectio
 entry_free(entry);
 goto fail;
 }
-
+/* When users select an output device from 
gnome-control-center UI, the gnome-control-center will change all entries
+ * in the database to bind the sink of this output device, 
this is not correct since at this moment, the sink is
+ * default_sink and we shouldn't bind a stream to default_sink 
via preferred_sink or database.
+ * After gnome-control-center fix the issue, let us remove 
this code */
+client_name = 
pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, 
PA_PROP_APPLICATION_PROCESS_BINARY));
+if (pa_safe_streq(client_name, "gnome-control-center")) {
+if (entry->device_valid && m->core->default_sink && 
pa_safe_streq(device, m->core->default_sink->name)) {
+entry_free(entry);
+goto fail;
+}
+}
 #ifdef HAVE_DBUS
 old = entry_read(u, name);
 #endif
-- 
2.17.1

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


[pulseaudio-discuss] [PATCH v2 7/8] sink: move the streams to the default_sink when the sink is unlinked

2019-01-16 Thread Hui Wang
When a sink is unlinked, all streams of this sink are moved to
default_sink, this action is implemented in the core rather than
modules now.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 50 -
 src/pulsecore/sink.c|  3 ++
 2 files changed, 3 insertions(+), 50 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index c7a5f228a..fd3acb5bd 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -96,7 +96,6 @@ struct userdata {
 *source_output_new_hook_slot,
 *source_output_fixate_hook_slot,
 *source_put_hook_slot,
-*sink_unlink_hook_slot,
 *source_unlink_hook_slot,
 *connection_unlink_hook_slot;
 pa_time_event *save_time_event;
@@ -1691,54 +1690,6 @@ static pa_hook_result_t source_put_hook_callback(pa_core 
*c, pa_source *source,
 return PA_HOOK_OK;
 }
 
-static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, 
struct userdata *u) {
-pa_sink_input *si;
-uint32_t idx;
-
-pa_assert(c);
-pa_assert(sink);
-pa_assert(u);
-pa_assert(u->on_rescue && u->restore_device);
-
-/* There's no point in doing anything if the core is shut down anyway */
-if (c->state == PA_CORE_SHUTDOWN)
-return PA_HOOK_OK;
-
-PA_IDXSET_FOREACH(si, sink->inputs, idx) {
-char *name;
-struct entry *e;
-
-if (!si->sink)
-continue;
-
-/* Skip this sink input if it is connecting a filter sink to
- * the master */
-if (si->origin_sink)
-continue;
-
-if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", 
IDENTIFICATION_PROPERTY)))
-continue;
-
-if ((e = entry_read(u, name))) {
-
-if (e->device_valid) {
-pa_sink *d;
-
-if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) &&
-d != sink &&
-PA_SINK_IS_LINKED(d->state))
-pa_sink_input_move_to(si, d, true);
-}
-
-entry_free(e);
-}
-
-pa_xfree(name);
-}
-
-return PA_HOOK_OK;
-}
-
 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source 
*source, struct userdata *u) {
 pa_source_output *so;
 uint32_t idx;
@@ -2420,7 +2371,6 @@ int pa__init(pa_module*m) {
 
 if (restore_device && on_rescue) {
 /* A little bit earlier than module-intended-roles, 
module-rescue-streams, ... */
-pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], 
PA_HOOK_LATE, (pa_hook_cb_t) sink_unlink_hook_callback, u);
 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], 
PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, u);
 }
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index cf43a78e8..d7973b7c9 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -745,6 +745,9 @@ void pa_sink_unlink(pa_sink* s) {
 
 linked = PA_SINK_IS_LINKED(s->state);
 
+if (linked)
+pa_sink_move_streams_to_default_sink(s->core, s, false);
+
 if (linked)
 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
 
-- 
2.17.1

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


Re: [pulseaudio-discuss] [alsa-devel] [PATCH] ALSA: hda: set the 2nd headphone's name to be Headphone2

2019-03-06 Thread Hui Wang
On 2019/3/6 下午4:10, Jaroslav Kysela wrote:
> Dne 06. 03. 19 v 1:23 Hui Wang napsal(a):
>> On 2019/3/6 上午4:00, Jaroslav Kysela wrote:
>>> Dne 05. 03. 19 v 15:09 Hui Wang napsal(a):
>>>> Recently I saw two Headphones on some HP machines, the 1st Headphone
>>>> comes from the Front Headphone Jack, the 2nd one comes from the Front
>>>> Headset Jack, and the current HDA driver will set the same name to
>>>> them and with different index, just like below:
>>>> 'Headphone Playback Volume'
>>>> 'Headphone Playback Switch'
>>>> 'Headphone Playback Volume' index 1
>>>> 'Headphone Playback Switch' index 1
>>>> 'Front Headphone Jack'
>>>> 'Front Headphone Jack' index 1
>>>>
>>>> This can't be handled by pulseaudio, and pulseaduio already has a
>>>> path analog-output-headphones-2.conf to handle the 2nd headphone, now
>>>> we set the 2nd headphone's name to "Headphone2", leave the other
>>>> headphones unchanged.
>>>>
>>>> The change of hda_auto_parser.c will change the name of Jack.
>>>>
>>>> The change of hda_generic.c will change the name of Volume and Switch.
>>> NAK. I'm afraid, but you're trying to revert the change from 2009:
>>>
>>> commit 668b9652be33510a2a42b290dd335d34d38e2068
>>> Author: Takashi Iwai 
>>> Date:   Fri Mar 6 10:13:24 2009 +0100
>>>
>>>   ALSA: hda - Create multiple HP / speaker controls with index
>>>
>>>   Create multiple "Headphone" and "Speaker" controls with non-zero index
>>>   numbers instead of "Headphone2", etc.
>>>
>>>   Signed-off-by: Takashi Iwai 
>>>
>>> I think that PA should be fixed instead try to fix the drivers. The
>>> indexes are exactly designed to distinguish the multiple similar I/O.
>>>
>>> I cannot find any other driver which uses the Headphone2 control name.
>>>
>>> Jaroslav
>>>
>> OK, got it.  I tried to add the index to the pulseaudio in Jan, but not
>> finish yet.  If you have time, please take a look at my patches and make
>> a comment on them.
>>
>> https://lists.freedesktop.org/archives/pulseaudio-discuss/2019-January/030761.html
> Your changes seem as a good start. Unfortunately, I don't know PA
> internals, so it would be better, if a PA developer can review those
> patches.
>
>   Jaroslav

OK, Thanks.



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

Re: [pulseaudio-discuss] [PATCH 1/3] alsa: fix infinite loop with Intel HDMI LPE

2019-03-25 Thread Hui Wang
On 2017/12/28 下午6:09, Tanu Kaskinen wrote:
> The Intel HDMI LPE driver works in a peculiar way when the HDMI cable is
> not plugged in: any written audio is immediately discarded and underrun
> is reported. That resulted in an infinite loop, because PulseAudio tried
> to keep the buffer filled, which was futile since the written audio was
> immediately consumed/discarded.
>
> This patch adds special handling for the LPE driver: if the active port
> of the sink is unavailable, the sink suspends itself. A new suspend
> cause is added: PA_SUSPEND_UNAVAILABLE.
>
> BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=100488
> ---
>  src/modules/alsa/alsa-mixer.h   |  1 +
>  src/modules/alsa/alsa-sink.c| 22 ++
>  src/modules/alsa/module-alsa-card.c | 34 ++
>  src/pulsecore/core.h|  1 +
>  4 files changed, 58 insertions(+)
>
> diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
> index 4ebf1922b..3577f435f 100644
> --- a/src/modules/alsa/alsa-mixer.h
> +++ b/src/modules/alsa/alsa-mixer.h
> @@ -364,6 +364,7 @@ int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata 
> *pd, snd_mixer_t *mixer,
>  struct pa_alsa_port_data {
>  pa_alsa_path *path;
>  pa_alsa_setting *setting;
> +bool suspend_when_unavailable;
>  };
>  
>  void pa_alsa_add_ports(void *sink_or_source_new_data, pa_alsa_path_set *ps, 
> pa_card *card);
> diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
> index 7936cfaca..a80caab2e 100644
> --- a/src/modules/alsa/alsa-sink.c
> +++ b/src/modules/alsa/alsa-sink.c
> @@ -1527,6 +1527,11 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port 
> *p) {
>  s->set_volume(s);
>  }
>  
> +if (data->suspend_when_unavailable && p->available == PA_AVAILABLE_NO)
> +pa_sink_suspend(s, true, PA_SUSPEND_UNAVAILABLE);
> +else

Hi Tanu,

We tried to backport this patch to pulseaudio-8.0 (for ubuntu linux
16.04),  but after applying this patch, all audio jacks (like headphone,
line-in/line-out) can't work anymore. If we change the above line as
below, the problem will disappear.

else (data->suspend_when_unavailable)

In theory, if a port is not set suspend_when_unavailable, the port
should not be changed by this patch. I don't know if it is correct or
not,  could you please take a look at it?

Thanks,

Hui.




> +pa_sink_suspend(s, false, PA_SUSPEND_UNAVAILABLE);
> +
>  return 0;
>  }
>  
> @@ -2460,6 +2465,23 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs 
> *ma, const char*driver, pa_ca
>  if (profile_set)
>  pa_alsa_profile_set_free(profile_set);
>  
> +/* Suspend if necessary. FIXME: It would be better to start suspended, 
> but
> + * that would require some core changes. It's possible to set
> + * pa_sink_new_data.suspend_cause, but that has to be done before the
> + * pa_sink_new() call, and we know if we need to suspend only after the
> + * pa_sink_new() call when the initial port has been chosen. Calling
> + * pa_sink_suspend() between pa_sink_new() and pa_sink_put() would
> + * otherwise work, but currently pa_sink_suspend() will crash if
> + * pa_sink_put() hasn't been called. */
> +if (u->sink->active_port) {
> +pa_alsa_port_data *port_data;
> +
> +port_data = PA_DEVICE_PORT_DATA(u->sink->active_port);
> +
> +if (port_data->suspend_when_unavailable && 
> u->sink->active_port->available == PA_AVAILABLE_NO)
> +pa_sink_suspend(u->sink, true, PA_SUSPEND_UNAVAILABLE);
> +}
> +
>  return u->sink;
>  
>  fail:
> diff --git a/src/modules/alsa/module-alsa-card.c 
> b/src/modules/alsa/module-alsa-card.c
> index 804b4f872..b193d40cc 100644
> --- a/src/modules/alsa/module-alsa-card.c
> +++ b/src/modules/alsa/module-alsa-card.c
> @@ -426,6 +426,22 @@ static int report_jack_state(snd_mixer_elem_t *melem, 
> unsigned int mask) {
>  if (tp->avail == PA_AVAILABLE_NO)
> pa_device_port_set_available(tp->port, tp->avail);
>  
> +for (tp = tports; tp->port; tp++) {
> +pa_alsa_port_data *data;
> +pa_sink *sink;
> +uint32_t idx;
> +
> +data = PA_DEVICE_PORT_DATA(tp->port);
> +
> +if (!data->suspend_when_unavailable)
> +continue;
> +
> +PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
> +if (sink->active_port == tp->port)
> +pa_sink_suspend(sink, tp->avail == PA_AVAILABLE_NO, 
> PA_SUSPEND_UNAVAILABLE);
> +}
> +}
> +
>  /* Update profile availabilities. The logic could be improved; for now we
>   * only set obviously unavailable profiles (those that contain only
>   * unavailable ports) to PA_AVAILABLE_NO and all others to
> @@ -836,6 +852,24 @@ int pa__init(pa_module *m) {
>  goto fail;
>  }
>  
> +/* The Intel HDMI LPE driver needs some special handling. When the HDMI
> + * cable is not plugged in, tryi

Re: [pulseaudio-discuss] [PATCH 1/3] alsa: fix infinite loop with Intel HDMI LPE

2019-03-26 Thread Hui Wang
On 2019/3/27 上午1:44, Tanu Kaskinen wrote:
> On Tue, 2019-03-26 at 13:17 +0800, Hui Wang wrote:
>> On 2017/12/28 下午6:09, Tanu Kaskinen wrote:
>>> The Intel HDMI LPE driver works in a peculiar way when the HDMI cable is
>>> not plugged in: any written audio is immediately discarded and underrun
>>> is reported. That resulted in an infinite loop, because PulseAudio tried
>>> to keep the buffer filled, which was futile since the written audio was
>>> immediately consumed/discarded.
>>>
>>> This patch adds special handling for the LPE driver: if the active port
>>> of the sink is unavailable, the sink suspends itself. A new suspend
>>> cause is added: PA_SUSPEND_UNAVAILABLE.
>>>
>>> BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=100488
>>> ---
>>>  src/modules/alsa/alsa-mixer.h   |  1 +
>>>  src/modules/alsa/alsa-sink.c| 22 ++
>>>  src/modules/alsa/module-alsa-card.c | 34 ++
>>>  src/pulsecore/core.h|  1 +
>>>  4 files changed, 58 insertions(+)
>>>
>>> diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
>>> index 4ebf1922b..3577f435f 100644
>>> --- a/src/modules/alsa/alsa-mixer.h
>>> +++ b/src/modules/alsa/alsa-mixer.h
>>> @@ -364,6 +364,7 @@ int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata 
>>> *pd, snd_mixer_t *mixer,
>>>  struct pa_alsa_port_data {
>>>  pa_alsa_path *path;
>>>  pa_alsa_setting *setting;
>>> +bool suspend_when_unavailable;
>>>  };
>>>  
>>>  void pa_alsa_add_ports(void *sink_or_source_new_data, pa_alsa_path_set 
>>> *ps, pa_card *card);
>>> diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
>>> index 7936cfaca..a80caab2e 100644
>>> --- a/src/modules/alsa/alsa-sink.c
>>> +++ b/src/modules/alsa/alsa-sink.c
>>> @@ -1527,6 +1527,11 @@ static int sink_set_port_cb(pa_sink *s, 
>>> pa_device_port *p) {
>>>  s->set_volume(s);
>>>  }
>>>  
>>> +if (data->suspend_when_unavailable && p->available == PA_AVAILABLE_NO)
>>> +pa_sink_suspend(s, true, PA_SUSPEND_UNAVAILABLE);
>>> +else
>> Hi Tanu,
>>
>> We tried to backport this patch to pulseaudio-8.0 (for ubuntu linux
>> 16.04),  but after applying this patch, all audio jacks (like headphone,
>> line-in/line-out) can't work anymore. If we change the above line as
>> below, the problem will disappear.
>>
>> else (data->suspend_when_unavailable)
>>
>> In theory, if a port is not set suspend_when_unavailable, the port
>> should not be changed by this patch. I don't know if it is correct or
>> not,  could you please take a look at it?
> I don't think your change is correct. This code is run when the sink
> changes its port, so there are two ports involved: the old port and the
> new one. If the old port caused the sink to be suspended with the
> UNAVAILABLE cause, and the new port doesn't require suspending when
> it's unavailable, then with your change the sink doesn't get
> unsuspended when it should.
>
> In practice your change should be harmless, though, because all ports
> on a Intel HDMI LPE card will have the suspend_when_unavailable flag
> set, and on other cards the flag is never set.
>
> You didn't specify what the exact problem with headphones etc. is. Is
> there an assertion error? I would guess that you're running into this
> bug that was introduced by the HDMI LPE fixes:
> https://bugs.freedesktop.org/show_bug.cgi?id=104761
>
> Fixing that bug involved rewriting much of the device suspending and
> state changing code. I don't know if you want to backport those patches
> if your small change seems to make things work well enough, but here's
> a list of relevant commits (oldest first, I'm not 100% that this is a
> complete list):
>
> 3da0de5418b29c90974d0d3e2198c471c39d229f
> 6ed37aeef28708f8da34a16c7035fa1331fa13cb
> d6e39b5e891c767dd42c369d9f118560b8bb24ae
> 7f201b1fd419b91a226d23ee1e216661ae082dcf
> 2dff0d6a6a4df2aab6f36212b705489d5af42835
> 7f09164ed7979210adcdb7674b9d6217fd44ed66
> f6fe411b32c0cf5932fb4f169f5288c76bc6923d
> 0fad369ceb18a8e275e8f74f10f784e0d7476dfb
> 73b8a57078b94033edf84de2fc0cfbe344c10dcd
> b2537a8f38ad71e4dee57263310235abdf2b95a4
> ad0616d4c91de52b7cb69e6222efe96961755482
> ad15e6e50e737fb55a87bb7def22332f774abce9

Ok, got it. I will investigate these commits.

Thanks,

Hui.



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

[pulseaudio-discuss] [PATCH] stream-restore: Don't restore if the active_port is PA_AVAILABLE_NO

2019-05-14 Thread Hui Wang
We met two problems recently, one happened on a Lenovo machine with
dual analogue codecs, the other happened on a Dell machine with
a digital mic directly connected to PCH. The two problems are
basically same, there is an internal mic and an external mic, the
internal mic always shows up in the gnome-control-center, the external
mic only shows up when it is plugged. After the external mic is
plugged and users select it from gnome-control-center, the
gnome-control-center will read all saved streams through extension_cb,
and bind the source of external mic to all streams, after that the
apps only record sound via the source of external mic, after the
external mic is unplugged, the internal mic will automatically be
selected since it is the only left input device in the
gnome-control-center, since users don't select it, all streams are
still bond the source of external mic. When users record sound via
apps, they can't record any sound even the default_source is the
source of internal mic and the internal mic is selected in the UI.

It is very common that a machine has internal mic and external mic,
but this problem didn't expose before, that is because both internal
mic and external mic belong to one source, but for those two
machines, the internal mic belongs to one source, while the external
mic belongs to another source (they are in differnt codecs or one is
in the codec and the other is from PCH),

To fix it with a mininal change, we just check if the active_port is
PA_AVAILABLE_NO or not when building a new stream, if it is, don't
restore the device to the new built stream, let pa_source_output_new()
decide the source device for this stream.

And we also do the same change to sink_input.

This change only affects the new built streams, it will not change
the database, so the users' preference is still saved in the database,
after the active_port is not PA_AVAILABLE_NO, the new streams will
still restore to the preferred device.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index 6c7b4c75b..cbef4782d 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1459,8 +1459,10 @@ static pa_hook_result_t 
sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
same time, in which case we want to make sure we don't
interfere with that */
 if (s && PA_SINK_IS_LINKED(s->state))
-if (pa_sink_input_new_data_set_sink(new_data, s, true, false))
-pa_log_info("Restoring device for stream %s.", name);
+if (!s->active_port || s->active_port->available != 
PA_AVAILABLE_NO) {
+if (pa_sink_input_new_data_set_sink(new_data, s, true, false))
+pa_log_info("Restoring device for stream %s.", name);
+   }
 
 entry_free(e);
 }
@@ -1562,8 +1564,10 @@ static pa_hook_result_t 
source_output_new_hook_callback(pa_core *c, pa_source_ou
same time, in which case we want to make sure we don't
interfere with that */
 if (s && PA_SOURCE_IS_LINKED(s->state)) {
-pa_log_info("Restoring device for stream %s.", name);
-pa_source_output_new_data_set_source(new_data, s, true, false);
+if (!s->active_port || s->active_port->available != 
PA_AVAILABLE_NO) {
+pa_log_info("Restoring device for stream %s.", name);
+pa_source_output_new_data_set_source(new_data, s, true, false);
+   }
 }
 
 entry_free(e);
-- 
2.17.1

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

Re: [pulseaudio-discuss] [PATCH v2 2/8] sink-input: add a new API pa_sink_input_set_preferred_sink

2019-07-02 Thread Hui Wang


On 2019/6/30 下午6:44, Georg Chini wrote:

Sorry for the late feedback.

On 17.01.19 07:53, Hui Wang wrote:

If the sink here is NULL, that means users want to clear the
preferred_sink and move the sink-input to the default_sink, otherwise
set the preferred_sink to the sink->name and move the sink-input to
the sink. After that fire the sink_input_change event.

After adding this API, we can use this API to simplify the entry_apply
in the module-stream-restore.c.

Signed-off-by: Hui Wang 
---
  src/modules/module-stream-restore.c | 10 ++
  src/pulsecore/sink-input.c  | 14 ++
  src/pulsecore/sink-input.h  |  2 ++
  3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c

index a8c6a42c5..366f1a5a8 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1953,18 +1953,12 @@ static void entry_apply(struct userdata *u, 
const char *name, struct entry *e) {
 preferred_sink is cleared as the user may 
have specifically

 removed the sink element from the rule. */
  pa_xfree(si->preferred_sink);
-    si->preferred_sink = NULL;
-    /* This is cheating a bit. The sink input itself 
has not changed
-   but the rules governing its routing have, so 
we fire this event
-   such that other routing modules (e.g. 
module-device-manager)
-   will pick up the change and reapply their 
routing */
-    pa_subscription_post(si->core, 
PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, 
si->index);

+    pa_sink_input_set_preferred_sink(si, NULL);
  }
  } else if ((s = pa_namereg_get(u->core, e->device, 
PA_NAMEREG_SINK))) {

  pa_log_info("Restoring device for stream %s.", name);
-    pa_sink_input_move_to(si, s, true);
  pa_xfree(si->preferred_sink);
-    si->preferred_sink = pa_xstrdup(s->name);
+    pa_sink_input_set_preferred_sink(si, s);
  }
  }
  }
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index f41eacf07..4dbc0cdef 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -2416,3 +2416,17 @@ void 
pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume 
*ratio
   pa_cvolume_snprint_verbose(old_ratio_str, 
sizeof(old_ratio_str), &old_ratio, &i->channel_map, true),
   pa_cvolume_snprint_verbose(new_ratio_str, 
sizeof(new_ratio_str), ratio, &i->channel_map, true));

  }
+
+/* Called from the main thread. */
+void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s) {
+    pa_assert(i);
+
+    if (s) {
+    i->preferred_sink = pa_xstrdup(s->name);
+    pa_sink_input_move_to(i, s, true);
+    } else {
+    i->preferred_sink = NULL;
+    pa_sink_input_move_to(i, i->core->default_sink, true);
+    }
+    pa_subscription_post(i->core, 
PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, 
i->index);

+}
You do not have to send the subscription event here, 
pa_sink_input_finish_move()

will already send the event.


OK, got it.

Thanks,

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

Re: [pulseaudio-discuss] [PATCH v2 3/8] sink-input: clear the preferred_sink if it is default_sink

2019-07-02 Thread Hui Wang


On 2019/6/30 下午6:47, Georg Chini wrote:

On 17.01.19 07:53, Hui Wang wrote:

When the user moves a stream to the current default sink, the
preferred_sink should be set to NULL and module-stream-restore
should clear the routing for that stream in the stream database. From
that point on the stream will be always routed to the default sink.

Signed-off-by: Hui Wang 
---
  src/modules/module-stream-restore.c | 19 ++-
  src/pulsecore/sink-input.c  |  6 +-
  2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c

index 366f1a5a8..142d1e3b4 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1311,13 +1311,22 @@ static void subscribe_callback(pa_core *c, 
pa_subscription_event_type_t t, uint3
  mute_updated = !created_new_entry && (!old->muted_valid 
|| entry->muted != old->muted);

  }
  -    if (sink_input->preferred_sink != NULL) {
+    if (sink_input->preferred_sink != NULL || !created_new_entry) {
  pa_xfree(entry->device);
-    entry->device = pa_xstrdup(sink_input->preferred_sink);
-    entry->device_valid = true;
+    if (sink_input->preferred_sink != NULL) {
+    entry->device = pa_xstrdup(sink_input->preferred_sink);
+    entry->device_valid = true;
+    } else {
+    entry->device = NULL;
+    entry->device_valid = false;
+    }
  -    device_updated = !created_new_entry && 
(!old->device_valid || !pa_streq(entry->device, old->device));

-    if (sink_input->sink->card) {
+    device_updated = !created_new_entry && 
!pa_safe_streq(entry->device, old->device);

+    if (entry->device_valid == false) {
+    pa_xfree(entry->card);
+    entry->card = NULL;
+    entry->card_valid = false;
+    } else {
  pa_xfree(entry->card);
  entry->card = 
pa_xstrdup(sink_input->sink->card->name);

  entry->card_valid = true;
You still need to check sink_input->sink->card. The virtual sinks 
don't have a card,

so it may well be that the device is valid but there is no card.


Ok, will add it.

Thanks.

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

Re: [pulseaudio-discuss] [PATCH v2 7/8] sink: move the streams to the default_sink when the sink is unlinked

2019-07-02 Thread Hui Wang


On 2019/6/30 下午8:15, Georg Chini wrote:

On 17.01.19 07:53, Hui Wang wrote:

When a sink is unlinked, all streams of this sink are moved to
default_sink, this action is implemented in the core rather than
modules now.

Signed-off-by: Hui Wang 
---
  src/modules/module-stream-restore.c | 50 -
  src/pulsecore/sink.c    |  3 ++
  2 files changed, 3 insertions(+), 50 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c

index c7a5f228a..fd3acb5bd 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -96,7 +96,6 @@ struct userdata {
  *source_output_new_hook_slot,
  *source_output_fixate_hook_slot,
  *source_put_hook_slot,
-    *sink_unlink_hook_slot,
  *source_unlink_hook_slot,
  *connection_unlink_hook_slot;
  pa_time_event *save_time_event;
@@ -1691,54 +1690,6 @@ static pa_hook_result_t 
source_put_hook_callback(pa_core *c, pa_source *source,

  return PA_HOOK_OK;
  }
  -static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, 
pa_sink *sink, struct userdata *u) {

-    pa_sink_input *si;
-    uint32_t idx;
-
-    pa_assert(c);
-    pa_assert(sink);
-    pa_assert(u);
-    pa_assert(u->on_rescue && u->restore_device);
-
-    /* There's no point in doing anything if the core is shut down 
anyway */

-    if (c->state == PA_CORE_SHUTDOWN)
-    return PA_HOOK_OK;
-
-    PA_IDXSET_FOREACH(si, sink->inputs, idx) {
-    char *name;
-    struct entry *e;
-
-    if (!si->sink)
-    continue;
-
-    /* Skip this sink input if it is connecting a filter sink to
- * the master */
-    if (si->origin_sink)
-    continue;
-
-    if (!(name = pa_proplist_get_stream_group(si->proplist, 
"sink-input", IDENTIFICATION_PROPERTY)))

-    continue;
-
-    if ((e = entry_read(u, name))) {
-
-    if (e->device_valid) {
-    pa_sink *d;
-
-    if ((d = pa_namereg_get(c, e->device, 
PA_NAMEREG_SINK)) &&

-    d != sink &&
-    PA_SINK_IS_LINKED(d->state))
-    pa_sink_input_move_to(si, d, true);
-    }
-
-    entry_free(e);
-    }
-
-    pa_xfree(name);
-    }
-
-    return PA_HOOK_OK;
-}
-
  static pa_hook_result_t source_unlink_hook_callback(pa_core *c, 
pa_source *source, struct userdata *u) {

  pa_source_output *so;
  uint32_t idx;
@@ -2420,7 +2371,6 @@ int pa__init(pa_module*m) {
    if (restore_device && on_rescue) {
  /* A little bit earlier than module-intended-roles, 
module-rescue-streams, ... */
-    pa_module_hook_connect(m, 
&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, 
(pa_hook_cb_t) sink_unlink_hook_callback, u);
  pa_module_hook_connect(m, 
&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, 
(pa_hook_cb_t) source_unlink_hook_callback, u);

  }
  diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index cf43a78e8..d7973b7c9 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -745,6 +745,9 @@ void pa_sink_unlink(pa_sink* s) {
    linked = PA_SINK_IS_LINKED(s->state);
  +    if (linked)
+    pa_sink_move_streams_to_default_sink(s->core, s, false);
+


This is called too early. It might be the current default sink that we 
are unlinking.


Right, will move it after the:

    pa_core_update_default_sink(s->core);




  if (linked)
pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);





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

[pulseaudio-discuss] [PATCH v3 3/8] sink-input: clear the preferred_sink if it is default_sink

2019-08-17 Thread Hui Wang
When the user moves a stream to the current default sink, the
preferred_sink should be set to NULL and module-stream-restore
should clear the routing for that stream in the stream database. From
that point on the stream will be always routed to the default sink.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 19 ++-
 src/pulsecore/sink-input.c  |  6 +-
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index c8bc02ecd..0d3f9d8ac 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1311,13 +1311,22 @@ static void subscribe_callback(pa_core *c, 
pa_subscription_event_type_t t, uint3
 mute_updated = !created_new_entry && (!old->muted_valid || 
entry->muted != old->muted);
 }
 
-if (sink_input->preferred_sink != NULL) {
+if (sink_input->preferred_sink != NULL || !created_new_entry) {
 pa_xfree(entry->device);
-entry->device = pa_xstrdup(sink_input->preferred_sink);
-entry->device_valid = true;
+if (sink_input->preferred_sink != NULL) {
+entry->device = pa_xstrdup(sink_input->preferred_sink);
+entry->device_valid = true;
+} else {
+entry->device = NULL;
+entry->device_valid = false;
+}
 
-device_updated = !created_new_entry && (!old->device_valid || 
!pa_streq(entry->device, old->device));
-if (sink_input->sink->card) {
+device_updated = !created_new_entry && 
!pa_safe_streq(entry->device, old->device);
+if (entry->device_valid == false) {
+pa_xfree(entry->card);
+entry->card = NULL;
+entry->card_valid = false;
+} else if (sink_input->sink->card) {
 pa_xfree(entry->card);
 entry->card = pa_xstrdup(sink_input->sink->card->name);
 entry->card_valid = true;
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 7521bed08..ee3083041 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -1927,8 +1927,12 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink 
*dest, bool save) {
save the preferred_sink */
 if (save) {
 pa_xfree(i->preferred_sink);
-i->preferred_sink = pa_xstrdup(dest->name);
+if (dest == dest->core->default_sink)
+i->preferred_sink = NULL;
+else
+i->preferred_sink = pa_xstrdup(dest->name);
 }
+
 pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
 
 PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
-- 
2.17.1

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

[pulseaudio-discuss] [PATCH v3 5/8] sink: move streams to new appeared sinks if they prefer these sinks

2019-08-17 Thread Hui Wang
When a new sink appears, all streams that have their preferred_sink
set to the new sink should be moved to the new sink.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 53 -
 src/pulsecore/core.c| 28 +++
 src/pulsecore/core.h|  2 ++
 src/pulsecore/sink.c|  2 ++
 4 files changed, 32 insertions(+), 53 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index 0d3f9d8ac..aa7bd38dc 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -95,7 +95,6 @@ struct userdata {
 *sink_input_fixate_hook_slot,
 *source_output_new_hook_slot,
 *source_output_fixate_hook_slot,
-*sink_put_hook_slot,
 *source_put_hook_slot,
 *sink_unlink_hook_slot,
 *source_unlink_hook_slot,
@@ -1643,57 +1642,6 @@ static pa_hook_result_t 
source_output_fixate_hook_callback(pa_core *c, pa_source
 return PA_HOOK_OK;
 }
 
-static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, 
struct userdata *u) {
-pa_sink_input *si;
-uint32_t idx;
-
-pa_assert(c);
-pa_assert(sink);
-pa_assert(u);
-pa_assert(u->on_hotplug && u->restore_device);
-
-PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
-char *name;
-struct entry *e;
-
-if (si->sink == sink)
-continue;
-
-if (pa_safe_streq(si->sink->name, si->preferred_sink))
-continue;
-
-/* Skip this if it is already in the process of being moved
- * anyway */
-if (!si->sink)
-continue;
-
-/* Skip this sink input if it is connecting a filter sink to
- * the master */
-if (si->origin_sink)
-continue;
-
-/* 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 */
-if (!PA_SINK_INPUT_IS_LINKED(si->state))
-continue;
-
-if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", 
IDENTIFICATION_PROPERTY)))
-continue;
-
-if ((e = entry_read(u, name))) {
-if (e->device_valid && pa_streq(e->device, sink->name))
-pa_sink_input_move_to(si, sink, true);
-
-entry_free(e);
-}
-
-pa_xfree(name);
-}
-
-return PA_HOOK_OK;
-}
-
 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source 
*source, struct userdata *u) {
 pa_source_output *so;
 uint32_t idx;
@@ -2471,7 +2419,6 @@ int pa__init(pa_module*m) {
 
 if (restore_device && on_hotplug) {
 /* A little bit earlier than module-intended-roles ... */
-pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PUT], 
PA_HOOK_LATE, (pa_hook_cb_t) sink_put_hook_callback, u);
 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], 
PA_HOOK_LATE, (pa_hook_cb_t) source_put_hook_callback, u);
 }
 
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index a112ff753..e761a9934 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -523,6 +523,34 @@ void pa_core_rttime_restart(pa_core *c, pa_time_event *e, 
pa_usec_t usec) {
 c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, true));
 }
 
+void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, 
pa_sink *s) {
+pa_sink_input *si;
+uint32_t idx;
+
+pa_assert(c);
+pa_assert(s);
+
+PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
+if (si->sink == s)
+continue;
+
+/* Skip this sink input if it is connecting a filter sink to
+ * the master */
+if (si->origin_sink)
+continue;
+
+/* 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 */
+if (!PA_SINK_INPUT_IS_LINKED(si->state))
+continue;
+
+if (pa_safe_streq(si->preferred_sink, s->name))
+pa_sink_input_move_to(si, s, false);
+}
+
+}
+
 /* Helper macro to reduce repetition in pa_suspend_cause_to_string().
  * Parameters:
  *   char *p: the current position in the write buffer
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 04f11f8e9..255fae4ae 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -278,4 +278,6 @@ static const size_t PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE =
  * provided buffer. The same buffer is the return value of this function. */
 const char *pa_suspend_cause_to_string(pa_suspend_cause_t cause, char 
buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE]);
 
+void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, 
pa_sink *s);
+
 #endif
dif

[pulseaudio-discuss] [PATCH v3 6/8] device-port: moving streams due to changing the status of active_port

2019-08-17 Thread Hui Wang
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 a sink changes state from unavailable, all
streams that have their preferred_sink set to this sink should be moved
to this sink.

Signed-off-by: Hui Wang 
---
 src/pulsecore/device-port.c | 30 ++
 src/pulsecore/device-port.h |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
index 464c3f8a2..49de33b9e 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,22 @@ 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_device_port_get_sink(p);
+if (!sink)
+return;
+if (p != sink->active_port)
+return;
+switch (p->direction) {
+case PA_DIRECTION_OUTPUT:
+if (sink->active_port->available == PA_AVAILABLE_NO)
+pa_sink_move_streams_to_default_sink(p->core, sink, false);
+else
+
pa_core_move_streams_to_newly_available_preferred_sink(p->core, sink);
+break;
+case PA_DIRECTION_INPUT:
+break;
+}
 }
 }
 
@@ -224,3 +241,16 @@ pa_device_port *pa_device_port_find_best(pa_hashmap *ports)
 
 return best;
 }
+
+pa_sink *pa_device_port_get_sink(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/device-port.h b/src/pulsecore/device-port.h
index fbdce1aa0..41988e5bb 100644
--- a/src/pulsecore/device-port.h
+++ b/src/pulsecore/device-port.h
@@ -87,4 +87,6 @@ void pa_device_port_set_preferred_profile(pa_device_port *p, 
const char *new_pp)
 
 pa_device_port *pa_device_port_find_best(pa_hashmap *ports);
 
+pa_sink *pa_device_port_get_sink(pa_device_port *p);
+
 #endif
-- 
2.17.1

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

[pulseaudio-discuss] [PATCH v3 0/8] Change the bool sink_save to char *preferred_sink

2019-08-17 Thread Hui Wang

In the V3, I addressed all Tanu's and Georg's comments:
0002-xxx.patch:
remove the pa_subscription_post() in the pa_sink_input_set_preferred_sink()

0003-xxx.patch:
Add the check of sink_input->sink->card in the subscribe_callback()

0004-xxx.patch:
Initialize the varible old_sink_is_unavailable
Add the check of core->default_sink == NULL || 
core->default_sink->unlink_requested
in the pa_sink_move_streams_to_default_sink()

0007-xxx.patch:
Move the calling of pa_sink_move_streams_to_default_sink() after the
pa_core_update_default_sink() in the pa_sink_unlink()
Add shutdown check in the pa_sink_move_streams_to_default_sink()
Change the logging message in the pa_sink_move_streams_to_default_sink()
Remove the sink and sink_input parts in the module-rescue-streams.c



This is based on Tanu's design:
https://lists.freedesktop.org/archives/pulseaudio-discuss/2018-October/030531.html

And this is only for sink-input and sink, not for source-output and source.

In the V2, I addressed all comments of V1 and split the big patch into small 
patches
as suggested by Tanu. It will be easy to review in the future.


Hui Wang (8):
  sink-input: change bool save_sink to char *preferred_sink
  sink-input: add a new API pa_sink_input_set_preferred_sink
  sink-input: clear the preferred_sink if it is default_sink
  core: move sink-inputs conditionally when update default_sink
  sink: move streams to new appeared sinks if they prefer these sinks
  device-port: moving streams due to changing the status of active_port
  sink: move the streams to the default_sink when the sink is unlinked
  stream-restore: skip entries setting action from gnome-control-center

 src/modules/dbus/iface-core.c   |   2 +-
 src/modules/module-default-device-restore.c |   2 +-
 src/modules/module-device-manager.c |   8 +-
 src/modules/module-intended-roles.c |   2 +-
 src/modules/module-rescue-streams.c | 134 +
 src/modules/module-stream-restore.c | 151 +---
 src/modules/module-switch-on-connect.c  |  27 +---
 src/pulsecore/cli-command.c |   2 +-
 src/pulsecore/core.c|  38 -
 src/pulsecore/core.h|   6 +-
 src/pulsecore/device-port.c |  32 -
 src/pulsecore/device-port.h |   2 +
 src/pulsecore/protocol-native.c |   2 +-
 src/pulsecore/sink-input.c  |  41 +-
 src/pulsecore/sink-input.h  |  19 ++-
 src/pulsecore/sink.c|  46 +-
 src/pulsecore/sink.h|   6 +
 17 files changed, 215 insertions(+), 305 deletions(-)

-- 
2.17.1

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

[pulseaudio-discuss] [PATCH v3 1/8] sink-input: change bool save_sink to char *preferred_sink

2019-08-17 Thread Hui Wang
The finial objective is to store the preferred sink name in the
sink-input struct, and use module-stream-restore to save and restore
it.

This patch just replaces the save_sink with preferred_sink, and tries
to keep the original logic.

Signed-off-by: Hui Wang 
---
 src/modules/module-device-manager.c|  8 
 src/modules/module-intended-roles.c|  2 +-
 src/modules/module-stream-restore.c| 15 +--
 src/modules/module-switch-on-connect.c |  2 +-
 src/pulsecore/sink-input.c | 24 +++-
 src/pulsecore/sink-input.h | 17 -
 6 files changed, 46 insertions(+), 22 deletions(-)

diff --git a/src/modules/module-device-manager.c 
b/src/modules/module-device-manager.c
index 15fd2..cba3a4ebc 100644
--- a/src/modules/module-device-manager.c
+++ b/src/modules/module-device-manager.c
@@ -656,14 +656,14 @@ static void route_sink_input(struct userdata *u, 
pa_sink_input *si) {
 pa_assert(u);
 pa_assert(u->do_routing);
 
-/* Don't override user or application routing requests. */
-if (si->save_sink || si->sink_requested_by_application)
-return;
-
 /* Skip this if it is already in the process of being moved anyway */
 if (!si->sink)
 return;
 
+/* Don't override user or application routing requests. */
+if (pa_safe_streq(si->sink->name, si->preferred_sink) || 
si->sink_requested_by_application)
+return;
+
 auto_filtered_prop = pa_proplist_gets(si->proplist, 
"module-device-manager.auto_filtered");
 if (auto_filtered_prop)
 auto_filtered = (pa_parse_boolean(auto_filtered_prop) == 1);
diff --git a/src/modules/module-intended-roles.c 
b/src/modules/module-intended-roles.c
index adee51c20..5596faf1f 100644
--- a/src/modules/module-intended-roles.c
+++ b/src/modules/module-intended-roles.c
@@ -175,7 +175,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, struct
 if (si->sink == sink)
 continue;
 
-if (si->save_sink)
+if (pa_safe_streq(si->sink->name, si->preferred_sink))
 continue;
 
 /* Skip this if it is already in the process of being moved
diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index cbef4782d..3c50fda1e 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1311,9 +1311,9 @@ static void subscribe_callback(pa_core *c, 
pa_subscription_event_type_t t, uint3
 mute_updated = !created_new_entry && (!old->muted_valid || 
entry->muted != old->muted);
 }
 
-if (sink_input->save_sink) {
+if (sink_input->preferred_sink != NULL) {
 pa_xfree(entry->device);
-entry->device = pa_xstrdup(sink_input->sink->name);
+entry->device = pa_xstrdup(sink_input->preferred_sink);
 entry->device_valid = true;
 
 device_updated = !created_new_entry && (!old->device_valid || 
!pa_streq(entry->device, old->device));
@@ -1650,7 +1650,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core 
*c, pa_sink *sink, struct
 if (si->sink == sink)
 continue;
 
-if (si->save_sink)
+if (pa_safe_streq(si->sink->name, si->preferred_sink))
 continue;
 
 /* Skip this if it is already in the process of being moved
@@ -1951,12 +1951,13 @@ static void entry_apply(struct userdata *u, const char 
*name, struct entry *e) {
 
 if (u->restore_device) {
 if (!e->device_valid) {
-if (si->save_sink) {
+if (si->preferred_sink != NULL) {
 pa_log_info("Ensuring device is not saved for stream %s.", 
name);
 /* If the device is not valid we should make sure the
-   save flag is cleared as the user may have specifically
+   preferred_sink is cleared as the user may have 
specifically
removed the sink element from the rule. */
-si->save_sink = false;
+pa_xfree(si->preferred_sink);
+si->preferred_sink = NULL;
 /* This is cheating a bit. The sink input itself has not 
changed
but the rules governing its routing have, so we fire 
this event
such that other routing modules (e.g. 
module-device-manager)
@@ -1966,6 +1967,8 @@ static void entry_apply(struct userdata *u, const char 
*name, struct entry *e) {
 } else if ((s = pa_namereg_get(u->core, e->device, 
PA_NAMEREG_SINK))) {
 pa_log_info("Restoring device for stream %s.", name);
 pa_sink_input_move_to(si, s, true);
+pa_xfree(si->pref

[pulseaudio-discuss] [PATCH v3 8/8] stream-restore: skip entries setting action from gnome-control-center

2019-08-17 Thread Hui Wang
When users select an output device from gnome-control-center UI, the
sink of this output device will be set to the configured_default_sink
and the default_sink, these actions are expected, but after these
actions, the gnome-control-center will call extension_cb() to modify
the entries in the database, let all stream entries to bind the sink
users select, this is not correct since the sink is default_sink now.

This is a temp fix for this issue, after gnome-control-center fixes
this problem, this patch should be reverted.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index 838b7fcaa..161f47fdb 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -2057,7 +2057,7 @@ static int extension_cb(pa_native_protocol *p, pa_module 
*m, pa_native_connectio
 }
 
 while (!pa_tagstruct_eof(t)) {
-const char *name, *device;
+const char *name, *device, *client_name;
 bool muted;
 struct entry *entry;
 #ifdef HAVE_DBUS
@@ -2098,7 +2098,17 @@ static int extension_cb(pa_native_protocol *p, pa_module 
*m, pa_native_connectio
 entry_free(entry);
 goto fail;
 }
-
+/* When users select an output device from 
gnome-control-center UI, the gnome-control-center will change all entries
+ * in the database to bind the sink of this output device, 
this is not correct since at this moment, the sink is
+ * default_sink and we shouldn't bind a stream to default_sink 
via preferred_sink or database.
+ * After gnome-control-center fix the issue, let us remove 
this code */
+client_name = 
pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, 
PA_PROP_APPLICATION_PROCESS_BINARY));
+if (pa_safe_streq(client_name, "gnome-control-center")) {
+if (entry->device_valid && m->core->default_sink && 
pa_safe_streq(device, m->core->default_sink->name)) {
+entry_free(entry);
+goto fail;
+}
+}
 #ifdef HAVE_DBUS
 old = entry_read(u, name);
 #endif
-- 
2.17.1

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

[pulseaudio-discuss] [PATCH v3 4/8] core: move sink-inputs conditionally when update default_sink

2019-08-17 Thread Hui Wang
When the default sink changes, the streams from the old default sink
should be moved to the new default sink, unless the preferred_sink
string is set to the old default sink and the active port of the old
default sink is not unavailable

Signed-off-by: Hui Wang 
---
 src/modules/dbus/iface-core.c   |  2 +-
 src/modules/module-default-device-restore.c |  2 +-
 src/modules/module-switch-on-connect.c  | 27 ++-
 src/pulsecore/cli-command.c |  2 +-
 src/pulsecore/core.c| 10 --
 src/pulsecore/core.h|  4 +--
 src/pulsecore/device-port.c |  2 +-
 src/pulsecore/protocol-native.c |  2 +-
 src/pulsecore/sink.c| 38 +++--
 src/pulsecore/sink.h|  6 
 10 files changed, 57 insertions(+), 38 deletions(-)

diff --git a/src/modules/dbus/iface-core.c b/src/modules/dbus/iface-core.c
index 5229c0467..9763480d2 100644
--- a/src/modules/dbus/iface-core.c
+++ b/src/modules/dbus/iface-core.c
@@ -721,7 +721,7 @@ static void handle_set_fallback_sink(DBusConnection *conn, 
DBusMessage *msg, DBu
 return;
 }
 
-pa_core_set_configured_default_sink(c->core, 
pa_dbusiface_device_get_sink(fallback_sink)->name);
+pa_core_set_configured_default_sink(c->core, 
pa_dbusiface_device_get_sink(fallback_sink)->name, true);
 
 pa_dbus_send_empty_reply(conn, msg);
 }
diff --git a/src/modules/module-default-device-restore.c 
b/src/modules/module-default-device-restore.c
index c4dbad99f..33e74c071 100644
--- a/src/modules/module-default-device-restore.c
+++ b/src/modules/module-default-device-restore.c
@@ -69,7 +69,7 @@ static void load(struct userdata *u) {
 pa_log_warn("Invalid sink name: %s", ln);
 else {
 pa_log_info("Restoring default sink '%s'.", ln);
-pa_core_set_configured_default_sink(u->core, ln);
+pa_core_set_configured_default_sink(u->core, ln, false);
 }
 
 } else if (errno != ENOENT)
diff --git a/src/modules/module-switch-on-connect.c 
b/src/modules/module-switch-on-connect.c
index f0cb29a7c..3ceac8b4f 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -54,9 +54,6 @@ struct userdata {
 };
 
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
-pa_sink_input *i;
-uint32_t idx;
-pa_sink *old_default_sink;
 const char *s;
 struct userdata *u = userdata;
 
@@ -88,7 +85,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 
 /* No default sink, nothing to move away, just set the new default */
 if (!c->default_sink) {
-pa_core_set_configured_default_sink(c, sink->name);
+pa_core_set_configured_default_sink(c, sink->name, false);
 return PA_HOOK_OK;
 }
 
@@ -103,28 +100,8 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, 
pa_sink *sink, void*
 return PA_HOOK_OK;
 }
 
-old_default_sink = c->default_sink;
-
 /* Actually do the switch to the new sink */
-pa_core_set_configured_default_sink(c, sink->name);
-
-/* Now move all old inputs over */
-if (pa_idxset_size(old_default_sink->inputs) <= 0) {
-pa_log_debug("No sink inputs to move away.");
-return PA_HOOK_OK;
-}
-
-PA_IDXSET_FOREACH(i, old_default_sink->inputs, idx) {
-if (pa_safe_streq(i->sink->name, i->preferred_sink) || 
!PA_SINK_INPUT_IS_LINKED(i->state))
-continue;
-
-if (pa_sink_input_move_to(i, 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)), 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)), sink->name);
-}
+pa_core_set_configured_default_sink(c, sink->name, false);
 
 return PA_HOOK_OK;
 }
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 5205349bd..cc7addaa1 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -1036,7 +1036,7 @@ static int pa_cli_command_sink_default(pa_core *c, 
pa_tokenizer *t, pa_strbuf *b
 }
 
 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
-pa_core_set_configured_default_sink(c, s->name);
+pa_core_set_configured_default_sink(c, s->name, true);
 else
 pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
 
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index e5bb2e47b..a112ff753 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsec

[pulseaudio-discuss] [PATCH v3 7/8] sink: move the streams to the default_sink when the sink is unlinked

2019-08-17 Thread Hui Wang
When a sink is unlinked, all streams of this sink are moved to
default_sink, this action is implemented in the core rather than
modules now.

Signed-off-by: Hui Wang 
---
 src/modules/module-rescue-streams.c | 134 +---
 src/modules/module-stream-restore.c |  50 ---
 src/pulsecore/sink.c|   8 +-
 3 files changed, 8 insertions(+), 184 deletions(-)

diff --git a/src/modules/module-rescue-streams.c 
b/src/modules/module-rescue-streams.c
index 0d8b1be8b..a21b95a96 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -24,7 +24,6 @@
 #include 
 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -32,7 +31,7 @@
 #include 
 
 PA_MODULE_AUTHOR("Lennart Poettering");
-PA_MODULE_DESCRIPTION("When a sink/source is removed, try to move its streams 
to the default sink/source");
+PA_MODULE_DESCRIPTION("When a source is removed, try to move its streams to 
the default source");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(true);
 
@@ -42,9 +41,7 @@ static const char* const valid_modargs[] = {
 
 struct userdata {
 pa_hook_slot
-*sink_unlink_slot,
 *source_unlink_slot,
-*sink_input_move_fail_slot,
 *source_output_move_fail_slot;
 };
 
@@ -65,23 +62,6 @@ static pa_source* find_source_from_port(pa_core *c, 
pa_device_port *port) {
 return NULL;
 }
 
-static pa_sink* find_sink_from_port(pa_core *c, pa_device_port *port) {
-pa_sink *target;
-uint32_t idx;
-void *state;
-pa_device_port *p;
-
-if (!port)
-return NULL;
-
-PA_IDXSET_FOREACH(target, c->sinks, idx)
-PA_HASHMAP_FOREACH(p, target->ports, state)
-if (port == p)
-return target;
-
-return NULL;
-}
-
 static void build_group_ports(pa_hashmap *g_ports, pa_hashmap *s_ports) {
 void *state;
 pa_device_port *p;
@@ -93,112 +73,6 @@ static void build_group_ports(pa_hashmap *g_ports, 
pa_hashmap *s_ports) {
 pa_hashmap_put(g_ports, p, p);
 }
 
-static pa_sink* find_evacuation_sink(pa_core *c, pa_sink_input *i, pa_sink 
*skip) {
-pa_sink *target, *fb_sink = NULL;
-uint32_t idx;
-pa_hashmap *all_ports;
-pa_device_port *best_port;
-
-pa_assert(c);
-pa_assert(i);
-
-if (c->default_sink && c->default_sink != skip && 
pa_sink_input_may_move_to(i, c->default_sink))
-return c->default_sink;
-
-all_ports = pa_hashmap_new(pa_idxset_trivial_hash_func, 
pa_idxset_trivial_compare_func);
-
-PA_IDXSET_FOREACH(target, c->sinks, idx) {
-if (target == c->default_sink)
-continue;
-
-if (target == skip)
-continue;
-
-if (!PA_SINK_IS_LINKED(target->state))
-continue;
-
-if (!pa_sink_input_may_move_to(i, target))
-continue;
-
-if (!fb_sink)
-fb_sink = target;
-
-build_group_ports(all_ports, target->ports);
-}
-
-best_port = pa_device_port_find_best(all_ports);
-
-pa_hashmap_free(all_ports);
-
-if (best_port)
-target = find_sink_from_port(c, best_port);
-else
-target = fb_sink;
-
-if (!target)
-pa_log_debug("No evacuation sink found.");
-
-return target;
-}
-
-static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, 
void* userdata) {
-pa_sink_input *i;
-uint32_t idx;
-
-pa_assert(c);
-pa_assert(sink);
-
-/* There's no point in doing anything if the core is shut down anyway */
-if (c->state == PA_CORE_SHUTDOWN)
-return PA_HOOK_OK;
-
-if (pa_idxset_size(sink->inputs) <= 0) {
-pa_log_debug("No sink inputs to move away.");
-return PA_HOOK_OK;
-}
-
-PA_IDXSET_FOREACH(i, sink->inputs, idx) {
-pa_sink *target;
-
-if (!(target = find_evacuation_sink(c, i, sink)))
-continue;
-
-if (pa_sink_input_move_to(i, target, 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)), target->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)), target->name);
-}
-
-return PA_HOOK_OK;
-}
-
-static pa_hook_result_t sink_input_move_fail_hook_callback(pa_core *c, 
pa_sink_input *i, void *userdata) {
-pa_sink *target;
-
-pa_assert(c);
-pa_assert(i);
-
-/* There's no point in doing anything if the core is shut down anyway */
-if (c->state == PA_CORE_SHUTDOWN)
-return PA_HOOK_OK;
-
-if (!(target = find_evacuation_sink(c, i, NULL)))
-return PA_HOOK_OK;
-
-if (pa_sink_in

[pulseaudio-discuss] [PATCH v3 2/8] sink-input: add a new API pa_sink_input_set_preferred_sink

2019-08-17 Thread Hui Wang
If the sink here is NULL, that means users want to clear the
preferred_sink and move the sink-input to the default_sink, otherwise
set the preferred_sink to the sink->name and move the sink-input to
the sink. After that fire the sink_input_change event.

After adding this API, we can use this API to simplify the entry_apply
in the module-stream-restore.c.

Signed-off-by: Hui Wang 
---
 src/modules/module-stream-restore.c | 10 ++
 src/pulsecore/sink-input.c  | 13 +
 src/pulsecore/sink-input.h  |  2 ++
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/src/modules/module-stream-restore.c 
b/src/modules/module-stream-restore.c
index 3c50fda1e..c8bc02ecd 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1957,18 +1957,12 @@ static void entry_apply(struct userdata *u, const char 
*name, struct entry *e) {
preferred_sink is cleared as the user may have 
specifically
removed the sink element from the rule. */
 pa_xfree(si->preferred_sink);
-si->preferred_sink = NULL;
-/* This is cheating a bit. The sink input itself has not 
changed
-   but the rules governing its routing have, so we fire 
this event
-   such that other routing modules (e.g. 
module-device-manager)
-   will pick up the change and reapply their routing */
-pa_subscription_post(si->core, 
PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, si->index);
+pa_sink_input_set_preferred_sink(si, NULL);
 }
 } else if ((s = pa_namereg_get(u->core, e->device, 
PA_NAMEREG_SINK))) {
 pa_log_info("Restoring device for stream %s.", name);
-pa_sink_input_move_to(si, s, true);
 pa_xfree(si->preferred_sink);
-si->preferred_sink = pa_xstrdup(s->name);
+pa_sink_input_set_preferred_sink(si, s);
 }
 }
 }
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 18766019e..7521bed08 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -2418,3 +2418,16 @@ void pa_sink_input_set_reference_ratio(pa_sink_input *i, 
const pa_cvolume *ratio
  pa_cvolume_snprint_verbose(old_ratio_str, 
sizeof(old_ratio_str), &old_ratio, &i->channel_map, true),
  pa_cvolume_snprint_verbose(new_ratio_str, 
sizeof(new_ratio_str), ratio, &i->channel_map, true));
 }
+
+/* Called from the main thread. */
+void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s) {
+pa_assert(i);
+
+if (s) {
+i->preferred_sink = pa_xstrdup(s->name);
+pa_sink_input_move_to(i, s, true);
+} else {
+i->preferred_sink = NULL;
+pa_sink_input_move_to(i, i->core->default_sink, true);
+}
+}
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 16b6bf8eb..d3de6e3f8 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -461,6 +461,8 @@ void pa_sink_input_set_volume_direct(pa_sink_input *i, 
const pa_cvolume *volume)
  * i->reference_ratio and logs a message if the value changes. */
 void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume 
*ratio);
 
+void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s);
+
 #define pa_sink_input_assert_io_context(s) \
 pa_assert(pa_thread_mq_get() || !PA_SINK_INPUT_IS_LINKED((s)->state))
 
-- 
2.17.1

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

Re: [pulseaudio-discuss] [PATCH v3 0/8] Change the bool sink_save to char *preferred_sink

2019-08-23 Thread Hui Wang

OK, I will create a merge request.

Thanks,

Hui.

On 2019/8/23 下午3:48, Georg Chini wrote:

On 18.08.19 07:32, Hui Wang wrote:

In the V3, I addressed all Tanu's and Georg's comments:
0002-xxx.patch:
remove the pa_subscription_post() in the 
pa_sink_input_set_preferred_sink()


0003-xxx.patch:
Add the check of sink_input->sink->card in the subscribe_callback()

0004-xxx.patch:
Initialize the varible old_sink_is_unavailable
Add the check of core->default_sink == NULL || 
core->default_sink->unlink_requested

in the pa_sink_move_streams_to_default_sink()

0007-xxx.patch:
Move the calling of pa_sink_move_streams_to_default_sink() after the
pa_core_update_default_sink() in the pa_sink_unlink()
Add shutdown check in the pa_sink_move_streams_to_default_sink()
Change the logging message in the pa_sink_move_streams_to_default_sink()
Remove the sink and sink_input parts in the module-rescue-streams.c



This is based on Tanu's design:
https://lists.freedesktop.org/archives/pulseaudio-discuss/2018-October/030531.html 



And this is only for sink-input and sink, not for source-output and 
source.


In the V2, I addressed all comments of V1 and split the big patch 
into small patches

as suggested by Tanu. It will be easy to review in the future.


Thanks for the updated patches. I will be on vacation starting end of 
next week,
so I will not find the time for a review before end of September. Is 
it possible

that you open a merge request on Gitlab for this?
https://gitlab.freedesktop.org/pulseaudio/pulseaudio/

If not, I will open the merge request for you once the review is complete
because we changed our policy so that all changes have to go through a
merge request.



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

Re: [pulseaudio-discuss] [PATCH v3 0/8] Change the bool sink_save to char *preferred_sink

2019-08-24 Thread Hui Wang
Done. 
https://gitlab.freedesktop.org/pulseaudio/pulseaudio/merge_requests/158


On 2019/8/24 上午9:25, Hui Wang wrote:

OK, I will create a merge request.

Thanks,

Hui.

On 2019/8/23 下午3:48, Georg Chini wrote:

On 18.08.19 07:32, Hui Wang wrote:

In the V3, I addressed all Tanu's and Georg's comments:
0002-xxx.patch:
remove the pa_subscription_post() in the 
pa_sink_input_set_preferred_sink()


0003-xxx.patch:
Add the check of sink_input->sink->card in the subscribe_callback()

0004-xxx.patch:
Initialize the varible old_sink_is_unavailable
Add the check of core->default_sink == NULL || 
core->default_sink->unlink_requested

in the pa_sink_move_streams_to_default_sink()

0007-xxx.patch:
Move the calling of pa_sink_move_streams_to_default_sink() after the
pa_core_update_default_sink() in the pa_sink_unlink()
Add shutdown check in the pa_sink_move_streams_to_default_sink()
Change the logging message in the 
pa_sink_move_streams_to_default_sink()

Remove the sink and sink_input parts in the module-rescue-streams.c



This is based on Tanu's design:
https://lists.freedesktop.org/archives/pulseaudio-discuss/2018-October/030531.html 



And this is only for sink-input and sink, not for source-output and 
source.


In the V2, I addressed all comments of V1 and split the big patch 
into small patches

as suggested by Tanu. It will be easy to review in the future.


Thanks for the updated patches. I will be on vacation starting end of 
next week,
so I will not find the time for a review before end of September. Is 
it possible

that you open a merge request on Gitlab for this?
https://gitlab.freedesktop.org/pulseaudio/pulseaudio/

If not, I will open the merge request for you once the review is 
complete

because we changed our policy so that all changes have to go through a
merge request.



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