nixpkgs-suyu/pkgs/os-specific/linux/alsa-project/alsa-lib/alsa-plugin-conf-multilib.patch
ivanbrennan 3b139b96c5
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:
ab8ef63ff4

The pulseaudio module then used the "libs" to declare locations for both native
and 32bit plugins:
0c8ad65560

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

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.
2022-01-31 20:12:59 -05:00

232 lines
6.2 KiB
Diff

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