diff options
| -rw-r--r-- | wireplumber/wireplumber.conf | 883 |
1 files changed, 883 insertions, 0 deletions
diff --git a/wireplumber/wireplumber.conf b/wireplumber/wireplumber.conf new file mode 100644 index 0000000..12a5843 --- /dev/null +++ b/wireplumber/wireplumber.conf @@ -0,0 +1,883 @@ +## The WirePlumber configuration + +context.spa-libs = { + ## SPA factory name to library mappings + ## Used to find SPA factory names. It maps a SPA factory name regular + ## expression to a library name that should contain that factory. + ## + ## Syntax: + ## <factory-name regex> = <library-name> + + api.alsa.* = alsa/libspa-alsa + api.bluez5.* = bluez5/libspa-bluez5 + api.v4l2.* = v4l2/libspa-v4l2 + api.libcamera.* = libcamera/libspa-libcamera + audio.convert.* = audioconvert/libspa-audioconvert + support.* = support/libspa-support +} + +context.modules = [ + ## PipeWire modules to load. + ## These modules are loaded before a connection to pipewire is attempted. + ## This section should be kept minimal and load only the modules that are + ## necessary for the protocol to work. + ## + ## If ifexists is given, the module is ignored when it is not found. + ## If nofail is given, module initialization failures are ignored. + ## + ## Syntax: + ## { + ## name = <module-name> + ## [ args = { <key> = <value> ... } ] + ## [ flags = [ ifexists | nofail ] ] + ## } + + # Uses RTKit to boost the data thread priority. Also allows clamping + # of utilisation when using the Completely Fair Scheduler on Linux. + { + name = libpipewire-module-rt + args = { + nice.level = -11 + # rt.prio = 88 + # rt.time.soft = -1 + # rt.time.hard = -1 + # uclamp.min = 0 + # uclamp.max = 1024 + } + flags = [ ifexists, nofail ] + } + + ## The native communication protocol. + { name = libpipewire-module-protocol-native } + + ## Support for metadata objects + { name = libpipewire-module-metadata } +] + +wireplumber.profiles = { + ## Syntax: + ## <profile> = { + ## inherits = [ other, profile, names ] # optional + ## # optional is the default + ## <feature name> = [ required | optional | disabled ] + ## ... + ## } + + # The default profile + main = { + inherits = [ base ] + + metadata.sm-settings = required + metadata.sm-objects = required + + policy.standard = required + + hardware.audio = required + hardware.bluetooth = required + hardware.video-capture = required + } + + # Profile for running on a systemwide level + main-systemwide = { + inherits = [ main, mixin.systemwide-session ] + } + + # Typical profile for embedded use cases, systemwide without maintaining state + main-embedded = { + inherits = [ main, mixin.systemwide-session, mixin.stateless ] + } + + # Profile for video-only use cases (camera & screen sharing) + video-only = { + inherits = [ main ] + hardware.audio = disabled + hardware.bluetooth = disabled + } + + ## + ## Profiles for multi-instance setup + ## + + policy = { + inherits = [ base ] + metadata.sm-settings = required + metadata.sm-objects = required + policy.standard = required + } + + audio = { + inherits = [ base ] + hardware.audio = required + } + + bluetooth = { + inherits = [ base ] + hardware.bluetooth = required + } + + video-capture = { + inherits = [ base ] + hardware.video-capture = required + } + + ## + ## The following are not complete profiles, but blocks that can be inherited + ## + + # The bare minimum that all instances should have by default + base = { + check.no-media-session = required + support.settings = required + support.log-settings = required + support.session-services = required + } + + # Disable features that are meant only for user sessions + mixin.systemwide-session = { + support.reserve-device = disabled + monitor.alsa.reserve-device = disabled + + support.portal-permissionstore = disabled + script.client.access-portal = disabled + + support.logind = disabled + monitor.bluez.seat-monitoring = disabled + } + + # Disable storing/restoring runtime state information regarding + # default nodes selection, profiles, routes and stream volume / properties + # This makes sense for embedded systems that should always reboot to a default + # state, not remembering any of the user's runtime changes + mixin.stateless = { + hooks.device.profile.state = disabled + hooks.device.routes.state = disabled + hooks.default-nodes.state = disabled + hooks.stream.state = disabled + } +} + +wireplumber.components = [ + ## WirePlumber components to load. + ## These components are loaded after a connection to pipewire is established. + ## type is mandatory; rest of the tags are optional + ## + ## Syntax: + ## { + ## name = <component-name> + ## type = <component-type> + ## arguments = { <json object> } + ## + ## # Feature that this component provides + ## provides = <feature> + ## + ## # List of features that must be provided before this component is loaded + ## requires = [ <features> ] + ## + ## # List of features that would offer additional functionality if provided + ## # but are not strictly required + ## wants = [ <features> ] + ## } + + ## Check to avoid loading together with media-session + { + name = ensure-no-media-session, type = built-in + provides = check.no-media-session + } + + ## Makes a secondary connection to PipeWire for exporting objects + { + name = export-core, type = built-in + provides = support.export-core + } + + ## Enables creating local nodes that are exported to pipewire + ## This is needed for LocalNode() / WpImplNode + ## This should be used with the export-core to avoid protocol deadlocks, + ## unless you know what you are doing + { + name = libpipewire-module-client-node, type = pw-module + provides = pw.client-node + wants = [ support.export-core ] + } + + ## Enables creating local devices that are exported to pipewire + ## This is needed for SpaDevice() / WpSpaDevice + ## This should be used with the export-core to avoid protocol deadlocks, + ## unless you know what you are doing + { + name = libpipewire-module-client-device, type = pw-module + provides = pw.client-device + wants = [ support.export-core ] + } + + # Provides a node factory to create SPA nodes + # You need this to use LocalNode("spa-node-factory", ...) + { + name = libpipewire-module-spa-node-factory, type = pw-module + provides = pw.node-factory.spa + requires = [ pw.client-node ] + } + + ## Provides a node factory to create SPA nodes wrapped in an adapter + ## You need this to use LocalNode("adapter", ...) + { + name = libpipewire-module-adapter, type = pw-module + provides = pw.node-factory.adapter + requires = [ pw.client-node ] + } + + ## Provides the "sm-settings" metadata object + { + name = libwireplumber-module-settings, type = module + arguments = { metadata.name = sm-settings } + provides = metadata.sm-settings + } + + ## Activates a global WpSettings instance, providing settings from + ## the sm-settings metadata object. Note that this blocks and waits for the + ## sm-settings metadata object to become available, so one instance must + ## provide that, while others should only load this to access settings + { + name = settings-instance, type = built-in + arguments = { metadata.name = sm-settings } + provides = support.settings + after = [ metadata.sm-settings ] + } + + ## Log level settings + { + name = libwireplumber-module-log-settings, type = module + provides = support.log-settings + } + + ## The lua scripting engine + { + name = libwireplumber-module-lua-scripting, type = module + provides = support.lua-scripting + } + + ## Module listening for pipewire objects to push events + { + name = libwireplumber-module-standard-event-source, type = module + provides = support.standard-event-source + } + + ## The shared D-Bus connection + { + name = libwireplumber-module-dbus-connection, type = module + provides = support.dbus + } + + ## Module managing the portal permissions + { + name = libwireplumber-module-portal-permissionstore, type = module + provides = support.portal-permissionstore + requires = [ support.dbus ] + } + + ## Needed for device reservation to work + { + name = libwireplumber-module-reserve-device, type = module + provides = support.reserve-device + requires = [ support.dbus ] + } + + ## logind integration to enable certain functionality only on the active seat + { + name = libwireplumber-module-logind, type = module + provides = support.logind + } + + ## Session item factories + { + name = libwireplumber-module-si-node, type = module + provides = si.node + } + { + name = libwireplumber-module-si-audio-adapter, type = module + provides = si.audio-adapter + } + { + name = libwireplumber-module-si-standard-link, type = module + provides = si.standard-link + } + + ## API to access default nodes from scripts + { + name = libwireplumber-module-default-nodes-api, type = module + provides = api.default-nodes + } + + ## API to access mixer controls + { + name = libwireplumber-module-mixer-api, type = module + provides = api.mixer + } + + ## API to get notified about file changes + { + name = libwireplumber-module-file-monitor-api, type = module + provides = api.file-monitor + } + + ## Provide the "default" pw_metadata + { + name = metadata.lua, type = script/lua + arguments = { metadata.name = default } + provides = metadata.default + } + + ## Provide the "filters" pw_metadata + { + name = metadata.lua, type = script/lua + arguments = { metadata.name = filters } + provides = metadata.filters + } + + ## Provide the "sm-objects" pw_metadata, supporting dynamic loadable objects + { + name = sm-objects.lua, type = script/lua + provides = metadata.sm-objects + } + + ## Populates the "session.services" property on the WirePlumber client object + { + name = session-services.lua, type = script/lua + provides = support.session-services + } + + ## Device monitors' optional features + { + type = virtual, provides = monitor.alsa.reserve-device, + requires = [ support.reserve-device ] + } + { + type = virtual, provides = monitor.alsa-midi.monitoring, + requires = [ api.file-monitor ] + } + { + type = virtual, provides = monitor.bluez.seat-monitoring, + requires = [ support.logind ] + } + + ## Device monitors + { + name = monitors/alsa.lua, type = script/lua + provides = monitor.alsa + requires = [ support.export-core, pw.client-device ] + wants = [ monitor.alsa.reserve-device ] + } + { + name = monitors/bluez.lua, type = script/lua + provides = monitor.bluez + requires = [ support.export-core, + pw.client-device, + pw.client-node, + pw.node-factory.adapter ] + wants = [ monitor.bluez.seat-monitoring ] + } + { + name = monitors/bluez-midi.lua, type = script/lua + provides = monitor.bluez-midi + requires = [ support.export-core, + pw.client-device, + pw.client-node, + pw.node-factory.spa ] + wants = [ monitor.bluez.seat-monitoring ] + } + { + name = monitors/alsa-midi.lua, type = script/lua + provides = monitor.alsa-midi + wants = [ monitor.alsa-midi.monitoring ] + } + ## v4l2 monitor + { + name = monitors/v4l2/name-device.lua, type = script/lua + provides = hooks.monitor.v4l2-name-device + } + { + name = monitors/v4l2/create-device.lua, type = script/lua + provides = hooks.monitor.v4l2-create-device + requires = [ support.export-core, + pw.client-device, + support.standard-event-source ] + } + { + name = monitors/v4l2/name-node.lua, type = script/lua + provides = hooks.monitor.v4l2-name-node + } + { + name = monitors/v4l2/create-node.lua, type = script/lua + provides = hooks.monitor.v4l2-create-node + } + { + name = monitors/v4l2/enumerate-device.lua, type = script/lua + provides = monitor.v4l2 + requires = [ support.export-core, + pw.client-device, + support.standard-event-source, + hooks.monitor.v4l2-create-device, + hooks.monitor.v4l2-create-node ] + wants = [ hooks.monitor.v4l2-name-device, + hooks.monitor.v4l2-name-node ] + } + ## libcamera monitor + { + name = monitors/libcamera/name-device.lua, type = script/lua + provides = hooks.monitor.libcamera-name-device + } + { + name = monitors/libcamera/create-device.lua, type = script/lua + provides = hooks.monitor.libcamera-create-device + requires = [ support.export-core, + pw.client-device, + support.standard-event-source ] + } + { + name = monitors/libcamera/name-node.lua, type = script/lua + provides = hooks.monitor.libcamera-name-node + } + { + name = monitors/libcamera/create-node.lua, type = script/lua + provides = hooks.monitor.libcamera-create-node + } + { + name = monitors/libcamera/enumerate-device.lua, type = script/lua + provides = monitor.libcamera + requires = [ support.export-core, + pw.client-device, + support.standard-event-source, + hooks.monitor.libcamera-create-device, + hooks.monitor.libcamera-create-node ] + wants = [ hooks.monitor.libcamera-name-device, + hooks.monitor.libcamera-name-node ] + } + + ## Client access configuration hooks + { + name = client/access-default.lua, type = script/lua + provides = script.client.access-default + } + { + name = client/access-portal.lua, type = script/lua + provides = script.client.access-portal + requires = [ support.portal-permissionstore ] + } + { + name = client/access-snap.lua, type = script/lua + provides = script.client.access-snap + } + { + type = virtual, provides = policy.client.access + wants = [ script.client.access-default, + script.client.access-portal, + script.client.access-snap ] + } + + ## Device profile selection hooks + { + name = device/select-profile.lua, type = script/lua + provides = hooks.device.profile.select + } + { + name = device/find-preferred-profile.lua, type = script/lua + provides = hooks.device.profile.find-preferred + } + { + name = device/find-best-profile.lua, type = script/lua + provides = hooks.device.profile.find-best + } + { + name = device/state-profile.lua, type = script/lua + provides = hooks.device.profile.state + } + { + name = device/apply-profile.lua, type = script/lua + provides = hooks.device.profile.apply + } + { + name = device/autoswitch-bluetooth-profile.lua, type = script/lua + provides = hooks.device.profile.autoswitch-bluetooth + } + { + type = virtual, provides = policy.device.profile + requires = [ hooks.device.profile.select, + hooks.device.profile.autoswitch-bluetooth, + hooks.device.profile.apply ] + wants = [ hooks.device.profile.find-best, hooks.device.profile.find-preferred, + hooks.device.profile.state ] + } + + # Device route selection hooks + { + name = device/select-routes.lua, type = script/lua + provides = hooks.device.routes.select + } + { + name = device/find-best-routes.lua, type = script/lua + provides = hooks.device.routes.find-best + } + { + name = device/state-routes.lua, type = script/lua + provides = hooks.device.routes.state + } + { + name = device/apply-routes.lua, type = script/lua + provides = hooks.device.routes.apply + } + { + type = virtual, provides = policy.device.routes + requires = [ hooks.device.routes.select, + hooks.device.routes.apply ] + wants = [ hooks.device.routes.find-best, + hooks.device.routes.state ] + } + + ## Default nodes selection hooks + { + name = default-nodes/rescan.lua, type = script/lua + provides = hooks.default-nodes.rescan + } + { + name = default-nodes/find-selected-default-node.lua, type = script/lua + provides = hooks.default-nodes.find-selected + requires = [ metadata.default ] + } + { + name = default-nodes/find-best-default-node.lua, type = script/lua + provides = hooks.default-nodes.find-best + } + { + name = default-nodes/state-default-nodes.lua, type = script/lua + provides = hooks.default-nodes.state + requires = [ metadata.default ] + } + { + name = default-nodes/apply-default-node.lua, type = script/lua, + provides = hooks.default-nodes.apply + requires = [ metadata.default ] + } + { + type = virtual, provides = policy.default-nodes + requires = [ hooks.default-nodes.rescan, + hooks.default-nodes.apply ] + wants = [ hooks.default-nodes.find-selected, + hooks.default-nodes.find-best, + hooks.default-nodes.state ] + } + + ## Node configuration hooks + { + name = node/create-item.lua, type = script/lua + provides = hooks.node.create-session-item + requires = [ si.audio-adapter, si.node ] + } + { + name = node/suspend-node.lua, type = script/lua + provides = hooks.node.suspend + } + { + name = node/state-stream.lua, type = script/lua + provides = hooks.stream.state + } + { + name = node/filter-forward-format.lua, type = script/lua + provides = hooks.filter.forward-format + } + { + type = virtual, provides = policy.node + requires = [ hooks.node.create-session-item ] + wants = [ hooks.node.suspend + hooks.stream.state + hooks.filter.forward-format ] + } + { + name = node/software-dsp.lua, type = script/lua + provides = node.software-dsp + } + + ## Linking hooks + { + name = linking/rescan.lua, type = script/lua + provides = hooks.linking.rescan + } + { + name = linking/find-media-role-target.lua, type = script/lua + provides = hooks.linking.target.find-media-role + } + { + name = linking/find-defined-target.lua, type = script/lua + provides = hooks.linking.target.find-defined + } + { + name = linking/find-filter-target.lua, type = script/lua + provides = hooks.linking.target.find-filter + requires = [ metadata.filters ] + } + { + name = linking/find-default-target.lua, type = script/lua + provides = hooks.linking.target.find-default + requires = [ api.default-nodes ] + } + { + name = linking/find-best-target.lua, type = script/lua + provides = hooks.linking.target.find-best + requires = [ metadata.filters ] + } + { + name = linking/get-filter-from-target.lua, type = script/lua + provides = hooks.linking.target.get-filter-from + requires = [ metadata.filters ] + } + { + name = linking/prepare-link.lua, type = script/lua + provides = hooks.linking.target.prepare-link + requires = [ api.default-nodes ] + } + { + name = linking/link-target.lua, type = script/lua + provides = hooks.linking.target.link + requires = [ si.standard-link ] + } + { + type = virtual, provides = policy.linking.standard + requires = [ hooks.linking.rescan, + hooks.linking.target.prepare-link, + hooks.linking.target.link ] + wants = [ hooks.linking.target.find-media-role, + hooks.linking.target.find-defined, + hooks.linking.target.find-filter, + hooks.linking.target.find-default, + hooks.linking.target.find-best, + hooks.linking.target.get-filter-from ] + } + + ## Linking: Role-based priority system + { + name = linking/rescan-media-role-links.lua, type = script/lua + provides = hooks.linking.role-based.rescan + requires = [ api.mixer ] + } + { + type = virtual, provides = policy.linking.role-based + requires = [ policy.linking.standard, + hooks.linking.role-based.rescan ] + } + + ## Standard policy definition + { + type = virtual, provides = policy.standard + requires = [ policy.client.access + policy.device.profile + policy.device.routes + policy.default-nodes + policy.linking.standard + policy.linking.role-based + policy.node + support.standard-event-source ] + } + + ## Load targets + { + type = virtual, provides = hardware.audio + wants = [ monitor.alsa, monitor.alsa-midi ] + } + { + type = virtual, provides = hardware.bluetooth + wants = [ monitor.bluez, monitor.bluez-midi ] + } + { + type = virtual, provides = hardware.video-capture + wants = [ monitor.v4l2, monitor.libcamera ] + } +] + +wireplumber.components.rules = [ + ## Rules to apply on top of wireplumber.components + ## Syntax: + ## { + ## matches = [ + ## { + ## [ <key> = <value> ... ] + ## } + ## ... + ## ] + ## actions = { + ## <override|merge> = { + ## [ <key> = <value> ... ] + ## } + ## ... + ## } + ## } + + { + matches = [ + { + type = "script/lua" + } + ] + actions = { + merge = { + requires = [ support.lua-scripting ] + } + } + } + { + matches = [ + { + provides = "~hooks.*" + name = "!~monitors/.*" + } + ] + actions = { + merge = { + before = [ support.standard-event-source ] + } + } + } + { + matches = [ + { provides = "~monitor.*" } + ] + actions = { + merge = { + after = [ support.standard-event-source ] + } + } + } + # session-services.lua must execute at the very end + { + matches = [ + { name = "!session-services.lua" } + ] + actions = { + merge = { + before = [ support.session-services ] + } + } + } +] + +wireplumber.settings.schema = { + ## Bluetooth + bluetooth.use-persistent-storage = { + description = "Whether to use persistent BT storage or not" + type = "bool" + default = true + } + bluetooth.autoswitch-to-headset-profile = { + description = "Whether to autoswitch to BT headset profile or not" + type = "bool" + default = true + } + + ## Device + device.restore-profile = { + description = "Whether to restore device profile or not" + type = "bool" + default = true + } + device.restore-routes = { + description = "Whether to restore device routes or not" + type = "bool" + default = true + } + device.routes.default-sink-volume = { + description = "The default volume for sink devices" + type = "float" + default = 0.064 + min = 0.0 + max = 1.0 + } + device.routes.default-source-volume = { + description = "The default volume for source devices" + type = "float" + default = 1.0 + min = 0.0 + max = 1.0 + } + + ## Linking + linking.role-based.duck-level = { + description = "The volume level to apply when ducking (= reducing volume for a higher priority stream to be audible) in the role-based linking policy" + type = "float" + default = 0.3 + min = 0.0 + max = 1.0 + } + linking.allow-moving-streams = { + description = "Whether to allow metadata to move streams at runtime or not" + type = "bool" + default = true + } + linking.follow-default-target = { + description = "Whether to allow streams follow the default device or not" + type = "bool" + default = true + } + + ## Monitor + monitor.camera-discovery-timeout = { + description = "The camera discovery timeout in milliseconds" + type = "int" + default = 1000 + min = 0 + max = 60000 + } + + ## Node + node.features.audio.no-dsp = { + description = "Whether to never convert audio to F32 format or not" + type = "bool" + default = false + } + node.features.audio.monitor-ports = { + description = "Whether to enable monitor ports on audio nodes or not" + type = "bool" + default = true + } + node.features.audio.control-port = { + description = "Whether to enable control ports on audio nodes or not" + type = "bool" + default = false + } + node.stream.restore-props = { + description = "Whether to restore properties on stream nodes or not" + type = "bool" + default = true + } + node.stream.restore-target = { + description = "Whether to restore target on stream nodes or not" + type = "bool" + default = true + } + node.stream.default-playback-volume = { + description = "The default volume for playback nodes" + type = "float" + default = 1.0 + min = 0.0 + max = 1.0 + } + node.stream.default-capture-volume = { + description = "The default volume for capture nodes" + type = "float" + default = 1.0 + min = 0.0 + max = 1.0 + } + node.stream.default-media-role = { + description = "A media.role to assign on streams that have none specified" + type = "string" + default = null + } + node.filter.forward-format = { + description = "Whether to forward format on filter nodes or not" + type = "bool" + default = false + } + node.restore-default-targets = { + description = "Whether to restore default targets or not" + type = "bool" + default = true + } +} |
