From 2dc0cf223a71d2a22ca19eff6c59d55d72028c64 Mon Sep 17 00:00:00 2001 From: Leo Famulari 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 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 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