{ config, lib, pkgs, ... }: with lib; let cfg = config.services.ezpw; in { options.services.ezpw = { enable = mkEnableOption "Enable pipewire"; lowLatency = mkOption { type = types.bool; description = "Enable low latency configuration"; default = true; }; usbSoundcard = mkOption { type = types.bool; description = "Doubles the audio rate for alsa outputs in low latency mode"; default = false; }; batch = mkOption { type = types.bool; description = "idfk"; default = cfg.usbSoundcard; }; 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 = 32; }; }; config = let qr = "${toString cfg.quantum}/${toString cfg.rate}"; in mkIf cfg.enable { services.pulseaudio.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; wireplumber.enable = lib.mkDefault true; extraConfig = { pipewire."92-low-latency" = mkIf cfg.lowLatency { "context.properties" = { "default.clock.rate" = cfg.rate; "default.clock.quantum" = cfg.quantum; "default.clock.min-quantum" = cfg.quantum; "default.clock.max-quantum" = cfg.quantum; }; }; pipewire-pulse."92-low-latency" = mkIf cfg.lowLatency { context.modules = [ { name = "libpipewire-module-protocol-pulse"; args = { pulse.min.req = qr; pulse.default.req = qr; pulse.max.req = qr; pulse.min.quantum = qr; pulse.max.quantum = qr; }; } ]; stream.properties = { node.latency = qr; resample.quality = 1; }; }; }; wireplumber.extraConfig."99-alsa-lowlatency"."alsa_monitor.rules" = [ { matches = [{"node.name" = "matches:alsa_output.*";}]; apply_properties = { "audio.format" = "S32LE"; "audio.rate" = toString (cfg.rate * ( if cfg.usbSoundcard then 2 else 1 )); # for USB soundcards it should be twice your desired rate "api.alsa.period-size" = toString cfg.periodSize; # defaults to 1024, tweak by trial-and-error "api.alsa.disable-batch" = if cfg.batch then "false" else "true"; # generally, USB soundcards use the batch mode }; } ]; }; environment.systemPackages = with pkgs; [ # pactl is required for lots of scripts still pulseaudio ]; }; }