lol
1{ lib, stdenv, fetchFromGitHub, meson, ninja, pkg-config, glib, systemd, boost, fmt, buildPackages
2# Darwin inputs
3, AudioToolbox, AudioUnit
4# Inputs
5, curl, libmms, libnfs, liburing, samba
6# Archive support
7, bzip2, zziplib
8# Codecs
9, audiofile, faad2, ffmpeg, flac, fluidsynth, game-music-emu
10, libmad, libmikmod, mpg123, libopus, libvorbis, lame
11# Filters
12, libsamplerate, soxr
13# Outputs
14, alsa-lib, libjack2, libpulseaudio, libshout, pipewire
15# Misc
16, icu, sqlite, avahi, dbus, pcre2, libgcrypt, expat
17# Services
18, yajl
19# Client support
20, libmpdclient
21# Tag support
22, libid3tag
23, nixosTests
24# For documentation
25, doxygen
26, python3Packages # for sphinx-build
27# For tests
28, gtest
29, zip
30}:
31
32let
33 concatAttrVals = nameList: set: lib.concatMap (x: set.${x} or []) nameList;
34
35 featureDependencies = {
36 # Storage plugins
37 udisks = [ dbus ];
38 webdav = [ curl expat ];
39 # Input plugins
40 curl = [ curl ];
41 io_uring = [ liburing ];
42 mms = [ libmms ];
43 nfs = [ libnfs ];
44 smbclient = [ samba ];
45 # Archive support
46 bzip2 = [ bzip2 ];
47 zzip = [ zziplib ];
48 # Decoder plugins
49 audiofile = [ audiofile ];
50 faad = [ faad2 ];
51 ffmpeg = [ ffmpeg ];
52 flac = [ flac ];
53 fluidsynth = [ fluidsynth ];
54 gme = [ game-music-emu ];
55 mad = [ libmad ];
56 mikmod = [ libmikmod ];
57 mpg123 = [ mpg123 ];
58 opus = [ libopus ];
59 vorbis = [ libvorbis ];
60 # Encoder plugins
61 vorbisenc = [ libvorbis ];
62 lame = [ lame ];
63 # Filter plugins
64 libsamplerate = [ libsamplerate ];
65 soxr = [ soxr ];
66 # Output plugins
67 alsa = [ alsa-lib ];
68 jack = [ libjack2 ];
69 pipewire = [ pipewire ];
70 pulse = [ libpulseaudio ];
71 shout = [ libshout ];
72 # Commercial services
73 qobuz = [ curl libgcrypt yajl ];
74 soundcloud = [ curl yajl ];
75 # Client support
76 libmpdclient = [ libmpdclient ];
77 # Tag support
78 id3tag = [ libid3tag ];
79 # Misc
80 dbus = [ dbus ];
81 expat = [ expat ];
82 icu = [ icu ];
83 pcre = [ pcre2 ];
84 sqlite = [ sqlite ];
85 syslog = [ ];
86 systemd = [ systemd ];
87 yajl = [ yajl ];
88 zeroconf = [ avahi dbus ];
89 };
90
91 nativeFeatureDependencies = {
92 documentation = [ doxygen python3Packages.sphinx ];
93 };
94
95 run = { features ? null }:
96 let
97 # Disable platform specific features if needed
98 # using libmad to decode mp3 files on darwin is causing a segfault -- there
99 # is probably a solution, but I'm disabling it for now
100 platformMask = lib.optionals stdenv.isDarwin [ "mad" "pulse" "jack" "smbclient" ]
101 ++ lib.optionals (!stdenv.isLinux) [ "alsa" "pipewire" "io_uring" "systemd" "syslog" ];
102
103 knownFeatures = builtins.attrNames featureDependencies ++ builtins.attrNames nativeFeatureDependencies;
104 platformFeatures = lib.subtractLists platformMask knownFeatures;
105
106 features_ = if (features == null )
107 then platformFeatures
108 else
109 let unknown = lib.subtractLists knownFeatures features; in
110 if (unknown != [])
111 then throw "Unknown feature(s): ${lib.concatStringsSep " " unknown}"
112 else
113 let unsupported = lib.subtractLists platformFeatures features; in
114 if (unsupported != [])
115 then throw "Feature(s) ${lib.concatStringsSep " " unsupported} are not supported on ${stdenv.hostPlatform.system}"
116 else features;
117
118 in stdenv.mkDerivation rec {
119 pname = "mpd";
120 version = "0.23.15";
121
122 src = fetchFromGitHub {
123 owner = "MusicPlayerDaemon";
124 repo = "MPD";
125 rev = "v${version}";
126 sha256 = "sha256-QURq7ysSsxmBOtoBlPTPWiloXQpjEdxnM0L1fLwXfpw=";
127 };
128
129 buildInputs = [
130 glib
131 boost
132 fmt
133 # According to the configurePhase of meson, gtest is considered a
134 # runtime dependency. Quoting:
135 #
136 # Run-time dependency GTest found: YES 1.10.0
137 gtest
138 ]
139 ++ concatAttrVals features_ featureDependencies
140 ++ lib.optionals stdenv.isDarwin [ AudioToolbox AudioUnit ];
141
142 nativeBuildInputs = [
143 meson
144 ninja
145 pkg-config
146 ]
147 ++ concatAttrVals features_ nativeFeatureDependencies;
148
149 depsBuildBuild = [ buildPackages.stdenv.cc ];
150
151 postPatch = lib.optionalString (stdenv.isDarwin && lib.versionOlder stdenv.hostPlatform.darwinSdkVersion "12.0") ''
152 substituteInPlace src/output/plugins/OSXOutputPlugin.cxx \
153 --replace kAudioObjectPropertyElement{Main,Master} \
154 --replace kAudioHardwareServiceDeviceProperty_Virtual{Main,Master}Volume
155 '';
156
157 # Otherwise, the meson log says:
158 #
159 # Program zip found: NO
160 nativeCheckInputs = [ zip ];
161
162 doCheck = true;
163
164 mesonAutoFeatures = "disabled";
165
166 outputs = [ "out" "doc" ]
167 ++ lib.optional (builtins.elem "documentation" features_) "man";
168
169 CXXFLAGS = lib.optionals stdenv.isDarwin [
170 "-D__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0"
171 ];
172
173 mesonFlags = [
174 "-Dtest=true"
175 "-Dmanpages=true"
176 "-Dhtml_manual=true"
177 ]
178 ++ map (x: "-D${x}=enabled") features_
179 ++ map (x: "-D${x}=disabled") (lib.subtractLists features_ knownFeatures)
180 ++ lib.optional (builtins.elem "zeroconf" features_)
181 "-Dzeroconf=avahi"
182 ++ lib.optional (builtins.elem "systemd" features_)
183 "-Dsystemd_system_unit_dir=etc/systemd/system";
184
185 passthru.tests.nixos = nixosTests.mpd;
186
187 meta = with lib; {
188 description = "A flexible, powerful daemon for playing music";
189 homepage = "https://www.musicpd.org/";
190 license = licenses.gpl2Only;
191 maintainers = with maintainers; [ astsmtl tobim ];
192 platforms = platforms.unix;
193 mainProgram = "mpd";
194
195 longDescription = ''
196 Music Player Daemon (MPD) is a flexible, powerful daemon for playing
197 music. Through plugins and libraries it can play a variety of sound
198 files while being controlled by its network protocol.
199 '';
200 };
201 };
202in
203{
204 mpd = run { };
205 mpd-small = run { features = [
206 "webdav" "curl" "mms" "bzip2" "zzip" "nfs"
207 "audiofile" "faad" "flac" "gme"
208 "mpg123" "opus" "vorbis" "vorbisenc"
209 "lame" "libsamplerate" "shout"
210 "libmpdclient" "id3tag" "expat" "pcre"
211 "yajl" "sqlite"
212 "soundcloud" "qobuz"
213 ] ++ lib.optionals stdenv.isLinux [
214 "alsa" "systemd" "syslog" "io_uring"
215 ] ++ lib.optionals (!stdenv.isDarwin) [
216 "mad" "jack"
217 ]; };
218 mpdWithFeatures = run;
219}