An update on this:

To begin, I installed alsa-plugins and alsa-plugins:pulseaudio and
configured the build of alsa-lib like this:

"--with-plugindir=/var/guix/profiles/per-user/leo/guix-profile/lib/alsa-lib"

Everything worked that way, but obviously it's not a solution.

Now, I am working on making alsa-lib respect ALSA_PLUGIN_DIRS, which
would be a search path specified by packages that provide ALSA plugins,
such as alsa-plugins. However, so far my attempt fails in another part
of alsa-lib, like this:

------
$ mpg123 -o alsa ~/file.mp3
ALSA lib dlmisc.c:204:(snd_dlsym_verify) unable to verify version for symbol 
conf_pulse_hook_load_if_running
ALSA lib conf.c:3686:(snd_config_hooks_call) symbol 
conf_pulse_hook_load_if_running is not defined inside 
libasound_module_conf_pulse.so
ALSA lib pcm.c:2685:(snd_pcm_open_noupdate) Unknown PCM default
[src/libout123/modules/alsa.c:181] error: cannot open device default
[src/libout123/libout123.c:455] error: Found no driver out of [alsa] working 
with device <default>.
main: [src/mpg123.c:314] error: out123 error 3: failure loading driver module
------

I don't know why snd_dlsym_verify fails with my patch but succeeds when
using '--with-plugindir'.

My current patch is attached...
From 2dc0cf223a71d2a22ca19eff6c59d55d72028c64 Mon Sep 17 00:00:00 2001
From: Leo Famulari <[email protected]>
Date: Sun, 26 Apr 2020 20:13:01 -0400
Subject: [PATCH 1/3] gnu: alsa-plugins: Add ALSA_PLUGIN_DIRS search path
 specification.

* gnu/packages/linux.scm (alsa-plugins)[native-search-paths]: New field.
---
 gnu/packages/linux.scm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 40323a85d6..b451f591ea 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -1858,6 +1858,10 @@ MIDI functionality to the Linux-based operating system.")
               (base32
                "0z9k3ssbfk2ky2w13avgyf202j1drsz9sv3834bp33cj1i2hc3qw"))))
     (build-system gnu-build-system)
