Accepting request 774846 from multimedia:libs
OBS-URL: https://build.opensuse.org/request/show/774846 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/pulseaudio?expand=0&rev=167
This commit is contained in:
commit
24b51185fe
@ -0,0 +1,48 @@
|
||||
From 3dff31e19ca627fc4e0a8f13aeb44923118ecfa1 Mon Sep 17 00:00:00 2001
|
||||
From: Tanu Kaskinen <tanuk@iki.fi>
|
||||
Date: Fri, 20 Sep 2019 17:09:40 +0300
|
||||
Subject: [PATCH] alsa-mixer-path-test: Hide unused functions when building
|
||||
with Meson
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Silences these warnings:
|
||||
|
||||
[509/574] Compiling C object 'src/tests/a4ccf2d@@alsa-mixer-path-test@exe/alsa-mixer-path-test.c.o'.
|
||||
../src/tests/alsa-mixer-path-test.c:24:20: warning: ‘load_makefile’ defined but not used [-Wunused-function]
|
||||
static pa_strlist *load_makefile() {
|
||||
^~~~~~~~~~~~~
|
||||
../src/tests/alsa-mixer-path-test.c:17:20: warning: ‘get_default_paths_dir’ defined but not used [-Wunused-function]
|
||||
static const char *get_default_paths_dir(void) {
|
||||
^~~~~~~~~~~~~~~~~~~~~
|
||||
---
|
||||
src/tests/alsa-mixer-path-test.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/src/tests/alsa-mixer-path-test.c b/src/tests/alsa-mixer-path-test.c
|
||||
index ee40587b7b13..75cf086138cc 100644
|
||||
--- a/src/tests/alsa-mixer-path-test.c
|
||||
+++ b/src/tests/alsa-mixer-path-test.c
|
||||
@@ -13,6 +13,10 @@
|
||||
#include <pulsecore/strlist.h>
|
||||
#include <modules/alsa/alsa-mixer.h>
|
||||
|
||||
+/* This test inspects the Makefile, so this is not applicable when using
|
||||
+ * Meson. */
|
||||
+#ifndef MESON_BUILD
|
||||
+
|
||||
/* This function was copied from alsa-mixer.c */
|
||||
static const char *get_default_paths_dir(void) {
|
||||
if (pa_run_from_build_tree())
|
||||
@@ -52,6 +56,7 @@ static pa_strlist *load_makefile() {
|
||||
fclose(f);
|
||||
return result;
|
||||
}
|
||||
+#endif /* end of #ifndef MESON_BUILD */
|
||||
|
||||
START_TEST (mixer_path_test) {
|
||||
#ifdef MESON_BUILD
|
||||
--
|
||||
2.16.4
|
||||
|
30
0002-alsa-mixer-recognize-the-Speaker-Jack-control.patch
Normal file
30
0002-alsa-mixer-recognize-the-Speaker-Jack-control.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 248a77c7fd2f9682c58d3d3dd6f3c2ba3ad2c111 Mon Sep 17 00:00:00 2001
|
||||
From: Tanu Kaskinen <tanuk@iki.fi>
|
||||
Date: Sat, 2 Sep 2017 15:35:01 +0300
|
||||
Subject: [PATCH] alsa-mixer: recognize the "Speaker Jack" control
|
||||
|
||||
This control has been seen in the wild:
|
||||
https://lists.freedesktop.org/archives/pulseaudio-discuss/2017-August/028595.html
|
||||
(The pastebin link in that mail might not work anymore, but the paste
|
||||
just shows that there's a Speaker Jack control).
|
||||
---
|
||||
src/modules/alsa/mixer/paths/analog-output-speaker.conf | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
|
||||
index 9f4dac414134..6f9968e1f537 100644
|
||||
--- a/src/modules/alsa/mixer/paths/analog-output-speaker.conf
|
||||
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
|
||||
@@ -56,6 +56,9 @@ state.unplugged = unknown
|
||||
state.plugged = no
|
||||
state.unplugged = unknown
|
||||
|
||||
+[Jack Speaker]
|
||||
+required-any = any
|
||||
+
|
||||
[Jack Speaker Phantom]
|
||||
required-any = any
|
||||
state.plugged = unknown
|
||||
--
|
||||
2.16.4
|
||||
|
104
0003-alsa-mixer-add-support-for-SteelSeries-Arctis-Pro-20.patch
Normal file
104
0003-alsa-mixer-add-support-for-SteelSeries-Arctis-Pro-20.patch
Normal file
@ -0,0 +1,104 @@
|
||||
From 7259e8c22fb97b1ae80ac4909713e51b293afc4a Mon Sep 17 00:00:00 2001
|
||||
From: Josh <questofiranon@gmail.com>
|
||||
Date: Sat, 25 May 2019 02:35:01 -0700
|
||||
Subject: [PATCH] alsa-mixer: add support for SteelSeries Arctis Pro 2019
|
||||
headset
|
||||
|
||||
Signed-off-by: Dave Chiluk <chiluk@ubuntu.com>
|
||||
---
|
||||
src/Makefile.am | 6 +++---
|
||||
src/modules/alsa/90-pulseaudio.rules | 10 +++++++---
|
||||
...ut-chat.conf => steelseries-arctis-output-chat-common.conf} | 0
|
||||
...ut-game.conf => steelseries-arctis-output-game-common.conf} | 0
|
||||
...usb-audio.conf => steelseries-arctis-common-usb-audio.conf} | 4 ++--
|
||||
5 files changed, 12 insertions(+), 8 deletions(-)
|
||||
rename src/modules/alsa/mixer/paths/{steelseries-arctis-5-output-chat.conf => steelseries-arctis-output-chat-common.conf} (100%)
|
||||
rename src/modules/alsa/mixer/paths/{steelseries-arctis-5-output-game.conf => steelseries-arctis-output-game-common.conf} (100%)
|
||||
rename src/modules/alsa/mixer/profile-sets/{steelseries-arctis-5-usb-audio.conf => steelseries-arctis-common-usb-audio.conf} (80%)
|
||||
|
||||
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||
index e3baf587a8a3..3db921a07e1b 100644
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -1353,7 +1353,7 @@ 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-5-usb-audio.conf \
|
||||
+ modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf \
|
||||
modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf \
|
||||
modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf \
|
||||
modules/alsa/mixer/profile-sets/cmedia-high-speed-true-hdaudio.conf
|
||||
@@ -1399,8 +1399,8 @@ dist_alsapaths_DATA = \
|
||||
modules/alsa/mixer/paths/hdmi-output-5.conf \
|
||||
modules/alsa/mixer/paths/hdmi-output-6.conf \
|
||||
modules/alsa/mixer/paths/hdmi-output-7.conf \
|
||||
- modules/alsa/mixer/paths/steelseries-arctis-5-output-chat.conf \
|
||||
- modules/alsa/mixer/paths/steelseries-arctis-5-output-game.conf \
|
||||
+ modules/alsa/mixer/paths/steelseries-arctis-output-chat-common.conf \
|
||||
+ modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf \
|
||||
modules/alsa/mixer/paths/steelseries-arctis-7-input.conf \
|
||||
modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf \
|
||||
modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf
|
||||
diff --git a/src/modules/alsa/90-pulseaudio.rules b/src/modules/alsa/90-pulseaudio.rules
|
||||
index d85763917d76..9d34e6dfdd38 100644
|
||||
--- a/src/modules/alsa/90-pulseaudio.rules
|
||||
+++ b/src/modules/alsa/90-pulseaudio.rules
|
||||
@@ -109,16 +109,20 @@ ATTRS{idVendor}=="0763", ATTRS{idProduct}=="2012", ENV{PULSE_PROFILE_SET}="maudi
|
||||
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"
|
||||
-ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1250", ENV{PULSE_PROFILE_SET}="steelseries-arctis-5-usb-audio.conf"
|
||||
+
|
||||
|
||||
# ID 1038:12ad is for the 2018 refresh of the Arctis 7.
|
||||
-# ID 1038:1294 is for Arctis Pro Wireless (which works with the Arctis 7
|
||||
-# configuration).
|
||||
+# ID 1038:1294 is for Arctis Pro Wireless (which works with the Arctis 7 configuration).
|
||||
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1260", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf"
|
||||
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12ad", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf"
|
||||
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1294", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf"
|
||||
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf"
|
||||
|
||||
+# ID 1038:1250 is for the Arctis 5
|
||||
+# ID 1038:1252 is for Arctis Pro 2019 edition
|
||||
+ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1250", ENV{PULSE_PROFILE_SET}="steelseries-arctis-common-usb-audio.conf"
|
||||
+ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1252", ENV{PULSE_PROFILE_SET}="steelseries-arctis-common-usb-audio.conf"
|
||||
+
|
||||
ATTRS{idVendor}=="147a", ATTRS{idProduct}=="e055", ENV{PULSE_PROFILE_SET}="cmedia-high-speed-true-hdaudio.conf"
|
||||
|
||||
GOTO="pulseaudio_end"
|
||||
diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-5-output-chat.conf b/src/modules/alsa/mixer/paths/steelseries-arctis-output-chat-common.conf
|
||||
similarity index 100%
|
||||
rename from src/modules/alsa/mixer/paths/steelseries-arctis-5-output-chat.conf
|
||||
rename to src/modules/alsa/mixer/paths/steelseries-arctis-output-chat-common.conf
|
||||
diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-5-output-game.conf b/src/modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf
|
||||
similarity index 100%
|
||||
rename from src/modules/alsa/mixer/paths/steelseries-arctis-5-output-game.conf
|
||||
rename to src/modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf
|
||||
diff --git a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-5-usb-audio.conf b/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf
|
||||
similarity index 80%
|
||||
rename from src/modules/alsa/mixer/profile-sets/steelseries-arctis-5-usb-audio.conf
|
||||
rename to src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf
|
||||
index fe353c38f09c..80c33707aea4 100644
|
||||
--- a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-5-usb-audio.conf
|
||||
+++ b/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf
|
||||
@@ -6,13 +6,13 @@ description = Chat
|
||||
device-strings = hw:%f,0,0
|
||||
channel-map = left,right
|
||||
paths-input = analog-input-mic
|
||||
-paths-output = steelseries-arctis-5-output-chat
|
||||
+paths-output = steelseries-arctis-output-chat-common
|
||||
|
||||
[Mapping analog-game]
|
||||
description = Game
|
||||
device-strings = hw:%f,1,0
|
||||
channel-map = left,right
|
||||
-paths-output = steelseries-arctis-5-output-game
|
||||
+paths-output = steelseries-arctis-output-game-common
|
||||
direction = output
|
||||
|
||||
[Profile output:analog-chat+output:analog-game+input:analog-chat]
|
||||
--
|
||||
2.16.4
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 79d3b99ba4773651c4ebc082233f9d0b5f68bfad Mon Sep 17 00:00:00 2001
|
||||
From: Krzysztof Stasiowski <krzys.stasiowski@gmail.com>
|
||||
Date: Tue, 18 Jun 2019 11:50:35 +0000
|
||||
Subject: [PATCH] alsa-mixer: Add support for SteelSeries Arctis 5 2019 headset
|
||||
|
||||
Signed-off-by: Dave Chiluk <chiluk@ubuntu.com>
|
||||
---
|
||||
src/modules/alsa/90-pulseaudio.rules | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/modules/alsa/90-pulseaudio.rules b/src/modules/alsa/90-pulseaudio.rules
|
||||
index 9d34e6dfdd38..61e7692543e8 100644
|
||||
--- a/src/modules/alsa/90-pulseaudio.rules
|
||||
+++ b/src/modules/alsa/90-pulseaudio.rules
|
||||
@@ -119,8 +119,10 @@ ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1294", ENV{PULSE_PROFILE_SET}="steel
|
||||
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf"
|
||||
|
||||
# ID 1038:1250 is for the Arctis 5
|
||||
-# ID 1038:1252 is for Arctis Pro 2019 edition
|
||||
+# ID 1037:12aa is for the Arctis 5 2019
|
||||
+# ID 1038:1252 is for the Arctis Pro 2019 edition
|
||||
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1250", ENV{PULSE_PROFILE_SET}="steelseries-arctis-common-usb-audio.conf"
|
||||
+ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12aa", ENV{PULSE_PROFILE_SET}="steelseries-arctis-common-usb-audio.conf"
|
||||
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1252", ENV{PULSE_PROFILE_SET}="steelseries-arctis-common-usb-audio.conf"
|
||||
|
||||
ATTRS{idVendor}=="147a", ATTRS{idProduct}=="e055", ENV{PULSE_PROFILE_SET}="cmedia-high-speed-true-hdaudio.conf"
|
||||
--
|
||||
2.16.4
|
||||
|
199
0005-alsa-mixer-add-support-for-LucidSound-LS31-and-creat.patch
Normal file
199
0005-alsa-mixer-add-support-for-LucidSound-LS31-and-creat.patch
Normal file
@ -0,0 +1,199 @@
|
||||
From 1ee1f749e154d2f64b4661f833eebaa18ae1a081 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Chiluk <chiluk@ubuntu.com>
|
||||
Date: Thu, 8 Aug 2019 23:10:01 -0500
|
||||
Subject: [PATCH] alsa-mixer: add support for LucidSound LS31, and create
|
||||
usb-gaming-headset profile
|
||||
|
||||
---
|
||||
src/Makefile.am | 8 ++++----
|
||||
src/modules/alsa/90-pulseaudio.rules | 10 ++++++----
|
||||
...tis-7-input.conf => usb-gaming-headset-input.conf} | 12 ++++++++++--
|
||||
...-mono.conf => usb-gaming-headset-output-mono.conf} | 15 ++++++++++-----
|
||||
...reo.conf => usb-gaming-headset-output-stereo.conf} | 15 ++++++++++-----
|
||||
...rctis-7-usb-audio.conf => usb-gaming-headset.conf} | 19 ++++++++++++-------
|
||||
6 files changed, 52 insertions(+), 27 deletions(-)
|
||||
rename src/modules/alsa/mixer/paths/{steelseries-arctis-7-input.conf => usb-gaming-headset-input.conf} (66%)
|
||||
rename src/modules/alsa/mixer/paths/{steelseries-arctis-7-output-mono.conf => usb-gaming-headset-output-mono.conf} (66%)
|
||||
rename src/modules/alsa/mixer/paths/{steelseries-arctis-7-output-stereo.conf => usb-gaming-headset-output-stereo.conf} (68%)
|
||||
rename src/modules/alsa/mixer/profile-sets/{steelseries-arctis-7-usb-audio.conf => usb-gaming-headset.conf} (79%)
|
||||
|
||||
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||
index 3db921a07e1b..0f1ded7f96c5 100644
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -1354,7 +1354,7 @@ dist_alsaprofilesets_DATA = \
|
||||
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-common-usb-audio.conf \
|
||||
- modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf \
|
||||
+ modules/alsa/mixer/profile-sets/usb-gaming-headset.conf \
|
||||
modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf \
|
||||
modules/alsa/mixer/profile-sets/cmedia-high-speed-true-hdaudio.conf
|
||||
|
||||
@@ -1401,9 +1401,9 @@ dist_alsapaths_DATA = \
|
||||
modules/alsa/mixer/paths/hdmi-output-7.conf \
|
||||
modules/alsa/mixer/paths/steelseries-arctis-output-chat-common.conf \
|
||||
modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf \
|
||||
- modules/alsa/mixer/paths/steelseries-arctis-7-input.conf \
|
||||
- modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf \
|
||||
- modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf
|
||||
+ modules/alsa/mixer/paths/usb-gaming-headset-input.conf \
|
||||
+ modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf \
|
||||
+ modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf
|
||||
|
||||
endif
|
||||
|
||||
diff --git a/src/modules/alsa/90-pulseaudio.rules b/src/modules/alsa/90-pulseaudio.rules
|
||||
index 61e7692543e8..fa43cb802a8e 100644
|
||||
--- a/src/modules/alsa/90-pulseaudio.rules
|
||||
+++ b/src/modules/alsa/90-pulseaudio.rules
|
||||
@@ -113,10 +113,12 @@ ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4014", ENV{PULSE_PROFILE_SET}="dell-
|
||||
|
||||
# ID 1038:12ad is for the 2018 refresh of the Arctis 7.
|
||||
# ID 1038:1294 is for Arctis Pro Wireless (which works with the Arctis 7 configuration).
|
||||
-ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1260", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf"
|
||||
-ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12ad", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf"
|
||||
-ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1294", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf"
|
||||
-ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf"
|
||||
+ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1260", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
||||
+ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12ad", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
||||
+ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1294", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
||||
+ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
||||
+# Lucidsound LS31
|
||||
+ATTRS{idVendor}=="2f12", ATTRS{idProduct}=="0109", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
||||
|
||||
# ID 1038:1250 is for the Arctis 5
|
||||
# ID 1037:12aa is for the Arctis 5 2019
|
||||
diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-7-input.conf b/src/modules/alsa/mixer/paths/usb-gaming-headset-input.conf
|
||||
similarity index 66%
|
||||
rename from src/modules/alsa/mixer/paths/steelseries-arctis-7-input.conf
|
||||
rename to src/modules/alsa/mixer/paths/usb-gaming-headset-input.conf
|
||||
index 3fa36e9385a5..9fa7fe908587 100644
|
||||
--- a/src/modules/alsa/mixer/paths/steelseries-arctis-7-input.conf
|
||||
+++ b/src/modules/alsa/mixer/paths/usb-gaming-headset-input.conf
|
||||
@@ -13,8 +13,16 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-; Steelseries Arctis 7 USB headset microphone path. Works also with Arctis Pro
|
||||
-; Wireless.
|
||||
+; USB gaming headset microphone input path. These headsets usually have two
|
||||
+; output devices. The first one is mono, meant for voice audio, and the second
|
||||
+; one is stereo, meant for everything else. The purpose of this unusual design
|
||||
+; is to provide separate volume controls for voice and other audio, which can
|
||||
+; be useful in gaming.
|
||||
+;
|
||||
+; Works with:
|
||||
+; Steelseries Arctis 7
|
||||
+; Steelseries Arctis Pro Wireless.
|
||||
+; Lucidsound LS31
|
||||
|
||||
[General]
|
||||
description-key = analog-input-microphone-headset
|
||||
diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf
|
||||
similarity index 66%
|
||||
rename from src/modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf
|
||||
rename to src/modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf
|
||||
index d8b24a2fbdf2..6df662f069e5 100644
|
||||
--- a/src/modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf
|
||||
+++ b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf
|
||||
@@ -13,11 +13,16 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-; Steelseries Arctis 7 USB headset mono output path. Works also with Arctis Pro
|
||||
-; Wireless. The headset has two output devices. The first one is mono, meant
|
||||
-; for voice audio, and the second one is stereo, meant for everything else. The
|
||||
-; purpose of this unusual design is to provide separate volume controls for
|
||||
-; voice and other audio, which can be useful in gaming.
|
||||
+; USB gaming headset mono output path. These headsets usually have two
|
||||
+; output devices. The first one is mono, meant for voice audio, and the second
|
||||
+; one is stereo, meant for everything else. The purpose of this unusual design
|
||||
+; is to provide separate volume controls for voice and other audio, which can
|
||||
+; be useful in gaming.
|
||||
+;
|
||||
+; Works with:
|
||||
+; Steelseries Arctis 7
|
||||
+; Steelseries Arctis Pro Wireless.
|
||||
+; Lucidsound LS31
|
||||
|
||||
[General]
|
||||
description-key = analog-output-headphones-mono
|
||||
diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf
|
||||
similarity index 68%
|
||||
rename from src/modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf
|
||||
rename to src/modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf
|
||||
index fcc58a033e2f..e3f91cd6cd2e 100644
|
||||
--- a/src/modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf
|
||||
+++ b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf
|
||||
@@ -13,11 +13,16 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-; Steelseries Arctis 7 USB headset stereo output path. Works also with Arctis
|
||||
-; Pro Wireless. The headset has two output devices. The first one is mono,
|
||||
-; meant for voice audio, and the second one is stereo, meant for everything
|
||||
-; else. The purpose of this unusual design is to provide separate volume
|
||||
-; controls for voice and other audio, which can be useful in gaming.
|
||||
+; USB gaming headset mono output path. These headsets usually have two
|
||||
+; output devices. The first one is mono, meant for voice audio, and the second
|
||||
+; one is stereo, meant for everything else. The purpose of this unusual design
|
||||
+; is to provide separate volume controls for voice and other audio, which can
|
||||
+; be useful in gaming.
|
||||
+;
|
||||
+; Works with:
|
||||
+; Steelseries Arctis 7
|
||||
+; Steelseries Arctis Pro Wireless.
|
||||
+; Lucidsound LS31
|
||||
;
|
||||
; This path doesn't provide hardware volume control, because the stereo
|
||||
; output is controlled by the PCM element with index 1, and currently
|
||||
diff --git a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf b/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf
|
||||
similarity index 79%
|
||||
rename from src/modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf
|
||||
rename to src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf
|
||||
index e1394dcfcc3b..01ecf864bcf2 100644
|
||||
--- a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf
|
||||
+++ b/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf
|
||||
@@ -13,12 +13,17 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-; Steelseries Arctis 7 USB and Arctis Pro Wireless USB headset. These headsets
|
||||
-; have a microphone and two output devices. The first output device is mono,
|
||||
-; meant for voice audio, and the second one is stereo, meant for everything
|
||||
-; else. The purpose of this unusual design is to provide separate volume
|
||||
+; USB gaming headset.
|
||||
+; These headsets usually have two output devices. The first one is mono,
|
||||
+; meant for voice audio, and the second one is stereo, meant for everything
|
||||
+; else. The purpose of this unusual design is to provide separate volume
|
||||
; controls for voice and other audio, which can be useful in gaming.
|
||||
;
|
||||
+; Works with:
|
||||
+; Steelseries Arctis 7
|
||||
+; Steelseries Arctis Pro Wireless.
|
||||
+; Lucidsound LS31
|
||||
+;
|
||||
; See default.conf for an explanation on the directives used here.
|
||||
|
||||
[General]
|
||||
@@ -27,13 +32,13 @@ auto-profiles = yes
|
||||
[Mapping analog-mono]
|
||||
device-strings = hw:%f,0,0
|
||||
channel-map = mono
|
||||
-paths-output = steelseries-arctis-7-output-mono
|
||||
-paths-input = steelseries-arctis-7-input
|
||||
+paths-output = usb-gaming-headset-output-mono
|
||||
+paths-input = usb-gaming-headset-input
|
||||
|
||||
[Mapping analog-stereo]
|
||||
device-strings = hw:%f,1,0
|
||||
channel-map = left,right
|
||||
-paths-output = steelseries-arctis-7-output-stereo
|
||||
+paths-output = usb-gaming-headset-output-stereo
|
||||
direction = output
|
||||
|
||||
[Profile output:analog-mono+output:analog-stereo+input:analog-mono]
|
||||
--
|
||||
2.16.4
|
||||
|
@ -0,0 +1,61 @@
|
||||
From c8f065250dde966825f171ff817f7301f423a42e Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Sat, 23 Nov 2019 15:17:30 +0100
|
||||
Subject: [PATCH] alsa-ucm: use ucm2 name for the direct card index open
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 28 ++++++++++++++++++----------
|
||||
1 file changed, 18 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 0a40ca8fe654..aeb4e59e323c 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -576,17 +576,25 @@ int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) {
|
||||
const char **verb_list;
|
||||
int num_verbs, i, err = 0;
|
||||
|
||||
- /* is UCM available for this card ? */
|
||||
- err = snd_card_get_name(card_index, &card_name);
|
||||
- if (err < 0) {
|
||||
- pa_log("Card can't get card_name from card_index %d", card_index);
|
||||
- goto name_fail;
|
||||
- }
|
||||
-
|
||||
+ /* support multiple card instances, address card directly by index */
|
||||
+ card_name = pa_sprintf_malloc("hw:%i", card_index);
|
||||
+ if (card_name == NULL)
|
||||
+ return -ENOMEM;
|
||||
err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
|
||||
if (err < 0) {
|
||||
- pa_log_info("UCM not available for card %s", card_name);
|
||||
- goto ucm_mgr_fail;
|
||||
+ /* fallback longname: is UCM available for this card ? */
|
||||
+ pa_xfree(card_name);
|
||||
+ err = snd_card_get_name(card_index, &card_name);
|
||||
+ if (err < 0) {
|
||||
+ pa_log("Card can't get card_name from card_index %d", card_index);
|
||||
+ goto name_fail;
|
||||
+ }
|
||||
+
|
||||
+ err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
|
||||
+ if (err < 0) {
|
||||
+ pa_log_info("UCM not available for card %s", card_name);
|
||||
+ goto ucm_mgr_fail;
|
||||
+ }
|
||||
}
|
||||
|
||||
pa_log_info("UCM available for card %s", card_name);
|
||||
@@ -626,7 +634,7 @@ ucm_verb_fail:
|
||||
}
|
||||
|
||||
ucm_mgr_fail:
|
||||
- free(card_name);
|
||||
+ pa_xfree(card_name);
|
||||
|
||||
name_fail:
|
||||
return err;
|
||||
--
|
||||
2.16.4
|
||||
|
72
0007-alsa-ucm-add-mixer-IDs-to-ucm_items.patch
Normal file
72
0007-alsa-ucm-add-mixer-IDs-to-ucm_items.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From ab5be56a10a83bfdfd7f40c02245db039e6eb730 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Sat, 23 Nov 2019 15:50:29 +0100
|
||||
Subject: [PATCH] alsa-ucm: add mixer IDs to ucm_items
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 6 ++++++
|
||||
src/modules/alsa/alsa-ucm.h | 18 ++++++++++++++++++
|
||||
2 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index aeb4e59e323c..14056825a25f 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -100,11 +100,17 @@ static struct ucm_items item[] = {
|
||||
{"CapturePCM", PA_ALSA_PROP_UCM_SOURCE},
|
||||
{"PlaybackVolume", PA_ALSA_PROP_UCM_PLAYBACK_VOLUME},
|
||||
{"PlaybackSwitch", PA_ALSA_PROP_UCM_PLAYBACK_SWITCH},
|
||||
+ {"PlaybackMixerElem", PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM},
|
||||
+ {"PlaybackMasterElem", PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM},
|
||||
+ {"PlaybackMasterType", PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE},
|
||||
{"PlaybackPriority", PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY},
|
||||
{"PlaybackRate", PA_ALSA_PROP_UCM_PLAYBACK_RATE},
|
||||
{"PlaybackChannels", PA_ALSA_PROP_UCM_PLAYBACK_CHANNELS},
|
||||
{"CaptureVolume", PA_ALSA_PROP_UCM_CAPTURE_VOLUME},
|
||||
{"CaptureSwitch", PA_ALSA_PROP_UCM_CAPTURE_SWITCH},
|
||||
+ {"CaptureMixerElem", PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM},
|
||||
+ {"CaptureMasterElem", PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM},
|
||||
+ {"CaptureMasterType", PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE},
|
||||
{"CapturePriority", PA_ALSA_PROP_UCM_CAPTURE_PRIORITY},
|
||||
{"CaptureRate", PA_ALSA_PROP_UCM_CAPTURE_RATE},
|
||||
{"CaptureChannels", PA_ALSA_PROP_UCM_CAPTURE_CHANNELS},
|
||||
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
|
||||
index c926f3cc39a6..4feb8c0bfc3f 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.h
|
||||
+++ b/src/modules/alsa/alsa-ucm.h
|
||||
@@ -51,6 +51,15 @@ typedef void snd_use_case_mgr_t;
|
||||
/** For devices: Playback switch e.g PlaybackSwitch */
|
||||
#define PA_ALSA_PROP_UCM_PLAYBACK_SWITCH "alsa.ucm.playback.switch"
|
||||
|
||||
+/** For devices: Playback mixer identifier */
|
||||
+#define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM "alsa.ucm.playback.mixer.element"
|
||||
+
|
||||
+/** For devices: Playback mixer master identifier */
|
||||
+#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM "alsa.ucm.playback.master.element"
|
||||
+
|
||||
+/** For devices: Playback mixer master type */
|
||||
+#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE "alsa.ucm.playback.master.type"
|
||||
+
|
||||
/** For devices: Playback priority */
|
||||
#define PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY "alsa.ucm.playback.priority"
|
||||
|
||||
@@ -69,6 +78,15 @@ typedef void snd_use_case_mgr_t;
|
||||
/** For devices: Capture switch e.g CaptureSwitch */
|
||||
#define PA_ALSA_PROP_UCM_CAPTURE_SWITCH "alsa.ucm.capture.switch"
|
||||
|
||||
+/** For devices: Capture mixer identifier */
|
||||
+#define PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM "alsa.ucm.capture.mixer.element"
|
||||
+
|
||||
+/** For devices: Capture mixer identifier */
|
||||
+#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM "alsa.ucm.capture.master.element"
|
||||
+
|
||||
+/** For devices: Capture mixer identifier */
|
||||
+#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE "alsa.ucm.capture.master.type"
|
||||
+
|
||||
/** For devices: Capture priority */
|
||||
#define PA_ALSA_PROP_UCM_CAPTURE_PRIORITY "alsa.ucm.capture.priority"
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
820
0008-alsa-mixer-handle-the-index-for-ALSA-mixer-element-i.patch
Normal file
820
0008-alsa-mixer-handle-the-index-for-ALSA-mixer-element-i.patch
Normal file
@ -0,0 +1,820 @@
|
||||
From 7f4b8e1a7c2c6a873ddb0207d9b407605bd3e7d6 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Sat, 23 Nov 2019 20:59:24 +0100
|
||||
Subject: [PATCH] alsa-mixer: handle the index for ALSA mixer element
|
||||
identifiers
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-mixer.c | 286 ++++++++++++++++++++++++++++++------------
|
||||
src/modules/alsa/alsa-mixer.h | 12 +-
|
||||
2 files changed, 217 insertions(+), 81 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
|
||||
index 1309cec5d8f8..38ace783a997 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.c
|
||||
+++ b/src/modules/alsa/alsa-mixer.c
|
||||
@@ -107,6 +107,33 @@ struct description_map {
|
||||
const char *description;
|
||||
};
|
||||
|
||||
+static char *alsa_id_str(char *dst, size_t dst_len, pa_alsa_mixer_id *id) {
|
||||
+ if (id->index > 0) {
|
||||
+ snprintf(dst, dst_len, "'%s',%d", id->name, id->index);
|
||||
+ } else {
|
||||
+ snprintf(dst, dst_len, "'%s'", id->name);
|
||||
+ }
|
||||
+ return dst;
|
||||
+}
|
||||
+
|
||||
+static int alsa_id_decode(const char *src, char *name, int *index) {
|
||||
+ char *idx;
|
||||
+
|
||||
+ *index = 0;
|
||||
+ strcpy(name, src);
|
||||
+ idx = strchr(name, ',');
|
||||
+ if (idx == NULL)
|
||||
+ return 0;
|
||||
+ *idx = '\0';
|
||||
+ idx++;
|
||||
+ if (*idx < '0' || *idx > '9') {
|
||||
+ pa_log("Element %s: index value is invalid", src);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ *index = atoi(idx);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *name) {
|
||||
pa_alsa_jack *jack;
|
||||
|
||||
@@ -641,6 +668,7 @@ static void decibel_fix_free(pa_alsa_decibel_fix *db_fix) {
|
||||
pa_xfree(db_fix->name);
|
||||
pa_xfree(db_fix->db_values);
|
||||
|
||||
+ pa_xfree(db_fix->key);
|
||||
pa_xfree(db_fix);
|
||||
}
|
||||
|
||||
@@ -656,7 +684,7 @@ static void element_free(pa_alsa_element *e) {
|
||||
if (e->db_fix)
|
||||
decibel_fix_free(e->db_fix);
|
||||
|
||||
- pa_xfree(e->alsa_name);
|
||||
+ pa_xfree(e->alsa_id.name);
|
||||
pa_xfree(e);
|
||||
}
|
||||
|
||||
@@ -717,11 +745,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) \
|
||||
- do { \
|
||||
- snd_mixer_selem_id_alloca(&(sid)); \
|
||||
- snd_mixer_selem_id_set_name((sid), (name)); \
|
||||
- snd_mixer_selem_id_set_index((sid), 0); \
|
||||
+#define SELEM_INIT(sid, aid) \
|
||||
+ do { \
|
||||
+ snd_mixer_selem_id_alloca(&(sid)); \
|
||||
+ snd_mixer_selem_id_set_name((sid), (aid)->name); \
|
||||
+ snd_mixer_selem_id_set_index((sid), (aid)->index); \
|
||||
} while(false)
|
||||
|
||||
static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v) {
|
||||
@@ -729,6 +757,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
||||
snd_mixer_elem_t *me;
|
||||
snd_mixer_selem_channel_id_t c;
|
||||
pa_channel_position_mask_t mask = 0;
|
||||
+ char buf[64];
|
||||
unsigned k;
|
||||
|
||||
pa_assert(m);
|
||||
@@ -736,9 +765,10 @@ 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_id);
|
||||
if (!(me = snd_mixer_find_selem(m, sid))) {
|
||||
- pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Element %s seems to have disappeared.", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -763,14 +793,16 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
||||
if (value < e->db_fix->min_step) {
|
||||
value = e->db_fix->min_step;
|
||||
snd_mixer_selem_set_playback_volume(me, c, value);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
pa_log_debug("Playback volume for element %s channel %i was below the dB fix limit. "
|
||||
- "Volume reset to %0.2f dB.", e->alsa_name, c,
|
||||
+ "Volume reset to %0.2f dB.", buf, c,
|
||||
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
|
||||
} else if (value > e->db_fix->max_step) {
|
||||
value = e->db_fix->max_step;
|
||||
snd_mixer_selem_set_playback_volume(me, c, value);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
pa_log_debug("Playback volume for element %s channel %i was over the dB fix limit. "
|
||||
- "Volume reset to %0.2f dB.", e->alsa_name, c,
|
||||
+ "Volume reset to %0.2f dB.", buf, c,
|
||||
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
|
||||
}
|
||||
|
||||
@@ -791,14 +823,16 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
||||
if (value < e->db_fix->min_step) {
|
||||
value = e->db_fix->min_step;
|
||||
snd_mixer_selem_set_capture_volume(me, c, value);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
pa_log_debug("Capture volume for element %s channel %i was below the dB fix limit. "
|
||||
- "Volume reset to %0.2f dB.", e->alsa_name, c,
|
||||
+ "Volume reset to %0.2f dB.", buf, c,
|
||||
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
|
||||
} else if (value > e->db_fix->max_step) {
|
||||
value = e->db_fix->max_step;
|
||||
snd_mixer_selem_set_capture_volume(me, c, value);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
pa_log_debug("Capture volume for element %s channel %i was over the dB fix limit. "
|
||||
- "Volume reset to %0.2f dB.", e->alsa_name, c,
|
||||
+ "Volume reset to %0.2f dB.", buf, c,
|
||||
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
|
||||
}
|
||||
|
||||
@@ -896,14 +930,16 @@ static int element_get_switch(pa_alsa_element *e, snd_mixer_t *m, bool *b) {
|
||||
snd_mixer_selem_id_t *sid;
|
||||
snd_mixer_elem_t *me;
|
||||
snd_mixer_selem_channel_id_t c;
|
||||
+ char buf[64];
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(e);
|
||||
pa_assert(b);
|
||||
|
||||
- SELEM_INIT(sid, e->alsa_name);
|
||||
+ SELEM_INIT(sid, &e->alsa_id);
|
||||
if (!(me = snd_mixer_find_selem(m, sid))) {
|
||||
- pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Element %s seems to have disappeared.", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1057,6 +1093,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
||||
snd_mixer_elem_t *me;
|
||||
snd_mixer_selem_channel_id_t c;
|
||||
pa_channel_position_mask_t mask = 0;
|
||||
+ char buf[64];
|
||||
unsigned k;
|
||||
|
||||
pa_assert(m);
|
||||
@@ -1065,9 +1102,10 @@ 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_id);
|
||||
if (!(me = snd_mixer_find_selem(m, sid))) {
|
||||
- pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Element %s seems to have disappeared.", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1250,14 +1288,16 @@ int pa_alsa_path_set_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_ma
|
||||
static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) {
|
||||
snd_mixer_elem_t *me;
|
||||
snd_mixer_selem_id_t *sid;
|
||||
+ char buf[64];
|
||||
int r;
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(e);
|
||||
|
||||
- SELEM_INIT(sid, e->alsa_name);
|
||||
+ SELEM_INIT(sid, &e->alsa_id);
|
||||
if (!(me = snd_mixer_find_selem(m, sid))) {
|
||||
- pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Element %s seems to have disappeared.", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1266,8 +1306,10 @@ static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) {
|
||||
else
|
||||
r = snd_mixer_selem_set_capture_switch_all(me, b);
|
||||
|
||||
- if (r < 0)
|
||||
- pa_log_warn("Failed to set switch of %s: %s", e->alsa_name, pa_alsa_strerror(errno));
|
||||
+ if (r < 0) {
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno));
|
||||
+ }
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -1302,13 +1344,15 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
|
||||
int r = 0;
|
||||
long volume = -1;
|
||||
bool volume_set = false;
|
||||
+ char buf[64];
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(e);
|
||||
|
||||
- SELEM_INIT(sid, e->alsa_name);
|
||||
+ SELEM_INIT(sid, &e->alsa_id);
|
||||
if (!(me = snd_mixer_find_selem(m, sid))) {
|
||||
- pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Element %s seems to have disappeared.", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1351,8 +1395,10 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
|
||||
r = snd_mixer_selem_set_capture_dB_all(me, 0, -1);
|
||||
}
|
||||
|
||||
- if (r < 0)
|
||||
- pa_log_warn("Failed to set volume of %s: %s", e->alsa_name, pa_alsa_strerror(errno));
|
||||
+ if (r < 0) {
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Failed to set volume of %s: %s", buf, pa_alsa_strerror(errno));
|
||||
+ }
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -1530,6 +1576,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
|
||||
int r;
|
||||
bool is_mono;
|
||||
pa_channel_position_t p;
|
||||
+ char buf[64];
|
||||
|
||||
if (e->direction == PA_ALSA_DIRECTION_OUTPUT) {
|
||||
if (!snd_mixer_selem_has_playback_volume(me)) {
|
||||
@@ -1555,29 +1602,33 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
|
||||
r = snd_mixer_selem_get_capture_volume_range(me, &e->min_volume, &e->max_volume);
|
||||
|
||||
if (r < 0) {
|
||||
- pa_log_warn("Failed to get volume range of %s: %s", e->alsa_name, pa_alsa_strerror(r));
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Failed to get volume range of %s: %s", buf, pa_alsa_strerror(r));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e->min_volume >= e->max_volume) {
|
||||
- pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.",
|
||||
- e->min_volume, e->max_volume);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Your kernel driver is broken for element %s: it reports a volume range from %li to %li which makes no sense.",
|
||||
+ buf, e->min_volume, e->max_volume);
|
||||
return false;
|
||||
}
|
||||
if (e->volume_use == PA_ALSA_VOLUME_CONSTANT && (e->min_volume > e->constant_volume || e->max_volume < e->constant_volume)) {
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
pa_log_warn("Constant volume %li configured for element %s, but the available range is from %li to %li.",
|
||||
- e->constant_volume, e->alsa_name, e->min_volume, e->max_volume);
|
||||
+ e->constant_volume, buf, e->min_volume, e->max_volume);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (e->db_fix && ((e->min_volume > e->db_fix->min_step) || (e->max_volume < e->db_fix->max_step))) {
|
||||
- pa_log_warn("The step range of the decibel fix for element %s (%li-%li) doesn't fit to the "
|
||||
- "real hardware range (%li-%li). Disabling the decibel fix.", e->alsa_name,
|
||||
- e->db_fix->min_step, e->db_fix->max_step, e->min_volume, e->max_volume);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("The step range of the decibel fix for element %s (%li-%li) doesn't fit to the "
|
||||
+ "real hardware range (%li-%li). Disabling the decibel fix.", buf,
|
||||
+ e->db_fix->min_step, e->db_fix->max_step, e->min_volume, e->max_volume);
|
||||
|
||||
- decibel_fix_free(e->db_fix);
|
||||
- e->db_fix = NULL;
|
||||
+ decibel_fix_free(e->db_fix);
|
||||
+ e->db_fix = NULL;
|
||||
}
|
||||
|
||||
if (e->db_fix) {
|
||||
@@ -1598,19 +1649,22 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
|
||||
long max_dB_checked = 0;
|
||||
|
||||
if (element_ask_vol_dB(me, e->direction, e->min_volume, &min_dB_checked) < 0) {
|
||||
- pa_log_warn("Failed to query the dB value for %s at volume level %li", e->alsa_name, e->min_volume);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Failed to query the dB value for %s at volume level %li", buf, e->min_volume);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (element_ask_vol_dB(me, e->direction, e->max_volume, &max_dB_checked) < 0) {
|
||||
- pa_log_warn("Failed to query the dB value for %s at volume level %li", e->alsa_name, e->max_volume);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Failed to query the dB value for %s at volume level %li", buf, e->max_volume);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (min_dB != min_dB_checked || max_dB != max_dB_checked) {
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
pa_log_warn("Your kernel driver is broken: the reported dB range for %s (from %0.2f dB to %0.2f dB) "
|
||||
"doesn't match the dB values at minimum and maximum volume levels: %0.2f dB at level %li, "
|
||||
- "%0.2f dB at level %li.", e->alsa_name, min_dB / 100.0, max_dB / 100.0,
|
||||
+ "%0.2f dB at level %li.", buf, min_dB / 100.0, max_dB / 100.0,
|
||||
min_dB_checked / 100.0, e->min_volume, max_dB_checked / 100.0, e->max_volume);
|
||||
return false;
|
||||
}
|
||||
@@ -1629,11 +1683,12 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
|
||||
}
|
||||
|
||||
if (e->volume_limit >= 0) {
|
||||
- if (e->volume_limit <= e->min_volume || e->volume_limit > e->max_volume)
|
||||
+ if (e->volume_limit <= e->min_volume || e->volume_limit > e->max_volume) {
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
pa_log_warn("Volume limit for element %s of path %s is invalid: %li isn't within the valid range "
|
||||
"%li-%li. The volume limit is ignored.",
|
||||
- e->alsa_name, e->path->name, e->volume_limit, e->min_volume + 1, e->max_volume);
|
||||
- else {
|
||||
+ buf, e->path->name, e->volume_limit, e->min_volume + 1, e->max_volume);
|
||||
+ } else {
|
||||
e->max_volume = e->volume_limit;
|
||||
|
||||
if (e->has_dB) {
|
||||
@@ -1641,7 +1696,8 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
|
||||
e->db_fix->max_step = e->max_volume;
|
||||
e->max_dB = ((double) e->db_fix->db_values[e->db_fix->max_step - e->db_fix->min_step]) / 100.0;
|
||||
} else if (element_ask_vol_dB(me, e->direction, e->max_volume, &max_dB) < 0) {
|
||||
- pa_log_warn("Failed to get dB value of %s: %s", e->alsa_name, pa_alsa_strerror(r));
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Failed to get dB value of %s: %s", buf, pa_alsa_strerror(r));
|
||||
e->has_dB = false;
|
||||
} else
|
||||
e->max_dB = ((double) max_dB) / 100.0;
|
||||
@@ -1681,7 +1737,8 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
|
||||
}
|
||||
|
||||
if (e->n_channels <= 0) {
|
||||
- pa_log_warn("Volume element %s with no channels?", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Volume element %s with no channels?", buf);
|
||||
return false;
|
||||
} else if (e->n_channels > 2) {
|
||||
/* FIXME: In some places code like this is used:
|
||||
@@ -1695,7 +1752,8 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
|
||||
* Since the array size is fixed at 2, we obviously
|
||||
* don't support elements with more than two
|
||||
* channels... */
|
||||
- pa_log_warn("Volume element %s has %u channels. That's too much! I can't handle that!", e->alsa_name, e->n_channels);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Volume element %s has %u channels. That's too much! I can't handle that!", buf, e->n_channels);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1733,7 +1791,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_id);
|
||||
|
||||
if (!(me = snd_mixer_find_selem(m, sid))) {
|
||||
|
||||
@@ -1854,6 +1912,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 *name;
|
||||
+ int index;
|
||||
|
||||
pa_assert(p);
|
||||
pa_assert(section);
|
||||
@@ -1869,16 +1929,22 @@ 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))
|
||||
+ name = alloca(strlen(section) + 1);
|
||||
+ if (alsa_id_decode(section, name, &index))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (p->last_element && pa_streq(p->last_element->alsa_id.name, name) &&
|
||||
+ p->last_element->alsa_id.index == index)
|
||||
return p->last_element;
|
||||
|
||||
PA_LLIST_FOREACH(e, p->elements)
|
||||
- if (pa_streq(e->alsa_name, section))
|
||||
+ if (pa_streq(e->alsa_id.name, name) && e->alsa_id.index == index)
|
||||
goto finish;
|
||||
|
||||
e = pa_xnew0(pa_alsa_element, 1);
|
||||
e->path = p;
|
||||
- e->alsa_name = pa_xstrdup(section);
|
||||
+ e->alsa_id.name = pa_xstrdup(name);
|
||||
+ e->alsa_id.index = index;
|
||||
e->direction = p->direction;
|
||||
e->volume_limit = -1;
|
||||
|
||||
@@ -1912,10 +1978,12 @@ finish:
|
||||
}
|
||||
|
||||
static pa_alsa_option* option_get(pa_alsa_path *p, const char *section) {
|
||||
- char *en;
|
||||
+ char *en, *name;
|
||||
const char *on;
|
||||
pa_alsa_option *o;
|
||||
pa_alsa_element *e;
|
||||
+ size_t len;
|
||||
+ int index;
|
||||
|
||||
if (!pa_startswith(section, "Option "))
|
||||
return NULL;
|
||||
@@ -1926,18 +1994,25 @@ static pa_alsa_option* option_get(pa_alsa_path *p, const char *section) {
|
||||
if (!(on = strchr(section, ':')))
|
||||
return NULL;
|
||||
|
||||
- en = pa_xstrndup(section, on - section);
|
||||
+ len = on - section;
|
||||
+ en = alloca(len + 1);
|
||||
+ strncpy(en, section, len);
|
||||
+ en[len] = '\0';
|
||||
+
|
||||
+ name = alloca(strlen(en) + 1);
|
||||
+ if (alsa_id_decode(en, name, &index))
|
||||
+ return NULL;
|
||||
+
|
||||
on++;
|
||||
|
||||
if (p->last_option &&
|
||||
- pa_streq(p->last_option->element->alsa_name, en) &&
|
||||
+ pa_streq(p->last_option->element->alsa_id.name, name) &&
|
||||
+ p->last_option->element->alsa_id.index == index &&
|
||||
pa_streq(p->last_option->alsa_name, on)) {
|
||||
- pa_xfree(en);
|
||||
return p->last_option;
|
||||
}
|
||||
|
||||
pa_assert_se(e = element_get(p, en, false));
|
||||
- pa_xfree(en);
|
||||
|
||||
PA_LLIST_FOREACH(o, e->options)
|
||||
if (pa_streq(o->alsa_name, on))
|
||||
@@ -2393,14 +2468,16 @@ static int jack_parse_append_pcm_to_name(pa_config_parser_state *state) {
|
||||
static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx) {
|
||||
snd_mixer_selem_id_t *sid;
|
||||
snd_mixer_elem_t *me;
|
||||
+ char buf[64];
|
||||
int r;
|
||||
|
||||
pa_assert(e);
|
||||
pa_assert(m);
|
||||
|
||||
- SELEM_INIT(sid, e->alsa_name);
|
||||
+ SELEM_INIT(sid, &e->alsa_id);
|
||||
if (!(me = snd_mixer_find_selem(m, sid))) {
|
||||
- pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Element %s seems to have disappeared.", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2411,14 +2488,18 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
|
||||
else
|
||||
r = snd_mixer_selem_set_capture_switch_all(me, alsa_idx);
|
||||
|
||||
- if (r < 0)
|
||||
- pa_log_warn("Failed to set switch of %s: %s", e->alsa_name, pa_alsa_strerror(errno));
|
||||
+ if (r < 0) {
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno));
|
||||
+ }
|
||||
|
||||
} else {
|
||||
pa_assert(e->enumeration_use == PA_ALSA_ENUMERATION_SELECT);
|
||||
|
||||
- if ((r = snd_mixer_selem_set_enum_item(me, 0, alsa_idx)) < 0)
|
||||
- pa_log_warn("Failed to set enumeration of %s: %s", e->alsa_name, pa_alsa_strerror(errno));
|
||||
+ if ((r = snd_mixer_selem_set_enum_item(me, 0, alsa_idx)) < 0) {
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Failed to set enumeration of %s: %s", buf, pa_alsa_strerror(errno));
|
||||
+ }
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -2462,6 +2543,7 @@ static int option_verify(pa_alsa_option *o) {
|
||||
{ "output-speaker", N_("Speaker") },
|
||||
{ "output-headphones", N_("Headphones") }
|
||||
};
|
||||
+ char buf[64];
|
||||
|
||||
pa_assert(o);
|
||||
|
||||
@@ -2472,14 +2554,16 @@ static int option_verify(pa_alsa_option *o) {
|
||||
|
||||
if (o->element->enumeration_use != PA_ALSA_ENUMERATION_SELECT &&
|
||||
o->element->switch_use != PA_ALSA_SWITCH_SELECT) {
|
||||
- pa_log("Element %s of option %s not set for select.", o->element->alsa_name, o->name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &o->element->alsa_id);
|
||||
+ pa_log("Element %s of option %s not set for select.", buf, o->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (o->element->switch_use == PA_ALSA_SWITCH_SELECT &&
|
||||
!pa_streq(o->alsa_name, "on") &&
|
||||
!pa_streq(o->alsa_name, "off")) {
|
||||
- pa_log("Switch %s options need be named off or on ", o->element->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &o->element->alsa_id);
|
||||
+ pa_log("Switch %s options need be named off or on ", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2495,6 +2579,7 @@ static int option_verify(pa_alsa_option *o) {
|
||||
|
||||
static int element_verify(pa_alsa_element *e) {
|
||||
pa_alsa_option *o;
|
||||
+ char buf[64];
|
||||
|
||||
pa_assert(e);
|
||||
|
||||
@@ -2503,12 +2588,14 @@ static int element_verify(pa_alsa_element *e) {
|
||||
(e->required_any != PA_ALSA_REQUIRED_IGNORE && e->required_any == e->required_absent) ||
|
||||
(e->required_absent == PA_ALSA_REQUIRED_ANY && e->required_any != PA_ALSA_REQUIRED_IGNORE) ||
|
||||
(e->required_absent == PA_ALSA_REQUIRED_ANY && e->required != PA_ALSA_REQUIRED_IGNORE)) {
|
||||
- pa_log("Element %s cannot be required and absent at the same time.", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log("Element %s cannot be required and absent at the same time.", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (e->switch_use == PA_ALSA_SWITCH_SELECT && e->enumeration_use == PA_ALSA_ENUMERATION_SELECT) {
|
||||
- pa_log("Element %s cannot set select for both switch and enumeration.", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log("Element %s cannot set select for both switch and enumeration.", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2660,9 +2747,15 @@ 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 *name;
|
||||
+ int index;
|
||||
|
||||
pa_assert(element);
|
||||
|
||||
+ name = alloca(strlen(element) + 1);
|
||||
+ if (alsa_id_decode(element, name, &index))
|
||||
+ return NULL;
|
||||
+
|
||||
p = pa_xnew0(pa_alsa_path, 1);
|
||||
p->name = pa_xstrdup(element);
|
||||
p->direction = direction;
|
||||
@@ -2670,7 +2763,8 @@ pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t d
|
||||
|
||||
e = pa_xnew0(pa_alsa_element, 1);
|
||||
e->path = p;
|
||||
- e->alsa_name = pa_xstrdup(element);
|
||||
+ e->alsa_id.name = pa_xstrdup(name);
|
||||
+ e->alsa_id.index = index;
|
||||
e->direction = direction;
|
||||
e->volume_limit = -1;
|
||||
|
||||
@@ -2820,6 +2914,7 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
|
||||
double min_dB[PA_CHANNEL_POSITION_MAX], max_dB[PA_CHANNEL_POSITION_MAX];
|
||||
pa_channel_position_t t;
|
||||
pa_channel_position_mask_t path_volume_channels = 0;
|
||||
+ char buf[64];
|
||||
|
||||
pa_assert(p);
|
||||
pa_assert(m);
|
||||
@@ -2843,12 +2938,13 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
|
||||
}
|
||||
|
||||
PA_LLIST_FOREACH(e, p->elements) {
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
if (element_probe(e, m) < 0) {
|
||||
p->supported = false;
|
||||
- pa_log_debug("Probe of element '%s' failed.", e->alsa_name);
|
||||
+ pa_log_debug("Probe of element %s failed.", buf);
|
||||
return -1;
|
||||
}
|
||||
- pa_log_debug("Probe of element '%s' succeeded (volume=%d, switch=%d, enumeration=%d).", e->alsa_name, e->volume_use, e->switch_use, e->enumeration_use);
|
||||
+ pa_log_debug("Probe of element %s succeeded (volume=%d, switch=%d, enumeration=%d).", buf, e->volume_use, e->switch_use, e->enumeration_use);
|
||||
|
||||
if (ignore_dB)
|
||||
e->has_dB = false;
|
||||
@@ -2884,13 +2980,13 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
|
||||
* which cannot do dB volumes, so we we need
|
||||
* to 'neutralize' this slider */
|
||||
e->volume_use = PA_ALSA_VOLUME_ZERO;
|
||||
- pa_log_info("Zeroing volume of '%s' on path '%s'", e->alsa_name, p->name);
|
||||
+ pa_log_info("Zeroing volume of %s on path '%s'", buf, p->name);
|
||||
}
|
||||
}
|
||||
} else if (p->has_volume) {
|
||||
/* We can't use this volume, so let's ignore it */
|
||||
e->volume_use = PA_ALSA_VOLUME_IGNORE;
|
||||
- pa_log_info("Ignoring volume of '%s' on path '%s' (missing dB info)", e->alsa_name, p->name);
|
||||
+ pa_log_info("Ignoring volume of %s on path '%s' (missing dB info)", buf, p->name);
|
||||
}
|
||||
p->has_volume = true;
|
||||
}
|
||||
@@ -2954,11 +3050,14 @@ void pa_alsa_option_dump(pa_alsa_option *o) {
|
||||
}
|
||||
|
||||
void pa_alsa_element_dump(pa_alsa_element *e) {
|
||||
+ char buf[64];
|
||||
+
|
||||
pa_alsa_option *o;
|
||||
pa_assert(e);
|
||||
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
pa_log_debug("Element %s, direction=%i, switch=%i, volume=%i, volume_limit=%li, enumeration=%i, required=%i, required_any=%i, required_absent=%i, mask=0x%llx, n_channels=%u, override_map=%s",
|
||||
- e->alsa_name,
|
||||
+ buf,
|
||||
e->direction,
|
||||
e->switch_use,
|
||||
e->volume_use,
|
||||
@@ -3008,14 +3107,16 @@ void pa_alsa_path_dump(pa_alsa_path *p) {
|
||||
static void element_set_callback(pa_alsa_element *e, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata) {
|
||||
snd_mixer_selem_id_t *sid;
|
||||
snd_mixer_elem_t *me;
|
||||
+ char buf[64];
|
||||
|
||||
pa_assert(e);
|
||||
pa_assert(m);
|
||||
pa_assert(cb);
|
||||
|
||||
- SELEM_INIT(sid, e->alsa_name);
|
||||
+ SELEM_INIT(sid, &e->alsa_id);
|
||||
if (!(me = snd_mixer_find_selem(m, sid))) {
|
||||
- pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &e->alsa_id);
|
||||
+ pa_log_warn("Element %s seems to have disappeared.", buf);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3081,6 +3182,8 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d
|
||||
char **pn = NULL, **en = NULL, **ie;
|
||||
pa_alsa_decibel_fix *db_fix;
|
||||
void *state, *state2;
|
||||
+ char name[64];
|
||||
+ int index;
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(m->profile_set);
|
||||
@@ -3160,9 +3263,18 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d
|
||||
if (je == ie)
|
||||
continue;
|
||||
|
||||
+ if (strlen(*je) + 1 >= sizeof(name)) {
|
||||
+ pa_log("Element identifier %s is too long!", *je);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (alsa_id_decode(*je, name, &index))
|
||||
+ continue;
|
||||
+
|
||||
e = pa_xnew0(pa_alsa_element, 1);
|
||||
e->path = p;
|
||||
- e->alsa_name = pa_xstrdup(*je);
|
||||
+ e->alsa_id.name = pa_xstrdup(name);
|
||||
+ e->alsa_id.index = index;
|
||||
e->direction = direction;
|
||||
e->required_absent = PA_ALSA_REQUIRED_ANY;
|
||||
e->volume_limit = -1;
|
||||
@@ -3183,7 +3295,8 @@ finish:
|
||||
pa_alsa_element *e;
|
||||
|
||||
PA_LLIST_FOREACH(e, p->elements) {
|
||||
- if (e->volume_use != PA_ALSA_VOLUME_IGNORE && pa_streq(db_fix->name, e->alsa_name)) {
|
||||
+ if (e->volume_use != PA_ALSA_VOLUME_IGNORE && pa_streq(db_fix->name, e->alsa_id.name) &&
|
||||
+ db_fix->index == e->alsa_id.index) {
|
||||
/* The profile set that contains the dB fix may be freed
|
||||
* before the element, so we have to copy the dB fix
|
||||
* object. */
|
||||
@@ -3256,6 +3369,8 @@ static bool enumeration_is_subset(pa_alsa_option *a_options, pa_alsa_option *b_o
|
||||
* Compares two elements to see if a is a subset of b
|
||||
*/
|
||||
static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_t *m) {
|
||||
+ char buf[64];
|
||||
+
|
||||
pa_assert(a);
|
||||
pa_assert(b);
|
||||
pa_assert(m);
|
||||
@@ -3293,9 +3408,10 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_
|
||||
snd_mixer_selem_id_t *sid;
|
||||
snd_mixer_elem_t *me;
|
||||
|
||||
- SELEM_INIT(sid, a->alsa_name);
|
||||
+ SELEM_INIT(sid, &a->alsa_id);
|
||||
if (!(me = snd_mixer_find_selem(m, sid))) {
|
||||
- pa_log_warn("Element %s seems to have disappeared.", a->alsa_name);
|
||||
+ alsa_id_str(buf, sizeof(buf), &a->alsa_id);
|
||||
+ pa_log_warn("Element %s seems to have disappeared.", buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3325,8 +3441,9 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_
|
||||
return false;
|
||||
for (s = 0; s <= SND_MIXER_SCHN_LAST; s++)
|
||||
if (a->masks[s][a->n_channels-1] != b->masks[s][b->n_channels-1]) {
|
||||
+ alsa_id_str(buf, sizeof(buf), &a->alsa_id);
|
||||
pa_log_debug("Element %s is not a subset - mask a: 0x%" PRIx64 ", mask b: 0x%" PRIx64 ", at channel %d",
|
||||
- a->alsa_name, a->masks[s][a->n_channels-1], b->masks[s][b->n_channels-1], s);
|
||||
+ buf, a->masks[s][a->n_channels-1], b->masks[s][b->n_channels-1], s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3423,7 +3540,8 @@ static void path_set_condense(pa_alsa_path_set *ps, snd_mixer_t *m) {
|
||||
break;
|
||||
|
||||
PA_LLIST_FOREACH(eb, p2->elements) {
|
||||
- if (pa_streq(ea->alsa_name, eb->alsa_name)) {
|
||||
+ if (pa_streq(ea->alsa_id.name, eb->alsa_id.name) &&
|
||||
+ ea->alsa_id.index == eb->alsa_id.index) {
|
||||
found_matching_element = true;
|
||||
is_subset = element_is_subset(ea, eb, m);
|
||||
break;
|
||||
@@ -3600,22 +3718,30 @@ static pa_alsa_profile *profile_get(pa_alsa_profile_set *ps, const char *name) {
|
||||
return p;
|
||||
}
|
||||
|
||||
-static pa_alsa_decibel_fix *decibel_fix_get(pa_alsa_profile_set *ps, const char *name) {
|
||||
+static pa_alsa_decibel_fix *decibel_fix_get(pa_alsa_profile_set *ps, const char *alsa_id) {
|
||||
pa_alsa_decibel_fix *db_fix;
|
||||
+ char *name;
|
||||
+ int index;
|
||||
|
||||
- if (!pa_startswith(name, "DecibelFix "))
|
||||
+ if (!pa_startswith(alsa_id, "DecibelFix "))
|
||||
return NULL;
|
||||
|
||||
- name += 11;
|
||||
+ alsa_id += 11;
|
||||
|
||||
- if ((db_fix = pa_hashmap_get(ps->decibel_fixes, name)))
|
||||
+ if ((db_fix = pa_hashmap_get(ps->decibel_fixes, alsa_id)))
|
||||
return db_fix;
|
||||
|
||||
+ name = alloca(strlen(alsa_id) + 1);
|
||||
+ if (alsa_id_decode(alsa_id, name, &index))
|
||||
+ return NULL;
|
||||
+
|
||||
db_fix = pa_xnew0(pa_alsa_decibel_fix, 1);
|
||||
db_fix->profile_set = ps;
|
||||
db_fix->name = pa_xstrdup(name);
|
||||
+ db_fix->index = index;
|
||||
+ db_fix->key = pa_xstrdup(alsa_id);
|
||||
|
||||
- pa_hashmap_put(ps->decibel_fixes, db_fix->name, db_fix);
|
||||
+ pa_hashmap_put(ps->decibel_fixes, db_fix->key, db_fix);
|
||||
|
||||
return db_fix;
|
||||
}
|
||||
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
|
||||
index 65b071165c6b..709f270fbfa5 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.h
|
||||
+++ b/src/modules/alsa/alsa-mixer.h
|
||||
@@ -34,6 +34,7 @@
|
||||
typedef struct pa_alsa_fdlist pa_alsa_fdlist;
|
||||
typedef struct pa_alsa_mixer_pdata pa_alsa_mixer_pdata;
|
||||
typedef struct pa_alsa_setting pa_alsa_setting;
|
||||
+typedef struct pa_alsa_mixer_id pa_alsa_mixer_id;
|
||||
typedef struct pa_alsa_option pa_alsa_option;
|
||||
typedef struct pa_alsa_element pa_alsa_element;
|
||||
typedef struct pa_alsa_jack pa_alsa_jack;
|
||||
@@ -97,6 +98,12 @@ struct pa_alsa_setting {
|
||||
unsigned priority;
|
||||
};
|
||||
|
||||
+/* ALSA mixer element identifier */
|
||||
+struct pa_alsa_mixer_id {
|
||||
+ char *name;
|
||||
+ int index;
|
||||
+};
|
||||
+
|
||||
/* An option belongs to an element and refers to one enumeration item
|
||||
* of the element is an enumeration item, or a switch status if the
|
||||
* element is a switch item. */
|
||||
@@ -123,7 +130,7 @@ struct pa_alsa_element {
|
||||
pa_alsa_path *path;
|
||||
PA_LLIST_FIELDS(pa_alsa_element);
|
||||
|
||||
- char *alsa_name;
|
||||
+ struct pa_alsa_mixer_id alsa_id;
|
||||
pa_alsa_direction_t direction;
|
||||
|
||||
pa_alsa_switch_use_t switch_use;
|
||||
@@ -315,9 +322,12 @@ struct pa_alsa_profile {
|
||||
};
|
||||
|
||||
struct pa_alsa_decibel_fix {
|
||||
+ char *key;
|
||||
+
|
||||
pa_alsa_profile_set *profile_set;
|
||||
|
||||
char *name; /* Alsa volume element name. */
|
||||
+ int index; /* Alsa volume element index. */
|
||||
long min_step;
|
||||
long max_step;
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
51
0009-alsa-mixer-improve-alsa_id_decode-function.patch
Normal file
51
0009-alsa-mixer-improve-alsa_id_decode-function.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 1c240b7a12e9e2f7c2266d18cbb74130bb81277e Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Tue, 26 Nov 2019 10:35:14 +0100
|
||||
Subject: [PATCH] alsa-mixer: improve alsa_id_decode() function
|
||||
|
||||
Accept those identifiers:
|
||||
|
||||
Speaker,1
|
||||
'Speaker',1
|
||||
"Speaker",1
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-mixer.c | 19 ++++++++++++++++---
|
||||
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
|
||||
index 38ace783a997..f57aabe5d885 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.c
|
||||
+++ b/src/modules/alsa/alsa-mixer.c
|
||||
@@ -117,11 +117,24 @@ static char *alsa_id_str(char *dst, size_t dst_len, pa_alsa_mixer_id *id) {
|
||||
}
|
||||
|
||||
static int alsa_id_decode(const char *src, char *name, int *index) {
|
||||
- char *idx;
|
||||
+ char *idx, c;
|
||||
+ int i;
|
||||
|
||||
*index = 0;
|
||||
- strcpy(name, src);
|
||||
- idx = strchr(name, ',');
|
||||
+ c = src[0];
|
||||
+ /* Strip quotes in entries such as 'Speaker',1 or "Speaker",1 */
|
||||
+ if (c == '\'' || c == '"') {
|
||||
+ strcpy(name, src + 1);
|
||||
+ for (i = 0; name[i] != '\0' && name[i] != c; i++);
|
||||
+ idx = NULL;
|
||||
+ if (name[i]) {
|
||||
+ name[i] = '\0';
|
||||
+ idx = strchr(name + i + 1, ',');
|
||||
+ }
|
||||
+ } else {
|
||||
+ strcpy(name, src);
|
||||
+ idx = strchr(name, ',');
|
||||
+ }
|
||||
if (idx == NULL)
|
||||
return 0;
|
||||
*idx = '\0';
|
||||
--
|
||||
2.16.4
|
||||
|
795
0010-alsa-ucm-Support-Playback-CaptureVolume.patch
Normal file
795
0010-alsa-ucm-Support-Playback-CaptureVolume.patch
Normal file
@ -0,0 +1,795 @@
|
||||
From 3dfccada466bef64f73ef9be3d94eaee7b6f9a60 Mon Sep 17 00:00:00 2001
|
||||
From: Arun Raghavan <git@arunraghavan.net>
|
||||
Date: Tue, 3 May 2016 18:22:10 +0530
|
||||
Subject: [PATCH] alsa-ucm: Support Playback/CaptureVolume
|
||||
|
||||
This allows us to support the PlaybackVolume and CaptureVolume commands
|
||||
in UCM, specifying a mixer control to use for hardware volume control.
|
||||
This only works with ports corresponding to single devices at the
|
||||
moment, and doesn't support stacking controls for combination ports.
|
||||
|
||||
The configuration is intended to provide a control (like Headphone
|
||||
Playback Volume), but we try to resolve to a simple mixer control
|
||||
(Headphone) to reuse existing volume paths.
|
||||
|
||||
On the UCM side, this also requires that when disabling the device for
|
||||
the port, the volume should be reset to some default.
|
||||
|
||||
When enabling/disabling combination devices, things are a bit iffy since
|
||||
we have no way to reset the volume before switching to a combination
|
||||
device. It would be nice to have a combination-transition-sequence
|
||||
command in UCM to handle this and other similar cases.
|
||||
|
||||
PlaybackSwitch and CaptureSwitch are yet to be implemented.
|
||||
---
|
||||
src/modules/alsa/alsa-sink.c | 70 +++++++++++----
|
||||
src/modules/alsa/alsa-source.c | 68 +++++++++++----
|
||||
src/modules/alsa/alsa-ucm.c | 165 +++++++++++++++++++++++++++++-------
|
||||
src/modules/alsa/alsa-ucm.h | 26 +++++-
|
||||
src/modules/alsa/module-alsa-card.c | 4 +-
|
||||
src/pulsecore/core-util.c | 26 ++++++
|
||||
src/pulsecore/core-util.h | 2 +
|
||||
7 files changed, 295 insertions(+), 66 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
|
||||
index 4b46708ce4a3..08d4d1f38b80 100644
|
||||
--- a/src/modules/alsa/alsa-sink.c
|
||||
+++ b/src/modules/alsa/alsa-sink.c
|
||||
@@ -1598,7 +1598,7 @@ static void sink_set_mute_cb(pa_sink *s) {
|
||||
static void mixer_volume_init(struct userdata *u) {
|
||||
pa_assert(u);
|
||||
|
||||
- if (!u->mixer_path->has_volume) {
|
||||
+ if (!u->mixer_path || !u->mixer_path->has_volume) {
|
||||
pa_sink_set_write_volume_callback(u->sink, NULL);
|
||||
pa_sink_set_get_volume_callback(u->sink, NULL);
|
||||
pa_sink_set_set_volume_callback(u->sink, NULL);
|
||||
@@ -1633,7 +1633,7 @@ static void mixer_volume_init(struct userdata *u) {
|
||||
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->mixer_path->has_dB ? "supported" : "not supported");
|
||||
}
|
||||
|
||||
- if (!u->mixer_path->has_mute) {
|
||||
+ if (!u->mixer_path || !u->mixer_path->has_mute) {
|
||||
pa_sink_set_get_mute_callback(u->sink, NULL);
|
||||
pa_sink_set_set_mute_callback(u->sink, NULL);
|
||||
pa_log_info("Driver does not support hardware mute control, falling back to software mute control.");
|
||||
@@ -1646,11 +1646,31 @@ static void mixer_volume_init(struct userdata *u) {
|
||||
|
||||
static int sink_set_port_ucm_cb(pa_sink *s, pa_device_port *p) {
|
||||
struct userdata *u = s->userdata;
|
||||
+ pa_alsa_ucm_port_data *data;
|
||||
+
|
||||
+ data = PA_DEVICE_PORT_DATA(p);
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(p);
|
||||
pa_assert(u->ucm_context);
|
||||
|
||||
+ u->mixer_path = data->path;
|
||||
+ mixer_volume_init(u);
|
||||
+
|
||||
+ if (u->mixer_path) {
|
||||
+ pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, s->muted);
|
||||
+
|
||||
+ if (s->set_mute)
|
||||
+ s->set_mute(s);
|
||||
+ if (s->flags & PA_SINK_DEFERRED_VOLUME) {
|
||||
+ if (s->write_volume)
|
||||
+ s->write_volume(s);
|
||||
+ } else {
|
||||
+ if (s->set_volume)
|
||||
+ s->set_volume(s);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return pa_alsa_ucm_set_port(u->ucm_context, p, true);
|
||||
}
|
||||
|
||||
@@ -2079,6 +2099,11 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (u->ucm_context) {
|
||||
+ /* We just want to open the device */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (element) {
|
||||
|
||||
if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_OUTPUT)))
|
||||
@@ -2116,16 +2141,31 @@ static int setup_mixer(struct userdata *u, bool ignore_dB) {
|
||||
return 0;
|
||||
|
||||
if (u->sink->active_port) {
|
||||
- pa_alsa_port_data *data;
|
||||
+ if (!u->ucm_context) {
|
||||
+ pa_alsa_port_data *data;
|
||||
|
||||
- /* We have a list of supported paths, so let's activate the
|
||||
- * one that has been chosen as active */
|
||||
+ /* We have a list of supported paths, so let's activate the
|
||||
+ * one that has been chosen as active */
|
||||
+
|
||||
+ data = PA_DEVICE_PORT_DATA(u->sink->active_port);
|
||||
+ u->mixer_path = data->path;
|
||||
+
|
||||
+ pa_alsa_path_select(data->path, data->setting, u->mixer_handle, u->sink->muted);
|
||||
+ } else {
|
||||
+ pa_alsa_ucm_port_data *data;
|
||||
|
||||
- data = PA_DEVICE_PORT_DATA(u->sink->active_port);
|
||||
- u->mixer_path = data->path;
|
||||
+ /* First activate the port on the UCM side */
|
||||
+ if (pa_alsa_ucm_set_port(u->ucm_context, u->sink->active_port, true) < 0)
|
||||
+ return -1;
|
||||
|
||||
- pa_alsa_path_select(data->path, data->setting, u->mixer_handle, u->sink->muted);
|
||||
+ data = PA_DEVICE_PORT_DATA(u->sink->active_port);
|
||||
|
||||
+ /* Now activate volume controls, if any */
|
||||
+ if (data->path) {
|
||||
+ u->mixer_path = data->path;
|
||||
+ pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, u->sink->muted);
|
||||
+ }
|
||||
+ }
|
||||
} else {
|
||||
|
||||
if (!u->mixer_path && u->mixer_path_set)
|
||||
@@ -2135,7 +2175,6 @@ static int setup_mixer(struct userdata *u, bool ignore_dB) {
|
||||
/* Hmm, we have only a single path, then let's activate it */
|
||||
|
||||
pa_alsa_path_select(u->mixer_path, u->mixer_path->settings, u->mixer_handle, u->sink->muted);
|
||||
-
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
@@ -2466,8 +2505,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||
/* ALSA might tweak the sample spec, so recalculate the frame size */
|
||||
frame_size = pa_frame_size(&ss);
|
||||
|
||||
- if (!u->ucm_context)
|
||||
- find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB);
|
||||
+ find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB);
|
||||
|
||||
pa_sink_new_data_init(&data);
|
||||
data.driver = driver;
|
||||
@@ -2524,7 +2562,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||
}
|
||||
|
||||
if (u->ucm_context)
|
||||
- pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, true, card);
|
||||
+ pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, true, card, u->pcm_handle, ignore_dB);
|
||||
else if (u->mixer_path_set)
|
||||
pa_alsa_add_ports(&data, u->mixer_path_set, card);
|
||||
|
||||
@@ -2598,10 +2636,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||
if (update_sw_params(u, false) < 0)
|
||||
goto fail;
|
||||
|
||||
- if (u->ucm_context) {
|
||||
- if (u->sink->active_port && pa_alsa_ucm_set_port(u->ucm_context, u->sink->active_port, true) < 0)
|
||||
- goto fail;
|
||||
- } else if (setup_mixer(u, ignore_dB) < 0)
|
||||
+ if (setup_mixer(u, ignore_dB) < 0)
|
||||
goto fail;
|
||||
|
||||
pa_alsa_dump(PA_LOG_DEBUG, u->pcm_handle);
|
||||
@@ -2725,7 +2760,8 @@ static void userdata_free(struct userdata *u) {
|
||||
if (u->mixer_fdl)
|
||||
pa_alsa_fdlist_free(u->mixer_fdl);
|
||||
|
||||
- if (u->mixer_path && !u->mixer_path_set)
|
||||
+ /* Only free the mixer_path if the sink owns it */
|
||||
+ if (u->mixer_path && !u->mixer_path_set && !u->ucm_context)
|
||||
pa_alsa_path_free(u->mixer_path);
|
||||
|
||||
if (u->mixer_handle)
|
||||
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
|
||||
index c8bf649e1730..657ed5aeda11 100644
|
||||
--- a/src/modules/alsa/alsa-source.c
|
||||
+++ b/src/modules/alsa/alsa-source.c
|
||||
@@ -1469,7 +1469,7 @@ static void source_set_mute_cb(pa_source *s) {
|
||||
static void mixer_volume_init(struct userdata *u) {
|
||||
pa_assert(u);
|
||||
|
||||
- if (!u->mixer_path->has_volume) {
|
||||
+ if (!u->mixer_path || !u->mixer_path->has_volume) {
|
||||
pa_source_set_write_volume_callback(u->source, NULL);
|
||||
pa_source_set_get_volume_callback(u->source, NULL);
|
||||
pa_source_set_set_volume_callback(u->source, NULL);
|
||||
@@ -1504,7 +1504,7 @@ static void mixer_volume_init(struct userdata *u) {
|
||||
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->mixer_path->has_dB ? "supported" : "not supported");
|
||||
}
|
||||
|
||||
- if (!u->mixer_path->has_mute) {
|
||||
+ if (!u->mixer_path || !u->mixer_path->has_mute) {
|
||||
pa_source_set_get_mute_callback(u->source, NULL);
|
||||
pa_source_set_set_mute_callback(u->source, NULL);
|
||||
pa_log_info("Driver does not support hardware mute control, falling back to software mute control.");
|
||||
@@ -1517,11 +1517,31 @@ static void mixer_volume_init(struct userdata *u) {
|
||||
|
||||
static int source_set_port_ucm_cb(pa_source *s, pa_device_port *p) {
|
||||
struct userdata *u = s->userdata;
|
||||
+ pa_alsa_ucm_port_data *data;
|
||||
+
|
||||
+ data = PA_DEVICE_PORT_DATA(p);
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(p);
|
||||
pa_assert(u->ucm_context);
|
||||
|
||||
+ u->mixer_path = data->path;
|
||||
+ mixer_volume_init(u);
|
||||
+
|
||||
+ if (u->mixer_path) {
|
||||
+ pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, s->muted);
|
||||
+
|
||||
+ if (s->set_mute)
|
||||
+ s->set_mute(s);
|
||||
+ if (s->flags & PA_SOURCE_DEFERRED_VOLUME) {
|
||||
+ if (s->write_volume)
|
||||
+ s->write_volume(s);
|
||||
+ } else {
|
||||
+ if (s->set_volume)
|
||||
+ s->set_volume(s);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return pa_alsa_ucm_set_port(u->ucm_context, p, false);
|
||||
}
|
||||
|
||||
@@ -1785,6 +1805,11 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (u->ucm_context) {
|
||||
+ /* We just want to open the device */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (element) {
|
||||
|
||||
if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_INPUT)))
|
||||
@@ -1822,16 +1847,31 @@ static int setup_mixer(struct userdata *u, bool ignore_dB) {
|
||||
return 0;
|
||||
|
||||
if (u->source->active_port) {
|
||||
- pa_alsa_port_data *data;
|
||||
+ if (!u->ucm_context) {
|
||||
+ pa_alsa_port_data *data;
|
||||
|
||||
- /* We have a list of supported paths, so let's activate the
|
||||
- * one that has been chosen as active */
|
||||
+ /* We have a list of supported paths, so let's activate the
|
||||
+ * one that has been chosen as active */
|
||||
|
||||
- data = PA_DEVICE_PORT_DATA(u->source->active_port);
|
||||
- u->mixer_path = data->path;
|
||||
+ data = PA_DEVICE_PORT_DATA(u->source->active_port);
|
||||
+ u->mixer_path = data->path;
|
||||
|
||||
- pa_alsa_path_select(data->path, data->setting, u->mixer_handle, u->source->muted);
|
||||
+ pa_alsa_path_select(data->path, data->setting, u->mixer_handle, u->source->muted);
|
||||
+ } else {
|
||||
+ pa_alsa_ucm_port_data *data;
|
||||
+
|
||||
+ /* First activate the port on the UCM side */
|
||||
+ if (pa_alsa_ucm_set_port(u->ucm_context, u->source->active_port, false) < 0)
|
||||
+ return -1;
|
||||
|
||||
+ data = PA_DEVICE_PORT_DATA(u->source->active_port);
|
||||
+
|
||||
+ /* Now activate volume controls, if any */
|
||||
+ if (data->path) {
|
||||
+ u->mixer_path = data->path;
|
||||
+ pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, u->source->muted);
|
||||
+ }
|
||||
+ }
|
||||
} else {
|
||||
|
||||
if (!u->mixer_path && u->mixer_path_set)
|
||||
@@ -2152,8 +2192,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||
/* ALSA might tweak the sample spec, so recalculate the frame size */
|
||||
frame_size = pa_frame_size(&ss);
|
||||
|
||||
- if (!u->ucm_context)
|
||||
- find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB);
|
||||
+ find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB);
|
||||
|
||||
pa_source_new_data_init(&data);
|
||||
data.driver = driver;
|
||||
@@ -2210,7 +2249,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||
}
|
||||
|
||||
if (u->ucm_context)
|
||||
- pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, false, card);
|
||||
+ pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, false, card, u->pcm_handle, ignore_dB);
|
||||
else if (u->mixer_path_set)
|
||||
pa_alsa_add_ports(&data, u->mixer_path_set, card);
|
||||
|
||||
@@ -2276,10 +2315,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||
if (update_sw_params(u) < 0)
|
||||
goto fail;
|
||||
|
||||
- if (u->ucm_context) {
|
||||
- if (u->source->active_port && pa_alsa_ucm_set_port(u->ucm_context, u->source->active_port, false) < 0)
|
||||
- goto fail;
|
||||
- } else if (setup_mixer(u, ignore_dB) < 0)
|
||||
+ if (setup_mixer(u, ignore_dB) < 0)
|
||||
goto fail;
|
||||
|
||||
pa_alsa_dump(PA_LOG_DEBUG, u->pcm_handle);
|
||||
@@ -2368,7 +2404,7 @@ static void userdata_free(struct userdata *u) {
|
||||
if (u->mixer_fdl)
|
||||
pa_alsa_fdlist_free(u->mixer_fdl);
|
||||
|
||||
- if (u->mixer_path && !u->mixer_path_set)
|
||||
+ if (u->mixer_path && !u->mixer_path_set && !u->ucm_context)
|
||||
pa_alsa_path_free(u->mixer_path);
|
||||
|
||||
if (u->mixer_handle)
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 14056825a25f..349a59566200 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -81,19 +81,11 @@ static void device_add_hw_mute_jack(pa_alsa_ucm_device *device, pa_alsa_jack *ja
|
||||
|
||||
static pa_alsa_ucm_device *verb_find_device(pa_alsa_ucm_verb *verb, const char *device_name);
|
||||
|
||||
-struct ucm_port {
|
||||
- pa_alsa_ucm_config *ucm;
|
||||
- pa_device_port *core_port;
|
||||
-
|
||||
- /* A single port will be associated with multiple devices if it represents
|
||||
- * a combination of devices. */
|
||||
- pa_dynarray *devices; /* pa_alsa_ucm_device */
|
||||
-};
|
||||
|
||||
-static void ucm_port_init(struct ucm_port *port, pa_alsa_ucm_config *ucm, pa_device_port *core_port,
|
||||
- pa_alsa_ucm_device **devices, unsigned n_devices);
|
||||
-static void ucm_port_free(pa_device_port *port);
|
||||
-static void ucm_port_update_available(struct ucm_port *port);
|
||||
+static void ucm_port_data_init(pa_alsa_ucm_port_data *port, pa_alsa_ucm_config *ucm, pa_device_port *core_port,
|
||||
+ pa_alsa_ucm_device **devices, unsigned n_devices);
|
||||
+static void ucm_port_data_free(pa_device_port *port);
|
||||
+static void ucm_port_update_available(pa_alsa_ucm_port_data *port);
|
||||
|
||||
static struct ucm_items item[] = {
|
||||
{"PlaybackPCM", PA_ALSA_PROP_UCM_SINK},
|
||||
@@ -303,6 +295,18 @@ static int ucm_get_device_property(
|
||||
else
|
||||
pa_log_debug("UCM playback priority %s for device %s error", value, device_name);
|
||||
}
|
||||
+
|
||||
+ value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_PLAYBACK_VOLUME);
|
||||
+ if (value) {
|
||||
+ /* Try to get the simple control name, and failing that, just use the name as is */
|
||||
+ char *selem;
|
||||
+
|
||||
+ if (!(selem = pa_str_strip_suffix(value, " Playback Volume")))
|
||||
+ if (!(selem = pa_str_strip_suffix(value, " Volume")))
|
||||
+ selem = pa_xstrdup(value);
|
||||
+
|
||||
+ pa_hashmap_put(device->playback_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), selem);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (device->capture_channels) { /* source device */
|
||||
@@ -324,6 +328,18 @@ static int ucm_get_device_property(
|
||||
else
|
||||
pa_log_debug("UCM capture priority %s for device %s error", value, device_name);
|
||||
}
|
||||
+
|
||||
+ value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_CAPTURE_VOLUME);
|
||||
+ if (value) {
|
||||
+ /* Try to get the simple control name, and failing that, just use the name as is */
|
||||
+ char *selem;
|
||||
+
|
||||
+ if (!(selem = pa_str_strip_suffix(value, " Capture Volume")))
|
||||
+ if (!(selem = pa_str_strip_suffix(value, " Volume")))
|
||||
+ selem = pa_xstrdup(value);
|
||||
+
|
||||
+ pa_hashmap_put(device->capture_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), selem);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (PA_UCM_PLAYBACK_PRIORITY_UNSET(device) || PA_UCM_CAPTURE_PRIORITY_UNSET(device)) {
|
||||
@@ -427,6 +443,11 @@ static int ucm_get_devices(pa_alsa_ucm_verb *verb, snd_use_case_mgr_t *uc_mgr) {
|
||||
d->hw_mute_jacks = pa_dynarray_new(NULL);
|
||||
d->available = PA_AVAILABLE_UNKNOWN;
|
||||
|
||||
+ d->playback_volumes = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree,
|
||||
+ pa_xfree);
|
||||
+ d->capture_volumes = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree,
|
||||
+ pa_xfree);
|
||||
+
|
||||
PA_LLIST_PREPEND(pa_alsa_ucm_device, verb->devices, d);
|
||||
}
|
||||
|
||||
@@ -707,6 +728,46 @@ static int pa_alsa_ucm_device_cmp(const void *a, const void *b) {
|
||||
return strcmp(pa_proplist_gets(d1->proplist, PA_ALSA_PROP_UCM_NAME), pa_proplist_gets(d2->proplist, PA_ALSA_PROP_UCM_NAME));
|
||||
}
|
||||
|
||||
+static void probe_volumes(pa_hashmap *hash, snd_pcm_t *pcm_handle, bool ignore_dB) {
|
||||
+ pa_device_port *port;
|
||||
+ pa_alsa_path *path;
|
||||
+ pa_alsa_ucm_port_data *data;
|
||||
+ snd_mixer_t *mixer_handle;
|
||||
+ const char *profile;
|
||||
+ void *state, *state2;
|
||||
+
|
||||
+ if (!(mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL))) {
|
||||
+ pa_log_error("Failed to find a working mixer device.");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ PA_HASHMAP_FOREACH(port, hash, state) {
|
||||
+ data = PA_DEVICE_PORT_DATA(port);
|
||||
+
|
||||
+ PA_HASHMAP_FOREACH_KV(profile, path, data->paths, state2) {
|
||||
+ if (pa_alsa_path_probe(path, NULL, mixer_handle, ignore_dB) < 0) {
|
||||
+ pa_log_warn("Could not probe path: %s, using s/w volume", data->path->name);
|
||||
+ pa_hashmap_remove(data->paths, profile);
|
||||
+ } else if (!path->has_volume) {
|
||||
+ pa_log_warn("Path %s is not a volume control", data->path->name);
|
||||
+ pa_hashmap_remove(data->paths, profile);
|
||||
+ } else
|
||||
+ pa_log_debug("Set up h/w volume using '%s' for %s:%s", path->name, profile, port->name);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ snd_mixer_close(mixer_handle);
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+fail:
|
||||
+ /* We could not probe the paths we created. Free them and revert to software volumes. */
|
||||
+ PA_HASHMAP_FOREACH(port, hash, state) {
|
||||
+ data = PA_DEVICE_PORT_DATA(port);
|
||||
+ pa_hashmap_remove_all(data->paths);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void ucm_add_port_combination(
|
||||
pa_hashmap *hash,
|
||||
pa_alsa_ucm_mapping_context *context,
|
||||
@@ -724,7 +785,10 @@ static void ucm_add_port_combination(
|
||||
char *name, *desc;
|
||||
const char *dev_name;
|
||||
const char *direction;
|
||||
+ const char *profile, *volume_element;
|
||||
pa_alsa_ucm_device *sorted[num], *dev;
|
||||
+ pa_alsa_ucm_port_data *data;
|
||||
+ void *state;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
sorted[i] = pdevices[i];
|
||||
@@ -772,8 +836,6 @@ static void ucm_add_port_combination(
|
||||
|
||||
port = pa_hashmap_get(ports, name);
|
||||
if (!port) {
|
||||
- struct ucm_port *ucm_port;
|
||||
-
|
||||
pa_device_port_new_data port_data;
|
||||
|
||||
pa_device_port_new_data_init(&port_data);
|
||||
@@ -781,17 +843,33 @@ static void ucm_add_port_combination(
|
||||
pa_device_port_new_data_set_description(&port_data, desc);
|
||||
pa_device_port_new_data_set_direction(&port_data, is_sink ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT);
|
||||
|
||||
- port = pa_device_port_new(core, &port_data, sizeof(struct ucm_port));
|
||||
- port->impl_free = ucm_port_free;
|
||||
+ port = pa_device_port_new(core, &port_data, sizeof(pa_alsa_ucm_port_data));
|
||||
pa_device_port_new_data_done(&port_data);
|
||||
|
||||
- ucm_port = PA_DEVICE_PORT_DATA(port);
|
||||
- ucm_port_init(ucm_port, context->ucm, port, pdevices, num);
|
||||
+ data = PA_DEVICE_PORT_DATA(port);
|
||||
+ ucm_port_data_init(data, context->ucm, port, pdevices, num);
|
||||
+ port->impl_free = ucm_port_data_free;
|
||||
|
||||
pa_hashmap_put(ports, port->name, port);
|
||||
pa_log_debug("Add port %s: %s", port->name, port->description);
|
||||
}
|
||||
|
||||
+ if (num == 1) {
|
||||
+ /* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination
|
||||
+ * ports. */
|
||||
+ data = PA_DEVICE_PORT_DATA(port);
|
||||
+
|
||||
+ PA_HASHMAP_FOREACH_KV(profile, volume_element, is_sink ? dev->playback_volumes : dev->capture_volumes, state) {
|
||||
+ pa_alsa_path *path = pa_alsa_path_synthesize(volume_element,
|
||||
+ is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT);
|
||||
+
|
||||
+ if (!path)
|
||||
+ pa_log_warn("Failed to set up volume control: %s", volume_element);
|
||||
+ else
|
||||
+ pa_hashmap_put(data->paths, pa_xstrdup(profile), path);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
port->priority = priority;
|
||||
|
||||
pa_xfree(name);
|
||||
@@ -971,7 +1049,9 @@ void pa_alsa_ucm_add_ports(
|
||||
pa_proplist *proplist,
|
||||
pa_alsa_ucm_mapping_context *context,
|
||||
bool is_sink,
|
||||
- pa_card *card) {
|
||||
+ pa_card *card,
|
||||
+ snd_pcm_t *pcm_handle,
|
||||
+ bool ignore_dB) {
|
||||
|
||||
uint32_t idx;
|
||||
char *merged_roles;
|
||||
@@ -986,6 +1066,9 @@ void pa_alsa_ucm_add_ports(
|
||||
/* add ports first */
|
||||
pa_alsa_ucm_add_ports_combination(*p, context, is_sink, card->ports, NULL, card->core);
|
||||
|
||||
+ /* now set up volume paths if any */
|
||||
+ probe_volumes(*p, pcm_handle, ignore_dB);
|
||||
+
|
||||
/* then set property PA_PROP_DEVICE_INTENDED_ROLES */
|
||||
merged_roles = pa_xstrdup(pa_proplist_gets(proplist, PA_PROP_DEVICE_INTENDED_ROLES));
|
||||
PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) {
|
||||
@@ -1010,10 +1093,13 @@ void pa_alsa_ucm_add_ports(
|
||||
}
|
||||
|
||||
/* Change UCM verb and device to match selected card profile */
|
||||
-int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, const char *new_profile, const char *old_profile) {
|
||||
+int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, const char *new_profile, const char *old_profile) {
|
||||
int ret = 0;
|
||||
const char *profile;
|
||||
pa_alsa_ucm_verb *verb;
|
||||
+ pa_device_port *port;
|
||||
+ pa_alsa_ucm_port_data *data;
|
||||
+ void *state;
|
||||
|
||||
if (new_profile == old_profile)
|
||||
return ret;
|
||||
@@ -1042,6 +1128,12 @@ int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, const char *new_profile, co
|
||||
}
|
||||
}
|
||||
|
||||
+ /* select volume controls on ports */
|
||||
+ PA_HASHMAP_FOREACH(port, card->ports, state) {
|
||||
+ data = PA_DEVICE_PORT_DATA(port);
|
||||
+ data->path = pa_hashmap_get(data->paths, new_profile);
|
||||
+ }
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1650,11 +1742,18 @@ static void free_verb(pa_alsa_ucm_verb *verb) {
|
||||
if (di->ucm_ports)
|
||||
pa_dynarray_free(di->ucm_ports);
|
||||
|
||||
+ if (di->playback_volumes)
|
||||
+ pa_hashmap_free(di->playback_volumes);
|
||||
+ if (di->capture_volumes)
|
||||
+ pa_hashmap_free(di->capture_volumes);
|
||||
+
|
||||
pa_proplist_free(di->proplist);
|
||||
+
|
||||
if (di->conflicting_devices)
|
||||
pa_idxset_free(di->conflicting_devices, NULL);
|
||||
if (di->supported_devices)
|
||||
pa_idxset_free(di->supported_devices, NULL);
|
||||
+
|
||||
pa_xfree(di);
|
||||
}
|
||||
|
||||
@@ -1785,7 +1884,7 @@ void pa_alsa_ucm_roled_stream_end(pa_alsa_ucm_config *ucm, const char *role, pa_
|
||||
}
|
||||
}
|
||||
|
||||
-static void device_add_ucm_port(pa_alsa_ucm_device *device, struct ucm_port *port) {
|
||||
+static void device_add_ucm_port(pa_alsa_ucm_device *device, pa_alsa_ucm_port_data *port) {
|
||||
pa_assert(device);
|
||||
pa_assert(port);
|
||||
|
||||
@@ -1813,7 +1912,7 @@ static void device_add_hw_mute_jack(pa_alsa_ucm_device *device, pa_alsa_jack *ja
|
||||
}
|
||||
|
||||
static void device_set_available(pa_alsa_ucm_device *device, pa_available_t available) {
|
||||
- struct ucm_port *port;
|
||||
+ pa_alsa_ucm_port_data *port;
|
||||
unsigned idx;
|
||||
|
||||
pa_assert(device);
|
||||
@@ -1847,8 +1946,8 @@ void pa_alsa_ucm_device_update_available(pa_alsa_ucm_device *device) {
|
||||
device_set_available(device, available);
|
||||
}
|
||||
|
||||
-static void ucm_port_init(struct ucm_port *port, pa_alsa_ucm_config *ucm, pa_device_port *core_port,
|
||||
- pa_alsa_ucm_device **devices, unsigned n_devices) {
|
||||
+static void ucm_port_data_init(pa_alsa_ucm_port_data *port, pa_alsa_ucm_config *ucm, pa_device_port *core_port,
|
||||
+ pa_alsa_ucm_device **devices, unsigned n_devices) {
|
||||
unsigned i;
|
||||
|
||||
pa_assert(ucm);
|
||||
@@ -1864,11 +1963,14 @@ static void ucm_port_init(struct ucm_port *port, pa_alsa_ucm_config *ucm, pa_dev
|
||||
device_add_ucm_port(devices[i], port);
|
||||
}
|
||||
|
||||
+ port->paths = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree,
|
||||
+ (pa_free_cb_t) pa_alsa_path_free);
|
||||
+
|
||||
ucm_port_update_available(port);
|
||||
}
|
||||
|
||||
-static void ucm_port_free(pa_device_port *port) {
|
||||
- struct ucm_port *ucm_port;
|
||||
+static void ucm_port_data_free(pa_device_port *port) {
|
||||
+ pa_alsa_ucm_port_data *ucm_port;
|
||||
|
||||
pa_assert(port);
|
||||
|
||||
@@ -1876,9 +1978,12 @@ static void ucm_port_free(pa_device_port *port) {
|
||||
|
||||
if (ucm_port->devices)
|
||||
pa_dynarray_free(ucm_port->devices);
|
||||
+
|
||||
+ if (ucm_port->paths)
|
||||
+ pa_hashmap_free(ucm_port->paths);
|
||||
}
|
||||
|
||||
-static void ucm_port_update_available(struct ucm_port *port) {
|
||||
+static void ucm_port_update_available(pa_alsa_ucm_port_data *port) {
|
||||
pa_alsa_ucm_device *device;
|
||||
unsigned idx;
|
||||
pa_available_t available = PA_AVAILABLE_YES;
|
||||
@@ -1910,7 +2015,7 @@ pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_cha
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, const char *new_profile, const char *old_profile) {
|
||||
+int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, const char *new_profile, const char *old_profile) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1923,7 +2028,9 @@ void pa_alsa_ucm_add_ports(
|
||||
pa_proplist *proplist,
|
||||
pa_alsa_ucm_mapping_context *context,
|
||||
bool is_sink,
|
||||
- pa_card *card) {
|
||||
+ pa_card *card,
|
||||
+ snd_pcm_t *pcm_handle,
|
||||
+ bool ignore_dB) {
|
||||
}
|
||||
|
||||
void pa_alsa_ucm_add_ports_combination(
|
||||
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
|
||||
index 4feb8c0bfc3f..2e39a09a51f3 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.h
|
||||
+++ b/src/modules/alsa/alsa-ucm.h
|
||||
@@ -113,10 +113,11 @@ typedef struct pa_alsa_ucm_modifier pa_alsa_ucm_modifier;
|
||||
typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
|
||||
typedef struct pa_alsa_ucm_config pa_alsa_ucm_config;
|
||||
typedef struct pa_alsa_ucm_mapping_context pa_alsa_ucm_mapping_context;
|
||||
+typedef struct pa_alsa_ucm_port_data pa_alsa_ucm_port_data;
|
||||
|
||||
int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index);
|
||||
pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_channel_map *default_channel_map);
|
||||
-int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, const char *new_profile, const char *old_profile);
|
||||
+int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, const char *new_profile, const char *old_profile);
|
||||
|
||||
int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, const char *verb_desc, pa_alsa_ucm_verb **p_verb);
|
||||
|
||||
@@ -125,7 +126,9 @@ void pa_alsa_ucm_add_ports(
|
||||
pa_proplist *proplist,
|
||||
pa_alsa_ucm_mapping_context *context,
|
||||
bool is_sink,
|
||||
- pa_card *card);
|
||||
+ pa_card *card,
|
||||
+ snd_pcm_t *pcm_handle,
|
||||
+ bool ignore_dB);
|
||||
void pa_alsa_ucm_add_ports_combination(
|
||||
pa_hashmap *hash,
|
||||
pa_alsa_ucm_mapping_context *context,
|
||||
@@ -157,6 +160,11 @@ struct pa_alsa_ucm_device {
|
||||
unsigned playback_channels;
|
||||
unsigned capture_channels;
|
||||
|
||||
+ /* These may be different per verb, so we store this as a hashmap of verb -> volume_control. We might eventually want to
|
||||
+ * make this a hashmap of verb -> per-verb-device-properties-struct. */
|
||||
+ pa_hashmap *playback_volumes;
|
||||
+ pa_hashmap *capture_volumes;
|
||||
+
|
||||
pa_alsa_mapping *playback_mapping;
|
||||
pa_alsa_mapping *capture_mapping;
|
||||
|
||||
@@ -224,4 +232,18 @@ struct pa_alsa_ucm_mapping_context {
|
||||
pa_idxset *ucm_modifiers;
|
||||
};
|
||||
|
||||
+struct pa_alsa_ucm_port_data {
|
||||
+ pa_alsa_ucm_config *ucm;
|
||||
+ pa_device_port *core_port;
|
||||
+
|
||||
+ /* A single port will be associated with multiple devices if it represents
|
||||
+ * a combination of devices. */
|
||||
+ pa_dynarray *devices; /* pa_alsa_ucm_device */
|
||||
+
|
||||
+ /* profile -> pa_alsa_path for volume control */
|
||||
+ pa_hashmap *paths;
|
||||
+ /* Current path, set when activating profile */
|
||||
+ pa_alsa_path *path;
|
||||
+};
|
||||
+
|
||||
#endif
|
||||
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
|
||||
index 1e1090fe024e..e2a86bc1c68d 100644
|
||||
--- a/src/modules/alsa/module-alsa-card.c
|
||||
+++ b/src/modules/alsa/module-alsa-card.c
|
||||
@@ -241,7 +241,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
|
||||
|
||||
/* if UCM is available for this card then update the verb */
|
||||
if (u->use_ucm) {
|
||||
- if (pa_alsa_ucm_set_profile(&u->ucm, nd->profile ? nd->profile->name : NULL,
|
||||
+ if (pa_alsa_ucm_set_profile(&u->ucm, c, nd->profile ? nd->profile->name : NULL,
|
||||
od->profile ? od->profile->name : NULL) < 0) {
|
||||
ret = -1;
|
||||
goto finish;
|
||||
@@ -294,7 +294,7 @@ static void init_profile(struct userdata *u) {
|
||||
|
||||
if (d->profile && u->use_ucm) {
|
||||
/* Set initial verb */
|
||||
- if (pa_alsa_ucm_set_profile(ucm, d->profile->name, NULL) < 0) {
|
||||
+ if (pa_alsa_ucm_set_profile(ucm, u->card, d->profile->name, NULL) < 0) {
|
||||
pa_log("Failed to set ucm profile %s", d->profile->name);
|
||||
return;
|
||||
}
|
||||
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
|
||||
index f5ec67b8f3fc..174987e4afda 100644
|
||||
--- a/src/pulsecore/core-util.c
|
||||
+++ b/src/pulsecore/core-util.c
|
||||
@@ -2893,6 +2893,32 @@ bool pa_str_in_list_spaces(const char *haystack, const char *needle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+char* pa_str_strip_suffix(const char *str, const char *suffix) {
|
||||
+ size_t str_l, suf_l, prefix;
|
||||
+ char *ret;
|
||||
+
|
||||
+ pa_assert(str);
|
||||
+ pa_assert(suffix);
|
||||
+
|
||||
+ str_l = strlen(str);
|
||||
+ suf_l = strlen(suffix);
|
||||
+
|
||||
+ if (str_l < suf_l)
|
||||
+ return NULL;
|
||||
+
|
||||
+ prefix = str_l - suf_l;
|
||||
+
|
||||
+ if (!pa_streq(&str[prefix], suffix))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ret = pa_xmalloc(prefix + 1);
|
||||
+
|
||||
+ strncpy(ret, str, prefix);
|
||||
+ ret[prefix] = '\0';
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
char *pa_get_user_name_malloc(void) {
|
||||
ssize_t k;
|
||||
char *u;
|
||||
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
|
||||
index d1c4ae1c49aa..9440af9172ca 100644
|
||||
--- a/src/pulsecore/core-util.h
|
||||
+++ b/src/pulsecore/core-util.h
|
||||
@@ -232,6 +232,8 @@ static inline bool pa_safe_streq(const char *a, const char *b) {
|
||||
bool pa_str_in_list_spaces(const char *needle, const char *haystack);
|
||||
bool pa_str_in_list(const char *haystack, const char *delimiters, const char *needle);
|
||||
|
||||
+char* pa_str_strip_suffix(const char *str, const char *suffix);
|
||||
+
|
||||
char *pa_get_host_name_malloc(void);
|
||||
char *pa_get_user_name_malloc(void);
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
242
0011-alsa-ucm-Fix-volume-control-based-on-review.patch
Normal file
242
0011-alsa-ucm-Fix-volume-control-based-on-review.patch
Normal file
@ -0,0 +1,242 @@
|
||||
From 9acacd9ba3b9f4df0957e9ddaacbcee00396175c Mon Sep 17 00:00:00 2001
|
||||
From: Jaska Uimonen <jaska.uimonen@intel.com>
|
||||
Date: Tue, 1 Oct 2019 18:34:17 +0300
|
||||
Subject: [PATCH] alsa-ucm: Fix volume control based on review
|
||||
|
||||
- sync mixer logic added
|
||||
- mixer path creation, empty set in mapping creation, paths added in path creation
|
||||
- path creation moved inside new port creation as it might be called twice otherwise
|
||||
- some comments added
|
||||
---
|
||||
src/modules/alsa/alsa-sink.c | 31 ++++++++--------------------
|
||||
src/modules/alsa/alsa-source.c | 29 ++++++++------------------
|
||||
src/modules/alsa/alsa-ucm.c | 47 +++++++++++++++++++++++++++++-------------
|
||||
src/modules/alsa/alsa-ucm.h | 2 +-
|
||||
4 files changed, 52 insertions(+), 57 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
|
||||
index 08d4d1f38b80..0a5c92529af3 100644
|
||||
--- a/src/modules/alsa/alsa-sink.c
|
||||
+++ b/src/modules/alsa/alsa-sink.c
|
||||
@@ -1266,7 +1266,7 @@ static void sync_mixer(struct userdata *u, pa_device_port *port) {
|
||||
|
||||
/* port may be NULL, because if we use a synthesized mixer path, then the
|
||||
* sink has no ports. */
|
||||
- if (port) {
|
||||
+ if (port && !u->ucm_context) {
|
||||
pa_alsa_port_data *data;
|
||||
|
||||
data = PA_DEVICE_PORT_DATA(port);
|
||||
@@ -1648,28 +1648,19 @@ static int sink_set_port_ucm_cb(pa_sink *s, pa_device_port *p) {
|
||||
struct userdata *u = s->userdata;
|
||||
pa_alsa_ucm_port_data *data;
|
||||
|
||||
- data = PA_DEVICE_PORT_DATA(p);
|
||||
-
|
||||
pa_assert(u);
|
||||
pa_assert(p);
|
||||
+ pa_assert(u->mixer_handle);
|
||||
pa_assert(u->ucm_context);
|
||||
|
||||
- u->mixer_path = data->path;
|
||||
+ data = PA_DEVICE_PORT_DATA(p);
|
||||
+ pa_assert_se(u->mixer_path = data->path);
|
||||
mixer_volume_init(u);
|
||||
|
||||
- if (u->mixer_path) {
|
||||
- pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, s->muted);
|
||||
-
|
||||
- if (s->set_mute)
|
||||
- s->set_mute(s);
|
||||
- if (s->flags & PA_SINK_DEFERRED_VOLUME) {
|
||||
- if (s->write_volume)
|
||||
- s->write_volume(s);
|
||||
- } else {
|
||||
- if (s->set_volume)
|
||||
- s->set_volume(s);
|
||||
- }
|
||||
- }
|
||||
+ if (s->flags & PA_SINK_DEFERRED_VOLUME)
|
||||
+ pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_SYNC_MIXER, p, 0, NULL);
|
||||
+ else
|
||||
+ sync_mixer(u, p);
|
||||
|
||||
return pa_alsa_ucm_set_port(u->ucm_context, p, true);
|
||||
}
|
||||
@@ -2091,6 +2082,7 @@ static void set_sink_name(pa_sink_new_data *data, pa_modargs *ma, const char *de
|
||||
}
|
||||
|
||||
static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) {
|
||||
+
|
||||
if (!mapping && !element)
|
||||
return;
|
||||
|
||||
@@ -2099,11 +2091,6 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
return;
|
||||
}
|
||||
|
||||
- if (u->ucm_context) {
|
||||
- /* We just want to open the device */
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
if (element) {
|
||||
|
||||
if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_OUTPUT)))
|
||||
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
|
||||
index 657ed5aeda11..d186101720b8 100644
|
||||
--- a/src/modules/alsa/alsa-source.c
|
||||
+++ b/src/modules/alsa/alsa-source.c
|
||||
@@ -1137,7 +1137,7 @@ static void sync_mixer(struct userdata *u, pa_device_port *port) {
|
||||
|
||||
/* port may be NULL, because if we use a synthesized mixer path, then the
|
||||
* source has no ports. */
|
||||
- if (port) {
|
||||
+ if (port && !u->ucm_context) {
|
||||
pa_alsa_port_data *data;
|
||||
|
||||
data = PA_DEVICE_PORT_DATA(port);
|
||||
@@ -1523,24 +1523,17 @@ static int source_set_port_ucm_cb(pa_source *s, pa_device_port *p) {
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(p);
|
||||
+ pa_assert(u->mixer_handle);
|
||||
pa_assert(u->ucm_context);
|
||||
|
||||
- u->mixer_path = data->path;
|
||||
+ data = PA_DEVICE_PORT_DATA(p);
|
||||
+ pa_assert_se(u->mixer_path = data->path);
|
||||
mixer_volume_init(u);
|
||||
|
||||
- if (u->mixer_path) {
|
||||
- pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, s->muted);
|
||||
-
|
||||
- if (s->set_mute)
|
||||
- s->set_mute(s);
|
||||
- if (s->flags & PA_SOURCE_DEFERRED_VOLUME) {
|
||||
- if (s->write_volume)
|
||||
- s->write_volume(s);
|
||||
- } else {
|
||||
- if (s->set_volume)
|
||||
- s->set_volume(s);
|
||||
- }
|
||||
- }
|
||||
+ if (s->flags & PA_SOURCE_DEFERRED_VOLUME)
|
||||
+ pa_asyncmsgq_send(u->source->asyncmsgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_SYNC_MIXER, p, 0, NULL);
|
||||
+ else
|
||||
+ sync_mixer(u, p);
|
||||
|
||||
return pa_alsa_ucm_set_port(u->ucm_context, p, false);
|
||||
}
|
||||
@@ -1805,11 +1798,6 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
return;
|
||||
}
|
||||
|
||||
- if (u->ucm_context) {
|
||||
- /* We just want to open the device */
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
if (element) {
|
||||
|
||||
if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_INPUT)))
|
||||
@@ -2404,6 +2392,7 @@ static void userdata_free(struct userdata *u) {
|
||||
if (u->mixer_fdl)
|
||||
pa_alsa_fdlist_free(u->mixer_fdl);
|
||||
|
||||
+ /* Only free the mixer_path if the sink owns it */
|
||||
if (u->mixer_path && !u->mixer_path_set && !u->ucm_context)
|
||||
pa_alsa_path_free(u->mixer_path);
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 349a59566200..a812b52f449e 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -852,21 +852,29 @@ static void ucm_add_port_combination(
|
||||
|
||||
pa_hashmap_put(ports, port->name, port);
|
||||
pa_log_debug("Add port %s: %s", port->name, port->description);
|
||||
- }
|
||||
-
|
||||
- if (num == 1) {
|
||||
- /* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination
|
||||
- * ports. */
|
||||
- data = PA_DEVICE_PORT_DATA(port);
|
||||
|
||||
- PA_HASHMAP_FOREACH_KV(profile, volume_element, is_sink ? dev->playback_volumes : dev->capture_volumes, state) {
|
||||
- pa_alsa_path *path = pa_alsa_path_synthesize(volume_element,
|
||||
- is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT);
|
||||
-
|
||||
- if (!path)
|
||||
- pa_log_warn("Failed to set up volume control: %s", volume_element);
|
||||
- else
|
||||
- pa_hashmap_put(data->paths, pa_xstrdup(profile), path);
|
||||
+ if (num == 1) {
|
||||
+ /* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination
|
||||
+ * ports. */
|
||||
+ data = PA_DEVICE_PORT_DATA(port);
|
||||
+
|
||||
+ PA_HASHMAP_FOREACH_KV(profile, volume_element, is_sink ? dev->playback_volumes : dev->capture_volumes, state) {
|
||||
+ pa_alsa_path *path = pa_alsa_path_synthesize(volume_element,
|
||||
+ is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT);
|
||||
+
|
||||
+ if (!path)
|
||||
+ pa_log_warn("Failed to set up volume control: %s", volume_element);
|
||||
+ else {
|
||||
+ pa_hashmap_put(data->paths, pa_xstrdup(profile), path);
|
||||
+
|
||||
+ /* Add path also to already created empty path set */
|
||||
+ dev = sorted[0];
|
||||
+ if (is_sink)
|
||||
+ pa_hashmap_put(dev->playback_mapping->output_path_set->paths, pa_xstrdup(volume_element), path);
|
||||
+ else
|
||||
+ pa_hashmap_put(dev->capture_mapping->input_path_set->paths, pa_xstrdup(volume_element), path);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1185,16 +1193,27 @@ int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *p
|
||||
|
||||
static void ucm_add_mapping(pa_alsa_profile *p, pa_alsa_mapping *m) {
|
||||
|
||||
+ pa_alsa_path_set *ps;
|
||||
+
|
||||
+ /* create empty path set for the future path additions */
|
||||
+ ps = pa_xnew0(pa_alsa_path_set, 1);
|
||||
+ ps->direction = m->direction;
|
||||
+ ps->paths = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
+
|
||||
switch (m->direction) {
|
||||
case PA_ALSA_DIRECTION_ANY:
|
||||
pa_idxset_put(p->output_mappings, m, NULL);
|
||||
pa_idxset_put(p->input_mappings, m, NULL);
|
||||
+ m->output_path_set = ps;
|
||||
+ m->input_path_set = ps;
|
||||
break;
|
||||
case PA_ALSA_DIRECTION_OUTPUT:
|
||||
pa_idxset_put(p->output_mappings, m, NULL);
|
||||
+ m->output_path_set = ps;
|
||||
break;
|
||||
case PA_ALSA_DIRECTION_INPUT:
|
||||
pa_idxset_put(p->input_mappings, m, NULL);
|
||||
+ m->input_path_set = ps;
|
||||
break;
|
||||
}
|
||||
}
|
||||
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
|
||||
index 2e39a09a51f3..d8507a83615c 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.h
|
||||
+++ b/src/modules/alsa/alsa-ucm.h
|
||||
@@ -240,7 +240,7 @@ struct pa_alsa_ucm_port_data {
|
||||
* a combination of devices. */
|
||||
pa_dynarray *devices; /* pa_alsa_ucm_device */
|
||||
|
||||
- /* profile -> pa_alsa_path for volume control */
|
||||
+ /* profile name -> pa_alsa_path for volume control */
|
||||
pa_hashmap *paths;
|
||||
/* Current path, set when activating profile */
|
||||
pa_alsa_path *path;
|
||||
--
|
||||
2.16.4
|
||||
|
120
0012-alsa-ucm-use-the-correct-mixer-identifiers-as-first.patch
Normal file
120
0012-alsa-ucm-use-the-correct-mixer-identifiers-as-first.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From dc9dc70fcc1b06788d08b5e7997c9053a13cbce2 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Tue, 26 Nov 2019 10:54:15 +0100
|
||||
Subject: [PATCH] alsa-ucm: use the correct mixer identifiers as first
|
||||
|
||||
The mixer identifiers should be used for snd_mixer_selem API.
|
||||
Use them as first, then try to fallback to the raw control
|
||||
identifiers.
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 78 ++++++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 56 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index a812b52f449e..65ec6941e8de 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -200,6 +200,50 @@ static void ucm_add_devices_to_idxset(
|
||||
}
|
||||
}
|
||||
|
||||
+/* Get the volume identifier */
|
||||
+static char *ucm_get_mixer_id(
|
||||
+ pa_alsa_ucm_device *device,
|
||||
+ const char *mprop,
|
||||
+ const char *cprop,
|
||||
+ const char *cid)
|
||||
+{
|
||||
+#if SND_LIB_VERSION >= 0x10201
|
||||
+ snd_ctl_elem_id_t *ctl;
|
||||
+ int err;
|
||||
+#endif
|
||||
+ const char *value;
|
||||
+ char *value2;
|
||||
+ int index;
|
||||
+
|
||||
+ value = pa_proplist_gets(device->proplist, mprop);
|
||||
+ if (value)
|
||||
+ return pa_xstrdup(value);
|
||||
+ value = pa_proplist_gets(device->proplist, cprop);
|
||||
+ if (value == NULL)
|
||||
+ return NULL;
|
||||
+#if SND_LIB_VERSION >= 0x10201
|
||||
+ snd_ctl_elem_id_alloca(&ctl);
|
||||
+ err = snd_use_case_parse_ctl_elem_id(ctl, cid, value);
|
||||
+ if (err < 0)
|
||||
+ return NULL;
|
||||
+ value = snd_ctl_elem_id_get_name(ctl);
|
||||
+ index = snd_ctl_elem_id_get_index(ctl);
|
||||
+#else
|
||||
+#warning "Upgrade to alsa-lib 1.2.1!"
|
||||
+ index = 0;
|
||||
+#endif
|
||||
+ if (!(value2 = pa_str_strip_suffix(value, " Playback Volume")))
|
||||
+ if (!(value2 = pa_str_strip_suffix(value, " Capture Volume")))
|
||||
+ if (!(value2 = pa_str_strip_suffix(value, " Volume")))
|
||||
+ value2 = pa_xstrdup(value);
|
||||
+ if (index > 0) {
|
||||
+ char *mix = pa_sprintf_malloc("'%s',%d", value2, index);
|
||||
+ pa_xfree(value2);
|
||||
+ return mix;
|
||||
+ }
|
||||
+ return value2;
|
||||
+}
|
||||
+
|
||||
/* Create a property list for this ucm device */
|
||||
static int ucm_get_device_property(
|
||||
pa_alsa_ucm_device *device,
|
||||
@@ -296,17 +340,12 @@ static int ucm_get_device_property(
|
||||
pa_log_debug("UCM playback priority %s for device %s error", value, device_name);
|
||||
}
|
||||
|
||||
- value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_PLAYBACK_VOLUME);
|
||||
- if (value) {
|
||||
- /* Try to get the simple control name, and failing that, just use the name as is */
|
||||
- char *selem;
|
||||
-
|
||||
- if (!(selem = pa_str_strip_suffix(value, " Playback Volume")))
|
||||
- if (!(selem = pa_str_strip_suffix(value, " Volume")))
|
||||
- selem = pa_xstrdup(value);
|
||||
-
|
||||
- pa_hashmap_put(device->playback_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), selem);
|
||||
- }
|
||||
+ value = ucm_get_mixer_id(device,
|
||||
+ PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM,
|
||||
+ PA_ALSA_PROP_UCM_PLAYBACK_VOLUME,
|
||||
+ "PlaybackVolume");
|
||||
+ if (value)
|
||||
+ pa_hashmap_put(device->playback_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), (void *)value);
|
||||
}
|
||||
|
||||
if (device->capture_channels) { /* source device */
|
||||
@@ -329,17 +368,12 @@ static int ucm_get_device_property(
|
||||
pa_log_debug("UCM capture priority %s for device %s error", value, device_name);
|
||||
}
|
||||
|
||||
- value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_CAPTURE_VOLUME);
|
||||
- if (value) {
|
||||
- /* Try to get the simple control name, and failing that, just use the name as is */
|
||||
- char *selem;
|
||||
-
|
||||
- if (!(selem = pa_str_strip_suffix(value, " Capture Volume")))
|
||||
- if (!(selem = pa_str_strip_suffix(value, " Volume")))
|
||||
- selem = pa_xstrdup(value);
|
||||
-
|
||||
- pa_hashmap_put(device->capture_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), selem);
|
||||
- }
|
||||
+ value = ucm_get_mixer_id(device,
|
||||
+ PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM,
|
||||
+ PA_ALSA_PROP_UCM_CAPTURE_VOLUME,
|
||||
+ "CaptureVolume");
|
||||
+ if (value)
|
||||
+ pa_hashmap_put(device->capture_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), (void *)value);
|
||||
}
|
||||
|
||||
if (PA_UCM_PLAYBACK_PRIORITY_UNSET(device) || PA_UCM_CAPTURE_PRIORITY_UNSET(device)) {
|
||||
--
|
||||
2.16.4
|
||||
|
330
0013-alsa-ucm-add-support-for-master-volume.patch
Normal file
330
0013-alsa-ucm-add-support-for-master-volume.patch
Normal file
@ -0,0 +1,330 @@
|
||||
From 6d830bf0f08c7f92418c2d8b0e73c0415dca03c8 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Wed, 27 Nov 2019 11:34:49 +0100
|
||||
Subject: [PATCH] alsa-ucm: add support for master volume
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-mixer.c | 20 +++++-----
|
||||
src/modules/alsa/alsa-mixer.h | 1 +
|
||||
src/modules/alsa/alsa-ucm.c | 86 +++++++++++++++++++++++++++++++++----------
|
||||
src/modules/alsa/alsa-ucm.h | 19 ++++++++++
|
||||
4 files changed, 96 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
|
||||
index f57aabe5d885..ed06f42d86da 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.c
|
||||
+++ b/src/modules/alsa/alsa-mixer.c
|
||||
@@ -1923,7 +1923,7 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping *mapping, snd_mixer_t *m)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static pa_alsa_element* element_get(pa_alsa_path *p, const char *section, bool prefixed) {
|
||||
+pa_alsa_element * pa_alsa_element_get(pa_alsa_path *p, const char *section, bool prefixed) {
|
||||
pa_alsa_element *e;
|
||||
char *name;
|
||||
int index;
|
||||
@@ -2025,7 +2025,7 @@ static pa_alsa_option* option_get(pa_alsa_path *p, const char *section) {
|
||||
return p->last_option;
|
||||
}
|
||||
|
||||
- pa_assert_se(e = element_get(p, en, false));
|
||||
+ pa_assert_se(e = pa_alsa_element_get(p, en, false));
|
||||
|
||||
PA_LLIST_FOREACH(o, e->options)
|
||||
if (pa_streq(o->alsa_name, on))
|
||||
@@ -2054,7 +2054,7 @@ static int element_parse_switch(pa_config_parser_state *state) {
|
||||
|
||||
p = state->userdata;
|
||||
|
||||
- if (!(e = element_get(p, state->section, true))) {
|
||||
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
|
||||
pa_log("[%s:%u] Switch makes no sense in '%s'", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
}
|
||||
@@ -2085,7 +2085,7 @@ static int element_parse_volume(pa_config_parser_state *state) {
|
||||
|
||||
p = state->userdata;
|
||||
|
||||
- if (!(e = element_get(p, state->section, true))) {
|
||||
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
|
||||
pa_log("[%s:%u] Volume makes no sense in '%s'", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
}
|
||||
@@ -2121,7 +2121,7 @@ static int element_parse_enumeration(pa_config_parser_state *state) {
|
||||
|
||||
p = state->userdata;
|
||||
|
||||
- if (!(e = element_get(p, state->section, true))) {
|
||||
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
|
||||
pa_log("[%s:%u] Enumeration makes no sense in '%s'", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
}
|
||||
@@ -2213,7 +2213,7 @@ static int element_parse_required(pa_config_parser_state *state) {
|
||||
|
||||
p = state->userdata;
|
||||
|
||||
- e = element_get(p, state->section, true);
|
||||
+ e = pa_alsa_element_get(p, state->section, true);
|
||||
o = option_get(p, state->section);
|
||||
j = jack_get(p, state->section);
|
||||
if (!e && !o && !j) {
|
||||
@@ -2279,7 +2279,7 @@ static int element_parse_direction(pa_config_parser_state *state) {
|
||||
|
||||
p = state->userdata;
|
||||
|
||||
- if (!(e = element_get(p, state->section, true))) {
|
||||
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
|
||||
pa_log("[%s:%u] Direction makes no sense in '%s'", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
}
|
||||
@@ -2305,7 +2305,7 @@ static int element_parse_direction_try_other(pa_config_parser_state *state) {
|
||||
|
||||
p = state->userdata;
|
||||
|
||||
- if (!(e = element_get(p, state->section, true))) {
|
||||
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
|
||||
pa_log("[%s:%u] Direction makes no sense in '%s'", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
}
|
||||
@@ -2328,7 +2328,7 @@ static int element_parse_volume_limit(pa_config_parser_state *state) {
|
||||
|
||||
p = state->userdata;
|
||||
|
||||
- if (!(e = element_get(p, state->section, true))) {
|
||||
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
|
||||
pa_log("[%s:%u] volume-limit makes no sense in '%s'", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
}
|
||||
@@ -2386,7 +2386,7 @@ static int element_parse_override_map(pa_config_parser_state *state) {
|
||||
|
||||
p = state->userdata;
|
||||
|
||||
- if (!(e = element_get(p, state->section, true))) {
|
||||
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
|
||||
pa_log("[%s:%u] Override map makes no sense in '%s'", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
}
|
||||
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
|
||||
index 709f270fbfa5..0b634f2f2be1 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.h
|
||||
+++ b/src/modules/alsa/alsa-mixer.h
|
||||
@@ -244,6 +244,7 @@ void pa_alsa_element_dump(pa_alsa_element *e);
|
||||
|
||||
pa_alsa_path *pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction);
|
||||
pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction);
|
||||
+pa_alsa_element *pa_alsa_element_get(pa_alsa_path *p, const char *section, bool prefixed);
|
||||
int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m, bool ignore_dB);
|
||||
void pa_alsa_path_dump(pa_alsa_path *p);
|
||||
int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v);
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 65ec6941e8de..46d016541ddf 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -200,6 +200,14 @@ static void ucm_add_devices_to_idxset(
|
||||
}
|
||||
}
|
||||
|
||||
+static void ucm_volume_free(pa_alsa_ucm_volume *vol) {
|
||||
+ pa_assert(vol);
|
||||
+ pa_xfree(vol->mixer_elem);
|
||||
+ pa_xfree(vol->master_elem);
|
||||
+ pa_xfree(vol->master_type);
|
||||
+ pa_xfree(vol);
|
||||
+}
|
||||
+
|
||||
/* Get the volume identifier */
|
||||
static char *ucm_get_mixer_id(
|
||||
pa_alsa_ucm_device *device,
|
||||
@@ -244,6 +252,32 @@ static char *ucm_get_mixer_id(
|
||||
return value2;
|
||||
}
|
||||
|
||||
+/* Get the volume identifier */
|
||||
+static pa_alsa_ucm_volume *ucm_get_mixer_volume(
|
||||
+ pa_alsa_ucm_device *device,
|
||||
+ const char *mprop,
|
||||
+ const char *cprop,
|
||||
+ const char *cid,
|
||||
+ const char *masterid,
|
||||
+ const char *mastertype)
|
||||
+{
|
||||
+ pa_alsa_ucm_volume *vol;
|
||||
+ char *mixer_elem;
|
||||
+
|
||||
+ mixer_elem = ucm_get_mixer_id(device, mprop, cprop, cid);
|
||||
+ if (mixer_elem == NULL)
|
||||
+ return NULL;
|
||||
+ vol = pa_xnew0(pa_alsa_ucm_volume, 1);
|
||||
+ if (vol == NULL) {
|
||||
+ pa_xfree(mixer_elem);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ vol->mixer_elem = mixer_elem;
|
||||
+ vol->master_elem = pa_xstrdup(pa_proplist_gets(device->proplist, masterid));
|
||||
+ vol->master_type = pa_xstrdup(pa_proplist_gets(device->proplist, mastertype));
|
||||
+ return vol;
|
||||
+}
|
||||
+
|
||||
/* Create a property list for this ucm device */
|
||||
static int ucm_get_device_property(
|
||||
pa_alsa_ucm_device *device,
|
||||
@@ -258,6 +292,7 @@ static int ucm_get_device_property(
|
||||
int err;
|
||||
uint32_t ui;
|
||||
int n_confdev, n_suppdev;
|
||||
+ pa_alsa_ucm_volume *vol;
|
||||
|
||||
for (i = 0; item[i].id; i++) {
|
||||
id = pa_sprintf_malloc("=%s/%s", item[i].id, device_name);
|
||||
@@ -340,12 +375,14 @@ static int ucm_get_device_property(
|
||||
pa_log_debug("UCM playback priority %s for device %s error", value, device_name);
|
||||
}
|
||||
|
||||
- value = ucm_get_mixer_id(device,
|
||||
- PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM,
|
||||
- PA_ALSA_PROP_UCM_PLAYBACK_VOLUME,
|
||||
- "PlaybackVolume");
|
||||
- if (value)
|
||||
- pa_hashmap_put(device->playback_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), (void *)value);
|
||||
+ vol = ucm_get_mixer_volume(device,
|
||||
+ PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM,
|
||||
+ PA_ALSA_PROP_UCM_PLAYBACK_VOLUME,
|
||||
+ "PlaybackVolume",
|
||||
+ PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM,
|
||||
+ PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE);
|
||||
+ if (vol)
|
||||
+ pa_hashmap_put(device->playback_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), vol);
|
||||
}
|
||||
|
||||
if (device->capture_channels) { /* source device */
|
||||
@@ -368,12 +405,14 @@ static int ucm_get_device_property(
|
||||
pa_log_debug("UCM capture priority %s for device %s error", value, device_name);
|
||||
}
|
||||
|
||||
- value = ucm_get_mixer_id(device,
|
||||
- PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM,
|
||||
- PA_ALSA_PROP_UCM_CAPTURE_VOLUME,
|
||||
- "CaptureVolume");
|
||||
- if (value)
|
||||
- pa_hashmap_put(device->capture_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), (void *)value);
|
||||
+ vol = ucm_get_mixer_volume(device,
|
||||
+ PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM,
|
||||
+ PA_ALSA_PROP_UCM_CAPTURE_VOLUME,
|
||||
+ "CaptureVolume",
|
||||
+ PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM,
|
||||
+ PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE);
|
||||
+ if (vol)
|
||||
+ pa_hashmap_put(device->capture_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), vol);
|
||||
}
|
||||
|
||||
if (PA_UCM_PLAYBACK_PRIORITY_UNSET(device) || PA_UCM_CAPTURE_PRIORITY_UNSET(device)) {
|
||||
@@ -478,9 +517,9 @@ static int ucm_get_devices(pa_alsa_ucm_verb *verb, snd_use_case_mgr_t *uc_mgr) {
|
||||
d->available = PA_AVAILABLE_UNKNOWN;
|
||||
|
||||
d->playback_volumes = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree,
|
||||
- pa_xfree);
|
||||
+ (pa_free_cb_t) ucm_volume_free);
|
||||
d->capture_volumes = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree,
|
||||
- pa_xfree);
|
||||
+ (pa_free_cb_t) ucm_volume_free);
|
||||
|
||||
PA_LLIST_PREPEND(pa_alsa_ucm_device, verb->devices, d);
|
||||
}
|
||||
@@ -819,9 +858,10 @@ static void ucm_add_port_combination(
|
||||
char *name, *desc;
|
||||
const char *dev_name;
|
||||
const char *direction;
|
||||
- const char *profile, *volume_element;
|
||||
+ const char *profile;
|
||||
pa_alsa_ucm_device *sorted[num], *dev;
|
||||
pa_alsa_ucm_port_data *data;
|
||||
+ pa_alsa_ucm_volume *vol;
|
||||
void *state;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
@@ -892,21 +932,27 @@ static void ucm_add_port_combination(
|
||||
* ports. */
|
||||
data = PA_DEVICE_PORT_DATA(port);
|
||||
|
||||
- PA_HASHMAP_FOREACH_KV(profile, volume_element, is_sink ? dev->playback_volumes : dev->capture_volumes, state) {
|
||||
- pa_alsa_path *path = pa_alsa_path_synthesize(volume_element,
|
||||
+ PA_HASHMAP_FOREACH_KV(profile, vol, is_sink ? dev->playback_volumes : dev->capture_volumes, state) {
|
||||
+ pa_alsa_path *path = pa_alsa_path_synthesize(vol->mixer_elem,
|
||||
is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT);
|
||||
|
||||
if (!path)
|
||||
- pa_log_warn("Failed to set up volume control: %s", volume_element);
|
||||
+ pa_log_warn("Failed to set up volume control: %s", vol->mixer_elem);
|
||||
else {
|
||||
+ if (vol->master_elem) {
|
||||
+ pa_alsa_element *e = pa_alsa_element_get(path, vol->master_elem, false);
|
||||
+ e->switch_use = PA_ALSA_SWITCH_MUTE;
|
||||
+ e->volume_use = PA_ALSA_VOLUME_MERGE;
|
||||
+ }
|
||||
+
|
||||
pa_hashmap_put(data->paths, pa_xstrdup(profile), path);
|
||||
|
||||
/* Add path also to already created empty path set */
|
||||
dev = sorted[0];
|
||||
if (is_sink)
|
||||
- pa_hashmap_put(dev->playback_mapping->output_path_set->paths, pa_xstrdup(volume_element), path);
|
||||
+ pa_hashmap_put(dev->playback_mapping->output_path_set->paths, pa_xstrdup(vol->mixer_elem), path);
|
||||
else
|
||||
- pa_hashmap_put(dev->capture_mapping->input_path_set->paths, pa_xstrdup(volume_element), path);
|
||||
+ pa_hashmap_put(dev->capture_mapping->input_path_set->paths, pa_xstrdup(vol->mixer_elem), path);
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
|
||||
index d8507a83615c..a6863abc05a6 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.h
|
||||
+++ b/src/modules/alsa/alsa-ucm.h
|
||||
@@ -60,6 +60,12 @@ typedef void snd_use_case_mgr_t;
|
||||
/** For devices: Playback mixer master type */
|
||||
#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE "alsa.ucm.playback.master.type"
|
||||
|
||||
+/** For devices: Playback mixer master identifier */
|
||||
+#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ID "alsa.ucm.playback.master.id"
|
||||
+
|
||||
+/** For devices: Playback mixer master type */
|
||||
+#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE "alsa.ucm.playback.master.type"
|
||||
+
|
||||
/** For devices: Playback priority */
|
||||
#define PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY "alsa.ucm.playback.priority"
|
||||
|
||||
@@ -87,6 +93,12 @@ typedef void snd_use_case_mgr_t;
|
||||
/** For devices: Capture mixer identifier */
|
||||
#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE "alsa.ucm.capture.master.type"
|
||||
|
||||
+/** For devices: Capture mixer identifier */
|
||||
+#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ID "alsa.ucm.capture.master.id"
|
||||
+
|
||||
+/** For devices: Capture mixer identifier */
|
||||
+#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE "alsa.ucm.capture.master.type"
|
||||
+
|
||||
/** For devices: Capture priority */
|
||||
#define PA_ALSA_PROP_UCM_CAPTURE_PRIORITY "alsa.ucm.capture.priority"
|
||||
|
||||
@@ -114,6 +126,7 @@ typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
|
||||
typedef struct pa_alsa_ucm_config pa_alsa_ucm_config;
|
||||
typedef struct pa_alsa_ucm_mapping_context pa_alsa_ucm_mapping_context;
|
||||
typedef struct pa_alsa_ucm_port_data pa_alsa_ucm_port_data;
|
||||
+typedef struct pa_alsa_ucm_volume pa_alsa_ucm_volume;
|
||||
|
||||
int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index);
|
||||
pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_channel_map *default_channel_map);
|
||||
@@ -246,4 +259,10 @@ struct pa_alsa_ucm_port_data {
|
||||
pa_alsa_path *path;
|
||||
};
|
||||
|
||||
+struct pa_alsa_ucm_volume {
|
||||
+ char *mixer_elem; /* mixer element identifier */
|
||||
+ char *master_elem; /* master mixer element identifier */
|
||||
+ char *master_type;
|
||||
+};
|
||||
+
|
||||
#endif
|
||||
--
|
||||
2.16.4
|
||||
|
59
0014-alsa-ucm-split-correctly-JackHWMute-device-names.patch
Normal file
59
0014-alsa-ucm-split-correctly-JackHWMute-device-names.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 156bd7742490d68701688572ec06f2c608f33db6 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Tue, 3 Dec 2019 14:52:08 +0100
|
||||
Subject: [PATCH] alsa-ucm: split correctly JackHWMute device names
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 28 +++++++++++++++++++++++++++-
|
||||
1 file changed, 27 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 46d016541ddf..65b786caf95e 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -200,6 +200,32 @@ static void ucm_add_devices_to_idxset(
|
||||
}
|
||||
}
|
||||
|
||||
+/* Split a string into words. Like pa_split_spaces() but handle '' and "". */
|
||||
+static char *ucm_split_devnames(const char *c, const char **state) {
|
||||
+ const char *current = *state ? *state : c;
|
||||
+ char h;
|
||||
+ size_t l;
|
||||
+
|
||||
+ if (!*current || *c == 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ current += strspn(current, "\n\r \t");
|
||||
+ h = *current;
|
||||
+ if (h == '\'' || h =='"') {
|
||||
+ c = ++current;
|
||||
+ for (l = 0; *c && *c != h; l++) c++;
|
||||
+ if (*c != h)
|
||||
+ return NULL;
|
||||
+ *state = c + 1;
|
||||
+ } else {
|
||||
+ l = strcspn(current, "\n\r \t");
|
||||
+ *state = current+l;
|
||||
+ }
|
||||
+
|
||||
+ return pa_xstrndup(current, l);
|
||||
+}
|
||||
+
|
||||
+
|
||||
static void ucm_volume_free(pa_alsa_ucm_volume *vol) {
|
||||
pa_assert(vol);
|
||||
pa_xfree(vol->mixer_elem);
|
||||
@@ -1607,7 +1633,7 @@ static int ucm_create_profile(
|
||||
char *hw_mute_device_name;
|
||||
const char *state = NULL;
|
||||
|
||||
- while ((hw_mute_device_name = pa_split_spaces(jack_hw_mute, &state))) {
|
||||
+ while ((hw_mute_device_name = ucm_split_devnames(jack_hw_mute, &state))) {
|
||||
pa_alsa_ucm_verb *verb2;
|
||||
bool device_found = false;
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
40
0015-alsa-ucm-fix-parsing-for-JackControl.patch
Normal file
40
0015-alsa-ucm-fix-parsing-for-JackControl.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From e04f14ebf3a0898dd2f665434524cc34cb267ddd Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Tue, 3 Dec 2019 15:13:48 +0100
|
||||
Subject: [PATCH] alsa-ucm: fix parsing for JackControl
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 65b786caf95e..221fed719284 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -1534,6 +1534,22 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d
|
||||
|
||||
jack_control = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_JACK_CONTROL);
|
||||
if (jack_control) {
|
||||
+#if SND_LIB_VERSION >= 0x10201
|
||||
+ snd_ctl_elem_id_t *ctl;
|
||||
+ int err, index;
|
||||
+ snd_ctl_elem_id_alloca(&ctl);
|
||||
+ err = snd_use_case_parse_ctl_elem_id(ctl, "JackControl", jack_control);
|
||||
+ if (err < 0)
|
||||
+ return NULL;
|
||||
+ jack_control = snd_ctl_elem_id_get_name(ctl);
|
||||
+ index = snd_ctl_elem_id_get_index(ctl);
|
||||
+ if (index > 0) {
|
||||
+ pa_log("[%s] Invalid JackControl index value: \"%s\",%d", device_name, jack_control, index);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+#else
|
||||
+#warning "Upgrade to alsa-lib 1.2.1!"
|
||||
+#endif
|
||||
if (!pa_endswith(jack_control, " Jack")) {
|
||||
pa_log("[%s] Invalid JackControl value: \"%s\"", device_name, jack_control);
|
||||
return NULL;
|
||||
--
|
||||
2.16.4
|
||||
|
45
0016-alsa-ucm-add-comments-to-ucm_get_mixer_id.patch
Normal file
45
0016-alsa-ucm-add-comments-to-ucm_get_mixer_id.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From f5c02dfcd821ab77fc7f91da985254a7bdb658ad Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Wed, 4 Dec 2019 16:29:51 +0100
|
||||
Subject: [PATCH] alsa-ucm: add comments to ucm_get_mixer_id()
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 221fed719284..3ee271845c19 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -241,7 +241,7 @@ static char *ucm_get_mixer_id(
|
||||
const char *cprop,
|
||||
const char *cid)
|
||||
{
|
||||
-#if SND_LIB_VERSION >= 0x10201
|
||||
+#if SND_LIB_VERSION >= 0x10201 /* alsa-lib-1.2.1+ check */
|
||||
snd_ctl_elem_id_t *ctl;
|
||||
int err;
|
||||
#endif
|
||||
@@ -249,13 +249,17 @@ static char *ucm_get_mixer_id(
|
||||
char *value2;
|
||||
int index;
|
||||
|
||||
+ /* mixer element as first, if it's found, return it without modifications */
|
||||
value = pa_proplist_gets(device->proplist, mprop);
|
||||
if (value)
|
||||
return pa_xstrdup(value);
|
||||
+ /* fallback, get the control element identifier */
|
||||
+ /* and try to do some heuristic to determine the mixer element name */
|
||||
value = pa_proplist_gets(device->proplist, cprop);
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
-#if SND_LIB_VERSION >= 0x10201
|
||||
+#if SND_LIB_VERSION >= 0x10201 /* alsa-lib-1.2.1+ check */
|
||||
+ /* The new parser may return also element index. */
|
||||
snd_ctl_elem_id_alloca(&ctl);
|
||||
err = snd_use_case_parse_ctl_elem_id(ctl, cid, value);
|
||||
if (err < 0)
|
||||
--
|
||||
2.16.4
|
||||
|
81
0017-alsa-ucm-validate-access-to-PA_DEVICE_PORT_DATA.patch
Normal file
81
0017-alsa-ucm-validate-access-to-PA_DEVICE_PORT_DATA.patch
Normal file
@ -0,0 +1,81 @@
|
||||
From e6779ad229d5858f90f5f10c3796c9778f05c3fa Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Wed, 4 Dec 2019 19:33:01 +0100
|
||||
Subject: [PATCH] alsa-ucm: validate access to PA_DEVICE_PORT_DATA()
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-sink.c | 3 ++-
|
||||
src/modules/alsa/alsa-source.c | 3 +--
|
||||
src/modules/alsa/module-alsa-card.c | 6 +++++-
|
||||
3 files changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
|
||||
index 0a5c92529af3..19e9efc3674b 100644
|
||||
--- a/src/modules/alsa/alsa-sink.c
|
||||
+++ b/src/modules/alsa/alsa-sink.c
|
||||
@@ -1672,6 +1672,7 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
|
||||
pa_assert(u);
|
||||
pa_assert(p);
|
||||
pa_assert(u->mixer_handle);
|
||||
+ pa_assert(!u->ucm_context);
|
||||
|
||||
data = PA_DEVICE_PORT_DATA(p);
|
||||
pa_assert_se(u->mixer_path = data->path);
|
||||
@@ -2688,7 +2689,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||
* 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) {
|
||||
+ if (u->sink->active_port && !u->ucm_context) {
|
||||
pa_alsa_port_data *port_data;
|
||||
|
||||
port_data = PA_DEVICE_PORT_DATA(u->sink->active_port);
|
||||
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
|
||||
index d186101720b8..34946b74c77f 100644
|
||||
--- a/src/modules/alsa/alsa-source.c
|
||||
+++ b/src/modules/alsa/alsa-source.c
|
||||
@@ -1519,8 +1519,6 @@ static int source_set_port_ucm_cb(pa_source *s, pa_device_port *p) {
|
||||
struct userdata *u = s->userdata;
|
||||
pa_alsa_ucm_port_data *data;
|
||||
|
||||
- data = PA_DEVICE_PORT_DATA(p);
|
||||
-
|
||||
pa_assert(u);
|
||||
pa_assert(p);
|
||||
pa_assert(u->mixer_handle);
|
||||
@@ -1545,6 +1543,7 @@ static int source_set_port_cb(pa_source *s, pa_device_port *p) {
|
||||
pa_assert(u);
|
||||
pa_assert(p);
|
||||
pa_assert(u->mixer_handle);
|
||||
+ pa_assert(!u->ucm_context);
|
||||
|
||||
data = PA_DEVICE_PORT_DATA(p);
|
||||
pa_assert_se(u->mixer_path = data->path);
|
||||
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
|
||||
index e2a86bc1c68d..be260e4badab 100644
|
||||
--- a/src/modules/alsa/module-alsa-card.c
|
||||
+++ b/src/modules/alsa/module-alsa-card.c
|
||||
@@ -538,6 +538,9 @@ static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) {
|
||||
if (mask == SND_CTL_EVENT_MASK_REMOVE)
|
||||
return 0;
|
||||
|
||||
+ if (u->use_ucm)
|
||||
+ return 0;
|
||||
+
|
||||
p = find_port_with_eld_device(u->card->ports, device);
|
||||
if (p == NULL) {
|
||||
pa_log_error("Invalid device changed in ALSA: %d", device);
|
||||
@@ -900,7 +903,8 @@ int pa__init(pa_module *m) {
|
||||
* results in an infinite loop of "fill buffer, handle underrun". To work
|
||||
* around this issue, the suspend_when_unavailable flag is used to stop
|
||||
* playback when the HDMI cable is unplugged. */
|
||||
- if (pa_safe_streq(pa_proplist_gets(data.proplist, "alsa.driver_name"), "snd_hdmi_lpe_audio")) {
|
||||
+ if (!u->use_ucm &&
|
||||
+ pa_safe_streq(pa_proplist_gets(data.proplist, "alsa.driver_name"), "snd_hdmi_lpe_audio")) {
|
||||
pa_device_port *port;
|
||||
void *state;
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
@ -0,0 +1,65 @@
|
||||
From 734a00c849815a45697970d593068c301a04ebbb Mon Sep 17 00:00:00 2001
|
||||
From: Kai-Heng Feng <kai.heng.feng@canonical.com>
|
||||
Date: Tue, 10 Dec 2019 16:16:18 +0800
|
||||
Subject: [PATCH] alsa: Skip resume PCM if hardware doesn't support it
|
||||
|
||||
Hardwares without SNDRV_PCM_INFO_RESUME capability, like USB Audio,
|
||||
don't support snd_pcm_resume() when it's in suspended state.
|
||||
|
||||
Let's use snd_pcm_hw_params_can_resume() to check hardware's capability
|
||||
before snd_pcm_resume() attempt. If it doesn't support resume, just go
|
||||
to snd_pcm_drop() to leave suspended state directly.
|
||||
---
|
||||
src/modules/alsa/alsa-util.c | 28 +++++++++++++++++++---------
|
||||
1 file changed, 19 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
|
||||
index bd0a47e5072c..a14b061118e6 100644
|
||||
--- a/src/modules/alsa/alsa-util.c
|
||||
+++ b/src/modules/alsa/alsa-util.c
|
||||
@@ -1066,6 +1066,7 @@ void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
|
||||
|
||||
int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
|
||||
snd_pcm_state_t state;
|
||||
+ snd_pcm_hw_params_t *hwparams;
|
||||
int err;
|
||||
|
||||
pa_assert(pcm);
|
||||
@@ -1103,16 +1104,25 @@ int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
|
||||
break;
|
||||
|
||||
case SND_PCM_STATE_SUSPENDED:
|
||||
- /* Retry resume 3 times before giving up, then fallback to restarting the stream. */
|
||||
- for (int i = 0; i < 3; i++) {
|
||||
- if ((err = snd_pcm_resume(pcm)) == 0)
|
||||
- return 0;
|
||||
- if (err != -EAGAIN)
|
||||
- break;
|
||||
- pa_msleep(25);
|
||||
+ snd_pcm_hw_params_alloca(&hwparams);
|
||||
+
|
||||
+ if ((err = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
|
||||
+ pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(err));
|
||||
+ return -1;
|
||||
}
|
||||
- pa_log_warn("Could not recover alsa device from SUSPENDED state, trying to restart PCM");
|
||||
- /* Fall through */
|
||||
+
|
||||
+ if (snd_pcm_hw_params_can_resume(hwparams)) {
|
||||
+ /* Retry resume 3 times before giving up, then fallback to restarting the stream. */
|
||||
+ for (int i = 0; i < 3; i++) {
|
||||
+ if ((err = snd_pcm_resume(pcm)) == 0)
|
||||
+ return 0;
|
||||
+ if (err != -EAGAIN)
|
||||
+ break;
|
||||
+ pa_msleep(25);
|
||||
+ }
|
||||
+ pa_log_warn("Could not recover alsa device from SUSPENDED state, trying to restart PCM");
|
||||
+ }
|
||||
+ /* Fall through */
|
||||
|
||||
default:
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
125
0019-alsa-ucm-parse-correctly-the-device-values.patch
Normal file
125
0019-alsa-ucm-parse-correctly-the-device-values.patch
Normal file
@ -0,0 +1,125 @@
|
||||
From 4c64f73c97c7f77426ee838f47fc7bad6a4563b6 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Fri, 6 Dec 2019 21:51:47 +0100
|
||||
Subject: [PATCH] alsa-ucm: parse correctly the device values
|
||||
|
||||
The UCM library is used to get the fallback values from the verbs
|
||||
and the defaults section. There is no reason to duplicate this code
|
||||
inside application.
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 55 ++++++---------------------------------------
|
||||
1 file changed, 7 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 3ee271845c19..ac1b71e94022 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -141,30 +141,6 @@ static struct ucm_info dev_info[] = {
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
-/* UCM profile properties - The verb data is store so it can be used to fill
|
||||
- * the new profiles properties */
|
||||
-static int ucm_get_property(pa_alsa_ucm_verb *verb, snd_use_case_mgr_t *uc_mgr, const char *verb_name) {
|
||||
- const char *value;
|
||||
- char *id;
|
||||
- int i;
|
||||
-
|
||||
- for (i = 0; item[i].id; i++) {
|
||||
- int err;
|
||||
-
|
||||
- id = pa_sprintf_malloc("=%s//%s", item[i].id, verb_name);
|
||||
- err = snd_use_case_get(uc_mgr, id, &value);
|
||||
- pa_xfree(id);
|
||||
- if (err < 0)
|
||||
- continue;
|
||||
-
|
||||
- pa_log_debug("Got %s for verb %s: %s", item[i].id, verb_name, value);
|
||||
- pa_proplist_sets(verb->proplist, item[i].property, value);
|
||||
- free((void*)value);
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-};
|
||||
-
|
||||
static int ucm_device_exists(pa_idxset *idxset, pa_alsa_ucm_device *dev) {
|
||||
pa_alsa_ucm_device *d;
|
||||
uint32_t idx;
|
||||
@@ -325,7 +301,7 @@ static int ucm_get_device_property(
|
||||
pa_alsa_ucm_volume *vol;
|
||||
|
||||
for (i = 0; item[i].id; i++) {
|
||||
- id = pa_sprintf_malloc("=%s/%s", item[i].id, device_name);
|
||||
+ id = pa_sprintf_malloc("%s/%s", item[i].id, device_name);
|
||||
err = snd_use_case_get(uc_mgr, id, &value);
|
||||
pa_xfree(id);
|
||||
if (err < 0)
|
||||
@@ -347,14 +323,8 @@ static int ucm_get_device_property(
|
||||
|
||||
/* get pcm */
|
||||
value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_SINK);
|
||||
- if (!value) { /* take pcm from verb playback default */
|
||||
- value = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_SINK);
|
||||
- if (value) {
|
||||
- pa_log_debug("UCM playback device %s fetch pcm from verb default %s", device_name, value);
|
||||
- pa_proplist_sets(device->proplist, PA_ALSA_PROP_UCM_SINK, value);
|
||||
- } else
|
||||
- pa_log("UCM playback device %s fetch pcm failed", device_name);
|
||||
- }
|
||||
+ if (!value) /* take pcm from verb playback default */
|
||||
+ pa_log("UCM playback device %s fetch pcm failed", device_name);
|
||||
}
|
||||
|
||||
value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_CAPTURE_CHANNELS);
|
||||
@@ -367,14 +337,8 @@ static int ucm_get_device_property(
|
||||
|
||||
/* get pcm */
|
||||
value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_SOURCE);
|
||||
- if (!value) { /* take pcm from verb capture default */
|
||||
- value = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_SOURCE);
|
||||
- if (value) {
|
||||
- pa_log_debug("UCM capture device %s fetch pcm from verb default %s", device_name, value);
|
||||
- pa_proplist_sets(device->proplist, PA_ALSA_PROP_UCM_SOURCE, value);
|
||||
- } else
|
||||
- pa_log("UCM capture device %s fetch pcm failed", device_name);
|
||||
- }
|
||||
+ if (!value) /* take pcm from verb capture default */
|
||||
+ pa_log("UCM capture device %s fetch pcm failed", device_name);
|
||||
}
|
||||
|
||||
if (device->playback_channels == 0 && device->capture_channels == 0) {
|
||||
@@ -387,8 +351,7 @@ static int ucm_get_device_property(
|
||||
/* get rate and priority of device */
|
||||
if (device->playback_channels) { /* sink device */
|
||||
/* get rate */
|
||||
- if ((value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_PLAYBACK_RATE)) ||
|
||||
- (value = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_PLAYBACK_RATE))) {
|
||||
+ if ((value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_PLAYBACK_RATE))) {
|
||||
if (pa_atou(value, &ui) == 0 && pa_sample_rate_valid(ui)) {
|
||||
pa_log_debug("UCM playback device %s rate %d", device_name, ui);
|
||||
device->playback_rate = ui;
|
||||
@@ -417,8 +380,7 @@ static int ucm_get_device_property(
|
||||
|
||||
if (device->capture_channels) { /* source device */
|
||||
/* get rate */
|
||||
- if ((value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_CAPTURE_RATE)) ||
|
||||
- (value = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_CAPTURE_RATE))) {
|
||||
+ if ((value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_CAPTURE_RATE))) {
|
||||
if (pa_atou(value, &ui) == 0 && pa_sample_rate_valid(ui)) {
|
||||
pa_log_debug("UCM capture device %s rate %d", device_name, ui);
|
||||
device->capture_rate = ui;
|
||||
@@ -796,9 +758,6 @@ int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, cons
|
||||
if (err < 0)
|
||||
pa_log("No UCM modifiers for verb %s", verb_name);
|
||||
|
||||
- /* Verb properties */
|
||||
- ucm_get_property(verb, uc_mgr, verb_name);
|
||||
-
|
||||
PA_LLIST_FOREACH(d, verb->devices) {
|
||||
const char *dev_name = pa_proplist_gets(d->proplist, PA_ALSA_PROP_UCM_NAME);
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
@ -0,0 +1,44 @@
|
||||
From ef1df946274a0499e1fa631a8b6680c23c4eb723 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Fri, 6 Dec 2019 15:43:04 +0100
|
||||
Subject: [PATCH] alsa-ucm: do not try to use UCM device name as jack name by
|
||||
default
|
||||
|
||||
Remove the implicit rule. It is perfectly ok to have the jack with
|
||||
the same name for another I/O in the driver. Trust only the
|
||||
value obtained from UCM.
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index ac1b71e94022..95f1a47f8b61 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -1522,9 +1522,8 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d
|
||||
* end, so drop the trailing " Jack". */
|
||||
name = pa_xstrndup(jack_control, strlen(jack_control) - 5);
|
||||
} else {
|
||||
- /* The jack control hasn't been explicitly configured - try a jack name
|
||||
- * that is the same as the device name. */
|
||||
- name = pa_xstrdup(device_name);
|
||||
+ /* The jack control hasn't been explicitly configured, fail. */
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
PA_LLIST_FOREACH(j, ucm->jacks)
|
||||
@@ -1603,7 +1602,8 @@ static int ucm_create_profile(
|
||||
ucm_create_mapping(ucm, ps, p, dev, verb_name, name, sink, source);
|
||||
|
||||
jack = ucm_get_jack(ucm, dev);
|
||||
- device_set_jack(dev, jack);
|
||||
+ if (jack)
|
||||
+ device_set_jack(dev, jack);
|
||||
|
||||
/* JackHWMute contains a list of device names. Each listed device must
|
||||
* be associated with the jack object that we just created. */
|
||||
--
|
||||
2.16.4
|
||||
|
@ -0,0 +1,84 @@
|
||||
From d8200ee805ed6b508a8174031080b1d98a7c27b3 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Fri, 6 Dec 2019 16:05:07 +0100
|
||||
Subject: [PATCH] alsa-util: do not try to guess the mixer name from the PCM
|
||||
name
|
||||
|
||||
This is just invalid. It results to an error in almost all cases.
|
||||
The hw:<number> scheme is sufficient to get the right card mixer.
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 2 ++
|
||||
src/modules/alsa/alsa-util.c | 26 +++++++-------------------
|
||||
2 files changed, 9 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 95f1a47f8b61..45eb83085b38 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -1725,6 +1725,8 @@ static void ucm_mapping_jack_probe(pa_alsa_mapping *m) {
|
||||
PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) {
|
||||
bool has_control;
|
||||
|
||||
+ if (!dev->jack)
|
||||
+ continue;
|
||||
has_control = pa_alsa_mixer_find(mixer_handle, dev->jack->alsa_name, 0) != NULL;
|
||||
pa_alsa_jack_set_has_control(dev->jack, has_control);
|
||||
pa_log_info("UCM jack %s has_control=%d", dev->jack->name, dev->jack->has_control);
|
||||
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
|
||||
index a14b061118e6..54fe1361148a 100644
|
||||
--- a/src/modules/alsa/alsa-util.c
|
||||
+++ b/src/modules/alsa/alsa-util.c
|
||||
@@ -1743,7 +1743,6 @@ snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device) {
|
||||
snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
|
||||
int err;
|
||||
snd_mixer_t *m;
|
||||
- const char *dev;
|
||||
snd_pcm_info_t* info;
|
||||
snd_pcm_info_alloca(&info);
|
||||
|
||||
@@ -1754,15 +1753,6 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /* First, try by name */
|
||||
- if ((dev = snd_pcm_name(pcm)))
|
||||
- if (prepare_mixer(m, dev) >= 0) {
|
||||
- if (ctl_device)
|
||||
- *ctl_device = pa_xstrdup(dev);
|
||||
-
|
||||
- return m;
|
||||
- }
|
||||
-
|
||||
/* Then, try by card index */
|
||||
if (snd_pcm_info(pcm, info) >= 0) {
|
||||
char *md;
|
||||
@@ -1771,17 +1761,15 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
|
||||
if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
|
||||
|
||||
md = pa_sprintf_malloc("hw:%i", card_idx);
|
||||
+ if (prepare_mixer(m, md) >= 0) {
|
||||
|
||||
- if (!dev || !pa_streq(dev, md))
|
||||
- if (prepare_mixer(m, md) >= 0) {
|
||||
+ if (ctl_device)
|
||||
+ *ctl_device = md;
|
||||
+ else
|
||||
+ pa_xfree(md);
|
||||
|
||||
- if (ctl_device)
|
||||
- *ctl_device = md;
|
||||
- else
|
||||
- pa_xfree(md);
|
||||
-
|
||||
- return m;
|
||||
- }
|
||||
+ return m;
|
||||
+ }
|
||||
|
||||
pa_xfree(md);
|
||||
}
|
||||
--
|
||||
2.16.4
|
||||
|
99
0022-alsa-ucm-add-control-and-mixer-device-items.patch
Normal file
99
0022-alsa-ucm-add-control-and-mixer-device-items.patch
Normal file
@ -0,0 +1,99 @@
|
||||
From ddd0fdb9970b920ef95e33cfe50a1e492be9d60b Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Fri, 6 Dec 2019 20:33:45 +0100
|
||||
Subject: [PATCH] alsa-ucm: add control and mixer device items
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 5 +++++
|
||||
src/modules/alsa/alsa-ucm.h | 15 +++++++++++++++
|
||||
2 files changed, 20 insertions(+)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 45eb83085b38..2a594b4df546 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -90,16 +90,20 @@ static void ucm_port_update_available(pa_alsa_ucm_port_data *port);
|
||||
static struct ucm_items item[] = {
|
||||
{"PlaybackPCM", PA_ALSA_PROP_UCM_SINK},
|
||||
{"CapturePCM", PA_ALSA_PROP_UCM_SOURCE},
|
||||
+ {"PlaybackCTL", PA_ALSA_PROP_UCM_PLAYBACK_CTL_DEVICE},
|
||||
{"PlaybackVolume", PA_ALSA_PROP_UCM_PLAYBACK_VOLUME},
|
||||
{"PlaybackSwitch", PA_ALSA_PROP_UCM_PLAYBACK_SWITCH},
|
||||
+ {"PlaybackMixer", PA_ALSA_PROP_UCM_PLAYBACK_MIXER_DEVICE},
|
||||
{"PlaybackMixerElem", PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM},
|
||||
{"PlaybackMasterElem", PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM},
|
||||
{"PlaybackMasterType", PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE},
|
||||
{"PlaybackPriority", PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY},
|
||||
{"PlaybackRate", PA_ALSA_PROP_UCM_PLAYBACK_RATE},
|
||||
{"PlaybackChannels", PA_ALSA_PROP_UCM_PLAYBACK_CHANNELS},
|
||||
+ {"CaptureCTL", PA_ALSA_PROP_UCM_CAPTURE_CTL_DEVICE},
|
||||
{"CaptureVolume", PA_ALSA_PROP_UCM_CAPTURE_VOLUME},
|
||||
{"CaptureSwitch", PA_ALSA_PROP_UCM_CAPTURE_SWITCH},
|
||||
+ {"CaptureMixer", PA_ALSA_PROP_UCM_CAPTURE_MIXER_DEVICE},
|
||||
{"CaptureMixerElem", PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM},
|
||||
{"CaptureMasterElem", PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM},
|
||||
{"CaptureMasterType", PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE},
|
||||
@@ -107,6 +111,7 @@ static struct ucm_items item[] = {
|
||||
{"CaptureRate", PA_ALSA_PROP_UCM_CAPTURE_RATE},
|
||||
{"CaptureChannels", PA_ALSA_PROP_UCM_CAPTURE_CHANNELS},
|
||||
{"TQ", PA_ALSA_PROP_UCM_QOS},
|
||||
+ {"JackCTL", PA_ALSA_PROP_UCM_JACK_DEVICE},
|
||||
{"JackControl", PA_ALSA_PROP_UCM_JACK_CONTROL},
|
||||
{"JackHWMute", PA_ALSA_PROP_UCM_JACK_HW_MUTE},
|
||||
{NULL, NULL},
|
||||
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
|
||||
index a6863abc05a6..014bc334ad67 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.h
|
||||
+++ b/src/modules/alsa/alsa-ucm.h
|
||||
@@ -45,12 +45,18 @@ typedef void snd_use_case_mgr_t;
|
||||
/** For devices: Playback roles */
|
||||
#define PA_ALSA_PROP_UCM_PLAYBACK_ROLES "alsa.ucm.playback.roles"
|
||||
|
||||
+/** For devices: Playback control device name */
|
||||
+#define PA_ALSA_PROP_UCM_PLAYBACK_CTL_DEVICE "alsa.ucm.playback.ctldev"
|
||||
+
|
||||
/** For devices: Playback control volume ID string. e.g PlaybackVolume */
|
||||
#define PA_ALSA_PROP_UCM_PLAYBACK_VOLUME "alsa.ucm.playback.volume"
|
||||
|
||||
/** For devices: Playback switch e.g PlaybackSwitch */
|
||||
#define PA_ALSA_PROP_UCM_PLAYBACK_SWITCH "alsa.ucm.playback.switch"
|
||||
|
||||
+/** For devices: Playback mixer device name */
|
||||
+#define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_DEVICE "alsa.ucm.playback.mixer.device"
|
||||
+
|
||||
/** For devices: Playback mixer identifier */
|
||||
#define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM "alsa.ucm.playback.mixer.element"
|
||||
|
||||
@@ -78,12 +84,18 @@ typedef void snd_use_case_mgr_t;
|
||||
/** For devices: Capture roles */
|
||||
#define PA_ALSA_PROP_UCM_CAPTURE_ROLES "alsa.ucm.capture.roles"
|
||||
|
||||
+/** For devices: Capture control device name */
|
||||
+#define PA_ALSA_PROP_UCM_CAPTURE_CTL_DEVICE "alsa.ucm.capture.ctldev"
|
||||
+
|
||||
/** For devices: Capture controls volume ID string. e.g CaptureVolume */
|
||||
#define PA_ALSA_PROP_UCM_CAPTURE_VOLUME "alsa.ucm.capture.volume"
|
||||
|
||||
/** For devices: Capture switch e.g CaptureSwitch */
|
||||
#define PA_ALSA_PROP_UCM_CAPTURE_SWITCH "alsa.ucm.capture.switch"
|
||||
|
||||
+/** For devices: Capture mixer device name */
|
||||
+#define PA_ALSA_PROP_UCM_CAPTURE_MIXER_DEVICE "alsa.ucm.capture.mixer.device"
|
||||
+
|
||||
/** For devices: Capture mixer identifier */
|
||||
#define PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM "alsa.ucm.capture.mixer.element"
|
||||
|
||||
@@ -114,6 +126,9 @@ typedef void snd_use_case_mgr_t;
|
||||
/** For devices: The modifier (if any) that this device corresponds to */
|
||||
#define PA_ALSA_PROP_UCM_MODIFIER "alsa.ucm.modifier"
|
||||
|
||||
+/* Corresponds to the "JackCTL" UCM value. */
|
||||
+#define PA_ALSA_PROP_UCM_JACK_DEVICE "alsa.ucm.jack_device"
|
||||
+
|
||||
/* Corresponds to the "JackControl" UCM value. */
|
||||
#define PA_ALSA_PROP_UCM_JACK_CONTROL "alsa.ucm.jack_control"
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
244
0023-alsa-ucm-get-the-mixer-names-from-ucm-don-t-guess.patch
Normal file
244
0023-alsa-ucm-get-the-mixer-names-from-ucm-don-t-guess.patch
Normal file
@ -0,0 +1,244 @@
|
||||
From e438382a51f7e0d04fb9439da2f45c183e958e0f Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Fri, 6 Dec 2019 21:32:21 +0100
|
||||
Subject: [PATCH] alsa-ucm: get the mixer names from ucm, don't guess
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-mixer.h | 1 +
|
||||
src/modules/alsa/alsa-ucm.c | 96 +++++++++++++++++++++++++++++++++++--------
|
||||
src/modules/alsa/alsa-util.c | 26 ++++++++----
|
||||
3 files changed, 97 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
|
||||
index 0b634f2f2be1..7864a2c1252f 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.h
|
||||
+++ b/src/modules/alsa/alsa-mixer.h
|
||||
@@ -364,6 +364,7 @@ void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
|
||||
void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
|
||||
void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *s);
|
||||
|
||||
+snd_mixer_t *pa_alsa_open_mixer_by_name(const char *dev);
|
||||
snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device);
|
||||
|
||||
pa_alsa_fdlist *pa_alsa_fdlist_new(void);
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 2a594b4df546..d02adab650fe 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -289,6 +289,31 @@ static pa_alsa_ucm_volume *ucm_get_mixer_volume(
|
||||
return vol;
|
||||
}
|
||||
|
||||
+/* Get the ALSA mixer device for the UCM device */
|
||||
+static const char *get_mixer_device(pa_alsa_ucm_device *dev, bool is_sink)
|
||||
+{
|
||||
+ const char *dev_name;
|
||||
+
|
||||
+ if (is_sink) {
|
||||
+ dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_PLAYBACK_MIXER_DEVICE);
|
||||
+ if (!dev_name)
|
||||
+ dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_PLAYBACK_CTL_DEVICE);
|
||||
+ } else {
|
||||
+ dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_CAPTURE_MIXER_DEVICE);
|
||||
+ if (!dev_name)
|
||||
+ dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_CAPTURE_CTL_DEVICE);
|
||||
+ }
|
||||
+ return dev_name;
|
||||
+}
|
||||
+
|
||||
+/* Get the ALSA mixer device for the UCM jack */
|
||||
+static const char *get_jack_mixer_device(pa_alsa_ucm_device *dev, bool is_sink) {
|
||||
+ const char *dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_JACK_DEVICE);
|
||||
+ if (!dev_name)
|
||||
+ return get_mixer_device(dev, is_sink);
|
||||
+ return dev_name;
|
||||
+}
|
||||
+
|
||||
/* Create a property list for this ucm device */
|
||||
static int ucm_get_device_property(
|
||||
pa_alsa_ucm_device *device,
|
||||
@@ -795,22 +820,41 @@ static int pa_alsa_ucm_device_cmp(const void *a, const void *b) {
|
||||
return strcmp(pa_proplist_gets(d1->proplist, PA_ALSA_PROP_UCM_NAME), pa_proplist_gets(d2->proplist, PA_ALSA_PROP_UCM_NAME));
|
||||
}
|
||||
|
||||
-static void probe_volumes(pa_hashmap *hash, snd_pcm_t *pcm_handle, bool ignore_dB) {
|
||||
+static void probe_volumes(pa_hashmap *hash, bool is_sink, snd_pcm_t *pcm_handle, bool ignore_dB) {
|
||||
pa_device_port *port;
|
||||
pa_alsa_path *path;
|
||||
pa_alsa_ucm_port_data *data;
|
||||
- snd_mixer_t *mixer_handle;
|
||||
- const char *profile;
|
||||
+ pa_alsa_ucm_device *dev;
|
||||
+ snd_mixer_t *mixer_handle = NULL;
|
||||
+ const char *profile, *mdev_opened = NULL, *mdev, *mdev2;
|
||||
void *state, *state2;
|
||||
-
|
||||
- if (!(mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL))) {
|
||||
- pa_log_error("Failed to find a working mixer device.");
|
||||
- goto fail;
|
||||
- }
|
||||
+ int idx;
|
||||
|
||||
PA_HASHMAP_FOREACH(port, hash, state) {
|
||||
data = PA_DEVICE_PORT_DATA(port);
|
||||
|
||||
+ mdev = NULL;
|
||||
+ PA_DYNARRAY_FOREACH(dev, data->devices, idx) {
|
||||
+ mdev2 = get_mixer_device(dev, is_sink);
|
||||
+ if (mdev && !pa_streq(mdev, mdev2)) {
|
||||
+ pa_log_error("Two mixer device names found ('%s', '%s'), using s/w volume", mdev, mdev2);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ mdev = mdev2;
|
||||
+ }
|
||||
+
|
||||
+ if (!mdev_opened || !pa_streq(mdev_opened, mdev)) {
|
||||
+ if (mixer_handle) {
|
||||
+ snd_mixer_close(mixer_handle);
|
||||
+ mdev_opened = NULL;
|
||||
+ }
|
||||
+ if (!(mixer_handle = pa_alsa_open_mixer_by_name(mdev))) {
|
||||
+ pa_log_error("Failed to find a working mixer device (%s).", mdev);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ mdev_opened = mdev;
|
||||
+ }
|
||||
+
|
||||
PA_HASHMAP_FOREACH_KV(profile, path, data->paths, state2) {
|
||||
if (pa_alsa_path_probe(path, NULL, mixer_handle, ignore_dB) < 0) {
|
||||
pa_log_warn("Could not probe path: %s, using s/w volume", data->path->name);
|
||||
@@ -823,7 +867,8 @@ static void probe_volumes(pa_hashmap *hash, snd_pcm_t *pcm_handle, bool ignore_d
|
||||
}
|
||||
}
|
||||
|
||||
- snd_mixer_close(mixer_handle);
|
||||
+ if (mixer_handle)
|
||||
+ snd_mixer_close(mixer_handle);
|
||||
|
||||
return;
|
||||
|
||||
@@ -1149,7 +1194,7 @@ void pa_alsa_ucm_add_ports(
|
||||
pa_alsa_ucm_add_ports_combination(*p, context, is_sink, card->ports, NULL, card->core);
|
||||
|
||||
/* now set up volume paths if any */
|
||||
- probe_volumes(*p, pcm_handle, ignore_dB);
|
||||
+ probe_volumes(*p, is_sink, pcm_handle, ignore_dB);
|
||||
|
||||
/* then set property PA_PROP_DEVICE_INTENDED_ROLES */
|
||||
merged_roles = pa_xstrdup(pa_proplist_gets(proplist, PA_PROP_DEVICE_INTENDED_ROLES));
|
||||
@@ -1716,28 +1761,43 @@ static void profile_finalize_probing(pa_alsa_profile *p) {
|
||||
}
|
||||
|
||||
static void ucm_mapping_jack_probe(pa_alsa_mapping *m) {
|
||||
- snd_pcm_t *pcm_handle;
|
||||
- snd_mixer_t *mixer_handle;
|
||||
+ snd_mixer_t *mixer_handle = NULL;
|
||||
pa_alsa_ucm_mapping_context *context = &m->ucm_context;
|
||||
pa_alsa_ucm_device *dev;
|
||||
+ bool is_sink = m->direction == PA_ALSA_DIRECTION_OUTPUT;
|
||||
+ const char *mdev_opened = NULL, *mdev;
|
||||
uint32_t idx;
|
||||
|
||||
- pcm_handle = m->direction == PA_ALSA_DIRECTION_OUTPUT ? m->output_pcm : m->input_pcm;
|
||||
- mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL);
|
||||
- if (!mixer_handle)
|
||||
- return;
|
||||
-
|
||||
PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) {
|
||||
bool has_control;
|
||||
|
||||
if (!dev->jack)
|
||||
continue;
|
||||
+
|
||||
+ mdev = get_jack_mixer_device(dev, is_sink);
|
||||
+ if (mdev == NULL) {
|
||||
+ pa_log_error("Unable to determine mixer device for jack %s", dev->jack->name);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (!mdev_opened || !pa_streq(mdev_opened, mdev)) {
|
||||
+ if (mixer_handle) {
|
||||
+ snd_mixer_close(mixer_handle);
|
||||
+ mdev_opened = NULL;
|
||||
+ }
|
||||
+ mixer_handle = pa_alsa_open_mixer_by_name(mdev);
|
||||
+ if (!mixer_handle)
|
||||
+ continue;
|
||||
+ mdev_opened = mdev;
|
||||
+ }
|
||||
+
|
||||
has_control = pa_alsa_mixer_find(mixer_handle, dev->jack->alsa_name, 0) != NULL;
|
||||
pa_alsa_jack_set_has_control(dev->jack, has_control);
|
||||
pa_log_info("UCM jack %s has_control=%d", dev->jack->name, dev->jack->has_control);
|
||||
}
|
||||
|
||||
- snd_mixer_close(mixer_handle);
|
||||
+ if (mixer_handle)
|
||||
+ snd_mixer_close(mixer_handle);
|
||||
}
|
||||
|
||||
static void ucm_probe_profile_set(pa_alsa_ucm_config *ucm, pa_alsa_profile_set *ps) {
|
||||
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
|
||||
index 54fe1361148a..2df2258d85af 100644
|
||||
--- a/src/modules/alsa/alsa-util.c
|
||||
+++ b/src/modules/alsa/alsa-util.c
|
||||
@@ -1740,20 +1740,31 @@ snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
|
||||
+snd_mixer_t *pa_alsa_open_mixer_by_name(const char *dev) {
|
||||
int err;
|
||||
snd_mixer_t *m;
|
||||
- snd_pcm_info_t* info;
|
||||
- snd_pcm_info_alloca(&info);
|
||||
|
||||
- pa_assert(pcm);
|
||||
+ pa_assert(dev);
|
||||
|
||||
if ((err = snd_mixer_open(&m, 0)) < 0) {
|
||||
pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /* Then, try by card index */
|
||||
+ if (prepare_mixer(m, dev) >= 0)
|
||||
+ return m;
|
||||
+
|
||||
+ snd_mixer_close(m);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
|
||||
+ snd_mixer_t *m;
|
||||
+ snd_pcm_info_t* info;
|
||||
+ snd_pcm_info_alloca(&info);
|
||||
+
|
||||
+ pa_assert(pcm);
|
||||
+
|
||||
if (snd_pcm_info(pcm, info) >= 0) {
|
||||
char *md;
|
||||
int card_idx;
|
||||
@@ -1761,8 +1772,8 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
|
||||
if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
|
||||
|
||||
md = pa_sprintf_malloc("hw:%i", card_idx);
|
||||
- if (prepare_mixer(m, md) >= 0) {
|
||||
-
|
||||
+ m = pa_alsa_open_mixer_by_name(md);
|
||||
+ if (m) {
|
||||
if (ctl_device)
|
||||
*ctl_device = md;
|
||||
else
|
||||
@@ -1775,7 +1786,6 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
|
||||
}
|
||||
}
|
||||
|
||||
- snd_mixer_close(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
@ -0,0 +1,93 @@
|
||||
From dacfcbb09c9d91ca20dedfa449da37f0f7e3953f Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Sat, 7 Dec 2019 11:50:13 +0100
|
||||
Subject: [PATCH] alsa-ucm: use the proper mixer name for ucm pcm sink/source
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-sink.c | 9 ++++++++-
|
||||
src/modules/alsa/alsa-source.c | 10 +++++++++-
|
||||
src/modules/alsa/alsa-ucm.c | 9 +++++++--
|
||||
3 files changed, 24 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
|
||||
index 19e9efc3674b..5ea4b2597449 100644
|
||||
--- a/src/modules/alsa/alsa-sink.c
|
||||
+++ b/src/modules/alsa/alsa-sink.c
|
||||
@@ -2083,11 +2083,18 @@ static void set_sink_name(pa_sink_new_data *data, pa_modargs *ma, const char *de
|
||||
}
|
||||
|
||||
static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) {
|
||||
+ const char *mdev;
|
||||
|
||||
if (!mapping && !element)
|
||||
return;
|
||||
|
||||
- if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device))) {
|
||||
+ mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device");
|
||||
+ if (mdev) {
|
||||
+ u->mixer_handle = pa_alsa_open_mixer_by_name(mdev);
|
||||
+ } else {
|
||||
+ u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device);
|
||||
+ }
|
||||
+ if (!mdev) {
|
||||
pa_log_info("Failed to find a working mixer device.");
|
||||
return;
|
||||
}
|
||||
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
|
||||
index 34946b74c77f..bd78d45e2a5b 100644
|
||||
--- a/src/modules/alsa/alsa-source.c
|
||||
+++ b/src/modules/alsa/alsa-source.c
|
||||
@@ -1789,10 +1789,18 @@ static void set_source_name(pa_source_new_data *data, pa_modargs *ma, const char
|
||||
}
|
||||
|
||||
static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) {
|
||||
+ const char *mdev;
|
||||
+
|
||||
if (!mapping && !element)
|
||||
return;
|
||||
|
||||
- if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device))) {
|
||||
+ mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device");
|
||||
+ if (mdev) {
|
||||
+ u->mixer_handle = pa_alsa_open_mixer_by_name(mdev);
|
||||
+ } else {
|
||||
+ u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device);
|
||||
+ }
|
||||
+ if (!mdev) {
|
||||
pa_log_info("Failed to find a working mixer device.");
|
||||
return;
|
||||
}
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index d02adab650fe..d1ca62d28619 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -1339,7 +1339,8 @@ static void ucm_add_mapping(pa_alsa_profile *p, pa_alsa_mapping *m) {
|
||||
|
||||
static void alsa_mapping_add_ucm_device(pa_alsa_mapping *m, pa_alsa_ucm_device *device) {
|
||||
char *cur_desc;
|
||||
- const char *new_desc;
|
||||
+ const char *new_desc, *mdev;
|
||||
+ bool is_sink = m->direction == PA_ALSA_DIRECTION_OUTPUT;
|
||||
|
||||
pa_idxset_put(m->ucm_context.ucm_devices, device, NULL);
|
||||
|
||||
@@ -1355,10 +1356,14 @@ static void alsa_mapping_add_ucm_device(pa_alsa_mapping *m, pa_alsa_ucm_device *
|
||||
m->description = m->description ? m->description : pa_xstrdup("");
|
||||
|
||||
/* save mapping to ucm device */
|
||||
- if (m->direction == PA_ALSA_DIRECTION_OUTPUT)
|
||||
+ if (is_sink)
|
||||
device->playback_mapping = m;
|
||||
else
|
||||
device->capture_mapping = m;
|
||||
+
|
||||
+ mdev = get_mixer_device(device, is_sink);
|
||||
+ if (mdev)
|
||||
+ pa_proplist_sets(m->proplist, "alsa.mixer_device", mdev);
|
||||
}
|
||||
|
||||
static void alsa_mapping_add_ucm_modifier(pa_alsa_mapping *m, pa_alsa_ucm_modifier *modifier) {
|
||||
--
|
||||
2.16.4
|
||||
|
125
0025-alsa-mixer-handle-interface-type-CARD-PCM-for-mixer-.patch
Normal file
125
0025-alsa-mixer-handle-interface-type-CARD-PCM-for-mixer-.patch
Normal file
@ -0,0 +1,125 @@
|
||||
From f18b0c3402f5e1f7db9d0a42c6e10cfe1f212da3 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Sat, 7 Dec 2019 17:54:04 +0100
|
||||
Subject: [PATCH] alsa-mixer: handle interface type (CARD,PCM) for mixer
|
||||
element lookups
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-mixer.c | 2 +-
|
||||
src/modules/alsa/alsa-ucm.c | 2 +-
|
||||
src/modules/alsa/alsa-util.c | 18 +++++++++++++++++-
|
||||
src/modules/alsa/alsa-util.h | 3 ++-
|
||||
src/modules/alsa/module-alsa-card.c | 4 ++--
|
||||
5 files changed, 23 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
|
||||
index ed06f42d86da..094cff817df7 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.c
|
||||
+++ b/src/modules/alsa/alsa-mixer.c
|
||||
@@ -1907,7 +1907,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_card(m, j->alsa_name, 0) != NULL;
|
||||
pa_alsa_jack_set_has_control(j, has_control);
|
||||
|
||||
if (j->has_control) {
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index d1ca62d28619..a64505a0c781 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -1796,7 +1796,7 @@ static void ucm_mapping_jack_probe(pa_alsa_mapping *m) {
|
||||
mdev_opened = mdev;
|
||||
}
|
||||
|
||||
- has_control = pa_alsa_mixer_find(mixer_handle, dev->jack->alsa_name, 0) != NULL;
|
||||
+ has_control = pa_alsa_mixer_find_card(mixer_handle, dev->jack->alsa_name, 0) != NULL;
|
||||
pa_alsa_jack_set_has_control(dev->jack, has_control);
|
||||
pa_log_info("UCM jack %s has_control=%d", dev->jack->name, dev->jack->has_control);
|
||||
}
|
||||
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
|
||||
index 2df2258d85af..08a144782394 100644
|
||||
--- a/src/modules/alsa/alsa-util.c
|
||||
+++ b/src/modules/alsa/alsa-util.c
|
||||
@@ -1610,7 +1610,11 @@ bool pa_alsa_may_tsched(bool want) {
|
||||
|
||||
#define SND_MIXER_ELEM_PULSEAUDIO (SND_MIXER_ELEM_LAST + 10)
|
||||
|
||||
-snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device) {
|
||||
+static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer,
|
||||
+ snd_ctl_elem_iface_t iface,
|
||||
+ const char *name,
|
||||
+ unsigned int index,
|
||||
+ unsigned int device) {
|
||||
snd_mixer_elem_t *elem;
|
||||
|
||||
for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) {
|
||||
@@ -1618,8 +1622,12 @@ snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsig
|
||||
if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO)
|
||||
continue;
|
||||
helem = snd_mixer_elem_get_private(elem);
|
||||
+ if (snd_hctl_elem_get_interface(helem) != iface)
|
||||
+ continue;
|
||||
if (!pa_streq(snd_hctl_elem_get_name(helem), name))
|
||||
continue;
|
||||
+ if (snd_hctl_elem_get_index(helem) != index)
|
||||
+ continue;
|
||||
if (snd_hctl_elem_get_device(helem) != device)
|
||||
continue;
|
||||
return elem;
|
||||
@@ -1627,6 +1635,14 @@ snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsig
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, const char *name, unsigned int device) {
|
||||
+ return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, name, 0, device);
|
||||
+}
|
||||
+
|
||||
+snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device) {
|
||||
+ return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_PCM, name, 0, device);
|
||||
+}
|
||||
+
|
||||
static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
|
||||
{
|
||||
/* Dummy compare function */
|
||||
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
|
||||
index 4ceaa06ee480..ceca48809400 100644
|
||||
--- a/src/modules/alsa/alsa-util.h
|
||||
+++ b/src/modules/alsa/alsa-util.h
|
||||
@@ -141,7 +141,8 @@ const char* pa_alsa_strerror(int errnum);
|
||||
|
||||
bool pa_alsa_may_tsched(bool want);
|
||||
|
||||
-snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device);
|
||||
+snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, const char *name, unsigned int device);
|
||||
+snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device);
|
||||
|
||||
snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device);
|
||||
|
||||
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
|
||||
index be260e4badab..ba7a19a38983 100644
|
||||
--- a/src/modules/alsa/module-alsa-card.c
|
||||
+++ b/src/modules/alsa/module-alsa-card.c
|
||||
@@ -588,7 +588,7 @@ static void init_eld_ctls(struct userdata *u) {
|
||||
if (device < 0)
|
||||
continue;
|
||||
|
||||
- melem = pa_alsa_mixer_find(u->mixer_handle, "ELD", device);
|
||||
+ melem = pa_alsa_mixer_find_pcm(u->mixer_handle, "ELD", device);
|
||||
if (melem) {
|
||||
snd_mixer_elem_set_callback(melem, hdmi_eld_changed);
|
||||
snd_mixer_elem_set_callback_private(melem, u);
|
||||
@@ -635,7 +635,7 @@ static void init_jacks(struct userdata *u) {
|
||||
u->mixer_handle = pa_alsa_open_mixer(u->alsa_card_index, NULL);
|
||||
if (u->mixer_handle && pa_alsa_fdlist_set_handle(u->mixer_fdl, u->mixer_handle, NULL, u->core->mainloop) >= 0) {
|
||||
PA_HASHMAP_FOREACH(jack, u->jacks, state) {
|
||||
- jack->melem = pa_alsa_mixer_find(u->mixer_handle, jack->alsa_name, 0);
|
||||
+ jack->melem = pa_alsa_mixer_find_card(u->mixer_handle, jack->alsa_name, 0);
|
||||
if (!jack->melem) {
|
||||
pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name);
|
||||
pa_alsa_jack_set_has_control(jack, false);
|
||||
--
|
||||
2.16.4
|
||||
|
@ -0,0 +1,51 @@
|
||||
From c6a0665618975eedc98bdf23e4140935a1af38c2 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Bigonville <bigon@bigon.be>
|
||||
Date: Thu, 7 Mar 2019 11:35:30 +0100
|
||||
Subject: [PATCH] alsa-mixer: Add the ability to pass the intended-role to the
|
||||
mapping
|
||||
|
||||
https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/640
|
||||
---
|
||||
src/modules/alsa/alsa-mixer.c | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
|
||||
index 094cff817df7..7956371b604b 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.c
|
||||
+++ b/src/modules/alsa/alsa-mixer.c
|
||||
@@ -3978,6 +3978,24 @@ static int mapping_parse_fallback(pa_config_parser_state *state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int mapping_parse_intended_roles(pa_config_parser_state *state) {
|
||||
+ pa_alsa_profile_set *ps;
|
||||
+ pa_alsa_mapping *m;
|
||||
+
|
||||
+ pa_assert(state);
|
||||
+
|
||||
+ ps = state->userdata;
|
||||
+
|
||||
+ if (!(m = pa_alsa_mapping_get(ps, state->section))) {
|
||||
+ pa_log("[%s:%u] %s invalid in section %s", state->filename, state->lineno, state->lvalue, state->section);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ pa_proplist_sets(m->proplist, PA_PROP_DEVICE_INTENDED_ROLES, state->rvalue);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
|
||||
static int profile_parse_mappings(pa_config_parser_state *state) {
|
||||
pa_alsa_profile_set *ps;
|
||||
@@ -4569,6 +4587,7 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
|
||||
{ "element-output", mapping_parse_element, NULL, NULL },
|
||||
{ "direction", mapping_parse_direction, NULL, NULL },
|
||||
{ "exact-channels", mapping_parse_exact_channels, NULL, NULL },
|
||||
+ { "intended-roles", mapping_parse_intended_roles, NULL, NULL },
|
||||
|
||||
/* Shared by [Mapping ...] and [Profile ...] */
|
||||
{ "description", mapping_parse_description, NULL, NULL },
|
||||
--
|
||||
2.16.4
|
||||
|
@ -0,0 +1,39 @@
|
||||
From 6438e5c46dc449e4726ec9312859cc70388d2851 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Bigonville <bigon@bigon.be>
|
||||
Date: Thu, 7 Mar 2019 11:36:02 +0100
|
||||
Subject: [PATCH] alsa-mixer: Set the intended-role of Steelseries Arctis 5/7
|
||||
headset as phone
|
||||
|
||||
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/640
|
||||
---
|
||||
.../alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf | 1 +
|
||||
src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf b/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf
|
||||
index 80c33707aea4..5f11ed1e26ef 100644
|
||||
--- a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf
|
||||
+++ b/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf
|
||||
@@ -7,6 +7,7 @@ device-strings = hw:%f,0,0
|
||||
channel-map = left,right
|
||||
paths-input = analog-input-mic
|
||||
paths-output = steelseries-arctis-output-chat-common
|
||||
+intended-roles = phone
|
||||
|
||||
[Mapping analog-game]
|
||||
description = Game
|
||||
diff --git a/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf b/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf
|
||||
index 01ecf864bcf2..f48b44f03767 100644
|
||||
--- a/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf
|
||||
+++ b/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf
|
||||
@@ -34,6 +34,7 @@ device-strings = hw:%f,0,0
|
||||
channel-map = mono
|
||||
paths-output = usb-gaming-headset-output-mono
|
||||
paths-input = usb-gaming-headset-input
|
||||
+intended-roles = phone
|
||||
|
||||
[Mapping analog-stereo]
|
||||
device-strings = hw:%f,1,0
|
||||
--
|
||||
2.16.4
|
||||
|
761
0028-alsa-rewrite-mixer-open-close-cache-mixer-accesses-i.patch
Normal file
761
0028-alsa-rewrite-mixer-open-close-cache-mixer-accesses-i.patch
Normal file
@ -0,0 +1,761 @@
|
||||
From 3bd7c70c518d66707cbfde138ab7dcc505e463ac Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Sat, 7 Dec 2019 20:39:21 +0100
|
||||
Subject: [PATCH] alsa: rewrite mixer open/close, cache mixer accesses in probe
|
||||
|
||||
The ALSA mixer can be opened multiple times (especially for UCM
|
||||
in the probe). This adds a simple mixer cache to prevent
|
||||
multiple open calls.
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-mixer.c | 19 ++++----
|
||||
src/modules/alsa/alsa-mixer.h | 19 ++++++--
|
||||
src/modules/alsa/alsa-sink.c | 21 ++++----
|
||||
src/modules/alsa/alsa-source.c | 21 ++++----
|
||||
src/modules/alsa/alsa-ucm.c | 66 ++++++++++----------------
|
||||
src/modules/alsa/alsa-ucm.h | 1 +
|
||||
src/modules/alsa/alsa-util.c | 95 +++++++++++++++++++------------------
|
||||
src/modules/alsa/alsa-util.h | 6 ++-
|
||||
src/modules/alsa/module-alsa-card.c | 76 ++++++++++++++++++-----------
|
||||
9 files changed, 175 insertions(+), 149 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
|
||||
index 7956371b604b..a3c998b654e9 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.c
|
||||
+++ b/src/modules/alsa/alsa-mixer.c
|
||||
@@ -147,13 +147,14 @@ static int alsa_id_decode(const char *src, char *name, int *index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *name) {
|
||||
+pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name) {
|
||||
pa_alsa_jack *jack;
|
||||
|
||||
pa_assert(name);
|
||||
|
||||
jack = pa_xnew0(pa_alsa_jack, 1);
|
||||
jack->path = path;
|
||||
+ jack->mixer_device_name = pa_xstrdup(mixer_device_name);
|
||||
jack->name = pa_xstrdup(name);
|
||||
jack->alsa_name = pa_sprintf_malloc("%s Jack", name);
|
||||
jack->state_unplugged = PA_AVAILABLE_NO;
|
||||
@@ -172,6 +173,7 @@ void pa_alsa_jack_free(pa_alsa_jack *jack) {
|
||||
|
||||
pa_xfree(jack->alsa_name);
|
||||
pa_xfree(jack->name);
|
||||
+ pa_xfree(jack->mixer_device_name);
|
||||
pa_xfree(jack);
|
||||
}
|
||||
|
||||
@@ -1982,7 +1984,7 @@ static pa_alsa_jack* jack_get(pa_alsa_path *p, const char *section) {
|
||||
if (pa_streq(j->name, section))
|
||||
goto finish;
|
||||
|
||||
- j = pa_alsa_jack_new(p, section);
|
||||
+ j = pa_alsa_jack_new(p, NULL, section);
|
||||
PA_LLIST_INSERT_AFTER(pa_alsa_jack, p->jacks, p->last_jack, j);
|
||||
|
||||
finish:
|
||||
@@ -4160,7 +4162,8 @@ fail:
|
||||
}
|
||||
|
||||
static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
|
||||
- pa_alsa_direction_t direction, pa_hashmap *used_paths) {
|
||||
+ pa_alsa_direction_t direction, pa_hashmap *used_paths,
|
||||
+ pa_hashmap *mixers) {
|
||||
|
||||
pa_alsa_path *p;
|
||||
void *state;
|
||||
@@ -4185,7 +4188,7 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
|
||||
- mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL);
|
||||
+ mixer_handle = pa_alsa_open_mixer_for_pcm(mixers, pcm_handle, true);
|
||||
if (!mixer_handle) {
|
||||
/* Cannot open mixer, remove all entries */
|
||||
pa_hashmap_remove_all(ps->paths);
|
||||
@@ -4203,9 +4206,6 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
|
||||
path_set_condense(ps, mixer_handle);
|
||||
path_set_make_path_descriptions_unique(ps);
|
||||
|
||||
- if (mixer_handle)
|
||||
- snd_mixer_close(mixer_handle);
|
||||
-
|
||||
PA_HASHMAP_FOREACH(p, ps->paths, state)
|
||||
pa_hashmap_put(used_paths, p, p);
|
||||
|
||||
@@ -4785,6 +4785,7 @@ static void mapping_query_hw_device(pa_alsa_mapping *mapping, snd_pcm_t *pcm) {
|
||||
|
||||
void pa_alsa_profile_set_probe(
|
||||
pa_alsa_profile_set *ps,
|
||||
+ pa_hashmap *mixers,
|
||||
const char *dev_id,
|
||||
const pa_sample_spec *ss,
|
||||
unsigned default_n_fragments,
|
||||
@@ -4914,14 +4915,14 @@ void pa_alsa_profile_set_probe(
|
||||
PA_IDXSET_FOREACH(m, p->output_mappings, idx)
|
||||
if (m->output_pcm) {
|
||||
found_output |= !p->fallback_output;
|
||||
- mapping_paths_probe(m, p, PA_ALSA_DIRECTION_OUTPUT, used_paths);
|
||||
+ mapping_paths_probe(m, p, PA_ALSA_DIRECTION_OUTPUT, used_paths, mixers);
|
||||
}
|
||||
|
||||
if (p->input_mappings)
|
||||
PA_IDXSET_FOREACH(m, p->input_mappings, idx)
|
||||
if (m->input_pcm) {
|
||||
found_input |= !p->fallback_input;
|
||||
- mapping_paths_probe(m, p, PA_ALSA_DIRECTION_INPUT, used_paths);
|
||||
+ mapping_paths_probe(m, p, PA_ALSA_DIRECTION_INPUT, used_paths, mixers);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
|
||||
index 7864a2c1252f..325b0c998b02 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.h
|
||||
+++ b/src/modules/alsa/alsa-mixer.h
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <pulsecore/rtpoll.h>
|
||||
|
||||
typedef struct pa_alsa_fdlist pa_alsa_fdlist;
|
||||
+typedef struct pa_alsa_mixer pa_alsa_mixer;
|
||||
typedef struct pa_alsa_mixer_pdata pa_alsa_mixer_pdata;
|
||||
typedef struct pa_alsa_setting pa_alsa_setting;
|
||||
typedef struct pa_alsa_mixer_id pa_alsa_mixer_id;
|
||||
@@ -98,6 +99,13 @@ struct pa_alsa_setting {
|
||||
unsigned priority;
|
||||
};
|
||||
|
||||
+/* An entry for one ALSA mixer */
|
||||
+struct pa_alsa_mixer {
|
||||
+ snd_mixer_t *mixer_handle;
|
||||
+ pa_alsa_fdlist *fdl;
|
||||
+ bool used_for_probe_only:1;
|
||||
+};
|
||||
+
|
||||
/* ALSA mixer element identifier */
|
||||
struct pa_alsa_mixer_id {
|
||||
char *name;
|
||||
@@ -165,6 +173,9 @@ struct pa_alsa_jack {
|
||||
pa_alsa_path *path;
|
||||
PA_LLIST_FIELDS(pa_alsa_jack);
|
||||
|
||||
+ snd_mixer_t *mixer_handle;
|
||||
+ char *mixer_device_name;
|
||||
+
|
||||
char *name; /* E g "Headphone" */
|
||||
char *alsa_name; /* E g "Headphone Jack" */
|
||||
bool has_control; /* is the jack itself present? */
|
||||
@@ -182,7 +193,7 @@ struct pa_alsa_jack {
|
||||
bool append_pcm_to_name;
|
||||
};
|
||||
|
||||
-pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *name);
|
||||
+pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name);
|
||||
void pa_alsa_jack_free(pa_alsa_jack *jack);
|
||||
void pa_alsa_jack_set_has_control(pa_alsa_jack *jack, bool has_control);
|
||||
void pa_alsa_jack_set_plugged_in(pa_alsa_jack *jack, bool plugged_in);
|
||||
@@ -201,6 +212,7 @@ struct pa_alsa_path {
|
||||
char *description;
|
||||
unsigned priority;
|
||||
bool autodetect_eld_device;
|
||||
+ pa_alsa_mixer *eld_mixer_handle;
|
||||
int eld_device;
|
||||
pa_proplist *proplist;
|
||||
|
||||
@@ -359,14 +371,11 @@ void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix);
|
||||
pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name);
|
||||
|
||||
pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus);
|
||||
-void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec);
|
||||
+void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, pa_hashmap *mixers, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec);
|
||||
void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
|
||||
void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
|
||||
void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *s);
|
||||
|
||||
-snd_mixer_t *pa_alsa_open_mixer_by_name(const char *dev);
|
||||
-snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device);
|
||||
-
|
||||
pa_alsa_fdlist *pa_alsa_fdlist_new(void);
|
||||
void pa_alsa_fdlist_free(pa_alsa_fdlist *fdl);
|
||||
int pa_alsa_fdlist_set_handle(pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, snd_hctl_t *hctl_handle, pa_mainloop_api* m);
|
||||
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
|
||||
index 5ea4b2597449..363b4be2fa25 100644
|
||||
--- a/src/modules/alsa/alsa-sink.c
|
||||
+++ b/src/modules/alsa/alsa-sink.c
|
||||
@@ -105,6 +105,7 @@ struct userdata {
|
||||
char *paths_dir;
|
||||
pa_alsa_fdlist *mixer_fdl;
|
||||
pa_alsa_mixer_pdata *mixer_pd;
|
||||
+ pa_hashmap *mixers;
|
||||
snd_mixer_t *mixer_handle;
|
||||
pa_alsa_path_set *mixer_path_set;
|
||||
pa_alsa_path *mixer_path;
|
||||
@@ -2088,13 +2089,16 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
if (!mapping && !element)
|
||||
return;
|
||||
|
||||
+ u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
|
||||
+ NULL, (pa_free_cb_t) pa_alsa_mixer_free);
|
||||
+
|
||||
mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device");
|
||||
if (mdev) {
|
||||
- u->mixer_handle = pa_alsa_open_mixer_by_name(mdev);
|
||||
+ u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, true);
|
||||
} else {
|
||||
- u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device);
|
||||
+ u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->mixers, u->pcm_handle, true);
|
||||
}
|
||||
- if (!mdev) {
|
||||
+ if (!u->mixer_handle) {
|
||||
pa_log_info("Failed to find a working mixer device.");
|
||||
return;
|
||||
}
|
||||
@@ -2121,10 +2125,9 @@ fail:
|
||||
u->mixer_path = NULL;
|
||||
}
|
||||
|
||||
- if (u->mixer_handle) {
|
||||
- snd_mixer_close(u->mixer_handle);
|
||||
- u->mixer_handle = NULL;
|
||||
- }
|
||||
+ u->mixer_handle = NULL;
|
||||
+ pa_hashmap_free(u->mixers);
|
||||
+ u->mixers = NULL;
|
||||
}
|
||||
|
||||
static int setup_mixer(struct userdata *u, bool ignore_dB) {
|
||||
@@ -2759,8 +2762,8 @@ static void userdata_free(struct userdata *u) {
|
||||
if (u->mixer_path && !u->mixer_path_set && !u->ucm_context)
|
||||
pa_alsa_path_free(u->mixer_path);
|
||||
|
||||
- if (u->mixer_handle)
|
||||
- snd_mixer_close(u->mixer_handle);
|
||||
+ if (u->mixers)
|
||||
+ pa_hashmap_free(u->mixers);
|
||||
|
||||
if (u->smoother)
|
||||
pa_smoother_free(u->smoother);
|
||||
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
|
||||
index bd78d45e2a5b..b46e845cc5a7 100644
|
||||
--- a/src/modules/alsa/alsa-source.c
|
||||
+++ b/src/modules/alsa/alsa-source.c
|
||||
@@ -93,6 +93,7 @@ struct userdata {
|
||||
char *paths_dir;
|
||||
pa_alsa_fdlist *mixer_fdl;
|
||||
pa_alsa_mixer_pdata *mixer_pd;
|
||||
+ pa_hashmap *mixers;
|
||||
snd_mixer_t *mixer_handle;
|
||||
pa_alsa_path_set *mixer_path_set;
|
||||
pa_alsa_path *mixer_path;
|
||||
@@ -1794,13 +1795,16 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
if (!mapping && !element)
|
||||
return;
|
||||
|
||||
+ u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
|
||||
+ NULL, (pa_free_cb_t) pa_alsa_mixer_free);
|
||||
+
|
||||
mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device");
|
||||
if (mdev) {
|
||||
- u->mixer_handle = pa_alsa_open_mixer_by_name(mdev);
|
||||
+ u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, false);
|
||||
} else {
|
||||
- u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device);
|
||||
+ u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->mixers, u->pcm_handle, false);
|
||||
}
|
||||
- if (!mdev) {
|
||||
+ if (!u->mixer_handle) {
|
||||
pa_log_info("Failed to find a working mixer device.");
|
||||
return;
|
||||
}
|
||||
@@ -1827,10 +1831,9 @@ fail:
|
||||
u->mixer_path = NULL;
|
||||
}
|
||||
|
||||
- if (u->mixer_handle) {
|
||||
- snd_mixer_close(u->mixer_handle);
|
||||
- u->mixer_handle = NULL;
|
||||
- }
|
||||
+ u->mixer_handle = NULL;
|
||||
+ pa_hashmap_free(u->mixers);
|
||||
+ u->mixers = NULL;
|
||||
}
|
||||
|
||||
static int setup_mixer(struct userdata *u, bool ignore_dB) {
|
||||
@@ -2403,8 +2406,8 @@ static void userdata_free(struct userdata *u) {
|
||||
if (u->mixer_path && !u->mixer_path_set && !u->ucm_context)
|
||||
pa_alsa_path_free(u->mixer_path);
|
||||
|
||||
- if (u->mixer_handle)
|
||||
- snd_mixer_close(u->mixer_handle);
|
||||
+ if (u->mixers)
|
||||
+ pa_hashmap_free(u->mixers);
|
||||
|
||||
if (u->smoother)
|
||||
pa_smoother_free(u->smoother);
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index a64505a0c781..b9a4b8c4b436 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -820,13 +820,13 @@ static int pa_alsa_ucm_device_cmp(const void *a, const void *b) {
|
||||
return strcmp(pa_proplist_gets(d1->proplist, PA_ALSA_PROP_UCM_NAME), pa_proplist_gets(d2->proplist, PA_ALSA_PROP_UCM_NAME));
|
||||
}
|
||||
|
||||
-static void probe_volumes(pa_hashmap *hash, bool is_sink, snd_pcm_t *pcm_handle, bool ignore_dB) {
|
||||
+static void probe_volumes(pa_hashmap *hash, bool is_sink, snd_pcm_t *pcm_handle, pa_hashmap *mixers, bool ignore_dB) {
|
||||
pa_device_port *port;
|
||||
pa_alsa_path *path;
|
||||
pa_alsa_ucm_port_data *data;
|
||||
pa_alsa_ucm_device *dev;
|
||||
- snd_mixer_t *mixer_handle = NULL;
|
||||
- const char *profile, *mdev_opened = NULL, *mdev, *mdev2;
|
||||
+ snd_mixer_t *mixer_handle;
|
||||
+ const char *profile, *mdev, *mdev2;
|
||||
void *state, *state2;
|
||||
int idx;
|
||||
|
||||
@@ -843,16 +843,9 @@ static void probe_volumes(pa_hashmap *hash, bool is_sink, snd_pcm_t *pcm_handle,
|
||||
mdev = mdev2;
|
||||
}
|
||||
|
||||
- if (!mdev_opened || !pa_streq(mdev_opened, mdev)) {
|
||||
- if (mixer_handle) {
|
||||
- snd_mixer_close(mixer_handle);
|
||||
- mdev_opened = NULL;
|
||||
- }
|
||||
- if (!(mixer_handle = pa_alsa_open_mixer_by_name(mdev))) {
|
||||
- pa_log_error("Failed to find a working mixer device (%s).", mdev);
|
||||
- goto fail;
|
||||
- }
|
||||
- mdev_opened = mdev;
|
||||
+ if (!(mixer_handle = pa_alsa_open_mixer_by_name(mixers, mdev, true))) {
|
||||
+ pa_log_error("Failed to find a working mixer device (%s).", mdev);
|
||||
+ goto fail;
|
||||
}
|
||||
|
||||
PA_HASHMAP_FOREACH_KV(profile, path, data->paths, state2) {
|
||||
@@ -867,9 +860,6 @@ static void probe_volumes(pa_hashmap *hash, bool is_sink, snd_pcm_t *pcm_handle,
|
||||
}
|
||||
}
|
||||
|
||||
- if (mixer_handle)
|
||||
- snd_mixer_close(mixer_handle);
|
||||
-
|
||||
return;
|
||||
|
||||
fail:
|
||||
@@ -1194,7 +1184,7 @@ void pa_alsa_ucm_add_ports(
|
||||
pa_alsa_ucm_add_ports_combination(*p, context, is_sink, card->ports, NULL, card->core);
|
||||
|
||||
/* now set up volume paths if any */
|
||||
- probe_volumes(*p, is_sink, pcm_handle, ignore_dB);
|
||||
+ probe_volumes(*p, is_sink, pcm_handle, context->ucm->mixers, ignore_dB);
|
||||
|
||||
/* then set property PA_PROP_DEVICE_INTENDED_ROLES */
|
||||
merged_roles = pa_xstrdup(pa_proplist_gets(proplist, PA_PROP_DEVICE_INTENDED_ROLES));
|
||||
@@ -1543,6 +1533,7 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d
|
||||
pa_alsa_jack *j;
|
||||
const char *device_name;
|
||||
const char *jack_control;
|
||||
+ const char *mixer_device_name;
|
||||
char *name;
|
||||
|
||||
pa_assert(ucm);
|
||||
@@ -1585,7 +1576,14 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d
|
||||
if (pa_streq(j->name, name))
|
||||
goto finish;
|
||||
|
||||
- j = pa_alsa_jack_new(NULL, name);
|
||||
+ mixer_device_name = get_jack_mixer_device(device, true);
|
||||
+ if (!mixer_device_name)
|
||||
+ mixer_device_name = get_jack_mixer_device(device, false);
|
||||
+ if (!mixer_device_name) {
|
||||
+ pa_log("[%s] No mixer device name for JackControl \"%s\"", device_name, jack_control);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ j = pa_alsa_jack_new(NULL, mixer_device_name, name);
|
||||
PA_LLIST_PREPEND(pa_alsa_jack, ucm->jacks, j);
|
||||
|
||||
finish:
|
||||
@@ -1765,44 +1763,28 @@ static void profile_finalize_probing(pa_alsa_profile *p) {
|
||||
}
|
||||
}
|
||||
|
||||
-static void ucm_mapping_jack_probe(pa_alsa_mapping *m) {
|
||||
- snd_mixer_t *mixer_handle = NULL;
|
||||
+static void ucm_mapping_jack_probe(pa_alsa_mapping *m, pa_hashmap *mixers) {
|
||||
+ snd_mixer_t *mixer_handle;
|
||||
pa_alsa_ucm_mapping_context *context = &m->ucm_context;
|
||||
pa_alsa_ucm_device *dev;
|
||||
- bool is_sink = m->direction == PA_ALSA_DIRECTION_OUTPUT;
|
||||
- const char *mdev_opened = NULL, *mdev;
|
||||
uint32_t idx;
|
||||
|
||||
PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) {
|
||||
bool has_control;
|
||||
|
||||
- if (!dev->jack)
|
||||
+ if (!dev->jack || !dev->jack->mixer_device_name)
|
||||
continue;
|
||||
|
||||
- mdev = get_jack_mixer_device(dev, is_sink);
|
||||
- if (mdev == NULL) {
|
||||
- pa_log_error("Unable to determine mixer device for jack %s", dev->jack->name);
|
||||
+ mixer_handle = pa_alsa_open_mixer_by_name(mixers, dev->jack->mixer_device_name, true);
|
||||
+ if (!mixer_handle) {
|
||||
+ pa_log_error("Unable to determine open mixer device '%s' for jack %s", dev->jack->mixer_device_name, dev->jack->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (!mdev_opened || !pa_streq(mdev_opened, mdev)) {
|
||||
- if (mixer_handle) {
|
||||
- snd_mixer_close(mixer_handle);
|
||||
- mdev_opened = NULL;
|
||||
- }
|
||||
- mixer_handle = pa_alsa_open_mixer_by_name(mdev);
|
||||
- if (!mixer_handle)
|
||||
- continue;
|
||||
- mdev_opened = mdev;
|
||||
- }
|
||||
-
|
||||
has_control = pa_alsa_mixer_find_card(mixer_handle, dev->jack->alsa_name, 0) != NULL;
|
||||
pa_alsa_jack_set_has_control(dev->jack, has_control);
|
||||
pa_log_info("UCM jack %s has_control=%d", dev->jack->name, dev->jack->has_control);
|
||||
}
|
||||
-
|
||||
- if (mixer_handle)
|
||||
- snd_mixer_close(mixer_handle);
|
||||
}
|
||||
|
||||
static void ucm_probe_profile_set(pa_alsa_ucm_config *ucm, pa_alsa_profile_set *ps) {
|
||||
@@ -1860,11 +1842,11 @@ static void ucm_probe_profile_set(pa_alsa_ucm_config *ucm, pa_alsa_profile_set *
|
||||
|
||||
PA_IDXSET_FOREACH(m, p->output_mappings, idx)
|
||||
if (!PA_UCM_IS_MODIFIER_MAPPING(m))
|
||||
- ucm_mapping_jack_probe(m);
|
||||
+ ucm_mapping_jack_probe(m, ucm->mixers);
|
||||
|
||||
PA_IDXSET_FOREACH(m, p->input_mappings, idx)
|
||||
if (!PA_UCM_IS_MODIFIER_MAPPING(m))
|
||||
- ucm_mapping_jack_probe(m);
|
||||
+ ucm_mapping_jack_probe(m, ucm->mixers);
|
||||
|
||||
profile_finalize_probing(p);
|
||||
}
|
||||
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
|
||||
index 014bc334ad67..49362992865b 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.h
|
||||
+++ b/src/modules/alsa/alsa-ucm.h
|
||||
@@ -248,6 +248,7 @@ struct pa_alsa_ucm_config {
|
||||
snd_use_case_mgr_t *ucm_mgr;
|
||||
pa_alsa_ucm_verb *active_verb;
|
||||
|
||||
+ pa_hashmap *mixers;
|
||||
PA_LLIST_HEAD(pa_alsa_ucm_verb, verbs);
|
||||
PA_LLIST_HEAD(pa_alsa_jack, jacks);
|
||||
};
|
||||
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
|
||||
index 08a144782394..34930c9fa155 100644
|
||||
--- a/src/modules/alsa/alsa-util.c
|
||||
+++ b/src/modules/alsa/alsa-util.c
|
||||
@@ -1726,83 +1726,86 @@ static int prepare_mixer(snd_mixer_t *mixer, const char *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device) {
|
||||
- int err;
|
||||
- snd_mixer_t *m;
|
||||
- char *md;
|
||||
- snd_pcm_info_t* info;
|
||||
- snd_pcm_info_alloca(&info);
|
||||
-
|
||||
- if ((err = snd_mixer_open(&m, 0)) < 0) {
|
||||
- pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- /* Then, try by card index */
|
||||
- md = pa_sprintf_malloc("hw:%i", alsa_card_index);
|
||||
- if (prepare_mixer(m, md) >= 0) {
|
||||
-
|
||||
- if (ctl_device)
|
||||
- *ctl_device = md;
|
||||
- else
|
||||
- pa_xfree(md);
|
||||
-
|
||||
- return m;
|
||||
- }
|
||||
-
|
||||
+snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool probe) {
|
||||
+ char *md = pa_sprintf_malloc("hw:%i", alsa_card_index);
|
||||
+ snd_mixer_t *m = pa_alsa_open_mixer_by_name(mixers, md, probe);
|
||||
pa_xfree(md);
|
||||
-
|
||||
- snd_mixer_close(m);
|
||||
- return NULL;
|
||||
+ return m;
|
||||
}
|
||||
|
||||
-snd_mixer_t *pa_alsa_open_mixer_by_name(const char *dev) {
|
||||
+snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe) {
|
||||
int err;
|
||||
snd_mixer_t *m;
|
||||
+ pa_alsa_mixer *pm;
|
||||
|
||||
+ pa_assert(mixers);
|
||||
pa_assert(dev);
|
||||
|
||||
+ pm = pa_hashmap_get(mixers, dev);
|
||||
+ if (pm) {
|
||||
+ if (!probe)
|
||||
+ pm->used_for_probe_only = false;
|
||||
+ return pm->mixer_handle;
|
||||
+ }
|
||||
+
|
||||
if ((err = snd_mixer_open(&m, 0)) < 0) {
|
||||
pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (prepare_mixer(m, dev) >= 0)
|
||||
- return m;
|
||||
+ if (prepare_mixer(m, dev) >= 0) {
|
||||
+ pm = pa_xnew0(pa_alsa_mixer, 1);
|
||||
+ if (pm) {
|
||||
+ pm->used_for_probe_only = probe;
|
||||
+ pm->mixer_handle = m;
|
||||
+ pa_hashmap_put(mixers, pa_xstrdup(dev), pm);
|
||||
+ return m;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
snd_mixer_close(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
|
||||
- snd_mixer_t *m;
|
||||
+snd_mixer_t *pa_alsa_open_mixer_for_pcm(pa_hashmap *mixers, snd_pcm_t *pcm, bool probe) {
|
||||
snd_pcm_info_t* info;
|
||||
snd_pcm_info_alloca(&info);
|
||||
|
||||
pa_assert(pcm);
|
||||
|
||||
if (snd_pcm_info(pcm, info) >= 0) {
|
||||
- char *md;
|
||||
int card_idx;
|
||||
|
||||
- if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
|
||||
+ if ((card_idx = snd_pcm_info_get_card(info)) >= 0)
|
||||
+ return pa_alsa_open_mixer(mixers, card_idx, probe);
|
||||
+ }
|
||||
|
||||
- md = pa_sprintf_malloc("hw:%i", card_idx);
|
||||
- m = pa_alsa_open_mixer_by_name(md);
|
||||
- if (m) {
|
||||
- if (ctl_device)
|
||||
- *ctl_device = md;
|
||||
- else
|
||||
- pa_xfree(md);
|
||||
+ return NULL;
|
||||
+}
|
||||
|
||||
- return m;
|
||||
- }
|
||||
+void pa_alsa_mixer_set_fdlist(pa_hashmap *mixers, snd_mixer_t *mixer_handle, pa_mainloop_api *ml)
|
||||
+{
|
||||
+ pa_alsa_mixer *pm;
|
||||
+ void *state;
|
||||
|
||||
- pa_xfree(md);
|
||||
+ PA_HASHMAP_FOREACH(pm, mixers, state)
|
||||
+ if (pm->mixer_handle == mixer_handle) {
|
||||
+ pm->used_for_probe_only = false;
|
||||
+ if (!pm->fdl) {
|
||||
+ pm->fdl = pa_alsa_fdlist_new();
|
||||
+ if (pm->fdl)
|
||||
+ pa_alsa_fdlist_set_handle(pm->fdl, pm->mixer_handle, NULL, ml);
|
||||
+ }
|
||||
}
|
||||
- }
|
||||
+}
|
||||
|
||||
- return NULL;
|
||||
+void pa_alsa_mixer_free(pa_alsa_mixer *mixer)
|
||||
+{
|
||||
+ if (mixer->fdl)
|
||||
+ pa_alsa_fdlist_free(mixer->fdl);
|
||||
+ if (mixer->mixer_handle)
|
||||
+ snd_mixer_close(mixer->mixer_handle);
|
||||
+ pa_xfree(mixer);
|
||||
}
|
||||
|
||||
int pa_alsa_get_hdmi_eld(snd_hctl_elem_t *elem, pa_hdmi_eld *eld) {
|
||||
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
|
||||
index ceca48809400..0d3d5af13370 100644
|
||||
--- a/src/modules/alsa/alsa-util.h
|
||||
+++ b/src/modules/alsa/alsa-util.h
|
||||
@@ -144,7 +144,11 @@ bool pa_alsa_may_tsched(bool want);
|
||||
snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, const char *name, unsigned int device);
|
||||
snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device);
|
||||
|
||||
-snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device);
|
||||
+snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool probe);
|
||||
+snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe);
|
||||
+snd_mixer_t *pa_alsa_open_mixer_for_pcm(pa_hashmap *mixers, snd_pcm_t *pcm, bool probe);
|
||||
+void pa_alsa_mixer_set_fdlist(pa_hashmap *mixers, snd_mixer_t *mixer, pa_mainloop_api *ml);
|
||||
+void pa_alsa_mixer_free(pa_alsa_mixer *mixer);
|
||||
|
||||
typedef struct pa_hdmi_eld pa_hdmi_eld;
|
||||
struct pa_hdmi_eld {
|
||||
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
|
||||
index ba7a19a38983..3b2f99fc4e54 100644
|
||||
--- a/src/modules/alsa/module-alsa-card.c
|
||||
+++ b/src/modules/alsa/module-alsa-card.c
|
||||
@@ -111,9 +111,8 @@ struct userdata {
|
||||
char *device_id;
|
||||
int alsa_card_index;
|
||||
|
||||
- snd_mixer_t *mixer_handle;
|
||||
+ pa_hashmap *mixers;
|
||||
pa_hashmap *jacks;
|
||||
- pa_alsa_fdlist *mixer_fdl;
|
||||
|
||||
pa_card *card;
|
||||
|
||||
@@ -569,9 +568,6 @@ static void init_eld_ctls(struct userdata *u) {
|
||||
void *state;
|
||||
pa_device_port *port;
|
||||
|
||||
- if (!u->mixer_handle)
|
||||
- return;
|
||||
-
|
||||
/* The code in this function expects ports to have a pa_alsa_port_data
|
||||
* struct as their data, but in UCM mode ports don't have any data. Hence,
|
||||
* the ELD controls can't currently be used in UCM mode. */
|
||||
@@ -580,6 +576,7 @@ static void init_eld_ctls(struct userdata *u) {
|
||||
|
||||
PA_HASHMAP_FOREACH(port, u->card->ports, state) {
|
||||
pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(port);
|
||||
+ snd_mixer_t *mixer_handle;
|
||||
snd_mixer_elem_t* melem;
|
||||
int device;
|
||||
|
||||
@@ -588,8 +585,13 @@ static void init_eld_ctls(struct userdata *u) {
|
||||
if (device < 0)
|
||||
continue;
|
||||
|
||||
- melem = pa_alsa_mixer_find_pcm(u->mixer_handle, "ELD", device);
|
||||
+ mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, true);
|
||||
+ if (!mixer_handle)
|
||||
+ continue;
|
||||
+
|
||||
+ melem = pa_alsa_mixer_find_pcm(mixer_handle, "ELD", device);
|
||||
if (melem) {
|
||||
+ pa_alsa_mixer_set_fdlist(u->mixers, mixer_handle, u->core->mainloop);
|
||||
snd_mixer_elem_set_callback(melem, hdmi_eld_changed);
|
||||
snd_mixer_elem_set_callback_private(melem, u);
|
||||
hdmi_eld_changed(melem, 0);
|
||||
@@ -630,25 +632,31 @@ static void init_jacks(struct userdata *u) {
|
||||
if (pa_hashmap_size(u->jacks) == 0)
|
||||
return;
|
||||
|
||||
- u->mixer_fdl = pa_alsa_fdlist_new();
|
||||
-
|
||||
- u->mixer_handle = pa_alsa_open_mixer(u->alsa_card_index, NULL);
|
||||
- if (u->mixer_handle && pa_alsa_fdlist_set_handle(u->mixer_fdl, u->mixer_handle, NULL, u->core->mainloop) >= 0) {
|
||||
- PA_HASHMAP_FOREACH(jack, u->jacks, state) {
|
||||
- jack->melem = pa_alsa_mixer_find_card(u->mixer_handle, jack->alsa_name, 0);
|
||||
- if (!jack->melem) {
|
||||
- pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name);
|
||||
- pa_alsa_jack_set_has_control(jack, false);
|
||||
- continue;
|
||||
+ PA_HASHMAP_FOREACH(jack, u->jacks, state) {
|
||||
+ if (!jack->mixer_device_name) {
|
||||
+ jack->mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, false);
|
||||
+ if (!jack->mixer_handle) {
|
||||
+ pa_log("Failed to open mixer for card %d for jack detection", u->alsa_card_index);
|
||||
+ continue;
|
||||
+ }
|
||||
+ } else {
|
||||
+ jack->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, jack->mixer_device_name, false);
|
||||
+ if (!jack->mixer_handle) {
|
||||
+ pa_log("Failed to open mixer '%s' for jack detection", jack->mixer_device_name);
|
||||
+ continue;
|
||||
}
|
||||
- snd_mixer_elem_set_callback(jack->melem, report_jack_state);
|
||||
- snd_mixer_elem_set_callback_private(jack->melem, u);
|
||||
- report_jack_state(jack->melem, 0);
|
||||
}
|
||||
-
|
||||
- } else
|
||||
- pa_log("Failed to open mixer for jack detection");
|
||||
-
|
||||
+ pa_alsa_mixer_set_fdlist(u->mixers, jack->mixer_handle, u->core->mainloop);
|
||||
+ jack->melem = pa_alsa_mixer_find_card(jack->mixer_handle, jack->alsa_name, 0);
|
||||
+ if (!jack->melem) {
|
||||
+ pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name);
|
||||
+ pa_alsa_jack_set_has_control(jack, false);
|
||||
+ continue;
|
||||
+ }
|
||||
+ snd_mixer_elem_set_callback(jack->melem, report_jack_state);
|
||||
+ snd_mixer_elem_set_callback_private(jack->melem, u);
|
||||
+ report_jack_state(jack->melem, 0);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void set_card_name(pa_card_new_data *data, pa_modargs *ma, const char *device_id) {
|
||||
@@ -772,6 +780,10 @@ int pa__init(pa_module *m) {
|
||||
u->use_ucm = true;
|
||||
u->ucm.core = m->core;
|
||||
|
||||
+ u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
|
||||
+ pa_xfree, (pa_free_cb_t) pa_alsa_mixer_free);
|
||||
+ u->ucm.mixers = u->mixers; /* alias */
|
||||
+
|
||||
if (!(u->modargs = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments.");
|
||||
goto fail;
|
||||
@@ -852,7 +864,7 @@ int pa__init(pa_module *m) {
|
||||
|
||||
u->profile_set->ignore_dB = ignore_dB;
|
||||
|
||||
- pa_alsa_profile_set_probe(u->profile_set, u->device_id, &m->core->default_sample_spec, m->core->default_n_fragments, m->core->default_fragment_size_msec);
|
||||
+ pa_alsa_profile_set_probe(u->profile_set, u->mixers, u->device_id, &m->core->default_sample_spec, m->core->default_n_fragments, m->core->default_fragment_size_msec);
|
||||
pa_alsa_profile_set_dump(u->profile_set);
|
||||
|
||||
pa_card_new_data_init(&data);
|
||||
@@ -952,6 +964,16 @@ int pa__init(pa_module *m) {
|
||||
init_profile(u);
|
||||
init_eld_ctls(u);
|
||||
|
||||
+ /* Remove all probe only mixers */
|
||||
+ if (u->mixers) {
|
||||
+ const char *devname;
|
||||
+ pa_alsa_mixer *pm;
|
||||
+ void *state;
|
||||
+ PA_HASHMAP_FOREACH_KV(devname, pm, u->mixers, state)
|
||||
+ if (pm->used_for_probe_only)
|
||||
+ pa_hashmap_remove_and_free(u->mixers, devname);
|
||||
+ }
|
||||
+
|
||||
if (reserve)
|
||||
pa_reserve_wrapper_unref(reserve);
|
||||
|
||||
@@ -1002,10 +1024,8 @@ void pa__done(pa_module*m) {
|
||||
if (!(u = m->userdata))
|
||||
goto finish;
|
||||
|
||||
- if (u->mixer_fdl)
|
||||
- pa_alsa_fdlist_free(u->mixer_fdl);
|
||||
- if (u->mixer_handle)
|
||||
- snd_mixer_close(u->mixer_handle);
|
||||
+ if (u->mixers)
|
||||
+ pa_hashmap_free(u->mixers);
|
||||
if (u->jacks)
|
||||
pa_hashmap_free(u->jacks);
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
264
0029-alsa-ucm-add-support-for-HDMI-ELD.patch
Normal file
264
0029-alsa-ucm-add-support-for-HDMI-ELD.patch
Normal file
@ -0,0 +1,264 @@
|
||||
From 3ceff8bb3f697ec16dc5c72e658b10ac40bc19f5 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Sat, 7 Dec 2019 23:22:33 +0100
|
||||
Subject: [PATCH] alsa-ucm: add support for HDMI ELD
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 72 +++++++++++++++++++++++++++++++++++--
|
||||
src/modules/alsa/alsa-ucm.h | 7 ++++
|
||||
src/modules/alsa/module-alsa-card.c | 56 ++++++++++++++++++-----------
|
||||
3 files changed, 113 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index b9a4b8c4b436..5695840abaf1 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -820,6 +820,36 @@ static int pa_alsa_ucm_device_cmp(const void *a, const void *b) {
|
||||
return strcmp(pa_proplist_gets(d1->proplist, PA_ALSA_PROP_UCM_NAME), pa_proplist_gets(d2->proplist, PA_ALSA_PROP_UCM_NAME));
|
||||
}
|
||||
|
||||
+static void set_eld_devices(pa_hashmap *hash)
|
||||
+{
|
||||
+ pa_device_port *port;
|
||||
+ pa_alsa_ucm_port_data *data;
|
||||
+ pa_alsa_ucm_device *dev;
|
||||
+ const char *eld_mixer_device_name;
|
||||
+ void *state;
|
||||
+ int idx, eld_device;
|
||||
+
|
||||
+ PA_HASHMAP_FOREACH(port, hash, state) {
|
||||
+ data = PA_DEVICE_PORT_DATA(port);
|
||||
+ eld_mixer_device_name = NULL;
|
||||
+ eld_device = -1;
|
||||
+ PA_DYNARRAY_FOREACH(dev, data->devices, idx) {
|
||||
+ if (dev->eld_device >= 0 && dev->eld_mixer_device_name) {
|
||||
+ if (eld_device >= 0 && eld_device != dev->eld_device) {
|
||||
+ pa_log_error("The ELD device is already set!");
|
||||
+ } else if (eld_mixer_device_name && pa_streq(dev->eld_mixer_device_name, eld_mixer_device_name)) {
|
||||
+ pa_log_error("The ELD mixer device is already set (%s, %s)!", dev->eld_mixer_device_name, dev->eld_mixer_device_name);
|
||||
+ } else {
|
||||
+ eld_mixer_device_name = dev->eld_mixer_device_name;
|
||||
+ eld_device = dev->eld_device;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ data->eld_device = eld_device;
|
||||
+ data->eld_mixer_device_name = pa_xstrdup(eld_mixer_device_name);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void probe_volumes(pa_hashmap *hash, bool is_sink, snd_pcm_t *pcm_handle, pa_hashmap *mixers, bool ignore_dB) {
|
||||
pa_device_port *port;
|
||||
pa_alsa_path *path;
|
||||
@@ -1159,6 +1189,9 @@ void pa_alsa_ucm_add_ports_combination(
|
||||
ucm_add_ports_combination(p, context, is_sink, pdevices, 0, PA_IDXSET_INVALID, ports, cp, core);
|
||||
pa_xfree(pdevices);
|
||||
}
|
||||
+
|
||||
+ /* ELD devices */
|
||||
+ set_eld_devices(ports);
|
||||
}
|
||||
|
||||
void pa_alsa_ucm_add_ports(
|
||||
@@ -1709,6 +1742,33 @@ static int ucm_create_profile(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void mapping_init_eld(pa_alsa_mapping *m, snd_pcm_t *pcm)
|
||||
+{
|
||||
+ pa_alsa_ucm_mapping_context *context = &m->ucm_context;
|
||||
+ pa_alsa_ucm_device *dev;
|
||||
+ uint32_t idx;
|
||||
+ char *mdev;
|
||||
+ snd_pcm_info_t *info;
|
||||
+ int pcm_card, pcm_device;
|
||||
+
|
||||
+ snd_pcm_info_alloca(&info);
|
||||
+ if (snd_pcm_info(pcm, info) < 0)
|
||||
+ return;
|
||||
+
|
||||
+ if ((pcm_card = snd_pcm_info_get_card(info)) < 0)
|
||||
+ return;
|
||||
+ if ((pcm_device = snd_pcm_info_get_device(info)) < 0)
|
||||
+ return;
|
||||
+
|
||||
+ PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) {
|
||||
+ mdev = pa_sprintf_malloc("hw:%i", pcm_card);
|
||||
+ if (mdev == NULL)
|
||||
+ continue;
|
||||
+ dev->eld_mixer_device_name = mdev;
|
||||
+ dev->eld_device = pcm_device;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static snd_pcm_t* mapping_open_pcm(pa_alsa_ucm_config *ucm, pa_alsa_mapping *m, int mode) {
|
||||
snd_pcm_t* pcm;
|
||||
pa_sample_spec try_ss = ucm->core->default_sample_spec;
|
||||
@@ -1730,8 +1790,11 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_ucm_config *ucm, pa_alsa_mapping *m,
|
||||
pcm = pa_alsa_open_by_device_string(m->device_strings[0], NULL, &try_ss,
|
||||
&try_map, mode, &try_period_size, &try_buffer_size, 0, NULL, NULL, exact_channels);
|
||||
|
||||
- if (pcm && !exact_channels)
|
||||
- m->channel_map = try_map;
|
||||
+ if (pcm) {
|
||||
+ if (!exact_channels)
|
||||
+ m->channel_map = try_map;
|
||||
+ mapping_init_eld(m, pcm);
|
||||
+ }
|
||||
|
||||
return pcm;
|
||||
}
|
||||
@@ -1912,6 +1975,8 @@ static void free_verb(pa_alsa_ucm_verb *verb) {
|
||||
if (di->supported_devices)
|
||||
pa_idxset_free(di->supported_devices, NULL);
|
||||
|
||||
+ pa_xfree(di->eld_mixer_device_name);
|
||||
+
|
||||
pa_xfree(di);
|
||||
}
|
||||
|
||||
@@ -2115,6 +2180,7 @@ static void ucm_port_data_init(pa_alsa_ucm_port_data *port, pa_alsa_ucm_config *
|
||||
port->ucm = ucm;
|
||||
port->core_port = core_port;
|
||||
port->devices = pa_dynarray_new(NULL);
|
||||
+ port->eld_device = -1;
|
||||
|
||||
for (i = 0; i < n_devices; i++) {
|
||||
pa_dynarray_append(port->devices, devices[i]);
|
||||
@@ -2139,6 +2205,8 @@ static void ucm_port_data_free(pa_device_port *port) {
|
||||
|
||||
if (ucm_port->paths)
|
||||
pa_hashmap_free(ucm_port->paths);
|
||||
+
|
||||
+ pa_xfree(ucm_port->eld_mixer_device_name);
|
||||
}
|
||||
|
||||
static void ucm_port_update_available(pa_alsa_ucm_port_data *port) {
|
||||
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
|
||||
index 49362992865b..48fd9db3f79f 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.h
|
||||
+++ b/src/modules/alsa/alsa-ucm.h
|
||||
@@ -207,6 +207,9 @@ struct pa_alsa_ucm_device {
|
||||
pa_alsa_jack *jack;
|
||||
pa_dynarray *hw_mute_jacks; /* pa_alsa_jack */
|
||||
pa_available_t available;
|
||||
+
|
||||
+ char *eld_mixer_device_name;
|
||||
+ int eld_device;
|
||||
};
|
||||
|
||||
void pa_alsa_ucm_device_update_available(pa_alsa_ucm_device *device);
|
||||
@@ -273,6 +276,10 @@ struct pa_alsa_ucm_port_data {
|
||||
pa_hashmap *paths;
|
||||
/* Current path, set when activating profile */
|
||||
pa_alsa_path *path;
|
||||
+
|
||||
+ /* ELD info */
|
||||
+ char *eld_mixer_device_name;
|
||||
+ int eld_device; /* PCM device number */
|
||||
};
|
||||
|
||||
struct pa_alsa_ucm_volume {
|
||||
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
|
||||
index 3b2f99fc4e54..c5852b43d844 100644
|
||||
--- a/src/modules/alsa/module-alsa-card.c
|
||||
+++ b/src/modules/alsa/module-alsa-card.c
|
||||
@@ -512,15 +512,24 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static pa_device_port* find_port_with_eld_device(pa_hashmap *ports, int device) {
|
||||
+static pa_device_port* find_port_with_eld_device(struct userdata *u, int device) {
|
||||
void *state;
|
||||
pa_device_port *p;
|
||||
|
||||
- PA_HASHMAP_FOREACH(p, ports, state) {
|
||||
- pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(p);
|
||||
- pa_assert(data->path);
|
||||
- if (device == data->path->eld_device)
|
||||
- return p;
|
||||
+ if (u->use_ucm) {
|
||||
+ PA_HASHMAP_FOREACH(p, u->card->ports, state) {
|
||||
+ pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(p);
|
||||
+ pa_assert(data->eld_mixer_device_name);
|
||||
+ if (device == data->eld_device)
|
||||
+ return p;
|
||||
+ }
|
||||
+ } else {
|
||||
+ PA_HASHMAP_FOREACH(p, u->card->ports, state) {
|
||||
+ pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(p);
|
||||
+ pa_assert(data->path);
|
||||
+ if (device == data->path->eld_device)
|
||||
+ return p;
|
||||
+ }
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -537,10 +546,7 @@ static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) {
|
||||
if (mask == SND_CTL_EVENT_MASK_REMOVE)
|
||||
return 0;
|
||||
|
||||
- if (u->use_ucm)
|
||||
- return 0;
|
||||
-
|
||||
- p = find_port_with_eld_device(u->card->ports, device);
|
||||
+ p = find_port_with_eld_device(u, device);
|
||||
if (p == NULL) {
|
||||
pa_log_error("Invalid device changed in ALSA: %d", device);
|
||||
return 0;
|
||||
@@ -571,21 +577,30 @@ static void init_eld_ctls(struct userdata *u) {
|
||||
/* The code in this function expects ports to have a pa_alsa_port_data
|
||||
* struct as their data, but in UCM mode ports don't have any data. Hence,
|
||||
* the ELD controls can't currently be used in UCM mode. */
|
||||
- if (u->use_ucm)
|
||||
- return;
|
||||
-
|
||||
PA_HASHMAP_FOREACH(port, u->card->ports, state) {
|
||||
- pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(port);
|
||||
snd_mixer_t *mixer_handle;
|
||||
snd_mixer_elem_t* melem;
|
||||
int device;
|
||||
|
||||
- pa_assert(data->path);
|
||||
- device = data->path->eld_device;
|
||||
- if (device < 0)
|
||||
- continue;
|
||||
+ if (u->use_ucm) {
|
||||
+ pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(port);
|
||||
+ device = data->eld_device;
|
||||
+ if (device < 0 || !data->eld_mixer_device_name)
|
||||
+ continue;
|
||||
+
|
||||
+ mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, data->eld_mixer_device_name, true);
|
||||
+ } else {
|
||||
+ pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(port);
|
||||
+
|
||||
+ pa_assert(data->path);
|
||||
+
|
||||
+ device = data->path->eld_device;
|
||||
+ if (device < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, true);
|
||||
+ }
|
||||
|
||||
- mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, true);
|
||||
if (!mixer_handle)
|
||||
continue;
|
||||
|
||||
@@ -595,9 +610,10 @@ static void init_eld_ctls(struct userdata *u) {
|
||||
snd_mixer_elem_set_callback(melem, hdmi_eld_changed);
|
||||
snd_mixer_elem_set_callback_private(melem, u);
|
||||
hdmi_eld_changed(melem, 0);
|
||||
+ pa_log_info("ELD device found for port %s (%d).", port->name, device);
|
||||
}
|
||||
else
|
||||
- pa_log_debug("No ELD device found for port %s.", port->name);
|
||||
+ pa_log_debug("No ELD device found for port %s (%d).", port->name, device);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
@ -0,0 +1,83 @@
|
||||
From 8837c90b7fe6b7c3cbbaeda0a29e2f5d311c3d14 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Sun, 8 Dec 2019 22:48:45 +0100
|
||||
Subject: [PATCH] alsa-mixer: do the quick card number lookup to save mixer
|
||||
instances
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-mixer.h | 1 +
|
||||
src/modules/alsa/alsa-util.c | 33 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 34 insertions(+)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
|
||||
index 325b0c998b02..d740a78c8dce 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.h
|
||||
+++ b/src/modules/alsa/alsa-mixer.h
|
||||
@@ -102,6 +102,7 @@ struct pa_alsa_setting {
|
||||
/* An entry for one ALSA mixer */
|
||||
struct pa_alsa_mixer {
|
||||
snd_mixer_t *mixer_handle;
|
||||
+ int card_index;
|
||||
pa_alsa_fdlist *fdl;
|
||||
bool used_for_probe_only:1;
|
||||
};
|
||||
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
|
||||
index 34930c9fa155..d86f43c10098 100644
|
||||
--- a/src/modules/alsa/alsa-util.c
|
||||
+++ b/src/modules/alsa/alsa-util.c
|
||||
@@ -1737,11 +1737,33 @@ snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, boo
|
||||
int err;
|
||||
snd_mixer_t *m;
|
||||
pa_alsa_mixer *pm;
|
||||
+ char *dev2;
|
||||
+ void *state;
|
||||
|
||||
pa_assert(mixers);
|
||||
pa_assert(dev);
|
||||
|
||||
pm = pa_hashmap_get(mixers, dev);
|
||||
+
|
||||
+ /* The quick card number/index lookup (hw:#)
|
||||
+ * We already know the card number/index, thus use the mixer
|
||||
+ * from the cache at first.
|
||||
+ */
|
||||
+ if (!pm && pa_strneq(dev, "hw:", 3)) {
|
||||
+ const char *s = dev + 3;
|
||||
+ int card_index;
|
||||
+ while (*s && *s >= 0 && *s <= '9') s++;
|
||||
+ if (*s == '\0' && pa_atoi(dev + 3, &card_index) >= 0) {
|
||||
+ PA_HASHMAP_FOREACH_KV(dev2, pm, mixers, state) {
|
||||
+ if (pm->card_index == card_index) {
|
||||
+ dev = dev2;
|
||||
+ pm = pa_hashmap_get(mixers, dev);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (pm) {
|
||||
if (!probe)
|
||||
pm->used_for_probe_only = false;
|
||||
@@ -1756,6 +1778,17 @@ snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, boo
|
||||
if (prepare_mixer(m, dev) >= 0) {
|
||||
pm = pa_xnew0(pa_alsa_mixer, 1);
|
||||
if (pm) {
|
||||
+ snd_hctl_t *hctl;
|
||||
+ pm->card_index = -1;
|
||||
+ /* determine the ALSA card number (index) and store it to card_index */
|
||||
+ err = snd_mixer_get_hctl(m, dev, &hctl);
|
||||
+ if (err >= 0) {
|
||||
+ snd_ctl_card_info_t *info;
|
||||
+ snd_ctl_card_info_alloca(&info);
|
||||
+ err = snd_ctl_card_info(snd_hctl_ctl(hctl), info);
|
||||
+ if (err >= 0)
|
||||
+ pm->card_index = snd_ctl_card_info_get_card(info);
|
||||
+ }
|
||||
pm->used_for_probe_only = probe;
|
||||
pm->mixer_handle = m;
|
||||
pa_hashmap_put(mixers, pa_xstrdup(dev), pm);
|
||||
--
|
||||
2.16.4
|
||||
|
134
0031-alsa-mixer-improve-check-for-the-empty-path-set-for-.patch
Normal file
134
0031-alsa-mixer-improve-check-for-the-empty-path-set-for-.patch
Normal file
@ -0,0 +1,134 @@
|
||||
From d7dbd0cbe3191661c02ac89d108b36c79474de3c Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Sun, 8 Dec 2019 23:17:32 +0100
|
||||
Subject: [PATCH] alsa-mixer: improve check for the empty path set for
|
||||
sink/source
|
||||
|
||||
The unused mixer instances are created without this code.
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-mixer.c | 6 ++++++
|
||||
src/modules/alsa/alsa-mixer.h | 1 +
|
||||
src/modules/alsa/alsa-sink.c | 19 +++++++++++++------
|
||||
src/modules/alsa/alsa-source.c | 9 ++++++---
|
||||
4 files changed, 26 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
|
||||
index a3c998b654e9..d184aec7aee7 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.c
|
||||
+++ b/src/modules/alsa/alsa-mixer.c
|
||||
@@ -741,6 +741,12 @@ void pa_alsa_path_set_free(pa_alsa_path_set *ps) {
|
||||
pa_xfree(ps);
|
||||
}
|
||||
|
||||
+int pa_alsa_path_set_is_empty(pa_alsa_path_set *ps) {
|
||||
+ if (ps && !pa_hashmap_isempty(ps->paths))
|
||||
+ return 0;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static long to_alsa_dB(pa_volume_t v) {
|
||||
return lround(pa_sw_volume_to_dB(v) * 100.0);
|
||||
}
|
||||
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
|
||||
index d740a78c8dce..df739cc2e0f3 100644
|
||||
--- a/src/modules/alsa/alsa-mixer.h
|
||||
+++ b/src/modules/alsa/alsa-mixer.h
|
||||
@@ -272,6 +272,7 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d
|
||||
void pa_alsa_path_set_dump(pa_alsa_path_set *s);
|
||||
void pa_alsa_path_set_set_callback(pa_alsa_path_set *ps, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
|
||||
void pa_alsa_path_set_free(pa_alsa_path_set *s);
|
||||
+int pa_alsa_path_set_is_empty(pa_alsa_path_set *s);
|
||||
|
||||
struct pa_alsa_mapping {
|
||||
pa_alsa_profile_set *profile_set;
|
||||
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
|
||||
index 363b4be2fa25..042d4dfd9c89 100644
|
||||
--- a/src/modules/alsa/alsa-sink.c
|
||||
+++ b/src/modules/alsa/alsa-sink.c
|
||||
@@ -1651,7 +1651,6 @@ static int sink_set_port_ucm_cb(pa_sink *s, pa_device_port *p) {
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(p);
|
||||
- pa_assert(u->mixer_handle);
|
||||
pa_assert(u->ucm_context);
|
||||
|
||||
data = PA_DEVICE_PORT_DATA(p);
|
||||
@@ -2089,6 +2088,9 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
if (!mapping && !element)
|
||||
return;
|
||||
|
||||
+ if (!element && mapping && pa_alsa_path_set_is_empty(mapping->output_path_set))
|
||||
+ return;
|
||||
+
|
||||
u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
|
||||
NULL, (pa_free_cb_t) pa_alsa_mixer_free);
|
||||
|
||||
@@ -2113,8 +2115,9 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
|
||||
pa_log_debug("Probed mixer path %s:", u->mixer_path->name);
|
||||
pa_alsa_path_dump(u->mixer_path);
|
||||
- } else if (!(u->mixer_path_set = mapping->output_path_set))
|
||||
- goto fail;
|
||||
+ } else {
|
||||
+ u->mixer_path_set = mapping->output_path_set;
|
||||
+ }
|
||||
|
||||
return;
|
||||
|
||||
@@ -2559,10 +2562,14 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- if (u->ucm_context)
|
||||
+ if (u->ucm_context) {
|
||||
pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, true, card, u->pcm_handle, ignore_dB);
|
||||
- else if (u->mixer_path_set)
|
||||
- pa_alsa_add_ports(&data, u->mixer_path_set, card);
|
||||
+ find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB);
|
||||
+ } else {
|
||||
+ find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB);
|
||||
+ if (u->mixer_path_set)
|
||||
+ pa_alsa_add_ports(&data, u->mixer_path_set, card);
|
||||
+ }
|
||||
|
||||
u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE | PA_SINK_LATENCY | (u->use_tsched ? PA_SINK_DYNAMIC_LATENCY : 0) |
|
||||
(set_formats ? PA_SINK_SET_FORMATS : 0));
|
||||
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
|
||||
index b46e845cc5a7..104de4e266dd 100644
|
||||
--- a/src/modules/alsa/alsa-source.c
|
||||
+++ b/src/modules/alsa/alsa-source.c
|
||||
@@ -1522,7 +1522,6 @@ static int source_set_port_ucm_cb(pa_source *s, pa_device_port *p) {
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(p);
|
||||
- pa_assert(u->mixer_handle);
|
||||
pa_assert(u->ucm_context);
|
||||
|
||||
data = PA_DEVICE_PORT_DATA(p);
|
||||
@@ -1795,6 +1794,9 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
if (!mapping && !element)
|
||||
return;
|
||||
|
||||
+ if (!element && mapping && pa_alsa_path_set_is_empty(mapping->input_path_set))
|
||||
+ return;
|
||||
+
|
||||
u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
|
||||
NULL, (pa_free_cb_t) pa_alsa_mixer_free);
|
||||
|
||||
@@ -1819,8 +1821,9 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
|
||||
|
||||
pa_log_debug("Probed mixer path %s:", u->mixer_path->name);
|
||||
pa_alsa_path_dump(u->mixer_path);
|
||||
- } else if (!(u->mixer_path_set = mapping->input_path_set))
|
||||
- goto fail;
|
||||
+ } else {
|
||||
+ u->mixer_path_set = mapping->input_path_set;
|
||||
+ }
|
||||
|
||||
return;
|
||||
|
||||
--
|
||||
2.16.4
|
||||
|
128
0032-alsa-ucm-allow-to-set-profile-priority-from-UCM-valu.patch
Normal file
128
0032-alsa-ucm-allow-to-set-profile-priority-from-UCM-valu.patch
Normal file
@ -0,0 +1,128 @@
|
||||
From cd4a69374cefe7c720bd6916f06ff7151da9892a Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Tue, 10 Dec 2019 12:34:19 +0100
|
||||
Subject: [PATCH] alsa-ucm: allow to set profile priority from UCM value
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
src/modules/alsa/alsa-ucm.c | 59 +++++++++++++++++++++++++++++++++------------
|
||||
src/modules/alsa/alsa-ucm.h | 1 +
|
||||
2 files changed, 45 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
|
||||
index 5695840abaf1..a57be6d22497 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.c
|
||||
+++ b/src/modules/alsa/alsa-ucm.c
|
||||
@@ -146,6 +146,26 @@ static struct ucm_info dev_info[] = {
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
+
|
||||
+static char *ucm_verb_value(
|
||||
+ snd_use_case_mgr_t *uc_mgr,
|
||||
+ const char *verb_name,
|
||||
+ const char *id) {
|
||||
+
|
||||
+ const char *value;
|
||||
+ char *_id = pa_sprintf_malloc("=%s//%s", id, verb_name);
|
||||
+ int err = snd_use_case_get(uc_mgr, _id, &value);
|
||||
+ pa_xfree(_id);
|
||||
+ if (err < 0)
|
||||
+ return NULL;
|
||||
+ pa_log_debug("Got %s for verb %s: %s", id, verb_name, value);
|
||||
+ /* Use the cast here to allow free() call without casting for callers.
|
||||
+ * The snd_use_case_get() returns mallocated string.
|
||||
+ * See the Note: in use-case.h for snd_use_case_get().
|
||||
+ */
|
||||
+ return (char *)value;
|
||||
+}
|
||||
+
|
||||
static int ucm_device_exists(pa_idxset *idxset, pa_alsa_ucm_device *dev) {
|
||||
pa_alsa_ucm_device *d;
|
||||
uint32_t idx;
|
||||
@@ -766,6 +786,8 @@ int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, cons
|
||||
pa_alsa_ucm_device *d;
|
||||
pa_alsa_ucm_modifier *mod;
|
||||
pa_alsa_ucm_verb *verb;
|
||||
+ char *value;
|
||||
+ unsigned ui;
|
||||
int err = 0;
|
||||
|
||||
*p_verb = NULL;
|
||||
@@ -780,6 +802,11 @@ int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, cons
|
||||
pa_proplist_sets(verb->proplist, PA_ALSA_PROP_UCM_NAME, pa_strnull(verb_name));
|
||||
pa_proplist_sets(verb->proplist, PA_ALSA_PROP_UCM_DESCRIPTION, pa_strna(verb_desc));
|
||||
|
||||
+ value = ucm_verb_value(uc_mgr, verb_name, "Priority");
|
||||
+ if (value && !pa_atou(value, &ui))
|
||||
+ verb->priority = ui > 10000 ? 10000 : ui;
|
||||
+ free(value);
|
||||
+
|
||||
err = ucm_get_devices(verb, uc_mgr);
|
||||
if (err < 0)
|
||||
pa_log("No UCM devices for verb %s", verb_name);
|
||||
@@ -1637,7 +1664,7 @@ static int ucm_create_profile(
|
||||
pa_alsa_ucm_modifier *mod;
|
||||
int i = 0;
|
||||
const char *name, *sink, *source;
|
||||
- char *verb_cmp, *c;
|
||||
+ unsigned int priority;
|
||||
|
||||
pa_assert(ps);
|
||||
|
||||
@@ -1657,24 +1684,26 @@ static int ucm_create_profile(
|
||||
p->supported = true;
|
||||
pa_hashmap_put(ps->profiles, p->name, p);
|
||||
|
||||
- /* TODO: get profile priority from ucm info or policy management */
|
||||
- c = verb_cmp = pa_xstrdup(verb_name);
|
||||
- while (*c) {
|
||||
- if (*c == '_') *c = ' ';
|
||||
- c++;
|
||||
- }
|
||||
+ /* TODO: get profile priority from policy management */
|
||||
+ priority = verb->priority;
|
||||
|
||||
- for (i = 0; verb_info[i].id; i++) {
|
||||
- if (strcasecmp(verb_info[i].id, verb_cmp) == 0) {
|
||||
- p->priority = verb_info[i].priority;
|
||||
- break;
|
||||
+ if (priority == 0) {
|
||||
+ char *verb_cmp, *c;
|
||||
+ c = verb_cmp = pa_xstrdup(verb_name);
|
||||
+ while (*c) {
|
||||
+ if (*c == '_') *c = ' ';
|
||||
+ c++;
|
||||
+ }
|
||||
+ for (i = 0; verb_info[i].id; i++) {
|
||||
+ if (strcasecmp(verb_info[i].id, verb_cmp) == 0) {
|
||||
+ priority = verb_info[i].priority;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
+ pa_xfree(verb_cmp);
|
||||
}
|
||||
|
||||
- pa_xfree(verb_cmp);
|
||||
-
|
||||
- if (verb_info[i].id == NULL)
|
||||
- p->priority = 1000;
|
||||
+ p->priority = priority;
|
||||
|
||||
PA_LLIST_FOREACH(dev, verb->devices) {
|
||||
pa_alsa_jack *jack;
|
||||
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
|
||||
index 48fd9db3f79f..e7a795cedeb7 100644
|
||||
--- a/src/modules/alsa/alsa-ucm.h
|
||||
+++ b/src/modules/alsa/alsa-ucm.h
|
||||
@@ -241,6 +241,7 @@ struct pa_alsa_ucm_verb {
|
||||
PA_LLIST_FIELDS(pa_alsa_ucm_verb);
|
||||
|
||||
pa_proplist *proplist;
|
||||
+ unsigned priority;
|
||||
|
||||
PA_LLIST_HEAD(pa_alsa_ucm_device, devices);
|
||||
PA_LLIST_HEAD(pa_alsa_ucm_modifier, modifiers);
|
||||
--
|
||||
2.16.4
|
||||
|
@ -1,3 +1,41 @@
|
||||
-------------------------------------------------------------------
|
||||
Wed Feb 12 22:01:05 CET 2020 - tiwai@suse.de
|
||||
|
||||
- Backport upstream fixes / enhancements about alsa modules:
|
||||
mainly for UCM support (boo#1160914):
|
||||
0001-alsa-mixer-path-test-Hide-unused-functions-when-buil.patch
|
||||
0002-alsa-mixer-recognize-the-Speaker-Jack-control.patch
|
||||
0003-alsa-mixer-add-support-for-SteelSeries-Arctis-Pro-20.patch
|
||||
0004-alsa-mixer-Add-support-for-SteelSeries-Arctis-5-2019.patch
|
||||
0005-alsa-mixer-add-support-for-LucidSound-LS31-and-creat.patch
|
||||
0006-alsa-ucm-use-ucm2-name-for-the-direct-card-index-ope.patch
|
||||
0007-alsa-ucm-add-mixer-IDs-to-ucm_items.patch
|
||||
0008-alsa-mixer-handle-the-index-for-ALSA-mixer-element-i.patch
|
||||
0009-alsa-mixer-improve-alsa_id_decode-function.patch
|
||||
0010-alsa-ucm-Support-Playback-CaptureVolume.patch
|
||||
0011-alsa-ucm-Fix-volume-control-based-on-review.patch
|
||||
0012-alsa-ucm-use-the-correct-mixer-identifiers-as-first.patch
|
||||
0013-alsa-ucm-add-support-for-master-volume.patch
|
||||
0014-alsa-ucm-split-correctly-JackHWMute-device-names.patch
|
||||
0015-alsa-ucm-fix-parsing-for-JackControl.patch
|
||||
0016-alsa-ucm-add-comments-to-ucm_get_mixer_id.patch
|
||||
0017-alsa-ucm-validate-access-to-PA_DEVICE_PORT_DATA.patch
|
||||
0018-alsa-Skip-resume-PCM-if-hardware-doesn-t-support-it.patch
|
||||
0019-alsa-ucm-parse-correctly-the-device-values.patch
|
||||
0020-alsa-ucm-do-not-try-to-use-UCM-device-name-as-jack-n.patch
|
||||
0021-alsa-util-do-not-try-to-guess-the-mixer-name-from-th.patch
|
||||
0022-alsa-ucm-add-control-and-mixer-device-items.patch
|
||||
0023-alsa-ucm-get-the-mixer-names-from-ucm-don-t-guess.patch
|
||||
0024-alsa-ucm-use-the-proper-mixer-name-for-ucm-pcm-sink-.patch
|
||||
0025-alsa-mixer-handle-interface-type-CARD-PCM-for-mixer-.patch
|
||||
0026-alsa-mixer-Add-the-ability-to-pass-the-intended-role.patch
|
||||
0027-alsa-mixer-Set-the-intended-role-of-Steelseries-Arct.patch
|
||||
0028-alsa-rewrite-mixer-open-close-cache-mixer-accesses-i.patch
|
||||
0029-alsa-ucm-add-support-for-HDMI-ELD.patch
|
||||
0030-alsa-mixer-do-the-quick-card-number-lookup-to-save-m.patch
|
||||
0031-alsa-mixer-improve-check-for-the-empty-path-set-for-.patch
|
||||
0032-alsa-ucm-allow-to-set-profile-priority-from-UCM-valu.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Feb 3 07:36:31 UTC 2020 - Bjørn Lie <bjorn.lie@gmail.com>
|
||||
|
||||
|
@ -50,6 +50,39 @@ Patch2: pulseaudio-wrong-memset.patch
|
||||
Patch5: qpaeq-shebang.patch
|
||||
# PATCH-FIX-OPENSUSE Workaround for old systemd on Leap 15.x
|
||||
Patch6: pulseaudio-old-systemd-workaround.patch
|
||||
# PATCH-FIX-UPSTREAM
|
||||
Patch1001: 0001-alsa-mixer-path-test-Hide-unused-functions-when-buil.patch
|
||||
Patch1002: 0002-alsa-mixer-recognize-the-Speaker-Jack-control.patch
|
||||
Patch1003: 0003-alsa-mixer-add-support-for-SteelSeries-Arctis-Pro-20.patch
|
||||
Patch1004: 0004-alsa-mixer-Add-support-for-SteelSeries-Arctis-5-2019.patch
|
||||
Patch1005: 0005-alsa-mixer-add-support-for-LucidSound-LS31-and-creat.patch
|
||||
Patch1006: 0006-alsa-ucm-use-ucm2-name-for-the-direct-card-index-ope.patch
|
||||
Patch1007: 0007-alsa-ucm-add-mixer-IDs-to-ucm_items.patch
|
||||
Patch1008: 0008-alsa-mixer-handle-the-index-for-ALSA-mixer-element-i.patch
|
||||
Patch1009: 0009-alsa-mixer-improve-alsa_id_decode-function.patch
|
||||
Patch1010: 0010-alsa-ucm-Support-Playback-CaptureVolume.patch
|
||||
Patch1011: 0011-alsa-ucm-Fix-volume-control-based-on-review.patch
|
||||
Patch1012: 0012-alsa-ucm-use-the-correct-mixer-identifiers-as-first.patch
|
||||
Patch1013: 0013-alsa-ucm-add-support-for-master-volume.patch
|
||||
Patch1014: 0014-alsa-ucm-split-correctly-JackHWMute-device-names.patch
|
||||
Patch1015: 0015-alsa-ucm-fix-parsing-for-JackControl.patch
|
||||
Patch1016: 0016-alsa-ucm-add-comments-to-ucm_get_mixer_id.patch
|
||||
Patch1017: 0017-alsa-ucm-validate-access-to-PA_DEVICE_PORT_DATA.patch
|
||||
Patch1018: 0018-alsa-Skip-resume-PCM-if-hardware-doesn-t-support-it.patch
|
||||
Patch1019: 0019-alsa-ucm-parse-correctly-the-device-values.patch
|
||||
Patch1020: 0020-alsa-ucm-do-not-try-to-use-UCM-device-name-as-jack-n.patch
|
||||
Patch1021: 0021-alsa-util-do-not-try-to-guess-the-mixer-name-from-th.patch
|
||||
Patch1022: 0022-alsa-ucm-add-control-and-mixer-device-items.patch
|
||||
Patch1023: 0023-alsa-ucm-get-the-mixer-names-from-ucm-don-t-guess.patch
|
||||
Patch1024: 0024-alsa-ucm-use-the-proper-mixer-name-for-ucm-pcm-sink-.patch
|
||||
Patch1025: 0025-alsa-mixer-handle-interface-type-CARD-PCM-for-mixer-.patch
|
||||
Patch1026: 0026-alsa-mixer-Add-the-ability-to-pass-the-intended-role.patch
|
||||
Patch1027: 0027-alsa-mixer-Set-the-intended-role-of-Steelseries-Arct.patch
|
||||
Patch1028: 0028-alsa-rewrite-mixer-open-close-cache-mixer-accesses-i.patch
|
||||
Patch1029: 0029-alsa-ucm-add-support-for-HDMI-ELD.patch
|
||||
Patch1030: 0030-alsa-mixer-do-the-quick-card-number-lookup-to-save-m.patch
|
||||
Patch1031: 0031-alsa-mixer-improve-check-for-the-empty-path-set-for-.patch
|
||||
Patch1032: 0032-alsa-ucm-allow-to-set-profile-priority-from-UCM-valu.patch
|
||||
BuildRequires: alsa-devel >= 1.0.19
|
||||
BuildRequires: bluez-devel >= 5
|
||||
BuildRequires: doxygen
|
||||
@ -338,6 +371,38 @@ Optional dependency offering zsh completion for various PulseAudio utilities
|
||||
%prep
|
||||
%setup -q -T -b0
|
||||
%patch0
|
||||
%patch1001 -p1
|
||||
%patch1002 -p1
|
||||
%patch1003 -p1
|
||||
%patch1004 -p1
|
||||
%patch1005 -p1
|
||||
%patch1006 -p1
|
||||
%patch1007 -p1
|
||||
%patch1008 -p1
|
||||
%patch1009 -p1
|
||||
%patch1010 -p1
|
||||
%patch1011 -p1
|
||||
%patch1012 -p1
|
||||
%patch1013 -p1
|
||||
%patch1014 -p1
|
||||
%patch1015 -p1
|
||||
%patch1016 -p1
|
||||
%patch1017 -p1
|
||||
%patch1018 -p1
|
||||
%patch1019 -p1
|
||||
%patch1020 -p1
|
||||
%patch1021 -p1
|
||||
%patch1022 -p1
|
||||
%patch1023 -p1
|
||||
%patch1024 -p1
|
||||
%patch1025 -p1
|
||||
%patch1026 -p1
|
||||
%patch1027 -p1
|
||||
%patch1028 -p1
|
||||
%patch1029 -p1
|
||||
%patch1030 -p1
|
||||
%patch1031 -p1
|
||||
%patch1032 -p1
|
||||
%patch1 -p1
|
||||
%patch2
|
||||
%patch5
|
||||
|
Loading…
Reference in New Issue
Block a user