Hello community, here is the log from the commit of package pulseaudio for openSUSE:Factory checked in at 2020-02-21 16:40:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pulseaudio (Old) and /work/SRC/openSUSE:Factory/.pulseaudio.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pulseaudio" Fri Feb 21 16:40:33 2020 rev:167 rq:774846 version:13.0 Changes: -------- --- /work/SRC/openSUSE:Factory/pulseaudio/pulseaudio.changes 2020-02-09 21:01:46.903331907 +0100 +++ /work/SRC/openSUSE:Factory/.pulseaudio.new.26092/pulseaudio.changes 2020-02-21 16:41:18.261906731 +0100 @@ -1,0 +2,38 @@ +Wed Feb 12 22:01:05 CET 2020 - [email protected] + +- 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 + +------------------------------------------------------------------- New: ---- 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 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pulseaudio.spec ++++++ --- /var/tmp/diff_new_pack.vpuNfm/_old 2020-02-21 16:41:19.073908353 +0100 +++ /var/tmp/diff_new_pack.vpuNfm/_new 2020-02-21 16:41:19.081908369 +0100 @@ -50,6 +50,39 @@ 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 @@ %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 ++++++ 0001-alsa-mixer-path-test-Hide-unused-functions-when-buil.patch ++++++ >From 3dff31e19ca627fc4e0a8f13aeb44923118ecfa1 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen <[email protected]> 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 ++++++ 0002-alsa-mixer-recognize-the-Speaker-Jack-control.patch ++++++ >From 248a77c7fd2f9682c58d3d3dd6f3c2ba3ad2c111 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen <[email protected]> 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 ++++++ 0003-alsa-mixer-add-support-for-SteelSeries-Arctis-Pro-20.patch ++++++ >From 7259e8c22fb97b1ae80ac4909713e51b293afc4a Mon Sep 17 00:00:00 2001 From: Josh <[email protected]> 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 <[email protected]> --- 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 ++++++ 0004-alsa-mixer-Add-support-for-SteelSeries-Arctis-5-2019.patch ++++++ >From 79d3b99ba4773651c4ebc082233f9d0b5f68bfad Mon Sep 17 00:00:00 2001 From: Krzysztof Stasiowski <[email protected]> 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 <[email protected]> --- 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 ++++++ 0005-alsa-mixer-add-support-for-LucidSound-LS31-and-creat.patch ++++++ >From 1ee1f749e154d2f64b4661f833eebaa18ae1a081 Mon Sep 17 00:00:00 2001 From: Dave Chiluk <[email protected]> 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 ++++++ 0006-alsa-ucm-use-ucm2-name-for-the-direct-card-index-ope.patch ++++++ >From c8f065250dde966825f171ff817f7301f423a42e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0007-alsa-ucm-add-mixer-IDs-to-ucm_items.patch ++++++ >From ab5be56a10a83bfdfd7f40c02245db039e6eb730 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> Date: Sat, 23 Nov 2019 15:50:29 +0100 Subject: [PATCH] alsa-ucm: add mixer IDs to ucm_items Signed-off-by: Jaroslav Kysela <[email protected]> --- 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 ++++++ 0008-alsa-mixer-handle-the-index-for-ALSA-mixer-element-i.patch ++++++ ++++ 820 lines (skipped) ++++++ 0009-alsa-mixer-improve-alsa_id_decode-function.patch ++++++ >From 1c240b7a12e9e2f7c2266d18cbb74130bb81277e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0010-alsa-ucm-Support-Playback-CaptureVolume.patch ++++++ ++++ 795 lines (skipped) ++++++ 0011-alsa-ucm-Fix-volume-control-based-on-review.patch ++++++ >From 9acacd9ba3b9f4df0957e9ddaacbcee00396175c Mon Sep 17 00:00:00 2001 From: Jaska Uimonen <[email protected]> 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 ++++++ 0012-alsa-ucm-use-the-correct-mixer-identifiers-as-first.patch ++++++ >From dc9dc70fcc1b06788d08b5e7997c9053a13cbce2 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0013-alsa-ucm-add-support-for-master-volume.patch ++++++ >From 6d830bf0f08c7f92418c2d8b0e73c0415dca03c8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> Date: Wed, 27 Nov 2019 11:34:49 +0100 Subject: [PATCH] alsa-ucm: add support for master volume Signed-off-by: Jaroslav Kysela <[email protected]> --- 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 ++++++ 0014-alsa-ucm-split-correctly-JackHWMute-device-names.patch ++++++ >From 156bd7742490d68701688572ec06f2c608f33db6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> Date: Tue, 3 Dec 2019 14:52:08 +0100 Subject: [PATCH] alsa-ucm: split correctly JackHWMute device names Signed-off-by: Jaroslav Kysela <[email protected]> --- 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 ++++++ 0015-alsa-ucm-fix-parsing-for-JackControl.patch ++++++ >From e04f14ebf3a0898dd2f665434524cc34cb267ddd Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> Date: Tue, 3 Dec 2019 15:13:48 +0100 Subject: [PATCH] alsa-ucm: fix parsing for JackControl Signed-off-by: Jaroslav Kysela <[email protected]> --- 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 ++++++ 0016-alsa-ucm-add-comments-to-ucm_get_mixer_id.patch ++++++ >From f5c02dfcd821ab77fc7f91da985254a7bdb658ad Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0017-alsa-ucm-validate-access-to-PA_DEVICE_PORT_DATA.patch ++++++ >From e6779ad229d5858f90f5f10c3796c9778f05c3fa Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0018-alsa-Skip-resume-PCM-if-hardware-doesn-t-support-it.patch ++++++ >From 734a00c849815a45697970d593068c301a04ebbb Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng <[email protected]> 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 ++++++ 0019-alsa-ucm-parse-correctly-the-device-values.patch ++++++ >From 4c64f73c97c7f77426ee838f47fc7bad6a4563b6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0020-alsa-ucm-do-not-try-to-use-UCM-device-name-as-jack-n.patch ++++++ >From ef1df946274a0499e1fa631a8b6680c23c4eb723 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0021-alsa-util-do-not-try-to-guess-the-mixer-name-from-th.patch ++++++ >From d8200ee805ed6b508a8174031080b1d98a7c27b3 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0022-alsa-ucm-add-control-and-mixer-device-items.patch ++++++ >From ddd0fdb9970b920ef95e33cfe50a1e492be9d60b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> Date: Fri, 6 Dec 2019 20:33:45 +0100 Subject: [PATCH] alsa-ucm: add control and mixer device items Signed-off-by: Jaroslav Kysela <[email protected]> --- 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 ++++++ 0023-alsa-ucm-get-the-mixer-names-from-ucm-don-t-guess.patch ++++++ >From e438382a51f7e0d04fb9439da2f45c183e958e0f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0024-alsa-ucm-use-the-proper-mixer-name-for-ucm-pcm-sink-.patch ++++++ >From dacfcbb09c9d91ca20dedfa449da37f0f7e3953f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0025-alsa-mixer-handle-interface-type-CARD-PCM-for-mixer-.patch ++++++ >From f18b0c3402f5e1f7db9d0a42c6e10cfe1f212da3 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0026-alsa-mixer-Add-the-ability-to-pass-the-intended-role.patch ++++++ >From c6a0665618975eedc98bdf23e4140935a1af38c2 Mon Sep 17 00:00:00 2001 From: Laurent Bigonville <[email protected]> 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 ++++++ 0027-alsa-mixer-Set-the-intended-role-of-Steelseries-Arct.patch ++++++ >From 6438e5c46dc449e4726ec9312859cc70388d2851 Mon Sep 17 00:00:00 2001 From: Laurent Bigonville <[email protected]> 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 ++++++ 0028-alsa-rewrite-mixer-open-close-cache-mixer-accesses-i.patch ++++++ ++++ 761 lines (skipped) ++++++ 0029-alsa-ucm-add-support-for-HDMI-ELD.patch ++++++ >From 3ceff8bb3f697ec16dc5c72e658b10ac40bc19f5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> Date: Sat, 7 Dec 2019 23:22:33 +0100 Subject: [PATCH] alsa-ucm: add support for HDMI ELD Signed-off-by: Jaroslav Kysela <[email protected]> --- 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 ++++++ 0030-alsa-mixer-do-the-quick-card-number-lookup-to-save-m.patch ++++++ >From 8837c90b7fe6b7c3cbbaeda0a29e2f5d311c3d14 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0031-alsa-mixer-improve-check-for-the-empty-path-set-for-.patch ++++++ >From d7dbd0cbe3191661c02ac89d108b36c79474de3c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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 ++++++ 0032-alsa-ucm-allow-to-set-profile-priority-from-UCM-valu.patch ++++++ >From cd4a69374cefe7c720bd6916f06ff7151da9892a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela <[email protected]> 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 <[email protected]> --- 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