+    (native-search-paths
+      (list (search-path-specification
+              (variable "ALSA_PLUGIN_DIRS")
+              (files '("lib/alsa-lib")))))
     ;; TODO: Split libavcodec and speex if possible. It looks like they can not
     ;; be split, there are references to both in files.
     ;; TODO: Remove OSS related plugins, they add support to run native
-- 
2.26.2


From a9ce47575add9eeb015eb6c605bde01948c5e341 Mon Sep 17 00:00:00 2001
From: Leo Famulari <[email protected]>
Date: Mon, 27 Apr 2020 01:05:41 -0400
Subject: [PATCH 2/3] gnu: Add the old Nix alsa-lib patch with a graft.

* gnu/packages/linux.scm (alsa-lib)[replacement]: New field.
(alsa-lib/fixed): New variable.
* gnu/packages/patches/alsa-lib.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
---
 gnu/local.mk                        |   1 +
 gnu/packages/linux.scm              |  10 +++
 gnu/packages/patches/alsa-lib.patch | 110 ++++++++++++++++++++++++++++
 3 files changed, 121 insertions(+)
 create mode 100644 gnu/packages/patches/alsa-lib.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 39267f2765..de17670beb 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -741,6 +741,7 @@ dist_patch_DATA =                                           
\
   %D%/packages/patches/akonadi-not-relocatable.patch           \
   %D%/packages/patches/akonadi-timestamps.patch                \
   %D%/packages/patches/allegro-mesa-18.2.5-and-later.patch     \
+  %D%/packages/patches/alsa-lib.patch                          \
   %D%/packages/patches/amule-crypto-6.patch                    \
   %D%/packages/patches/anki-mpv-args.patch                     \
   %D%/packages/patches/antiword-CVE-2014-8123.patch                    \
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index b451f591ea..e0ed8c040d 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -1771,6 +1771,7 @@ intercept and print the system calls executed by the 
program.")
 (define-public alsa-lib
   (package
     (name "alsa-lib")
+    (replacement alsa-lib/fixed)
     (version "1.2.2")
     (source (origin
              (method url-fetch)
@@ -1792,6 +1793,15 @@ intercept and print the system calls executed by the 
program.")
 MIDI functionality to the Linux-based operating system.")
     (license license:lgpl2.1+)))
 
+(define alsa-lib/fixed
+  (package
+    (inherit alsa-lib)
+    (source (origin
+              (inherit (package-source alsa-lib))
+              (patches (append
+                         (origin-patches (package-source alsa-lib))
+                         (search-patches "alsa-lib.patch")))))))
+
 (define-public alsa-utils
   (package
     (name "alsa-utils")
diff --git a/gnu/packages/patches/alsa-lib.patch 
b/gnu/packages/patches/alsa-lib.patch
new file mode 100644
index 0000000000..3cee02aa0c
--- /dev/null
+++ b/gnu/packages/patches/alsa-lib.patch
@@ -0,0 +1,110 @@
+diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
+index 74d1d1a..17ffb12 100644
+--- a/src/pcm/pcm.c
++++ b/src/pcm/pcm.c
+@@ -2042,6 +2042,19 @@ static const char *const build_in_pcms[] = {
+       NULL
+ };
+ 
++
++// helper funcion used below
++int file_exists(const char * filename)
++{
++      FILE * file;
++      if (file = fopen(filename, "r"))
++      {
++              fclose(file);
++              return 1;
++      }
++      return 0;
++}
++
+ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
+                            snd_config_t *pcm_root, snd_config_t *pcm_conf,
+                            snd_pcm_stream_t stream, int mode)
+@@ -2141,8 +2154,38 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const 
char *name,
+                               err = -ENOMEM;
+                               goto _err;
+                       }
+-                      lib = buf1;
+                       sprintf(buf1, "%s/libasound_module_pcm_%s.so", 
ALSA_PLUGIN_DIR, str);
++                      if (!file_exists(buf1)){
++                              // try to locate plugin in one of 
ALSA_PLUGIN_DIRS which is colon separated list of paths
++                              char * pdirs = getenv("ALSA_PLUGIN_DIRS");
++
++                              if (pdirs){ // env var set?
++                                      char * saveptr;
++                                      while (1) {
++                                              char * dir_tok = 
strtok_r(pdirs, "::::", &saveptr); // "::::" to work around bug in glibc and 
-O2 ? ":" seems to cause a segfault
++                                              if (dir_tok == NULL)
++                            break;
++                                              char * so_file = 
malloc(strlen(str) + strlen(dir_tok) + 32);
++                                              if (so_file == NULL) {
++                                                      err = -ENOMEM;
++                                                      goto _err;
++                                              }
++
++                                              sprintf(so_file, 
"%s/libasound_module_pcm_%s.so", dir_tok, str);
++
++                                              if (file_exists(so_file)){
++
++                                                      free(buf1);
++                                                      buf1 = so_file;
++                                                      break;
++                                              } else {
++                                                      free (so_file);
++                                              }
++                                              pdirs = NULL;
++                                      }
++                              }
++                      }
++                      lib = buf1;
+               }
+       }
+ #ifndef PIC
+
+
+diff --git a/src/control/control.c b/src/control/control.c
+index c090797..137fe57 100644
+--- a/src/control/control.c
++++ b/src/control/control.c
+@@ -854,8 +854,38 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char 
*name,
+                               err = -ENOMEM;
+                               goto _err;
+                       }
++                      sprintf(buf1, "%s/libasound_module_pcm_%s.so", 
ALSA_PLUGIN_DIR, str);
++                      if (!file_exists(buf1)){
++                              // try to locate plugin in one of 
ALSA_PLUGIN_DIRS which is colon separated list of paths
++                              char * pdirs = getenv("ALSA_PLUGIN_DIRS");
++
++                              if (pdirs){ // env var set?
++                                      char * saveptr;
++                                      while (1) {
++                                              char * dir_tok = 
strtok_r(pdirs, "::::", &saveptr); // "::::" to work around bug in glibc and 
-O2 ? ":" seems to cause a segfault
++                                              if (dir_tok == NULL)
++                            break;
++                                              char * so_file = 
malloc(strlen(str) + strlen(dir_tok) + 32);
++                                              if (so_file == NULL) {
++                                                      err = -ENOMEM;
++                                                      goto _err;
++                                              }
++
++                                              sprintf(so_file, 
"%s/libasound_module_ctl_%s.so", dir_tok, str);
++
++                                              if (file_exists(so_file)){
++
++                                                      free(buf1);
++                                                      buf1 = so_file;
++                                                      break;
++                                              } else {
++                                                      free (so_file);
++                                              }
++                                              pdirs = NULL;
++                                      }
++                              }
++                      }
+                       lib = buf1;
+-                      sprintf(buf1, "%s/libasound_module_ctl_%s.so", 
ALSA_PLUGIN_DIR, str);
+               }
+       }
+ #ifndef PIC
-- 
2.26.2


From 71c5ccb8f24165bea6154d566056b2474adeebc7 Mon Sep 17 00:00:00 2001
From: Leo Famulari <[email protected]>
Date: Fri, 8 May 2020 18:27:00 -0400
Subject: [PATCH 3/3] WIP: Make alsa-lib look for ALSA plugins at run-time.

Currently it doesn't work :(

Test on foreign distro with `mpg123 -o alsa ~/file.mp3`.

* gnu/packages/patches/alsa-lib.patch: Make alsa-lib look up plugins in
the directories named in $ALSA_PLUGIN_DIRS.
---
 gnu/packages/patches/alsa-lib.patch | 76 +++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/gnu/packages/patches/alsa-lib.patch 
b/gnu/packages/patches/alsa-lib.patch
index 3cee02aa0c..7ca6b7960a 100644
--- a/gnu/packages/patches/alsa-lib.patch
+++ b/gnu/packages/patches/alsa-lib.patch
@@ -108,3 +108,79 @@ index c090797..137fe57 100644
                }
        }
  #ifndef PIC
