1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-11-08 19:46:05 +01:00
home-manager/modules/services/mpd.nix
2025-07-25 12:44:09 -05:00

238 lines
6.8 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkIf mkOption types;
cfg = config.services.mpd;
in
{
options = {
services.mpd = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable MPD, the music player daemon.
'';
};
package = lib.mkPackageOption pkgs "mpd" { };
musicDirectory = mkOption {
type = with types; either path str;
defaultText = lib.literalExpression ''
''${home.homeDirectory}/music if state version < 22.11
''${xdg.userDirs.music} if xdg.userDirs.enable == true
undefined otherwise
'';
apply = toString; # Prevent copies to Nix store.
description = ''
The directory where mpd reads music from.
If [](#opt-xdg.userDirs.enable) is
`true` then the defined XDG music directory is used.
Otherwise, you must explicitly specify a value.
'';
};
playlistDirectory = mkOption {
type = types.path;
default = "${cfg.dataDir}/playlists";
defaultText = "\${dataDir}/playlists";
apply = toString; # Prevent copies to Nix store.
description = ''
The directory where mpd stores playlists.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra directives added to the end of MPD's configuration
file, {file}`mpd.conf`. Basic configuration
like file location and uid/gid is added automatically to the
beginning of the file. For available options see
{manpage}`mpd.conf(5)`.
'';
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--verbose" ];
description = ''
Extra command-line arguments to pass to MPD.
'';
};
dataDir = mkOption {
type = types.path;
default = "${config.xdg.dataHome}/mpd";
defaultText = "$XDG_DATA_HOME/mpd";
apply = toString; # Prevent copies to Nix store.
description = ''
The directory where MPD stores its state, tag cache,
playlists etc.
'';
};
network = {
startWhenNeeded = mkOption {
type = types.bool;
default = false;
visible = pkgs.stdenv.hostPlatform.isLinux;
readOnly = pkgs.stdenv.hostPlatform.isDarwin;
description = ''
Enable systemd socket activation. This is only supported on Linux.
'';
};
listenAddress = mkOption {
type = types.str;
default = "127.0.0.1";
example = "any";
description = ''
The address for the daemon to listen on.
Use `any` to listen on all addresses.
'';
};
port = mkOption {
type = types.port;
default = 6600;
description = ''
The TCP port on which the the daemon will listen.
'';
};
};
dbFile = mkOption {
type = types.nullOr types.str;
default = "${cfg.dataDir}/tag_cache";
defaultText = "\${dataDir}/tag_cache";
description = ''
The path to MPD's database. If set to
`null` the parameter is omitted from the
configuration.
'';
};
};
};
config =
let
mpdConf = pkgs.writeText "mpd.conf" (
''
music_directory "${cfg.musicDirectory}"
playlist_directory "${cfg.playlistDirectory}"
''
+ lib.optionalString (cfg.dbFile != null) ''
db_file "${cfg.dbFile}"
''
+ lib.optionalString (pkgs.stdenv.hostPlatform.isDarwin) ''
log_file "${config.home.homeDirectory}/Library/Logs/mpd/log.txt"
''
+ ''
state_file "${cfg.dataDir}/state"
sticker_file "${cfg.dataDir}/sticker.sql"
''
+ lib.optionalString (cfg.network.listenAddress != "any") ''
bind_to_address "${cfg.network.listenAddress}"
''
+ lib.optionalString (cfg.network.port != 6600) ''
port "${toString cfg.network.port}"
''
+ lib.optionalString (cfg.extraConfig != "") ''
${cfg.extraConfig}
''
);
in
mkIf cfg.enable {
home.packages = [ cfg.package ];
services.mpd = lib.mkMerge [
(mkIf (lib.versionAtLeast config.home.stateVersion "22.11" && config.xdg.userDirs.enable) {
musicDirectory = lib.mkOptionDefault config.xdg.userDirs.music;
})
(mkIf (lib.versionOlder config.home.stateVersion "22.11") {
musicDirectory = lib.mkOptionDefault "${config.home.homeDirectory}/music";
})
];
systemd.user = lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
services.mpd = {
Unit = lib.mkMerge [
{
Description = "Music Player Daemon";
After = [
"network.target"
"sound.target"
];
}
(mkIf cfg.network.startWhenNeeded {
Requires = [ "mpd.socket" ];
After = [ "mpd.socket" ];
})
];
Install = mkIf (!cfg.network.startWhenNeeded) {
WantedBy = [ "default.target" ];
};
Service = {
Environment = [ "PATH=${config.home.profileDirectory}/bin" ];
ExecStart = "${cfg.package}/bin/mpd --no-daemon ${mpdConf} ${lib.escapeShellArgs cfg.extraArgs}";
Type = "notify";
ExecStartPre = ''${pkgs.bash}/bin/bash -c "${pkgs.coreutils}/bin/mkdir -p '${cfg.dataDir}' '${cfg.playlistDirectory}'"'';
};
};
sockets.mpd = mkIf cfg.network.startWhenNeeded {
Socket = {
ListenStream =
let
listen =
if cfg.network.listenAddress == "any" then
toString cfg.network.port
else
"${cfg.network.listenAddress}:${toString cfg.network.port}";
in
[
listen
"%t/mpd/socket"
];
Backlog = 5;
KeepAlive = true;
};
Install = {
WantedBy = [ "sockets.target" ];
};
};
};
launchd.agents.mpd = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
enable = true;
config = {
ProgramArguments = [
(lib.getExe cfg.package)
"--no-daemon"
"${mpdConf}"
]
++ cfg.extraArgs;
KeepAlive = true;
ProcessType = "Interactive";
};
};
};
}