From b68cd0541fd744dc66a6a8fd69523c9153c18a23 Mon Sep 17 00:00:00 2001 From: notgne2 Date: Sun, 15 May 2022 04:52:02 -0700 Subject: [PATCH] add low latency pipewire options --- common.nix | 1 + modules/ezpw.nix | 238 ++++++++++++++++++++++++++++++++-------- modules/workstation.nix | 2 +- 3 files changed, 193 insertions(+), 48 deletions(-) diff --git a/common.nix b/common.nix index e3aac70..4a6b665 100644 --- a/common.nix +++ b/common.nix @@ -100,6 +100,7 @@ # Use a firewall networking.firewall.enable = lib.mkDefault true; + networking.firewall.allowPing = true; networking.firewall.allowedTCPPorts = lib.mkDefault [ 22 ]; programs.fish.enable = lib.mkDefault true; diff --git a/modules/ezpw.nix b/modules/ezpw.nix index ce47784..164b6a5 100644 --- a/modules/ezpw.nix +++ b/modules/ezpw.nix @@ -5,55 +5,199 @@ let in { options.services.ezpw = { - enable = - mkEnableOption - "Enable pipewire"; - }; + enable = mkEnableOption "Enable pipewire"; - config = mkIf cfg.enable { - hardware.pulseaudio.enable = lib.mkDefault false; - sound.enable = lib.mkDefault false; - - services.pipewire = { - enable = lib.mkDefault true; - jack.enable = lib.mkDefault true; - alsa.enable = lib.mkDefault true; - alsa.support32Bit = lib.mkDefault true; - pulse.enable = lib.mkDefault true; - - media-session.enable = lib.mkDefault false; - wireplumber.enable = lib.mkDefault true; - - media-session.config.bluez-monitor = { - properties = { - "bluez5.codecs" = [ "sbc" "aac" "ldac" "aptx" "aptx_hd" ]; - "bluez5.mdbc-support" = true; - }; - rules = [ - { - actions = { - update-props = { - "bluez5.auto-connect" = [ "hsp_hs" "hfp_hf" "a2dp_sink" ]; - "bluez5.hw-volume" = - [ "hsp_ag" "hfp_ag" "a2dp_source" "a2dp_sink" ]; - "bluez5.autoswitch-profile" = true; - }; - }; - matches = [{ "device.name" = "~bluez_card.*"; }]; - } - { - actions = { update-props = { "node.pause-on-idle" = false; }; }; - matches = [ - { "node.name" = "~bluez_input.*"; } - { "node.name" = "~bluez_output.*"; } - ]; - } - ]; - }; + lowLatency = mkOption { + type = types.bool; + description = "Enable low latency configuration"; + default = true; }; - xdg.portal.enable = lib.mkDefault true; - xdg.portal.gtkUsePortal = lib.mkDefault true; - xdg.portal.extraPortals = lib.mkDefault (with pkgs; [ xdg-desktop-portal-wlr xdg-desktop-portal-gtk ]); + usbSoundcard = mkOption { + type = types.bool; + description = "Doubles the audio rate for alsa outputs in low latency mode"; + default = false; + }; + + periodSize = mkOption { + type = types.int; + description = "Pipewire period size in low latency mode (\"tweak by trial-and-error\")"; + default = 32; + }; + + rate = mkOption { + type = types.int; + description = "Pipewire rate in low latency mode"; + default = 48000; + }; + + quantum = mkOption { + type = types.int; + description = "Pipewire quantum in low latency mode"; + default = 64; + }; }; + + config = + let + qr = "${toString cfg.quantum}/${toString cfg.rate}"; + in + mkIf cfg.enable { + hardware.pulseaudio.enable = lib.mkDefault false; + sound.enable = lib.mkDefault false; + + services.pipewire = { + enable = lib.mkDefault true; + jack.enable = lib.mkDefault true; + alsa.enable = lib.mkDefault true; + alsa.support32Bit = lib.mkDefault true; + pulse.enable = lib.mkDefault true; + + media-session.enable = lib.mkDefault false; + wireplumber.enable = lib.mkDefault true; + + config = mkIf cfg.lowLatency { + pipewire = { + "context.properties" = { + "default.clock.rate" = cfg.rate; + "default.clock.quantum" = cfg.quantum; + "default.clock.min-quantum" = cfg.quantum; + }; + + "context.modules" = [ + { + name = "libpipewire-module-rtkit"; + args = { + "nice.level" = -11; + "rt.prio" = 88; + "rt.time.soft" = 200000; + "rt.time.hard" = 200000; + }; + flags = [ "ifexists" "nofail" ]; + } + { name = "libpipewire-module-protocol-native"; } + { name = "libpipewire-module-profiler"; } + { name = "libpipewire-module-metadata"; } + { name = "libpipewire-module-spa-device-factory"; } + { name = "libpipewire-module-spa-node-factory"; } + { name = "libpipewire-module-client-node"; } + { name = "libpipewire-module-client-device"; } + { + name = "libpipewire-module-portal"; + flags = [ "ifexists" "nofail" ]; + } + { + name = "libpipewire-module-access"; + args = { }; + } + { name = "libpipewire-module-adapter"; } + { name = "libpipewire-module-link-factory"; } + { name = "libpipewire-module-session-manager"; } + ]; + }; + + pipewire-pulse = { + "context.modules" = [ + { + name = "libpipewire-module-rtkit"; + args = { + "nice.level" = -11; + "rt.prio" = 88; + "rt.time.soft" = 200000; + "rt.time.hard" = 200000; + }; + flags = [ "ifexists" "nofail" ]; + } + { name = "libpipewire-module-protocol-native"; } + { name = "libpipewire-module-client-node"; } + { name = "libpipewire-module-adapter"; } + { name = "libpipewire-module-metadata"; } + { + name = "libpipewire-module-protocol-pulse"; + args = { + "pulse.min.req" = qr; + "pulse.default.req" = qr; + "pulse.min.quantum" = qr; + "server.address" = [ "unix:native" ]; + }; + } + ]; + + "stream.properties" = { + "node.latency" = qr; + "resample.quality" = 1; + }; + }; + }; + + media-session.config.alsa-monitor = mkIf cfg.lowLatency { + rules = [ + { + matches = [{ node.name = "alsa_output.*"; }]; + actions = { + update-props = { + "audio.format" = "S32LE"; + "audio.rate" = cfg.rate * (if cfg.usbSoundcard then 2 else 1); + "api.alsa.period-size" = cfg.periodSize; + }; + }; + } + ]; + }; + + media-session.config.bluez-monitor = { + properties = { + "bluez5.codecs" = [ "sbc" "aac" "ldac" "aptx" "aptx_hd" ]; + "bluez5.mdbc-support" = true; + }; + rules = [ + { + actions = { + update-props = { + "bluez5.auto-connect" = [ "hsp_hs" "hfp_hf" "a2dp_sink" ]; + "bluez5.hw-volume" = + [ "hsp_ag" "hfp_ag" "a2dp_source" "a2dp_sink" ]; + "bluez5.autoswitch-profile" = true; + }; + }; + matches = [{ "device.name" = "~bluez_card.*"; }]; + } + { + actions = { update-props = { "node.pause-on-idle" = false; }; }; + matches = [ + { "node.name" = "~bluez_input.*"; } + { "node.name" = "~bluez_output.*"; } + ]; + } + ]; + }; + }; + + environment.systemPackages = with pkgs; [ + # pactl is required for pipewire-pulse + pulseaudio + ]; + + environment.etc."wireplumber/main.lua.d/51-alsa-config.lua".text = mkIf cfg.lowLatency '' + alsa_monitor.properties = { + ["audio.rate"] = ${toString (cfg.rate * (if cfg.usbSoundcard then 2 else 1))}, + ["audio.format"] = "S32LE", + ["api.alsa.headroom"] = 512, + ["api.alsa.period-size"] = ${toString cfg.periodSize} + } + ''; + + environment.etc."wireplumber/bluetooth.lua.d/51-bluez-config.lua".text = '' + bluez_monitor.properties = { + ["bluez5.enable-sbc-xq"] = true, + ["bluez5.enable-msbc"] = true, + ["bluez5.enable-hw-volume"] = true, + ["bluez5.headset-roles"] = "[ hsp_hs hsp_ag hfp_hf hfp_ag ]" + } + ''; + + xdg.portal.enable = lib.mkDefault true; + xdg.portal.gtkUsePortal = lib.mkDefault true; + xdg.portal.extraPortals = lib.mkDefault (with pkgs; [ xdg-desktop-portal-wlr xdg-desktop-portal-gtk ]); + }; } diff --git a/modules/workstation.nix b/modules/workstation.nix index 41b316a..d3ec357 100644 --- a/modules/workstation.nix +++ b/modules/workstation.nix @@ -150,7 +150,7 @@ in domain = "@users"; type = "-"; item = "nice"; - value = "-10"; + value = "-15"; } ];