{ lib }: rec { ## Renames an alsa device from a given `name` using the new `description`. ## #@ { name: String, description: String } -> { matches: List, apply_properties: Attrs } mkAlsaRename = { name, description }: { matches = [ [ [ "device.name" "matches" name ] ] ]; # actions = { "update-props" = { "node.description" = description; }; }; apply_properties = { "device.description" = description; }; }; ## Create a pipewire audio node. ## #@ { name: String, factory: String ? "adapter", ... } -> { factory: String, args: Attrs } mkAudioNode = args@{ name, factory ? "adapter", ... }: { inherit factory; args = (builtins.removeAttrs args [ "name" "description" ]) // { "node.name" = name; "node.description" = args.description or args."node.description"; "factory.name" = args."factory.name" or "support.null-audio-sink"; }; }; ## Create a virtual pipewire audio node. ## #@ { name: String, ... } -> { factory: "adapter", args: Attrs } mkVirtualAudioNode = args@{ name, ... }: mkAudioNode (args // { name = "virtual-${lib.toLower name}-audio"; description = "${name} (Virtual)"; "media.class" = args.class or args."media.class" or "Audio/Duplex"; "object.linger" = args."object.linger" or true; "audio.position" = args."audio.position" or [ "FL" "FR" ]; "monitor.channel-volumes" = args."monitor.channel-volumes" or true; }); ## Connect two pipewire audio nodes ## #@ { name: String?, from: String, to: String, ... } -> { name: "libpipewire-module-loopback", args: Attrs } mkBridgeAudioModule = args@{ from, to, ... }: { name = "libpipewire-module-loopback"; args = (builtins.removeAttrs args [ "from" "to" "name" ]) // { "node.name" = if args ? name then "${args.name}-bridge" else "${lib.toLower from}-to-${lib.toLower to}-bridge"; "audio.position" = args."audio.position" or [ "FL" "FR" ]; "capture.props" = { "node.target" = from; } // (args."capture.props" or { }); "playback.props" = { "node.target" = to; "monitor.channel-volumes" = true; } // (args."playback.props" or { }); }; }; }