1 { config, lib, options, pkgs, ... }:
6 cfg = config.services.mpdscribble;
7 mpdCfg = config.services.mpd;
8 mpdOpt = options.services.mpd;
11 "last.fm" = "http://post.audioscrobbler.com";
12 "libre.fm" = "http://turtle.libre.fm";
13 "jamendo" = "http://postaudioscrobbler.jamendo.com";
14 "listenbrainz" = "http://proxy.listenbrainz.org";
17 mkSection = secname: secCfg: ''
20 username = ${secCfg.username}
21 password = {{${secname}_PASSWORD}}
22 journal = /var/lib/mpdscribble/${secname}.journal
25 endpoints = concatStringsSep "\n" (mapAttrsToList mkSection cfg.endpoints);
26 cfgTemplate = pkgs.writeText "mpdscribble.conf" ''
27 ## This file was automatically genenrated by NixOS and will be overwritten.
28 ## Do not edit. Edit your NixOS configuration instead.
30 ## mpdscribble - an audioscrobbler for the Music Player Daemon.
31 ## http://mpd.wikia.com/wiki/Client:mpdscribble
34 ${optionalString (cfg.proxy != null) "proxy = ${cfg.proxy}"}
36 # The location of the mpdscribble log file. The special value
37 # "syslog" makes mpdscribble use the local syslog daemon. On most
38 # systems, log messages will appear in /var/log/daemon.log then.
39 # "-" means log to stderr (the current terminal).
42 # How verbose mpdscribble's logging should be. Default is 1.
43 verbose = ${toString cfg.verbose}
45 # How often should mpdscribble save the journal file? [seconds]
46 journal_interval = ${toString cfg.journalInterval}
48 # The host running MPD, possibly protected by a password
49 # ([PASSWORD@]HOSTNAME).
50 host = ${(optionalString (cfg.passwordFile != null) "{{MPD_PASSWORD}}@") + cfg.host}
52 # The port that the MPD listens on and mpdscribble should try to
54 port = ${toString cfg.port}
59 cfgFile = "/run/mpdscribble/mpdscribble.conf";
61 replaceSecret = secretFile: placeholder: targetFile:
62 optionalString (secretFile != null) ''
63 ${pkgs.replace-secret}/bin/replace-secret '${placeholder}' '${secretFile}' '${targetFile}' '';
65 preStart = pkgs.writeShellScript "mpdscribble-pre-start" ''
66 cp -f "${cfgTemplate}" "${cfgFile}"
67 ${replaceSecret cfg.passwordFile "{{MPD_PASSWORD}}" cfgFile}
68 ${concatStringsSep "\n" (mapAttrsToList (secname: cfg:
69 replaceSecret cfg.passwordFile "{{${secname}_PASSWORD}}" cfgFile)
73 localMpd = (cfg.host == "localhost" || cfg.host == "127.0.0.1");
78 options.services.mpdscribble = {
80 enable = mkEnableOption "mpdscribble, an MPD client which submits info about tracks being played to Last.fm (formerly AudioScrobbler)";
84 type = types.nullOr types.str;
94 Log level for the mpdscribble daemon.
98 journalInterval = mkOption {
103 How often should mpdscribble save the journal file? [seconds]
108 default = (if mpdCfg.network.listenAddress != "any" then
109 mpdCfg.network.listenAddress
112 defaultText = literalExpression ''
113 if config.${mpdOpt.network.listenAddress} != "any"
114 then config.${mpdOpt.network.listenAddress}
119 Host for the mpdscribble daemon to search for a mpd daemon on.
123 passwordFile = mkOption {
124 default = if localMpd then
126 (c: any (x: x == "read") c.permissions)
127 { passwordFile = null; }
128 mpdCfg.credentials).passwordFile
131 defaultText = literalMD ''
132 The first password file with read access configured for MPD when using a local instance,
135 type = types.nullOr types.str;
137 File containing the password for the mpd daemon.
138 If there is a local mpd configured using {option}`services.mpd.credentials`
139 the default is automatically set to a matching passwordFile of the local mpd.
144 default = mpdCfg.network.port;
145 defaultText = literalExpression "config.${mpdOpt.network.port}";
148 Port for the mpdscribble daemon to search for a mpd daemon on.
152 endpoints = mkOption {
154 endpoint = { name, ... }: {
158 default = endpointUrls.${name} or "";
159 description = "The url endpoint where the scrobble API is listening.";
161 username = mkOption {
164 Username for the scrobble service.
167 passwordFile = mkOption {
168 type = types.nullOr types.str;
169 description = "File containing the password, either as MD5SUM or cleartext.";
173 in types.attrsOf (types.submodule endpoint));
178 passwordFile = "/run/secrets/lastfm_password";
182 Endpoints to scrobble to.
183 If the endpoint is one of "${
184 concatStringsSep "\", \"" (attrNames endpointUrls)
185 }" the url is set automatically.
191 ###### implementation
193 config = mkIf cfg.enable {
194 systemd.services.mpdscribble = {
195 after = [ "network.target" ] ++ (optional localMpd "mpd.service");
196 description = "mpdscribble mpd scrobble client";
197 wantedBy = [ "multi-user.target" ];
200 StateDirectory = "mpdscribble";
201 RuntimeDirectory = "mpdscribble";
202 RuntimeDirectoryMode = "700";
203 # TODO use LoadCredential= instead of running preStart with full privileges?
204 ExecStartPre = "+${preStart}";
206 "${pkgs.mpdscribble}/bin/mpdscribble --no-daemon --conf ${cfgFile}";