Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 01ad1729214c
Choose a base ref
...
head repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 502a4263a34a
Choose a head ref
  • 2 commits
  • 2 files changed
  • 2 contributors

Commits on Mar 6, 2019

  1. nixos/snapserver: init

    A nixos module for configuring the server side of pkgs.snapcast.
    The module is named "snapserver" following upstream convention.
    This commit does not provide module for the corresponding client.
    
    Fix handling of port and controlPort
    
    Fix stream uri generation & address review
    
    Remove unused streams options & add description
    
    Add missing description & Remove default fs path
    
    Use types.port for ports & formatting improvements
    
    Force mpd and mopidy to wait for snapserver
    tobim committed Mar 6, 2019
    Copy the full SHA
    085751b View commit details
  2. Merge pull request #55936 from tobim/modules/snapserver

    nixos/snapserver: init
    infinisil authored Mar 6, 2019

    Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    502a426 View commit details
Showing with 218 additions and 0 deletions.
  1. +1 −0 nixos/modules/module-list.nix
  2. +217 −0 nixos/modules/services/audio/snapserver.nix
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
@@ -182,6 +182,7 @@
./services/audio/mpd.nix
./services/audio/mopidy.nix
./services/audio/slimserver.nix
./services/audio/snapserver.nix
./services/audio/squeezelite.nix
./services/audio/ympd.nix
./services/backup/bacula.nix
217 changes: 217 additions & 0 deletions nixos/modules/services/audio/snapserver.nix
Original file line number Diff line number Diff line change
@@ -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 ];
};

}