nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at master 219 lines 6.8 kB view raw
1{ 2 config, 3 lib, 4 options, 5 pkgs, 6 ... 7}: 8let 9 cfg = config.services.mpdscribble; 10 mpdCfg = config.services.mpd; 11 12 endpointUrls = { 13 "last.fm" = "http://post.audioscrobbler.com"; 14 "libre.fm" = "http://turtle.libre.fm"; 15 "jamendo" = "http://postaudioscrobbler.jamendo.com"; 16 "listenbrainz" = "http://proxy.listenbrainz.org"; 17 }; 18 19 mkSection = secname: secCfg: '' 20 [${secname}] 21 url = ${secCfg.url} 22 username = ${secCfg.username} 23 password = {{${secname}_PASSWORD}} 24 journal = /var/lib/mpdscribble/${secname}.journal 25 ''; 26 27 endpoints = lib.concatStringsSep "\n" (lib.mapAttrsToList mkSection cfg.endpoints); 28 cfgTemplate = pkgs.writeText "mpdscribble.conf" '' 29 ## This file was automatically genenrated by NixOS and will be overwritten. 30 ## Do not edit. Edit your NixOS configuration instead. 31 32 ## mpdscribble - an audioscrobbler for the Music Player Daemon. 33 ## http://mpd.wikia.com/wiki/Client:mpdscribble 34 35 # HTTP proxy URL. 36 ${lib.optionalString (cfg.proxy != null) "proxy = ${cfg.proxy}"} 37 38 # The location of the mpdscribble log file. The special value 39 # "syslog" makes mpdscribble use the local syslog daemon. On most 40 # systems, log messages will appear in /var/log/daemon.log then. 41 # "-" means log to stderr (the current terminal). 42 log = - 43 44 # How verbose mpdscribble's logging should be. Default is 1. 45 verbose = ${toString cfg.verbose} 46 47 # How often should mpdscribble save the journal file? [seconds] 48 journal_interval = ${toString cfg.journalInterval} 49 50 # The host running MPD, possibly protected by a password 51 # ([PASSWORD@]HOSTNAME). 52 host = ${(lib.optionalString (cfg.passwordFile != null) "{{MPD_PASSWORD}}@") + cfg.host} 53 54 # The port that the MPD listens on and mpdscribble should try to 55 # connect to. 56 port = ${toString cfg.port} 57 58 ${endpoints} 59 ''; 60 61 cfgFile = "/run/mpdscribble/mpdscribble.conf"; 62 63 replaceSecret = 64 secretFile: placeholder: targetFile: 65 lib.optionalString ( 66 secretFile != null 67 ) "${pkgs.replace-secret}/bin/replace-secret '${placeholder}' '${secretFile}' '${targetFile}' "; 68 69 preStart = pkgs.writeShellScript "mpdscribble-pre-start" '' 70 cp -f "${cfgTemplate}" "${cfgFile}" 71 ${replaceSecret cfg.passwordFile "{{MPD_PASSWORD}}" cfgFile} 72 ${lib.concatStringsSep "\n" ( 73 lib.mapAttrsToList ( 74 secname: cfg: replaceSecret cfg.passwordFile "{{${secname}_PASSWORD}}" cfgFile 75 ) cfg.endpoints 76 )} 77 ''; 78 79 localMpd = (cfg.host == "localhost" || cfg.host == "127.0.0.1"); 80 81in 82{ 83 ###### interface 84 85 options.services.mpdscribble = { 86 87 enable = lib.mkEnableOption "mpdscribble, an MPD client which submits info about tracks being played to Last.fm (formerly AudioScrobbler)"; 88 89 proxy = lib.mkOption { 90 default = null; 91 type = lib.types.nullOr lib.types.str; 92 description = '' 93 HTTP proxy URL. 94 ''; 95 }; 96 97 verbose = lib.mkOption { 98 default = 1; 99 type = lib.types.int; 100 description = '' 101 Log level for the mpdscribble daemon. 102 ''; 103 }; 104 105 journalInterval = lib.mkOption { 106 default = 600; 107 example = 60; 108 type = lib.types.int; 109 description = '' 110 How often should mpdscribble save the journal file? [seconds] 111 ''; 112 }; 113 114 host = lib.mkOption { 115 default = ( 116 if mpdCfg.settings.bind_to_address != "any" then mpdCfg.settings.bind_to_address else "localhost" 117 ); 118 defaultText = lib.literalExpression '' 119 if config.services.mpd.settings.bind_to_address != "any" 120 then config.services.mpd.settings.bind_to_address 121 else "localhost" 122 ''; 123 type = lib.types.str; 124 description = '' 125 Host for the mpdscribble daemon to search for a mpd daemon on. 126 ''; 127 }; 128 129 passwordFile = lib.mkOption { 130 default = 131 if localMpd then 132 (lib.findFirst (c: lib.elem "read" c.permissions) { 133 passwordFile = null; 134 } mpdCfg.credentials).passwordFile 135 else 136 null; 137 defaultText = lib.literalMD '' 138 The first password file with read access configured for MPD when using a local instance, 139 otherwise `null`. 140 ''; 141 type = lib.types.nullOr lib.types.str; 142 description = '' 143 File containing the password for the mpd daemon. 144 If there is a local mpd configured using {option}`services.mpd.credentials` 145 the default is automatically set to a matching passwordFile of the local mpd. 146 ''; 147 }; 148 149 port = lib.mkOption { 150 default = mpdCfg.settings.port; 151 defaultText = lib.literalExpression "config.services.mpd.settings.port"; 152 type = lib.types.port; 153 description = '' 154 Port for the mpdscribble daemon to search for a mpd daemon on. 155 ''; 156 }; 157 158 endpoints = lib.mkOption { 159 type = ( 160 let 161 endpoint = 162 { name, ... }: 163 { 164 options = { 165 url = lib.mkOption { 166 type = lib.types.str; 167 default = endpointUrls.${name} or ""; 168 description = "The url endpoint where the scrobble API is listening."; 169 }; 170 username = lib.mkOption { 171 type = lib.types.str; 172 description = '' 173 Username for the scrobble service. 174 ''; 175 }; 176 passwordFile = lib.mkOption { 177 type = lib.types.nullOr lib.types.str; 178 description = "File containing the password, either as MD5SUM or cleartext."; 179 }; 180 }; 181 }; 182 in 183 lib.types.attrsOf (lib.types.submodule endpoint) 184 ); 185 default = { }; 186 example = { 187 "last.fm" = { 188 username = "foo"; 189 passwordFile = "/run/secrets/lastfm_password"; 190 }; 191 }; 192 description = '' 193 Endpoints to scrobble to. 194 If the endpoint is one of "${lib.concatStringsSep "\", \"" (lib.attrNames endpointUrls)}" the url is set automatically. 195 ''; 196 }; 197 198 }; 199 200 ###### implementation 201 202 config = lib.mkIf cfg.enable { 203 systemd.services.mpdscribble = { 204 after = [ "network.target" ] ++ (lib.optional localMpd "mpd.service"); 205 description = "mpdscribble mpd scrobble client"; 206 wantedBy = [ "multi-user.target" ]; 207 serviceConfig = { 208 DynamicUser = true; 209 StateDirectory = "mpdscribble"; 210 RuntimeDirectory = "mpdscribble"; 211 RuntimeDirectoryMode = "700"; 212 # TODO use LoadCredential= instead of running preStart with full privileges? 213 ExecStartPre = "+${preStart}"; 214 ExecStart = "${pkgs.mpdscribble}/bin/mpdscribble --no-daemon --conf ${cfgFile}"; 215 }; 216 }; 217 }; 218 219}