1{ lib, stdenv, fetchFromGitHub, fetchpatch, 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
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 # Output plugins
66 alsa = [ alsa-lib ];
67 jack = [ libjack2 ];
68 pipewire = [ pipewire ];
69 pulse = [ libpulseaudio ];
70 shout = [ libshout ];
71 # Commercial services
72 qobuz = [ curl libgcrypt yajl ];
73 soundcloud = [ curl yajl ];
74 # Client support
75 libmpdclient = [ libmpdclient ];
76 # Tag support
77 id3tag = [ libid3tag ];
78 # Misc
79 dbus = [ dbus ];
80 expat = [ expat ];
81 icu = [ icu ];
82 pcre = [ pcre2 ];
83 sqlite = [ sqlite ];
84 syslog = [ ];
85 systemd = [ systemd ];
86 yajl = [ yajl ];
87 zeroconf = [ avahi dbus ];
88 };
89
90 nativeFeatureDependencies = {
91 documentation = [ doxygen python3Packages.sphinx ];
92 };
93
94 run = { features ? null }:
95 let
96 # Disable platform specific features if needed
97 # using libmad to decode mp3 files on darwin is causing a segfault -- there
98 # is probably a solution, but I'm disabling it for now
99 platformMask = lib.optionals stdenv.isDarwin [ "mad" "pulse" "jack" "smbclient" ]
100 ++ lib.optionals (!stdenv.isLinux) [ "alsa" "pipewire" "io_uring" "systemd" "syslog" ];
101
102 knownFeatures = builtins.attrNames featureDependencies ++ builtins.attrNames nativeFeatureDependencies;
103 platformFeatures = lib.subtractLists platformMask knownFeatures;
104
105 features_ = if (features == null )
106 then platformFeatures
107 else
108 let unknown = lib.subtractLists knownFeatures features; in
109 if (unknown != [])
110 then throw "Unknown feature(s): ${lib.concatStringsSep " " unknown}"
111 else
112 let unsupported = lib.subtractLists platformFeatures features; in
113 if (unsupported != [])
114 then throw "Feature(s) ${lib.concatStringsSep " " unsupported} are not supported on ${stdenv.hostPlatform.system}"
115 else features;
116
117 in stdenv.mkDerivation rec {
118 pname = "mpd";
119 version = "0.23.13";
120
121 src = fetchFromGitHub {
122 owner = "MusicPlayerDaemon";
123 repo = "MPD";
124 rev = "v${version}";
125 sha256 = "sha256-OqSK4oo+Tx7zf7slHH/sRPCCUOBjyipsqDCPovw45Mo=";
126 };
127
128 buildInputs = [
129 glib
130 boost
131 fmt
132 # According to the configurePhase of meson, gtest is considered a
133 # runtime dependency. Quoting:
134 #
135 # Run-time dependency GTest found: YES 1.10.0
136 gtest
137 ]
138 ++ concatAttrVals features_ featureDependencies
139 ++ lib.optionals stdenv.isDarwin [ AudioToolbox AudioUnit ];
140
141 nativeBuildInputs = [
142 meson
143 ninja
144 pkg-config
145 ]
146 ++ concatAttrVals features_ nativeFeatureDependencies;
147
148 depsBuildBuild = [ buildPackages.stdenv.cc ];
149
150 patches = [
151 (fetchpatch {
152 name = "mpd-systemd-paths.patch";
153 url = "https://github.com/MusicPlayerDaemon/MPD/commit/838af929a0ae07e238d30cd7afc96cd7311457ef.patch";
154 hash = "sha256-dqMxoeyRwRuhrbDxXyw1EyqPwXxJt48MdkdTweL7M/k=";
155 })
156 ];
157
158 postPatch = lib.optionalString (stdenv.isDarwin && lib.versionOlder stdenv.targetPlatform.darwinSdkVersion "12.0") ''
159 substituteInPlace src/output/plugins/OSXOutputPlugin.cxx \
160 --replace kAudioObjectPropertyElement{Main,Master} \
161 --replace kAudioHardwareServiceDeviceProperty_Virtual{Main,Master}Volume
162 '';
163
164 # Otherwise, the meson log says:
165 #
166 # Program zip found: NO
167 nativeCheckInputs = [ zip ];
168
169 doCheck = true;
170
171 mesonAutoFeatures = "disabled";
172
173 outputs = [ "out" "doc" ]
174 ++ lib.optional (builtins.elem "documentation" features_) "man";
175
176 CXXFLAGS = lib.optionals stdenv.isDarwin [
177 "-D__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0"
178 ];
179
180 mesonFlags = [
181 "-Dtest=true"
182 "-Dmanpages=true"
183 "-Dhtml_manual=true"
184 ]
185 ++ map (x: "-D${x}=enabled") features_
186 ++ map (x: "-D${x}=disabled") (lib.subtractLists features_ knownFeatures)
187 ++ lib.optional (builtins.elem "zeroconf" features_)
188 "-Dzeroconf=avahi"
189 ++ lib.optional (builtins.elem "systemd" features_)
190 "-Dsystemd_system_unit_dir=etc/systemd/system";
191
192 passthru.tests.nixos = nixosTests.mpd;
193
194 meta = with lib; {
195 description = "A flexible, powerful daemon for playing music";
196 homepage = "https://www.musicpd.org/";
197 license = licenses.gpl2Only;
198 maintainers = with maintainers; [ astsmtl ehmry tobim ];
199 platforms = platforms.unix;
200
201 longDescription = ''
202 Music Player Daemon (MPD) is a flexible, powerful daemon for playing
203 music. Through plugins and libraries it can play a variety of sound
204 files while being controlled by its network protocol.
205 '';
206 };
207 };
208in
209{
210 mpd = run { };
211 mpd-small = run { features = [
212 "webdav" "curl" "mms" "bzip2" "zzip" "nfs"
213 "audiofile" "faad" "flac" "gme"
214 "mpg123" "opus" "vorbis" "vorbisenc"
215 "lame" "libsamplerate" "shout"
216 "libmpdclient" "id3tag" "expat" "pcre"
217 "yajl" "sqlite"
218 "soundcloud" "qobuz"
219 ] ++ lib.optionals stdenv.isLinux [
220 "alsa" "systemd" "syslog" "io_uring"
221 ] ++ lib.optionals (!stdenv.isDarwin) [
222 "mad" "jack"
223 ]; };
224 mpdWithFeatures = run;
225}