1{
2 lib,
3 stdenv,
4 fetchFromGitHub,
5 meson,
6 ninja,
7 pkg-config,
8 glib,
9 systemd,
10 fmt,
11 buildPackages,
12 # Inputs
13 curl,
14 libcdio,
15 libcdio-paranoia,
16 libmms,
17 libnfs,
18 liburing,
19 samba,
20 # Archive support
21 bzip2,
22 zziplib,
23 # Codecs
24 audiofile,
25 faad2,
26 ffmpeg,
27 flac,
28 fluidsynth,
29 game-music-emu,
30 libmad,
31 libmikmod,
32 mpg123,
33 libopus,
34 libvorbis,
35 lame,
36 # Filters
37 libsamplerate,
38 soxr,
39 # Outputs
40 alsa-lib,
41 libao,
42 libjack2,
43 libpulseaudio,
44 libshout,
45 pipewire,
46 # Misc
47 icu,
48 sqlite,
49 avahi,
50 dbus,
51 pcre2,
52 libgcrypt,
53 expat,
54 nlohmann_json,
55 zlib,
56 libupnp,
57 # Client support
58 libmpdclient,
59 # Tag support
60 libid3tag,
61 nixosTests,
62 # For documentation
63 doxygen,
64 python3Packages, # for sphinx-build
65 # For tests
66 gtest,
67 zip,
68}:
69
70let
71 concatAttrVals = nameList: set: lib.concatMap (x: set.${x} or [ ]) nameList;
72
73 featureDependencies = {
74 # Storage plugins
75 udisks = [ dbus ];
76 webdav = [
77 curl
78 expat
79 ];
80 # Input plugins
81 cdio_paranoia = [
82 libcdio
83 libcdio-paranoia
84 ];
85 curl = [ curl ];
86 io_uring = [ liburing ];
87 mms = [ libmms ];
88 nfs = [ libnfs ];
89 smbclient = [ samba ];
90 # Archive support
91 bzip2 = [ bzip2 ];
92 zzip = [ zziplib ];
93 # Decoder plugins
94 audiofile = [ audiofile ];
95 faad = [ faad2 ];
96 ffmpeg = [ ffmpeg ];
97 flac = [ flac ];
98 fluidsynth = [ fluidsynth ];
99 gme = [ game-music-emu ];
100 mad = [ libmad ];
101 mikmod = [ libmikmod ];
102 mpg123 = [
103 libid3tag
104 mpg123
105 ];
106 opus = [ libopus ];
107 vorbis = [ libvorbis ];
108 # Encoder plugins
109 vorbisenc = [ libvorbis ];
110 lame = [ lame ];
111 # Filter plugins
112 libsamplerate = [ libsamplerate ];
113 soxr = [ soxr ];
114 # Output plugins
115 alsa = [ alsa-lib ];
116 ao = [ libao ];
117 jack = [ libjack2 ];
118 pipewire = [ pipewire ];
119 pulse = [ libpulseaudio ];
120 shout = [ libshout ];
121 # Commercial services
122 qobuz = [
123 curl
124 libgcrypt
125 nlohmann_json
126 ];
127 # Client support
128 libmpdclient = [ libmpdclient ];
129 # Tag support
130 id3tag = [
131 libid3tag
132 zlib
133 ];
134 # Misc
135 dbus = [ dbus ];
136 expat = [ expat ];
137 icu = [ icu ];
138 pcre = [ pcre2 ];
139 sqlite = [ sqlite ];
140 syslog = [ ];
141 systemd = [ systemd ];
142 zeroconf = [
143 avahi
144 dbus
145 ];
146 };
147
148 nativeFeatureDependencies = {
149 documentation = [
150 doxygen
151 python3Packages.sphinx
152 ];
153 };
154
155 run =
156 {
157 features ? null,
158 }:
159 let
160 # Disable platform specific features if needed
161 # using libmad to decode mp3 files on darwin is causing a segfault -- there
162 # is probably a solution, but I'm disabling it for now
163 platformMask =
164 lib.optionals stdenv.hostPlatform.isDarwin [
165 "mad"
166 "pulse"
167 "jack"
168 "smbclient"
169 ]
170 ++ lib.optionals (!stdenv.hostPlatform.isLinux) [
171 "alsa"
172 "pipewire"
173 "io_uring"
174 "systemd"
175 "syslog"
176 ];
177
178 knownFeatures =
179 builtins.attrNames featureDependencies ++ builtins.attrNames nativeFeatureDependencies;
180 platformFeatures = lib.subtractLists platformMask knownFeatures;
181
182 features_ =
183 if (features == null) then
184 platformFeatures
185 else
186 let
187 unknown = lib.subtractLists knownFeatures features;
188 in
189 if (unknown != [ ]) then
190 throw "Unknown feature(s): ${lib.concatStringsSep " " unknown}"
191 else
192 let
193 unsupported = lib.subtractLists platformFeatures features;
194 in
195 if (unsupported != [ ]) then
196 throw "Feature(s) ${lib.concatStringsSep " " unsupported} are not supported on ${stdenv.hostPlatform.system}"
197 else
198 features;
199
200 in
201 stdenv.mkDerivation rec {
202 pname = "mpd";
203 version = "0.24.5";
204
205 src = fetchFromGitHub {
206 owner = "MusicPlayerDaemon";
207 repo = "MPD";
208 rev = "v${version}";
209 sha256 = "sha256-MgepOQeOl+n65+7b8zXe2u0fCHFAviSqL1aNu2iSXiM=";
210 };
211
212 buildInputs = [
213 glib
214 fmt
215 # According to the configurePhase of meson, gtest is considered a
216 # runtime dependency. Quoting:
217 #
218 # Run-time dependency GTest found: YES 1.10.0
219 gtest
220 libupnp
221 ]
222 ++ concatAttrVals features_ featureDependencies;
223
224 nativeBuildInputs = [
225 meson
226 ninja
227 pkg-config
228 ]
229 ++ concatAttrVals features_ nativeFeatureDependencies;
230
231 depsBuildBuild = [ buildPackages.stdenv.cc ];
232
233 postPatch =
234 lib.optionalString
235 (stdenv.hostPlatform.isDarwin && lib.versionOlder stdenv.hostPlatform.darwinSdkVersion "12.0")
236 ''
237 substituteInPlace src/output/plugins/OSXOutputPlugin.cxx \
238 --replace kAudioObjectPropertyElement{Main,Master} \
239 --replace kAudioHardwareServiceDeviceProperty_Virtual{Main,Master}Volume
240 '';
241
242 # Otherwise, the meson log says:
243 #
244 # Program zip found: NO
245 nativeCheckInputs = [ zip ];
246
247 doCheck = true;
248
249 mesonAutoFeatures = "disabled";
250
251 outputs = [
252 "out"
253 "doc"
254 ]
255 ++ lib.optional (builtins.elem "documentation" features_) "man";
256
257 CXXFLAGS = lib.optionals stdenv.hostPlatform.isDarwin [
258 "-D__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0"
259 ];
260
261 mesonFlags = [
262 "-Dtest=true"
263 "-Dmanpages=true"
264 "-Dhtml_manual=true"
265 ]
266 ++ map (x: "-D${x}=enabled") features_
267 ++ map (x: "-D${x}=disabled") (lib.subtractLists features_ knownFeatures)
268 ++ lib.optional (builtins.elem "zeroconf" features_) (
269 "-Dzeroconf=" + (if stdenv.hostPlatform.isDarwin then "bonjour" else "avahi")
270 )
271 ++ lib.optional (builtins.elem "systemd" features_) "-Dsystemd_system_unit_dir=etc/systemd/system"
272 ++ lib.optional (builtins.elem "qobuz" features_) "-Dnlohmann_json=enabled";
273
274 passthru.tests.nixos = nixosTests.mpd;
275
276 meta = with lib; {
277 description = "Flexible, powerful daemon for playing music";
278 homepage = "https://www.musicpd.org/";
279 license = licenses.gpl2Only;
280 maintainers = with maintainers; [
281 tobim
282 ];
283 platforms = platforms.unix;
284 mainProgram = "mpd";
285
286 longDescription = ''
287 Music Player Daemon (MPD) is a flexible, powerful daemon for playing
288 music. Through plugins and libraries it can play a variety of sound
289 files while being controlled by its network protocol.
290 '';
291 };
292 };
293in
294{
295 mpd = run { };
296 mpd-small = run {
297 features = [
298 "webdav"
299 "curl"
300 "mms"
301 "bzip2"
302 "zzip"
303 "nfs"
304 "audiofile"
305 "faad"
306 "flac"
307 "gme"
308 "mpg123"
309 "opus"
310 "vorbis"
311 "vorbisenc"
312 "lame"
313 "libsamplerate"
314 "shout"
315 "libmpdclient"
316 "id3tag"
317 "expat"
318 "pcre"
319 "sqlite"
320 "qobuz"
321 ]
322 ++ lib.optionals stdenv.hostPlatform.isLinux [
323 "alsa"
324 "systemd"
325 "syslog"
326 "io_uring"
327 ]
328 ++ lib.optionals (!stdenv.hostPlatform.isDarwin) [
329 "mad"
330 "jack"
331 ];
332 };
333 mpdWithFeatures = run;
334}