diff --git a/modules/config/pulseaudio.nix b/modules/config/pulseaudio.nix index 5dffd9d3afba..1043cca2be7e 100644 --- a/modules/config/pulseaudio.nix +++ b/modules/config/pulseaudio.nix @@ -1,92 +1,148 @@ { config, pkgs, ... }: with pkgs.lib; +with pkgs; -let cfg = config.hardware.pulseaudio; in +let -{ + cfg = config.hardware.pulseaudio; + + uid = config.ids.uids.pulseaudio; + gid = config.ids.gids.pulseaudio; + + pulseRuntimePath = "/var/run/pulse"; + + # Create pulse/client.conf even if PulseAudio is disabled so + # that we can disable the autospawn feature in programs that + # are built with PulseAudio support (like KDE). + clientConf = writeText "client.conf" '' + autospawn=${if (cfg.enable && !cfg.systemWide) then "yes" else "no"} + ${optionalString (cfg.enable && !cfg.systemWide) + "daemon-binary=${cfg.package}/bin/pulseaudio"} + ''; + + # Write an /etc/asound.conf that causes all ALSA applications to + # be re-routed to the PulseAudio server through ALSA's Pulse + # plugin. + alsaConf = writeText "asound.conf" '' + pcm_type.pulse { + lib ${alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so + } + pcm.!default { + type pulse + hint.description "Default Audio Device (via PulseAudio)" + } + ctl_type.pulse { + lib ${alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so + } + ctl.!default { + type pulse + } + ''; + +in { options = { - hardware.pulseaudio.enable = mkOption { - default = false; - description = '' - Whether to enable the PulseAudio sound server. - ''; - }; + hardware.pulseaudio = { + enable = mkOption { + default = false; + description = '' + Whether to enable the PulseAudio sound server. + ''; + }; - hardware.pulseaudio.package = mkOption { - default = pkgs.pulseaudio; - example = "pkgs.pulseaudio.override { jackaudioSupport = true; }"; - description = '' - The PulseAudio derivation to use. This can be used to enable - features (such as JACK support) that are not enabled in the - default PulseAudio in Nixpkgs. - ''; + systemWide = mkOption { + type = types.bool; + default = false; + description = '' + If false, a PulseAudio server is launched automatically for + each user that tries to use the sound system. The server runs + with user priviliges. This is the recommended and most secure + way to use PulseAudio. If true, one system-wide PulseAudio + server is launched on boot, running as the user "pulse". + Please read the PulseAudio documentation for more details. + ''; + }; + + configFile = mkOption { + type = types.uniq types.path; + default = "${pulseaudio}/etc/pulse/default.pa"; + description = '' + The path to the configuration the PulseAudio server + should use. By default, the "default.pa" configuration + from the PulseAudio distribution is used. + ''; + }; + + package = mkOption { + default = pulseaudio; + example = "pulseaudio.override { jackaudioSupport = true; }"; + description = '' + The PulseAudio derivation to use. This can be used to enable + features (such as JACK support) that are not enabled in the + default PulseAudio in Nixpkgs. + ''; + }; }; }; - config = mkMerge - [ # Create pulse/client.conf even if PulseAudio is disabled so - # that we can disable the autospawn feature in programs that - # are built with PulseAudio support (like KDE). - { environment.etc = singleton - { target = "pulse/client.conf"; - source = pkgs.writeText "client.conf" - '' - autospawn=${if cfg.enable then "yes" else "no"} - ${optionalString cfg.enable '' - daemon-binary=${cfg.package}/bin/pulseaudio - ''} - ''; - }; - } + config = mkMerge [ + { + environment.etc = singleton { + target = "pulse/client.conf"; + source = clientConf; + }; + } - (mkIf cfg.enable { + (mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; - environment.systemPackages = [ cfg.package ]; + environment.etc = singleton { + target = "asound.conf"; + source = alsaConf; + }; - environment.etc = - [ # Write an /etc/asound.conf that causes all ALSA applications to - # be re-routed to the PulseAudio server through ALSA's Pulse - # plugin. - { target = "asound.conf"; - source = pkgs.writeText "asound.conf" - '' - pcm_type.pulse { - lib ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so - } + # Allow PulseAudio to get realtime priority using rtkit. + security.rtkit.enable = true; + }) - pcm.!default { - type pulse - hint.description "Default Audio Device (via PulseAudio)" - } + (mkIf (cfg.enable && !cfg.systemWide) { + environment.etc = singleton { + target = "pulse/default.pa"; + source = cfg.configFile; + }; + }) - ctl_type.pulse { - lib ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so - } - - ctl.!default { - type pulse - } - ''; - } - - { target = "pulse/default.pa"; - source = "${cfg.package}/etc/pulse/default.pa"; - } - - { target = "pulse/system.pa"; - source = "${cfg.package}/etc/pulse/system.pa"; - } - ]; - - # Allow PulseAudio to get realtime priority using rtkit. - security.rtkit.enable = true; - - }) - ]; + (mkIf (cfg.enable && cfg.systemWide) { + users.extraUsers.pulse = { + # For some reason, PulseAudio wants UID == GID. + uid = assert uid == gid; uid; + group = "pulse"; + extraGroups = [ "audio" ]; + description = "PulseAudio system service user"; + home = pulseRuntimePath; + }; + + users.extraGroups.pulse.gid = gid; + + systemd.services.pulseaudio = { + description = "PulseAudio system-wide server"; + wantedBy = [ "sound.target" ]; + before = [ "sound.target" ]; + path = [ pulseaudio ]; + environment.PULSE_RUNTIME_PATH = pulseRuntimePath; + preStart = '' + mkdir -p --mode 755 ${pulseRuntimePath} + chown -R pulse:pulse ${pulseRuntimePath} + ''; + script = '' + exec pulseaudio --system -n --file="${cfg.configFile}" + ''; + }; + }) + ]; } diff --git a/modules/module-list.nix b/modules/module-list.nix index a899baa6b280..76101dcb7c8c 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -60,7 +60,6 @@ ./services/audio/alsa.nix ./services/audio/fuppes.nix ./services/audio/mpd.nix - ./services/audio/pulseaudio.nix ./services/backup/mysql-backup.nix ./services/backup/postgresql-backup.nix ./services/backup/sitecopy-backup.nix diff --git a/modules/services/audio/pulseaudio.nix b/modules/services/audio/pulseaudio.nix deleted file mode 100644 index 04df2a8e867d..000000000000 --- a/modules/services/audio/pulseaudio.nix +++ /dev/null @@ -1,87 +0,0 @@ -{ config, pkgs, ... }: - -with pkgs.lib; - -let - - uid = config.ids.uids.pulseaudio; - gid = config.ids.gids.pulseaudio; - -in - -{ - - ###### interface - - options = { - - services.pulseaudio = { - - enable = mkOption { - default = false; - description = '' - Whether to enable the PulseAudio system-wide audio server. - Note that the documentation recommends running PulseAudio - daemons per-user rather than system-wide on desktop machines. - ''; - }; - - logLevel = mkOption { - default = "notice"; - example = "debug"; - description = '' - A string denoting the log level: one of - error, warn, - notice, info, - or debug. - ''; - }; - - }; - - }; - - - ###### implementation - - config = mkIf config.services.pulseaudio.enable { - - environment.systemPackages = [ pkgs.pulseaudio ]; - - users.extraUsers = singleton - { name = "pulse"; - # For some reason, PulseAudio wants UID == GID. - uid = assert uid == gid; uid; - group = "pulse"; - description = "PulseAudio system-wide daemon"; - home = "/var/run/pulse"; - }; - - users.extraGroups = singleton - { name = "pulse"; - inherit gid; - }; - - jobs.pulseaudio = - { description = "PulseAudio system-wide server"; - - startOn = "startup"; - - preStart = - '' - test -d /var/run/pulse || \ - ( mkdir -p --mode 755 /var/run/pulse && \ - chown pulse:pulse /var/run/pulse ) - ''; - - exec = - '' - ${pkgs.pulseaudio}/bin/pulseaudio \ - --system --daemonize \ - --log-level="${config.services.pulseaudio.logLevel}" - ''; - }; - - }; - -}