1{
2 lib,
3 stdenv,
4 fetchurl,
5 pkg-config,
6 libsndfile,
7 libtool,
8 makeWrapper,
9 perlPackages,
10 xorg,
11 libcap,
12 alsa-lib,
13 glib,
14 dconf,
15 avahi,
16 libjack2,
17 libasyncns,
18 lirc,
19 dbus,
20 sbc,
21 bluez5,
22 udev,
23 udevCheckHook,
24 openssl,
25 fftwFloat,
26 soxr,
27 speexdsp,
28 systemd,
29 webrtc-audio-processing_1,
30 gst_all_1,
31 check,
32 libintl,
33 meson,
34 ninja,
35 m4,
36 wrapGAppsHook3,
37 fetchpatch2,
38 nixosTests,
39
40 x11Support ? false,
41
42 useSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
43
44 # Whether to support the JACK sound system as a backend.
45 jackaudioSupport ? false,
46
47 # Whether to build the OSS wrapper ("padsp").
48 ossWrapper ? true,
49
50 airtunesSupport ? false,
51
52 bluetoothSupport ? stdenv.hostPlatform.isLinux,
53 advancedBluetoothCodecs ? false,
54
55 remoteControlSupport ? false,
56
57 zeroconfSupport ? false,
58
59 alsaSupport ? stdenv.hostPlatform.isLinux,
60 udevSupport ? stdenv.hostPlatform.isLinux,
61
62 # Whether to build only the library.
63 libOnly ? false,
64
65}:
66
67stdenv.mkDerivation rec {
68 pname = "${lib.optionalString libOnly "lib"}pulseaudio";
69 version = "17.0";
70
71 src = fetchurl {
72 url = "http://freedesktop.org/software/pulseaudio/releases/pulseaudio-${version}.tar.xz";
73 hash = "sha256-BTeU1mcaPjl9hJ5HioC4KmPLnYyilr01tzMXu1zrh7U=";
74 };
75
76 patches = [
77 # Install sysconfdir files inside of the nix store,
78 # but use a conventional runtime sysconfdir outside the store
79 ./add-option-for-installation-sysconfdir.patch
80
81 # Fix crashes with some UCM devices
82 # See https://gitlab.archlinux.org/archlinux/packaging/packages/pulseaudio/-/issues/4
83 (fetchpatch2 {
84 name = "alsa-ucm-Check-UCM-verb-before-working-with-device-status.patch";
85 url = "https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/commit/f5cacd94abcc47003bd88ad7ca1450de649ffb15.patch";
86 hash = "sha256-WyEqCitrqic2n5nNHeVS10vvGy5IzwObPPXftZKy/A8=";
87 })
88 (fetchpatch2 {
89 name = "alsa-ucm-Replace-port-device-UCM-context-assertion-with-an-error.patch";
90 url = "https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/commit/ed3d4f0837f670e5e5afb1afa5bcfc8ff05d3407.patch";
91 hash = "sha256-fMJ3EYq56sHx+zTrG6osvI/QgnhqLvWiifZxrRLMvns=";
92 })
93 ];
94
95 postPatch = ''
96 # Fails in LXC containers where not all cores are enabled, where this setaffinity call will return EINVAL
97 sed -i "/fail_unless(pthread_setaffinity_np/d" src/tests/once-test.c
98 '';
99
100 outputs = [
101 "out"
102 "dev"
103 ];
104
105 nativeBuildInputs = [
106 pkg-config
107 meson
108 ninja
109 makeWrapper
110 perlPackages.perl
111 perlPackages.XMLParser
112 m4
113 udevCheckHook
114 ]
115 ++ lib.optionals (!stdenv.hostPlatform.isDarwin) [ glib ]
116 # gstreamer plugin discovery requires wrapping
117 ++ lib.optional (bluetoothSupport && advancedBluetoothCodecs) wrapGAppsHook3;
118
119 propagatedBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [ libcap ];
120
121 buildInputs = [
122 libtool
123 libsndfile
124 soxr
125 speexdsp
126 fftwFloat
127 check
128 ]
129 ++ lib.optionals (!stdenv.hostPlatform.isDarwin) [
130 glib
131 dbus
132 ]
133 ++ lib.optionals (stdenv.hostPlatform.isDarwin || stdenv.hostPlatform.isFreeBSD) [
134 libintl
135 ]
136 ++ lib.optionals (!libOnly) (
137 [
138 libasyncns
139 webrtc-audio-processing_1
140 ]
141 ++ lib.optional jackaudioSupport libjack2
142 ++ lib.optionals x11Support [
143 xorg.libICE
144 xorg.libSM
145 xorg.libX11
146 xorg.libXi
147 xorg.libXtst
148 ]
149 ++ lib.optional useSystemd systemd
150 ++ lib.optionals stdenv.hostPlatform.isLinux [
151 alsa-lib
152 udev
153 ]
154 ++ lib.optional airtunesSupport openssl
155 ++ lib.optionals bluetoothSupport [
156 bluez5
157 sbc
158 ]
159 # aptX and LDAC codecs are in gst-plugins-bad so far, rtpldacpay is in -good
160 ++ lib.optionals (bluetoothSupport && advancedBluetoothCodecs) (
161 builtins.attrValues {
162 inherit (gst_all_1)
163 gst-plugins-bad
164 gst-plugins-good
165 gst-plugins-base
166 gstreamer
167 ;
168 }
169 )
170 ++ lib.optional remoteControlSupport lirc
171 ++ lib.optional zeroconfSupport avahi
172 );
173
174 env =
175 lib.optionalAttrs (stdenv.cc.bintools.isLLVM && lib.versionAtLeast stdenv.cc.bintools.version "17")
176 {
177 # https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/3848
178 NIX_LDFLAGS = "--undefined-version";
179 };
180
181 mesonFlags = [
182 (lib.mesonEnable "alsa" (!libOnly && alsaSupport))
183 (lib.mesonEnable "asyncns" (!libOnly))
184 (lib.mesonEnable "avahi" zeroconfSupport)
185 (lib.mesonEnable "bluez5" (!libOnly && bluetoothSupport))
186 # advanced bluetooth audio codecs are provided by gstreamer
187 (lib.mesonEnable "bluez5-gstreamer" (!libOnly && bluetoothSupport && advancedBluetoothCodecs))
188 (lib.mesonOption "database" "simple")
189 (lib.mesonBool "doxygen" false)
190 (lib.mesonEnable "elogind" false)
191 # gsettings does not support cross-compilation
192 (lib.mesonEnable "gsettings" (
193 stdenv.hostPlatform.isLinux && (stdenv.buildPlatform == stdenv.hostPlatform)
194 ))
195 (lib.mesonEnable "gstreamer" false)
196 (lib.mesonEnable "gtk" false)
197 (lib.mesonEnable "jack" (jackaudioSupport && !libOnly))
198 (lib.mesonEnable "lirc" remoteControlSupport)
199 (lib.mesonEnable "openssl" airtunesSupport)
200 (lib.mesonEnable "orc" false)
201 (lib.mesonEnable "systemd" (useSystemd && !libOnly))
202 (lib.mesonEnable "tcpwrap" false)
203 (lib.mesonEnable "udev" (!libOnly && udevSupport))
204 (lib.mesonEnable "valgrind" false)
205 (lib.mesonEnable "webrtc-aec" (!libOnly))
206 (lib.mesonEnable "x11" x11Support)
207
208 (lib.mesonOption "localstatedir" "/var")
209 (lib.mesonOption "sysconfdir" "/etc")
210 (lib.mesonOption "sysconfdir_install" "${placeholder "out"}/etc")
211 (lib.mesonOption "udevrulesdir" "${placeholder "out"}/lib/udev/rules.d")
212
213 # pulseaudio complains if its binary is moved after installation;
214 # this is needed so that wrapGApp can operate *without*
215 # renaming the unwrapped binaries (see below)
216 "--bindir=${placeholder "out"}/.bin-unwrapped"
217 ]
218 ++ lib.optionals (stdenv.hostPlatform.isLinux && useSystemd) [
219 (lib.mesonOption "systemduserunitdir" "${placeholder "out"}/lib/systemd/user")
220 ]
221 ++ lib.optionals stdenv.hostPlatform.isDarwin [
222 (lib.mesonEnable "consolekit" false)
223 (lib.mesonEnable "dbus" false)
224 (lib.mesonEnable "glib" false)
225 (lib.mesonEnable "oss-output" false)
226 ];
227
228 # tests fail on Darwin because of timeouts
229 doCheck = !stdenv.hostPlatform.isDarwin;
230
231 doInstallCheck = true;
232
233 preCheck = ''
234 export HOME=$(mktemp -d)
235 '';
236
237 postInstall =
238 lib.optionalString libOnly ''
239 find $out/share -maxdepth 1 -mindepth 1 ! -name "vala" -prune -exec rm -r {} \;
240 find $out/share/vala -maxdepth 1 -mindepth 1 ! -name "vapi" -prune -exec rm -r {} \;
241 rm -r $out/{.bin-unwrapped,etc,lib/pulse-*}
242 ''
243 + ''
244 moveToOutput lib/cmake "$dev"
245 rm -f $out/.bin-unwrapped/qpaeq # this is packaged by the "qpaeq" package now, because of missing deps
246
247 cp config.h $dev/include/pulse
248 '';
249
250 preFixup =
251 lib.optionalString (stdenv.hostPlatform.isLinux && (stdenv.hostPlatform == stdenv.buildPlatform)) ''
252 wrapProgram $out/libexec/pulse/gsettings-helper \
253 --prefix XDG_DATA_DIRS : "$out/share/gsettings-schemas/${pname}-${version}" \
254 --prefix GIO_EXTRA_MODULES : "${lib.getLib dconf}/lib/gio/modules"
255 ''
256 # add .so symlinks for modules to be found under macOS
257 + lib.optionalString stdenv.hostPlatform.isDarwin ''
258 for file in $out/lib/pulseaudio/modules/*.dylib; do
259 ln -s "''$file" "''${file%.dylib}.so"
260 ln -s "''$file" "$out/lib/pulseaudio/''$(basename ''$file .dylib).so"
261 done
262 ''
263 # put symlinks to binaries in `$prefix/bin`;
264 # then wrapGApp will *rename these symlinks* instead of
265 # the original binaries in `$prefix/.bin-unwrapped` (see above);
266 # when pulseaudio is looking for its own binary (it does!),
267 # it will be happy to find it in its original installation location
268 + lib.optionalString (!libOnly) ''
269 mkdir -p $out/bin
270 ln -st $out/bin $out/.bin-unwrapped/*
271
272 # Ensure that service files use the wrapped binaries.
273 find "$out" -name "*.service" | while read f; do
274 substituteInPlace "$f" --replace "$out/.bin-unwrapped/" "$out/bin/"
275 done
276 '';
277
278 passthru.tests = {
279 inherit (nixosTests) pulseaudio;
280 };
281
282 meta = {
283 description = "Sound server for POSIX and Win32 systems";
284 homepage = "http://www.pulseaudio.org/";
285 license = lib.licenses.lgpl2Plus;
286 maintainers = with lib.maintainers; [ lovek323 ];
287 platforms = lib.platforms.unix;
288
289 # https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1089
290 badPlatforms = [ lib.systems.inspect.platformPatterns.isStatic ];
291
292 longDescription = ''
293 PulseAudio is a sound server for POSIX and Win32 systems. A
294 sound server is basically a proxy for your sound applications.
295 It allows you to do advanced operations on your sound data as it
296 passes between your application and your hardware. Things like
297 transferring the audio to a different machine, changing the
298 sample format or channel count and mixing several sounds into
299 one are easily achieved using a sound server.
300 '';
301 };
302}