mirror of
https://github.com/nestriness/nestri.git
synced 2026-10-01 23:22:24 +03:00
Fixes: #335 Still a work-in-progress. --------- Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Wanjohi <elviswanjohi47@gmail.com>
67 lines
3.2 KiB
Plaintext
67 lines
3.2 KiB
Plaintext
# pipewire-pulse, the PulseAudio protocol on top of PipeWire, for clients that
|
|
# speak nothing else. Wine's audio driver is one of them.
|
|
#
|
|
# The socket moves out of the service user's runtime directory. That directory
|
|
# is 0700 and the workload runs as a different user, so a client there finds
|
|
# nothing and plays silently, which is the failure PipeWire's own socket was
|
|
# moved for. The workload is pointed here with PULSE_SERVER, and nesinit starts
|
|
# this under a umask that lets a user who does not own the socket open it. This
|
|
# path is written in nesinit too, and a test there compares the two.
|
|
#
|
|
# A drop-in replaces a key of pulse.properties rather than appending to it, so
|
|
# the default "unix:native" socket is not created as well.
|
|
pulse.properties = {
|
|
server.address = [ "unix:/run/pipewire/pulse-native" ]
|
|
|
|
# module-always-sink creates a "Dummy Output" sink whenever no other sink
|
|
# exists, and while neswire's sink is not up yet that is always. A second
|
|
# sink is a second default-node candidate, and a game that picks it plays
|
|
# into nothing. neswire has to be the only sink; see the WirePlumber
|
|
# drop-in.
|
|
pulse.cmd.always-sink = false
|
|
|
|
# The root is read-only and every box starts from the same image, so there
|
|
# is nothing to restore and nowhere to save, which is the reasoning behind
|
|
# turning off WirePlumber's state hooks. Left on, these are one more place
|
|
# that could pin a default.
|
|
pulse.cmd.device-manager = false
|
|
pulse.cmd.device-restore = false
|
|
pulse.cmd.stream-restore = false
|
|
|
|
# Wine sizes its whole audio path from this number. At startup its driver
|
|
# opens a probe stream asking for a 1-frame request size, reads back what
|
|
# the server grants, which is this floor, and makes the device period ten
|
|
# times that. Streams then queue three periods. The default floor of 256
|
|
# frames therefore becomes a 53 ms period and about 160 ms of audio in
|
|
# flight, which is desktop playback and not a game being streamed.
|
|
#
|
|
# 48 frames (1 ms) makes that period 10 ms, the default period Windows
|
|
# itself uses, so a game gets the buffering it was written for. A stream
|
|
# then asks for 480-frame requests, which is what is granted, so the floor
|
|
# affects the probe and nothing else Wine does.
|
|
pulse.min.req = 48/48000
|
|
|
|
# What a client gets when it asks for no particular buffering. The shipped
|
|
# default is two seconds, which is only harmless where nobody is listening
|
|
# live. 10 ms requests and 40 ms of target buffer are enough for a client
|
|
# that does not say.
|
|
pulse.default.req = 480/48000
|
|
pulse.default.tlength = 1920/48000
|
|
}
|
|
|
|
# pipewire-pulse.conf raises the minimum node latency to 1024 frames (21.3 ms)
|
|
# inside a virtual machine, which a box is. That puts every Pulse client, and
|
|
# therefore Wine, at least 21 ms behind, whatever it asked for. Floor it where
|
|
# the graph itself is floored instead; see the pipewire.conf drop-in for why
|
|
# 256 frames. A drop-in appends to this array, and every matching rule applies
|
|
# in order, so this runs after the shipped rule and wins.
|
|
pulse.properties.rules = [
|
|
{ matches = [ { cpu.vm.name = !null } ]
|
|
actions = {
|
|
update-props = {
|
|
pulse.min.quantum = 256/48000
|
|
}
|
|
}
|
|
}
|
|
]
|