{ config, lib, pkgs, ... }: with lib; let ladspaPath = "${pkgs.ladspaPlugins}/lib/ladspa"; jackScript = pkgs.writeShellScriptBin "jack" (lib.fileContents ../../assets/jack.sh); queueElement = { options = { plugin = mkOption { type = with types; str; description = "file name without suffix of the plugin"; }; label = mkOption { type = with types; str; description = "label of the queue element (needs to be correct)"; }; control = mkOption { type = with types; listOf str; description = "parameter of plugin"; }; }; }; sinkElement = { options = { name = mkOption { type = with types; str; description = "name of the sink"; }; queue = mkOption { type = with types; listOf (submodule queueElement); description = "queues"; }; }; }; cfg = config.system.custom.audio; in { options.system.custom.audio = { enable = mkEnableOption "use PluseAudio"; sinks = mkOption { type = with types; listOf (submodule sinkElement); description = "list of sinks"; }; }; config = mkIf cfg.enable { # add virtual midi module # ----------------------- #boot = { # # to route midi signals # # between bitwig and vcvrack # kernelModules = [ "snd_virmidi" ]; # # index=-2 prevents from beeing recognised as the default # # audio device # # midi_devs limit the number of midi devices. # extraModprobeConfig = "options snd-virmidi index=-2 midi_devs=1"; #}; # LADSPA # ------ programs.bash.interactiveShellInit = # sh '' # set ladspa library path # about testing the plugins check analyseplugin command export LADSPA_PATH=${ladspaPath} ''; programs.zsh.interactiveShellInit = # sh '' # set ladspa library path # about testing the plugins check analyseplugin command export LADSPA_PATH=${ladspaPath} ''; # PulseAudio # ---------- # because of systemWide ensure main user is in audio group system.custom.mainUser.extraGroups = [ "audio" "pipewire" ]; #services.pipewire = { # enable = true; # systemWide = true; # media-session.enable = false; # pulse.enable = true; # jack.enable = false; # alsa.enable = false; #}; #hardware.pulseaudio.enable = false; # todo use pipewire for this hardware.pulseaudio = { enable = true; package = pkgs.pulseaudioFull; # all in audio group can do audio systemWide = true; extraConfig = '' # automatically switch to newly-connected devices load-module module-switch-on-connect # http://plugin.org.uk/ladspa-swh/docs/ladspa-swh.html # https://gavv.github.io/articles/pulseaudio-under-the-hood/#ladspa-plugin-sink ${builtins.toString (flip map cfg.sinks (sink: '' # ladspa sink : ${sink.name} # ------------- ${builtins.toString (flip imap0 (reverseList sink.queue) (index: queua: let sinkName = suffix: "${sink.name}${builtins.toString suffix}"; sinkValue = "sink_name=${sinkName index}"; sinkDescription = "sink_properties=device.description=${ sinkName index }-${queua.label}"; masterValue = if (index == 0) then "" else "sink_master=${sinkName (index - 1)}"; pluginValue = "plugin=${ladspaPath}/${queua.plugin}"; labelValue = "label=${queua.label}"; controlValue = "control=${ builtins.toString (foldl (a: b: "${a},${b}") (head queua.control) (tail queua.control)) }"; in '' # ${sinkName index} : ${queua.label} load-module module-ladspa-sink ${sinkValue} ${sinkDescription} ${masterValue} ${pluginValue} ${labelValue} ${controlValue} ''))} ''))} ''; }; # Packages needed # --------------- environment.systemPackages = with pkgs; [ # Music making # ------------ #jackScript #jack2Full #patchage #zynaddsubfx #qjackctl alsaUtils # LADSPA # ------ ladspaPlugins ladspa-sdk # PulseAudio control # ------------------ pavucontrol lxqt.pavucontrol-qt ]; }; }