# SPDX-License-Identifier: MIT # Copyright © 2018 Wim Taymans # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice (including the next # paragraph) shall be included in all copies or substantial portions of the # Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. context.properties = { ## Configure properties in the system. link.max-buffers = 16 # version < 3 clients can't handle more core.daemon = true # listening for socket connections core.name = pipewire-0 # core name and socket name default.clock.min-quantum = 1024 # account for running in a VM } context.spa-libs = { # = # # Used to find spa factory names. It maps an spa factory name # regular expression to a library name that should contain # that factory. # audio.convert.* = audioconvert/libspa-audioconvert api.alsa.* = alsa/libspa-alsa support.* = support/libspa-support } context.modules = [ # Uses realtime scheduling to boost the audio thread priorities. This uses # RTKit if the user doesn't have permission to use regular realtime # scheduling. You can also clamp utilisation values to improve scheduling # on embedded and heterogeneous systems, e.g. Arm big.LITTLE devices. # use module.rt.args = { ... } to override the arguments. { name = libpipewire-module-rt args = { nice.level = -11 rt.prio = 88 } flags = [ ifexists nofail ] condition = [ { module.rt = !false } ] } # The native communication protocol. { name = libpipewire-module-protocol-native args = { # List of server Unix sockets, and optionally permissions #sockets = [ { name = "pipewire-0" }, { name = "pipewire-0-manager" } ] } } # Allows applications to create metadata objects. It creates # a factory for Metadata objects. { name = libpipewire-module-metadata condition = [ { module.metadata = !false } ] } # Creates a factory for making devices that run in the # context of the PipeWire server. { name = libpipewire-module-spa-device-factory condition = [ { module.spa-device-factory = !false } ] } # Creates a factory for making nodes that run in the # context of the PipeWire server. { name = libpipewire-module-spa-node-factory condition = [ { module.spa-node-factory = !false } ] } # Allows creating nodes that run in the context of the # client. Is used by all clients that want to provide # data to PipeWire. { name = libpipewire-module-client-node condition = [ { module.client-node = !false } ] } # Allows creating devices that run in the context of the # client. Is used by the session manager. { name = libpipewire-module-client-device condition = [ { module.client-device = !false } ] } # The portal module monitors the PID of the portal process # and tags connections with the same PID as portal # connections. { name = libpipewire-module-portal flags = [ ifexists nofail ] condition = [ { module.portal = !false } ] } # The access module can perform access checks and block # new clients. { name = libpipewire-module-access args = { # Socket-specific access permissions #access.socket = { pipewire-0 = "default", pipewire-0-manager = "unrestricted" } # Deprecated legacy mode (not socket-based), # for now enabled by default if access.socket is not specified #access.legacy = true } condition = [ { module.access = !false } ] } # Makes a factory for wrapping nodes in an adapter with a # converter and resampler. { name = libpipewire-module-adapter condition = [ { module.adapter = !false } ] } # Makes a factory for creating links between ports. # use module.link-factory.args = { ... } to override the arguments. { name = libpipewire-module-link-factory args = { #allow.link.passive = false } condition = [ { module.link-factory = !false } ] } # Provides factories to make session manager objects. { name = libpipewire-module-session-manager condition = [ { module.session-manager = !false } ] } # The PulseAudio communication protocol { name = libpipewire-module-protocol-pulse args = { # the addresses this server listens on server.address = [ "unix:native" ] } } ] context.objects = [ # A default dummy driver. This handles nodes marked with the "node.always-process" # property 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 node.group = pipewire.dummy node.sync-group = sync.dummy priority.driver = 200000 #clock.id = monotonic # realtime | tai | monotonic-raw | boottime #clock.name = "clock.system.monotonic" } condition = [ { factory.dummy-driver = !false } ] } { factory = spa-node-factory args = { factory.name = support.node.driver node.name = Freewheel-Driver priority.driver = 190000 node.group = pipewire.freewheel node.sync-group = sync.dummy node.freewheel = true #freewheel.wait = 10 } condition = [ { factory.freewheel-driver = !false } ] } { factory = adapter args = { factory.name = "api.alsa.pcm.source" node.name = "alsa_input" media.class = "Audio/Source" alsa.card = 0, alsa.card_name = "VirtIO SoundCard" alsa.device = 0 alsa.driver_name = "virtio_snd" alsa.id = "SoundCard" alsa.long_card_name = "VirtIO SoundCard at pci/0000:00:01.0/virtio0" alsa.name = "VirtIO SoundCard" alsa.subdevice = 1 alsa.subdevice_name = "subdevice #1" api.alsa.card.longname = "VirtIO SoundCard at pci/0000:00:01.0/virtio0" api.alsa.card.name = "VirtIO SoundCard" api.alsa.headroom = 0 api.alsa.path = "hw:0" api.alsa.pcm.card = 0, api.alsa.pcm.stream = "capture" media.class = "Audio/Source" api.alsa.path = "hw:0" node.suspend-on-idle = true audio.format = "S32" audio.rate = 48000 audio.allowed-rates = [ ] audio.channels = 2 audio.position = "FL,FR" } } { factory = adapter args = { factory.name = "api.alsa.pcm.sink" node.name = "alsa_output" media.class = "Audio/Sink" alsa.card = 0, alsa.card_name = "VirtIO SoundCard" alsa.device = 0 alsa.driver_name = "virtio_snd" alsa.id = "SoundCard" alsa.long_card_name = "VirtIO SoundCard at pci/0000:00:01.0/virtio0" alsa.name = "VirtIO SoundCard" alsa.subdevice = 0 alsa.subdevice_name = "subdevice #0" api.alsa.card.longname = "VirtIO SoundCard at pci/0000:00:01.0/virtio0" api.alsa.card.name = "VirtIO SoundCard" api.alsa.headroom = 0 api.alsa.path = "hw:0" api.alsa.pcm.card = 0, api.alsa.pcm.stream = "playback" node.suspend-on-idle = true audio.format = "S32" audio.rate = 48000 audio.allowed-rates = [ ] audio.channels = 2 audio.position = "FL,FR" } } ] pulse.cmd = [ { cmd = "load-module" args = "module-always-sink" flags = [ ] condition = [ { pulse.cmd.always-sink = !false } ] } { cmd = "load-module" args = "module-device-manager" flags = [ ] condition = [ { pulse.cmd.device-manager = !false } ] } { cmd = "load-module" args = "module-device-restore" flags = [ ] condition = [ { pulse.cmd.device-restore = !false } ] } { cmd = "load-module" args = "module-stream-restore" flags = [ ] condition = [ { pulse.cmd.stream-restore = !false } ] } ] pulse.properties.rules = [ { matches = [ { cpu.vm.name = !null } ] actions = { update-props = { # These overrides are only applied when running in a vm. pulse.min.quantum = 1024/48000 # 22ms } } } ] # client/stream specific properties pulse.rules = [ { # skype does not want to use devices that don't have an S16 sample format. matches = [ { application.process.binary = "teams" } { application.process.binary = "teams-insiders" } { application.process.binary = "teams-for-linux" } { application.process.binary = "skypeforlinux" } ] actions = { quirks = [ force-s16-info ] } } { # firefox marks the capture streams as don't move and then they # can't be moved with pavucontrol or other tools. matches = [ { application.process.binary = "firefox" } ] actions = { quirks = [ remove-capture-dont-move ] } } { # speech dispatcher asks for too small latency and then underruns. matches = [ { application.name = "~speech-dispatcher.*" } ] actions = { update-props = { pulse.min.req = 512/48000 # 10.6ms pulse.min.quantum = 512/48000 # 10.6ms pulse.idle.timeout = 5 # pause after 5 seconds of underrun } } } ] context.exec = []