Merge pull request #55936 from tobim/modules/snapserver
nixos/snapserver: init
This commit is contained in:
commit
502a4263a3
@ -182,6 +182,7 @@
|
|||||||
./services/audio/mpd.nix
|
./services/audio/mpd.nix
|
||||||
./services/audio/mopidy.nix
|
./services/audio/mopidy.nix
|
||||||
./services/audio/slimserver.nix
|
./services/audio/slimserver.nix
|
||||||
|
./services/audio/snapserver.nix
|
||||||
./services/audio/squeezelite.nix
|
./services/audio/squeezelite.nix
|
||||||
./services/audio/ympd.nix
|
./services/audio/ympd.nix
|
||||||
./services/backup/bacula.nix
|
./services/backup/bacula.nix
|
||||||
|
217
nixos/modules/services/audio/snapserver.nix
Normal file
217
nixos/modules/services/audio/snapserver.nix
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
package = "snapcast";
|
||||||
|
name = "snapserver";
|
||||||
|
|
||||||
|
cfg = config.services.snapserver;
|
||||||
|
|
||||||
|
# Using types.nullOr to inherit upstream defaults.
|
||||||
|
sampleFormat = mkOption {
|
||||||
|
type = with types; nullOr str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Default sample format.
|
||||||
|
'';
|
||||||
|
example = "48000:16:2";
|
||||||
|
};
|
||||||
|
|
||||||
|
codec = mkOption {
|
||||||
|
type = with types; nullOr str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Default audio compression method.
|
||||||
|
'';
|
||||||
|
example = "flac";
|
||||||
|
};
|
||||||
|
|
||||||
|
streamToOption = name: opt:
|
||||||
|
let
|
||||||
|
os = val:
|
||||||
|
optionalString (val != null) "${val}";
|
||||||
|
os' = prefixx: val:
|
||||||
|
optionalString (val != null) (prefixx + "${val}");
|
||||||
|
flatten = key: value:
|
||||||
|
"&${key}=${value}";
|
||||||
|
in
|
||||||
|
"-s ${opt.type}://" + os opt.location + "?" + os' "name=" name
|
||||||
|
+ concatStrings (mapAttrsToList flatten opt.query);
|
||||||
|
|
||||||
|
optionalNull = val: ret:
|
||||||
|
optional (val != null) ret;
|
||||||
|
|
||||||
|
optionString = concatStringsSep " " (mapAttrsToList streamToOption cfg.streams
|
||||||
|
++ ["-p ${toString cfg.port}"]
|
||||||
|
++ ["--controlPort ${toString cfg.controlPort}"]
|
||||||
|
++ optionalNull cfg.sampleFormat "--sampleFormat ${cfg.sampleFormat}"
|
||||||
|
++ optionalNull cfg.codec "-c ${cfg.codec}"
|
||||||
|
++ optionalNull cfg.streamBuffer "--streamBuffer ${cfg.streamBuffer}"
|
||||||
|
++ optionalNull cfg.buffer "-b ${cfg.buffer}"
|
||||||
|
++ optional cfg.sendToMuted "--sendToMuted");
|
||||||
|
|
||||||
|
in {
|
||||||
|
|
||||||
|
###### interface
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.snapserver = {
|
||||||
|
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to enable snapserver.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 1704;
|
||||||
|
description = ''
|
||||||
|
The port that snapclients can connect to.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
controlPort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 1705;
|
||||||
|
description = ''
|
||||||
|
The port for control connections (JSON-RPC).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to automatically open the specified ports in the firewall.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
inherit sampleFormat;
|
||||||
|
inherit codec;
|
||||||
|
|
||||||
|
streams = mkOption {
|
||||||
|
type = with types; attrsOf (submodule {
|
||||||
|
options = {
|
||||||
|
location = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
description = ''
|
||||||
|
The location of the pipe.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
type = mkOption {
|
||||||
|
type = types.enum [ "pipe" "file" "process" "spotify" "airplay" ];
|
||||||
|
default = "pipe";
|
||||||
|
description = ''
|
||||||
|
The type of input stream.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
query = mkOption {
|
||||||
|
type = attrsOf str;
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
Key-value pairs that convey additional parameters about a stream.
|
||||||
|
'';
|
||||||
|
example = literalExample ''
|
||||||
|
# for type == "pipe":
|
||||||
|
{
|
||||||
|
mode = "listen";
|
||||||
|
};
|
||||||
|
# for type == "process":
|
||||||
|
{
|
||||||
|
params = "--param1 --param2";
|
||||||
|
logStderr = "true";
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
inherit sampleFormat;
|
||||||
|
inherit codec;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = { default = {}; };
|
||||||
|
description = ''
|
||||||
|
The definition for an input source.
|
||||||
|
'';
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
mpd = {
|
||||||
|
type = "pipe";
|
||||||
|
location = "/run/snapserver/mpd";
|
||||||
|
sampleFormat = "48000:16:2";
|
||||||
|
codec = "pcm";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
streamBuffer = mkOption {
|
||||||
|
type = with types; nullOr int;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Stream read (input) buffer in ms.
|
||||||
|
'';
|
||||||
|
example = 20;
|
||||||
|
};
|
||||||
|
|
||||||
|
buffer = mkOption {
|
||||||
|
type = with types; nullOr int;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Network buffer in ms.
|
||||||
|
'';
|
||||||
|
example = 1000;
|
||||||
|
};
|
||||||
|
|
||||||
|
sendToMuted = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Send audio to muted clients.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
systemd.services.snapserver = {
|
||||||
|
after = [ "network.target" ];
|
||||||
|
description = "Snapserver";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
before = [ "mpd.service" "mopidy.service" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
DynamicUser = true;
|
||||||
|
ExecStart = "${pkgs.snapcast}/bin/snapserver --daemon ${optionString}";
|
||||||
|
Type = "forking";
|
||||||
|
LimitRTPRIO = 50;
|
||||||
|
LimitRTTIME = "infinity";
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
PIDFile = "/run/${name}/pid";
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX";
|
||||||
|
RestrictNamespaces = true;
|
||||||
|
RuntimeDirectory = name;
|
||||||
|
StateDirectory = name;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = optionals cfg.openFirewall [ cfg.port cfg.controlPort ];
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
maintainers = with maintainers; [ tobim ];
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user