nixos/pulseaudio: tcp streaming & zeroconf
Adds options for tcp streaming and avahi zeroconf support (so that the server can be easily found by clients). There is also an option to allow anonymous clients to stream to the server (by default pulseaudio uses a cookie mechanism, see manpage).
This commit is contained in:
parent
fa03b541b2
commit
5074a79937
@ -9,11 +9,36 @@ let
|
|||||||
|
|
||||||
systemWide = cfg.enable && cfg.systemWide;
|
systemWide = cfg.enable && cfg.systemWide;
|
||||||
nonSystemWide = cfg.enable && !cfg.systemWide;
|
nonSystemWide = cfg.enable && !cfg.systemWide;
|
||||||
|
hasZeroconf = let z = cfg.zeroconf; in z.publish.enable || z.discovery.enable;
|
||||||
|
|
||||||
|
overriddenPackage = cfg.package.override
|
||||||
|
(optionalAttrs hasZeroconf { zeroconfSupport = true; });
|
||||||
|
binary = "${getBin overriddenPackage}/bin/pulseaudio";
|
||||||
|
binaryNoDaemon = "${binary} --daemonize=no";
|
||||||
|
|
||||||
# Forces 32bit pulseaudio and alsaPlugins to be built/supported for apps
|
# Forces 32bit pulseaudio and alsaPlugins to be built/supported for apps
|
||||||
# using 32bit alsa on 64bit linux.
|
# using 32bit alsa on 64bit linux.
|
||||||
enable32BitAlsaPlugins = cfg.support32Bit && stdenv.isx86_64 && (pkgs_i686.alsaLib != null && pkgs_i686.libpulseaudio != null);
|
enable32BitAlsaPlugins = cfg.support32Bit && stdenv.isx86_64 && (pkgs_i686.alsaLib != null && pkgs_i686.libpulseaudio != null);
|
||||||
|
|
||||||
|
|
||||||
|
myConfigFile =
|
||||||
|
let
|
||||||
|
addModuleIf = cond: mod: optionalString cond "load-module ${mod}";
|
||||||
|
allAnon = optional cfg.tcp.anonymousClients.allowAll "auth-anonymous=1";
|
||||||
|
ipAnon = let a = cfg.tcp.anonymousClients.allowedIpRanges;
|
||||||
|
in optional (a != []) ''auth-ip-acl=${concatStringsSep ";" a}'';
|
||||||
|
in writeTextFile {
|
||||||
|
name = "default.pa";
|
||||||
|
text = ''
|
||||||
|
.include ${cfg.configFile}
|
||||||
|
${addModuleIf cfg.zeroconf.publish.enable "module-zeroconf-publish"}
|
||||||
|
${addModuleIf cfg.zeroconf.discovery.enable "module-zeroconf-discover"}
|
||||||
|
${addModuleIf cfg.tcp.enable (concatStringsSep " "
|
||||||
|
([ "load-module module-native-protocol-tcp" ] ++ allAnon ++ ipAnon))}
|
||||||
|
${cfg.extraConfig}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
ids = config.ids;
|
ids = config.ids;
|
||||||
|
|
||||||
uid = ids.uids.pulseaudio;
|
uid = ids.uids.pulseaudio;
|
||||||
@ -26,7 +51,7 @@ let
|
|||||||
# are built with PulseAudio support (like KDE).
|
# are built with PulseAudio support (like KDE).
|
||||||
clientConf = writeText "client.conf" ''
|
clientConf = writeText "client.conf" ''
|
||||||
autospawn=${if nonSystemWide then "yes" else "no"}
|
autospawn=${if nonSystemWide then "yes" else "no"}
|
||||||
${optionalString nonSystemWide "daemon-binary=${cfg.package.out}/bin/pulseaudio"}
|
${optionalString nonSystemWide "daemon-binary=${binary}"}
|
||||||
${cfg.extraClientConf}
|
${cfg.extraClientConf}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
@ -44,7 +69,7 @@ let
|
|||||||
hint.description "Default Audio Device (via PulseAudio)"
|
hint.description "Default Audio Device (via PulseAudio)"
|
||||||
}
|
}
|
||||||
ctl_type.pulse {
|
ctl_type.pulse {
|
||||||
libs.native = ${alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ;
|
libs.native = ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ;
|
||||||
${lib.optionalString enable32BitAlsaPlugins
|
${lib.optionalString enable32BitAlsaPlugins
|
||||||
"libs.32Bit = ${pkgs_i686.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ;"}
|
"libs.32Bit = ${pkgs_i686.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ;"}
|
||||||
}
|
}
|
||||||
@ -89,16 +114,25 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
configFile = mkOption {
|
configFile = mkOption {
|
||||||
type = types.path;
|
type = types.nullOr types.path;
|
||||||
description = ''
|
description = ''
|
||||||
The path to the configuration the PulseAudio server
|
The path to the default configuration options the PulseAudio server
|
||||||
should use. By default, the "default.pa" configuration
|
should use. By default, the "default.pa" configuration
|
||||||
from the PulseAudio distribution is used.
|
from the PulseAudio distribution is used.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
description = ''
|
||||||
|
Literal string to append to <literal>configFile</literal>
|
||||||
|
and the config file generated by the pulseaudio module.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
extraClientConf = mkOption {
|
extraClientConf = mkOption {
|
||||||
type = types.str;
|
type = types.lines;
|
||||||
default = "";
|
default = "";
|
||||||
description = ''
|
description = ''
|
||||||
Extra configuration appended to pulse/client.conf file.
|
Extra configuration appended to pulse/client.conf file.
|
||||||
@ -127,6 +161,31 @@ in {
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
zeroconf = {
|
||||||
|
discovery.enable =
|
||||||
|
mkEnableOption "discovery of pulseaudio sinks in the local network";
|
||||||
|
publish.enable =
|
||||||
|
mkEnableOption "publishing the pulseaudio sink in the local network";
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO: enable by default?
|
||||||
|
tcp = {
|
||||||
|
enable = mkEnableOption "tcp streaming support";
|
||||||
|
|
||||||
|
anonymousClients = {
|
||||||
|
allowAll = mkEnableOption "all anonymous clients to stream to the server";
|
||||||
|
allowedIpRanges = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = literalExample ''[ "127.0.0.1" "192.168.1.0/24" ]'';
|
||||||
|
description = ''
|
||||||
|
A list of IP subnets that are allowed to stream to the server.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -139,11 +198,11 @@ in {
|
|||||||
source = clientConf;
|
source = clientConf;
|
||||||
};
|
};
|
||||||
|
|
||||||
hardware.pulseaudio.configFile = mkDefault "${getBin cfg.package}/etc/pulse/default.pa";
|
hardware.pulseaudio.configFile = mkDefault "${getBin overriddenPackage}/etc/pulse/default.pa";
|
||||||
}
|
}
|
||||||
|
|
||||||
(mkIf cfg.enable {
|
(mkIf cfg.enable {
|
||||||
environment.systemPackages = [ cfg.package ];
|
environment.systemPackages = [ overriddenPackage ];
|
||||||
|
|
||||||
environment.etc = singleton {
|
environment.etc = singleton {
|
||||||
target = "asound.conf";
|
target = "asound.conf";
|
||||||
@ -152,12 +211,21 @@ in {
|
|||||||
|
|
||||||
# Allow PulseAudio to get realtime priority using rtkit.
|
# Allow PulseAudio to get realtime priority using rtkit.
|
||||||
security.rtkit.enable = true;
|
security.rtkit.enable = true;
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
(mkIf hasZeroconf {
|
||||||
|
services.avahi.enable = true;
|
||||||
|
})
|
||||||
|
(mkIf cfg.zeroconf.publish.enable {
|
||||||
|
services.avahi.publish.enable = true;
|
||||||
|
services.avahi.publish.userServices = true;
|
||||||
})
|
})
|
||||||
|
|
||||||
(mkIf nonSystemWide {
|
(mkIf nonSystemWide {
|
||||||
environment.etc = singleton {
|
environment.etc = singleton {
|
||||||
target = "pulse/default.pa";
|
target = "pulse/default.pa";
|
||||||
source = cfg.configFile;
|
source = myConfigFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.user = {
|
systemd.user = {
|
||||||
@ -167,10 +235,11 @@ in {
|
|||||||
wantedBy = [ "default.target" ];
|
wantedBy = [ "default.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "notify";
|
Type = "notify";
|
||||||
ExecStart = "${getBin cfg.package}/bin/pulseaudio --daemonize=no";
|
ExecStart = binaryNoDaemon;
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
};
|
};
|
||||||
environment = { DISPLAY = ":${toString config.services.xserver.display}"; };
|
environment = { DISPLAY = ":${toString config.services.xserver.display}"; };
|
||||||
|
restartIfChanged = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
sockets.pulseaudio = {
|
sockets.pulseaudio = {
|
||||||
@ -205,7 +274,7 @@ in {
|
|||||||
environment.PULSE_RUNTIME_PATH = stateDir;
|
environment.PULSE_RUNTIME_PATH = stateDir;
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "notify";
|
Type = "notify";
|
||||||
ExecStart = "${getBin cfg.package}/bin/pulseaudio --daemonize=no --log-level=${cfg.daemon.logLevel} --system -n --file=${cfg.configFile}";
|
ExecStart = "${binaryNoDaemon} --log-level=${cfg.daemon.logLevel} --system -n --file=${myConfigFile}";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user