summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHui Wang <hui.wang@canonical.com>2020-11-23 11:25:51 +0800
committerArun Raghavan <arun@asymptotic.io>2021-01-07 19:17:22 -0500
commit254cb4bd1f0905270f77462d766c88bf39ccf8a5 (patch)
tree3cb5ebc8a741e612b2e047acfc87c041029043ae
parentb3e6e2e0df2112ec59109f9c071e873c2f50322d (diff)
downloadpulseaudio-254cb4bd1f0905270f77462d766c88bf39ccf8a5.tar.gz
switch-on-port-available: Switch to headset or mic on unknown avail
On some Dell AIO machines, there is no internal mic, only a multi function audio jack, so the only input devices are headphone-mic and headset-mic, and they share the Jack with headphone. When there is no headset plugged in that Jack, the headphone-mic and headset-mic are off. And since there is no available port under the analog input source, this source is unlinked (if there is internal mic, the source will not be unlinked). so the only pa-source left in the PA is analog-stereo-monitor. After the headset is plugged, we need to let switch_to_port() handle headset-mic and headphone-mic conditionally, this will guarantee the source will be created if it is unlinked before plugging, and then the input profile could be selected correctly. Signed-off-by: Hui Wang <hui.wang@canonical.com> Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/390>
-rw-r--r--src/modules/module-switch-on-port-available.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
index 84b856659..f450004ca 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -228,9 +228,7 @@ static struct port_pointers find_port_pointers(pa_device_port *port) {
}
/* Switches to a port, switching profiles if necessary or preferred */
-static void switch_to_port(pa_device_port *port) {
- struct port_pointers pp = find_port_pointers(port);
-
+static void switch_to_port(pa_device_port *port, struct port_pointers pp) {
if (pp.is_port_active)
return; /* Already selected */
@@ -252,8 +250,7 @@ static void switch_to_port(pa_device_port *port) {
}
/* Switches away from a port, switching profiles if necessary or preferred */
-static void switch_from_port(pa_device_port *port) {
- struct port_pointers pp = find_port_pointers(port);
+static void switch_from_port(pa_device_port *port, struct port_pointers pp) {
pa_device_port *p, *best_port = NULL;
void *state;
@@ -282,12 +279,12 @@ static void switch_from_port(pa_device_port *port) {
* PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED callback, as at this point
* the profile availability hasn't been updated yet. */
if (best_port)
- switch_to_port(best_port);
+ switch_to_port(best_port, pp);
}
static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
- pa_assert(port);
+ struct port_pointers pp = find_port_pointers(port);
if (!port->card) {
pa_log_warn("Port %s does not have a card", port->name);
@@ -314,6 +311,15 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port
* functionality for setups that can't trigger this kind of
* interaction.
*
+ * For headset or microphone, if they are part of some availability group
+ * and they become unknown from off, it needs to check if their source is
+ * unlinked or not, if their source is unlinked, let switch_to_port()
+ * process them, then with the running of pa_card_set_profile(), their
+ * source will be created, otherwise the headset or microphone can't be used
+ * to record sound since there is no source for these 2 ports. This issue
+ * is observed on Dell machines which have multi-function audio jack but no
+ * internal mic.
+ *
* We should make this configurable so that users can optionally
* override the default to a headset or mic. */
@@ -323,20 +329,22 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port
break;
}
- /* For no we only switch the headphone port */
- if (port->direction != PA_DIRECTION_OUTPUT) {
+ /* Switch the headphone port, the input ports without source and the
+ * input ports their source->active_port is part of a group of ports.
+ */
+ if (port->direction == PA_DIRECTION_INPUT && pp.source && !pp.source->active_port->availability_group) {
pa_log_debug("Not switching to input port %s, its availability is unknown.", port->name);
break;
}
- switch_to_port(port);
+ switch_to_port(port, pp);
break;
case PA_AVAILABLE_YES:
- switch_to_port(port);
+ switch_to_port(port, pp);
break;
case PA_AVAILABLE_NO:
- switch_from_port(port);
+ switch_from_port(port, pp);
break;
default:
break;