PipeWire: Difference between revisions
m some small changes to formatting and grammar |
format code with nixfmt |
||
Line 10: | Line 10: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
# On NixOS 24.05 or older, this option must be set: | # On NixOS 24.05 or older, this option must be set: | ||
#sound.enable = false; | #sound.enable = false; | ||
# rtkit is optional but recommended | # rtkit is optional but recommended | ||
security.rtkit.enable = true; | security.rtkit.enable = true; | ||
services.pipewire = { | services.pipewire = { | ||
enable = true; | |||
alsa.enable = true; | |||
alsa.support32Bit = true; | |||
pulse.enable = true; | |||
# If you want to use JACK applications, uncomment this | |||
#jack.enable = true; | |||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 33: | Line 33: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
services.pipewire.wireplumber.extraConfig."10-bluez.conf" = { | services.pipewire.wireplumber.extraConfig."10-bluez.conf" = { | ||
"monitor.bluez.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" | |||
]; | |||
}; | |||
}; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 46: | Line 51: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
services.pipewire.wireplumber.configPackages = [ | services.pipewire.wireplumber.configPackages = [ | ||
(pkgs.writeTextDir "share/wireplumber/wireplumber.conf.d/10-bluez.conf" '' | |||
monitor.bluez.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] | |||
} | |||
'') | |||
]; | ]; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 63: | Line 68: | ||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
services.pipewire | services.pipewire = { | ||
media-session.config.bluez-monitor.rules = [ | |||
{ | |||
# Matches all cards | |||
matches = [ { "device.name" = "~bluez_card.*"; } ]; | |||
actions = { | |||
"update-props" = { | |||
"bluez5.reconnect-profiles" = [ | |||
"hfp_hf" | |||
"hsp_hs" | |||
"a2dp_sink" | |||
]; | |||
# mSBC is not expected to work on all headset + adapter combinations. | |||
"bluez5.msbc-support" = true; | |||
# SBC-XQ is not expected to work on all headset + adapter combinations. | |||
"bluez5.sbc-xq-support" = true; | |||
}; | |||
}; | }; | ||
} | } | ||
{ | |||
matches = [ | |||
# Matches all sources | |||
{ "node.name" = "~bluez_input.*"; } | |||
# Matches all outputs | |||
{ "node.name" = "~bluez_output.*"; } | |||
]; | |||
} | |||
]; | |||
}; | |||
}; | |||
</syntaxHighlight> | </syntaxHighlight> | ||
Line 110: | Line 119: | ||
For NixOS 24.05 and newer: | For NixOS 24.05 and newer: | ||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
services.pipewire.extraConfig.pipewire."91-null-sinks" = | services.pipewire.extraConfig.pipewire."91-null-sinks" = { | ||
"context.objects" = [ | "context.objects" = [ | ||
{ | { | ||
Line 158: | Line 126: | ||
factory = "spa-node-factory"; | factory = "spa-node-factory"; | ||
args = { | args = { | ||
"factory.name" | "factory.name" = "support.node.driver"; | ||
"node.name" | "node.name" = "Dummy-Driver"; | ||
"priority.driver" | "priority.driver" = 8000; | ||
}; | }; | ||
} | } | ||
Line 166: | Line 134: | ||
factory = "adapter"; | factory = "adapter"; | ||
args = { | args = { | ||
"factory.name" | "factory.name" = "support.null-audio-sink"; | ||
"node.name" | "node.name" = "Microphone-Proxy"; | ||
"node.description" = "Microphone"; | "node.description" = "Microphone"; | ||
"media.class" | "media.class" = "Audio/Source/Virtual"; | ||
"audio.position" | "audio.position" = "MONO"; | ||
}; | }; | ||
} | } | ||
Line 176: | Line 144: | ||
factory = "adapter"; | factory = "adapter"; | ||
args = { | args = { | ||
"factory.name" | "factory.name" = "support.null-audio-sink"; | ||
"node.name" | "node.name" = "Main-Output-Proxy"; | ||
"node.description" = "Main Output"; | "node.description" = "Main Output"; | ||
"media.class" | "media.class" = "Audio/Sink"; | ||
"audio.position" | "audio.position" = "FL,FR"; | ||
}; | }; | ||
} | } | ||
]; | ]; | ||
}; | }; | ||
}; | </syntaxHighlight> | ||
If you're still using 23.11 or earlier, you can use <code>environment.etc</code> and <code>pkgs.formats.json</code>: | |||
<syntaxHighlight lang=nix> | |||
environment.etc = | |||
let | |||
json = pkgs.formats.json { }; | |||
in | |||
{ | |||
"pipewire/pipewire.d/91-null-sinks.conf".source = json.generate "91-null-sinks.conf" { | |||
"context.objects" = [ | |||
{ | |||
# A default dummy driver. This handles nodes marked with the "node.always-driver" | |||
# properyty when no other driver is currently active. JACK clients need this. | |||
factory = "spa-node-factory"; | |||
args = { | |||
"factory.name" = "support.node.driver"; | |||
"node.name" = "Dummy-Driver"; | |||
"priority.driver" = 8000; | |||
}; | |||
} | |||
{ | |||
factory = "adapter"; | |||
args = { | |||
"factory.name" = "support.null-audio-sink"; | |||
"node.name" = "Microphone-Proxy"; | |||
"node.description" = "Microphone"; | |||
"media.class" = "Audio/Source/Virtual"; | |||
"audio.position" = "MONO"; | |||
}; | |||
} | |||
{ | |||
factory = "adapter"; | |||
args = { | |||
"factory.name" = "support.null-audio-sink"; | |||
"node.name" = "Main-Output-Proxy"; | |||
"node.description" = "Main Output"; | |||
"media.class" = "Audio/Sink"; | |||
"audio.position" = "FL,FR"; | |||
}; | |||
} | |||
]; | |||
}; | |||
}; | |||
</syntaxHighlight> | </syntaxHighlight> | ||
Line 208: | Line 219: | ||
For 24.05 and newer: | For 24.05 and newer: | ||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
services.pipewire.extraConfig.pipewire."92-low-latency" = { | services.pipewire.extraConfig.pipewire."92-low-latency" = { | ||
"context.properties" = { | |||
"default.clock.rate" = 48000; | |||
"default.clock.quantum" = 32; | |||
"default.clock.min-quantum" = 32; | |||
"default.clock.max-quantum" = 32; | |||
}; | |||
}; | }; | ||
</syntaxHighlight> | </syntaxHighlight> | ||
Line 226: | Line 237: | ||
For 24.05 or newer: | For 24.05 or newer: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
services.pipewire.extraConfig.pipewire-pulse."92-low-latency" = { | services.pipewire.extraConfig.pipewire-pulse."92-low-latency" = { | ||
"context.properties" = [ | |||
{ | |||
name = "libpipewire-module-protocol-pulse"; | |||
args = { }; | |||
} | |||
]; | |||
"pulse.properties" = { | |||
"pulse.min.req" = "32/48000"; | |||
"pulse.default.req" = "32/48000"; | |||
"pulse.max.req" = "32/48000"; | |||
"pulse.min.quantum" = "32/48000"; | |||
"pulse.max.quantum" = "32/48000"; | |||
}; | |||
"stream.properties" = { | |||
"node.latency" = "32/48000"; | |||
"resample.quality" = 1; | |||
}; | |||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
If you're still using 23.11 or earlier, you can use <code>environment.etc</code> and <code>pkgs.formats.json</code> like in [[PipeWire#Advanced_Configuration|Advanced Configuration]]. | If you're still using 23.11 or earlier, you can use <code>environment.etc</code> and <code>pkgs.formats.json</code> like in [[PipeWire#Advanced_Configuration|Advanced Configuration]]. | ||
Line 254: | Line 265: | ||
For 24.05 and newer: | For 24.05 and newer: | ||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
services.pipewire.wireplumber.configPackages = [ | services.pipewire.wireplumber.configPackages = [ | ||
(pkgs.writeTextDir "share/wireplumber/main.lua.d/99-alsa-lowlatency.lua" '' | |||
alsa_monitor.rules = { | |||
{ | |||
matches = {{{ "node.name", "matches", "alsa_output.*" }}}; | |||
apply_properties = { | |||
["audio.format"] = "S32LE", | |||
["audio.rate"] = "96000", -- for USB soundcards it should be twice your desired rate | |||
["api.alsa.period-size"] = 2, -- defaults to 1024, tweak by trial-and-error | |||
-- ["api.alsa.disable-batch"] = true, -- generally, USB soundcards use the batch mode | |||
}, | |||
}, | |||
} | |||
'') | |||
]; | |||
</syntaxHighlight> | |||
Once [https://github.com/NixOS/nixpkgs/pull/292115 #292115] is merged and has reached nixos-unstable, you'll be able to use <code>services.pipewire.wireplumber.extraLuaConfig</code> as well: | |||
<syntaxHighlight lang=nix> | |||
services.pipewire.wireplumber.extraLuaConfig.main."99-alsa-lowlatency" = '' | |||
alsa_monitor.rules = { | alsa_monitor.rules = { | ||
{ | { | ||
Line 267: | Line 296: | ||
}, | }, | ||
} | } | ||
'' | ''; | ||
</syntaxHighlight> | </syntaxHighlight> | ||
If you're still using 23.11 or earlier, you can use <code>environment.etc</code>: | |||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
environment.etc."wireplumber/main.lua.d/99-alsa-lowlatency.lua".text = '' | |||
alsa_monitor.rules = { | |||
{ | |||
matches = {{{ "node.name", "matches", "alsa_output.*" }}}; | |||
apply_properties = { | |||
["audio.format"] = "S32LE", | |||
["audio.rate"] = "96000", -- for USB soundcards it should be twice your desired rate | |||
["api.alsa.period-size"] = 2, -- defaults to 1024, tweak by trial-and-error | |||
-- ["api.alsa.disable-batch"] = true, -- generally, USB soundcards use the batch mode | |||
}, | |||
}, | }, | ||
} | } | ||
''; | |||
''; | |||
</syntaxHighlight> | </syntaxHighlight> | ||
The <code>matches</code> attribute applies the <code>actions</code> to the devices/properties listed there. It is usually used with soundcard names, like shown in the config above. <code><matches></code> can match any of the outputs of | The <code>matches</code> attribute applies the <code>actions</code> to the devices/properties listed there. It is usually used with soundcard names, like shown in the config above. <code><matches></code> can match any of the outputs of |