# Simple daemon config file for PipeWire version "1.2.3" # # # Copy and edit this file in /etc/pipewire for system-wide changes # or in ~/.config/pipewire for local changes. # # It is also possible to place a file with an updated section in # /etc/pipewire/minimal.conf.d/ for system-wide changes or in # ~/.config/pipewire/minimal.conf.d/ for local changes. # context.properties = { ## Configure properties in the system. #library.name.system = support/libspa-support #context.data-loop.library.name.system = support/libspa-support #support.dbus = true #link.max-buffers = 64 link.max-buffers = 16 # version < 3 clients can't handle more #mem.warn-mlock = false #mem.allow-mlock = true #mem.mlock-all = false #clock.power-of-two-quantum = true #log.level = 2 #cpu.zero.denormals = false core.daemon = true # listening for socket connections core.name = pipewire-0 # core name and socket name ## Properties for the DSP configuration. #default.clock.rate = 48000 #default.clock.allowed-rates = [ 48000 ] #default.clock.quantum = 1024 #default.clock.min-quantum = 32 #default.clock.max-quantum = 2048 #default.clock.quantum-limit = 8192 #default.clock.quantum-floor = 4 #default.video.width = 640 #default.video.height = 480 #default.video.rate.num = 25 #default.video.rate.denom = 1 # settings.check-quantum = true settings.check-rate = true # This config can use udev or hardcoded ALSA devices. Make sure to # change the alsa device below when disabling udev minimal.use-udev = true # Load the pulseaudio emulation daemon minimal.use-pulse = true } context.properties.rules = [ { matches = [ { cpu.vm.name = !null } ] actions = { update-props = { # These overrides are only applied when running in a vm. default.clock.min-quantum = 1024 } } } ] 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 audio.adapt = audioconvert/libspa-audioconvert api.alsa.* = alsa/libspa-alsa support.* = support/libspa-support } context.modules = [ #{ name = # ( args = { = ... } ) # ( flags = [ ( ifexists ) ( nofail ) ] ) # ( condition = [ { = ... } ... ] ) #} # # Loads a module with the given parameters. # If ifexists is given, the module is ignored when it is not found. # If nofail is given, module initialization failures are ignored. # # Uses realtime scheduling to boost the audio thread priorities. This uses # RTKit if the user doesn't have permission to use regular realtime # scheduling. { name = libpipewire-module-rt args = { nice.level = -11 rt.prio = 88 #rt.time.soft = -1 #rt.time.hard = -1 } flags = [ ifexists nofail ] } # The native communication protocol. { name = libpipewire-module-protocol-native } # The profile module. Allows application to access profiler # and performance data. It provides an interface that is used # by pw-top and pw-profiler. { name = libpipewire-module-profiler } # Allows applications to create metadata objects. It creates # a factory for Metadata objects. { name = libpipewire-module-metadata } # Creates a factory for making nodes that run in the # context of the PipeWire server. { name = libpipewire-module-spa-node-factory } { name = libpipewire-module-spa-device-factory } # 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 } # The access module can perform access checks and block # new clients. { name = libpipewire-module-access args = { # access.allowed to list an array of paths of allowed # apps. #access.allowed = [ # /usr/bin/pipewire-media-session #] # An array of rejected paths. #access.rejected = [ ] # An array of paths with restricted access. #access.restricted = [ ] # Anything not in the above lists gets assigned the # access.force permission. #access.force = flatpak } } # Makes a factory for wrapping nodes in an adapter with a # converter and resampler. { name = libpipewire-module-adapter } # Makes a factory for creating links between ports. { name = libpipewire-module-link-factory } { name = libpipewire-module-protocol-pulse condition = [ { minimal.use-pulse = true } ] } ] pulse.properties = { # the addresses this server listens on server.address = [ "unix:native" ] } stream.properties = { adapter.auto-port-config = { mode = dsp } } context.objects = [ #{ factory = # ( args = { = ... } ) # ( flags = [ ( nofail ) ] ) # ( condition = [ { = ... } ... ] ) #} # # Creates an object from a PipeWire factory with the given parameters. # If nofail is given, errors are ignored (and no object is created). # #{ factory = spa-node-factory args = { factory.name = videotestsrc node.name = videotestsrc node.description = videotestsrc "Spa:Pod:Object:Param:Props:patternType" = 1 } } #{ factory = spa-device-factory args = { factory.name = api.jack.device foo=bar } flags = [ nofail ] } #{ factory = spa-device-factory args = { factory.name = api.alsa.enum.udev } } #{ factory = spa-node-factory args = { factory.name = api.alsa.seq.bridge node.name = Internal-MIDI-Bridge } } #{ factory = adapter args = { factory.name = audiotestsrc node.name = my-test node.description = audiotestsrc } } #{ factory = spa-node-factory args = { factory.name = api.vulkan.compute.source node.name = my-compute-source } } # Make a default metadata store { factory = metadata args = { metadata.name = default # metadata.values = [ # { key = default.audio.sink value = { name = somesink } } # { key = default.audio.source value = { name = somesource } } # ] } } # 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 priority.driver = 20000 } } { factory = spa-node-factory args = { factory.name = support.node.driver node.name = Freewheel-Driver priority.driver = 19000 node.group = pipewire.freewheel node.freewheel = true #freewheel.wait = 10 } } # This creates a ALSA udev device that will enumerate all # ALSA devices. Because it is using ACP and has the auto-profile # property set, this will enable a profile and create associated # nodes, which will be automatically configured to their best # configuration with the auto-port-config settings. # Extra node and device params can be given with node.param and # device.param prefixes. { factory = spa-device-factory args = { factory.name = api.alsa.enum.udev alsa.use-acp = true device.object.properties = { api.acp.auto-profile = true api.acp.auto-port = true device.object.properties = { node.adapter = audio.adapt resample.disable = false adapter.auto-port-config = { mode = dsp monitor = false control = false position = preserve # unknown, aux } #node.param.Props = { # channelVolumes = [ 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.6 ] #} } #device.param.Profile = { # #idx = 0 # name = pro-audio #} } } condition = [ { minimal.use-udev = true } ] } # This creates a single PCM source device for the given # alsa device path hw:0. You can change source to sink # to make a sink in the same way. { factory = adapter args = { factory.name = api.alsa.pcm.source node.name = "system" node.description = "system" media.class = "Audio/Source" api.alsa.path = "hw:4" #api.alsa.period-size = 0 #api.alsa.period-num = 0 #api.alsa.headroom = 0 #api.alsa.start-delay = 0 #api.alsa.disable-mmap = false #api.alsa.disable-batch = false #api.alsa.use-chmap = false #api.alsa.multirate = true #latency.internal.rate = 0 #latency.internal.ns = 0 #clock.name = api.alsa.0 node.suspend-on-idle = false #audio.format = "S32" #audio.rate = 48000 #audio.allowed-rates = [ ] #audio.channels = 4 #audio.position = [ FL FR RL RR ] #resample.quality = 4 resample.disable = true #monitor.channel-volumes = false #channelmix.normalize = false #channelmix.mix-lfe = true #channelmix.upmix = true #channelmix.upmix-method = psd # none, simple #channelmix.lfe-cutoff = 150 #channelmix.fc-cutoff = 12000 #channelmix.rear-delay = 12.0 #channelmix.stereo-widen = 0.0 #channelmix.hilbert-taps = 0 #channelmix.disable = false #dither.noise = 0 #node.param.Props = { # params = [ # audio.channels 6 # ] #} adapter.auto-port-config = { mode = dsp monitor = false control = false position = unknown # aux, preserve } #node.param.PortConfig = { # direction = Output # mode = dsp # format = { # mediaType = audio # mediaSubtype = raw # format = F32 # rate = 48000 # channels = 4 # position = [ FL FR RL RR ] # } #} #node.param.Props = { # channelVolumes = [ 0.5 0.4 0.3 0.5 ] #} } condition = [ { minimal.use-udev = false } ] } { factory = adapter args = { factory.name = api.alsa.pcm.sink node.name = "system" node.description = "system" media.class = "Audio/Sink" api.alsa.path = "hw:4" #api.alsa.period-size = 0 #api.alsa.period-num = 0 #api.alsa.headroom = 0 #api.alsa.start-delay = 0 #api.alsa.disable-mmap = false #api.alsa.disable-batch = false #api.alsa.use-chmap = false #api.alsa.multirate = true #latency.internal.rate = 0 #latency.internal.ns = 0 #clock.name = api.alsa.0 node.suspend-on-idle = false #audio.format = "S32" #audio.rate = 48000 #audio.allowed-rates = [ ] #audio.channels = 2 #audio.position = "FL,FR" #resample.quality = 4 resample.disable = true #channelmix.normalize = false #channelmix.mix-lfe = true #channelmix.upmix = true #channelmix.upmix-method = psd # none, simple #channelmix.lfe-cutoff = 150 #channelmix.fc-cutoff = 12000 #channelmix.rear-delay = 12.0 #channelmix.stereo-widen = 0.0 #channelmix.hilbert-taps = 0 #channelmix.disable = false #dither.noise = 0 #node.param.Props = { # params = [ # audio.format S16 # ] #} adapter.auto-port-config = { mode = dsp monitor = false control = false position = unknown # aux, preserve } #node.param.PortConfig = { # direction = Input # mode = dsp # monitor = true # format = { # mediaType = audio # mediaSubtype = raw # format = F32 # rate = 48000 # channels = 4 # } #} #node.param.Props = { # channelVolumes = [ 0.5 0.4 0.3 0.5 ] #} } condition = [ { minimal.use-udev = false } ] } # This creates a new Source node. It will have input ports # that you can link, to provide audio for this source. #{ factory = adapter # args = { # factory.name = support.null-audio-sink # node.name = "my-mic" # node.description = "Microphone" # media.class = "Audio/Source/Virtual" # audio.position = "FL,FR" # monitor.passthrough = true # adapter.auto-port-config = { # mode = dsp # monitor = true # position = preserve # unknown, aux, preserve # } # } #} # This creates a new link between the source and the virtual # source ports. #{ factory = link-factory # args = { # link.output.node = system # link.output.port = capture_1 # link.input.node = my-mic # link.input.port = input_FL # } #} #{ factory = link-factory # args = { # link.output.node = system # link.output.port = capture_2 # link.input.node = my-mic # link.input.port = input_FR # } #} ] context.exec = [ #{ path = # ( args = "" | [ ... ] ) # ( condition = [ { = ... } ... ] ) #} # # Execute the given program with arguments. # # You can optionally start the pulseaudio-server here as well # but it is better to start it as a systemd service. # It can be interesting to start another daemon here that listens # on another address with the -a option (eg. -a tcp:4713). # ##{ path = "/usr/bin/pipewire" args = "-c pipewire-pulse.conf" } ] node.rules = [ { matches = [ { # all keys must match the value. ! negates. ~ starts regex. #alsa.card_name = "ICUSBAUDIO7D" #api.alsa.pcm.stream = "playback" } ] actions = { update-props = { #node.name = "alsa_playback.ICUSBAUDIO7D" } } } ] device.rules = [ { matches = [ { #alsa.card_name = "ICUSBAUDIO7D" } ] actions = { update-props = { #device.name = "alsa_card.ICUSBAUDIO7D" #api.acp.auto-profile = false #api.acp.auto-port = false #device.param.Profile = { # #idx = 0 # name = off #} } } } ]