From 3b139b96c54e56f9ac7b3b49fc650867391bb665 Mon Sep 17 00:00:00 2001 From: ivanbrennan Date: Sat, 29 Jan 2022 12:51:54 -0500 Subject: [PATCH 1/2] alsa-lib: re-add alsa-plugin-conf-multilib.patch This patch was originally added in 2014 to support running apps with 32bit sound on 64bit architecture. The patch itself add a "libs" field to syntax recognized in /etc/asound.conf: ab8ef63ff49dd6276f765cce10d88b3e5b86b837 The pulseaudio module then used the "libs" to declare locations for both native and 32bit plugins: 0c8ad65560fa1df07ea7b7937e02b44b1ce2b498 In a recent alsa-lib upgrade (1.2.5.1 -> 1.2.6.1), the patch was removed without understanding its purpose, leaving alsa-lib unable to parse the etc/asound.conf that the pulseaudio module generated: aeea1bb53b28fc7bbe4583bd21f5bda8b05d5041 As a result, ALSA utils are failing on x86_64 architecture if pulseaudio is enabled. E.g. $ alsactl monitor default alsa-lib control.c:1464:(snd_ctl_open_conf) Unknown field libs Cannot open ctl default $ alsamixer ALSA lib control.c:1464:(snd_ctl_open_conf) Unknown field libs cannot open mixer: Invalid argument $ speaker-test -t wav -c 2 speaker-test 1.2.6 Playback device is default Stream parameters are 48000Hz, S16_LE, 2 channels WAV file(s) ALSA lib pcm.c:2576:(snd_pcm_open_conf) Unknown field libs Playback open error: -22,Invalid argument Put the patch back in place to fix what was broken. --- .../alsa-lib/alsa-plugin-conf-multilib.patch | 232 ++++++++++++++++++ .../linux/alsa-project/alsa-lib/default.nix | 4 + 2 files changed, 236 insertions(+) create mode 100644 pkgs/os-specific/linux/alsa-project/alsa-lib/alsa-plugin-conf-multilib.patch diff --git a/pkgs/os-specific/linux/alsa-project/alsa-lib/alsa-plugin-conf-multilib.patch b/pkgs/os-specific/linux/alsa-project/alsa-lib/alsa-plugin-conf-multilib.patch new file mode 100644 index 000000000000..b17df9a492e5 --- /dev/null +++ b/pkgs/os-specific/linux/alsa-project/alsa-lib/alsa-plugin-conf-multilib.patch @@ -0,0 +1,232 @@ +diff --git a/src/control/control.c b/src/control/control.c +index d66ed75..42cecad 100644 +--- a/src/control/control.c ++++ b/src/control/control.c +@@ -838,6 +838,10 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, + #ifndef PIC + extern void *snd_control_open_symbols(void); + #endif ++ ++ snd_config_t *libs = NULL; ++ const char *libs_lib = NULL; ++ + if (snd_config_get_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND) { + if (name) + SNDERR("Invalid type for CTL %s definition", name); +@@ -879,6 +883,19 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, + SNDERR("Invalid type for %s", id); + goto _err; + } ++ ++ continue; ++ } ++ // Handle an array of extra libs. ++ if (strcmp(id, "libs") == 0) { ++ if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { ++ SNDERR("Invalid type for libs definition in CTL %s definition", ++ str); ++ goto _err; ++ } ++ ++ libs = n; ++ + continue; + } + if (strcmp(id, "open") == 0) { +@@ -903,7 +920,62 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, + open_name = buf; + sprintf(buf, "_snd_ctl_%s_open", str); + } +- if (!lib) { ++ ++#ifndef PIC ++ snd_control_open_symbols(); ++#endif ++ ++ // Normal alsa behaviour when there is no libs array. ++ if (!libs) { ++ if (lib) { ++ open_func = snd_dlobj_cache_get(lib, open_name, ++ SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION), 1); ++ } ++ } ++ // Handle libs array. ++ // Suppresses error messages if any function is loaded successfully. ++ else { ++ if (lib) { ++ open_func = snd_dlobj_cache_get(lib, open_name, ++ SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION), 0); ++ } ++ ++ if (!open_func) { ++ snd_config_for_each(i, next, libs) { ++ snd_config_t *n = snd_config_iterator_entry(i); ++ ++ err = snd_config_get_string(n, &libs_lib); ++ if (err < 0) { ++ SNDERR("Invalid entry in CTL %s libs definition", str); ++ goto _err; ++ } ++ ++ if (!open_func) { ++ open_func = snd_dlobj_cache_get(libs_lib, open_name, ++ SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION), 0); ++ } ++ } ++ } ++ ++ // Print error messages. ++ if (!open_func) { ++ if (lib) { ++ SNDERR("Either %s cannot be opened or %s was not defined inside", ++ lib, open_name); ++ } ++ ++ snd_config_for_each(i, next, libs) { ++ snd_config_t *n = snd_config_iterator_entry(i); ++ ++ snd_config_get_string(n, &libs_lib); ++ SNDERR("Either %s cannot be opened or %s was not defined inside", ++ libs_lib, open_name); ++ } ++ } ++ } ++ ++ // Look in ALSA_PLUGIN_DIR iff we found nowhere else to look. ++ if (!lib && (!libs || !libs_lib)) { + const char *const *build_in = build_in_ctls; + while (*build_in) { + if (!strcmp(*build_in, str)) +@@ -919,12 +991,11 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, + lib = buf1; + sprintf(buf1, "%s/libasound_module_ctl_%s.so", ALSA_PLUGIN_DIR, str); + } +- } +-#ifndef PIC +- snd_control_open_symbols(); +-#endif +- open_func = snd_dlobj_cache_get(lib, open_name, ++ ++ open_func = snd_dlobj_cache_get(lib, open_name, + SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION), 1); ++ } ++ + if (open_func) { + err = open_func(ctlp, name, ctl_root, ctl_conf, mode); + if (err >= 0) { +diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c +index 2e24338..7f489f4 100644 +--- a/src/pcm/pcm.c ++++ b/src/pcm/pcm.c +@@ -2116,6 +2116,10 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, + #ifndef PIC + extern void *snd_pcm_open_symbols(void); + #endif ++ ++ snd_config_t *libs = NULL; ++ const char *libs_lib = NULL; ++ + if (snd_config_get_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND) { + char *val; + id = NULL; +@@ -2160,6 +2164,19 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, + SNDERR("Invalid type for %s", id); + goto _err; + } ++ ++ continue; ++ } ++ // Handle an array of extra libs. ++ if (strcmp(id, "libs") == 0) { ++ if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { ++ SNDERR("Invalid type for libs definition in PCM %s definition", ++ str); ++ goto _err; ++ } ++ ++ libs = n; ++ + continue; + } + if (strcmp(id, "open") == 0) { +@@ -2184,7 +2201,62 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, + open_name = buf; + sprintf(buf, "_snd_pcm_%s_open", str); + } +- if (!lib) { ++ ++#ifndef PIC ++ snd_pcm_open_symbols(); /* this call is for static linking only */ ++#endif ++ ++ // Normal alsa behaviour when there is no libs array. ++ if (!libs) { ++ if (lib) { ++ open_func = snd_dlobj_cache_get(lib, open_name, ++ SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION), 1); ++ } ++ } ++ // Handle libs array. ++ // Suppresses error messages if any function is loaded successfully. ++ else { ++ if (lib) { ++ open_func = snd_dlobj_cache_get(lib, open_name, ++ SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION), 0); ++ } ++ ++ if (!open_func) { ++ snd_config_for_each(i, next, libs) { ++ snd_config_t *n = snd_config_iterator_entry(i); ++ ++ err = snd_config_get_string(n, &libs_lib); ++ if (err < 0) { ++ SNDERR("Invalid entry in PCM %s libs definition", str); ++ goto _err; ++ } ++ ++ if (!open_func) { ++ open_func = snd_dlobj_cache_get(libs_lib, open_name, ++ SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION), 0); ++ } ++ } ++ } ++ ++ // Print error messages. ++ if (!open_func) { ++ if (lib) { ++ SNDERR("Either %s cannot be opened or %s was not defined inside", ++ lib, open_name); ++ } ++ ++ snd_config_for_each(i, next, libs) { ++ snd_config_t *n = snd_config_iterator_entry(i); ++ ++ snd_config_get_string(n, &libs_lib); ++ SNDERR("Either %s cannot be opened or %s was not defined inside", ++ libs_lib, open_name); ++ } ++ } ++ } ++ ++ // Look in ALSA_PLUGIN_DIR iff we found nowhere else to look. ++ if (!lib && (!libs || !libs_lib)) { + const char *const *build_in = build_in_pcms; + while (*build_in) { + if (!strcmp(*build_in, str)) +@@ -2200,12 +2272,11 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, + lib = buf1; + sprintf(buf1, "%s/libasound_module_pcm_%s.so", ALSA_PLUGIN_DIR, str); + } +- } +-#ifndef PIC +- snd_pcm_open_symbols(); /* this call is for static linking only */ +-#endif +- open_func = snd_dlobj_cache_get(lib, open_name, ++ ++ open_func = snd_dlobj_cache_get(lib, open_name, + SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION), 1); ++ } ++ + if (open_func) { + err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode); + if (err >= 0) { diff --git a/pkgs/os-specific/linux/alsa-project/alsa-lib/default.nix b/pkgs/os-specific/linux/alsa-project/alsa-lib/default.nix index 445d171d31fd..f2cc2b48a7eb 100644 --- a/pkgs/os-specific/linux/alsa-project/alsa-lib/default.nix +++ b/pkgs/os-specific/linux/alsa-project/alsa-lib/default.nix @@ -14,6 +14,10 @@ stdenv.mkDerivation rec { hash = "sha256-rVgpk9Us21+xWaC+q2CmrFfqsMwb34XcTbbWGX8CMz8="; }; + patches = [ + ./alsa-plugin-conf-multilib.patch + ]; + enableParallelBuilding = true; postInstall = '' From dd35016349992f73947b2c7f4c0e7597d6337425 Mon Sep 17 00:00:00 2001 From: ivanbrennan Date: Tue, 1 Feb 2022 08:44:15 -0500 Subject: [PATCH 2/2] alsa-lib: document alsa-plugin-conf-multilib.patch --- pkgs/os-specific/linux/alsa-project/alsa-lib/default.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/os-specific/linux/alsa-project/alsa-lib/default.nix b/pkgs/os-specific/linux/alsa-project/alsa-lib/default.nix index f2cc2b48a7eb..58e5990ae0a6 100644 --- a/pkgs/os-specific/linux/alsa-project/alsa-lib/default.nix +++ b/pkgs/os-specific/linux/alsa-project/alsa-lib/default.nix @@ -15,6 +15,10 @@ stdenv.mkDerivation rec { }; patches = [ + # Add a "libs" field to the syntax recognized in the /etc/asound.conf file. + # The nixos modules for pulseaudio, jack, and pipewire are leveraging this + # "libs" field to declare locations for both native and 32bit plugins, in + # order to support apps with 32bit sound running on x86_64 architecture. ./alsa-plugin-conf-multilib.patch ];