From e1e3ccda5d37e1796efbfbe2ca1b7e2887e17ab1 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 27 Apr 2026 12:22:29 +0100 Subject: [PATCH 1/4] ldacbt: use Sony AOSP source Also build all functionalities into a single shared library: encoder, decoder, and ABR. --- ...-support-for-dynamic-loading-libldac.patch | 164 ++++++++++++++++++ pkgs/by-name/ld/ldacbt/package.nix | 116 ++++++++++--- 2 files changed, 255 insertions(+), 25 deletions(-) create mode 100644 pkgs/by-name/ld/ldacbt/0001-abr-drop-support-for-dynamic-loading-libldac.patch diff --git a/pkgs/by-name/ld/ldacbt/0001-abr-drop-support-for-dynamic-loading-libldac.patch b/pkgs/by-name/ld/ldacbt/0001-abr-drop-support-for-dynamic-loading-libldac.patch new file mode 100644 index 000000000000..e054d75fd395 --- /dev/null +++ b/pkgs/by-name/ld/ldacbt/0001-abr-drop-support-for-dynamic-loading-libldac.patch @@ -0,0 +1,164 @@ +From 040210591a5e90fc3e0ca0ec438426273e86c497 Mon Sep 17 00:00:00 2001 +From: "yshuiv7@gmail.com" +Date: Mon, 27 Apr 2026 15:30:10 +0100 +Subject: [PATCH] abr: drop support for dynamic loading libldac + +--- + abr/inc/ldacBT_abr.h | 2 +- + abr/src/ldacBT_abr.c | 76 +------------------------------------------- + 2 files changed, 2 insertions(+), 76 deletions(-) + +diff --git a/abr/inc/ldacBT_abr.h b/abr/inc/ldacBT_abr.h +index 294e230..735ea67 100644 +--- a/abr/inc/ldacBT_abr.h ++++ b/abr/inc/ldacBT_abr.h +@@ -89,7 +89,7 @@ typedef struct _ldacbt_abr_param * HANDLE_LDAC_ABR; + * Return value + * HANDLE_LDAC_ABR for success, NULL for failure. + */ +-LDAC_ABR_API HANDLE_LDAC_ABR ldac_ABR_get_handle(const char *libpath); ++LDAC_ABR_API HANDLE_LDAC_ABR ldac_ABR_get_handle(void); + + /* Release of LDAC ABR handle. + * Format +diff --git a/abr/src/ldacBT_abr.c b/abr/src/ldacBT_abr.c +index 0af6278..fad2dd0 100644 +--- a/abr/src/ldacBT_abr.c ++++ b/abr/src/ldacBT_abr.c +@@ -8,10 +8,6 @@ + + #include + #include +-#ifdef LDAC_ABR_DYNAMIC_LINK_LDAC_API +-#include +-#include +-#endif + + #define LDAC_ABR_OBSERVING_TIME_MS 500 /* [ms] the time length for storing Tx Queue Depth */ + #define LDAC_ABR_PENALTY_MAX 4 +@@ -56,18 +52,11 @@ typedef int (*tLDACBT_GET_ERR)(HANDLE_LDAC_BT hLdacBt); + + typedef struct _ldacbt_api_param + { +-#ifdef LDAC_ABR_DYNAMIC_LINK_LDAC_API +- const char *lib_name; +- void *lib_handle; +-#endif + tLDACBT_ALTER_EQMID_PRIORITY alter_eqmid_priority; + tLDACBT_GET_EQMID get_eqmid; + tLDACBT_GET_ERR get_error_code; + } LDACBT_API_PARAMS, * HANDLE_LDACBT_API; + +-#ifdef LDAC_ABR_DYNAMIC_LINK_LDAC_API +-static int open_lib(HANDLE_LDACBT_API hLdacBtApi, const char *lib_name ); +-#endif + + static int load_ldacbt_api_functions(HANDLE_LDACBT_API hLdacBtApi); + +@@ -122,7 +111,7 @@ static const int sizeOfEqmidToBitrateSortedIdTable = (int)(sizeof(aEqmidToAbrQua + / sizeof(aEqmidToAbrQualityModeID[0])); + + /* Get LDAC ABR handle */ +-HANDLE_LDAC_ABR ldac_ABR_get_handle(const char *libpath) ++HANDLE_LDAC_ABR ldac_ABR_get_handle(void) + { + HANDLE_LDAC_ABR hLdacAbr; + ABRDBG( "" ); +@@ -131,15 +120,6 @@ HANDLE_LDAC_ABR ldac_ABR_get_handle(const char *libpath) + return NULL; + } + clear_data( hLdacAbr, sizeof(LDAC_ABR_PARAMS) ); +-#ifdef LDAC_ABR_DYNAMIC_LINK_LDAC_API +- if (libpath != NULL) { +- if (open_lib( &hLdacAbr->ldacBtApi, libpath ) < 0) { +- ABRDBG( "[ERR] Failed to open shared library \"%s\".", libpath ); +- ldac_ABR_free_handle(hLdacAbr); +- return NULL; +- } +- } +-#endif + if( load_ldacbt_api_functions(&hLdacAbr->ldacBtApi) != 0 ){ + ldac_ABR_free_handle(hLdacAbr); + return NULL; +@@ -156,12 +136,6 @@ void ldac_ABR_free_handle(HANDLE_LDAC_ABR hLdacAbr) + if (hLdacAbr->TxQD_Info.pHist){ + free(hLdacAbr->TxQD_Info.pHist); + } +-#ifdef LDAC_ABR_DYNAMIC_LINK_LDAC_API +- if (hLdacAbr->ldacBtApi.lib_handle != NULL) { +- dlclose(hLdacAbr->ldacBtApi.lib_handle); +- hLdacAbr->ldacBtApi.lib_handle = NULL; +- } +-#endif + free(hLdacAbr); + } + } +@@ -408,65 +382,17 @@ int ldac_ABR_Proc( HANDLE_LDAC_BT hLDAC, HANDLE_LDAC_ABR hLdacAbr, + } + + +-#ifdef LDAC_ABR_DYNAMIC_LINK_LDAC_API +-static void *load_func(void *lib_handle, const char* func_name) +-{ +- void *func_ptr = dlsym(lib_handle, func_name); +- if(func_ptr == NULL){ +- ABRDBG("[ERR] cannot find function '%s' in the library.\n", func_name); +- return NULL; +- } +- return func_ptr; +-} +- +-static int open_lib(HANDLE_LDACBT_API hLdacBtApi, const char *lib_name ) +-{ +- if( hLdacBtApi == NULL ){ +- ABRDBG("[ERR] handle is NULL"); +- return -1; +- } +- if( lib_name == NULL ){ +- ABRDBG("[ERR] lib_name is NULL"); +- return -1; +- } +- // open library +- hLdacBtApi->lib_handle = dlopen(lib_name, RTLD_NOW); +- if(hLdacBtApi->lib_handle == NULL){ +-#ifdef LOCAL_DEBUG +- char buffer_str[1024]; +- strerror_r(errno, buffer_str, sizeof(buffer_str)); +- ABRDBG("[ERR] cannot open library '%s': errno = %d (%s)\n", +- lib_name, errno, buffer_str); +-#endif +- return -1; +- } +- return 0; +-} +-#endif /* LDAC_ABR_DYNAMIC_LINK_LDAC_API */ +- + // Load functions + static int load_ldacbt_api_functions(HANDLE_LDACBT_API hLdacBtApi) + { + hLdacBtApi->alter_eqmid_priority = +-#ifdef LDAC_ABR_DYNAMIC_LINK_LDAC_API +- load_func(hLdacBtApi->lib_handle, "ldacBT_alter_eqmid_priority"); +-#else + ldacBT_alter_eqmid_priority; +-#endif + + hLdacBtApi->get_eqmid = +-#ifdef LDAC_ABR_DYNAMIC_LINK_LDAC_API +- load_func(hLdacBtApi->lib_handle, "ldacBT_get_eqmid"); +-#else + ldacBT_get_eqmid; +-#endif + + hLdacBtApi->get_error_code = +-#ifdef LDAC_ABR_DYNAMIC_LINK_LDAC_API +- load_func(hLdacBtApi->lib_handle, "ldacBT_get_error_code"); +-#else + ldacBT_get_error_code; +-#endif + + if( (hLdacBtApi->alter_eqmid_priority == NULL) || + (hLdacBtApi->get_eqmid == NULL) || +-- +2.53.0 + diff --git a/pkgs/by-name/ld/ldacbt/package.nix b/pkgs/by-name/ld/ldacbt/package.nix index 72320637739d..de766de0d615 100644 --- a/pkgs/by-name/ld/ldacbt/package.nix +++ b/pkgs/by-name/ld/ldacbt/package.nix @@ -2,19 +2,17 @@ lib, stdenv, fetchFromGitHub, - cmake, }: stdenv.mkDerivation (finalAttrs: { pname = "ldacBT"; - version = "2.0.2.3"; + version = "2.0.72"; src = fetchFromGitHub { - repo = "ldacBT"; - owner = "ehfive"; - tag = "v${finalAttrs.version}"; - sha256 = "09dalysx4fgrgpfdm9a51x6slnf4iik1sqba4xjgabpvq91bnb63"; - fetchSubmodules = true; + owner = "open-vela"; + repo = "external_libldac"; + rev = "5b4bf66096ba0d69615efb2422ba3d023c34c2fd"; + hash = "sha256-5jeqTyhSBtYky15Xw1lIbUxeGZMQQQdM/EQUFicyi3Y="; }; outputs = [ @@ -22,31 +20,99 @@ stdenv.mkDerivation (finalAttrs: { "dev" ]; - nativeBuildInputs = [ - cmake + patches = [ + ./0001-abr-drop-support-for-dynamic-loading-libldac.patch ]; - cmakeFlags = [ - # CMakeLists.txt by default points to $out - "-DINSTALL_INCLUDEDIR=${placeholder "dev"}/include" - ]; + env.NIX_CFLAGS_COMPILE = "-O2 -fPIC -fno-merge-constants -Wall -Iinc -Isrc -Iabr/inc"; - # Fix the build with CMake 4. - # - # See: - postPatch = '' - substituteInPlace CMakeLists.txt \ - --replace-fail \ - 'cmake_minimum_required(VERSION 3.0)' \ - 'cmake_minimum_required(VERSION 3.0...3.10)' + # Verify finalAttrs.version matches LDACBT_LIB_VER_* in upstream source. + # Guards against silent version drift when the pinned commit changes. + preBuild = '' + awk -v want=${finalAttrs.version} ' + /^#define LDACBT_LIB_VER_/ { v = v sep ($3+0); sep = "." } + END { + if (v != want) { print "version mismatch: package says " want ", source reports " v > "/dev/stderr"; exit 1 } + } + ' src/ldacBT_api.c + ''; + + # Upstream ships AOSP build files and a gcc/ makefile that only knows + # about the in-tree layout. Compile and link directly; the entire + # library is two umbrella translation units. + buildPhase = '' + runHook preBuild + + soname=libldacBT.so.${lib.versions.major finalAttrs.version} + sofile=libldacBT.so.${finalAttrs.version} + + $CC -shared -Wl,-soname,$soname src/ldaclib.c src/ldacBT.c abr/src/ldacBT_abr.c -lm -o $sofile + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + install -Dm644 -t $out/lib $sofile + ln -s $sofile $out/lib/$soname + ln -s $sofile $out/lib/libldacBT.so + + install -Dm644 inc/ldacBT.h $dev/include/ldac/ldacBT.h + install -Dm644 abr/inc/ldacBT_abr.h $dev/include/ldac/ldacBT_abr.h + + mkdir -p $dev/lib/pkgconfig + cat > $dev/lib/pkgconfig/ldacBT-dec.pc < $dev/lib/pkgconfig/ldacBT-enc.pc < $dev/lib/pkgconfig/ldacBT-abr.pc < Date: Mon, 27 Apr 2026 12:41:51 +0100 Subject: [PATCH 2/4] pipewire: drop libldac-dec from buildInputs The now unified ldacbt has decoding support as well. Fixes #511056 --- pkgs/by-name/pi/pipewire/package.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/by-name/pi/pipewire/package.nix b/pkgs/by-name/pi/pipewire/package.nix index 3929f392ee6a..7f5ff1315146 100644 --- a/pkgs/by-name/pi/pipewire/package.nix +++ b/pkgs/by-name/pi/pipewire/package.nix @@ -52,7 +52,6 @@ fdk_aac, libopus, ldacbt, - libldac-dec, spandsp, modemmanager, libpulseaudio, @@ -176,7 +175,6 @@ stdenv.mkDerivation (finalAttrs: { ++ lib.optional webrtcAudioProcessingSupport webrtc-audio-processing ++ lib.optional stdenv.hostPlatform.isLinux alsa-lib ++ lib.optional ldacbtSupport ldacbt - ++ lib.optional (ldacBtDecodeSupport && ldacbtSupport) libldac-dec ++ lib.optional libcameraSupport libcamera ++ lib.optional zeroconfSupport avahi ++ lib.optional raopSupport openssl From 8d765834f4a0ec6e74938f52306ff24fc61fa951 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 27 Apr 2026 16:07:13 +0100 Subject: [PATCH 3/4] libldac-dec: drop --- pkgs/by-name/li/libldac-dec/package.nix | 85 ------------------------- 1 file changed, 85 deletions(-) delete mode 100644 pkgs/by-name/li/libldac-dec/package.nix diff --git a/pkgs/by-name/li/libldac-dec/package.nix b/pkgs/by-name/li/libldac-dec/package.nix deleted file mode 100644 index 89fa401ea258..000000000000 --- a/pkgs/by-name/li/libldac-dec/package.nix +++ /dev/null @@ -1,85 +0,0 @@ -{ - lib, - stdenv, - fetchFromGitHub, -}: - -stdenv.mkDerivation (finalAttrs: { - pname = "libldac-dec"; - version = "2.0.72"; - - src = fetchFromGitHub { - owner = "open-vela"; - repo = "external_libldac"; - rev = "5b4bf66096ba0d69615efb2422ba3d023c34c2fd"; - hash = "sha256-5jeqTyhSBtYky15Xw1lIbUxeGZMQQQdM/EQUFicyi3Y="; - }; - - outputs = [ - "out" - "dev" - ]; - - env.NIX_CFLAGS_COMPILE = "-O2 -fPIC -Wall -D_DECODE_ONLY -Iinc -Isrc"; - - # Verify finalAttrs.version matches LDACBT_LIB_VER_* in upstream source. - # Guards against silent version drift when the pinned commit changes. - preBuild = '' - awk -v want=${finalAttrs.version} ' - /^#define LDACBT_LIB_VER_/ { v = v sep ($3+0); sep = "." } - END { - if (v != want) { print "version mismatch: package says " want ", source reports " v > "/dev/stderr"; exit 1 } - } - ' src/ldacBT_api.c - ''; - - # Upstream ships AOSP build files and a gcc/ makefile that only knows - # about the in-tree layout. Compile and link directly; the entire - # library is two umbrella translation units. - buildPhase = '' - runHook preBuild - - soname=libldacBT_dec.so.${lib.versions.major finalAttrs.version} - sofile=libldacBT_dec.so.${finalAttrs.version} - - $CC -shared -Wl,-soname,$soname src/ldaclib.c src/ldacBT.c -lm -o $sofile - - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - - install -Dm644 -t $out/lib $sofile - ln -s $sofile $out/lib/$soname - ln -s $sofile $out/lib/libldacBT_dec.so - - install -Dm644 inc/ldacBT.h $dev/include/ldac/ldacBT.h - - mkdir -p $dev/lib/pkgconfig - cat > $dev/lib/pkgconfig/ldacBT-dec.pc < Date: Mon, 1 Jun 2026 08:19:33 +0100 Subject: [PATCH 4/4] pipewire: remove the ldacBtDecodeSupport option Always enable it if ldac is available. --- pkgs/by-name/pi/pipewire/package.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/by-name/pi/pipewire/package.nix b/pkgs/by-name/pi/pipewire/package.nix index 7f5ff1315146..cd01b173b031 100644 --- a/pkgs/by-name/pi/pipewire/package.nix +++ b/pkgs/by-name/pi/pipewire/package.nix @@ -73,7 +73,6 @@ x11Support && lib.systems.equals stdenv.buildPlatform stdenv.hostPlatform && lib.meta.availableOn stdenv.hostPlatform ffado, - ldacBtDecodeSupport ? false, ffado, libselinux, libebur128, @@ -243,7 +242,7 @@ stdenv.mkDerivation (finalAttrs: { (lib.mesonEnable "bluez5-codec-lc3plus" false) (lib.mesonEnable "bluez5-codec-lc3" bluezSupport) (lib.mesonEnable "bluez5-codec-ldac" (bluezSupport && ldacbtSupport)) - (lib.mesonEnable "bluez5-codec-ldac-dec" (bluezSupport && ldacbtSupport && ldacBtDecodeSupport)) + (lib.mesonEnable "bluez5-codec-ldac-dec" (bluezSupport && ldacbtSupport)) (lib.mesonEnable "opus" true) (lib.mesonOption "sysconfdir" "/etc") (lib.mesonEnable "raop" raopSupport)