+diff --git a/src/dlmisc.c b/src/dlmisc.c
+index 8c8f3ff7..274d4b84 100644
+--- a/src/dlmisc.c
++++ b/src/dlmisc.c
+@@ -82,19 +82,52 @@ void *snd_dlopen(const char *name, int mode, char *errbuf, 
size_t errbuflen)
+       char *filename = NULL;
+ 
+       if (name && name[0] != '/') {
+-              filename = alloca(sizeof(ALSA_PLUGIN_DIR) + 1 + strlen(name) + 
1);
+-              if (filename) {
+-                      strcpy(filename, ALSA_PLUGIN_DIR);
+-                      strcat(filename, "/");
+-                      strcat(filename, name);
+-                      handle = dlopen(filename, mode);
+-                      if (!handle) {
+-                              /* if the filename exists and cannot be opened 
*/
+-                              /* return immediately */
+-                              if (access(filename, X_OK) == 0)
+-                                      goto errpath;
++                // 'name' is the full library.so name, e.g. 
libasound_module_conf_pulse.so
++              fprintf(stderr, "XXX name is %s\n", name);
++              char * plugindirs = getenv("ALSA_PLUGIN_DIRS");
++              fprintf(stderr, "XXX plugindirs are %s\n" ,plugindirs);
++              if (plugindirs) {
++                      char * saveptr;
++                      while (1) {
++                              // See comment in src/control/control.c about 
"::::"
++                              char * dir_tok = strtok_r(plugindirs, "::::", 
&saveptr);
++                              if (dir_tok == NULL)
++                                      break;
++                              fprintf(stderr, "XXX dir token is %s\n" 
,dir_tok);
++                              char * so_file = malloc(strlen(name) + 
strlen(dir_tok) + 32);
++                              sprintf(so_file, "%s/%s" ,dir_tok, name);
++                              // TODO Check if so_file == NULL here
++                              if (file_exists(so_file)) {
++                                      fprintf(stderr, "XXX Found the library 
%s\n" ,so_file);
++                                      handle = dlopen(filename, mode);
++                                      if (!handle) {
++                                              /* if the filename exists and 
cannot be opened */
++                                              /* return immediately */
++                                              if (access(filename, X_OK) == 0)
++                                                      goto errpath;
++                                      }
++                                      break;
++                              } else {
++                                      fprintf(stderr, "XXX Did not find the 
library %s\n" ,so_file);
++                                      break;
++                              }
+                       }
+               }
++// Cut here:
++//            filename = alloca(sizeof(ALSA_PLUGIN_DIR) + 1 + strlen(name) + 
1);
++//            if (filename) {
++//                    strcpy(filename, ALSA_PLUGIN_DIR);
++//                    strcat(filename, "/");
++//                    strcat(filename, name);
++//                    handle = dlopen(filename, mode);
++//                    if (!handle) {
++//                            /* if the filename exists and cannot be opened 
*/
++//                            /* return immediately */
++//                            if (access(filename, X_OK) == 0)
++//                                    goto errpath;
++//                    }
++//            }
++// ... to here.
+       }
+       if (!handle) {
+               handle = dlopen(name, mode);
+@@ -104,6 +137,7 @@ void *snd_dlopen(const char *name, int mode, char *errbuf, 
size_t errbuflen)
+       return handle;
+ errpath:
+       if (errbuf)
++              fprintf(stderr, "XXX couldn't find your thing!\n");
+               snprintf(errbuf, errbuflen, "%s: %s", filename, dlerror());
+ #endif
+       return NULL;
-- 
2.26.2

Attachment: signature.asc
Description: PGP signature

Reply via email to