Compare commits

..

1031 commits

Author SHA1 Message Date
lumingzh
862925ff9b update zh_CN.po 2026-05-07 17:03:41 +08:00
Julian Bouzas
8b42a5a3ae wpctl: Apply the same volume to all nodes when setting by PID
Fixes #944
2026-05-05 07:43:21 -04:00
bhack
5a2f52dab4 spa-pod: mark borrowed string out params transfer none 2026-05-04 22:05:35 +02:00
Julian Bouzas
7fa44ef8d0 find-preferred-profile: Add new 'bluetooth.profile-preference' setting
This setting will use the best quality or latency profiles  for BT devices if
available. HSP/HFP profiles will always be ignored. The setting is a string that
only accepts 'quality' and 'latency' strings. Any other value will be treated
the same way as the 'quality' value.
2026-04-30 07:35:38 -04:00
qaqland
c579d1d839 wpctl: add bash completion for list subcommand
Refs: 85a7201409
Signed-off-by: qaqland <anguoli@uniontech.com>
2026-04-29 16:13:25 +03:00
Torkel Niklasson
26f5fc11a6 permission-manager: Add core_permissions support
The core object (ID 0) is implicit in the PipeWire connection and never
appears in the permission manager's ObjectManager. Add a
core_permissions field to set explicit permissions on it independently
of default_permissions.
2026-04-29 08:20:55 +02:00
Torkel Niklasson
1f0c590f49 docs: add WpPermissionManager API page and document permission managers in access config 2026-04-29 08:20:55 +02:00
zhouyong
1f8475b15f find-portal-access:Add a cache for camera permission checks to avoid frequent calls 2026-04-23 18:06:05 +08:00
zhouyong
bd4beadb43 portal-permissionstore: Add 3s timeout to D-Bus calls and fix Set create parameter 2026-04-22 19:39:05 +08:00
Sergey Veselkov
85a7201409 wpctl: add list subcommand to show objects in a more script-friendly format 2026-04-14 19:14:40 +03:00
Sergey Veselkov
5c0712322f meson: fix tools build without daemon 2026-04-14 18:38:55 +03:00
Марко М. Костић (Marko M. Kostić)
2fa1414fbe
po: Format the updated Serbian and Serbian Latin translations 2026-04-11 14:06:45 +02:00
Марко М. Костић (Marko M. Kostić)
45a2786c1b
po: Update Serbian and add Serbian Latin translations 2026-04-11 14:03:06 +02:00
George Kiagiadakis
409446046c Revert "object, registry: Increase prio of idle sources"
This is suspected to be the reason why the CI pipelines fail on some
of the linking tests. Reverting the commit for now, until the issue
is better understood.

See #934

This reverts commit 529aaa66cb.
2026-04-09 15:29:43 +03:00
Julian Bouzas
767a83a5f0 state-profile: Fix nil value when logging
Use warning instead of critical as there is no critical level API in Lua.
2026-04-09 11:00:07 +03:00
Julian Bouzas
f4f1a33446 permission-manager: Fix null pointer dereference
This fixes issue reported by coverity scan.
2026-04-09 09:26:51 +03:00
Julian Bouzas
e1874f8b31 wpctl: Connect to the manager socket if possible
This gives the tool unrestricted access.
2026-04-07 09:38:58 -04:00
Julian Bouzas
478c9402fc module: Call parent's destructor before finalizing
This fixes memleaks when unreferencing the module.
2026-04-01 08:36:39 -04:00
Julian Bouzas
210467c5ce scripts/client: Refactor scripts to use the new PermissionManager API
The refactoring uses a new 'select-access' event to select the access for each
client with a fallback mechanism. The fallback priority is: configuration,
flatpak, snap, portal, and default.

The access JSON configuration has also been improved so that users can create
their custom permission managers and attach them to any client. See the access
configuration example for more information describing how to do this.
2026-03-31 12:15:14 +03:00
Julian Bouzas
dcd59bc31d client: Add _attach_permission_manager () API
This attaches a permission manager to a client so that it can handle permissions
automatically when the interested objects have changed.
2026-03-31 12:15:14 +03:00
Julian Bouzas
c03f4fd4d7 m-lua-scripting: Add Lua API for WpPermissionManager
This allows using the new permission manager API in Lua scripts.
2026-03-31 12:15:14 +03:00
Julian Bouzas
484e1f0fb7 lib: Add new WpPermissionManager API
This allows setting object specific permissions on any client easily.
2026-03-31 12:15:14 +03:00
Julian Bouzas
78bd42cad8 bluez: Don't set bluez5.autoswitch-routes on BT devices
This seems to cause some issues with BT profile autoswitch.

See #932
2026-03-30 07:33:58 -04:00
Jonas Holmberg
529aaa66cb object, registry: Increase prio of idle sources
Raise the priority of all idle sources that need to be dispatched in
order to make the linking/linkable-added-immediate hook run.
2026-03-25 16:30:46 +01:00
Jonas Holmberg
374c48b339 event-dispatcher: Dispatch one event at a time
Return after dispatching one event so that other GSources also can be
dispatched in between events when there are many events in queue.
2026-03-25 16:30:46 +01:00
George Kiagiadakis
07e730b279 0.5.14 2026-03-25 12:49:03 +02:00
Barnabás Pőcze
c2b96ebb39 m-lua-scripting: impl_module_new(): fix property list memory leak
The `properties` argument of `wp_impl_module_load()` is marked
"transfer none", thus the caller's reference remains valid and
must be disposed of.

Fixes: ef29018c55 ("m-lua-scripting: Add WpImplModule bindings")
2026-03-20 20:30:44 +01:00
Torkel Niklasson
1cfeab9a86 linking: Make rescan optional on linkable changes
Split rescan-on-linkable triggering into a separate script file
(linking/rescan-on-linkable.lua) that can be disabled via
wireplumber.profiles by setting hooks.linking.rescan-on-linkable =
disabled.
2026-03-19 20:29:32 +02:00
Julian Bouzas
b453464320 autoswitch-bluetooth-profile: Switch/restore the profile using 'autoswitch-*' event hooks
Since 'autoswitch-*' events have lower priority than 'select-*' events,
this guarantees that the autoswitch hooks will always run after the
'device/apply-profile' hook, avoiding possible race conditions.
2026-03-19 20:25:38 +02:00
Julian Bouzas
7023ad0c2c m-standard-event-source: Add 'autoswitch-*' local event priority
These local events have lower priority than the 'create-*' and 'select-*' ones,
and are meant to be used when wireplumber wants to automatically switch profiles
or other things.
2026-03-19 20:25:38 +02:00
Julian Bouzas
20238072e2 autoswitch-bluetooth-profile: Ensure the saved profile is headset/non-headset before switching/restoring
Otherwise find the highest priority one.
2026-03-19 20:25:38 +02:00
Julian Bouzas
f38f1a2af8 autoswitch-bluetooth-profile: Rename device-profile-changed hook name to be more consistent
This makes all the script hooks more consistent.
2026-03-19 20:25:38 +02:00
Julian Bouzas
9fb963d4e5 autoswitch-bluetooth-profile: Don't evaluate if node state changes from 'idle' to 'suspended'
This is not needed and can improve performance a little bit.
2026-03-19 20:25:38 +02:00
Julian Bouzas
8dcf3ce6ed autoswitch-bluetooth-profile: Check profile names to see if a profile is headset
We cannot only rely on the input routes to check whether a profile is a headset
profile or not because some BT devices can have A2DP source nodes, causing the
autoswitch logic to not work properly.

This patch fixes the problem by also checking if the profile name matches the
'headset-head-unit*' or 'bap-duplex' patterns. If the profile name does not
match those patterns, the profile is not considered headset profile.

See #926
2026-03-19 20:25:38 +02:00
Julian Bouzas
2954e0d5e8 autoswitch-bluetooth-profile: Make sure current profile is valid before switching 2026-03-19 20:25:38 +02:00
Pauli Virtanen
76b26deabf monitors/bluez: Don't set api.bluez5.internal=true on HFP HF streams
Setting api.bluez5.internal=true changes media.class to
Audio/(Stream|Sink)/Internal which makes HFP HF output get wrong media
class.

Don't set this for headset-audio-gateway. Fixes HFP HF stream media
class.
2026-03-18 22:14:14 +02:00
Arun Raghavan
eef9baee61 apply-routes.lua: Add a mechanism for per-device default volumes
This allows us to have per-device configuration for device volumes, via
a `device.routes.default-volume` property. This allows a non-global
override for situations where we want to expose a different out-of-box
volume (say for an internal speaker where we know a better comfortable
default setting, or HDMI where we might want to avoid attenuation by
default).
2026-03-18 18:05:28 +02:00
NorwayFun
46638971c3 po: Update Georgian translation 2026-03-18 17:59:58 +02:00
Barnabás Pőcze
215c9efd02 monitors/libcamera: load node locally
At the moment the libcamera monitor and "Device" objects are loaded in the
wireplumber process, but the "Node" objects are loaded in the pipewire daemon.
Due to that, both processes have their own separate `libcamera::CameraManager`
objects. These operate independently.

As a consequence of the above, there is an inherent race condition: when a
new camera appears and the wireplumber process detects it and instructs the
pipewire process to create a "Node" for it, at that point, the camera might
not exist in the `CameraManager` of the "pipewire" process.

This can happen during the initial enumeration as well as hotplug. So load
the nodes locally in the wireplumber process so that all libcamera objects
use the same `CameraManager`, thus eliminating the race condition.
2026-03-18 17:35:33 +02:00
Robert Mader
f535befda4 systemd: allow mincore system call for Mesa/EGL
This is required in order to allow plugins to use GL as mincore
is used in Mesas `_eglPointerIsDereferenceable()`.

One example for a client wanting to do so is the in-development
libcamera GPUISP, see https://patchwork.libcamera.org/cover/24183/

(cherry picked from commit pipewire@4796b3fb9524c20ac0f5006143b6a13ee50c01ec)

See pipewire/pipewire!2530
2026-03-18 17:35:33 +02:00
Frédéric Danis
1762d91e75 wp-uninstalled: Allow to pass WIREPLUMBER_CONFIG_DIR 2026-03-18 17:29:42 +02:00
Baurzhan Muftakhidinov
355bb0fb8f Update Kazakh translation 2026-03-02 12:28:25 +02:00
Anders Jonsson
b262ac43be Update Swedish translation 2026-02-25 09:08:25 +02:00
twlvnn
38c07393e5 Updated Bulgarian translation 2026-02-21 13:07:17 +01:00
Julian Bouzas
83d08dfa43 bluez: Remove sink loopback node
Desktop environments like KDE and GNOME seem to have issues with sink loopback
nodes. Let's remove them for now.
2026-02-16 21:54:37 +02:00
Julian Bouzas
48ed27d11b state-stream: fix Lua 5.4 compatibility
The 'elseif' and 'else if' keywords are treated differently in Lua 5.4
2026-02-13 10:17:02 -05:00
George Kiagiadakis
de0bca5902 state-stream: fix crash in case the Format has a Choice for the number of channels
Fixes: #903
2026-02-06 11:28:34 +02:00
Achill Gilgenast
27337ed268
systemd: Allow installation of systemd services without libsystemd
Allows installation of systemd services without libsystemd installed.
Useful for Alpine Linux where systemd services are allowed to be subpackaged
(e.g. for postmarketOS) but hasn't systemd in it's repos.

It has no change in existing behavior, but installs services if the unit
directories are explicitly set.
2026-02-05 17:42:14 +01:00
Julian Bouzas
72b680fc4c bluez: Use 'target.object' instead of smart filters for BT loopback nodes
This allows treating BT loopback nodes as regular nodes.

See #898
2026-02-03 12:49:57 -05:00
Barnabás Pőcze
11af177902 event-hook: fix interest hook event type memory leak
In `wp_interest_event_hook_get_matching_event_types()`, the variable
`res` owns the allocated `GPtrArray`, but there is an early return
in the function. Hitting that will leak the allocation, so use
`g_autoptr` to avoid that.

Fixes: b80a0975c7 ("event-dispatcher: Register hooks for defined events in a hash table")
2026-01-29 12:47:27 +01:00
Barnabás Pőcze
2b78d9c20d meson: update lua wrap to 5.5.0
Update the lua wrap file to the latest lua version, which is 5.5.0.
2026-01-29 11:06:00 +01:00
Julian Bouzas
4cebb63d76 monitors/bluez: Always create loopbacks if Device support A2DP and HSP/HFP profiles
This simplifies a lot the logic as we don't need to destroy and re-create the
internal BT nodes right away if the loopback nodes were create after them.

We also now listen for changes in the BT profile autoswitch setting. If the
setting is disabled, the source loopback is destroyed. If it is enabled, the
source loopack is created. This makes the setting to take effect immediately,
without needing to disconnect and re-connect the BT device for the setting to
take effect.
2026-01-27 09:28:34 +02:00
Pauli Virtanen
d81b170bbf monitors/bluez: fix BAP device set channel prop
As properties are no longer Lua tables, we'll need to make a table copy
for the Json constructor.

Fixes assigning Json.Array to a non-table, and ending up with
"audio.position":"0x7b771267d690" instead of ["FL","FR"] in json output,
which caused BAP device set node to always have mono channels.
2026-01-26 19:56:28 +02:00
George Kiagiadakis
024f88322c wpctl: Allow virtual nodes in set-default command
Use prefix matching instead of exact matching for media.class when
validating nodes in the set-default command. This allows virtual
nodes (e.g. Audio/Source/Virtual) to be set as default devices,
while still excluding internal nodes.

Fixes #896

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 12:39:17 +02:00
Julian Bouzas
80842cbb96 default-nodes: Never consider Audio/Sink nodes as best for default audio.source node type
Audio/Sink nodes should only be used as default audio source node type if the
user has explicitly selected it. If the user has not explicitly selected it,
we should always ignore it and instead select the highest priority Audio/Source
node.

Fixes #886
2026-01-21 10:49:13 -05:00
Barnabás Pőcze
a5a079ec1d meson: accept lua 5.5 as well
Lua 5.5 was released on 2025-12-22[0], and wireplumber appears
to work fine with it.

[0]: https://lua.org/versions.html#5.5
2026-01-12 14:20:16 +01:00
Barnabás Pőcze
9040ec1e51 meson: simplify lua dependency lookup
Use an array to store all the possible dependency name suffixes and
look them up in order instead of manually doing each dependency lookup.
2026-01-12 14:20:16 +01:00
Julian Bouzas
f088a6f63d autoswitch-bluetooth-profile: Fix attempt to index a number value error
The getLinkedBluetoothLoopbackSourceNodeForStream() function expects stream to be
and object and not a stream ID.
2026-01-08 13:47:41 -05:00
Pauli Virtanen
b60b2f4ece monitors/bluez: request device ports take loopback nodes into account
Take the loopback nodes into account also in device Routes.

Some Pulseaudio applications (eg GNOME) determine what to do based on
device ports, so make sure they are consistent with what nodes will be
emitted.
2026-01-05 00:16:01 +02:00
George Kiagiadakis
84429b4794 0.5.13 2025-12-23 20:48:36 +02:00
Zander Brown
58b48c0a8a m-mpris: Check variant type directly 2025-12-23 20:05:09 +02:00
Zander Brown
af7a951bd9 m-mpris: We must chain up on finalize 2025-12-23 20:05:09 +02:00
Zander Brown
ded213093d m-mpris: Only initialise the builder once 2025-12-23 20:05:09 +02:00
Zander Brown
3a6f2c1e90 m-mpris: ‘Item’s are allocated with GLib
As are the string copies they point to, don't leak them and free them
the right way.
2025-12-23 20:05:09 +02:00
Zander Brown
1846d75717 m-mpris: ‘items’ is a GHashTable, not a GObject
That did fun things to my session that did.
2025-12-23 20:00:18 +02:00
George Kiagiadakis
444bfc04d8 Revert "state-routes.lua: Add new 'bluetooth.keep-volume-on-profile-changed' setting"
This reverts commit 00c272670c.

https://gitlab.freedesktop.org/pipewire/wireplumber/-/merge_requests/739#note_3163620
2025-12-23 19:57:12 +02:00
Julian Bouzas
3887e1ca82 monitor/bluez.lua: Don't set priority.driver in loopback nodes
Loopback nodes should never be the driver as it can cause audio issues.
2025-12-23 19:54:07 +02:00
Julian Bouzas
00c272670c state-routes.lua: Add new 'bluetooth.keep-volume-on-profile-changed' setting
If enabled, this setting will use the same volume levels as the previous
profile. This is useful on some bluetooth devices if the bluetooth profile
audioswitch is enabled.
2025-12-23 19:54:07 +02:00
Julian Bouzas
da831fdc65 monitors/bluez.lua: Create sink loopback for SCO-A2DP sink nodes
If the BT profile autoswitch setting is enabled, we also want to create a sink
loopback for SCO-A2DP sink nodes. Since BT nodes are removed and created again
when the profile changes, this avoids confusing some apps making them think
that the BT profile has not changed at all, because the loopback nodes are
always present, even when switching profiles.
2025-12-23 19:54:07 +02:00
Julian Bouzas
6a9e977d26 autoswitch-bluetooth-profile.lua: Refactor and fix issues with saved profiles
This patch improves the BT profile autoswitch logic so that it is simpler and
more robust. Instead of just relying on capture clients that are linked to (or
unlinked from) the BT loopback source node to evaluate whether we have to switch
to a headset profile or not, we now also evaluate the autoswitch every time the
BT loopback source node state changes. This avoids problems with some capture
clients that pause the input stream without closing them.

Apart from this, the patch also fixes some issues with saved profiles if the
user manually switched to a headset profile when no capture streams are present.
The autoswitch logic should restore back the non-headset profile (A2DP) every
time a capture client is disconnected or the BT loopback source node stops
running.

Finally, the 'bluetooth.autoswitch-to-headset-profile' setting will now register
or remove the necessary hooks depending on whether the setting is enabled or
disabled, improving WirePlumber performance if autoswitching is disabled.
2025-12-23 19:54:07 +02:00
filmsi
80478e7548 Update Slovenian translation (sl.po) 2025-12-16 16:03:57 +02:00
Barnabás Pőcze
3fb5b775ee m-modem-manager: Unref WpCore
When getting the "core" property from a `WpObject`, a strong reference is
returned to the `WpCore` object. This has to be unref-d when not needed
anymore. `wp_modem_manager_enable()` fails to do so, so fix it.

Fixes: 2794764d5a ("m-modem-manager: add module for tracking status of voice calls")
2025-12-16 15:59:07 +02:00
lumingzh
a5538f4167 update Chinese translation 2025-12-16 10:14:56 +08:00
Julian Bouzas
bec20fc054 create-item: Only configure audio device sink nodes in MONO
This allows multi channel mixing in the graph, even if MONO is enabled.
2025-12-08 09:43:56 -05:00
George Kiagiadakis
beded0214d meson: define SPA_AUDIO_MAX_CHANNELS only on newer spa headers
Older spa headers define this without an #ifndef check,
which could lead to compilation issues.
2025-12-02 12:59:58 +02:00
George Kiagiadakis
2286152c07 ci: adapt pipewire build options based on the pw version we are building 2025-12-02 12:32:01 +02:00
George Kiagiadakis
94fe1cbfbd ci: add builds with older versions of libpipewire 2025-12-02 11:59:45 +02:00
Torkel Niklasson
6ebf81453c rescan: Optimize linking for simple stream nodes
Add immediate linking for common cases to reduce latency when new
audio/video streams are added. The full rescan mechanism is preserved
and still triggers for all session-item-added events via the
rescan-trigger hook.
2025-11-28 11:05:34 +00:00
Wim Taymans
ceed5dca7c meson: bump max channels to 128
Recompiling with the SPA_AUDIO_MAX_CHANNELS=128u defined, will create
larger audio_info structures that can hold more channels. Because
PipeWire is now using 128 channels, do the same in wireplumber so that
the generated PortConfig param can hold all channel positions.

See pipewire#4995
2025-11-26 10:35:00 +01:00
Evangelos Ribeiro Tzaras
84e4752f1a m-modem-manager: Prefer automatic cleanup
Signed-off-by: Evangelos Ribeiro Tzaras <devrtz@fortysixandtwo.eu>
2025-11-25 14:41:42 +02:00
Evangelos Ribeiro Tzaras
9e390f1121 m-modem-manager: Avoid memory allocations unpacking string types
Signed-off-by: Evangelos Ribeiro Tzaras <devrtz@fortysixandtwo.eu>
2025-11-25 14:41:42 +02:00
Evangelos Ribeiro Tzaras
133b82e61a m-modem-manager: Don't leak path
Fixes: 2794764d5a (m-modem-manager: add module for tracking status of voice calls)

Signed-off-by: Evangelos Ribeiro Tzaras <devrtz@fortysixandtwo.eu>
2025-11-25 14:41:42 +02:00
Evangelos Ribeiro Tzaras
9045d2439a m-modem-manager: Don't leak error
And include the error message while we're at it.

Fixes: 2794764d5a (m-modem-manager: add module for tracking status of voice calls)

Signed-off-by: Evangelos Ribeiro Tzaras <devrtz@fortysixandtwo.eu>
2025-11-25 14:41:42 +02:00
Evangelos Ribeiro Tzaras
278541f637 m-modem-manager: Set GDBusConnection before trying to use it
Fixes: 2794764d5a (m-modem-manager: add module for tracking status of voice calls)

Signed-off-by: Evangelos Ribeiro Tzaras <devrtz@fortysixandtwo.eu>
2025-11-25 14:41:42 +02:00
Evangelos Ribeiro Tzaras
27b6027649 m-modem-manager: Use correct error clearing function
We segfault otherwise on error:

  Thread 1 "wireplumber" received signal SIGSEGV, Segmentation fault.
  g_type_check_instance_is_fundamentally_a (type_instance=type_instance@entry=0x7fffec008120,
      fundamental_type=fundamental_type@entry=0x50 [GObject]) at ../../../gobject/gtype.c:3917
  warning: 3917	../../../gobject/gtype.c: No such file or directory
  (gdb) bt
  #0  g_type_check_instance_is_fundamentally_a
      (type_instance=type_instance@entry=0x7fffec008120, fundamental_type=fundamental_type@entry=0x50 [GObject])
      at ../../../gobject/gtype.c:3917
  #1  0x00007ffff7eafe3d in g_object_unref (_object=0x7fffec008120) at ../../../gobject/gobject.c:4743
  #2  0x00007ffff4784ec1 in list_calls_done (obj=<optimized out>, res=<optimized out>, data=0x5555556ab1b0)
      at ../modules/module-modem-manager.c:209

Fixes: 2794764d5a (m-modem-manager: add module for tracking status of voice calls)

Signed-off-by: Evangelos Ribeiro Tzaras <devrtz@fortysixandtwo.eu>
2025-11-25 14:41:42 +02:00
Guido Günther
6398bf1bce docs: Switch to build directory for run invocation
There's no `Makefile` in the top level build directory so
switch to the build dir.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-11-24 23:23:51 +01:00
Julian Bouzas
f196d10e87 linking/rescan.lua: Clean a bit the code using the new properties API 2025-11-24 19:42:07 +02:00
Julian Bouzas
5071a85997 scripts: Fix compatibility issues with new Lua Properties API
We need to explicitly use Properties() in those cases as {} construct tables.
2025-11-24 19:42:07 +02:00
Julian Bouzas
15d98f59e5 state-routes: use get_count() instead of next()
We cannot use next() as the properties are not a Lua table anymore.
2025-11-24 19:42:07 +02:00
Julian Bouzas
be6f2b2926 m-lua-scripting: Handle both Properties and Lua tables in all Lua APIs 2025-11-24 19:42:07 +02:00
Julian Bouzas
01eb206460 m-lua-scripting: Add get_property() API for pipewire objects
This can be faster if we only want to get one property.
2025-11-24 19:42:07 +02:00
Julian Bouzas
5a4ecceee6 m-lua-scripting: Add get_property() API for session items
This can be faster if we only want to get one property.
2025-11-24 19:42:07 +02:00
Julian Bouzas
a35e40c1d2 m-lua-scripting: Add WpProperties API
Similar to Pod and Json, this API allows handling WpProperties references.
2025-11-24 19:42:07 +02:00
Julian Bouzas
2712cbb5a9 pipewire-object-mixin: Copy the props instead of wrapping them
This allows users to have full control of the properties when they get them.
2025-11-24 19:42:07 +02:00
Julian Bouzas
c68eb59017 device: Copy the props instead of wrapping them before emitting create-device signal
This allows the signal handlers to have full control of the properties.
2025-11-24 19:42:07 +02:00
Julian Bouzas
c0e047c241 apply-default-node: Make sure the metadata is valid
This fixes some warnings in the Lua tests scripts from tests/scripts/scripts/*
2025-11-24 19:42:07 +02:00
Julian Bouzas
238fd3c067 event-dispatcher: Sort hooks when registering them
This avoids sorting them constantly when collecting them. If a hook has a
circular dependency, a warning will be logged and the hook won't be registered.

See #824
2025-11-24 08:01:06 -05:00
Julian Bouzas
b80a0975c7 event-dispatcher: Register hooks for defined events in a hash table
Since all the current hooks are defined specifically for a particular event
type, we can register the hooks in a hash table using the event type as key
for faster event hook collection.

Also, hooks that are not specific to a particular event type, like constraints
such as 'event.type=*', will be registered in both the undefined hook list,
and also in all the hash table defined hook lists so they are always evaluated.

Even though 'wp_event_dispatcher_new_hooks_iterator()' can still be used, it is
now marked as deprecated because it is slower. The event hook collection uses
'wp_event_dispatcher_new_hooks_for_event_type_iterator()' now because it is
much faster.

Previously, the more hooks we were registering, the slower WirePlumber would
process events as all hooks needed to be evaluated for all events constantly.
This is not the case anymore with this patch. We can register thousands of
hooks, and if only 1 of those runs for a particular event, only 1 will be
evaluated instead of all of them.

See #824
2025-11-24 08:01:00 -05:00
qaqland
7ca21699a9 wpctl: add bash completions 2025-11-17 18:00:48 +08:00
Julian Bouzas
551353482a monitor/alsa: Also include alsa.* device properties for rule matching
UCM alsa nodes don't seem to have the 'alsa.*' properties from the device
included, which make it harder to match those nodes with alsa rules. This
patch adds all the 'alsa.*' properties in the UCM node to solve this.
2025-11-13 11:09:41 -05:00
George Kiagiadakis
f0b224b210 po: update Turkish translation
Closes: #871
2025-11-10 12:45:20 +02:00
George Kiagiadakis
0dad52f774 event-hook: simplify interest matching
We never use the feature of matching the subject type, so we can make
this simpler by not specifying CHECK_ALL, which also allows the
match_full() function to return early if some constraint doesn't match
instead of checking them all and wasting time.
2025-10-31 18:52:03 +02:00
Charles
27f97f6c45 monitors/alsa: Increase headroom for VMware and VirtualBox
Ubuntu received reports of very bad audio stuttering when running
25.10 in VMware & Virtualbox on Windows 11 hosts.

ac0d8ee4a8 dropped the headroom from
8192 samples to 2048. This seems fine for QEMU+KVM, but for unknown
reasons, the system emulation on Windows with these VMware/Virtualbox
is much slower, and xruns become frequent.

See:
https://bugs.launchpad.net/ubuntu/+source/wireplumber/+bug/2127250
https://discourse.ubuntu.com/t/vm-ubuntu2025-10-on-vmware-workstation-and-sound-problem/71066/3
2025-10-28 04:49:03 +00:00
filmsi
285230af67 Update Slovenian translation 2025-10-26 08:28:03 +00:00
Guido Günther
c095ae5254 role-based-policy: Allow to set target sink for media role loopbacks
There are streams that should go to a speaker rather than a headphone
or earpiece by default. Examples are alarms and emergency alerts on
phones. Allow to set a preference via
`policy.role-based.preferred-target` which then looks up the target
via `node.name` and `node.nick`.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-10-25 16:12:01 +03:00
Guido Günther
d2a49e8bc5 docs/linking: Fix typo
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-10-25 16:12:01 +03:00
Guido Günther
b2c4993ab5 doc: Fix role based policy name
The role-priority-system doesn't exist anymore

Fixes: 0d995c56 ("wireplumber.conf: improve standard policy definition")
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-10-25 16:12:01 +03:00
Julian Bouzas
ae30b4f022 state-profile: Handle new 'session.dont-restore-off-profile' property
This avoids restoring the Off profile if it was saved before. The property can
be set using the 'monitor.alsa.rules' section of the configuration.
2025-10-25 15:36:00 +03:00
Guido Günther
962be34a2b docs: Update rescan-for-linking priority
`rescan-for-linking` is the lowest priority linking event but the
`rescan-for-media-role-volume` event is lower overall priority.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-10-24 12:24:25 +02:00
Guido Günther
6f5ca5a79d wireplumber.conf: Enable default volume control tracking
Track a suitable default volume for media role based policies.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-10-24 12:20:33 +02:00
Guido Günther
5ecfe9f555 scripts: Add script to find a suitable volume control
When using role based priorities a volume slider presented to the
user should adjust the volume of the currently playing role.

E.g. when a phone has an incoming call and is ringing the default volume
slider should adjust the ringing volume and once the call has been
picked up it should adjust the call volume and once the call ended it
should adjust the media volume again.

It's currently hard for e.g. desktop shells to find out what a suitable
sink for volume control is so add a script to find a suitable target for
volume control (based on media role priority) by storing it's name in
the metadata.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-10-24 12:20:33 +02:00
Guido Günther
93377a8b4f m-std-event-source: Add rescan-for-media-role-volume
This allows us to do reduce the number of default volume updates.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-10-24 12:18:56 +02:00
Wim Taymans
ee72196500 m-si-audio-adapter: don't overread the position array
Limit the amount of channels we read from and write to the position
array with SPA_N_ELEMENTS(). The number of channels might be larger than
what we have positions for.
2025-10-21 16:31:00 +02:00
Julian Bouzas
e30c2a7cd9 state-routes.lua: Use the returned iterator from enum_params() to update routes info
This does not really fix anything but it saves some CPU cycles as we don't need
to get the route params from the cache anymore.
2025-10-17 09:05:27 -04:00
Julian Bouzas
4239055454 m-lua-scripting: Pass returned itrator to the closure when finishing enum_param()
We should not ignore the returned iterator as it allows users to get the exact
returned params after enumerating them, which might be useful in some cases.
2025-10-17 09:05:27 -04:00
Julian Bouzas
f188ddfb34 m-lua-scripting: Add WpIterator API
We skip the fold() API as the same thing can be done just using Lua closures.
2025-10-17 09:05:22 -04:00
Julian Bouzas
fb1738932b audio-group.lua: Demote creation of audio group log to info
This was never meant to be a warning message.
2025-10-17 15:49:02 +03:00
Julian Bouzas
f8be5a76e6 proc-utils: Make sure '/proc/<pid>/*' files exist before opening them
This avoids warnings if the specific file does not exist, especially when the
process has being removed quickly.

Fixes #816
2025-10-17 15:49:02 +03:00
Julian Bouzas
5c6a72e3cf m-si-standard-link: log error message when link activation fails
This makes debugging easier if a link fails to activate.
2025-10-17 08:41:48 -04:00
lumingzh
7b78078ed2 update Chinese translation 2025-10-14 10:01:43 +08:00
Julian Bouzas
6cfaf3f70d automute-alsa-routes.lua: Don't register/remove hooks if never registered/removed before
This avoids avent dispatcher errors in the log.
2025-10-13 16:15:34 +03:00
Julian Bouzas
2942903d0e scripts: Add node/filter-graph.lua 2025-10-13 15:48:41 +03:00
Arun Raghavan
38a21ea191 monitor/alsa: Add a setting to use HDMI channel detection
This allows us to set up the device to use HDMI ELD information for
channels. Not yet documented while we experiment with different ways to
make this work.
2025-10-10 15:44:48 -07:00
George Kiagiadakis
41b310c2d5 Add AGENTS.md
This helps steer LLMs when operating on this codebase - https://agents.md/

Mostly to help me with making releases for now
2025-10-10 18:03:07 +03:00
George Kiagiadakis
499916b996 0.5.12 2025-10-10 17:43:57 +03:00
Charles
627b003a05 m-permissions-portal: Avoid race condition during shutdown
Attempts to workaround a race condition between daemon thread and
GDBus worker thread during shutdown.

Ubuntu bug: https://bugs.launchpad.net/bugs/2127049

I've not been able to get a symbolic backtrace yet or reproduce it
myself, but the behaviour points to a threading bug. Hypothesis,

Main thread (1, daemon thread) shuts down, unregistering its plugins.
One of the plugins, module-permissions-portal, is triggered to
shutdown.
It tries to clear its GDBus connection handle without disconnecting
its signal handlers.
GDBus thread (2) is in the middle of writing a message on the same
connection handle.
Once finished, it also tries to clear its handle.
The main thread has already taken the signal lock and the signal
handler table ends up in an invalid state, triggering the assert.

I believe this could happen since
wp_portal_permissionstore_plugin_disable is not disconnecting its
signal handlers before trying to clear its DBus object.

See https://bugzilla.gnome.org/show_bug.cgi?id=730296 for more
discussion about this assert in the Glib signal handling code.
2025-10-10 13:04:01 +03:00
lumingzh
385fc83f46 update Chinese translation 2025-10-02 07:58:47 +08:00
Julian Bouzas
f82247c42c config: Add new 'node.features.audio.mono' setting
This setting allows users to toggle between MONO audio or not at runtime.
2025-10-01 18:59:13 +03:00
Julian Bouzas
084b3aab89 m-si-audio-adapter: Add new 'item.features.mono' configuration property
This allows configuring the audio adapter in MONO. The property is set to FALSE
by default.
2025-10-01 18:59:13 +03:00
Julian Bouzas
71f98c40f0 create-item: Reconfigure audio adapters if 'node.features.audio.*' settings changed
Up until now, all the 'node.features.audio.*' settings did not have any effect
if changed at runtime. This patch fixes this by reconfiguring the audio adapters
every time those settings have changed.
2025-10-01 18:59:13 +03:00
Julian Bouzas
2a4aa9281c m-si-audio-adapter: Configure the node ports if the item has been re-configured
If we re-configure the adapter with different settings than the ones from the
first configuration, we also need to configure the node ports to make sure they
are updated with the new settings.

For example, this is needed for stream audio adapters that have been configured
with monitor ports, and later re-configured without monitor ports. Without this
change, since stream audio adapters never configure the node ports on activation,
the internal node will still have the monitor ports present even after disabling
them in the 2nd re-configuration.
2025-10-01 18:59:13 +03:00
Julian Bouzas
35d63a7847 scripts: Add automute-alsa-routes.lua to auto-mute ALSA routes
This script mutes available output ALSA routes if an audio node that was
previously running was removed. This is useful for cases where users might
unplug their headset accidentaly, causing undesired loud audio to play on the
Speakers.

Two new settings are added to chose whether the user wants to do this for
ALSA devices, Bluetooth devices or both. The settings are set to false by
default.

Finally, a notification is also sent to notify the user that the devices were
muted.
2025-10-01 18:04:58 +03:00
Julian Bouzas
d21ff24ea1 modules: Add notifications-api module
This allows sending Desktop notifications using D-Bus.
2025-10-01 18:04:58 +03:00
lumingzh
68bd93e1ed Update Chinese translation 2025-09-29 12:49:33 +03:00
Carlos Rafael Giani
a461d9e738 object-interest: set pw_props variable if not set and global props exist
Otherwise, object manager lookups and iterations with type "pw" may
not work properly.
2025-09-10 15:04:36 +02:00
Julian Bouzas
ebd9d2a7d5 state-routes.lua: Make sure the device is still valid after doing enum_params() 2025-09-10 15:43:57 +03:00
Pablo Correa Gómez
7eacea9da9
apply-profile: add find-calling-profile to after array 2025-09-07 10:23:26 +02:00
Pablo Correa Gómez
dcf083ef3b
find-voice-call-profile: improve logging
To make it more specific to the hook and avoid confusion with the
best-profile one.
2025-09-07 10:23:26 +02:00
Pablo Correa Gómez
a6c0bb202d
scripts: document device/find-calling-profile hook 2025-09-07 10:23:26 +02:00
Pablo Correa Gómez
97d8761914
scripts: document device/find-preferred-profile hook 2025-09-07 10:23:26 +02:00
George Kiagiadakis
df0136ce0b docs: improve copyright & author statements 2025-09-05 18:19:25 +03:00
George Kiagiadakis
a5e58536dd docs: add wpctl man page and Tools documentation section
Add comprehensive wpctl documentation that generates both HTML docs and an installable man page from a single RST source.

Closes: #825

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 18:15:08 +03:00
Yukari Chiba
1bde4f2cdf device-info-cache: use Log.warning instead of Log.critical
Log.critical does not actually exist.
When logging error, it will in fact throw an exception:

[string "device-info-cache.lua"]:36: attempt to call a nil value
(field 'critical')

Change Log.critical to Log.warning to fix it.
2025-09-05 01:40:05 +08:00
George Kiagiadakis
3a785e5026 0.5.11 2025-09-02 16:26:40 +03:00
George Kiagiadakis
865cdcb89c conf: remove std-event-source dependency from the find-voice-call hook
This dependency must not be added here because it creates a circle.
m-standard-event-source is loaded after the hooks, as specified in the
wireplumber.components.rules section.
2025-08-29 19:55:18 +03:00
George Kiagiadakis
5ded5cbf1e lib: fix GObject introspection closure annotation warnings
Move closure annotations from data parameters to function parameters and
also add destroy annotations where necessary. This fixes the "invalid
closure annotation" warnings during the build.
2025-08-29 19:38:11 +03:00
Mark Nauwelaerts
e1807231ce global-proxy: also clear OWNED_BY_PROXY flag when proxy destroyed
... to avoid potential subsequent dangling pointer to proxy
2025-08-29 18:59:46 +03:00
Pauli Virtanen
8fdf726a66 linking: remove/add mpris-pause hooks on setting enable/disable
Remove mpris-pause hooks when the controlling setting is disabled,
and re-add when enabled, to avoid unnecessary processing.

Fix link tracking initialization, which previously never run. It worked
earlier since the event hook was registered early, but now it's needed.
2025-08-29 18:51:44 +03:00
Pauli Virtanen
2287c49139 po: restore deleted translations in sl.po 2025-08-29 18:22:13 +03:00
filmsi
9a89596ad2 Update Slovenian (sl) 2025-08-29 18:22:13 +03:00
Richard Acayan
0fd1b05b01 device-profile-hooks: add hook to select Voice Call profile
A "Voice Call" profile is supposed to be active during a call, even if
there is a higher priority device profile. Add a hook to select the
Voice Call profile when a call is active, and select a profile when
transitioning in and out of an active call.
2025-08-29 18:13:02 +03:00
Richard Acayan
2794764d5a m-modem-manager: add module for tracking status of voice calls
Voice calls can require special audio routing to work, such as by
switching the profile or opening an audio stream. Add a module to
monitor for the starting and stopping of a voice call.

Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-08-29 18:02:59 +03:00
Julian Bouzas
bc026593d6 m-dbus-connection: Add 'plugin.name' and 'bus.system' args
These allow creating a shared system D-Bus connection.
2025-08-29 18:02:59 +03:00
Julian Bouzas
ed58f65184 state-routes.lua: Don't save again the route when restoring it
There is no need to save the route again after it has been restored because its
value has not changed.
2025-08-22 12:15:13 -04:00
Julian Bouzas
5060b27a9e apply-routes.lua: Always set save=false when applying routes
When applying new routes, we always want the save property to be false because
it is done by WirePlumber (not the user). WirePlumber applies routes when
restoring them from the state file, or when finding the best routes after the
profile has changed. In both cases, it does not make sense to set save=true.
2025-08-22 12:15:13 -04:00
Julian Bouzas
ea6f24e861 state-routes: Don't save routes that are not available
If the user changed the volume on a ACP 'Headphones' route to a value different
than 100%, and then unplugs the jack headset, the ACP 'Headphones' route becomes
unavailable with volume set to 100% and the save flag not cleared.

Since the save flag is not cleared when the ACP 'Headphones' route becomes
unavailable, WirePlumber will save it with 100% volume, overriding the previous
volume value set by the user. This is not ideal because the volume will be
restored to 100% by WirePlumber when plugging back the headset.

This change fixes this by never saving routes that are not available.
2025-08-22 12:15:13 -04:00
Julian Bouzas
ebd6d49a81 state-routes.lua: Make sure routes cache is always updated when evaluating them
The Route params changed event can be emitted before the EnumRoute params with
some devices, causing wrong evaluation of the routes because their cached info
is not updated. This change always enumerates the EnumRoute params before
evaluating them to make sure the cache info is always valid.

Fixes: #762
2025-08-22 12:15:13 -04:00
Julian Bouzas
8ab6ae5897 m-lua-scripting: Add enum_params Lua API for WpPipewireObject 2025-08-22 12:15:08 -04:00
George Kiagiadakis
30e8440b25 Update Slovenian (sl) po file
Closes: #832
2025-08-15 18:53:26 +03:00
Demi Marie Obenour
15f5f96693 Fix Lua type confusion bug
The only secure and robust way to check that a userdata is of the
expected type is to check its metatable.  Userdata metatables are not
changeable by Lua code without the debug library, so if the metatable is
a certain table, only C code could have made it so.  GLib type checking
functions are _not_ a robust or secure way to check that a block of
memory is a specific type of GObject, because Lua code could cause a
type confusion bug and potentially use it to forge pointers.
2025-07-29 17:24:35 -04:00
Barnabás Pőcze
05c3f31362 script-tester: wp_script_tester_create_stream(): fix property list leak
The `WpProperties` object containing the properties of the stream
was not released after it was no longer needed. Fix that.
2025-07-29 09:18:46 +03:00
Barnabás Pőcze
83e992b238 lib: settings: iterator: release parent object reference
`wp_settings_new_iterator()` takes a reference to the underlying
`WpSettings` object with `g_object_ref()`, however, it fails to
release it during finalization. Fix that.
2025-07-28 21:23:59 +02:00
George Kiagiadakis
96848883fe lib: spa-type: convert constant to a #define to make it work in switch statements 2025-07-25 22:38:19 +03:00
Demi Marie Obenour
f3625bee61 lua: fix SPA POD array and choice builders
These builders had many bugs:

1. They would longjmp() across the destructor of a g_autoptr() if a Lua
   error was thrown.  This will leak the memory in the g_autoptr()
   unless Lua is compiled with C++ exceptions.
2. They depended on the iteration order of numerical keys in Lua tables.
   Lua explicitly does not specify this order.
3. They would produce nonsensical SPA POD array or choice types with
   strings or bytes as values.  These would cause undefined behavior if
   manipulated by naive C code, or assertion failures if
   spa_pod_is_array() and spa_pod_is_choice() are modified to check that
   the contents of arrays and choices have sensible types.
4. They silently accepted extra arguments, potentially causing confusion
   and making it harder to extend the functions in a
   backwards-compatible way.

Solve the first problem by calling functions that can raise a Lua error
in a protected environment (with lua_pcall).  If there is a Lua error,
rethrow it after the g_autoptr() destructor has run.

Solve the second problem by first obtaining the number of keys in the
table and then iterating over the keys that are expected to be present.
If any of the keys are not contiguious integers starting at 1, the range
[1..number of keys] will include a number that is not a table key.  This
will result in lua_rawgeti pushing a nil onto the Lua stack.  An
explicit check throws a useful error in this case.

Solve the third problem by explicitly checking that the type is
reasonable before building an array or choice.  If it is wrong,
a Lua error is thrown.

Solve the fourth problem by using luaL_checktype (L, 2, LUA_TNONE) to
check that no unwanted values were passed.  The C function called with
lua_pcall is passed every argument passed by Lua, followed by a light
userdata that stores a context pointer.  After the light userdata is
popped from the Lua stack, the Lua stack is identical to what Lua
created when it called the outer C function, so the type-checking
functions in the auxillary library can be used to enforce that only the
correct number and type of arguments were passed.
2025-07-24 12:36:29 +03:00
Demi Marie Obenour
0cba7b9525 lua: Push "_new", not '_' and then "new".
No functional change intended.
2025-07-24 12:36:29 +03:00
Demi Marie Obenour
2ea068de1b _wplua_pcall: avoid Lua stack overflow
C code must ensure that the Lua stack does not overflow.  Ensure there
are enough slots for both the error handler and for the return values.
2025-07-24 12:36:29 +03:00
Demi Marie Obenour
db755a6a19 lua: use Lua extradata to store the reference count
Lua provides "extra data", which is some memory in each Lua state that
the application can use for its own purposes.  Use this to store the
reference count.
2025-07-24 12:36:29 +03:00
Pauli Virtanen
36f809fb50 lib: settings: make settings name optional
The "name" field needs to be optional, to be backward compatible with
old settings spec format.  If it's omitted, make it NULL.
2025-07-24 12:14:33 +03:00
Pauli Virtanen
9e47393643 po: update Finnish translation 2025-07-24 11:44:04 +03:00
Pauli Virtanen
a32e31ffa1 wpctl: localize settings descriptions + show names 2025-07-24 11:44:04 +03:00
Pauli Virtanen
8d26e9f73c wireplumber.conf: provide human-readable names for settings 2025-07-24 11:44:04 +03:00
Pauli Virtanen
3b1acc5474 lib: settings: add wp_settings_spec_get_name() for human-readable name
Extend settings spec with a human-readable name, and add function to get
it.
2025-07-24 11:44:04 +03:00
Pauli Virtanen
a8283001d9 po: extract translatable strings from wireplumber.conf
Add rules to extract translatable strings from wireplumber.conf.

Meson i18n.gettext does not support extracting strings from
autogenerated files. Hence, we must commit conf.pot to repository.

These setting descriptions are meant to be user-facing. Translating them
allows also 3rd party apps to get the translations from 'wireplumber'
domain.
2025-07-24 11:29:44 +03:00
Pauli Virtanen
e070260c5c tools: add utility to extract strings from SPA-JSON for translation
Add utility that extracts strings from SPA-JSON files in POT format.
2025-07-24 11:29:20 +03:00
Pauli Virtanen
f6912ec23c wireplumber.conf: improve settings descriptions
The setting descriptions are in principle user-facing, so try to make
their descriptions more clear.
2025-07-24 11:29:16 +03:00
Pauli Virtanen
fb218fe016 scripts: add mpris-pause.lua to pause media streams when target removed
When current output target of a media player application is removed, it
can be useful if playback is paused (to avoid e.g. music playback to
going to speakers when headset is accidentally unplugged).  Android etc.
implement a policy like this.

Add a policy script that monitors stream target removals. When it
detects a media player application that is linked to a no longer present
output target, it checks whether the stream is associated with a media
player seen in MPRIS. If yes, it sends MPRIS Pause() command to the
media player.

Enable this policy by default.
2025-07-23 10:19:44 +03:00
Pauli Virtanen
bc713acafd m-mpris: add MPRIS plugin
Add a plugin module that can list active MPRIS media players, and send
Pause commands to them.
2025-07-23 10:19:44 +03:00
George Kiagiadakis
6430e747f9 gitlab-ci: s/systemd/libsystemd/ in pipewire's meson command line
See pipewire@f2c878a2
2025-07-23 10:15:06 +03:00
George Kiagiadakis
faf042a82b wpctl: set-profile: set the "save" flag on the selected profile
Fixes: #808
2025-07-01 13:37:02 +03:00
George Kiagiadakis
e9928b4beb default-nodes/README: update documentation regarding the select-default-node event 2025-07-01 13:20:22 +03:00
George Kiagiadakis
754c805061 default-nodes/find-best: skip the hook if a very high priority node is selected
Just to optimize a bit more for performance
2025-07-01 13:13:21 +03:00
George Kiagiadakis
f1c96843ee default-nodes/rescan: remove unused table and access node.properties only once 2025-07-01 12:52:36 +03:00
Julian Bouzas
a433a49e28 default-nodes: Use session and route priorities when finding the default node
Some PCM devices can expose multiple nodes with same session priorities but
different route priorities. This improves the default nodes logic to also check
the route priorities when the session priorities are the same.
2025-07-01 12:52:36 +03:00
Carlos Rafael Giani
e97551818a m-si-audio-adapter: Suspend node before setting Format and avoid redundancy
When a new Format param is set, the node's state is not checked, so this
attempt can even take place when the node is not suspended. Setting that
param will not work if the node isn't suspended though. Add a check for
the state and suspend the node if needed.

Also, do not set the Format param if the new param POD is the same as that
of the existing format to avoid redundant calls.

(This mirrors already existing checks for the PortConfig param.)
2025-06-27 13:08:30 +03:00
Julian Bouzas
84e2fcc050 monitor/alsa: Increase priority for USB devices
We always want the plugged USB ALSA device to have higher priority than the
internal ALSA device.
2025-06-26 14:05:38 -04:00
Richard Acayan
73f52cfb94 monitors/alsa: manage node when bound
If the managed node needs to emit events before it is bound, Wireplumber
treats it as destroyed and ignores the events. Add the node as pending
before it is bound so the node can run set_param on events that happen
before it gets bound.

Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-06-23 08:02:46 +03:00
George Kiagiadakis
f198f39f37 lib: module: clear the impl_module pointer when it is destroyed by itself
Some modules (like module-loopback) may destroy themselves with
pw_impl_module_schedule_destroy() when the pipewire connection closes.
In that case, we need to clear our pointer so that we don't try to
destroy them again (and crash)

Fixes: #812
2025-06-12 07:40:21 +03:00
George Kiagiadakis
7a4d317755 0.5.10 2025-05-21 07:32:15 +03:00
Tiago de Paula
ee42211bc6
fix: nil value in haveAvailableRoutes
Cause from partially renamed variables in af3c520d.

Closes #797
2025-05-21 01:00:59 -03:00
George Kiagiadakis
76b9e509d1 0.5.9 2025-05-19 12:32:21 +02:00
Philipp Jungkamp
404a634b92 docs: fix wrong description of software_dsp example 2025-05-18 15:49:59 +03:00
Julian Bouzas
0251d644a8 default-nodes/rescan: Check available routes using linking-utils
The linking-utils module already implements a way to check for available routes,
this patch uses it in default-nodes/rescan.lua to remove redundant code.
2025-05-18 14:11:53 +02:00
George Kiagiadakis
b8506d0d56 linking-utils: fix missing 'end' 2025-05-18 14:11:53 +02:00
George Kiagiadakis
af3c520d3e linking-utils: improve haveAvailableRoutes
Based on nodeHasAvailableRoutes() from default-nodes/rescan.lua
2025-05-18 13:56:14 +02:00
Julian Bouzas
050cd772be settings: cache setting values locally to avoid syncing issues
This patch caches the settings info to make sure their values are always
updated, even if using the settings API multiple times before pipewire
finishes synchronizing the metadata objects.

Fixes #749
2025-05-17 13:39:12 +03:00
Andrew Sayers
2a5606e437
Add TID and SYSLOG_{IDENTIFIER,FACILITY,PID} to log messages
Systemd journal entries have several common entries:
https://www.freedesktop.org/software/systemd/man/latest/systemd.journal-fields.html

Add "SYSLOG_IDENTIFIER" to make it easier to find wireplumber messages.
Add "SYSLOG_FACILITY" to avoid confusing programs that expect both or neither.
Add "TID" and "SYSLOG_PID" to make debugging a little easier.
2025-04-22 11:24:09 +01:00
David Mandelberg
08d7e51efb test-utils: make it possible to specify a device's props
The test I wrote for
https://gitlab.freedesktop.org/pipewire/wireplumber/-/issues/778 uses
this, since it needs a target-loudness to make a loudness filter:

```
tu.createDeviceNode (
  "default-device-node",
  "Audio/Sink",
  { ["device.target-loudness"] = -18 }
)
```
2025-04-11 13:55:24 +00:00
Pauli Virtanen
2d48caa74b monitors/alsa: fix nil table indexing
It's possible that managed_node.properties["node.name"] == nil if the
node is gone.

The removeDevice call above has already cleared the node names, so no
need to do it again.
2025-04-11 13:07:43 +00:00
George Kiagiadakis
9f440d0b50 monitors/libcamera: fix deduplicating devices with the same name 2025-04-11 15:53:44 +03:00
Lukas Riezler
e51e1b6080 v4l2/monitor: scripts: fix for deduplicate devices with the same name 2025-04-08 10:06:45 +02:00
David Mandelberg
a2605a2cdf Change node.dont-remix to stream.dont-remix
I'm guessing this was a typo? I ran `git grep dont-remix` in both
wireplumber's and pipewire's repos, and all the other references were to
stream.dont-remix, including the definition of PW_KEY_STREAM_DONT_REMIX.
2025-04-07 17:28:15 +00:00
Robert Mader
0d356f90ed monitor-utils: Support devices without any device ids
Such as libcameras virtual devices.
2025-04-07 17:04:22 +00:00
Andrew Sayers
1eed9669f1
Avoid spurious warnings when dbus.service stops
wireplumber.service generates the following when dbus.service
stops before it (e.g. when the user logs out):

    m-dbus-connection: <WpDBusConnection:0x556b3c561680> DBus connection closed: Underlying GIOStream returned 0 bytes on an async read
    m-dbus-connection: <WpDBusConnection:0x556b3c561680> Trying to reconnect after core sync

Stop the service before dbus.service exits, to avoid these messages.
2025-04-03 15:38:08 +01:00
Julian Bouzas
ce4f9b08a9 proc-utils: Make sure cgroup length is valid before removing EOF char
This fixes a Coverity Scan defect.
2025-03-05 13:36:04 -05:00
George Kiagiadakis
0f3e005a92 gitlab-ci: update fedora and alpine images 2025-03-05 19:05:12 +02:00
George Kiagiadakis
ff692952c4 docs: software_dsp: fix example config snippet
The wireplumber.profiles section is an object, not an array
2025-03-05 17:50:43 +02:00
Julian Bouzas
0b716118c7 scripts: Add audio-group-utils.lua to group audio streams
This allows grouping audio streams that have a pw-audio-namespace ancestor
process name. The grouping is done by creating a loopback filter for each group
or namespace. Those loopback filters are then linked in between the actual
stream and device nodes. A '--target-object' flag is also supported in the
ancestor process name to define a target for the loopback stream node.
2025-03-05 16:28:34 +02:00
Julian Bouzas
86cdfaccc4 lib: Add new proc-utils API for process utilities 2025-03-05 16:28:34 +02:00
Pauli Virtanen
78f1e34029 autoswitch-bluetooth-profile: use s-device log topic 2025-03-02 15:09:53 +02:00
Hugo
d222b957af Improve documentation for lua scripts
I had a hard time figuring out all the steps relevant for this to work.
Hopefully this brief summary and couple of links will help the next
person writing their own script.

See: #601
2025-02-24 06:48:40 +00:00
Andrew Sayers
eec702e4a1
Use wp_info() on normal termination
The service is normally stopped by SIGTERM.  Using wp_info() here
means users will be more likely to notice abnormal exits.
2025-02-21 13:03:11 +00:00
Andrew Sayers
07e8248928
Use wp_info() for "Loading profile" message
This is an ordinary progress message - nothing for the user to do about it.
2025-02-21 13:03:09 +00:00
Andrew Sayers
d91c366c2f
Change the new "skipping device" warning to debug
The other "skipping device" (a few lines later) uses log:debug,
so it makes sense for these to be the same.
2025-02-21 13:03:03 +00:00
Barnabás Pőcze
5846d12ea1 wpctl: fix types in variadic arguments
`wp_object_manager_add_interest()` passes the format string
and the arguments after that to `g_variant_new()`, which
requires a 32-bit integer for "u". Passing a 64-bit integer
will cause problems on certain ABIs.

Furthermore, remove the metadata related interest declaration
from `set_default_prepare()` since the "set-default" command
does not access metadata directly, it uses the "default-nodes-api"
plugin.

Fixes: 7784cfad92 ("wpctl: support @DEFAULT_{AUDIO,VIDEO}_{SINK,SOURCE}@ as ID ")
Fixes #773
2025-02-19 18:49:07 +01:00
Barnabás Pőcze
f3bc7168ed wpctl: fix default device name leak
The `get-default-configured-node-name` handler returns a copy
of the name of the node, hence it must be freed.
2025-02-19 18:35:42 +01:00
George Kiagiadakis
32d2abdf34 internal-comp-loader: generate a "provides" for components that don't have one
It is valid for components not to have a "provides" field, but it
prevents them from being able to have "before" and "after" dependencies.
With this patch, we generate a hidden "provides" field so that the
dependencies sorting algorithm can work without issues.

Fixes: #771
2025-02-13 16:06:29 +02:00
George Kiagiadakis
ac69acb3c2 0.5.8 2025-02-07 17:42:58 +02:00
George Kiagiadakis
b031d3fcd1 scripts: populate session.services via a script
See pipewire!1409 / wireplumber!441
2025-02-07 11:05:44 +00:00
George Kiagiadakis
b697546476 lua: bind wp_core_update_properties() 2025-02-07 11:05:44 +00:00
George Kiagiadakis
b8f0cf3644 monitors/bluez: make the source loopback node appear as non-virtual
Fixes: #729
2025-02-07 12:54:43 +02:00
George Kiagiadakis
14cbddd007 tests/scripts: fix tests to respect "object.serial" vs "node.id" differences
Fixes: #761
2025-02-07 08:54:05 +02:00
Twlvnn Kraftwerk
48a415bc8f Update Bulgarian translation
Based of on https://l10n.gnome.org/vertimus/WirePlumber/master/po/bg/

Signed-off-by: Alexander Shopov <ash@kambanaria.org>
2025-02-05 12:09:53 +01:00
luzpaz
cb770c1d7e docs: fix various codebase typos Found via codespell -q 3 -S "*.po,./po/*,NEWS.rst" -L bootup,gir,inout 2025-01-28 15:45:54 +01:00
Pauli Virtanen
899943bfcf monitors: disable stream-restore for device loopback nodes
stream-restore should not be touching node properties of the Bluetooth
mic / device set / offload / ALSA UCM split loopback nodes. Those are
controlled by Route settings on the device.

Set device.routes and state.restore-props=false as appropriate to avoid
that.
2025-01-26 21:33:22 +02:00
George Kiagiadakis
a1bc3d9285 lua: fix wp_lua_log_topic_copy() to copy the topic name correctly
Fixes: #757
2025-01-08 11:35:57 +02:00
Pauli Virtanen
4d02d0275f monitors/alsa: provide splitting of UCM SplitPCM nodes
Instruct ACP to provide information about UCM SplitPCM channel
splitting instead of doing it with alsa-lib plugins.

Use the provided information to load loopbacks that create virtual sinks
that do the channel remapping from UCM.
2024-12-23 11:42:23 +02:00
Pauli Virtanen
83e93876d5 lib: spa-device: fix POD props iteration + key lifetimes
Fix memory leaks in bad GValue handling.  Unset iterator GValue after
use and strdup keys.  The keys aren't necessarily static strings (for
id-XXXX properties), so have to be dup'd.
2024-12-20 19:44:36 +02:00
Pauli Virtanen
027aba7f3b monitors/bluez: rename api.bluez5.id -> spa.object.id
Use same name as in alsa monitor.
2024-12-19 18:45:16 +02:00
Pauli Virtanen
ada687a4cc monitors/alsa: decouple name deduplication from node objects
Node name deduplication relying on presence of node objects creates race
conditions, as the name cannot be marked unused if the node object was
not created or was destroyed.

Use separate (device_id, node_id) -> name table to track name ownership
separately from the existence of node objects.

Also clear up the reserved names when device is destroyed, by the
monitor or device reservation.  In these cases "object-removed" for
nodes is not called, so this fixes names leaking when e.g. pw-reserve is
used.
2024-12-19 18:41:01 +02:00
Pauli Virtanen
65989e7e38 monitors: use WpSpaDevice:set_managed_pending()
In cases where a Node is created asynchronously and associated with the
Device later, set the id pending so that we don't miss ObjectConfig
events.

The "set Route again" workaround is also not needed, moreover it was not
reliable before either since the Device might issue ObjectConfig only
for changed properties.
2024-12-15 20:51:55 +02:00
Pauli Virtanen
2df5d94697 m-lua-scripting: add WpSpaDevice:set_managed_pending 2024-12-15 20:51:55 +02:00
Pauli Virtanen
22ab3c938f lib: spa-device: add wp_spa_device_set_managed_pending()
Allow marking WpSpaDevice object ids "pending", which means Props from
any ObjectConfig events received for the ids are saved, if there is no
associated object set yet.

When wp_spa_device_store_managed_object() is called, any pending Props
are set on the managed object.

This is useful when nodes cannot be immediately created in the
"create-object" signal handler. For example, in cases where the nodes
are created asynchronously, e.g.  by "module-loopback".  In this case,
although the nodes can be later associated with the WpSpaDevice, any
ObjectConfig events received in the meantime are lost, so for example
restoring saved Routes will race against async node creation.  Using
wp_spa_device_set_managed_pending() solves this race condition.
2024-12-15 20:51:55 +02:00
Quentin
2bfc464444 Update Occitan locale 2024-12-10 17:18:41 +00:00
Pauli Virtanen
4c1a6f5840 monitors/bluez: recreate SCO source when loopback is emitted
If loopback is emitted after the SCO node, e.g. when A2DP profile
connects late, recreate the SCO node.

This ensures the underlying SCO node is hidden when the loopback is
present.
2024-12-09 20:28:53 +02:00
George Kiagiadakis
3e7c87a84c 0.5.7 2024-12-02 16:10:17 +02:00
George Kiagiadakis
4c07fd1da1 device: find-preferred-profile: define device_name variable
Fixes: #751
2024-12-02 12:18:42 +02:00
George Kiagiadakis
e76ebde6d8 conf.d.examples: improve alsa.conf
Completely remove references to auto-profile/auto-port.
It's better if users are not tempted to enable them.
2024-11-28 16:04:55 +02:00
George Kiagiadakis
f79d4b1b3b monitors: alsa: disable api.acp.auto-profile by default
This seems to be an omission from when we transferred the default device
properties from the config file on to the Lua script. Both auto-profile
and auto-port are meant to be disabled, so that we can apply our own
management logic.

Fixes: #734
2024-11-28 16:02:57 +02:00
George Kiagiadakis
77d2dcd97f autoswitch-bluetooth-profile.lua: drop local function declarations
There is no point in local functions in the global script scope.
We use a sandbox anyway to isolate from other scripts.
2024-11-28 11:55:38 +02:00
Pauli Virtanen
1ddb473deb monitors/alsa: handle node activation failure
When node activation fails, it won't be created and its object-removed
signal can be called with some properties missing.  This breaks node
name deduplication, causing error

wplua: [string "alsa.lua"]:182: attempt to concatenate a nil value (local 'node_name')

It occurs e.g. when switching ALSA device profile, while some
application has opened the device with ALSA and is keeping it busy.

Fix by handling the activation failure, and tolerating missing property
in object-removed.
2024-11-23 17:11:37 +02:00
Wim Taymans
f4f495ee21 node: cast proxy to pw_node* when calling pw_node functions
This currently works fine because the functions accept void* but will
fail when they accept struct pw_node* in the future.
2024-11-20 10:10:09 +01:00
Andika Triwidada
19526e128f Update Indonesian translation 2024-11-11 10:37:30 +00:00
Pauli Virtanen
b65b53b200 m-reserve-device: cancel get proxy callback properly
Cancel the async calls that get the name of the application owning the
service, when WpReserveDevice is finalized or we are going to make
another call.

Fixes UAF accessing self when the async callback runs.
2024-11-01 20:46:54 +02:00
Pauli Virtanen
71f8682337 po: update Finnish translation 2024-10-12 13:46:30 +03:00
Julian Bouzas
76985fff5b autoswitch-bluetooth-profile: Switch to HSP/HFP on timeout
This patch adds a 500ms timeout callback to switch to HSP/HFP when a stream
starts capturing BT audio. This avoids quickly switching from A2DP to HSP/HFP
back and forth if an application just wants to probe the BT source for a short
period of time.

See #634
2024-10-10 15:54:59 +00:00
George Kiagiadakis
881c7ce2d7 ci: improve the rules of the previous commit 2024-10-09 17:15:47 -04:00
George Kiagiadakis
e3fbc91abf ci: optimize the CI to run less when not needed
Some jobs do not make sense to be run on certain cases and we can save
CI cycles that way.

Most build rules can be run only on merge requests and custom branches.
On master, it only makes sense to build fedora_with_docs for the
purpose of deploying updated documentation on gitlab pages.
The analysis steps only make sense to run when the relevant files have
changed.
2024-10-09 17:05:19 -04:00
lumingzh
51b68a7c20 update Chinese translation 2024-10-09 18:03:54 +00:00
Arun Raghavan
f5ed10d857 ci: Add workflow rules to avoid duplicate branch/MR pipelines
Copied from pipewire@15b5185e6fa5d4437b6acd9cbdf7a698e01019ab
2024-10-09 14:01:16 -04:00
Jhonata Fernandes
3e101f6941 Update Brazilian Portuguese translation 2024-10-09 17:33:31 +00:00
Robert Mader
b2d2f656fd monitor-utils: Check all libcamera v4l2 devices
The actual deduplication only checked the first device. Extend it to the
full list, as intended.

Fixes: 848b6326 (monitor-utils: Rework camera deduplication code)
2024-10-03 10:46:49 +02:00
Robert Mader
848b6326a9 monitor-utils: Rework camera deduplication code
The previous code made some invalid assumptions and was rather
complicated. Rework and simplify it.

The approach work as follows:
1. Once a new device gets registered, store its data in a list of pending
   devices.
2. Start a timer. On timeout, we check all pending devices and depulicate
   according to our heuristic. The timer gets reset whenever a device is
   added in order to avoid race conditions.
3. On timeout, add the pending devices to categories. For now: UVC cameras
   from the V4L2 plugin, libcamera cameras and other cameras from the V4L2
   plugin.
4. Then process the different categories in order of preference and store
   their V4L2 device IDs in a list for each plugin.
5. Before creating a camera, check that the V4L2 device(s) it uses are not
   yet used by a already existing camera from the other plugin.

While on it, drop support for Pipewire versions that don't report V4L2
device IDs at all.

Closes https://gitlab.freedesktop.org/pipewire/wireplumber/-/issues/689
Closes https://gitlab.freedesktop.org/pipewire/wireplumber/-/issues/708
2024-09-30 01:06:40 +02:00
Barnabás Pőcze
ed80938b8c module-dbus-connection: fix GCancellable leak
`wp_dbus_connection_disable()` creates a new GCancellable
object at the end, which is never freed if the GObject
is then destroyed. To fix this, override `finalize()` and
clear everything there as well.

Direct leak of 64 byte(s) in 1 object(s) allocated from:
    0 0x70e688efd1aa in calloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
    1 0x70e6874b3e62 in g_malloc0 (/usr/lib/libglib-2.0.so.0+0x63e62) (BuildId: 7b781c8d1a6e2161838c5d8f3bd797797c132753)
    2 0x70e6875dea75 in g_type_create_instance (/usr/lib/libgobject-2.0.so.0+0x3ea75) (BuildId: 5af5e0f7d0a900ecb6083fbd71e22e5522d872e2)
    3 0x70e6875c3804  (/usr/lib/libgobject-2.0.so.0+0x23804) (BuildId: 5af5e0f7d0a900ecb6083fbd71e22e5522d872e2)
    4 0x70e6875c4e7e in g_object_new_with_properties (/usr/lib/libgobject-2.0.so.0+0x24e7e) (BuildId: 5af5e0f7d0a900ecb6083fbd71e22e5522d872e2)
    5 0x70e6875c5ed1 in g_object_new (/usr/lib/libgobject-2.0.so.0+0x25ed1) (BuildId: 5af5e0f7d0a900ecb6083fbd71e22e5522d872e2)
    6 0x70e684d2a8a6 in wp_dbus_connection_disable ../subprojects/wireplumber/modules/module-dbus-connection.c:173
    7 0x70e688a833cc in wp_plugin_deactivate ../subprojects/wireplumber/lib/wp/plugin.c:144
    8 0x70e688a7126c in wp_object_deactivate ../subprojects/wireplumber/lib/wp/object.c:542
    9 0x70e688a6e74e in wp_object_dispose ../subprojects/wireplumber/lib/wp/object.c:191
    10 0x70e6875c0f6c in g_object_unref (/usr/lib/libgobject-2.0.so.0+0x20f6c) (BuildId: 5af5e0f7d0a900ecb6083fbd71e22e5522d872e2)
    11 0x70e6841f7d6d in wp_portal_permissionstore_plugin_disable ../subprojects/wireplumber/modules/module-portal-permissionstore.c:207
    12 0x70e688a833cc in wp_plugin_deactivate ../subprojects/wireplumber/lib/wp/plugin.c:144
    [...]
2024-09-26 15:08:39 +02:00
Torkel Niklasson
255b65d182 m-mixer-api: Fix memory in leak wp_mixer_api_set_volume
Declare result from wp_object_manager_lookup as g_autoptr, to prevent
leaking memory.
2024-09-26 14:12:18 +02:00
Pauli Virtanen
b68a6794cd autoswitch-bluetooth-profile: switch only Bluetooth devices
Handle only devices associated with Bluetooth loopback nodes.

Make sure the node.link-group iteration cannot get stuck if there is a
loop in the link graph.
2024-09-10 07:51:03 +00:00
George Kiagiadakis
141b2d5d3f 0.5.6 2024-09-05 20:59:11 +03:00
George Kiagiadakis
f2013d8cd0 lib: wp_core_connect_fd: add \since marker 2024-09-05 20:19:33 +03:00
George Kiagiadakis
e7dc79859d docs: document multi-instance configuration profiles 2024-09-05 20:12:03 +03:00
Robert Rosengren
ec8975ac6a docs: clarified how to setup debug logs in lua 2024-09-05 10:52:28 +00:00
George Kiagiadakis
40e5dbff3d systemd: load the system instance with the 'main-systemwide' profile by default
This can still be overriden in the configuration file, if needed.

See #608
2024-09-03 11:40:05 +03:00
George Kiagiadakis
43ea3db02c wireplumber.conf: add systemwide, embedded and split-instance profiles
Revamp the profiles section, making use of the inherits feature
and add commonly used profiles for systemwide & embedded use cases,
as well as profiles for a split-instance configuration where the
policy hooks run in a separate instance from the alsa, bluetooth
and camera monitors (which run in 3 separate instances respectively)

Also add an example on how to configure the loaded profile using
a config file instead of the CLI switch.

Fixes: #608
2024-09-03 11:39:10 +03:00
George Kiagiadakis
a061018150 internal-comp-loader: implement profiles inheriting other profiles
This allows to inherit all the profile definitions of another profile
before the current profile's definitions are parsed, allowing for
more complex structures to be present in the default wireplumber.conf
without too much copy-paste
2024-09-02 17:00:53 +03:00
George Kiagiadakis
fae966558c wireplumber.conf: add before/after dependencies where needed
All hooks except the monitor ones should be loaded before the
standard-event-source and all the monitors should be loaded after.
2024-09-02 15:45:29 +03:00
George Kiagiadakis
32be79ee56 wireplumber.conf: improve the v4l2 and libcamera monitors components definitions
This was needlessly complicated and some of the requires did not make sense
2024-09-02 13:55:41 +03:00
George Kiagiadakis
89ab5616c0 tests: component-loader: fix GError memory leak 2024-08-31 20:47:45 +03:00
George Kiagiadakis
a245d5fa46 internal-comp-loader: implement before/after dependencies for components
In some cases, requires/wants dependencies are not enough. As we saw in
!617, the m-standard-event-source module needs to be loaded after all
the hooks, otherwise there may be missed events that the hook was
supposed to "catch", but they were delivered before the hook was actually
loaded. In a similar fashion, we have in purpose put all the "monitor"
components at the every end of the array because if we load them earlier,
they will create devices and nodes before all the hooks are in place to
react.

While in standard configuration we can work this around, in extended
user configurations with custom components, it is impossible to do this
without overriding the entire components array.

To fix this properly, introduce before/after dependencies. They work in
a similar fashion as they work with event hooks. They do not implicitly
"pull" any components to be loaded, but they affect the ordering if the
mentioned components are indeed present.

Note that for backwards compatibility reasons and unlike systemd units,
the "requires"/"wants" targets imply an "after" dependency on them.

Fixes: #600
2024-08-31 20:33:42 +03:00
George Kiagiadakis
479523abf9 lib: settings: find the first loaded instance of WpSettings when metadata_name is NULL
This allows changing the metadata name in the configuration file
and get all the Lua scripts looking at this new settings metadata
without requiring any other code changes. It can be useful in
multi-instance setups where we'd like the instances to be isolated
and load their own settings instead of relying on each other for that.
2024-08-29 17:15:50 +03:00
George Kiagiadakis
219711129e main: show the profile name on the app name
Useful in multi-instance configurations
2024-08-29 17:15:50 +03:00
tytan652
895c1c7286 lib: core: merge wp_core_connect implementations 2024-08-26 14:56:03 +00:00
tytan652
41523b68ba lib: core: allow to connect a core with a given socket 2024-08-26 14:56:03 +00:00
George Kiagiadakis
8c25ee2e19 po: add Slovenian (sl) language
Closes: #705
2024-08-26 17:33:36 +03:00
Julian Bouzas
0a86653085 autoswitch-bluetooth-profile: Use event source object managers
This patch removes the manually created object managers in the BT profile
autoswitch logic, and instead uses the object managers from the event source,
simplifying the logic a bit.
2024-07-12 10:18:12 -04:00
George Kiagiadakis
773fee315a docs: add info on how to set the log level via configuration 2024-07-09 08:59:18 +03:00
Julian Bouzas
afcb91f59b rescan: Stop rescan for 2s if BT node is removed
The intention here is to fix a Bluetooth bug where changing between different
profiles momentarily causes streams to be linked to an internal speaker.
Unfortunately, this case is not handled by the event dispatcher because some
signals are emitted using idle callbacks, and therefore we have to rely on
extra logic in rescan.lua to solve the problem.
2024-07-01 08:12:33 -04:00
Julian Bouzas
ff33f38bea rescan: Merge filters metadata changed hook with rescan-trigger 2024-06-28 11:42:11 -04:00
George Kiagiadakis
43e939c0e3 0.5.5 2024-06-28 18:18:02 +03:00
Julian Bouzas
c60475b293 wpctl: Make sure default node Id is updated when printing filters
This will properly show '*' for default sink filters in the status output.
2024-06-28 15:13:34 +00:00
George Kiagiadakis
11f10b4f45 Revert "lib: core: set the export core to be shared to pipewire modules"
This reverts commit 8012fbd5cf.

There seems to be some underlying bug that sometimes causes a crash
when the Bluetooth monitor uses a loopback for autoswitching between
profiles. Reverting temporarily until the cause is fully determined.

See #682
2024-06-28 18:01:56 +03:00
George Kiagiadakis
01a7339625 linking: explicitly mark targets that should be managed by the role-based policy
The previous assumption that any target with "device.intended-roles"
should be managed by the role-based policy is wrong, as for example
Bluetooth SCO nodes always have "device.intended-roles = Communication"
and some ALSA devices managed by ACP also do. This is meant to be used
as a hint for the desktop policy (it's been there in PulseAudio as well)
and does not necessarily mean that a role-priority-based policy should
be applied on all links to those devices.

Instead, use a new property to explicitly mark all the targets that
are meant to be managed by the role-based policy and respect that in
all places where we check for a potential role-based policy link.

Fixes: #682
2024-06-28 10:21:02 +03:00
George Kiagiadakis
abc299c1d3 linking: redefine script dependencies
This way of definining dependencies ensures that if we remove one
of the find-* hooks from the config, the rest of them will continue
to work in the expected order. Previously, removing one of them
would break the entire chain.
2024-06-28 10:21:02 +03:00
Julian Bouzas
96dc045382 l/find-best-target: Allow regular filters to be best targets
Similar to 4868b3c3 and fa671216, we always want to treat regular filters as
normal stream/device nodes.
2024-06-27 15:36:42 +00:00
George Kiagiadakis
fe42d931da linking-utils: fallback to role priority 0 if none is defined
See #682
2024-06-27 17:10:04 +03:00
George Kiagiadakis
dc6694fb84 0.5.4 2024-06-26 17:39:04 +03:00
George Kiagiadakis
d31615c58f smart-equalizer.conf: fix filter.smart.target usage example 2024-06-26 17:32:33 +03:00
George Kiagiadakis
317b5e8013 config: rename the duck-level option to have "role-based" in its name
Also, move the example from linking.conf to media-role-nodes.conf,
as it's more relevant there, and make sure the setting is constantly
read back in the Lua script, so that runtime changes can work.
2024-06-26 17:23:09 +03:00
George Kiagiadakis
52590ac850 docs: linking: update existing hooks documentation 2024-06-26 16:34:39 +03:00
George Kiagiadakis
d8fbf887b8 scripts: remove deprecated and outdated intended-roles.lua
This is now provided by find-media-role-target.lua
2024-06-26 16:30:45 +03:00
George Kiagiadakis
54d0f6fc7b l/rescan: use parseBool() to interpret boolean property
The previous check was also working, but this is safer
2024-06-26 16:19:32 +03:00
George Kiagiadakis
9436dc7afe s/link-target: mark links as role-based only if the role links rescan hook is enabled
Otherwise we would be left with broken links that are never activated
2024-06-26 16:11:00 +03:00
George Kiagiadakis
248b489b1b script-tester: load find-media-role-target.lua to fix test failure 2024-06-26 15:50:20 +03:00
George Kiagiadakis
39a1ce4eee config: add example that shows how to setup a smart equalizer filter 2024-06-26 15:50:20 +03:00
George Kiagiadakis
ebe158d8cb s/link-target: do not treat links to monitoring streams as role links
There are 2 cases captured here:

1. The stream has "stream.monitor = true", which is used
by pavucontrol for the vu meters and should probably not be managed
by the role policy, no matter if the target is a Source or a Sink

2. The stream is an Input (capture) stream and is targeting a Sink,
which may be used to target the sink's monitor ports. Even if we
want, we can't manage these links because they have opposite direction
than the one expected. Let's leave them alone...
2024-06-26 15:50:20 +03:00
George Kiagiadakis
fd4607b4f5 s/link-target: avoid holding a reference to the si in the link-error callback 2024-06-26 15:50:20 +03:00
George Kiagiadakis
fea6b11ad1 s/create-item: add setting to enforce a media.role on streams that don't have one 2024-06-26 15:50:20 +03:00
George Kiagiadakis
42727fcbc6 linking: move find-media-role-target hook to run later in the chain
A defined target should have priority over a role-based target
2024-06-26 15:50:20 +03:00
George Kiagiadakis
8012fbd5cf lib: core: set the export core to be shared to pipewire modules
pw_context allows sharing a core between modules and this is useful
to avoid having all the role loopbacks connect to pipewire on their own
2024-06-26 15:50:20 +03:00
George Kiagiadakis
b029e5a5b5 config: add example media-role-nodes.conf 2024-06-26 15:50:20 +03:00
George Kiagiadakis
0d995c56a8 wireplumber.conf: improve standard policy definition
First, add the find-media-role-target to the standard policy.
It does not affect anything and it doubles as the replacement
for intended-roles.lua, as it merely prioritizes linking nodes
that have "media.role" set to targets that have "device.intended-roles"
set to the corresponding role.

Second, make the rescan-media-role-links.lua also load as part
of the standard policy. The idea is to embrace this functionality
by default and make it available on desktops. It does not break
anything as well, but it will apply its own rules to links that
are created between nodes that have a
"media.role" <-> "device.indended-roles" match.
2024-06-26 15:48:07 +03:00
Ashok Sidipotu
5948539551 remove "virtual items" scripts, m-si-audio-virtual and related tests 2024-06-26 15:48:07 +03:00
Ashok Sidipotu
f6b77c7456 linking: role based priority system: hook to apply policy 2024-06-26 15:48:07 +03:00
Ashok Sidipotu
fcaece85e9 linking-utils: add routines to keep track of the priority media role link 2024-06-26 15:48:07 +03:00
Ashok Sidipotu
375094151d linking: get-filter-from-target.lua: bypass for media role targets 2024-06-26 10:16:10 +03:00
Ashok Sidipotu
4dd831424a linking: add a new hook to find media role targets 2024-06-26 10:16:10 +03:00
Julian Bouzas
4868b3c336 get-filter-from-target: Don't bypass the hook if the session item is a regular filter
Regular filters should be treated as regular stream / device nodes. Note that
the filter utils API is meant to be used using the direction of the main smart
filter nodes. This is why we use the target direction instead of the actual
stream direction to check if the stream session item is smart or not.
2024-06-25 14:15:46 -04:00
Julian Bouzas
fa67121665 filter-utils: Allow smart filters to have as target filters that are not smart
Filters that are not smart should be treated as regular client/device nodes,
therfore, smart filters should be able to use them as a target.
2024-06-25 14:05:43 -04:00
Wim Taymans
78dd8b1d8f tests: skip some tests when audiotestsrc is unavailable 2024-06-18 13:23:44 +02:00
George Kiagiadakis
47ec81408e scripts/device: avoid crashing if the device.name is not set
This should never happen, but there are odd cases with broken
configuration where such a device may appear and the least we can do
is not crash, at least not when the device.name is only used for
debug messages. In state-profile and other places where the name
really matters, we actually have checks in place.

Fixes: #674
2024-06-17 09:13:16 +03:00
George Kiagiadakis
31806862b0 tests/examples: add example on how to set node "params" under Props 2024-06-15 14:05:27 +03:00
Julian Bouzas
2353a0991b autoswitch-bluetooth-profile: Always destroy the restore timeout source before switching
We always have to destroy the restore timeout source when we want to switch to
HSP/HFP profile, even if the device is already set to HSP/HFP or has already an
input route. Apart from this, we also want to make sure there is no pending
timeout source when we are creating a new one. This should avoid an infinite
loop about switching BT profiles when capture nodes are created and destroyed
quickly.
2024-06-12 16:27:19 -04:00
James Calligeros
f57a46308d node/software-dsp: ensure that filter chains are properly unloaded
Indexing into the subject from a node-removed event is slightly quirky.
As a result, we were not properly freeing filter chains tied to
disconnected nodes.

Change how we store the list of loaded filters and ensure they
are properly freed when their parent node is removed from the graph.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-06-10 11:31:50 +00:00
Julian Bouzas
eb707096f7 scripts: Fix autoswitch BT profile when using filters
If a source filter is used, the BT profile autoswitch does not work because
WirePlumber thinks there is always a client capturing audio from it. This patch
fixes the issue by recursively walking through the source filters that are
linked to the BT loopback source until a stream is found. If a stream is found
at the end of the chain, then it switches to HSP/HFP profile, if the stream is
not found, the profile stays to A2DP.
2024-06-06 17:05:18 -04:00
Julian Bouzas
789b526c61 bluez: Don't create loopback source if autoswitch setting is disabled 2024-06-06 17:00:46 -04:00
George Kiagiadakis
be9259d952 conf: further improve how top-level objects are handled
With this change, it is possible to have a top-level object that does
not start at exactly the beginning of the file, allowing comments and
whitespace to exist.

Also add an empty conf file in the tests to verify that
it does not crash.
2024-06-02 15:47:09 +03:00
George Kiagiadakis
5235c025fe conf: skip empty configuration files to avoid crashing
g_mapped_file_get_contents() returns NULL if the file is empty

Fixes: #671
2024-06-02 15:17:06 +03:00
George Kiagiadakis
65e4ae83b9 0.5.3 2024-06-01 14:53:36 +03:00
Barnabás Pőcze
53e3cc7c7e metadata: remove incorrect transfer annotation 2024-05-31 23:03:12 +02:00
Barnabás Pőcze
b6595fb586 core: add missing \ingroup 2024-05-31 23:00:36 +02:00
Barnabás Pőcze
7e21e27ca9 docs: gen-api-gtkdoc.py: fix SyntaxWarning with raw strings
Use raw strings for regex patterns to avoid the invalid escape
sequence `SyntaxWarning`.
2024-05-31 22:54:13 +02:00
George Kiagiadakis
0b51b6b570 gi: hide WP_PRIVATE_API functions from gir
Document them and annotate them with (skip) so that they are
marked as introspectable=0 in the gir file.

Fixes: #599
2024-05-31 21:00:07 +03:00
George Kiagiadakis
ba0de72a9d tests: conf: test a few more edge cases
- split merge.conf into two files, one being standard JSON,
  to ensure we can parse this
- ensure that key-value pairs are correctly overriden when
  merging without the override. prefix
- remove context.modules, which is no longer needed there
- fix a typo with a stray ; character
2024-05-31 19:55:07 +03:00
George Kiagiadakis
5ec1d2c2e1 tests: conf: add test for as-section parsing 2024-05-31 19:54:04 +03:00
George Kiagiadakis
a3d5c8088b lib: conf: make it possible to parse files wrapped in {}, to allow standard JSON
A bit of refactoring was needed in order to avoid breaking as-section
loading, which expects the entire file to be an object or array and doesn't
parse it.

Fixes: #633
2024-05-31 18:35:32 +03:00
George Kiagiadakis
9847ca129a lib: spa-device: emit object-removed & create-object in sequence when an object is updated
In some cases the monitors emit the object_info callback with the same id
and non-NULL info multiple times. For example, when an ACP profile changes from
output:analog-stereo+input:analog-stereo to just output:analog-stereo, it emits
object_info() with NULL info for the input node and object_info() with updated
properties and the same id as before for the output node.

This causes the spa-device here to emit create-object multiple times for the
same object and this breaks the name deduplication logic. To solve this, make
sure we emit object-removed before calling create-object a second time.

Fixes #500
2024-05-31 17:04:18 +03:00
George Kiagiadakis
e6eed2dfb0 monitors/alsa: add some logging around node name deduplication 2024-05-31 17:03:33 +03:00
George Kiagiadakis
e3e8c9cdcb device/state-profile: do not restore unavailable profiles from the state file
Fixes: #613
2024-05-31 12:14:19 +03:00
George Kiagiadakis
9b4628455c node/create-item: simplify si properties configuration
Copy all the node properties into the session item and customize
afterwards, instead of starting with an empty set and cherry-picking
properties... We need to cherry-pick more and more properties
overtime and it's easy to make mistakes
2024-05-24 20:41:16 +03:00
George Kiagiadakis
df8bc12464 state-stream: fix using the default volume
When there was no previous state stored, the default volume was
also not applied because the code would return from the hook early

Fixes: #655
2024-05-24 20:36:28 +03:00
Julian Bouzas
b40ba825c2 filter-utils.lua: Check media type when finding the default filter
This avoids wireplumber trying to link a video stream node with the default
audio smart filter if smart audio filters are configured.
2024-05-24 07:33:21 -04:00
George Kiagiadakis
226be2e2b2 monitor-utils: fix variable check
See !636
2024-05-23 12:59:46 +03:00
George Kiagiadakis
2811d46a38 monitor-utils: make cam_api_data a local variable
Otherwise it is global and it retains a reference to the `parent`
WpSpaDevice object until this function is called again, which prevents
some camera nodes - in some cases - from being destroyed

Fixes #640
2024-05-23 12:35:23 +03:00
Barnabás Pőcze
4ed51791e0 linking: return after aborting transition
Avoid calling return_error() on the same transition multiple times.

Fixes: 4b153ec553 ("link-target.lua: change into a async hook")
See #628
2024-05-18 01:36:39 +02:00
Barnabás Pőcze
89b6766cd6 transition: ensure single completion and finish
At the moment, the same transition can be completed multiple times
(assuming sufficiently high reference count):

  return_error()
  finish()
  return_error()

The consequence of that is that the transition closure will be
invoked multiple times. This is unexpected.

Add some guards against completing a transition or calling finish()
multiple times.

Fixes #628
2024-05-18 01:36:39 +02:00
Barnabás Pőcze
1ddfbc532c transition: fix memory leak when error is already set
Fixes: 18377fbf82 ("transition: don't allow _return_error() to be called recursively")
2024-05-18 00:46:58 +02:00
Ashok Sidipotu
88d1dd86e5 wireplumber.conf: increase the cam discovery timer value 2024-05-08 14:20:16 +00:00
Ashok Sidipotu
a6328cf2c1 m-lua-scripting: correct typo 2024-05-08 14:20:16 +00:00
Ashok Sidipotu
06e11dc4be monitors/camera: fix camera device deduplication not working for certain devices.
Enhance the parsing logic to consider more than one device number. libcamera
devices some times use up multiple V4L2 devices, in this case libcamera should
be given a chance to enumerate the device.

Fixes #623
2024-05-08 14:20:16 +00:00
Tom Hughes
ae983e6fd7 Improve monitoring of seat state
If the user is reported as active then check that they have at
least one active seat and downgrade the status to online if not.

This ensures that a remote login session won't be interpreted as
the user being active on a local seat.
2024-05-08 13:58:16 +00:00
George Kiagiadakis
3e643aad85 log: use G_GNUC_DEPRECATED_FOR to deprecate wp_log_checked 2024-05-03 13:46:52 +00:00
Pauli Virtanen
2fb055f43d log: add wp_logt_checked taking WpLogTopic, to decide on debug messages
Make decision on whether to show code location in journal messages based
on whether the WpLogTopic would enable DEBUG level messages.

Add wp_logt_checked API to take WpLogTopic as input to make this
possible, and deprecate wp_log_checked.
2024-05-03 13:46:52 +00:00
Pauli Virtanen
8016ad1cec log: prepend topic to journald logs & add locations on debug levels
Logging messages are usually developed based on the stderr logging,
which shows code location and log topics as context, and especially
higher log level messages can be cryptic or useless without that
context.

This context is not shown in journalctl by default, and so usually is
missing from logs submitted by users. In principle it is available in
journalctl but requires extra work to show it.

Fix by prepending the log topic to the messages, like Pipewire logging
does. Also show code locations if log level is high enough.
2024-05-03 13:46:52 +00:00
George Kiagiadakis
4eb9454ceb wireplumber.conf: add a video-only profile
For systems where only camera & screensharing are to be used.

Fixes: #652
2024-05-03 16:13:10 +03:00
George Kiagiadakis
e6a70db254 json-utils: fix overriding of non-container values when merging
Non-container values should always be overriden

Fixes: #653
2024-05-03 15:54:37 +03:00
Julian Bouzas
0bd64f17af filter-utils: Check main filter nodes in a more robust way
This patch makes the check more robust when detecting main filter nodes. This is
because some filters might append '/Internal' to their main node media class.
The direction check has also been improved to work with Video filters.
2024-05-02 12:26:55 -04:00
Stefan Ursella
709eecb21f lua: json: fix error ouput 2024-04-30 05:32:33 +00:00
Stefan Ursella
fd7a1af7ff lua: json: add method to merge json containers 2024-04-30 05:32:33 +00:00
Pauli Virtanen
42370f0547 scripts: fix event:get_data() usage in apply-profile
event:set_data() coerces Lua tables to properties, so that keys and
values become strings.  Take into account that profile.index is a string
due to this.

Fixes WP setting the profile, even though it is already the active one.
2024-04-27 17:48:16 +03:00
George Kiagiadakis
b302ebd6ab 0.5.2 2024-04-22 17:19:47 +03:00
Pauli Virtanen
7f30adeb42 core: fix WpLoopSource lifecycle
Currently nothing removes the WpLoopSource from the main context, and we
moreover are creating and attaching unused WpLoopSources when sharing
same pw_context between multiple WpCore.

Fix this by keeping track of the WpLoopSource in the pw_context user
data, only creating them when needed, and finalizing it after the
context is destroyed.
2024-04-22 08:49:28 +00:00
Pauli Virtanen
7997fd490b core: keep pw loop entered exactly when it is running
It is intended that the Pipewire loops are "entered" the whole time they
are running, i.e. are going to process further events. Currently we
enter/leave for single iterations, which is not right.

Fix by entering the loop on initial GSource idle callback, and leaving
at finalize.

That the loop has to be left from the same thread it was entered from is
a bit hard to do with GSources, as the finalize callback appears not
guaranteed to be called from any particular thread.  I didn't find a
fully general way to do this, so this puts additional constraints on how
WpLoopSource (and WpCore) are to be cleaned up.
2024-04-22 08:49:28 +00:00
George Kiagiadakis
e4f9fb824e default-nodes: fallback to priority.driver if priority.session is not set
See #642
2024-04-22 11:39:45 +03:00
Stefan Ursella
473e463c56 meson: create the lib version like pipewire
If we use the project version as library version,
it is not possible to append something to the
project version to indicate a modified wireplumber version.
2024-04-18 09:35:23 +00:00
James Calligeros
1844fd6d61
Revert "node/software-dsp: do not hide target node when hide-parent is false"
Using parseBool is actually more broken if the property is already parsed as a
boolean, and causes the node to remain unhidden even when hide-parent = true.

Revert 2a45842169 to fix this behaviour.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-04-17 18:31:09 +10:00
James Calligeros
4c57647203
docs: document filter-path property of software DSP policy
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-04-17 18:31:09 +10:00
James Calligeros
d89293b606
node/software-dsp: implement loading filter graphs from disk
Using the new Conf() constructor, we can load and parse a filter graph
from a file on disk. This is useful when, for example, maintaining a
large database of filter graphs. It also keeps wireplumber.conf.d free
from clutter.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-04-17 18:31:09 +10:00
James Calligeros
d77edf70e9
lua: allow Conf methods to be indexed or called
Given that we are allowing Conf() to instantiate a new WpConf,
the methods on the class need to be callable in reference to Self while
maintaining API compatibility with being indexable from the table as a
static method.

Allow this by checking if the first argument passed in is userdata.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-04-17 18:31:09 +10:00
James Calligeros
f769ea8f30
lua: add constructor and file ops for WpConf
This exposes the ability to load a SPA-JSON representation of a WpConf
object from an arbitrary file on disk to the Lua API

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-04-17 18:31:04 +10:00
James Calligeros
59d29f37ac conf: allow a SPA-JSON container to be loaded as a named WpConf section
A "plain" JSON object may be passed to WpConf constructors. Previously, this
would cause an error as open_and_load_sections expects the first parsed token
to be a string. Use WpProperties to denote that the file being parsed is an
object/container, and specify a section name for it.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-04-09 13:15:50 +00:00
James Calligeros
34040d8e44 conf: allow a WpConf to be loaded without fragments
Use WpProperties to indicate that searching for and loading
conf.d fragments can/should be skipped.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-04-09 13:15:50 +00:00
James Calligeros
42666e2054 conf: Add WpProperties as a member of WpConf
WpProperties may be used to control the behaviour of a WpConf
object. This allows those properties to be referenced at any time
during the lifetime of a WpConf.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-04-09 13:15:50 +00:00
James Calligeros
105d53025e conf: explain behaviour of wp_base_dirs_find_file
The signature of the function is quite misleading. If an absolute
path is passed to it, it will ignore the directory constraint flags
and search outside of the specified directories anyway. Make a note
of this in its caller.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-04-09 13:15:50 +00:00
George Kiagiadakis
8892204f24 wplua/sandbox: support mixing static methods and constructors in class identifiers
Global class identifiers, such as "Node", "SessionItem", "Conf", etc
are so far defined either as methods, which are constructors for
the GObject class, or as tables, which contain "static" methods, i.e.
methods that can be called without an instance.

In some cases, we may want to mix a class being both instantiatable
with a constructor and also have static methods. To support this,
allow the class identifier be declared as a table with the constructor
being defined as the "__new" method. This change allows calling the
table as a method and execute "__new" underneath.

For instance:
```
json = Conf.get_section_as_json("foobar") -- static method
conf = Conf("/foo/bar") -- constructor, equivalent to Conf.__new("/foo/bar")
```

See also !629
2024-04-09 13:15:50 +00:00
Pauli Virtanen
9d7c6b85d0 monitors/bluez: fix BAP device set node naming
It is intended that its name is the actual device node name.
Fix this, as it was broken in some recent changes.
2024-04-06 21:59:16 +03:00
George Kiagiadakis
8ee351838d monitor-utils: clear cam data after creating nodes
The cam_data structure stores a reference to the "parent" WpSpaDevice
and doesn't allow it to be destroyed when the monitor detects that
the device is no longer present. Clear it right after pushing the event
to make sure there's no dangling reference left around

Fixes: #627
2024-04-03 12:31:42 +00:00
George Kiagiadakis
7856124df0 core: set context.modules.allow-empty to silence warning in pw_context
See cddea858d9

Closes: #620
2024-04-03 11:52:18 +03:00
George Kiagiadakis
961450b2ac 0.5.1 2024-03-30 16:50:38 +02:00
George Kiagiadakis
1fddefa072 docs: move the software_dsp document down in the TOC
This is one of the least likely things that a user would want to
discover and use, making it wierd to be the very first "policy"
to present.
2024-03-30 15:52:14 +02:00
George Kiagiadakis
ab18cb1848 docs: improve the wording and formatting of the software_dsp doc 2024-03-30 15:44:38 +02:00
George Kiagiadakis
3b0c0fcd7e state-stream: fix storing/restoring notification volume
We apparently store things in the <media-class>:<key>:<value>
format, while pipewire-pulse expects <media-class>.<key>:<value>
and this detail was missed in the latest refactoring.

It also seems that I forgot to ensure that restoring this metadata
key worked. The hook was there, but not registered.
Remove the hook and directly populate the metadata object when
it is activated, as it seems simpler.

Fixes: #604
2024-03-30 11:53:45 +02:00
James Calligeros
2a45842169
node/software-dsp: do not hide target node when hide-parent is false
The existence of props["hide-parent"] is truthy. Parse the boolean explicitly
to get the correct logic.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-03-30 00:00:57 +10:00
James Calligeros
b45eafa53c
docs: Document automatic software DSP handling
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-03-30 00:00:52 +10:00
James Calligeros
692e6e4b5b
wireplumber.conf: add node.software-dsp to wireplumber.components
This component provides the automatic filter graph interface to consumers.
We provide the component by default, however it is not activated unless
explicitly requested in wireplumber.profiles by a consumer.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-03-29 23:49:21 +10:00
James Calligeros
82b0ec8c30
node/software-dsp: Port Node ObjectManager to SimpleEventHook
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-03-29 23:48:09 +10:00
James Calligeros
9ab7c024f8
node/software-dsp: get match rules from conf.d
This allows DSP rules to be specified in a wireplumber.conf.d file under
the node.software-dsp.rules section. Properties are specified in the
software-dsp action.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-03-29 23:46:54 +10:00
James Calligeros
d5217fd4b6
node/software-dsp: move and rename scripts/policy-dsp.lua
As this DSP "policy" is intended to run on the creation/deletion
of a node, move it into the node subdir.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-03-29 22:44:53 +10:00
James Calligeros
62dd6effa8
policy-dsp: allow matching on all node properties
Prevously, we were only looking at node["global-properties"] for
properties to match on. Change this to instead run against
node.properties, so that we can use type-specific properties such as alsa.id.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2024-03-26 19:14:05 +10:00
Robert Mader
3ffd0956d4 linking: Use sendClientError in link-error handler
The current code was not updated to use `clients_om`, thus never
found a client, ending up never sending client errors.
Just use the shared helper to avoid such issues in the future.
2024-03-25 14:56:30 +01:00
Robert Mader
94031f8ef9 scripts: add error code argument to sendClientError helper
And update all users accordingly. This will allow the following commit
to use the helper with a different error code.
2024-03-25 14:56:04 +01:00
George Kiagiadakis
f69d25631d m-portal-permissionstore: improve the warnings printed due to remote errors
Demote the NotFound error returned by Lookup(), as it seems common to be
printed if the permission has not been configured.
2024-03-25 13:51:46 +02:00
George Kiagiadakis
053d2ae69c m-lua-scripting: downgrade notice to debug when printing operation errors
These errors are propagated to the caller, so it's the caller's
responsibility to print them appropriately, if necessary. Printing
a notice also here is only confusing.

A debug mesage is still be useful for developers to understand the flow.
2024-03-25 09:55:59 +02:00
George Kiagiadakis
c89316e52c linking: improve link failure & debug messages 2024-03-25 09:55:13 +02:00
George Kiagiadakis
7612068675 main: print warning about old style config files
Closes: #611
2024-03-25 09:07:22 +02:00
George Kiagiadakis
3043d258b3 docs: remove main.rst
This is out-of-date and wrong. I wanted to salvage the virtual-items
configuration docs from in there, but we are going to change that soon
- see https://gitlab.freedesktop.org/pipewire/wireplumber/-/issues/610 -
so the entire file can go away.
2024-03-23 17:14:01 +02:00
George Kiagiadakis
04a248f4d1 docs: conf_file: raise more the visibility of the config break 2024-03-23 17:09:09 +02:00
George Kiagiadakis
e6dc547624 docs/daemon: re-arrange some sections in the toctree to make more sense 2024-03-23 17:05:49 +02:00
George Kiagiadakis
ccfc501e82 docs: move well-known settings docs from src/scripts/lib to where they belong
These were documented in src/scripts/lib initially because the settings-manager
scripts used to be also there and it made sense to keep them close together.
2024-03-23 16:49:13 +02:00
George Kiagiadakis
c4d4cd48f6 docs: add a basic "config migration from 0.4" guide 2024-03-23 16:45:32 +02:00
Pauli Virtanen
61d1398f5b autoswitch-bluetooth-profile: never use headset profile without input
Autoswitch should make sure the saved headset profile always has an
input route.  Check this on loading/saving it, otherwise reselect it.

Headset mode profile without mic used to make some sense when it wasn't
using the loopback node (ie.  easy way to disable it), but now with the
loopback node this doesn't make sense any more and it's confusing if it
occurs, so we shouldn't allow it.
2024-03-23 14:02:21 +02:00
Pauli Virtanen
a73c931723 monitors/bluez: fix autoswitch A2DP input profiles
Profile autoswitch should support also A2DP profiles with input route,
so the loopback should not assume the source node is SCO one.

Also fix handling of AG SCO output stream nodes, which should not be
hidden as internal.
2024-03-23 14:02:21 +02:00
George Kiagiadakis
a562b22f60 docs: fix typo in {device,node}.disabled documentation
Fixes: #609
2024-03-23 12:00:55 +02:00
Julian Bouzas
291d3cd9a2 m-settings: remove all persistent settings if key is null
The wp_settings_delete_all() API internally uses wp_metadata_clear() to clear
all the keys in the persistent-sm-settings metadata object. This call emits
the metadata changed signal with both 'key' and 'value' set to NULL. When that
happens, we need to clear all settings from the state file.
2024-03-23 09:39:45 +00:00
Julian Bouzas
b16763f8d4 m-settings: clear schema settings metadata when plugin is disabled 2024-03-23 09:39:45 +00:00
George Kiagiadakis
50497cea03 m-std-event-source: cancel events when the node associated with the si dies
It is possible that a node is destroyed while the select-target
event is ongoing. In that case, the next hook to run will likely crash.
Fix this by cancelling events automatically when their subject
is a session-item associated with a node, as soon as the node is destroyed.

See !619
2024-03-22 15:35:22 +02:00
Pauli Virtanen
428462ddf3 filter-utils: fix handling of targetless smart filters
A smart filter should be considered "targetless" (i.e. interpose on
streams going to default target) only if filter.smart.target is not set.

Currently any smart filter with specified target not found is considered
such, which is wrong.  This causes misbehavior, such as all recording
streams going to the bluetooth dummy source.

Fix this by doing it correctly.
2024-03-21 20:19:26 +02:00
George Kiagiadakis
59d190a2bd 0.5.0 2024-03-18 17:51:32 +02:00
George Kiagiadakis
0508561686 main: set application.version on the core
This allows seeing wireplumber's version in pw-dump and such
2024-03-18 17:13:50 +02:00
George Kiagiadakis
a79d002402 alsa: rename vm.type to cpu.vm.name to be consistent with pipewire master
See 7e9e261fa6
2024-03-18 17:03:44 +02:00
George Kiagiadakis
d0b7dde4e9 log: make the log topic flags an enumeration and publicly documented
Fixes: #591
2024-03-18 16:39:45 +02:00
George Kiagiadakis
8a893bdaf0 docs: add document on how to modify the configuration
Including information about the rules syntax.
Fixes: #595
2024-03-18 13:57:26 +02:00
George Kiagiadakis
59183e938a docs: update access configuration doc 2024-03-18 13:57:26 +02:00
George Kiagiadakis
0649ba9aa6 docs: remove "policy" configuration doc page
This is all part of the well-known settings now
2024-03-18 13:57:26 +02:00
George Kiagiadakis
7b918060c4 docs: improve bluetooth documentation and example config file 2024-03-18 13:57:26 +02:00
Ashok Sidipotu
4683f1fa44 wireplumber.conf: run stream-state.lua before m-standard-event-source
Restore-stream hook is missing some of the node-added events if it is run after
they are reported by the m-standard-event-source

Fixes: #577
2024-03-15 16:58:41 +00:00
Anders Jonsson
6e4dff6960 Update Swedish translation 2024-03-15 14:44:10 +01:00
George Kiagiadakis
e0192789e9 docs: configuration: update docs on "settings" after the latest changes 2024-03-13 18:11:49 +02:00
George Kiagiadakis
95cfa9e453 wpctl: fix settings --help listing
GOptionEntry arrays need to be NULL terminated, otherwise garbage
will be printed after the last entry...
2024-03-12 16:50:25 +02:00
George Kiagiadakis
857cee10cf docs: conf_file: small updates 2024-03-12 16:39:44 +02:00
George Kiagiadakis
1ebed7804c docs: installing: update dependency versions 2024-03-12 16:35:14 +02:00
George Kiagiadakis
7d217e37ce si-linkables: do not fully reset when the underlying proxy is destroyed
Reset back to the session item's "configured" state instead of clearing
the si properties completely. This allows the "session-item-removed"
event to be dispatched with all the original properties of the node
intact, for constraint matching purposes.

Fixes #588
2024-03-12 12:44:32 +02:00
George Kiagiadakis
ad743a2143 registry: move to a separate file and decouple it from the object manager
So that it can have its own log topic...
It also makes the code a bit easier to navigate.
2024-03-12 11:55:45 +02:00
George Kiagiadakis
8caf6a6271 log: docs: document the log topic definition macros 2024-03-12 11:55:45 +02:00
Julian Bouzas
f6fede9ee4 monitors/bluez: add 'internal' prefix to internal bluez node names.
And name the loopback source node the same as bluez source without 'internal'
prefix. This keeps consistency with input/output node names when switching
bluetooth profiles.
2024-03-11 13:49:01 -04:00
Julian Bouzas
5f9b3a9659 monitor/bluez: set node.name property when creating combine stream 2024-03-11 13:41:23 -04:00
Julian Bouzas
9caa44cfab meson: bump min pipewire version to 1.0.2
This is because of using 'api.bluez5.internal' property in bluez.lua.

See !589
2024-03-11 12:07:18 -04:00
Julian Bouzas
5e19722491 scripts: fix regression in state-routes.lua when marking routes as 'active'
Like WirePlumber 0.4.17, we need to mark the current routes as 'active' if they
were previously not active as soon as we detect it. This avoids a possible
infinite loop that restores the routes and saves them constantly, which happens
when the device's Route param has changed more than once before the event
'select-routes' is triggered.
2024-03-11 09:47:31 +00:00
Julian Bouzas
bed3b62e0d scripts: improve linking logs 2024-03-11 09:47:31 +00:00
Ashok Sidipotu
88f893e2ce monitors: use parseBool for boolean properties in rules
The boolean values of properties in rules are strings in JSON config files and
they will retain the same type when they are translated to Lua.
Use cutils.parseBool() function when they have to be interpreted as bools.

Fixes: #586
2024-03-11 07:19:27 +00:00
Ashok Sidipotu
08ae195cdb config: add {device|node}.disable 2024-03-11 07:19:27 +00:00
George Kiagiadakis
dee7403f69 object-interest: make WP_INTEREST_MATCH_ALL part of the enum
This is to avoid potential issues with g-i parsing.

See #540
2024-03-09 17:26:52 +02:00
George Kiagiadakis
6ed05b3f00 proxy: make the FEATURES_MINIMAL and FEATURES_ALL constants part of the enum
This fixes their parsing by g-i, correcting their values in the bindings,
which were previously wrong.

Fixes #540
2024-03-09 17:25:03 +02:00
George Kiagiadakis
b106b774f8 log: fix WP_LOG_LEVEL_TRACE value in the g-i bindings
See #540
2024-03-09 17:23:32 +02:00
George Kiagiadakis
f4d8fa94d7 base-dirs: wrap flag groups in parenthesis
The absence of parenthesis confuses the gobject-introspection parser
for some reason, making it emit WP_BASE_DIRS_FLAG_SUBDIR_WIREPLUMBER
multiple times in the .gir file
2024-03-09 16:30:15 +02:00
George Kiagiadakis
e9d8eeedef log.h: define G_LOG_DOMAIN only if WP_USE_LOCAL_LOG_TOPIC_IN_G_LOG is defined
Define WP_USE_LOCAL_LOG_TOPIC_IN_G_LOG in project scope, so that we always
use this feature in our codebase without causing problems for other projects.

Fixes #571
2024-03-09 15:58:01 +02:00
George Kiagiadakis
d8b1efcba7 meson: make sure the boolean options have boolean values
meson 1.1.0 has deprecated the use of strings for boolean options
2024-03-09 15:58:01 +02:00
George Kiagiadakis
3fa5228d22 meson: move the common CFLAGS to project-wide scope 2024-03-09 15:58:01 +02:00
Julian Bouzas
d0f16e4757 scripts: make sure target is not nil when iterating filters with matching targets 2024-03-08 10:56:34 -05:00
George Kiagiadakis
f24edf67fa docs: update the documentation around file search locations 2024-03-07 19:58:52 +02:00
Julian Bouzas
22de7513c1 scripts: rescan linkables when device EnumRoute param changes
This is needed for some devices that expose both Headset and Speaker nodes, so
that the applications are automatically linked to the Headset node or Speakers
node automatically when plugging and unplugging a headset.
2024-03-06 10:46:50 -05:00
Julian Bouzas
e496222a03 scripts: fix available routes check when selecting the default node
Also reevaluates default nodes when the device params changed.
2024-03-06 10:46:50 -05:00
George Kiagiadakis
a141ec0c68 scripts: fix typo in rescan-virtual-links.lua 2024-03-05 16:34:11 +02:00
George Kiagiadakis
2249d8d9df 0.4.90 (0.5.0~rc1) 2024-03-04 19:29:09 +02:00
Julian Bouzas
9da732d88c m-mixer-api: use gboolean instead of bool
The WpSpaPodParser always expects gboolean for boolean values. We should never
use bool in WirePlumber unless strictly necessary.

Fixes #584
2024-03-04 17:22:03 +00:00
George Kiagiadakis
9c3aa5409e core: close the configuration file after loading all components
All components are supposed to read the configuration file during
initialization. After that, the file is not needed anymore.
2024-03-04 16:33:14 +00:00
George Kiagiadakis
6321ff9f62 scripts: access: cache the access.rules in a global config variable 2024-03-04 16:33:14 +00:00
George Kiagiadakis
655a24acf0 scripts: remove cutils.evaluateRulesApplyProperties()
Cache the rules in a global variable in each script, as JSON,
and use JsonUtils directly to evaluate them. This will allow us to
close the WpConf in the future after loading the scripts.

Also change the order of the return values of the match_rules_apply_properties
function to be able to easily ignore the number of changed values,
which is useless in most cases.
2024-03-04 16:33:14 +00:00
George Kiagiadakis
3fbf1286e6 lua: change the Conf API to have methods for getting sections as specific types
In some cases we need to get a section as JSON, so that we can pass it
down to the rules parser, while in other cases we neeed to get it as a
table to use it natively, and in that case we even need to differentiate
between it being an object, an array or an object with WpProperties.

Make it also possible to optionally pass tables with default values to
the functions so that we can get rid of cutils.get_config_section()
as well.
2024-03-04 16:33:14 +00:00
Julian Bouzas
91b5ba5e92 meson: bump min pipewire version to 0.3.82 2024-03-04 16:13:47 +00:00
George Kiagiadakis
acb446d26e meson: fix typo in lib/wp/meson.build: @0 -> @0@ 2024-03-04 17:34:21 +02:00
Julian Bouzas
00e5c0d7f8 settings: log warnings if setting does not exist in the schema 2024-03-04 09:03:51 -05:00
Julian Bouzas
ee366446b6 conf: fix settings schema typos
Fixes #583
2024-03-04 09:03:51 -05:00
George Kiagiadakis
4b0024ed27 base-dirs: add missing (nullable) annotation 2024-03-04 07:07:56 +00:00
George Kiagiadakis
8040967e47 base-dirs: ensure we skip non-absolute paths in the XDG env variables
The XDG basedir spec explicitly says non-absolute paths must be ignored
and the glib wraper functions don't check that.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
a873f47d2e base-dirs: tidy up the build-time base dirs and honor the SUBDIR_WIREPLUMBER flag
Add a new private header file, wpbuildbasedirs.h, that contains the
build-time base directories passed directly from meson, without
the "wireplumber" suffix.

Use this to set the WP_BASE_DIRS_BUILD_* and adjust the code to honor
the SUBDIR_WIREPLUMBER flag.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
ad4c6999e8 base-dirs: add a SUBDIR_WIREPLUMBER flag to append "/wireplumber" to the base dirs
This removes the previous hardcoding of this suffix and allows the
functions to be useful to other projects that use libwireplumber
and want to use this code to locate their data & config.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
e7484c16a3 base-dirs: rename ETC & PREFIX* flags to BUILD* and improve documentation
The directories specified by these flags are build-time constants,
so the BUILD* prefix is more appropriate.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
14daab576b docs: add base-dirs in the generated C API documentation 2024-03-04 07:07:56 +00:00
George Kiagiadakis
c841ec97a8 conf: drop all the _get_value() functions and remove the fallback from _get_section()
We do not use these APIs, so there's no point in keeping them.

Realistically, every component that needs a section just does its
own parsing on it, so the _get_value() functions are not needed.

The fallback in _get_section() is also not needed, as we always
pass NULL and then test for it. In Lua, however, it seems we are
using the fallback to return an empty object, so that getting
a section does not expand to multiple lines of code. For that reason,
I have kept the syntax there and implemented it in the bindings layer.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
4596b7162e conf: add a simple check for old format wireplumber.conf files 2024-03-04 07:07:56 +00:00
George Kiagiadakis
08df33d7a3 wireplumber.conf: document the main difference between context.modules and wp.components 2024-03-04 07:07:56 +00:00
George Kiagiadakis
3d5cee55d8 meson: install configuration files back in $wireplumber_data_dir 2024-03-04 07:07:56 +00:00
George Kiagiadakis
60382df63f conf: refactor configuration loading
Changes:

- Configuration files are no longer located by libpipewire,
  which allows us to control the paths that are being looked up.
  This is a requirement for installations where pipewire and
  wireplumber are built using different prefixes, in which case
  the configuration files of wireplumber end up being installed in
  a place that libpipewire doesn't look into...

- The location of conf files is now again $prefix/share/wireplumber,
  /etc/wireplumber and $XDG_CONFIG_HOME/wireplumber, instead of using
  the pipewire directories. Also, since the previous commits, we now
  also support $XDG_CONFIG_DIRS/wireplumber (typically /etc/xdg/wireplumber)
  and $XDG_DATA_DIRS/wireplumber for system-wide configuration.

- Since libpipewire doesn't expose the parser, we now also do the
  parsing of sections ourselves. This has the advantage that we can
  optimize it a bit for our use case.

- The WpConf API has changed to not be a singleton and it is a
  property of WpCore instead. The configuration is now expected
  to be opened before the core is created, which allows the caller
  to identify configuration errors in advance. By not being a singleton,
  we can also reuse the WpConf API to open other SPA-JSON files.

- WpConf also now has a lazy loading mechanism. The configuration
  files are mmap'ed and the various sections are located in advance,
  but not parsed until they are actually requested. Also, the sections
  are not copied in memory, unlike what happens in libpipewire. They
  are only copied when merging is needed.

- WpCore now disables loading of a configuration file in pw_context,
  if a WpConf is provided. This is to have complete control here.
  The 'context.spa-libs' and 'context.modules' sections are still
  loaded, but we load them in WpConf and pass them down to pw_context
  for parsing. If a WpConf is not provided, pw_context is left to load
  the default configuration file (client.conf normally).
2024-03-04 07:07:56 +00:00
George Kiagiadakis
64c233f3f4 spa-json: wrap the data instead of the spa_json* in _parser_get_json()
This allows the returned WpSpaJson object to be kept around
after the parser has advanced to the next token. The behaviour
of the _new_wrap() function is to wrap the underlying spa_json*
and it breaks as soon as the parser advances.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
ccdca1ffb4 tests/wp/spa-json: add "undefined" parser unit test 2024-03-04 07:07:56 +00:00
George Kiagiadakis
d07b6188e5 spa-json: add new "undefined" parser constructor
This allows reading non-standard JSON data that is not a valid JSON
object or array, but can be treated as such.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
9e77240b64 base-dirs: return NULL from lookup_dirs() when the searched path is absolute
This allows the files iterator to lookup in a specific directory
when the given path is absolute, similar to how pipewire behaves
for configuration files (e.g. /foo/bar/wireplumber.conf must
include /foo/bar/wireplumber.conf.d/*.conf).

This also allows improving the wp_base_dirs_find_file() structure to
avoid duplicated code and add a debug message easily.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
f76f45124e base-dirs: add support for finding modules and remove wp_get_module_dir()
This makes things more consistent and allows us also to add more
search paths in the future if necessary.

Also, stop using g_module_build_path() because it's deprecated and
build the path manually. This obviously is not portable to Windows/Mac
or other exotic platforms, but portability is not important at this
point. PipeWire is also not portable beyond Linux & BSD.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
c8feaad7a9 base-dirs: add XDG_CONFIG/DATA_DIRS and CONFIGURATION & DATA groups
This adds support for the system-wide locations for configuration and
data files, as defined by the XDG Base Directory Specification.

In addition, it adds two flag groups, CONFIGURATION and DATA, to the
base-dirs system, so that we don't have to hard-code the combinations
of flags everywhere.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
a95cbda846 base-dirs: change the function signatures to prefix with wp_base_dirs_*
... and fix the arguments order and the documentation
2024-03-04 07:07:56 +00:00
George Kiagiadakis
6ae8c254a0 base-dirs: move file lookup utils out of wp.{c,h} and into base-dirs.{c,h} 2024-03-04 07:07:56 +00:00
George Kiagiadakis
3dc837c370 WpLookupDirs: remove the flag for looking into G_TEST_SRCDIR
Instead, make it so that WIREPLUMBER_*_DIR environment variables can
contain a list of directories to look into. This is safer and,
as a bonus, allows for more control over the lookup directories.
Using the G_TEST_SRCDIR variable can cause problems for tests of other
projects that use libwireplumber and may also lead to unexpected
behavior by not being obvious that this causes wireplumber to skip
looking in its standard directories...

This also brings back WIREPLUMBER_CONFIG_DIR, which is going to be
needed again for the upcoming WpConf changes.
2024-03-04 07:07:56 +00:00
George Kiagiadakis
770028aad5 wp_new_files_iterator: refactor to behave like pipewire
Previously files would be sorted across all configuration dirs
so their filename was all that mattered, not the priority of the directory.

Ex. you could get:

- /etc/wireplumber/10-foo.conf
- /usr/share/wireplumber/20-bar.conf
- $XDG_CONFIG_HOME/wireplumber/30-baz.conf
- /usr/share/wireplumber/40-zzz.conf

This commit changes that so that it follows the hirerachy of the directories
first and then the order of the filenames, starting from the lowest priority
directory. So now for the same files you get:

- /usr/share/wireplumber/20-bar.conf
- /usr/share/wireplumber/40-zzz.conf
- /etc/wireplumber/10-foo.conf
- $XDG_CONFIG_HOME/wireplumber/30-baz.conf

In addition, the hash table is avoided, making things a bit more efficient
and the files are checked for G_FILE_TEST_IS_REGULAR

Shadowing of files still works the same, so in the above example
if /etc/wireplumber/30-baz.conf also exists, it is not returned
in the list, because it's shadowed by $XDG_CONFIG_HOME/wireplumber/30-baz.conf
2024-03-04 07:07:56 +00:00
George Kiagiadakis
28f9716eff wp_find_file: s/char/gchar/ in suffix argument 2024-03-04 07:07:56 +00:00
Julian Bouzas
db21eb5dec docs: fix documentation for WpMetadataItem 2024-03-04 06:33:04 +00:00
Piotr Drąg
c0f65f6dc3 Update Polish translation 2024-03-03 14:46:29 +01:00
Julian Bouzas
578b85584c settings: fix all coverity scan defects 2024-02-29 07:23:58 -05:00
Julian Bouzas
8935837cda scripts: remove settings-manager and use the Settings API
The settings manager is not needed anymore because the WpSettings Lua API
returns now the default value from the schema if the setting is not found.
2024-02-28 10:20:31 -05:00
Julian Bouzas
f18a8c5a35 wpctl: use WpSettings API instead of metadata in 'settings' sub-command
Also adds -r flag to reset settings to their default value.
2024-02-28 10:20:31 -05:00
Julian Bouzas
f2e7a41175 m-lua-scripting: complete Lua Settings API
This patch adds the new WpSettings API in Lua.
2024-02-28 10:20:26 -05:00
Julian Bouzas
138591c449 m-settings: load all settings in sm-metadata
If a setting is not in the configuration file, use its default value.
2024-02-28 10:20:26 -05:00
Julian Bouzas
424a8e5263 settings: add API to set, reset, save, delete and iterate settings
Also improves and refactor the settings unit test to test all the new API added.
2024-02-28 10:20:20 -05:00
Julian Bouzas
a492d23019 m-settings: add settings schema to metadata
This patch improves module-settings to load the settings schema into a
'schema-sm-settings' metadata for clients to know what values types and range
are accepted for each particular setting. This settings schema is defined in
the wireplumber.conf, under a new section called 'wireplumber.settings.schema'.
2024-02-28 08:15:21 -05:00
Julian Bouzas
a23248847a metadata: remove wp_metadata_iterator_item_extract() API
Similar to WpPropertiesItem, this implements a new WpMetadataItem type that is
returned when iterating metadata
2024-02-28 08:15:17 -05:00
Julian Bouzas
bebfc07d84 wpctl: add settings subcomand to show, delete or change settings 2024-02-14 12:04:41 -05:00
George Kiagiadakis
5826a21456 0.4.82 (0.5.0 pre-release 2) 2024-02-14 18:40:30 +02:00
George Kiagiadakis
4dc7317010 docs: update ALSA documentation 2024-02-14 15:58:19 +02:00
Ashok Sidipotu
89b9218031 device-profile-hooks: add a hook to prioritize the profiles 2024-02-12 13:15:02 +05:30
Ashok Sidipotu
112a45a230 device-profile-hooks: move the selected profile check
move the check to the beginning of the hook.
2024-02-12 13:15:02 +05:30
Ashok Sidipotu
ad8d7aaf75 json-utils: correct typo 2024-02-12 13:15:02 +05:30
George Kiagiadakis
475ec4944d lib/settings: make the WpSettings object a non-singleton
This doesn't need to be a singleton, since we have the core registration
API available publicly nowadays. Makes things more clean for the API,
following the pattern of WpPlugin and WpSiFactory and simplifies the
built-in settings component in the internal component loader :)
2024-02-10 17:48:23 +02:00
George Kiagiadakis
d61bf89969 lib/settings: reorder functions to follow the pattern of other files 2024-02-10 16:42:15 +02:00
George Kiagiadakis
4d33aff107 monitors: improve notice messages about missing SPA plugins 2024-02-10 11:44:19 +02:00
George Kiagiadakis
99ee41c490 README: remove broken badge 2024-02-10 11:44:19 +02:00
Julian Bouzas
b703c01d4c wpctl: show persistent settings and add sub-command to clear them 2024-02-07 11:53:01 -05:00
Julian Bouzas
22f51336aa module-settings: don't remove setting from sm-settings if it was removed from persistent-sm-settings
Similar to 'default.audio.sink', a setting from sm-settings should never be
removed when the associated persistent setting is removed. Only settings from
persistent-sm-settings can be removed, like 'default.configured.audio.sink'.
2024-02-07 11:43:42 -05:00
Julian Bouzas
9bf646aed0 wpctl: show filters in the status output 2024-02-07 11:43:37 -05:00
Stefan Ursella
ac508aef57 linking: handle 'node.linger' property when target node not known
Do not send an error to the client when the target is not defined
and the 'node.linger' property is set.

It is not absolutely necessary that every node has a defined target.

We can have a 'Stream/Output/*' node which can be linked to
multiple 'Stream/Input/*' nodes and only the 'Stream/Input/*'
nodes have a defined target.
2024-02-04 17:33:46 +01:00
Julian Bouzas
1d2fe9b62d module-settings: remove 'settings.persistent' option
This patch removes the 'settings.persistent' option from the configuration as it
only allowed making settings persistent globally instead of individually. This
issue has been addressed in a simpler way by creating a 'persistent-sm-settings'
metadata. If a user wants to make a setting persistent, he can change the
'persistent-sm-settings' metadata object, if the user does not want to make a
persistent change, he can use the 'sm-settings' metadata object. Any changes in
the 'persistent-sm-settings' metadata will be also reflected in the 'sm-settings'
metadata object.
2024-02-02 14:02:49 -05:00
Julian Bouzas
b3a71e3f1c linking: rename props to 'node.dont-fallback', 'node.dont-move' and 'node.linger'
This makes those properties more consistent with 'node.dont-reconnect'.
2024-02-02 11:15:31 +00:00
Julian Bouzas
1c46115433 docs: add linking documentation 2024-02-02 11:15:31 +00:00
George Kiagiadakis
7a13189ce4 tests/wp/events.c: replace g_assert() with g_assert_true()
Fixes: #565
2024-02-01 17:45:44 +02:00
Julian Bouzas
d01441ca0a scripts: move filter-forward-format.lua from 'linking' to 'node' subdirectory
This is because 'filter-forward-format.lua' only configures nodes, and therefore
does not have anything to do with the linking logic. The setting has also been
renamed to 'node.filter.forward-format'.
2024-02-01 10:00:22 -05:00
George Kiagiadakis
32f86e38ad docs: improve smart filters documentation 2024-01-31 16:12:17 +02:00
Pauli Virtanen
6d9205cfe0 filter-utils: fix indexing nil value
Check target is not nil, which sometimes occurs, before trying to access
its .id property.

Fixes lua errors in logs.
2024-01-31 09:04:54 +00:00
George Kiagiadakis
c6e3dbf887 scripts/linking/rescan.lua: fix log access
The log object should be used with : in order to make sure that the
log handler has the correct topic in context.
2024-01-31 11:00:37 +02:00
Julian Bouzas
5581a9c2b7 scripts: only log session item Id when unhandling it
This is because the associated node does not exist anymore. This change also
logs the session item Id when handling it, so that it is easy to know if the
unhandled session item was handled or not.
2024-01-30 11:51:17 -05:00
George Kiagiadakis
2fcd24b2d3 docs: move smart filters documentation to the policies section 2024-01-30 12:13:16 +02:00
George Kiagiadakis
052ca9b4a7 docs: add policies section 2024-01-30 12:07:25 +02:00
Julian Bouzas
9cdb8f3110 bluez.lua: always hide sco-source nodes from applications
Since the loopback bluetooth source node is meant to be always used by
applications, this change hides the actual bluez sco-source node by marking
them as internal. This avoids showing 2 input devices in pavucontrol per BT
device if HSP/HFP profile is enabled.
2024-01-29 12:11:45 -05:00
George Kiagiadakis
cc4549134a script-tester: load the new settings-instance component 2024-01-29 12:57:35 +02:00
George Kiagiadakis
74bfe4baa3 script-tester: simplify the load_component() function 2024-01-29 12:56:46 +02:00
George Kiagiadakis
58b58b4b48 docs: reorder menu items under "Configuration" section
Also remove "main.rst", which is to be removed entirely as a file
(but only after its contents are all moved to other files).
2024-01-29 11:55:18 +02:00
George Kiagiadakis
ef24f35ff8 docs: rename settings section and add link back to the config option types 2024-01-29 11:55:18 +02:00
George Kiagiadakis
e19839dfce docs: add link from the well-known features section back to components & profiles 2024-01-29 11:55:18 +02:00
George Kiagiadakis
d5926b08e0 docs: add info about the different configuration option types 2024-01-29 11:55:18 +02:00
George Kiagiadakis
8b4885d21d conf: split out unneeded example sections to log.conf and settings.conf fragments 2024-01-29 11:55:18 +02:00
George Kiagiadakis
bdc7839ff2 m-settings: rename persistent.settings to settings.persistent
This makes it more consistent with the nomenclature of other settings
2024-01-29 11:55:18 +02:00
George Kiagiadakis
4c94cee54c docs: update multi-instance documentation 2024-01-29 11:55:18 +02:00
George Kiagiadakis
a511c54c5c m-settings: split out the WpSettings instance loading to a new built-in component
When running multi-instance setups or when clients like wpctl want to
access the WpSettings instance, it makes no sense to load the entire
module-settings, which will also create sm-settings metadata instances.
2024-01-29 11:55:18 +02:00
Julian Bouzas
95ae88d3e7 bluez.lua: set the loopback input stream media class to internal
This hides the loopback stream node from applications, making desktop
environments to not show the 'recording from microphone' icon (Eg gnome-panel)
when the bluetooth device is not recording yet.
2024-01-23 11:59:57 -05:00
Robert Rosengren
2e9e3a7564 link/node: Fix docs on state_changed_callback
Docs for state_changed_callback indicates state being emited as pointer,
but implementation emits it as enum value.
2024-01-22 13:45:15 +01:00
Julian Bouzas
874a432c69 autoswitch-bluetooth-profile: remove applications array and use loopback filter
This patch improves the bluetooth profile autoswitch so that it works with any
application that wants to capture from a bluetooth device. To do so, a loopback
source filter is created per connected bluetooth device. If an application wants
to capture audio from such loopback source filter, the profile in the associated
bluetooth device is changed to HSP/HFP. If there isn't any application connected
to the loopback source filter, the profile switches back to A2DP.
2024-01-22 10:15:16 +00:00
Julian Bouzas
68c6fc2a38 filter-utils: always convert to string when checking if target rules match
This fixes the target not being found when setting non-string values in the
JSON matching rules of the 'filter.smart.target' property.
2024-01-22 10:15:16 +00:00
Julian Bouzas
caded6070d linking: remove redundant 'dont_move' parameter
The 'target.dont_move' property is only meant to be used with 'target.object'
metadata property, not smart filters metadata properties. This was probably
left accidentaly unused when designing a solution for #524 involving smart
filters.

Fixes #558
2024-01-19 13:29:02 -05:00
Pauli Virtanen
6f3eb32937 config: update example bluetooth.conf
bluez5.auto-connect is by default disabled. device.profile does not
exist. MIDI nodes also have node.latency-offset-msec
2024-01-14 21:26:06 +02:00
Pauli Virtanen
b932e22849 docs: update Bluetooth docs 2024-01-14 21:23:17 +02:00
George Kiagiadakis
d17c99f63f docs: update locations.rst 2024-01-13 18:49:04 +02:00
Pauli Virtanen
d8a345a30c log: rename back to wp_log_set_level 2024-01-13 16:33:05 +00:00
Pauli Virtanen
82df32b0b0 m-lua-scripting: register/unregister log topics 2024-01-13 16:33:05 +00:00
Pauli Virtanen
35c10181d7 log: forward log level patterns also to libpipewire
Use pw_log_set_level_string to set log topic levels also for libpipewire
topics.
2024-01-13 16:33:05 +00:00
Pauli Virtanen
c746e18350 log: support topic patterns also in config file log.level
Handle log topic patterns also in wp_log_set_global_level, so that they
can be specified everywhere.
2024-01-13 16:33:05 +00:00
Pauli Virtanen
7c28c226b8 log: allow dynamic log levels for WpLogTopic
Change design of WpLogTopic so that it allows for changing their log
levels at runtime.

Add wp_log_topic_register/unregister functions to track lifetime of the
topics.

Auto-register statically defined log topics.

Make the topic registration threadsafe, in case it is done from
constructors that run in a different thread than main thread.
2024-01-13 16:33:05 +00:00
Sergio Costas
2ec202dfa1 client access: add support for snap permissions
This patch adds to wireplumber code to manage the Snap audio
permissions.

SNAP containers have two main "audio" rules:

 * audio-playback: the applications inside the container can
   send audio samples into a sink
 * audio-record: the applications inside the container can
   get audio samples from a source

Also, old SNAP containers had the "pulseaudio" rule, which just
exposed the pulseaudio socket directly, without limits. This
is similar to the current Flatpak audio permissions.

In the pulseaudio days, an specific pulseaudio module was used
that checked the permissions given to the application and
allowed or forbide access to the pulseaudio operations.
With the change to pipewire, this functionality must be
implemented in pipewire-pulse and wireplumber to guarantee
the sandbox security.

The current code checks for the presence of the pipewire.snap.id
property in a client, in which case it will read the
pipewire.snap.audio.playback and pipewire.snap.audio.record
properties, and allow or deny access to that client to
the nodes with Audio/Sink or Audio/Source media.class
property.

See !567 and pipewire!1779
2024-01-13 16:18:13 +00:00
Julian Bouzas
598b3c83ce filter-utils: handle new 'filter.smart.targetable' property
This property indicates whether the filter can be directly linked with clients
that have a defined target (Eg: pw-play --target <filter-name>) or not. This can
be useful when a client wants to be linked with a filter that is in the middle
of the chain in order to bypass the filters that are placed before the selected
one. If the property is not set, wireplumber will consider the filter not
targetable by default, meaning filters will never by bypassed by clients, and
clients will always be linked with the first filter in the chain.

Fixes #554
2024-01-11 10:54:41 -05:00
Julian Bouzas
cdeac07814 linking: handle defined target properly with smart filters
This patch fixes the policy to not link the client to the default filter if the
client's defined target is found, is not a filter, does not have any other
filters linked with it. In this case, the client is therefore linked to the
actual defined target. On the other hand, if the client's defined target is a
filter, the client is linked to the first filter in the chain that has the same
target as the defined filter's target.
2024-01-11 10:48:27 -05:00
Julian Bouzas
c37f95169d filter-utils: improve get_filter_from_target API to also work with filters 2024-01-11 10:34:13 -05:00
Piotr Drąg
42f4fa92b3 Update POTFILES.in 2024-01-08 10:36:34 +00:00
George Kiagiadakis
c5c5317599 state-routes: use the correct device id when restoring route properties
Fixes: #551
2024-01-08 12:28:21 +02:00
George Kiagiadakis
7bd4032a28 lua: hooks: record the entire 'after' array
Previously we were ignoring the last element in the 'after' arrays
because of a wrong loop limit
2024-01-08 12:28:21 +02:00
George Kiagiadakis
4a3557d8e4 event: add some trace logs to debug sorting hook dependencies 2024-01-08 12:28:21 +02:00
George Kiagiadakis
03098c88bb bt-pinephone.lua: remove useless variable assignments
This is a copy/paste from the code that now lives in apply-routes.lua,
but there is no point since the route here is a real route param and
not a route_info structure.
2024-01-08 12:28:21 +02:00
George Kiagiadakis
0b0595a156 apply-routes.lua: rename variable to make the code easier to understand 2024-01-08 12:28:21 +02:00
George Kiagiadakis
a7d0dacd12 state-routes: fix restoring volumes when a Route is changed manually
When a manual change is applied, the store-or-restore-routes is the only
hook that gets executed for this event. In order to be able to test if a
route was changed, we need to reset all of them to 'active = false',
record the previous value of 'active' and test their difference.

Testing only the 'active' variable (and discarding 'prev_active') sounds
tempting here, but if a route is changed back and forth (from A to B
and back to A), there is nothing to reset the 'active' variable of A
when it gets deactivated and it will appear as previously active on
the second switch.

Related to: #551
2024-01-08 12:21:27 +02:00
Julian Bouzas
d60747f40f docs: remove obsolete tags 2024-01-05 09:34:35 -05:00
Julian Bouzas
4ac7dc831e event-dispatcher: fix ingroup documentation 2024-01-05 09:34:35 -05:00
Willow Barraco
cdd472713d
docs-policy: add filter.smart = true 2024-01-05 10:11:00 +01:00
George Kiagiadakis
4c82e59163 0.4.81 2024-01-04 20:33:29 +02:00
George Kiagiadakis
eb2d6efcd4 state: add save_after_timeout() method to replace all custom timeout code
This was a common pattern that we had in many places, so it makes sense
to consolidate it.
2024-01-04 16:38:33 +02:00
George Kiagiadakis
7fa16292c3 common-utils: remove the simple serializer functions that were used for state files 2024-01-04 10:38:23 +02:00
George Kiagiadakis
38b6eec456 state-routes: use json to store info in the state file 2024-01-04 10:27:02 +02:00
George Kiagiadakis
5d41ef2311 scripts: s/putils/lutils/g ("policy" utils -> "linking" utils) 2024-01-03 11:10:56 +02:00
George Kiagiadakis
994f1c1f4a Merge branch 'master' into next 2024-01-03 10:47:16 +02:00
Ferdinand Bachmann
3a40a8795b wpctl: resolve device id and route device internally 2023-12-27 19:36:56 +01:00
Ferdinand Bachmann
f01177d08a wpctl: add set-route subcommand 2023-12-25 23:06:32 +01:00
Pauli Virtanen
88c59ff9c6 docs: explain runtime logging controls 2023-12-24 17:59:59 +02:00
Pauli Virtanen
43e190e3b4 wpctl: add set-log-level command
Add command for changing log level for Pipewire or Wireplumber daemons
at runtime.

It can be done with pw-metadata, but make it easier so that the user
doesn't need to look up Wireplumber client ids.
2023-12-24 17:59:59 +02:00
Pauli Virtanen
6037a6af94 m-log-settings: add module for changing log level at runtime
Pipewire server uses the global "settings" metadata for adjusting its
own log level.

Make it a convention that clients may watch "log.level" in this metadata
with their client id as subject, for setting their own log level
dynamically.

Watch the global "settings" metadata for "log.level" changes for our id.
On changes, set our log level accordingly.
2023-12-24 17:59:59 +02:00
Pauli Virtanen
4e17edb1ac wp: make wp_log_set_global_level public API
Applications may want to change WP log level at runtime.

Also change it to return error stataus instead of printing warnings on
error.
2023-12-24 17:58:30 +02:00
George Kiagiadakis
c2d125b0da Merge branch 'master' into next 2023-12-23 18:34:00 +02:00
George Kiagiadakis
f3f89b8fc1 docs: shuffle files to have the same logical hierarchy as on the generated doc
Also:
 - rename some files to remove redundant information from the filenames
 - rename many labels to match the filename and its place in the hierarchy
 - move lua_api under the scripting section
2023-12-23 12:36:27 +02:00
George Kiagiadakis
7dfc346a7b script docs: rewrite all csv-table to list-table for better source readability 2023-12-23 11:32:56 +02:00
George Kiagiadakis
6afdadc549 docs: update understanding_wireplumber.rst, merging changes from !535 2023-12-21 13:26:44 +02:00
George Kiagiadakis
59972b6e4f systemd: change the template services to load different profiles instead of conf files 2023-12-21 11:28:50 +02:00
George Kiagiadakis
0037733545 daemon: add cmdline option to load custom profile and report error if not found 2023-12-18 17:58:09 +02:00
George Kiagiadakis
c0b212bb0e scripts: common-utils: do not crash if the defaults table is nil
Fixes #542, #544
2023-12-18 10:56:30 +02:00
George Kiagiadakis
b58c94816a docs: update configuration.rst 2023-12-15 21:14:24 +02:00
George Kiagiadakis
6ace763868 docs: add central doc section about the configuration file 2023-12-15 21:07:02 +02:00
George Kiagiadakis
32b31232d1 docs: document components, profiles, features and settings 2023-12-14 16:49:12 +02:00
George Kiagiadakis
396b88e64b docs: update copyright years 2023-12-14 12:33:42 +02:00
George Kiagiadakis
f63174ad5f docs: lua: document missing Core functions 2023-12-14 12:30:13 +02:00
George Kiagiadakis
c4a0f5317e meson: exclude rst files from being installed with the scripts
and add them nicely to the sphinx_files without referencing '..' paths
2023-12-13 16:31:50 +02:00
Yaron Shahrabani
1e03b5bbe1 Added Hebrew translation. 2023-12-13 09:24:38 +00:00
Tom A. Wagner
bae3381c76 meson: Set correct package version for generated .gir file for gobject introspection
Previously the package version used for the gir file was hardcoded and did not change
when the `wireplumber_api_version` definition was changed, which has now been fixed to
use that definition.
2023-12-12 12:13:51 +01:00
George Kiagiadakis
ca3bc3eb6d scripts: tidy up monitor settings and config options
* add a new common-utils method to get configuration sections with
  defaults more efficiently and with less boilerplate
* rework the ALSA reserve-device settings so that the priority is
  configured per device using rules and the application name comes
  from the WpCore instead of the config file
* rename bluetooth to bluez in all options for consistency with other
  monitors that use the backend API name
* rename alsa.midi to alsa-midi for consistency with bluez-midi
2023-12-09 15:52:24 +02:00
George Kiagiadakis
4feebfc3a3 m-lua-scripting: add Core.get_properties() method 2023-12-08 12:28:24 +02:00
George Kiagiadakis
600adf003b scripts: tidy up device-related settings
* rename settings to make more sense
* split out monitor settings into a separate category
* add setting for restoring the default nodes in the node category
2023-12-08 12:06:28 +02:00
George Kiagiadakis
d3eb77b292 release 0.4.17 2023-12-03 20:05:19 +02:00
George Kiagiadakis
e193ae0efc policy-endpoint-device: handle filters only if we have endpoints
Otherwise the filters are handled both in policy-node and here
and everything is messed up

Fixes: #536
2023-12-03 19:46:20 +02:00
George Kiagiadakis
4cc387d81d object-manager: ref all object managers before exposing tmp globals
It is possible that during this process some object managers emit
their "installed" signal, and it is possible that some object managers
are destroyed within the handler of this signal, ending up with a dangling
object manager pointer (since we do not ref object managers in the registry)
and with a modified object_managers list during iteration...

Related to: #534
2023-12-02 11:32:17 +02:00
Wim Taymans
a063d48281 scripts: pass is_filter to createLink
createLink uses an is_link variable that is unset. Fix this by passing
the is_link from the caller.
2023-11-29 11:01:34 +01:00
Wim Taymans
e9fc965b32 scripts: log si_link after creating it
Or else we get a exception because it is nil.
2023-11-29 11:00:08 +01:00
Julian Bouzas
78fe6f1ef9 m-si-audio-adapter: make sure format task is finished even if ports were already configured
Currently, if the adapter node already has its ports configured when wireplumber
starts (For example a virtual node), the async _set_ports_format() call is never
completed because the node ports have not changed, stalling the event stack.
This fixes the issue by checking the Props param after configuring the ports,
and completes the task if there is one pending and the node already has ports
available.

Fixes #527
2023-11-28 10:59:15 +00:00
Danial Behzadi
e0cb9a845f Update fa.po 2023-11-25 12:27:15 +00:00
George Kiagiadakis
0d249b8a13 release 0.4.16 2023-11-22 16:20:02 +02:00
George Kiagiadakis
0ac2947aed scripts: add new sm-objects script
This allows loading objects on demand by adding entries on the
"sm-objects" metadata object.

It is useful to dynamically load pipewire modules such as loopbacks
or network modules without having to start a new pipewire process with
a hardcoded config file.

It is also useful to load new metadata objects in order to implement
the singleton metatada concept as discussed in pipewire!1742

This may be expanded in the future to be able to load other types of
objects.

The key name, combined with the subject, is considered a unique id for
this instance of the object. The value should be a json object with
a 'type' specifying the type of object, together with a 'name' and 'args'
2023-11-22 08:38:36 +00:00
Ashok Sidipotu
256f60ebf2 policy-device-profile.lua: add a method to prioritize BT codecs. 2023-11-22 08:32:28 +00:00
Ashok Sidipotu
a87d0478ea policy-endpoint-device.lua: connect filter output to actual sinks
The device script will also scan for the filter output streams and
connect them to the actual sink devices.
2023-11-22 08:22:59 +00:00
Ashok Sidipotu
9f6066ea0d policy-endpoint-device.lua: logic to connect endpoint to filter
While handling endpoints, first check to see if there is a filter
intending to connect to it.
Also prevent Endpoints connecting to filters unless otherwise
configured.
2023-11-22 08:22:59 +00:00
Ashok Sidipotu
83e990bf2d policy-endpoint-device.lua: enhance link log msgs 2023-11-22 08:22:59 +00:00
Ashok Sidipotu
eba3d9d6f8 policy-endpoint-client.lua: avoid connecting filters to endpoints
Equalizer Node or filter nodes are considered as regular linkable and
its output is connected to endpoint. Prevent this by skipping over
filter nodes in this script.
2023-11-22 08:22:59 +00:00
George Kiagiadakis
5922f1f077 meson: bump the required pipewire version to 0.3.68
This is for the passive links behavioural change
2023-11-20 12:05:53 +02:00
George Kiagiadakis
0a7bd4fe86 si-standard-link: remove the "passive" property
PipeWire no longer uses the link.passive property, so there's no
point in adding it here. The node.passive property is used directly.
2023-11-20 12:00:54 +02:00
George Kiagiadakis
5b1ff7377f si-audio-endpoint: mark the nodes as passive instead of marking the links
This is a behavioural change in effect since pipewire 0.3.68, where
pipewire's link-factory ignores the link.passive property and the
node.pasive = in/out/true is used instead.
2023-11-20 11:56:07 +02:00
George Kiagiadakis
383b0e605d scripts: tidy-up linking related settings
* prefix all settings with just "linking."
* rename settings to make more sense
* fix the handling of the "follow" setting
* move the "move" handler to the rescan.lua script, as it's just a rescan hook
2023-11-19 18:34:33 +02:00
George Kiagiadakis
33fc476cb3 s-linking: always rescan when the default targets change
The "follow" setting was never really meant to disable reacting to
default target changes. It is also not meant to disable moving normal streams
to follow the default target. It is only meant to control whether streams
with a 'target.object' that matches the default target will move or not
to follow the default target changes (PulseAudio compat thing...)

Even if we leave this code here, disabling the "follow" option may disable
reacting to default target changes, but the streams will be moved anyway
when there is some other change in the graph (i.e. in the next rescan)
2023-11-19 17:52:20 +02:00
George Kiagiadakis
679d660058 settings: tidy up node-related settings
* prefix all settings with "node."
* move settings-stream.lua to settings-node.lua
* move the "audio-no-dsp" setting to the node settings
* add more settings related to node features
* split the default stream volume into 2 settings, one for playback
  streams and one for capture streams
2023-11-15 18:16:52 +02:00
George Kiagiadakis
2f071a67be scripts: rename all foo-config libs to settings-foo
And also use the term 'settings' everywhere instead of 'config' to refer
to the options managed by the WpSettings architecture
2023-11-15 15:44:01 +02:00
George Kiagiadakis
beafcf1ac3 config: install commented-out conf files as examples in /usr/share/doc/wireplumber/examples 2023-11-15 15:44:01 +02:00
George Kiagiadakis
460e714a10 access-default: do not crash if the rules section is not defined in the config 2023-11-15 15:44:01 +02:00
George Kiagiadakis
ab44996ce9 access-default: do not require the configuration file rules to operate 2023-11-15 13:37:33 +02:00
George Kiagiadakis
cb243eea6d common-utils: avoid crashing when a rules section is not defined in the config 2023-11-15 12:57:41 +02:00
George Kiagiadakis
ac0d8ee4a8 monitors/alsa: remove vm.node.defaults and use match rules instead
The vm.node.defaults logic which was inherited from p-m-s is not really
good because it seems like different VM hardware requires different
values for the defaults. Also, passthrough USB hardware should not
inerhit these values, they just cause trouble.

Instead, we can use rules to match the vm.type and specific device
properties to set a more informed period & headroom.

For now, I am also decreasing the default headroom down to 2048, which
works for me and perhaps it's a good default. We can always add more
rules here and fine-tune per vm type and virtual hardware.

See !394, #316, #348, #507, #162, pipewire#3452
2023-11-14 21:32:18 +02:00
George Kiagiadakis
501f119803 monitors/alsa-midi: move default property values in the Lua script 2023-11-14 21:26:34 +02:00
George Kiagiadakis
2f226aca75 monitors/libcamera: s/libcam/libcamera/g 2023-11-14 17:33:59 +02:00
George Kiagiadakis
9cf372b8ab monitors: remove the unused libcamera.lua script 2023-11-14 15:45:35 +02:00
George Kiagiadakis
8ca781c63a wireplumber.conf: refactor optional pipewire modules into components
This allows loading these pw modules only if they are needed.
2023-11-14 15:34:51 +02:00
George Kiagiadakis
6a88d8aa2c comp-loader: add support for loading pipewire modules as components 2023-11-14 15:34:11 +02:00
George Kiagiadakis
4593245fbb comp-loader: add support for wireplumber.components.rules
This is a new rules section that allows defining rules to modify
component definitions. This is useful to add repetitive dependencies,
for example, as in the case of "type = script/lua" that always requires
the "support.lua-scripting" feature. This can also be useful to modify
other component properties, such as the arguments, in overriding
configuration files, without needing to redefine the whole components
section.
2023-11-14 12:42:32 +02:00
George Kiagiadakis
42b64bfc28 spa-json: rename _from_string() to _wrap_string() and add new "from" variants
The previous naming convention was confusing because it did not make
it explicit that the string is not being copied. We had this wrong already
in the Lua bindings and thanks to some miracle it hasn't backfired so far
(it was using the "wrap" behaviour with a string that doesn't stay alive).

In some places we actually need the "copy" behaviour and in some other
places we need the "wrap" behaviour, so let's have both variants available.
2023-11-14 12:36:10 +02:00
George Kiagiadakis
96eae7d523 json-utils: add wp_json_utils_merge_containers(), factored out of conf.c 2023-11-14 12:02:31 +02:00
George Kiagiadakis
585279e13a config: add bluetooth seat-monitoring feature 2023-11-13 17:18:40 +02:00
George Kiagiadakis
5541832416 monitors: test the features that enable optional functionality 2023-11-13 17:18:40 +02:00
George Kiagiadakis
bac54c8f0e monitors/alsa: drop the half-implemented support for the "JACK device"
Users are recommended to use the JACK bridge instead, nowadays:
https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-JACK#jack-bridge
2023-11-13 17:18:40 +02:00
George Kiagiadakis
d30fcf34a4 config: drop some unused settings and replace others with component features 2023-11-13 17:18:40 +02:00
George Kiagiadakis
b1f891e149 lua api: add support for PW_PERM_L 2023-11-13 17:18:40 +02:00
Stefan Ursella
762ebad4c8 scripts: skip profile iteration when device.profile found
Do not continue iteration over all other profiles when
we found the profile set in the 'device.profile' property.
In other case we would overwrite this profile when
we find a best_profile.
2023-11-13 12:13:01 +01:00
George Kiagiadakis
74d3b550d3 metadata: export using the pw_impl_metadata properties 2023-11-10 16:15:34 +02:00
George Kiagiadakis
cf4fb87b35 lua api: allow nil to be passed on all constructors that take optional properties 2023-11-10 13:23:50 +02:00
George Kiagiadakis
a6bea40172 core: add wp_core_get_own_bound_id() method
This allows retrieving the bound-id of our own client
2023-11-10 11:27:13 +02:00
George Kiagiadakis
e88fa840f2 lua: json: add optional argument in the json parse() method to limit the number of recursions
This allows partially parsing a json object, allowing some parts to be
passed on as strings to another component that does its own parsing
(ex. a pipewire module)
2023-11-10 11:27:13 +02:00
George Kiagiadakis
0bc6ca6a2d lua: json: allow keys inside objects to be without quotes 2023-11-10 11:27:13 +02:00
George Kiagiadakis
6f3a307e6f spa-pod: don't use assertion macro in code that needs to run always 2023-11-08 20:41:34 +02:00
George Kiagiadakis
9b8987e8c0 spa-pod: fix parser to be able to collect IDs as strings ('K') 2023-11-08 20:40:19 +02:00
George Kiagiadakis
18ea9606d2 tests: fix script-tester to work with the metadata.lua changes 2023-11-08 20:37:13 +02:00
George Kiagiadakis
83e47ab7c2 tree-wide: refactor active feature checks to use _test_active_features()
Similar to 5fc7e68d10, it's wrong to test
multiple flags with a simple & operation. In some cases we had this wrong.
2023-11-08 12:23:00 +02:00
George Kiagiadakis
44a157b506 lib: object: add functions to test active and supported features 2023-11-08 12:08:30 +02:00
George Kiagiadakis
ed224f7c79 scripts: merge metadata.lua and filters-metadata.lua 2023-11-07 22:07:04 +02:00
George Kiagiadakis
6eed30cf77 properties: update doc to mention that it's possible to use JSON in _new_string() 2023-11-07 20:26:16 +02:00
James Calligeros
3fa87510d1 config: allow passing arguments to pipewire modules
Sometimes, it may be necessary to pass arguments in to a
Pipewire module being loaded. Allow this to be done using
the same format as load_module()/load_optional_module().

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2023-11-07 15:22:29 +00:00
George Kiagiadakis
a6dd60ff83 conf: remove wp_conf_apply_rules() 2023-11-07 16:36:49 +02:00
George Kiagiadakis
299e671ffa scripts: switch to using JsonUtils.match_rules_apply_properties()
Note: this requires all existing config files to be modified to follow
pipewire's rules syntax, with an "actions" object wrapping the
"update-props" object.
2023-11-07 16:36:49 +02:00
George Kiagiadakis
fbecc50319 lua: api: bind json-utils functions 2023-11-07 16:36:49 +02:00
George Kiagiadakis
89ac416e99 lib: add new json-utils set of functions
The purpose is to wrap some utilities that pipewire provides that use JSON.

Start by wrapping pw_conf_match_rules(), which despite its name, it has nothing
to do with the configuration object. It operates directly on JSON and can be
useful to work with match rules outside the context of configuration files.
2023-11-07 16:36:49 +02:00
George Kiagiadakis
d45c5eb623 s-create-item: add some debug logging 2023-11-07 16:36:49 +02:00
James Calligeros
7394f478d6
conf: update module-rt usage
update the module-rt description and commented-out defaults to
reflect the addition of utilisation clamping to the module.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2023-11-07 22:06:28 +10:00
Barnabás Pőcze
5e48a2afc1 meson.build: set WIREPLUMBER_CONFIG_DIR in devenv
This is needed for wireplumber to start up correctly in the meson
devenv when built as a subproject of pipewire. The reason for this
is that the value set for `PIPEWIRE_CONFIG_DIR` in the wireplumber
meson build file will be overriden when the pipewire meson files
set up another devenv with its own `PIPEWIRE_CONFIG_DIR`.
2023-11-03 03:24:23 +01:00
Julian Bouzas
f5a29981aa linking: use si_props for 'target.*' properties
This avoids indexing the Lua table every time the properties are accessed.
2023-11-02 16:09:48 +00:00
Julian Bouzas
8ac96f4a37 linking: handle 'target.linger' property
When set to 'true', the node will remain alive without any error produced if
it cannot be linked to its specified target; in all other cases, an error will
be produced and the node will be destroyed.
2023-11-02 16:09:48 +00:00
Julian Bouzas
970050d3b5 linking: handle 'target.dont-fallback' and 'target.dont-move' properties
Two new properties are available to change the behavior of the linking policy:
 - target.dont-fallback: when set to true, the node shouldn't be allowed to
fallback to another available target other than the one specified in the
target.object property or metadata.
 - target.dont-move: when set to true, wireplumber should ignore the
target.object metadata, so that it isn't possible to dynamically move the node
to another target using metadata.

See #524
2023-11-02 16:09:48 +00:00
Julian Bouzas
a6bacde2c8 link-target: set was_handled flag when link was created
fixes 'node.dont-reconnect' property when the node was linked before.
2023-11-02 16:09:48 +00:00
Julian Bouzas
a2469b5b39 find-defined-target: don't stop processing if defined target is not prepared yet
This is an old hack that was needed before the event dispatcher was implemented,
and therefore is not needed anymore.
2023-11-02 16:09:48 +00:00
Pauli Virtanen
0809a89442 tests: script-tester: fix locking of test-server
Calling functions on test server must lock the thread loop, otherwise
the concurrency causes corruptiont in module-protocol-native and you get
bogus messages etc.
2023-11-01 21:00:55 +02:00
James Calligeros
7a65d76a57 policy-dsp: add ability to hide parent nodes
some hardware devices are never supposed to be accessed directly by
clients, and are designed under the assumption that they will be
front-loaded by some sort of DSP. add a hide_parent property
to policy-dsp and revoke all permissions to the bound node of a DSP
graph where this is set to prevent hardware misuse or damage by poorly
behaved/configured clients.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
2023-10-30 20:11:47 +00:00
Pauli Virtanen
e0b09e7a76 main: try to connect preferably to the manager socket
Try to connect to the default manager remote, before trying the default
remote.

Check libpipewire version is new enough to support setting arrays.
Bump Pipewire version to have pw_check_library_version.
2023-10-30 20:00:57 +00:00
Barnabás Pőcze
47ebc33de5 internal-comp-loader: fix WpSpaJson memory leak
Previously, the `deps` variable was reused for parsing
the required and wanted dependencies of a component,
which lead to the old value allocated here:

  if (wp_spa_json_object_get (json, "requires", "J", &deps, NULL)) {

being leaked when a bit later

  if (wp_spa_json_object_get (json, "wants", "J", &deps, NULL)) {

succeeded.

Fix that by using two separate variables.
2023-10-30 19:53:55 +00:00
Julian Bouzas
98f622f718 m-default-nodes: clear all previous configured nodes if metadata changes to NULL
This will completely clear all the default nodes (current and previous ones)
if the configured metadata value has been set to NULL. This is needed so that
the 'wpctl clear-default' command completely clears all the default nodes state.
2023-10-26 13:21:55 -04:00
Julian Bouzas
c9dc02d941 rescan: make sure disabled smart filters are unlinked before rescanning
This patch improves the smart filters unlinking logic by only unlinking smart
filters that are disabled, instead of any kind of filters. The patch also
removes redundant filter hooks.
2023-10-26 08:15:09 -04:00
Julian Bouzas
6980f9ff5d filter-utils: always evaluate filters before 'linking/rescan' hook
Fixes smart filters not being linked correctly when starting wireplumber if no
clients are playing/capturing audio.
2023-10-25 10:34:40 -04:00
Matthew Horan
a6d30c6f77 docs: fix typo in ALSA passthrough instructions 2023-10-25 09:43:03 -04:00
George Kiagiadakis
dbf8204cf9 Revert "api: module: support loading arguments from file"
This reverts commit 2ae1b3cbd9.

This is not a good API. It was only allowed temporarily in 0.4.15
to get things done. We should approach this properly in 0.5
2023-10-24 11:55:52 +03:00
George Kiagiadakis
22cb31571d Revert "link: add WP_LINK_FEATURE_ESTABLISHED to track when a link is PAUSED/ACTIVE"
This reverts commit 9def3f96d2.

This was never a good idea, as it turns out. It was not used in practice because
it was breaking other things (see 370b692933)
and now it appears to be causing more problems in Lua object managers that don't
install because they are waiting for inactive links to become active.

Fixes: #518
2023-10-24 11:31:45 +03:00
George Kiagiadakis
eb6f569be8 Merge branch 'master' into next 2023-10-24 11:09:52 +03:00
George Kiagiadakis
23ba01970f object-manager: use an idle callback to expose tmp globals instead of pw_core_sync
A core sync is not really necessary here because whatever objects the remote
pipewire daemon has to announce have already been sent to us on a message
and this message is already being processed at this point. This means, we are
not going to be returning to the main loop until all the new objects have been
announced and therefore placed into the tmp globals array. So, we can also use
an idle callback and achieve the same effect of slightly delaying until all
new globals have been announced.

With an idle callback, we can be more agile and add those new objects immediately
after the message has been processed instead of waiting for a pw_core_sync()
reply, which will come in the next message.

This fixes an odd failure of the si-standard-link test after applying the fix
for #517, which was caused by the fact that the test was previously relying on
a delay caused by some unrelated globals being prepared in the object manager
that tries to verify the graph state. After those globals were removed from the
internal preparation queue, the test would fail to detect the link objects
because they were stuck in the tmp_globals array for too long.
2023-10-23 23:14:48 +03:00
George Kiagiadakis
5fc7e68d10 object-manager: reduce the amount of globals that initially match the interest
With the previous check, any global matching either the type or the global
properties of the interest would be considered for inclusion in the object
manager and would be prepared only to fail the same check later.

The correct way to check is (variable & (X|Y) == (X|Y)), which is what
SPA_FLAG_IS_SET() expands to.

Fixes #517
2023-10-23 23:04:02 +03:00
t123yh
b6c1fdb2e1 scripts: Fix typo in autoswitch-bluetooth-profile.lua 2023-10-23 09:50:38 +00:00
Barnabás Pőcze
6d01627cd0 wpctl: use auto cleanup for the WpCtl object
This is already done for `WpDaemon` and `WpExec`, so let's do it
here as well. This prevents some memory leaks in error paths,
which makes it easier to find real issues in the ASan output.
2023-10-22 23:02:35 +02:00
Matt Horan
686048d6fa docs: Provide example for iec958.codecs config 2023-10-19 12:11:36 -04:00
Julian Bouzas
388acb6ff3 scripts: Fix bluetooth profile autoswitch
This patch updates the deprecated policy-bluetooth.lua script so that it works
with the current version. The script has been moved into the device sub-folder,
and renamed to autoswitch-blueooth-profile.lua. The settings-manager is also
used for the configuration, and the actual configuration has been moved from
linkind.conf to bluetooth.conf.
2023-10-19 11:24:42 -04:00
Pauli Virtanen
c91dcaa046 access: set pipewire.access.effective property on clients
Report the resolved access level in pipewire.access.effective property,
so that the final level is visible in pw-dump.
2023-10-17 21:06:31 +03:00
Pauli Virtanen
199671dfa3 access: handle pipewire.client.access and flatpak status
Handle client-requested and flatpak access on the session manager side.

Pipewire daemon doesn't know about the intended permission hierarchy, so
it is better done on the session manager side, where all the rules are.
2023-10-17 21:06:31 +03:00
Pauli Virtanen
7a369b70dc access: support new "default" pipewire.access value
The "default" access is used for normal clients, in the use case where
Pipewire server will not assign permissions itself but leaves it to the
session manager. In this use case only session manager has
"unrestricted".

Make "default" equal to "unrestricted" in the default access
configuration.
2023-10-16 19:54:19 +03:00
Pauli Virtanen
7f495b63eb lua: add new Client.update_properties() API
This allows Lua scripts to update properties of other clients.
2023-10-15 21:27:14 +00:00
Pauli Virtanen
bf082964d4 client: add wp_client_update_properties
Add Wp interface function for pw_client_update_properties.
2023-10-15 21:27:14 +00:00
Pauli Virtanen
b65f8884a5 m-lua-scripting: check argument type is table to avoid crashing
In conf_apply_rules, check input argument is a table before assuming it
is and potentially crashing.

Add check also in wplua_table_to_properties to avoid similar bugs.
2023-10-13 22:47:57 +03:00
Julian Bouzas
4ad263b16c scripts: add new 'filter.smart' property
This allows users to enable/disable smart filter policy per filter. The property
is considered false by default, meaning that smart filter policy is disabled for
all filters by default.
2023-10-02 10:44:46 -04:00
Julian Bouzas
7044226f66 scripts: use 'filter.smart' prefix for smart filter properties 2023-10-02 10:44:46 -04:00
Julian Bouzas
0b44d9cf84 scripts: change filter.enabled property to filter.disabled
Avoids confusion with default value if the property is not defined.
2023-10-02 10:44:38 -04:00
George Kiagiadakis
1e40108d94 linking-utils: rename unwrap_find_target_event -> unwrap_select_target_event 2023-09-30 12:06:40 +03:00
George Kiagiadakis
c7b00599d7 scripts: remove 'active-features' session item constraints
I don't fully remember where this originates from, but it looks like
some sort of hack to workaround a race condition where the event handler
would try to iterate over items that were just created and were not yet
fully ready to be used.
2023-09-30 11:10:30 +03:00
George Kiagiadakis
6af88b283c linking-utils: cleanup duplicate functions 2023-09-30 11:02:02 +03:00
George Kiagiadakis
43aa2d4952 scripts: don't use 'local' for file-wide scoped variables
Since all scripts run in a sandbox with their own global environment,
it means that they don't interfere with each other's global variables.
Therefore, all file-wide variables can be declared global without
any change in behavior. In my understanding, it is better to do so
because this means that any code accessing those variables is going
to access them directly from the global environment table with a simple
lookup rather than having each variable referenced in the local closure
of each function separately.
2023-09-29 23:13:28 +03:00
George Kiagiadakis
2f89c64b7f docs: add documentation on device, default-nodes and linking scripts 2023-09-29 16:14:08 +03:00
George Kiagiadakis
493be2fae6 event: annotate key in wp_event_get_data 2023-09-26 10:11:36 +03:00
Ashok Sidipotu
d4f3e2bdca tests: replace "policy" with "linking" 2023-09-26 10:09:47 +03:00
Ashok Sidipotu
0dcd28e50f Lua scripts: replace "policy" with "linking" 2023-09-26 10:09:03 +03:00
Ashok Sidipotu
1f92767d4b config: replace "policy" with "linking" 2023-09-26 10:07:57 +03:00
Ashok Sidipotu
70b781ed64 steam.conf: enhance the illustration of the config 2023-09-26 10:06:03 +03:00
Ashok Sidipotu
9aeaf7367e bluetooth.conf: change the syntax for rules from Lua to JSON 2023-09-26 10:03:44 +03:00
Ashok Sidipotu
f4d421988c access.conf: uncomment the rules the way they were before 2023-09-26 10:03:07 +03:00
George Kiagiadakis
6d7232a1fd settings: correct class description 2023-09-26 10:00:43 +03:00
George Kiagiadakis
1e714fe784 session-item: improve class description 2023-09-26 09:57:50 +03:00
Ashok Sidipotu
da91c5d377 docs: add WpConf documentation page 2023-09-26 09:44:07 +03:00
Ashok Sidipotu
4594f4b7e7 docs: fix WpComponentLoader documentation page 2023-09-26 09:43:54 +03:00
George Kiagiadakis
91a8c344b1 m-std-event-source: restore the rescan_scheduled flag before rescanning
Fixes: #506
See also: !536
2023-09-24 00:26:27 +03:00
George Kiagiadakis
0d8dfc8187 tests: add test for glob patterns in hook dependencies 2023-09-24 00:23:34 +03:00
George Kiagiadakis
3823ea4b40 event: allow hook before/after strings to be glob patterns 2023-09-24 00:09:55 +03:00
Julian Bouzas
06fa06ca5c scripts: fix minor issues with smart filters policy
The filter's destination target was not being found properly due to iterating
the matching rules table with ipairs instead of pairs... the later is meant to
be used with JSON objects. In addition, the filters were not being re-evaluated
and linked properly when a device node was removed, this is because of a typo in
the find-best-target.lua script.

See #501
2023-09-21 09:04:31 -04:00
Julian Bouzas
0c53f9b130 docs: fix warnings and errors in filter documentation 2023-09-21 05:41:52 -04:00
Julian Bouzas
3eaaae3a45 docs: Add filters documentation 2023-09-03 14:33:34 +00:00
Julian Bouzas
56017fdbe6 scripts: use filter-utils to implement smart filter policy 2023-09-03 14:33:34 +00:00
Julian Bouzas
1ba3844f2c scripts: add filter-utils.lua
Utilities Lua script for the policy to easily handle filter nodes.
2023-09-03 14:33:34 +00:00
Julian Bouzas
b984af7c87 scripts: add filters_metadata.lua
Creates a filters metadata to configure filters at runtime.
2023-09-03 14:33:34 +00:00
Julian Bouzas
d383762812 device: remove echo-cancel configuration
This will be possible to do with the new filter-utils.lua design.
2023-09-03 14:33:34 +00:00
Duncan Overbruck
15f5d84d47 tests: add event dispatch order test for same priority events 2023-09-03 17:30:03 +03:00
Duncan Overbruck
bebee99fc8 event-dispatcher: sort same priority events by the order they have been received 2023-09-03 17:30:03 +03:00
George Kiagiadakis
67f9f63520 Merge branch '0.4' into next 2023-09-01 19:12:20 +03:00
Julian Bouzas
dcee74fcca scripts: do not store the link in si_flags
Otherwise the link is not destroyed right away when doing silink:remove()
2023-08-15 16:32:19 -04:00
Ashok Sidipotu
591d0b4370 camera-monitors: add a config property for camera discovery timeout 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
2d4cdcd5da wireplumber.conf: run monitors towards the end
This solves the problem of linkables not created for libcamera nodes. It makes
sense to run monitors towards the end when rest of the system is really
waiting for them.
2023-08-15 07:14:59 +00:00
Ashok Sidipotu
359ea7b17d monitor-utils: use uniform naming style for lib apis 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
426e1bbffe camera monitors: introduce cam device arbitration logic 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
7bca8cacde camera monitors: pass device and node properties as event data
This avoids event properties show up in device and node properties.
2023-08-15 07:14:59 +00:00
Ashok Sidipotu
3fe930f15f api.c: add wp_core_test_feature API 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
92de80eb2e wireplumber.conf: add new v4l2 monitor hooks 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
f45d7b43f3 v4l2/monitors: rebase v4l2 monitor into a bunch of hooks 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
86ea1f61f9 wireplumber.conf: add the new libcamera monitor hooks 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
bb0e15e631 libcamera/monitors: rebase libcamera monitor into a bunch of hooks 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
6596d71c4f monitor-utils: introduce monitor utils lua library 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
27c1ea869b event*.c: add a few more log msgs 2023-08-15 07:14:59 +00:00
Ashok Sidipotu
03e6de9894 m-standard-source: handle create-* events 2023-08-15 07:14:59 +00:00
Stefan Ursella
7ee69a9a47 log: set empty string to not set log_fields
not all functions in glib returns a value for the used log fields
in this case a 'g_return_val_if_fail(..) will only set 4 fields an
set the other field to NULL which leads to a segfault

Jul 22 13:41:37 Cynap-Pro-01121508 systemd-coredump[7247]: Process 496 (wireplumber) of user 4242 dumped core.

                                                           Stack trace of thread 496:
                                                           #0  0x00007f6b2ce58e99 __strlen_avx2 (libc.so.6 + 0x150e99)
                                                           #1  0x00007f6b2cf3ebe5 g_log_writer_journald (libglib-2.0.so.0 + 0x5fbe5)
                                                           #2  0x00007f6b2d0a9316 wp_log_fields_write_to_journal (libwireplumber-0.5.so.0 + 0x2b316)
                                                           #3  0x00007f6b2d0a96f5 wp_log_writer_default (libwireplumber-0.5.so.0 + 0x2b6f5)
                                                           #4  0x00007f6b2cf3cf3e g_log_structured_array (libglib-2.0.so.0 + 0x5df3e)
                                                           #5  0x00007f6b2cf3d0ae g_log_structured_array (libglib-2.0.so.0 + 0x5e0ae)
                                                           #6  0x00007f6b2cf3d4b7 g_logv (libglib-2.0.so.0 + 0x5e4b7)
                                                           #7  0x00007f6b2cf3d7ef g_log (libglib-2.0.so.0 + 0x5e7ef)
                                                           #8  0x00007f6b29efafef get_node_by_id (libwireplumber-module-cb-ipc.so + 0x24fef)
                                                           #9  0x00007f6b29efb032 wp_cb_ipc_get_app_properties (libwireplumber-module-cb-ipc.so + 0x25032)
2023-08-01 08:30:05 +00:00
Stefan Ursella
72edbb1ba4 m-mixer-api: track monitorMute and allow modifying them 2023-07-31 13:26:28 +02:00
Stefan Ursella
407c2f04de scripts: run find-best-profile hook before running apply-profile hook 2023-07-17 17:33:40 +02:00
George Kiagiadakis
98cd13284c tests: wait for the cores to connect before starting
Otherwise we end up executing the test without
an established connection
2023-07-04 15:09:31 +03:00
George Kiagiadakis
f94519a67a tests: upgrade failure notices to criticals
It's not very clear that these are the cause of failure when you look
at the logs
2023-07-04 14:57:26 +03:00
George Kiagiadakis
84d3382292 config: make it possible to have feature profiles
A profile is a list of features set to required/optional/disabled
which governs which components are getting loaded, given a static
components list with well-defined dependencies
2023-06-23 20:15:26 +03:00
George Kiagiadakis
840a2304b4 core: load components internally and refactor main to just activate it
+ move the export-core creation and media-session check to be built-in components
+ add WpCore API to find the export core
2023-06-23 18:01:26 +03:00
George Kiagiadakis
6bab78bf3f object: make wp_object_get_core() return itself if it's the core 2023-06-23 18:01:26 +03:00
George Kiagiadakis
11add27f81 core: refactor to subclass from WpObject 2023-06-23 18:01:26 +03:00
George Kiagiadakis
9970450bfa object.h: don't include core.h 2023-06-23 18:01:26 +03:00
George Kiagiadakis
417b0dff4c m-std-event-source: don't push events during the core dispose sequence 2023-06-23 18:01:26 +03:00
George Kiagiadakis
a982b7917c tests: reduce logs coming from libpipewire
These tests are meant to catch wireplumber issues, so the libpipewire
logs are not very interesting and just make it hard to go through
the interesting bits
2023-06-23 18:01:26 +03:00
Duncan Overbruck
760ce55de1
device/state-routes.lua: fix finding stored routes
This wrongly stored the matched route in a new variable instead of the
locally declared variable it supposed to use.
2023-06-23 13:13:44 +02:00
Duncan Overbruck
7eb6ff3b9e
device/state-routes.lua: fix check for empty selected-routes
This hook and previous hooks hooks default to setting the
selected-routes event property to an empty table, not nil.
2023-06-23 13:13:44 +02:00
Ashok Sidipotu
b0460d8050 src/scripts: add few comments 2023-06-22 16:28:56 +05:30
George Kiagiadakis
a0497b4256 Merge branch '0.4' into next 2023-06-21 20:59:04 +03:00
George Kiagiadakis
2840964f37 internal-comp-loader: fix error ownership in parsing step 2023-06-20 17:20:01 +03:00
George Kiagiadakis
19cfd37da6 comp-loader: register the component & feature only if it activates successfully
Fixes #470
See also !503
2023-06-20 17:20:01 +03:00
George Kiagiadakis
357105fa94 gitlab-ci: bump ubuntu image to 22.04 LTS
Required for more recent glib
2023-06-20 12:39:29 +03:00
George Kiagiadakis
db5bd534ce tests: do not explicitly free f->base.conf_file
This is done inside wp_base_test_fixture_teardown() now, as it should.
2023-06-20 12:39:29 +03:00
George Kiagiadakis
e738076cb0 conf: refactor component loading to use a dependency system
Each component can now list required and optional dependencies,
using the component feature names to match other components.
In addition, each component feature can be declared as required, optional
or disabled, making optional components easier to deal with.
The component flags (ifexists, nofail) have been removed.

Using virtual components, this system also allows easier customization
of which components should be loaded for a specific configuration,
without requiring the user to copy the list of components and edit it.

Also bump the required glib version to 2.68 for g_assert_cmpstrv()
2023-06-20 12:39:29 +03:00
George Kiagiadakis
9c2d25b985 tests: add component loader unit test 2023-06-20 12:39:29 +03:00
George Kiagiadakis
8a8cd97ca8 core: make the object registration functions public
This allows registering arbitrary objects on the core's registry and
finding them later, without having to add API for each and every object.

I think this is useful enough to have it public, even though it's
probably not going to be used that much... The rationale here is to
allow registering custom component loaders without having to make them
subclass WpPlugin or to create custom API for registering component
loaders specifically.

Also, remove the wp_plugin_register() and wp_si_factory_register()
functions, since they are not going to be used much in the future.
The idea is to let the component loader do the registration under the
scenes, as the component is getting loaded.
2023-06-20 12:39:29 +03:00
George Kiagiadakis
c7cb193588 core: introduce the notion of provided features on components
Each component can optionally "provide" a feature, which is basically
a string that describes the feature (ex. "support.dbus"). If the
component loads successfully, the feature is marked as provided and
can be tested for its presence with wp_core_test_feature()
2023-06-20 12:39:29 +03:00
George Kiagiadakis
f878e2f62d properties: add json to properties converters 2023-06-20 12:39:29 +03:00
George Kiagiadakis
add310d9eb dbus: refactor WpDBus into a plugin called dbus-connection
Now that we have proper module load order, we can have this shared
dbus connection in a module instead of the library. The module has
to be loaded before any other modules that need it, obviously.
2023-06-20 12:39:29 +03:00
Duncan Overbruck
542e56d9f7
conf: fix equal matches 2023-06-17 20:07:58 +02:00
Duncan Overbruck
575030aaf3
tests: add conf test for equal matches 2023-06-17 20:07:11 +02:00
Julian Bouzas
19213efa9f event-hook: fix different signedness comparison warning 2023-06-05 15:20:44 -04:00
George Kiagiadakis
b347415501 main: move the code that loads the components section into the library
This allows it to be reused in other wireplumber clients and tests
2023-05-29 15:48:39 +03:00
George Kiagiadakis
55fc845098 component-loader: make wp_core_load_component_finish() return a boolean
There is no reason to return the component object... all components
are supposed to be long-lived objects that are referenced by the
registry and there is API to find them. The caller is only interested
in the success or failure of the operation.
2023-05-28 21:07:15 +03:00
George Kiagiadakis
7fdbf7ff50 component-loader: activate & register objects through a common code path
Do this in wp_core_load_component() and let the component loaders worry
only about creating the object.

Also run the main loop in tests while loading components, to ensure
that the async operation finishes before continuing execution. GTask
makes sure to make the operation async always, by emitting the callback
from an idle GSource.
2023-05-26 21:22:48 +03:00
George Kiagiadakis
d0e96358ea component-loader: add a load_finish() vfunc to finish the async operation
It's not acceptable to assume that the underlying implementation uses a GTask,
so we have to defer the finish function to the implementation as well
2023-05-26 19:21:51 +03:00
George Kiagiadakis
41c9de30bf core: move wp_core_load_component* declarations to component-loader.h 2023-05-26 18:59:42 +03:00
George Kiagiadakis
f53185e951 component-loader: move module loading to a new WpInternalCompLoader object 2023-05-26 13:49:40 +03:00
George Kiagiadakis
843e7ef4dd component-loader: pass core and cancellable parameters in load()
Regarding the core parameter, the case used to be that WpComponentLoader
was a WpPlugin, so it had a reference to the core internally, but since
this is no longer a requirement, we need to pass this explicitly
2023-05-26 13:04:10 +03:00
George Kiagiadakis
eb180cebe8 component-loader: convert WpComponentLoader to a GInterface 2023-05-25 19:20:40 +03:00
George Kiagiadakis
5c3032c064 core: change the component arguments to be WpSpaJson instead of GVariant
This allows us to pass entire JSON objects from the config file
down to the modules / scripts without any conversion
2023-05-25 18:29:58 +03:00
George Kiagiadakis
d755ec4f20 log: ensure that warnings from pw/spa are printed as warnings
converting a spa log level to a native log level is not trivial, it seems;
when we want to print a message, we should map 2 (WARN) to W, but when we
want to translate WIREPLUMBER_DEBUG=2 to a log level, we should map 2 to N
2023-05-25 18:25:41 +03:00
George Kiagiadakis
70980fe355 lua: json: catch syntax errors when converting to native lua types
and most importantly, push nil on the stack, so that there is something
returned from this function... the caller always expects a value to
be pushed
2023-05-25 18:22:26 +03:00
George Kiagiadakis
8912dc25c3 log: fix log level mask to be able to test the trace level
Trace is 1<<8 and the mask was 0xFF, allowing only bits 0-7
to be tested
2023-05-25 17:59:56 +03:00
George Kiagiadakis
bd672b71f7 script-tester: decouple script tests setup/teardown from basic
basic_tests_setup points to a config file that doesn't exist in
the script tests directory
2023-05-24 19:45:58 +03:00
George Kiagiadakis
49ea4d90f6 tests: run with WIREPLUMBER_DEBUG=T, not 7... 2023-05-19 21:13:19 +03:00
George Kiagiadakis
5ce80a0528 meson: bump version to 0.4.80 and API version to 0.5 2023-05-19 20:20:35 +03:00
George Kiagiadakis
982bebe5aa scripts: use log topics 2023-05-19 20:12:08 +03:00
George Kiagiadakis
9e09f4e221 docs: update the log system documentation 2023-05-19 19:46:17 +03:00
George Kiagiadakis
ae7bed5655 log: make the level name a plain character in the log_level_info struct 2023-05-19 11:04:56 +03:00
George Kiagiadakis
cbf0d7284a log: make debug level 0 enable fatal errors
We always want to show fatal errors
2023-05-19 10:58:31 +03:00
George Kiagiadakis
3034fc7c79 log: accept 0 as a level and do safety checks on the level string 2023-05-19 10:50:46 +03:00
George Kiagiadakis
4f27d18bd3 log: rename "message" level to "notice" and print criticals with "E"
Syslog calls this level "notice" and I prefer it because we use it
to display significant messages that are not warnings, but they
are not really "standard", as GLib wants them to be. There is nothing
"standard" about log messages in general.

Also, make these notice messages be enabled at debug level 2, together
with warnings. The default log.level is 2 and it is a good idea to show
notices by default too.

Finally, show them in the log with "N" and also change criticals to be
shown with "E", meaning "error"... Then promote G_LOG_LEVEL_ERROR
messages to be shown with "F", meaning "fatal", because in fact these
messages are always fatal and always call abort(). Still, keep the term
"critical" in the functions to make sure that whoever uses them is aware
that this level is only for critical conditions and not suitable to
display any kind of error.
2023-05-18 16:19:49 +03:00
George Kiagiadakis
89c31d8190 log: disable "conn.*" topic by default, like pipewire does
This topic contains traces to debug the pipewire socket protocol.
Adding this pattern allows WIREPLUMBER_DEBUG=5 to show everything
except this trace by default, which is a more reasonable amount
of trace. To enable it, it must be explicitly specified in the
WIREPLUMBER_DEBUG env variable.
2023-05-18 15:53:50 +03:00
George Kiagiadakis
17b893c266 log: always set PIPEWIRE_DEBUG 2023-05-18 13:10:13 +03:00
George Kiagiadakis
b7e4654da4 log: rename log_level_index to level_index_from_flags, for consistency 2023-05-18 13:04:33 +03:00
George Kiagiadakis
dc548a3259 log: improve the initialization process
* initialize all log-related features in a new wp_log_init() function
* remove the ability to change the log patterns later, as the log
  topics are not referenced by the log system and there is no way to
  re-initialize them with different levels (we can still implement this
  in the future, if necessary, though)
* introduce the notion of a "global log level", referenced by all topics,
  and make the topics know if they have a custom level or not, like in
  pipewire; this is necessary to be able to set the level in the config
  file, which is read later by pw_context / WpCore.
2023-05-18 12:50:52 +03:00
George Kiagiadakis
2d3d5256b9 lua: add new Log.open_topic() API
This allows lua scripts to work with log topics. A topic must be
opened at the top of the file, in global scope, and subsequently
all log commands should be executed on the returned object instead
of the Log global table
2023-05-16 20:42:28 +03:00
George Kiagiadakis
4736d56557 log: implement a log topics system, like pipewire
The intention is to make checks for enabled log topics faster.

Every topic has its own structure that is statically defined in the file
where the logs are printed from. The structure is initialized transparently
when it is first used and it contains all the log level flags for the levels
that this topic should print messages. It is then checked on the wp_log()
macro before printing the message.

Topics from SPA/PipeWire are also handled natively, so messages are printed
directly without checking if the topic is enabled, since the PipeWire and SPA
macros do the checking themselves.

Messages coming from GLib are checked inside the handler.

An internal WpLogFields object is used to manage the state of each log
message, populating all the fields appropriately from the place they
are coming from (wp_log, spa_log, glib log), formatting the message and
then printing it. For printing to the journald, we still use the glib
message handler, converting all the needed fields to GLogField on demand.
That message handler does not do any checks for the topic or the level, so
we can just call it to send the message.
2023-05-16 20:42:28 +03:00
George Kiagiadakis
e908b93f3b log: describe the syslog priority numbers for code clarity 2023-05-16 16:46:43 +03:00
George Kiagiadakis
2e2ccd5934 component-loader: update documentation 2023-04-25 16:06:32 +03:00
George Kiagiadakis
67f1eb585f log: implement different debug level per topic, like in pipewire 2023-04-25 08:50:13 +03:00
George Kiagiadakis
0fa484ac55 log: map spa ERROR and WARN to GLib's CRITICAL and WARNING respectively
Previously we were mapping SPA ERROR to GLib WARNING and
SPA WARN to GLib MESSAGE, which has been causing some confusion.

After some careful consideration, it makes sense to change that and
leave the GLib MESSAGE level as something to be avoided. With that
change, WIREPLUMBER_DEBUG=M will still enable the MESSAGE level,
but WIREPLUMBER_DEBUG=2 will only enable the WARN level and it will
take WIREPLUMBER_DEBUG=3 to enable both the INFO and MESSAGE levels.
2023-04-25 08:50:13 +03:00
Pauli Virtanen
5a00686e3c bluez: minor configuration fixup
api.bluez5.connection-info is not a setting, but must always be enabled.
The bluez-midi servers should also not be enabled by default.
2023-04-17 19:41:28 +03:00
George Kiagiadakis
33fcccf44a daemon: homogenize the init transition debug messages 2023-04-17 07:48:18 -04:00
George Kiagiadakis
049992866c daemon: use g_steal_pointer() to NULL-ify the head of the components list 2023-04-17 07:48:18 -04:00
George Kiagiadakis
7ed188fba3 daemon: use a different GList pointer to iterate the components list
This keeps the original head pointer intact, so that we can effectively
free the list later. If we use the head pointer to iterate, then at the
end we are not freeing anything because the pointer is NULL
2023-04-17 07:48:18 -04:00
George Kiagiadakis
e55e8bb447 object-manager: set self->installed=TRUE before emiting the signal
This avoids recursing into the same signal, in rare cases where a
new object is registered from within the signal handler
2023-04-17 07:48:18 -04:00
George Kiagiadakis
8505e75cd0 daemon: wait for export-core to be connected to continue the transition 2023-04-17 07:48:18 -04:00
George Kiagiadakis
903fab9c3c core: return true from _is_connected() only after receiving the info structure 2023-04-17 07:48:18 -04:00
George Kiagiadakis
f00011d23a daemon: fallthrough to the error case instead of repeating cleanup statements 2023-04-17 07:48:18 -04:00
George Kiagiadakis
13f9f98bc8 daemon: check for media-session before loading any components
We shouldn't start doing anything if another session manager is running,
it will just break the other session manager's state.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
51d5beb36c daemon: remove redundant calls to component_data_free()
The component data pointer in this function is wrapped in g_autoptr,
so this should happen automatically
2023-04-17 07:48:18 -04:00
George Kiagiadakis
0fed249eb9 daemon: exit with WP_EXIT_CONFIG code if a component fails to load
This should be considered a configuration error: the user has
specified some component in the config file that cannot be loaded.
Changing the configuration file should fix it.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
65c94c71fd daemon: check for the correct "file not found" code
When a script fails to load, the lua component loader returns
G_IO_ERROR / G_IO_ERROR_NOT_FOUND.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
8219cc58c1 daemon: remove unused variable 2023-04-17 07:48:18 -04:00
Julian Bouzas
310232b810 meson: install scripts in /usr/share/wireplumber
Since the wireplumber configuration has been moved to /usr/share/pipewire, it
does not makes sense to have a different path for the WIREPLUMBER_CONFIG_DIR
environment variable. Therefore, the WIREPLUMBER_CONFIG_DIR environment variable
has been changed to just be an alias of PIPEWIRE_CONFIG_DIR. Finally, Lua
scripts are now installed under /usr/share/wireplumber/scripts instead of
/usr/share/pipewire/scripts as they are a wireplumber feature only.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
e7c992e97d default-nodes-tests: use the changed variable in test utils 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
5c17747112 policy-utils.lua: remove object managers 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
80554fe1c7 common-utils.lua: remove metadata object managers 2023-04-17 07:48:18 -04:00
Torge Matthies
ab6a3393e6 lib/wp: Fix lookup_dirs with WP_LOOKUP_DIR_ENV_DATA or WP_LOOKUP_DIR_ENV_TEST_SRCDIR
Fixes: aa2f7e9f308f ("lib/wp: add a new search folder to locate the Lua Test scripts")
2023-04-17 07:48:18 -04:00
Julian Bouzas
c61d1e4245 component-loader: make wp_core_load_component() API asynchronous
This change completely refactors the way components are loaded in wireplumber:
- The module_init() function must return a GObject now. This object is either
a WpPlugin or a WpSiFactory in the current modules.
- When the component loader initializes a module, it automatically registers
the WpPlugin or WpSiFactory with their respective methods. There is no need
to register the WpPlugin or WpSiFactory in the module now.
- The wp_core_load_component() API has been refactored to be asynchronows. This
allows the component loader to automatically activate WpPlugin objects, and
therefore allows the application to directly get the WpPlugin without having
to find it. This simplifies a lot of things.
- The 'ifexists' and 'nofail' component flags now work even if the respective
WpPlugin could not be activated.
- The code that loads components in main.c has also been simplified a lot,
and the option to load dangling components has also been removed.
2023-04-17 07:48:18 -04:00
Julian Bouzas
ad940b6efc component-loader: remove handling of 'pw_module' components 2023-04-17 07:48:18 -04:00
Julian Bouzas
6259a3a0fa m-lua-scripting: remove handling of 'config/lua' files
Not needed anymore as the configuration is written in JSON now.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
7c2e713c9d m-metadata: remove module-metadata and replace it with a simple lua script 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
de3214d21b default-node: rename select-default-nodes.lua
Consistent across linking and default node scripts.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
50377f2a70 default-nodes: make the default-config* keys trigger common
This trigger will be available all the time irrespective of whether persistant
option is enable or not.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
03bdf7d283 find-selected-default-node.lua: add a new default node hook
Hook accords higher priority to the currently selected device over and on top of
the previously selected devices.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
9a0f8647ac test-utils: align style 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
c7c06351f7 test-utils: add a restartPlugin API 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
c88a569835 default node tests: add initial test
tests the initial metadata setup.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
0b29286f4f script-tester: add a restart-plugin action signal 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
d4d4e23e9c script-tester: pass the fixture pointer to plugin 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
c9e55e6565 script-tester: run default-node scripts ahead of m-metadata 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
85db1e371e state-default-nodes: initialize the metadata variable 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
0d73c34c68 common-utils: add a null check for default-nodes query
common-utils is a singleton common resource, it cannot depend on the order in
which the components are loaded.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
137cbf3f22 wireplumber.conf: hike the priority of default-node scripts
default-node scripts need to run before metadata module as default nodes need to
act when the default metadata is created.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
000a869035 apply-default-node.lua: re-instate the "set default node" debug log msg 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
82c8269381 prepare-link.lua: fix unassigned variables 2023-04-17 07:48:18 -04:00
Julian Bouzas
d2123827f7 scripts: use the event stack to handle virtual session items
This removes both the policy-virtual-client.lua and policy-virtual-device.lua
scripts, and creates a new linking/find-virtual-target.lua script to link
clients with virtual session items if one of them can be found. In addition to
this, this patch also ports the policy-virtual-client-links.lua into a new
scripts/rescan-virtual-links.lua to use the event stack. The idea is for the
scripts/link-target.lua to create all links but only activate non virtual links,
and for the scripts/rescan-virtual-links.lua to activate/deactivate virtual
links based on role priorities.
2023-04-17 07:48:18 -04:00
Julian Bouzas
9ee0f096ec tests: remove audiotestsrc-play example 2023-04-17 07:48:18 -04:00
Julian Bouzas
fb855b00cf Rename endpoint concept to virtual session item 2023-04-17 07:48:18 -04:00
Julian Bouzas
9004362cda lib: remove WpEndpoint and WpSiEndpoint APIs 2023-04-17 07:48:18 -04:00
Julian Bouzas
d43b55d01e tests: use WpConf for the settings unit tests
Also moves the settings.conf file into settings/wireplumber.conf
2023-04-17 07:48:18 -04:00
Julian Bouzas
360e0b3eaf scripts: use WpConf API to get configuration values
This patch also moves nested configuration objects that are not considered
settings from the wireplumber.settings section to its own configuration
section (eg the rules array, the spa plugin properties, etc...). This allows
those objects to be merged with other same sections defined in other files.
2023-04-17 07:48:18 -04:00
Julian Bouzas
6c6d5eccf9 main: use WpConf to get wireplumber component dependencies 2023-04-17 07:48:18 -04:00
Julian Bouzas
fdcd280120 m-settings: use WpConf to get the wireplumber settings 2023-04-17 07:48:18 -04:00
Julian Bouzas
a7a7e614db m-lua-scripting: add WpConf Lua API 2023-04-17 07:48:18 -04:00
Julian Bouzas
cb80cb750b conf: add support to override sections and nested objects/arrays 2023-04-17 07:48:18 -04:00
Julian Bouzas
8f66b16673 lib: add WpConf API 2023-04-17 07:48:18 -04:00
George Kiagiadakis
fe3d0b55ac docs: initial design documentation 2023-04-17 07:48:18 -04:00
George Kiagiadakis
3779a92fcc lua: AsyncEventHook: allow hooks to handle transition errors
When in error, attempt to execute a step called "error", if it exists.
This is rarely needed, but it might be useful in some cases to cleanup
some state, rolling back changes, when something fails.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
18377fbf82 transition: don't allow _return_error() to be called recursively 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
6495eb6d21 linking tests: create stream node after device nodes are ready 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
8a6e28f496 test-utils.lua: create stream node with script tester plugin 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
cd7e9b190b script-tester: create a new script tester plugin
script tester plugin with a action signal to create the stream node.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
de394f7d02 linking tests: add defined tests 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
0099ef2932 test-utils.lua: add support for defined test cases 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
669b91678d linking tests: add default device test cases 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
db4ace420c test-lib.lua: add support of default device selection 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
de24f7a432 linking tests: add non default device tests 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
0d0230177a test-utils.lua: support non-default device tests 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
e13a3a0a89 script-tester.c: use the latest list of components
use the latest list of components needed to launch linking tests.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
4b153ec553 link-target.lua: change into a async hook
link setup is a asynchronous action, async hook serves the purpose well
here.

The code dependent on links will be less error prone with this design.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
a8aeb1010e policy tests: facilitate Lua src tests in script-tester.c 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
a1e79cc84b script tests: add test utils 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
1b09061b9d tests: settings: run all the tests with default metadata
There is no need to use an exclusive metadata just for tests, remove it to
simplify the code.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
8e78ec58e3 lua tests: script tests: add a new folder
Move the script-tester.c one folder up so that it is common for wplua and these tests.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
fcfae4eeb3 lib/wp: add a new search folder to locate the Lua Test scripts 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
e23964c94b lua tests: script-tester: add new infrastructure needed to launch the policy tests
-Also add a dummy file for policy-tests
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
5dcdad4db7 lua tests: give a label to the current Lua script tests
This allows for Lua test scripts to be grouped into a label. So that they can be
treated different in terms of the init infrastructure that the script-tester
lays out for those tests.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
81c468cf23 find-best-routes.lua: add a null check while selecting routes 2023-04-17 07:48:18 -04:00
George Kiagiadakis
153c019343 m-std-event-source: separate rescan events for linking and default-nodes
Call the event "rescan-for-<context>", where <context> is either
"linking" or "default-nodes" and can be expanded in the future.

Add an additional hook in default-nodes to trigger the
rescan-for-default-nodes event when sources and sinks come and go.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
dc196df239 m-std-event-source: fix state names in node-state-changed event
We need to use the enum nicknames ("idle"), not the enum names
("WP_NODE_STATE_IDLE"). This makes suspend-node work again.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
26e47db4b4 scripts: default-nodes: fix mistakes to make default-node selection work 2023-04-17 07:48:18 -04:00
George Kiagiadakis
28548e0933 scripts: move create-item.lua under node/ and modernize it 2023-04-17 07:48:18 -04:00
George Kiagiadakis
258d9f32e1 scripts: rename all hooks to follow a nicer naming scheme
Use the directory name and file name to construct the hook's name,
like a path. This way, when you see a hook name, it is clear where
to find that hook in the source code.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
652a6a6698 scripts: rename directories to follow the new naming scheme
* client: Logic that deals with configuring clients (basically, permissions)
* device: Anyhing that that deals with configuring devices (profiles, routes, ...)
* node: Anything that deals with node objects: configuring nodes, changing
  their state, their properties and also creating new nodes (but NOT linking them)
* linking: All the logic for creating links between nodes (and obviously,
  deciding which links to create)
* monitors: Scripts that deal with hardware subsystems, mainly monitoring
  hardware changes and reflecting them on pipewire
* default-nodes: All the logic for selecting the default sinks and sources
2023-04-17 07:48:18 -04:00
George Kiagiadakis
dbca5783d0 m-std-event-source: don't crash in disable() if the core is not available
When the core is shutting down, the weak reference to it is cleared before
we have a change to use it, but it's ok because everything is getting destroyed
at this point, including the hook that we want to unregister.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
ce44d9a5ef tests: lua-json: verify that nested objects inside arrays work 2023-04-17 07:48:18 -04:00
George Kiagiadakis
08a9d39295 events: rename find-target-si-and-link to select-target
And make sure it does not get prefixed with the subject type
2023-04-17 07:48:18 -04:00
George Kiagiadakis
374602d759 test-lua-json: verify that empty arrays and objects work 2023-04-17 07:48:18 -04:00
George Kiagiadakis
73b6b90a35 m-lua-scripting/api: allow EventDispatcher.push_event() to accept event objects 2023-04-17 07:48:18 -04:00
George Kiagiadakis
d46d54f261 wireplumber.conf: update the list of loaded modules and scripts
A bit dirty for now, as the script auto-loading feature does not
work properly yet
2023-04-17 07:48:18 -04:00
George Kiagiadakis
8e9faa6a25 m-default-nodes-api: revert to the version from master, without hooks
But keep the additional comments and debug statement improvements.
Also, merge the stuff from common.h, which was previously shared
with m-default-nodes.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
2325178d5c default-nodes: port to a set of scripts with hooks 2023-04-17 07:48:18 -04:00
George Kiagiadakis
d8e461940f scripts: refactor restore-stream into node/state-stream
* Use more hooks and no custom object managers
* Use the settings manager for the config values
* Allow fully disabling the hooks when both restore-props and restore-target
  are disabled in the settings
* Change the format AND the name of the state file; use json directly
  in the values now that we can
2023-04-17 07:48:18 -04:00
George Kiagiadakis
85858c8a84 state-profile: dynamically respond to config.use-persistent-storage changes 2023-04-17 07:48:18 -04:00
George Kiagiadakis
b5d8a7982f scripts: split/refactor the policy-device-routes script into smaller hooks 2023-04-17 07:48:18 -04:00
George Kiagiadakis
7ae4fca46b m-std-event-source: add a "create-event" action
This allows the calling script to also attach event data before
pushing the event on the dispatcher
2023-04-17 07:48:18 -04:00
George Kiagiadakis
9891758c70 remove policy-device-profile and m-default-profile 2023-04-17 07:48:18 -04:00
George Kiagiadakis
f99c3005f2 scripts: rewrite policy-device-profile and m-default-profile into a set of hooks
... excluding the persistent profile functionality for now (I am not convinced)
2023-04-17 07:48:18 -04:00
George Kiagiadakis
e1a8c3459a scripts: remove priority from all hooks and set up some basic dependencies 2023-04-17 07:48:18 -04:00
George Kiagiadakis
ffa85840ac event: move cancelling of events on pw-proxy-destroyed to m-std-event-source
It is really out of place to do this inside WpEvent, as it is not
a generic action. It should only happen for some events.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
3a23fb451a event-dispatcher: refactor to use before/after dependencies on hooks
* Remove entirely the hook priority numbers and use before/after dependencies
* Split the WpEvent code out of WpEventDispatcher
* Add methods on WpEvent to interface with it from the WpEventDispatcher.
  As a bonus, we can now also implement tooling to inspect which hooks would
  in theory run for an event and write tests around that
* Removed some internal debugging facilities and log calls, will redo it later.
* Using spa_list now for the list of hooks, to reduce the number of allocations
  happening in the "hook collection" algorithm
* Switched some internal data to use g_new0 instead of g_slice_new0
* Added g_free to free WpEvent structures... surprisingly, we were leaking them
  before
2023-04-17 07:48:18 -04:00
George Kiagiadakis
5a435fae11 event-dispatcher: expose iterator to iterate over the registered hooks 2023-04-17 07:48:18 -04:00
George Kiagiadakis
b100bdda4a event-hook: remove the exec type property & enumeration
With the latest changes, we can implement the "after-events" type
with external code that pushes a very low priority event that is
the "rescan" event.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
bcb4e80723 m-std-event-source: use type-specific event names and multiple object managers
It is better to have type-specific event names to minimize the amount
of constraint string matches we do on hooks, as most hooks (if not all)
are interested on specific types of objects only.

Similarly, use a different object manager for each object type to
minimize the performance impact of iterations and lookups, as all
such actions are interested in only 1 object type every time.

Port all existing hooks to the new event names and the get-object-manager API.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
54b14d1a29 scripts: port suspend-node.lua to the event dispatcher architecture 2023-04-17 07:48:18 -04:00
George Kiagiadakis
6668b40941 scripts: simplify policy-device-profile.lua 2023-04-17 07:48:18 -04:00
George Kiagiadakis
c2c95bf726 scripts: port misc hooks to use the new priority enumerations 2023-04-17 07:48:18 -04:00
George Kiagiadakis
c6c740e94a wplua: expose setmetatable / getmetatable in the sandbox 2023-04-17 07:48:18 -04:00
George Kiagiadakis
374e4ecaff m-standard-event-source: simplify push_event, removing the subject_type
This avoids having to determine the subject type prior to pushing
an event from lua code and makes the call more convenient

Also add a debug statement to trace calls to push_event
2023-04-17 07:48:18 -04:00
George Kiagiadakis
5c113d2745 scripts: delete policy-node.lua
This has been split into smaller files in policy-desktop/
2023-04-17 07:48:18 -04:00
George Kiagiadakis
993a2686f6 scripts/policy-desktop: add main rescan script 2023-04-17 07:48:18 -04:00
George Kiagiadakis
dd733df9c3 scripts/policy-desktop: add script for the filter-forward-format logic 2023-04-17 07:48:18 -04:00
George Kiagiadakis
6bc782d070 scripts/policy-desktop: add move & follow settings handlers 2023-04-17 07:48:18 -04:00
George Kiagiadakis
67ab0eced2 scripts/lib: update policy-config to use the settings manager 2023-04-17 07:48:18 -04:00
George Kiagiadakis
57d4a8cb07 scripts/lib: add a new settings manager lua library
This intends to reduce the amount of code needed to maintain
tables of settings values across different scripts
2023-04-17 07:48:18 -04:00
George Kiagiadakis
73870c528b scripts: policy-node: use policy-config library 2023-04-17 07:48:18 -04:00
George Kiagiadakis
aafac752a1 scripts: remove policy-hooks.lua 2023-04-17 07:48:18 -04:00
George Kiagiadakis
6c27da6365 scripts/policy-desktop: add back the sample user hook on a separate file 2023-04-17 07:48:18 -04:00
George Kiagiadakis
2e3d2b2bb9 scripts/policy-desktop: fix the code of the find-target hooks to work again
* Use a common function to unwrap the objects out of the event
* Use the same common function to get the si flags
* Do not store back the si flags - there is no point in doing that,
  tables are objects in lua and they are passed around by reference
* Store the target on the event
2023-04-17 07:48:18 -04:00
George Kiagiadakis
013a61b440 scripts/lib: add policy-config script library 2023-04-17 07:48:18 -04:00
George Kiagiadakis
e5764e33a4 scripts: split policy-hooks into separate files, one for each hook 2023-04-17 07:48:18 -04:00
George Kiagiadakis
515b3f07d1 m-lua-scripting: api: bind WpEvent set_data/get_data 2023-04-17 07:48:18 -04:00
George Kiagiadakis
6c3bd9e27d event: add datalist to store arbitrary data on the event 2023-04-17 07:48:18 -04:00
George Kiagiadakis
55122b84b4 m-standard-event-source: add "schedule-rescan" action signal
This can be used anywhere else in the codebase to push a "rescan-session"
event, making sure that there is only one such event pushed on the stack,
no matter how many times this is called.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
24db3fe24a event-hook: rewrite the hook priorities enum
Hooks need to have a priority relative to the event they are executed on,
so it does not make much sense to have all kinds of different priorities
based also on the event type and/or the module where they are defined.
Also, it wouldn't be acceptable to have such an enumeration on the public API.
2023-04-17 07:48:18 -04:00
George Kiagiadakis
e2b9cb0b5e m-standard-event-source: export the push_event function as an action signal 2023-04-17 07:48:18 -04:00
George Kiagiadakis
252c5b4935 m-standard-event-source: refactor around a central "push_event" function
Also redo some priorities and rename the object-changed event
to metadata-changed
2023-04-17 07:48:18 -04:00
George Kiagiadakis
79d8c9f5d9 m-standard-event-source: pass self as the event's source object 2023-04-17 07:48:18 -04:00
George Kiagiadakis
ab1668af15 m-standard-event-source: add object-manager property 2023-04-17 07:48:18 -04:00
George Kiagiadakis
b2f2e3f745 m-standard-event-source: add SiLink to the object type & priority list
Just to avoid warnings for now
2023-04-17 07:48:18 -04:00
George Kiagiadakis
48635cb780 m-standard-event-source: manage all kinds of session items in the om
So that we can also work with SiLink objects with this object manager
2023-04-17 07:48:18 -04:00
George Kiagiadakis
c0322cb34f m-standard-event-source: remove the devices object manager
That makes no sense to have. The only script that uses this can easily
be rewriten so that it uses object-added/removed instead.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
7be388c881 main: Free the component deps using the correct API 2023-04-17 07:48:18 -04:00
Julian Bouzas
102792527a lib: remove deprecated APIs 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
c0905c233f m-settings: trigger init of WpSettings object
After the creation of metadata with config data, m-settings will also need to
trigger the init of WpSettings Object/API. Earlier this was done in main.c as
part of init transition but the logic there is much more generalized now and so
it has been moved here.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
d9d3a49f5a settings: remove unnecessary log message 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
85900fba64 m-lua-scripting: support dangling components
- Dangling components are those not present in the json config files but present
in the wireplumber lookup folders.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
6f039003ec component-loader: support dangling components
- Dangling components are those not present in the json config files but present
in the wireplumber lookup folders.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
904751ede1 main.c: refactor the init transition with priority tag
- Support `priority` tag in definition of wireplumber components in json
  config files.
- Support loading dangling components. These are components which are
  NOT present in the json config files but present in the wireplumber
  lookup folders.
- Simplify the init transition by removing the unneeded steps.
2023-04-17 07:48:18 -04:00
Julian Bouzas
78b0dd58db conf: move endpoints into wireplumber.settings 2023-04-17 07:48:18 -04:00
George Kiagiadakis
497f30453d lib: event-hook/dispatcher: constness and staticness fixes 2023-04-17 07:48:18 -04:00
Julian Bouzas
1da43c6031 settings: append matches if the rule name matches 2023-04-17 07:48:18 -04:00
Julian Bouzas
36cba7fe55 config: comment all remaining rules 2023-04-17 07:48:18 -04:00
Julian Bouzas
6afca096e8 policy-device-profile.lua: use default rules if none are defined 2023-04-17 07:48:18 -04:00
Julian Bouzas
56087777f6 bluez.lua: use default rules if none are defined 2023-04-17 07:48:18 -04:00
Julian Bouzas
ed79e9a4d0 alsa.lua: use default rules if none are defined 2023-04-17 07:48:18 -04:00
Julian Bouzas
4bb949fd89 access-default.lua: use default rules if none are defined 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
119b99dc23 event-dispatcher: Add a trace log msg to indicate the events created 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
0fadd4f4fd wpexec: Add support for event dispatcher
-Scripts loaded with wpexec will also need 'module-standard-event-source'
 to be able to convert the pipewire signals to wireplumber events.
-Simplify the init transition states.
2023-04-17 07:48:18 -04:00
Julian Bouzas
a8d6d50e2a config: use wireplumber nomenclature for the setting names 2023-04-17 07:48:18 -04:00
Julian Bouzas
fe21c2f8b2 config: comment persistent.settings to false as it is its default value 2023-04-17 07:48:18 -04:00
Julian Bouzas
6a612db57a config: make remaining non rule settings optional 2023-04-17 07:48:18 -04:00
Julian Bouzas
f1fbeaa661 m-lua-scripting: add fallback value for parse_{array|object}_safe() APIs 2023-04-17 07:48:18 -04:00
Julian Bouzas
f416482f65 config: always comment the default values
This allows users to know what values are set by default.
2023-04-17 07:48:18 -04:00
Julian Bouzas
f6c4590299 config: consider dependency valid if not defined in WpSettings
Needed so that the configuration is fully commented.
2023-04-17 07:48:18 -04:00
Julian Bouzas
c5c36b26ba config: move all components into wireplumber.conf 2023-04-17 07:48:18 -04:00
Julian Bouzas
8df09a872b config: fix flags for libpipewire-module-rt 2023-04-17 07:48:18 -04:00
Julian Bouzas
5dcb4f0037 config: use the pipewire directory 2023-04-17 07:48:18 -04:00
Julian Bouzas
d79d3e1465 policy-device-endpoint.lua: remove unused move configuration 2023-04-17 07:48:18 -04:00
Julian Bouzas
a23168af52 policy-hooks.lua: set move configuration to true by default 2023-04-17 07:48:18 -04:00
Julian Bouzas
048a975818 common-utils.lua: use different timeout callbacks for different states
This allows saving different states at the same time.
2023-04-17 07:48:18 -04:00
Julian Bouzas
c64139afbe conf: comment persistent.settings as it is disable by default 2023-04-17 07:48:18 -04:00
Julian Bouzas
3c26f278cd module-settings: refactor to only load state file when plugin is enabled
Also fixes issues with persistent.settings not working if no changes have
happened.
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
f4382da5ba policy-hooks.lua: An example of user injectible hook 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
bbe3b919d3 policy-{node|hooks}.lua: Fix issues in Zoom Desktop Video Sharing.
Fixes #339
2023-04-17 07:48:18 -04:00
Ashok Sidipotu
40a1c3b948 m-lua-scripting: Return the event in the push_event API 2023-04-17 07:48:18 -04:00
Ashok Sidipotu
68eaede3e4 event-dispatcher: Group after-events-with-event hooks of a session item
after-events-with-event hooks are rendered based on the priority, this means
when a rescan event happens, all the findDefinedTarget hooks(of different
session items) are run first and then all the findDefinedTarget hooks, so on.

This kind of scheduling of hooks was removing the established link between zoom
voice engine and digial mic. Also It is slightly difficult to follow the flow in
the logs.

Instead of arranging the hooks flately based on priority, better scheme to
prioritize them in two layers. First all the hooks for an event or session items
are grouped and with in that group, priority of the hook is honored.

src/scripts/policy-hooks.lua #	modified:   src/scripts/policy-node.lua #
2023-04-17 07:48:18 -04:00
Julian Bouzas
89dcd64003 settings: make sure WpSpaJson is valid after doing wp_iterator_next() 2023-04-17 07:48:18 -04:00
Julian Bouzas
b84261773a settings: make sure WpSpaJson is not NULL when checking its type 2023-04-17 07:48:18 -04:00
Julian Bouzas
d0e27ac82e settings: remove wp_settings_get_all() API
Not used anymore. It is better to use parse_object_safe() Lua API instead.
2023-04-17 07:48:18 -04:00
Julian Bouzas
61fe102c28 main: parse component flags in a more robust way 2023-04-17 07:48:18 -04:00
Julian Bouzas
90eb2c831f main: always expect component deps to be a JSON array
Makes the configuration simpler
2023-04-17 07:48:18 -04:00
Julian Bouzas
0491fd172f main: use smart pointers to avoid wp_spa_json_unref() 2023-04-17 07:48:18 -04:00
Julian Bouzas
42fc17b234 config: clean and comment all configuration that is not needed by default
Most of the configuration settings have a default value when they are loaded by
the Lua scripts if they are not present, so we leave them commented in the
configuration. This will make the configuration smaller when supporting layered
configuration, as all the commented sections will be part of the override files.
2023-04-17 07:48:16 -04:00
Ashok Sidipotu
e1ff6bf4bf main.c: Allow for array of dependencies
A Wireplumber component can now be loaded dependent on an array of
wireplumber settings.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
efb0c5a635 Wireplumber Settings: Port the latest changes from master
Port them from Lua config to JSON config.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
6762de3990 policy-{bluetooth|device-profile|device-routes}.lua: Optimize for Event stack
- Sharpen the hooks.
- Make settings live, apply them when they are changed.
- Move some of the common functions to common_utils.lua
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
8e7611fa9f m-default-nodes{-api}: Correct the critical log msg 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
66c63a91a9 monitors: Align nomenclature of the settings and rules 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
335fe69461 restore-stream.lua: optimize for event-stack
- Sharpen the hooks.
- Make settings live, apply them when they are changed.
- Move common funtions to common-utils.lua
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
4dd8dd6ce5 policy-node.lua: apply policy settings live
Also change the setting names as per nomenclature.
2023-04-17 07:47:09 -04:00
Julian Bouzas
d28d7d4278 settings: use WpSpaJson instead of raw string in WpSettingsChangedCallback
Avoids users to construct a WpSpaJson every time the callback is triggered.
2023-04-17 07:47:09 -04:00
Julian Bouzas
a512ddaaf3 scripts: use the WpSettings safe APIs
Avoids Lua errors if a setting cannot be parsed or does not exist.
2023-04-17 07:47:09 -04:00
Julian Bouzas
a77fe0b021 settings: add APIs to parse all types safely 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
a060c6a130 m-default-nodes{-api}: optimize for event-stack
- Sharpen the hooks, so that they are called only when needed.
- Make settings live, apply them when they are changed.
- Remove the state saver after events hook, call it directly.
- Remove the settings bookkeeping as the gobject properties.
- Remove the scheduling of default-nodes-changed signal via core.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
a5a6300662 policy-node.lua: fix the session items unhandling 2023-04-17 07:47:09 -04:00
Julian Bouzas
0983326433 scripts: use the new object ID as index in the Lua tables
We cannot guarantee that the object's bound-id is always valid when an event is
triggered, especially when an object is removed. This patch uses the new object
wireplumber unique ID to index Lua tables, fixing runtime WP_PROXY_FEATURE_BOUND
check warnings.
2023-04-17 07:47:09 -04:00
Julian Bouzas
63fbcdc82c session-item: remove ID property
Not needed anymore, the object API has a unique ID now.
2023-04-17 07:47:09 -04:00
Julian Bouzas
69c241c4b8 object: add ID property
This is a WirePlumber object unique ID, which comes very useful when identifying
objects in the Lua scripts.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
b172ae915f test/settings.lua: fix the assert failure in the callback API tests
The callback for the last test was getting called with non-string type and this
fails the test. fix it by sending string in correct format.

This test failure was not failing the "make test" this is known limitation in the test
setup. The limitation here is only with the last assert statement.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
72536261e9 policy-node.lua: Second round of cleanup.
- WirePlumber Lua now facilitates Lua libraries/modules, utilize this and create
  modules. Add some tests around this functionality.
- Create policy-hooks.lua containing all the hooks to find-target events
- Create policy-utils.lua module and push all the policy utility functions to it.
- Create common-utils.lua module and push the common utility functions to it.
- Remove all the above functionality from policy-node.lua and clean it up.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
3832e14c1c policy-node.lua: First round of cleanup
- remove scheduling rescan via core APIs instead use the event stack for proper
  scheduling.
- The rescan & handlelinkable hooks will push new findTargetSiAndLink events one
  per session item.
- Register a new "after-events-with-event" hook for findTargetSiAndLink event,
  it runs with lower priority than the rescan hook and so rescan hook can cancel
  unneeded findTargetSiAndLink events.
- Register hooks for move and follow properties.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
270dc5c041 m-lua-scripting: push_event API to return the event created 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
3b211d9082 event-dispatcher: Introduce after-events-with-event hook type
after-events hooks are instantiated with rescan event, not with the event which
actually triggered it. after-events-with-event fills this gap.

policy-node clean needed this kind of hooks.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
33ee9984ed Revert "event-dispatcher: after-events hooks to get the trigger event info"
This reverts commit f97e60a331e72e1c1b79075a9498517628e2a349.
2023-04-17 07:47:09 -04:00
Julian Bouzas
51b78e3572 settings: don't show warning if rule or action are empty objects 2023-04-17 07:47:09 -04:00
Julian Bouzas
2f1aece8b6 settings: remove _get_{boolean|int|float|string}() APIs
They is really no needed with the new _get() API and the WpSpaJson API. In C,
users can use 'wp_spa_json_parse_{boolean|int|float|string}()' APIs to parse the
WpSpaJson. In Lua, users can just do 'Settings.get(setting, m):parse()'.
2023-04-17 07:47:09 -04:00
Julian Bouzas
535af7a33e m-lua-scripting: don't show warning if object key is not a string
The wp_spa_json_parse_string() API also works for strings without quotes.
2023-04-17 07:47:09 -04:00
Julian Bouzas
d79c0f45d5 settings: fix code format 2023-04-17 07:47:09 -04:00
Julian Bouzas
271b6931de settings: fix memory leaks 2023-04-17 07:47:09 -04:00
Julian Bouzas
5e6262718a monitors: use new Settings.get_all() API 2023-04-17 07:47:09 -04:00
Julian Bouzas
1a98155599 settings: add new _get_all() API 2023-04-17 07:47:09 -04:00
Julian Bouzas
2223cd47d4 settings: use WpSpaJson to parse the settings
We need to use WpSpaJson to parse the values in WpSettings. This is because the
wireplumber configuration is written in JSON, so WpSettings should only hold
JSON values. To fix this, 2 API changes have been done:

- wp_settings_get_int() only accepts gint values, instead of gint64 values. This
is because the WpSpaJson API only parses int values, like spa_json_parse_int().

- wp_settings_get_string() now returns a newly allocated string, this is because
the string needs to be decoded in case it has quotes.
2023-04-17 07:47:09 -04:00
Julian Bouzas
9f2168e022 spa-json: add _add_from_string() and _add_from_stringn() builder APIs 2023-04-17 07:47:09 -04:00
Julian Bouzas
bef5b2ef04 settings: use TRUE/FALSE instead of true/false 2023-04-17 07:47:09 -04:00
Julian Bouzas
a76e780b4b docs: update new configuration file names 2023-04-17 07:47:09 -04:00
Julian Bouzas
4d41490f82 conf: rename '*-settings.conf' files to just '*.conf' 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
074294568b create-node.lua: Adjust style 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
cc36ea2fac m-default-profile: Adjust style and update summary. 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
3878b88952 tests/events.c: Adjust style 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
3ff9f240c8 event-dispatcher: after-events hooks to get the trigger event info
after-events hooks will get the original event triggering it, instead of the
rescan event.

after-events hook can register with any event, but it is called with rescan event
info. This is so because, after-events hook run after all the on-events hooks
are done with and as a part of the rescan event. so it is triggered with rescan
event data, which doesnt carry much info, instead of rescan event, it makes more
sense to call the after-events hook with the original event which triggered it.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
72226e3934 policy-node.lua: Adjust style 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
5550777983 policy-bluetooth.lua: Port onto Event-stack 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
1f77be36e5 policy-bluetooth.lua: Adjust style 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
da2ac1b7a1 lib: event-dispatcher: Dont push empty events
Empty events are the events without any hooks, refine log msgs further.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
d57e387f75 event-hooks: give unique names to event hooks 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
6bdc6fb697 event-dispatcher: Donot cancel the object-removed event
The event is not reaching the object-removal hooks due to this.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
82a8bc5673 event-hooks: remove the unwanted second arg in simple hooks 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
695b99f0e8 device-profiles: Port to event-stack 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
464cda4cad create-item.lua: Adjust style 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
ebffbc9ca1 restore-stream.lua: Adjust style 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
78c2e3167a device-profiles: Add summary 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
9197dac94d policy-device-profile.lua: Adjust style 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
bc2d403396 policy-device-routes.lua: Port to event-stack 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
f8072889aa policy-device-routes.lua: Add summary and enhance the debug messages 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
5ebef4be6e policy-device-defaults.lua: Adjust style 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
6e31b47c28 event-dispatcher: Add an enumeration of default event hook priorities
This scheme provides for an orderly execution of hooks as the priorities
are controlled from one single place. Enumeration is defined in such a
way that new items can be added easily.

All the event hooks are changed to get the priorities from this
enumeration.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
9337bb25ef m-default-nodes*: Remove suffixes in hooks name
Suffix is redundant for on events as Events names and Event chains are
printed with 847c0.

Update the settings file used.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
ff03094d67 restore-stream.lua: Port to event-stack 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
dc3e523240 policy-node.lua: Update settings file used 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
ff833b138d event-dispatcher: log event and hook names and chains
- Add a new variable "name" in WpEventHook and use it to log all the
  hooks(by name) picked up in _push_event(). This gives a clear picture
  if hook is registered for a given event.
- Form a name for an event and a chain of events for an event run, log
  both of them. This gives a clear picture of the events executed and
  order in which they are dispatched.
- Similarly build hooks chain and print it in _source_dispatch(), this
  gives a clear picture of the hooks picked and the order in which they
  are dispatched.
- Log only the dispatchable(with hooks) events, this de-clutters
  the log messages.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
a6b3f1c1fb m-standard-event-source: fix params of on-params-changed event 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
025b0f6e2e m-default-nodes: Port to Event stack 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
d61be3c397 doc: event-dispatcher: Update the annotations 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
f5f4acf95d m-standard-event-source: fix metadata changed evnt
Assign type and priority for metadata events
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
869a1068a4 event-dispatcher: Merge global properties
Global properties are needed for event stack to deal with global
objects.

Refine debug messages
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
11dacb9b5f policy-node.lua: Update the summary
Update the summary of what the script does.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
18727d41e4 create-item.lua: Update the summary
Update the summary of what the script does.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
d2770123d3 policy-node: Adjust the priority of policy event
handlelinkable() should run after the linkable is created by the
create-item adjust the Priorities accordingly.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
655e052f59 lib: Refine trace messages 2023-04-17 07:47:09 -04:00
Ashok Sidipotu
4d1a86ced1 m-lua-scripting: Fix bug in WpEvent referencing
While calling async execute closure, take a reference to the WpEvent
object before pushing it to the Lua stack. Otherwise Lua garbage
collector frees it, which leads to invalid memory access.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
fbac3a38a9 policy-node: Port to Event Stack design
- register hooks(simple) for handling linkable object-added/removed
  events.
- register simple rescanning after-event hook for "linkable
  addition/removal" and "device added" events.
2023-04-17 07:47:09 -04:00
George Kiagiadakis
aefc50da3d create-item: push linkable events.
push linkable object-added/removed events.
2023-04-17 07:47:09 -04:00
Ashok Sidipotu
3c2c954107 wireplumber.conf: add m-standard-event-source 2023-04-17 07:47:09 -04:00
George Kiagiadakis
fd91d8a35b WIP: port create-item.lua to use event hooks 2023-04-17 07:47:09 -04:00
George Kiagiadakis
d72f31e803 lua: add EventInterest convenience constructor for declaring interest on events 2023-04-17 07:47:09 -04:00
George Kiagiadakis
2cffd9177a tests: wplua: add event hooks lua test 2023-04-17 07:47:09 -04:00
George Kiagiadakis
01a56496e2 event-dispatcher: use an eventfd to make the source ready
- the source shouldn't become ready if there is nothing to do,
  otherwise idle sources do not run (since they have lower priority)
- when the source becomes ready, we need a fd to wake up GLib's event
  dispatching mechanism to continue processing, otherwise nothing happens
2023-04-17 07:47:09 -04:00
George Kiagiadakis
9db63e8ca6 event-hook: do not expose the dispatcher in the public API
It's a singleton, we can get it from its instance function...
2023-04-17 07:47:09 -04:00
George Kiagiadakis
f91ff40a2d simple-event-hook: do not pass the dispatcher as argument to the closure 2023-04-17 07:47:09 -04:00
George Kiagiadakis
4c7cb5145d lua: implement EventDispatcher.push_event 2023-04-17 07:47:09 -04:00
George Kiagiadakis
5c2565c9b1 lua: add WpAsyncEventHook bindings 2023-04-17 07:47:09 -04:00
George Kiagiadakis
795dc240b6 event-hook: add an async event hook implementation
This one uses 2 closures to implement a WpTransition internally
2023-04-17 07:47:09 -04:00
George Kiagiadakis
b62fdd8fef modules: add m-standard-event-source
An event source for standard pipewire events
2023-04-17 07:47:09 -04:00
George Kiagiadakis
60e1f320c9 event-hook: use WP_TYPE_EVENT as the type for hook interest
and also accept other types, which will match the type of the
event subject
2023-04-17 07:47:09 -04:00
George Kiagiadakis
60c5982cd0 lua: add bindings for event / hook / dispatcher 2023-04-17 07:47:09 -04:00
George Kiagiadakis
9afd588d79 lib: initial version of WpEventDispatcher / WpEvent / WpEventHook 2023-04-17 07:47:09 -04:00
George Kiagiadakis
1fea0f60f4 config: remove obsolete files 2023-04-17 07:47:06 -04:00
Ashok Sidipotu
cfd51d9fe2 lib: wpsettings: Add _register_callback () API 2023-04-17 07:44:19 -04:00
Ashok Sidipotu
8e9d852124 docs: configs-refactor changes. 2023-04-17 07:44:19 -04:00
Ashok Sidipotu
6de381ad45 config/JSON: Spruce up the JSON config files
- declutter the wireplumber.conf file.
- adjust the nomenclature of *-settings.conf files.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
3011a1c07e m-settings: Fix the crash with empty settings
Add a null check when iterator gets the value to detect the end of the
JSON object, this will ensure the rest of the code that operates on the
value is bypassed.

Still it must be noted that an empty setting screws up the following
settings and behavior is undefined, this is the limiation in the
spa-json parsing.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
8a0c4fde4c policy: Switch policy settings to JSON
- Create policy-settings.conf and move all the policy settings to it.
- Change all the policy scripts to fetch the settigs from WpSettings
  API.
- Remove all the references to config/lua.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
067b1954e3 tests: Add tests for JSON array of strings
Bluetooth has a setting that would need JSON array of strings and so
these tests help prepare the ground.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
2f60077460 endpoints: Switch endpoints config to JSON
- Move the endpoints defination to wireplumber.conf under a new section
  in the form of two JSON objects, namely endpoints and
  endpoints-roles.
- Treat the endpoint objects as settings, for the sake of loading,
  parsing and querying.
- m-settings loads the objects and WpSettings parses them as any other
  settings.
- Make the following changes in endpoint scripts.
   - Get the endpoint settings using the _get_string() API.
   - Parse and use the data.
   - Remove references to the config/lua
- Remove the endpoints defination in config/lua
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
ff3b5fe828 main.c: Add support for ifexits and nofail flags
- pipewire uses these flags to control module loading.
- remove all the references of bluetooth config/lua and move to
  wpsettings.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
2ef76f823a bluez.lua: Switch bluez lua monitor to wpsettings
- Monitor to use the JSON APIs and move away from config/lua
- Enhance logic in wpsettings to parse settings which are JSON arrays,
  some of the bluetooth properties are JSON arrays and parsing
  logic confused them for a rule.
- Add corresponding tests around this logic as well.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
4282dff187 wpsettings: switch settings in main.lua.d to JSON
- switch stream based lua script and their configs to wpsettings,
  remove all the config/lua references
- move last remaining scripts and modules from 90-enable-all.lua to
  wireplumber.conf
- delete all files in main.lua.d
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
e180ff2f94 device-settings: Switch device settings to wpsettings
- move all the device based settings and scripts to JSON config and
  remove config/lua references.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
3a25bc14d2 lib: Add _get_float() wpsettings API
- also add the corresponding C & Lua tests.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
b76baca520 wireplumber.conf: split up the wireplumber config
- create wireplumber.conf.d and create a file each for a group
  of settings.
- distrube the "wireplumber.components" section as well into these
  files
2023-04-17 07:44:19 -04:00
George Kiagiadakis
893e44c51e lua: fix number of returned values in Settings.apply_rule 2023-04-17 07:44:19 -04:00
George Kiagiadakis
5cefe9e800 settings: fix doxygen/g-i strings/commands and link them to the sphinx site 2023-04-17 07:44:19 -04:00
Ashok Sidipotu
161c43b71a lua monitors: switch to wpsetttings
- switch alsa.lua, v4l2.lua & libcamera.lua
- remove the config/lua references for these scripts
- fix the wpsettings deps parsing bug.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
7d304096e5 lib: Add _get_{int,string}() APIs
- add integer and string version of the APIs,
- Also Refine the APIs, return value to indicate the setting existance
  and a new param to return the value of the setting.
- add their lua bindings as well, in lua binding the return value nil
  indicates that the setting is not defnied.
- Add corresponding C and lua tests as well.
- Add a few handy debug msgs.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
a4f16a98f0 main: Add support for deps flag in loading modules
- support loading modules dependent on wireplumber settings in JSON
  config.
- load the settings module before parsing wireplumber.components,
  so that dependencies can be fetched during parsing.
- access lua scripts are switched to JSON based config and lua configs
  are removed.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
a5d62b7bbd lib: Add wp_settings_apply_rule() API
- add C based tests
- add lua binding for the API and corresponding lua tests
- address comments from previous commits
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
229f5d0630 spa-json: add _is_container () API 2023-04-17 07:44:19 -04:00
Ashok Sidipotu
75c61f9388 lib: Add parsing logic for rules
- unlike pipewire, rules will be parsed during the bootup time, i.e
  during the creation of the wpsettings object.
- The rules are parsed into the wpinterest objects and stored in the
  wpsettings object, they will be eventually used to service the
  apply_rule() API.
- Support pipewire syntax of rules defination in this version.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
4d7ce2292e tests: Add tests for WpSettings object
- settings.c tests conf file loading & parsing, metadata updates,
  wpsetttings object creation and its API.
- settings.lua tests the API from lua scripts.
- Add a sample settings.conf file, this file contains sections copied
  over from client.conf along with the settings section. Add a file
  each for wp side and lua side of scripts.
- Make changes in base test infrastructure to take a custom conf file.
- Enhance the wp_settings_get_instance_api() to be take metadata_name
  parameter. So, Wpsetttings is now a singleton instance for a given
  metadata file.
- Enhance the m-settings module also to be take metadata_name parameter.
  this is handy for lua side of tests as its cumbersome to do this is
  lua.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
8fd8b01b7a lib: Introduce WpSettings API
- WpSettings is a singleton object which attaches itself to the core
  and registry, it provides a get_instance () for its clients.
- WpSettings provides API to get/set wireplumber settings and rules.
- main.c loads the new object and makes sure it is available for
  for all the modules and scripts. This is achieved by introducing
  a new activation step.
- Add the lua bindings for get_setting API.
2023-04-17 07:44:19 -04:00
Ashok Sidipotu
e9391b195f m-settings: Module to handle JSON config settings.
- parse settings from .conf file.
- create "sm-settings" metadata and copy settings as key value pairs
  to it.
- put in place "persistent" behavior, control it with a special
  setting.
- when persistent behavior is enabled.

  - create a state file and update settings to it.
  - monitor changes in the metadata and update the settings to state
    file.
2023-04-17 07:44:19 -04:00
486 changed files with 45186 additions and 15708 deletions

View file

@ -1,6 +1,15 @@
# Create merge request pipelines for open merge requests, branch pipelines
# otherwise. This allows MRs for new users to run CI, and prevents duplicate
# pipelines for branches with open MRs.
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH
stages: stages:
- container - container
- container_coverity
- build - build
- analysis - analysis
- pages - pages
@ -10,8 +19,8 @@ variables:
# change to build against a different tag or branch of pipewire # change to build against a different tag or branch of pipewire
PIPEWIRE_HEAD: 'master' PIPEWIRE_HEAD: 'master'
# ci-templates as of Mar 24th 2023 # ci-templates as of Feb 14th 2025
.templates_sha: &templates_sha dd90ac0d7a03b574eb4f18d7358083f0c97825f3 .templates_sha: &templates_sha ef5e4669b7500834a17ffe9277e15fbb6d977fff
include: include:
- project: 'freedesktop/ci-templates' - project: 'freedesktop/ci-templates'
@ -27,8 +36,8 @@ include:
.fedora: .fedora:
variables: variables:
# Update this tag when you want to trigger a rebuild # Update this tag when you want to trigger a rebuild
FDO_DISTRIBUTION_TAG: '2023-03-24.1' FDO_DISTRIBUTION_TAG: '2025-03-05.1'
FDO_DISTRIBUTION_VERSION: '37' FDO_DISTRIBUTION_VERSION: '41'
# findutils: used by the .build script below # findutils: used by the .build script below
# dbus-devel: required by pipewire # dbus-devel: required by pipewire
# dbus-daemon: required by GDBus unit tests # dbus-daemon: required by GDBus unit tests
@ -59,12 +68,13 @@ include:
.ubuntu: .ubuntu:
variables: variables:
# Update this tag when you want to trigger a rebuild # Update this tag when you want to trigger a rebuild
FDO_DISTRIBUTION_TAG: '2023-03-24.1' FDO_DISTRIBUTION_TAG: '2023-06-16.1'
FDO_DISTRIBUTION_VERSION: '20.04' FDO_DISTRIBUTION_VERSION: '22.04'
FDO_DISTRIBUTION_PACKAGES: >- FDO_DISTRIBUTION_PACKAGES: >-
debhelper-compat debhelper-compat
findutils findutils
git git
meson
ninja-build ninja-build
pkg-config pkg-config
python3-pip python3-pip
@ -75,14 +85,12 @@ include:
libgirepository1.0-dev libgirepository1.0-dev
doxygen doxygen
python3-lxml python3-lxml
FDO_DISTRIBUTION_EXEC: >-
pip3 install meson
.alpine: .alpine:
variables: variables:
# Update this tag when you want to trigger a rebuild # Update this tag when you want to trigger a rebuild
FDO_DISTRIBUTION_TAG: '2023-03-24.1' FDO_DISTRIBUTION_TAG: '2025-03-05.1'
FDO_DISTRIBUTION_VERSION: '3.15' FDO_DISTRIBUTION_VERSION: '3.21'
FDO_DISTRIBUTION_PACKAGES: >- FDO_DISTRIBUTION_PACKAGES: >-
dbus dbus
dbus-dev dbus-dev
@ -113,14 +121,23 @@ include:
tar xf /tmp/cov-analysis-linux64.tgz ; tar xf /tmp/cov-analysis-linux64.tgz ;
mv cov-analysis-linux64-* coverity ; mv cov-analysis-linux64-* coverity ;
rm /tmp/cov-analysis-linux64.tgz rm /tmp/cov-analysis-linux64.tgz
only:
variables:
- $COVERITY
.not_coverity: .rules_on_success_except_coverity:
except: rules:
variables: - if: $COVERITY
- $COVERITY when: never
- when: on_success
.rules_only_on_coverity:
rules:
- if: $COVERITY
.rules_only_on_mr_and_branch:
rules:
- if: $COVERITY
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH != "master"
.build: .build:
before_script: before_script:
@ -137,13 +154,22 @@ include:
# Fedora also ships that, but without the test plugins that we need... # Fedora also ships that, but without the test plugins that we need...
- git clone --depth=1 --branch="$PIPEWIRE_HEAD" - git clone --depth=1 --branch="$PIPEWIRE_HEAD"
https://gitlab.freedesktop.org/pipewire/pipewire.git https://gitlab.freedesktop.org/pipewire/pipewire.git
- meson "$PW_BUILD_DIR" pipewire --prefix="$PREFIX" # Set build options based on PipeWire version
-Dpipewire-alsa=disabled -Dpipewire-jack=disabled - |
-Dalsa=disabled -Dv4l2=disabled -Djack=disabled -Dbluez5=disabled case "$PIPEWIRE_HEAD" in
-Dvulkan=disabled -Dgstreamer=disabled -Dsystemd=disabled 1.0|1.2|1.4)
-Ddocs=disabled -Dman=disabled -Dexamples=disabled -Dpw-cat=disabled export PIPEWIRE_BUILD_OPTIONS="-Dsystemd=disabled"
-Dsdl2=disabled -Dsndfile=disabled -Dlibpulse=disabled -Davahi=disabled ;;
-Decho-cancel-webrtc=disabled -Dsession-managers=[] *)
export PIPEWIRE_BUILD_OPTIONS="-Dlibsystemd=disabled"
;;
esac
- meson "$PW_BUILD_DIR" pipewire --prefix="$PREFIX" $PIPEWIRE_BUILD_OPTIONS
-Dpipewire-alsa=disabled -Dpipewire-jack=disabled -Dalsa=disabled
-Dv4l2=disabled -Djack=disabled -Dbluez5=disabled -Dvulkan=disabled
-Dgstreamer=disabled -Ddocs=disabled -Dman=disabled -Dexamples=disabled
-Dpw-cat=disabled -Dsdl2=disabled -Dsndfile=disabled -Dlibpulse=disabled
-Davahi=disabled -Decho-cancel-webrtc=disabled -Dsession-managers=[]
-Dvideotestsrc=enabled -Daudiotestsrc=enabled -Dtest=enabled -Dvideotestsrc=enabled -Daudiotestsrc=enabled -Dtest=enabled
- ninja $NINJA_ARGS -C "$PW_BUILD_DIR" install - ninja $NINJA_ARGS -C "$PW_BUILD_DIR" install
# misc environment only for wireplumber # misc environment only for wireplumber
@ -165,6 +191,7 @@ include:
container_fedora: container_fedora:
extends: extends:
- .rules_on_success_except_coverity
- .fedora - .fedora
- .fdo.container-build@fedora - .fdo.container-build@fedora
stage: container stage: container
@ -173,6 +200,7 @@ container_fedora:
container_ubuntu: container_ubuntu:
extends: extends:
- .rules_only_on_mr_and_branch
- .ubuntu - .ubuntu
- .fdo.container-build@ubuntu - .fdo.container-build@ubuntu
stage: container stage: container
@ -181,6 +209,7 @@ container_ubuntu:
container_alpine: container_alpine:
extends: extends:
- .rules_only_on_mr_and_branch
- .alpine - .alpine
- .fdo.container-build@alpine - .fdo.container-build@alpine
stage: container stage: container
@ -189,17 +218,18 @@ container_alpine:
container_coverity: container_coverity:
extends: extends:
- .rules_only_on_coverity
- .fedora - .fedora
- .coverity - .coverity
- .fdo.container-build@fedora - .fdo.container-build@fedora
stage: container_coverity stage: container
variables: variables:
GIT_STRATEGY: none GIT_STRATEGY: none
build_on_fedora_with_docs: build_on_fedora_with_docs:
extends: extends:
- .rules_on_success_except_coverity
- .fedora - .fedora
- .not_coverity
- .fdo.distribution-image@fedora - .fdo.distribution-image@fedora
- .build - .build
stage: build stage: build
@ -208,18 +238,21 @@ build_on_fedora_with_docs:
build_on_fedora_no_docs: build_on_fedora_no_docs:
extends: extends:
- .rules_only_on_mr_and_branch
- .fedora - .fedora
- .not_coverity
- .fdo.distribution-image@fedora - .fdo.distribution-image@fedora
- .build - .build
stage: build stage: build
variables: variables:
BUILD_OPTIONS: -Dintrospection=enabled -Ddoc=disabled -Dsystem-lua=false BUILD_OPTIONS: -Dintrospection=enabled -Ddoc=disabled -Dsystem-lua=false
parallel:
matrix:
- PIPEWIRE_HEAD: ['master', '1.4', '1.2', '1.0']
build_on_ubuntu_with_gir: build_on_ubuntu_with_gir:
extends: extends:
- .rules_only_on_mr_and_branch
- .ubuntu - .ubuntu
- .not_coverity
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .build - .build
stage: build stage: build
@ -228,8 +261,8 @@ build_on_ubuntu_with_gir:
build_on_ubuntu_no_gir: build_on_ubuntu_no_gir:
extends: extends:
- .rules_only_on_mr_and_branch
- .ubuntu - .ubuntu
- .not_coverity
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .build - .build
stage: build stage: build
@ -238,8 +271,8 @@ build_on_ubuntu_no_gir:
build_on_alpine: build_on_alpine:
extends: extends:
- .rules_only_on_mr_and_branch
- .alpine - .alpine
- .not_coverity
- .fdo.distribution-image@alpine - .fdo.distribution-image@alpine
- .build - .build
stage: build stage: build
@ -248,6 +281,7 @@ build_on_alpine:
build_with_coverity: build_with_coverity:
extends: extends:
- .rules_only_on_coverity
- .fedora - .fedora
- .coverity - .coverity
- .fdo.suffixed-image@fedora - .fdo.suffixed-image@fedora
@ -277,16 +311,23 @@ build_with_coverity:
shellcheck: shellcheck:
extends: extends:
- .fedora - .fedora
- .not_coverity
- .fdo.distribution-image@fedora - .fdo.distribution-image@fedora
stage: analysis stage: analysis
script: script:
- shellcheck $(git grep -l "#\!/.*bin/.*sh") - shellcheck $(git grep -l "#\!/.*bin/.*sh")
rules:
- if: $COVERITY
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
- "**/*.sh"
- if: $CI_COMMIT_BRANCH != "master"
changes:
- "**/*.sh"
linguas_check: linguas_check:
extends: extends:
- .fedora - .fedora
- .not_coverity
- .fdo.distribution-image@fedora - .fdo.distribution-image@fedora
stage: analysis stage: analysis
script: script:
@ -295,10 +336,17 @@ linguas_check:
- ls *.po | sed s/.po//g | sort > LINGUAS.new - ls *.po | sed s/.po//g | sort > LINGUAS.new
- diff -u LINGUAS.sorted LINGUAS.new - diff -u LINGUAS.sorted LINGUAS.new
- rm -f LINGUAS.* - rm -f LINGUAS.*
rules:
- if: $COVERITY
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
- po/*
- if: $CI_COMMIT_BRANCH != "master"
changes:
- po/*
pages: pages:
extends:
- .not_coverity
stage: pages stage: pages
dependencies: dependencies:
- build_on_fedora_with_docs - build_on_fedora_with_docs
@ -308,5 +356,7 @@ pages:
artifacts: artifacts:
paths: paths:
- public - public
only: rules:
- master - if: $COVERITY
when: never
- if: $CI_COMMIT_BRANCH == "master"

37
AGENTS.md Normal file
View file

@ -0,0 +1,37 @@
## Building and Testing
- To compile the project: `meson compile -C build` (compiles everything, no target needed)
- To run tests: `meson test -C build`
- The build artifacts always live in a directory called `build` or `builddir`.
If `build` doesn't exist, use `-C builddir` in the meson commands.
## Git Workflow
- Main branch: `master`
- Always create feature branches for new work
- Use descriptive commit messages following project conventions
- Reference GitLab MR/issue numbers in commits where applicable
- Never commit build artifacts or temporary files
- Use `glab` CLI tool for GitLab interactions (MRs, issues, etc.)
## Making a release
- Each release always consists of an entry in NEWS.rst, at the top of the file, which describes
the changes between the previous release and the current one. In addition, each release is given
a unique version number, which is present:
1. on the section header of that NEWS.rst entry
2. in the project() command in meson.build
3. on the commit message of the commit that introduces the above 2 changes
4. on the git tag that marks the above commit
- In order to make a release:
- Begin by analyzing the git history and the merged MRs from GitLab between the previous release
and today. GitLab MRs that are relevant always have the new release's version number set as a
"milestone"
- Create a new entry in NEWS.rst describing the changes, in a similar style and format as the
previous entries. Consolidate the changes to larger work items and also reference the relevant
gitlab MR that corresponds to each change and/or the gitlab issues that were addressed by each
change.
- Make sure to move the "Past releases" section header up, so that the only 2 top-level sections
are the new release section and the "Past releases" section.
- Edit meson.build to change the project version to the new release number
- Do not commit anything to git. Let the user review the changes and commit manually.

778
NEWS.rst
View file

@ -1,6 +1,779 @@
WirePlumber 0.4.15 WirePlumber 0.5.14
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
Additions & Enhancements:
- Added per-device default volume configuration via the
``device.routes.default-{source,sink}-volume`` property, allowing device-specific volume
defaults (e.g. a comfortable default for internal speakers or no attenuation for HDMI) (!772)
- Added Lua 5.5 support; the bundled Lua subproject wrap has also been updated to 5.5.0
(!775, !788)
- Enhanced libcamera monitor to load camera nodes locally within the WirePlumber
process instead of the PipeWire daemon, eliminating race conditions that could occur
during initial enumeration and hotplug events (!790)
- Enhanced Bluetooth loopback nodes to always be created when a device supports both
A2DP and HSP/HFP profiles, simplifying the logic and making the BT profile autoswitch
setting take effect immediately without requiring device reconnection (!782)
- Enhanced Bluetooth loopback nodes to use ``target.object`` property instead of smart
filters, fixing issues that prevented users from setting them as default nodes and
also allowing smart filters to be used with them (#898; !792)
- Enhanced Bluetooth profile autoswitch logic with further robustness improvements,
including better headset profile detection using profile name patterns and resolving
race conditions by running profile switching after ``device/apply-profile`` in a
dedicated event hook (#926, #923; !776, !777, !808)
- Enhanced wpctl ``set-default`` command to accept virtual nodes (e.g.
``Audio/Source/Virtual``) in addition to regular device nodes (#896; !787)
- Improved stream linking to make the full graph rescan optional when linkable items
change, saving CPU on low-end systems and reducing audio startup latency when
connecting multiple streams in quick succession (!800)
- Allowed installation of systemd service units without libsystemd being present,
useful for distributions like Alpine Linux that allow systemd service subpackages
(!793)
- Allowed the ``mincore`` syscall in the WirePlumber systemd sandbox, required for
Mesa/EGL (e.g. for the libcamera GPUISP pipeline)
- Allowed passing ``WIREPLUMBER_CONFIG_DIR`` via the ``wp-uninstalled`` script,
useful for passing additional configuration paths in an uninstalled environment (!801)
Fixes:
- Removed Bluetooth sink loopback node, which was causing issues with KDE and GNOME (!794)
- Fixed default audio source selection to never automatically use ``Audio/Sink`` nodes
as the default source unless explicitly selected by the user (#886; !781)
- Fixed crash in ``state-stream`` when the Format parameter has a Choice for the
number of channels (#903; !795)
- Fixed BAP Bluetooth device set channel properties, where ``audio.position`` was
incorrectly serialized as a pointer address instead of the channel array (!786)
- Fixed memory leaks in ``wp_interest_event_hook_get_matching_event_types`` and in
the Lua ``LocalModule()`` implementation (!784, !810)
- Fixed HFP HF stream media class being incorrectly assigned due to
``api.bluez5.internal=true`` being set on HFP HF streams (!809)
- Fixed Lua 5.4 compatibility in ``state-stream`` script
- Updated translations: Bulgarian, Georgian, Kazakh, Swedish
Past releases
~~~~~~~~~~~~~
WirePlumber 0.5.13
..................
Additions & Enhancements:
- Added internal filter graph support for audio nodes, allowing users to
create audio preprocessing and postprocessing chains without exposing
filters to applications, useful for software DSP (!743)
- Added new Lua Properties API that significantly improves performance by
avoiding constant serialization between WpProperties and Lua tables,
resulting in approximately 40% faster node linking (!757)
- Added WpIterator Lua API for more efficient parameter enumeration (!746)
- Added bash completions for wpctl command (!762)
- Added script to find suitable volume control when using role-based policy,
allowing volume sliders to automatically adjust the volume of the currently
active role (e.g., ringing, call, media) (!711)
- Added experimental HDMI channel detection setting to use HDMI ELD
information for channel configuration (!749)
- Enhanced role-based policy to allow setting preferred target sinks for
media role loopbacks via ``policy.role-based.preferred-target`` (!754)
- Enhanced Bluetooth profile autoswitch logic to be more robust and handle
saved profiles correctly, including support for loopback sink nodes (!739)
- Enhanced ALSA monitor to include ``alsa.*`` device properties on nodes for
rule matching (!761)
- Optimized stream node linking for common cases to reduce latency when new
audio/video streams are added (!760)
- Improved event dispatcher performance by using hash table registration for
event hooks, eliminating performance degradation as more hooks are
registered (!765)
- Increased audio headroom for VMware and VirtualBox virtual machines (!756)
- Added setting to prevent restoring "Off" profiles via
``session.dont-restore-off-profile`` property (!753)
- Added support for 128 audio channels when compiled with a recent version of
PipeWire (pipewire#4995; CI checks in !768)
Fixes:
- Fixed memory leaks and issues in the modem manager module (!770, !764)
- Fixed MPRIS module incorrectly treating GHashTable as GObject (!759)
- Fixed warning messages when process files in ``/proc/<pid>/*`` don't exist,
particularly when processes are removed quickly (#816, !717)
- Fixed MONO audio configuration to only apply to device sink nodes, allowing
multi-channel mixing in the graph (!769)
- Fixed event dispatcher hook registration and removal to avoid spurious
errors (!747)
- Improved logging for standard-link activation failures (!744)
- Simplified event-hook interest matching for better performance (!758)
WirePlumber 0.5.12
..................
Additions & Enhancements:
- Added mono audio configuration support via ``node.features.audio.mono``
setting that can be changed at runtime with wpctl (!721)
- Added automatic muting of ALSA devices when a running node is removed,
helping prevent loud audio on speakers when headsets are unplugged (!734)
- Added notifications API module for sending system notifications (!734)
- Added comprehensive wpctl man page and documentation (!735, #825)
- Enhanced object interest handling for PipeWire properties on session items (!738)
Fixes:
- Fixed race condition during shutdown in the permissions portal module that
could cause crashes in GDBus signal handling (!748)
- Added device validity check in state-routes handling to prevent issues
when devices are removed during async operations (!737, #844)
- Fixed Log.critical undefined function error in device-info-cache (!733)
- Improved device hook documentation and configuration (!736)
WirePlumber 0.5.11
..................
Additions & Enhancements:
- Added modem manager module for tracking voice call status and voice call
device profile selection hooks to improve phone call audio routing on
mobile devices (!722, !729, #819)
- Added MPRIS media player pause functionality that automatically pauses
media playback when the audio target (e.g. headphones) is removed (!699, #764)
- Added support for human-readable names and localization of settings in
``wireplumber.conf`` with ``wpctl`` displaying localized setting descriptions (!712)
- Improved default node selection logic to use both session and route
priorities when nodes have equal session priorities (!720)
- Increased USB device priority in the ALSA monitor (!719)
Fixes:
- Fixed multiple Lua runtime issues including type confusion bugs, stack
overflow prevention, and SPA POD array/choice builders (!723, !728)
- Fixed proxy object lifecycle management by properly clearing the
OWNED_BY_PROXY flag when proxies are destroyed to prevent dangling
pointers (!732)
- Fixed state-routes handling to prevent saving unavailable routes and
eliminate race conditions during profile switching (!730, #762)
- Fixed some memory leaks in the script tester and the settings iterator (!727, !726)
- Fixed a potential crash caused by module-loopback destroying itself when the
pipewire connection is closed (#812)
- Fixed profile saving behavior in ``wpctl set-profile`` command (#808)
- Fixed GObject introspection closure annotation
WirePlumber 0.5.10
..................
Fixed a critical crash in ``linking-utils.haveAvailableRoutes`` that was
introduced accidentally in 0.5.9 and caused loss of audio output on affected
systems (#797, #799, #800, !713)
WirePlumber 0.5.9
.................
Additions & Enhancements:
- Added a new audio node grouping functionality using an external command line
tool (!646)
- The libcamera monitor now supports devices that are not associated with
device ids (!701)
- The wireplumber user systemd service is now associated with dbus.service to
avoid strange warnings when dbus exits (!702)
- Added "SYSLOG_IDENTIFIER", "SYSLOG_FACILITY", "SYSLOG_PID" and "TID" to log
messages that are sent to the journal (!709)
Fixes:
- Fixed a crash of ``wpctl set-default`` on 32-bit architectures (#773)
- Fixed a crash when a configuration component had no 'provides' field (#771)
- Reduced the log level of some messages that didn't need to be as high (!695)
- Fixed another nil reference issue in the alsa.lua monitor script (!704)
- Fixed name deduplication of v4l2 and libcamera devices (!705)
- Fixed an issue with wpctl not being able to save settings sometimes (!708, #749)
WirePlumber 0.5.8
.................
Additions & Enhancements:
- Added support for handling UCM SplitPCM nodes in the ALSA monitor, which
allows native PipeWire channel remapping using loopbacks for devices that
use this feature (!685)
- Introduced new functions to mark WpSpaDevice child objects as pending.
This allows properly associating asynchronously created loopback nodes with
their parent WpSpaDevice without losing ObjectConfig events (!687, !689)
- Improved the node name deduplication logic in the ALSA monitor to prevent
node names with .2, .3, etc appended to them in some more cases (!688)
- Added a new script to populate ``session.services``. This is a step towards
implementing detection of features that PipeWire can service (!686)
Fixes:
- Fixed an issue that was causing duplicate Bluetooth SCO (HSP/HFP) source
nodes to be shown in UIs (#701, !683)
- In the BlueZ monitor, marked the source loopback node as non-virtual,
addressing how it appears on UIs (#729)
- Disabled stream-restore for device loopback nodes to prevent unwanted
property changes (!691)
- Fixed ``wp_lua_log_topic_copy()`` to correctly copy topic names (#757)
- Updated script tests to handle differences in object identifiers
(``object.serial`` vs ``node.id``), ensuring proper test behavior (#761)
WirePlumber 0.5.7
.................
Highlights:
- Fixed an issue that would cause random profile switching when an application
was trying to capture from non-Bluetooth devices (#715, #634, !669)
- Fixed an issue that would cause strange profile selection issues [choices
not being remembered or unavailable routes being selected] (#734)
- Added a timer that delays switching Bluetooth headsets to the HSP/HFP
profile, avoiding needless rapid switching when an application is trying to
probe device capabilities instead of actually capturing audio (!664)
- Improved libcamera/v4l2 device deduplication logic to work with more complex
devices (!674, !675, #689, #708)
Fixes:
- Fixed two memory leaks in module-mixer-api and module-dbus-connection
(!672, !673)
- Fixed a crash that could occur in module-reserve-device (!680, #742)
- Fixed an issue that would cause the warning "[string "alsa.lua"]:182:
attempt to concatenate a nil value (local 'node_name')" to appear in the
logs when an ALSA device was busy, breaking node name deduplication (!681)
- Fixed an issue that could make find-preferred-profile.lua crash instead of
properly applying profile priority rules (#751)
WirePlumber 0.5.6
.................
Additions:
- Implemented before/after dependencies for components, to ensure correct
load order in custom configurations (#600)
- Implemented profile inheritance in the configuration file. This allows
profiles to inherit all the feature specifications of other profiles, which
is useful to avoid copying long lists of features just to make small changes
- Added multi-instance configuration profiles, tested and documented them
- Added a ``main-systemwide`` profile, which is now the default for instances
started via the system-wide systemd service and disables features that
depend on the user session (#608)
- Added a ``wp_core_connect_fd`` method, which allows making a connection to
PipeWire via an existing open socket (useful for portal-based connections)
Fixes:
- The Bluetooth auto-switch script now uses the common event source object
managers, which should improve its stability (!663)
- Fix an issue where switching between Bluetooth profiles would temporarily
link active audio streams to the internal speakers (!655)
WirePlumber 0.5.5
.................
Highlights:
- Hotfix release to address crashes in the Bluetooth HSP/HFP autoswitch
functionality that were side-effects of some changes that were part
of the role-based linking policy (#682)
Improvements:
- wpctl will now properly show a '*' in front of sink filters when they are
selected as the default sink (!660)
WirePlumber 0.5.4
.................
Highlights:
- Refactored the role-based linking policy (previously known also as
"endpoints" or "virtual items" policy) to blend in with the standard desktop
policy. It is now possible use role-based sinks alongside standard desktop
audio operations and they will only be used for streams that have a
"media.role" defined. It is also possible to force streams to have a
media.role, using a setting. Other features include: blending with smart
filters in the graph and allowing hardware DSP nodes to be also used easily
instead of requiring software loopbacks for all roles. (#610, !649)
Improvements:
- Filters that are not declared as smart will now behave again as normal
application streams, instead of being treated sometimes differently (!657)
Fixes:
- Fixed an issue that would cause WirePlumber to crash at startup if an
empty configuration file was present in one of the search paths (#671)
- Fixed Bluetooth profile auto-switching when a filter is permanently linked
to the Bluetooth source (!650)
- Fixed an issue in the software-dsp script that would cause DSP filters to
stay around and cause issues after their device node was destroyed (!651)
- Fixed an issue in the autoswitch-bluetooth-profile script that could cause
an infinite loop of switching between profiles (!652, #617)
- Fixed a rare issue that could cause WirePlumber to crash when dealing with
a device object that didn't have the "device.name" property set (#674)
WirePlumber 0.5.3
.................
Fixes:
- Fixed a long standing issue that would cause many device nodes to have
inconsistent naming, with a '.N' suffix (where N is a number >= 2) being
appended at seemingly random times (#500)
- Fixed an issue that would cause unavailable device profiles to be selected
if they were previously stored in the state file, sometimes requiring users
to manually remove the state file to get things working again (#613)
- Fixed an occasional crash that could sometimes be triggered by hovering
the volume icon on the KDE taskbar, and possibly other similar actions
(#628, !644)
- Fixed camera device deduplication logic when the same device is available
through both V4L2 and libcamera, and the libcamera one groups multiple V4L2
devices together (#623, !636)
- Fixed applying the default volume on streams that have no volume previously
stored in the state file (#655)
- Fixed an issue that would prevent some camera nodes - in some cases -
from being destroyed when the camera device is removed (#640)
- Fixed an issue that would cause video stream nodes to be linked with audio
smart filters, if smart audio filters were configured (!647)
- Fixed an issue that would cause WP to re-activate device profiles even
though they were already active (!639)
- Configuration files in standard JSON format (starting with a '{', among
other things) are now correctly parsed (#633)
- Fixed overriding non-container values when merging JSON objects (#653)
- Functions marked with WP_PRIVATE_API are now also marked as
non-introspectable in the gobject-introspection metadata (#599)
Improvements:
- Logging on the systemd journal now includes the log topic and also the log
level and location directly on the message string when the log level is
high enough, which is useful for gathering additional context in logs
submitted by users (!640)
- Added a video-only profile in wireplumber.conf, for systems where only
camera & screensharing are to be used (#652)
- Improved seat state monitoring so that Bluetooth devices are only enabled
when the user is active on a local seat, instead of allowing remote users
as well (!641)
- Improved how main filter nodes are detected for the smart filters (!642)
- Added Lua method to merge JSON containers (!637)
WirePlumber 0.5.2
.................
Highlights:
- Added support for loading configuration files other than the default
wireplumber.conf within Lua scripts (!629)
- Added support for loading single-section configuration files, without
fragments (!629)
- Updated the node.software-dsp script to be able to load filter-chain graphs
from external configuration files, which is needed for Asahi Linux audio
DSP configuration (!629)
Fixes:
- Fixed destroying camera nodes when the camera device is removed (#627, !631)
- Fixed an issue with Bluetooth BAP device set naming (!632)
- Fixed an issue caused by the pipewire event loop not being "entered" as
expected (!634, #638)
- A false positive warning about no modules being loaded is now suppressed
when using libpipewire >= 1.0.5 (#620)
- Default nodes can now be selected using priority.driver when
priority.session is not set (#642)
Changes:
- The library version is now generated following pipewire's versioning scheme:
libwireplumber-0.5.so.0.5.2 becomes libwireplumber-0.5.so.0.0502.0 (!633)
WirePlumber 0.5.1
.................
Highlights:
- Added a guide documenting how to migrate configuration from 0.4 to 0.5,
also available online at:
https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/migration.html
If you are packaging WirePlumber for a distribution, please consider
informing users about this.
Fixes:
- Fixed an odd issue where microphones would stop being usable when a
Bluetooth headset was connected in the HSP/HFP profile (#598, !620)
- Fixed an issue where it was not possible to store the volume/mute state of
system notifications (#604)
- Fixed a rare crash that could occur when a node was destroyed while the
'select-target' event was still being processed (!621)
- Fixed deleting all the persistent settings via ``wpctl --delete`` (!622)
- Fixed using Bluetooth autoswitch with A2DP profiles that have an input route
(!624)
- Fixed sending an error to clients when linking fails due to a format
mismatch (!625)
Additions:
- Added a check that prints a verbose warning when old-style 0.4.x Lua
configuration files are found in the system. (#611)
- The "policy-dsp" script, used in Asahi Linux to provide a software DSP
for Apple Sillicon devices, has now been ported to 0.5 properly and
documented (#619, !627)
WirePlumber 0.5.0
.................
Changes:
- Bumped the minimum required version of PipeWire to 1.0.2, because we
make use of the 'api.bluez5.internal' property of the BlueZ monitor (!613)
- Improved the naming of Bluetooth nodes when the auto-switching loopback
node is present (!614)
- Updated the documentation on "settings", the Bluetooth monitor, the Access
configuration, the file search locations and added a document on how to
modify the configuration file (#595, !616)
Fixes:
- Fixed checking for available routes when selecting the default node (!609)
- Fixed an issue that was causing an infinite loop storing routes in the
state file (!610)
- Fixed the interpretation of boolean values in the alsa monitor rules (#586, !611)
- Fixes a Lua crash when we have 2 smart filters, one with a target and one
without (!612)
- Fixed an issue where the default nodes would not be updated when the
currently selected default node became unavailable (#588, !615)
- Fixed an issue that would cause the Props (volume, mute, etc) of loopbacks
and other filter nodes to not be restored at startup (#577, !617)
- Fixed how some constants were represented in the gobject-introspection file,
mostly by converting them from defines to enums (#540, #591)
- Fixed an issue using WirePlumber headers in other projects due to
redefinition of G_LOG_DOMAIN (#571)
WirePlumber 0.4.90
..................
This is the first release candidate (RC1) of WirePlumber 0.5.0.
Highlights:
- The configuration system has been changed back to load files from the
WirePlumber configuration directories, such as ``/etc/wireplumber`` and
``$XDG_CONFIG_HOME/wireplumber``, unlike in the pre-releases. This was done
because issues were observed with installations that use a different prefix
for pipewire and wireplumber. If you had a ``wireplumber.conf`` file in
``/etc/pipewire`` or ``$XDG_CONFIG_HOME/pipewire``, you should move it to
``/etc/wireplumber`` or ``$XDG_CONFIG_HOME/wireplumber`` respectively (!601)
- The internal base directories lookup system now also respects the
``XDG_CONFIG_DIRS`` and ``XDG_DATA_DIRS`` environment variables, and their
default values as per the XDG spec, so it is possible to install
configuration files also in places like ``/etc/xdg/wireplumber`` and
override system-wide data paths (!601)
- ``wpctl`` now has a ``settings`` subcommand to show, change and delete
settings at runtime. This comes with changes in the ``WpSettings`` system to
validate settings using a schema that is defined in the configuration file.
The schema is also exported on a metadata object, so it is available to any
client that wants to expose WirePlumber settings (!599, !600)
- The ``WpConf`` API has changed to not be a singleton and support opening
arbitrary config files. The main config file now needs to be opened prior to
creating a ``WpCore`` and passed to the core using a property. The core uses
that without letting the underlying ``pw_context`` open and read the default
``client.conf``. The core also closes the ``WpConf`` after all components
are loaded, which means all the config loading is done early at startup.
Finally, ``WpConf`` loads all sections lazily, keeping the underlying files
memory mapped until it is closed and merging them on demand (!601, !606)
WirePlumber 0.4.82
..................
This is a second pre-release of WirePlumber 0.5.0, made available for testing
purposes. This is not API/ABI stable yet and there is still pending work to do
before the final 0.5.0 release, both in the codebase and the documentation.
Highlights:
- Bluetooth auto-switching is now implemented with a virtual source node. When
an application links to it, the actual device switches to the HSP/HFP
profile to provide the real audio stream. This is a more robust solution
that works with more applications and is more user-friendly than the
previous application whitelist approach
- Added support for dynamic log level changes via the PipeWire ``settings``
metadata. Also added support for log level patterns in the configuration
file
- The "persistent" (i.e. stored) settings approach has changed to use two
different metadata objects: ``sm-settings`` and ``persistent-sm-settings``.
Changes in the former are applied in the current session but not stored,
while changes in the latter are stored and restored at startup. Some work
was also done to expose a ``wpctl`` interface to read and change these
settings, but more is underway
- Several WirePlumber-specific node properties that used to be called
``target.*`` have been renamed to ``node.*`` to match the PipeWire
convention of ``node.dont-reconnect``. These are also now fully documented
Other changes:
- Many documentation updates
- Added support for SNAP container permissions
- Fixed multiple issues related to restoring the Route parameter of devices,
which includes volume state (#551)
- Smart filters can now be targetted by specific streams directly when
the ``filter.smart.targetable`` property is set (#554)
- Ported the mechanism to override device profile priorities in the
configuration, which is used to re-prioritize Bluetooth codecs
- WpSettings is no longer a singleton class and there is a built-in component
to preload an instance of it
WirePlumber 0.4.81
..................
This is a preliminary release of WirePlumber 0.5.0, which is made available
for testing purposes. Please test it and report feedback (merge requests are
also welcome ;) ). This is not API/ABI stable yet and there is still pending
work to do before the final 0.5.0 release, both in the codebase and the
documentation.
Highlights:
- Lua scripts have been refactored to use the new event dispatcher API, which
allows them to be split into multiple small fragments that react to
events in a specified order. This allows scripts to be more modular and
easier to maintain, as well as more predictable in terms of execution
order.
- The configuration system has been refactored to use a single SPA-JSON file,
like PipeWire does, with support for fragments that can override options.
This file is also now loaded using PipeWire's configuration API, which
effectively means that the file is now loaded from the PipeWire configuration
directories, such as ``/etc/pipewire`` and ``$XDG_CONFIG_HOME/pipewire``.
- The configuration system now has the concept of profiles, which are groups
of components that can be loaded together, with the ability to mark certain
components as optional. This allows having multiple configurations that
can be loaded using the same configuration file. Optional components also
allow loading the same profile gracefully on different setups, where some
components may not be available (ex, loading of the session D-Bus plugin on
a system-wide PipeWire setup now does not fail).
- Many configuration options are now exposed in the ``sm-settings`` metadata,
which allows changing them at runtime. This can be leveraged in the future
to implement configuration tools that can modify WirePlumber's behaviour
dynamically, without restarting.
- A new "filters" system has been implemented, which allows specifying chains
of "filter" nodes to be dynamically linked in-between streams and devices.
This is achieved with certain properties and metadata that can be set on
the filter nodes themselves.
- The default linking policy now reads some more ``target.*`` properties from
nodes, which allows fine-tuning some aspects of their linking behaviour,
such as whether they are allowed to be re-linked or whether an error should
be sent to the client if they cannot be linked.
- Some state files have been renamed and some have changed format to use JSON
for storing complex values, such as arrays. This may cause some of the old
state to be lost on upgrade, as there is no transition path implemented.
- The libcamera and V4L2 monitors have a "device deduplication" logic built-in,
which means that for each physical camera device, only one node will be
created, either from libcamera or V4L2, depending on which one is considered
better for the device. This is mainly to avoid having multiple nodes for
the same camera device, which can cause confusion when looking at the list
of available cameras in applications.
WirePlumber 0.4.17
..................
Fixes:
- Fixed a reference counting issue in the object managers that could cause
crashes due to memory corruption (#534)
- Fixed an issue with filters linking to wrong targets, often with two sets
of links (#536)
- Fixed a crash in the endpoints policy that would show up when log messages
were enabled at level 3 or higher
WirePlumber 0.4.16
..................
Additions:
- Added a new "sm-objects" script that allows loading objects on demand
via metadata entries that describe the object to load; this can be used to
load pipewire modules, such as filters or network sources/sinks, on demand
- Added a mechanism to override device profile priorities in the configuration,
mainly as a way to re-prioritize Bluetooth codecs, but this also can be used
for other devices
- Added a mechanism in the endpoints policy to allow connecting filters
between a certain endpoint's virtual sink and the device sink; this is
specifically intended to allow plugging a filter-chain to act as equalizer
on the Multimedia endpoint
- Added wp_core_get_own_bound_id() method in WpCore
Changes:
- PipeWire 0.3.68 is now required
- policy-dsp now has the ability to hide hardware nodes behind the DSP sink
to prevent hardware misuse or damage
- JSON parsing in Lua now allows keys inside objects to be without quotes
- Added optional argument in the Lua JSON parse() method to limit recursions,
making it possible to partially parse a JSON object
- It is now possible to pass ``nil`` in Lua object constructors that expect an
optional properties object; previously, omitting the argument was the only
way to skip the properties
- The endpoints policy now marks the endpoint nodes as "passive" instead of
marking their links, adjusting for the behavior change in PipeWire 0.3.68
- Removed the "passive" property from si-standard-link, since only nodes are
marked as passive now
Fixes:
- Fixed the ``wpctl clear-default`` command to completely clear all the
default nodes state instead of only the last set default
- Reduced the amount of globals that initially match the interest in the
object manager
- Used an idle callback instead of pw_core_sync() in the object manager to
expose tmp globals
WirePlumber 0.4.15
..................
Additions: Additions:
- A new "DSP policy" module has been added; its purpose is to automatically - A new "DSP policy" module has been added; its purpose is to automatically
@ -51,9 +824,6 @@ Changes/Fixes:
- Added some missing `\since` annotations and made them show up in the - Added some missing `\since` annotations and made them show up in the
generated gobject-introspection file, to help bindings generators generated gobject-introspection file, to help bindings generators
Past releases
~~~~~~~~~~~~~
WirePlumber 0.4.14 WirePlumber 0.4.14
.................. ..................

View file

@ -7,9 +7,6 @@ WirePlumber
.. image:: https://scan.coverity.com/projects/21488/badge.svg .. image:: https://scan.coverity.com/projects/21488/badge.svg
:alt: Coverity Scan Build Status :alt: Coverity Scan Build Status
.. image:: https://img.shields.io/tokei/lines/gitlab.freedesktop.org/pipewire/wireplumber
:alt: Lines of code
.. image:: https://img.shields.io/badge/license-MIT-green .. image:: https://img.shields.io/badge/license-MIT-green
:alt: License :alt: License

View file

@ -1240,15 +1240,6 @@ HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80 HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that # documentation will contain a main index with vertical navigation menus that
# are dynamically created via JavaScript. If disabled, the navigation index will # are dynamically created via JavaScript. If disabled, the navigation index will
@ -1543,17 +1534,6 @@ HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10 FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
# to create new LaTeX commands to be used in formulas as building blocks. See # to create new LaTeX commands to be used in formulas as building blocks. See
# the section "Including formulas" for details. # the section "Including formulas" for details.
@ -1865,14 +1845,6 @@ LATEX_HIDE_INDICES = NO
LATEX_BIB_STYLE = plain LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_TIMESTAMP = NO
# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
# path from which the emoji images will be read. If a relative path is entered, # path from which the emoji images will be read. If a relative path is entered,
# it will be relative to the LATEX_OUTPUT directory. If left blank the # it will be relative to the LATEX_OUTPUT directory. If left blank the
@ -2265,23 +2237,6 @@ HAVE_DOT = YES
DOT_NUM_THREADS = 0 DOT_NUM_THREADS = 0
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# setting DOT_FONTPATH to the directory containing the font.
# The default value is: Helvetica.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTNAME = Helvetica
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
# dot graphs.
# Minimum value: 4, maximum value: 24, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the default font as specified with # By default doxygen will tell dot to use the default font as specified with
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set # DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
# the path where dot can find it using this tag. # the path where dot can find it using this tag.
@ -2518,18 +2473,6 @@ DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0 MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
# to support this out of the box.
#
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This # files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support # makes dot run faster, but since only newer versions of dot (>1.8.10) support

View file

@ -1,11 +1,15 @@
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
project = 'WirePlumber' project = 'WirePlumber'
copyright = '2021, Collabora' copyright = '2020-2025, Collabora & contributors'
author = 'Collabora' author = 'The WirePlumber Developers'
release = '@VERSION@' release = '@VERSION@'
version = '@VERSION@' version = '@VERSION@'
# -- General configuration ---------------------------------------------------
smartquotes = False
# -- Breathe configuration --------------------------------------------------- # -- Breathe configuration ---------------------------------------------------
extensions = [ extensions = [
@ -43,3 +47,9 @@ html_css_files = ['custom.css']
graphviz_output_format = "svg" graphviz_output_format = "svg"
pygments_style = "friendly" pygments_style = "friendly"
# -- Options for manual page output -----------------------------------------
man_pages = [
('tools/wpctl', 'wpctl', 'WirePlumber Control CLI', ['The WirePlumber Developers'], 1)
]

View file

@ -130,7 +130,7 @@ class DoxygenProcess(object):
def __process_element(self, xml): def __process_element(self, xml):
s = "" s = ""
if xml.text and re.search('\S', xml.text): if xml.text and re.search(r'\S', xml.text):
s += xml.text s += xml.text
for n in xml.getchildren(): for n in xml.getchildren():
if n.tag == "emphasis": if n.tag == "emphasis":
@ -143,7 +143,7 @@ class DoxygenProcess(object):
s += " - " + self.__process_element(n) s += " - " + self.__process_element(n)
if n.tag == "para": if n.tag == "para":
p = self.__process_element(n) p = self.__process_element(n)
if re.search('\S', p): if re.search(r'\S', p):
s += p + "\n" s += p + "\n"
if n.tag == "ref": if n.tag == "ref":
s += n.text if n.text else "" s += n.text if n.text else ""
@ -168,7 +168,7 @@ class DoxygenProcess(object):
if n.tag == "htmlonly": if n.tag == "htmlonly":
s += "" s += ""
if n.tail: if n.tail:
if re.search('\S', n.tail): if re.search(r'\S', n.tail):
s += n.tail s += n.tail
if n.tag.startswith("param"): if n.tag.startswith("param"):
pass # parameters are handled separately in DoxyFunction::from_memberdef() pass # parameters are handled separately in DoxyFunction::from_memberdef()
@ -319,6 +319,8 @@ class DoxyFunction(DoxyElement):
d = normalize_text(d) d = normalize_text(d)
e = DoxyFunction(name, d) e = DoxyFunction(name, d)
if (xml.get("prot") == "private"):
e.extra = "(skip)"
e.add_brief(xml.find("briefdescription")) e.add_brief(xml.find("briefdescription"))
e.add_detail(xml.find("detaileddescription")) e.add_detail(xml.find("detaileddescription"))
for p in xml.xpath(".//detaileddescription/*/parameterlist[@kind='param']/parameteritem"): for p in xml.xpath(".//detaileddescription/*/parameterlist[@kind='param']/parameteritem"):

View file

@ -69,6 +69,7 @@ if build_doc
meson.current_source_dir()/'..'/'README.rst', meson.current_source_dir()/'..'/'README.rst',
meson.current_source_dir()/'..'/'NEWS.rst', meson.current_source_dir()/'..'/'NEWS.rst',
) )
sphinx_files += scripts_doc_files
subdir('rst') subdir('rst')
sphinx_conf_data = configuration_data() sphinx_conf_data = configuration_data()
@ -98,7 +99,27 @@ if build_doc
depends: [doxyxml_wp], depends: [doxyxml_wp],
output: 'html', output: 'html',
install: true, install: true,
install_dir: get_option('datadir') / 'doc' / 'wireplumber', install_dir: wireplumber_doc_dir,
build_by_default: true,
)
# Generate man pages directory with sphinx
custom_target('manpages',
command: [sphinx_p,
'-q', # quiet
'-E', # rebuild from scratch
'-b', 'man', # man page builder
'-d', '@PRIVATE_DIR@', # doctrees dir
'-c', '@OUTDIR@', # conf.py dir
'@CURRENT_SOURCE_DIR@/rst', # source dir
'@OUTDIR@', # output directory
],
depend_files: [
sphinx_conf, sphinx_files,
],
output: ['wpctl.1'],
install: true,
install_dir: get_option('mandir') / 'man1',
build_by_default: true, build_by_default: true,
) )
endif endif
@ -140,7 +161,7 @@ if build_gir
dependencies: [wp_dep, dummy_dep], dependencies: [wp_dep, dummy_dep],
namespace: 'Wp', namespace: 'Wp',
nsversion: wireplumber_api_version, nsversion: wireplumber_api_version,
export_packages: 'wireplumber-0.4', export_packages: 'wireplumber-' + wireplumber_api_version,
header: 'wp/wp.h', header: 'wp/wp.h',
sources: [wpenums_h, wp_gtkdoc_h, wp_lib_headers], sources: [wpenums_h, wp_gtkdoc_h, wp_lib_headers],
include_directories: [wpenums_include_dir], include_directories: [wpenums_include_dir],

View file

@ -1,24 +0,0 @@
.. _endpoint_api:
PipeWire Endpoint
=================
.. graphviz::
:align: center
digraph inheritance {
rankdir=LR;
GObject -> WpObject;
WpObject -> WpProxy;
WpProxy -> WpGlobalProxy;
WpGlobalProxy -> WpEndpoint;
GInterface -> WpPipewireObject;
WpPipewireObject -> WpEndpoint;
WpEndpoint -> WpImplEndpoint;
}
.. doxygenstruct:: WpEndpoint
.. doxygenstruct:: WpImplEndpoint
.. doxygengroup:: wpendpoint
:content-only:

View file

@ -1,34 +0,0 @@
.. _configuration:
Configuration
=============
WirePlumber is a heavily modular daemon. By itself, it doesn't do anything
except load the configured modules. All the rest of the logic is implemented
inside those modules.
Modular design ensures that it is possible to swap the implementation of
specific functionality without having to re-implement the rest of it, allowing
flexibility on target-sensitive parts, such as policy management and
making use of non-standard hardware.
At startup, WirePlumber first reads its **main** configuration file.
This file configures the operation context (properties of the daemon,
modules to be loaded, etc). This file may also specify additional, secondary
configuration files which will be loaded as well at the time of parsing the
main file.
All files and modules are specified relative to their standard search locations,
which are documented later in this chapter.
.. toctree::
:maxdepth: 1
configuration/locations.rst
configuration/main.rst
configuration/config_lua.rst
configuration/multi_instance.rst
configuration/alsa.rst
configuration/bluetooth.rst
configuration/policy.rst
configuration/access.rst

View file

@ -1,63 +0,0 @@
.. _config_access:
Access configuration
====================
main.lua.d/50-default-access-config.lua
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Using a similar format as the :ref:`ALSA monitor <config_alsa>`, this
configuration file is charged to configure the client objects created by
PipeWire.
* *default_access.properties*
A Lua object that contains generic client configuration properties in the
for of key pairs.
Example:
.. code-block:: lua
default_access.properties = {
["enable-flatpak-portal"] = true,
}
The above example sets to ``true`` the ``enable-flatpak-portal`` property.
The list of valid properties are:
.. code-block:: lua
["enable-flatpak-portal"] = true,
Whether to enable the flatpak portal or not.
* *default_access.rules*
This is a Lua array that can contain objects with rules for a client object.
Those Lua objects have 2 properties. Similar to the
:ref:`ALSA configuration <config_alsa>`, the first property is ``matches``,
which allow users to define rules to match a client object.
The second property is ``default_permissions``, and it is used to set
permissions on the matched client object.
Example:
.. code-block:: lua
{
matches = {
{
{ "pipewire.access", "=", "flatpak" },
},
},
default_permissions = "rx",
}
This grants read and execute permissions to all clients that have the
``pipewire.access`` property set to ``flatpak``.
Possible permissions are any combination of ``r``, ``w`` and ``x`` for read,
write and execute; or ``all`` for all kind of permissions.

View file

@ -1,478 +0,0 @@
.. _config_alsa:
ALSA configuration
==================
Modifying the default configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ALSA devices are created and managed by the session manager with the *alsa.lua*
monitor script. In the default configuration, this script is loaded by
``main.lua.d/30-alsa-monitor.lua``, which also specifies an ``alsa_monitor``
global table that can be filled in with properties and rules in subsequent
config files. By default, these are filled in ``main.lua.d/50-alsa-config.lua``.
The ``alsa_monitor`` global table has 2 sub-tables:
* *alsa_monitor.properties*
This is a simple Lua table that has key value pairs used as properties.
Example:
.. code-block:: lua
alsa_monitor.properties = {
["alsa.jack-device"] = false,
["alsa.reserve"] = true,
}
The above example will configure the ALSA monitor to not enable the JACK
device, and do ALSA device reservation using the mentioned DBus interface.
A list of valid properties are:
.. code-block:: lua
["alsa.jack-device"] = false
Creates a JACK device if set to ``true``. This is not enabled by default because
it requires that the PipeWire JACK replacement libraries are not used by the
session manager, in order to be able to connect to the real JACK server.
.. code-block:: lua
["alsa.reserve"] = true
Reserve ALSA devices via *org.freedesktop.ReserveDevice1* on D-Bus.
.. code-block:: lua
["alsa.reserve.priority"] = -20
The used ALSA device reservation priority.
.. code-block:: lua
["alsa.reserve.application-name"] = "WirePlumber"
The used ALSA device reservation application name.
* *alsa_monitor.rules*
This is a Lua array that can contain objects with rules for a device or node.
Those objects have 2 properties. The first one is ``matches``, which allow
users to define rules to match a device or node. The second property is
``apply_properties``, and it is used to apply properties on the matched object.
Example:
.. code-block:: lua
alsa_monitor.rules = {
matches = {
{
{ "device.name", "matches", "alsa_card.*" },
},
},
apply_properties = {
["api.alsa.use-acp"] = true,
}
}
This sets the API ALSA use ACP property to all devices with a name that
matches the ``alsa_card.*`` pattern.
The ``matches`` section is an array of arrays. On the first level, the rules
are ORed together, so any rule match is going to apply the properties. On
the second level, the rules are merged with AND, so they must all match.
Example:
.. code-block:: lua
matches = {
{
{ "node.name", "matches", "alsa_input.*" },
{ "alsa.driver_name", "equals", "snd_hda_intel" },
},
{
{ "node.name", "matches", "alsa_output.*" },
},
},
This is equivalent to the following logic, in pseudocode:
.. code-block::
if ("node.name" MATCHES "alsa_input.*" AND "alsa.driver_name" EQUALS "snd_hda_intel" )
OR
("node.name" MATCHES "alsa_output.*")
then
... apply the properties ...
end
As you can notice, the individual rules are themselves also lua arrays. The
first element is a property name (ex "node.name"), the second element is a
verb and the third element is an expected value, which depends on the verb.
Internally, this uses the ``Constraint`` API, which is documented in the
:ref:`Object Interet API <lua_object_interest_api>` section. All the verbs
that you can use on ``Constraint`` are also allowed here.
.. note::
When using the "matches" verb, the values are not complete regular expressions.
They are wildcard patterns, which means that '*' matches an arbitrary,
possibly empty, string and '?' matches an arbitrary character.
All the possible properties that you can apply to devices and nodes of the
ALSA monitor are described in the sections below.
Device properties
^^^^^^^^^^^^^^^^^
PipeWire devices correspond to the ALSA cards.
The following properties can be configured on devices created by the monitor:
.. code-block:: lua
["api.alsa.use-acp"] = true
Use the ACP (alsa card profile) code to manage the device. This will probe the
device and configure the available profiles, ports and mixer settings. The
code to do this is taken directly from PulseAudio and provides devices that
look and feel exactly like the PulseAudio devices.
.. code-block:: lua
["api.alsa.use-ucm"] = true
By default, the UCM configuration is used when it is available for your device.
With this option you can disable this and use the ACP profiles instead.
.. code-block:: lua
["api.alsa.soft-mixer"] = false
Setting this option to true will disable the hardware mixer for volume control
and mute. All volume handling will then use software volume and mute, leaving
the hardware mixer untouched. The hardware mixer will still be used to mute
unused audio paths in the device.
.. code-block:: lua
["api.alsa.ignore-dB"] = false
Setting this option to true will ignore the decibel setting configured by the
driver. Use this when the driver reports wrong settings.
.. code-block:: lua
["device.profile-set"] = "profileset-name"
This option can be used to select a custom profile set name for the device.
Usually this is configured in Udev rules but it can also be specified here.
.. code-block:: lua
["device.profile"] = "default profile name"
The default active profile name.
.. code-block:: lua
["api.acp.auto-profile"] = false
Automatically select the best profile for the device. Normally this option is
disabled because the session manager will manage the profile of the device.
The session manager can save and load previously selected profiles. Enable
this if your session manager does not handle this feature.
.. code-block:: lua
["api.acp.auto-port"] = false
Automatically select the highest priority port that is available. This is by
default disabled because the session manager handles the task of selecting and
restoring ports. It can, for example, restore previously saved volumes. Enable
this here when the session manager does not handle port restore.
.. code-block:: lua
["api.acp.probe-rate"] = 48000
Sets the samplerate used for probing the ALSA devices and collecting the profiles
and ports.
.. code-block:: lua
["api.acp.pro-channels"] = 64
Sets the number of channels to use when probing the Pro Audio profile. Normally,
the maximum amount of channels will be used but with this setting this can be
reduced, which can make it possible to use other samplerates on some devices.
Some of the other properties that might be configured on devices:
.. code-block:: lua
["device.nick"] = "My Device",
["device.description"] = "My Device"
``device.description`` will show up in most apps when a device name is shown.
Node Properties
^^^^^^^^^^^^^^^
Nodes are sinks or sources in the PipeWire graph. They correspond to the ALSA
devices. In addition to the generic stream node configuration options, there are
some alsa specific options as well:
.. code-block:: lua
["priority.driver"] = 2000
This configures the node driver priority. Nodes with higher priority will be
used as a driver in the graph. Other nodes with lower priority will have to
resample to the driver node when they are joined in the same graph. The default
value is set based on some heuristics.
.. code-block:: lua
["priority.session"] = 1200
This configures the priority of the node when selecting a default node.
Higher priority nodes will be more likely candidates as a default node.
.. note::
By default, sources have a ``priority.session`` value around 1600-2000 and
sinks have a value around 600-1000. If you are increasing the priority of a
sink, it is **not advised** to use a value higher than 1500, as it may cause
a sink's monitor to be selected as a default source.
.. code-block:: lua
["node.pause-on-idle"] = false
Pause-on-idle will stop the node when nothing is linked to it anymore.
This is by default false because some devices cause a pop when they are
opened/closed. The node will, normally, pause and suspend after a timeout
(see suspend-node.lua).
.. code-block:: lua
["session.suspend-timeout-seconds"] = 5 -- 0 disables suspend
This option configures a different suspend timeout on the node.
By default this is 5 seconds. For some devices (HiFi amplifiers, for example)
it might make sense to set a higher timeout because they might require some
time to restart after being idle.
A value of 0 disables suspend for a node and will leave the ALSA device busy.
The device can then manually be suspended with ``pactl suspend-sink|source``.
**The following properties can be used to configure the format used by the
ALSA device:**
.. code-block:: lua
["audio.format"] = "S16LE"
By default, PipeWire will use a 32 bits sample format but a different format
can be set here.
The Audio rate of a device can be set here:
.. code-block:: lua
["audio.rate"] = 44100
By default, the ALSA device will be configured with the same samplerate as the
global graph. If this is not supported, or a custom values is set here,
resampling will be used to match the graph rate.
.. code-block:: lua
["audio.channels"] = 2
["audio.position"] = "FL,FR"
By default the channels and their position are determined by the selected
Device profile. You can override this setting here and optionally swap or
reconfigure the channel positions.
.. code-block:: lua
["api.alsa.use-chmap"] = false
Use the channel map as reported by the driver. This is disabled by default
because it is often wrong and the ACP code handles this better.
.. code-block:: lua
["api.alsa.disable-mmap"] = true
PipeWire will by default access the memory of the device using mmap.
This can be disabled and force the usage of the slower read and write access
modes in case the mmap support of the device is not working properly.
.. code-block:: lua
["channelmix.normalize"] = true
Makes sure that during such mixing & resampling original 0 dB level is
preserved, so nothing sounds wildly quieter/louder.
.. code-block:: lua
["channelmix.mix-lfe"] = true
Creates "center" channel for X.0 recordings from front stereo on X.1 setups and
pushes some low-frequency/bass from "center" from X.1 recordings into front
stereo on X.0 setups.
.. code-block:: lua
["monitor.channel-volumes"] = false
By default, the volume of the sink/source does not influence the volume on the
monitor ports. Set this option to true to change this. PulseAudio has
inconsistent behaviour regarding this option, it applies channel-volumes only
when the sink/source is using software volumes.
ALSA buffer properties
^^^^^^^^^^^^^^^^^^^^^^
PipeWire uses a timer to consume and produce samples to/from ALSA devices.
After every timeout, it queries the device hardware pointers of the device and
uses this information to set a new timeout. See also this example program.
By default, PipeWire handles ALSA batch devices differently from non-batch
devices. Batch devices only get their hardware pointers updated after each
hardware interrupt. Non-batch devices get updates independent of the interrupt.
This means that for batch devices we need to set the interrupt at a sufficiently
high frequency (at the cost of CPU usage) while for non-batch devices we want to
set the interrupt frequency as low as possible (to save CPU).
For batch devices we also need to take the extra buffering into account caused
by the delayed updates of the hardware pointers.
Most USB devices are batch devices and will be handled as such by PipeWire by
default.
There are 2 tunable parameters to control the buffering and timeouts in a
device
.. code-block:: lua
["api.alsa.period-size"] = 1024
This sets the device interrupt to every period-size samples for non-batch
devices and to half of this for batch devices. For batch devices, the other
half of the period-size is used as extra buffering to compensate for the delayed
update. So, for batch devices, there is an additional period-size/2 delay.
It makes sense to lower the period-size for batch devices to reduce this delay.
.. code-block:: lua
["api.alsa.headroom"] = 0
This adds extra delay between the hardware pointers and software pointers.
In most cases this can be set to 0. For very bad devices or emulated devices
(like in a VM) it might be necessary to increase the headroom value.
In summary, this is the overview of buffering and timings:
============== ========================================== =========
Property Batch Non-Batch
============== ========================================== =========
IRQ Frequency api.alsa.period-size/2 api.alsa.period-size
Extra Delay api.alsa.headroom + api.alsa.period-size/2 api.alsa.headroom
============== ========================================== =========
It is possible to disable the batch device tweaks with:
.. code-block:: lua
["api.alsa.disable-batch"] = true
It removes the extra delay added of period-size/2 if the device can support this.
For batch devices it is also a good idea to lower the period-size
(and increase the IRQ frequency) to get smaller batch updates and lower latency.
ALSA extra latency properties
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Extra internal delay in the DAC and ADC converters of the device itself can be
set with the ``latency.internal.*`` properties:
.. code-block:: lua
["latency.internal.rate"] = 256
["latency.internal.ns"] = 0
You can configure a latency in samples (relative to rate with
``latency.internal.rate``) or in nanoseconds (``latency.internal.ns``).
This value will be added to the total reported latency by the node of the device.
You can use a tool like ``jack_iodelay`` to get the number of samples of
internal latency of your device.
This property is also adjustable at runtime with the ``ProcessLatency`` param.
You will need to find the id of the Node you want to change. For example:
Query the current internal latency of an ALSA node with id 58:
.. code-block:: console
$ pw-cli e 58 ProcessLatency
Object: size 80, type Spa:Pod:Object:Param:ProcessLatency (262156), id Spa:Enum:ParamId:ProcessLatency (16)
Prop: key Spa:Pod:Object:Param:ProcessLatency:quantum (1), flags 00000000
Float 0.000000
Prop: key Spa:Pod:Object:Param:ProcessLatency:rate (2), flags 00000000
Int 0
Prop: key Spa:Pod:Object:Param:ProcessLatency:ns (3), flags 00000000
Long 0
Set the internal latency to 256 samples:
.. code-block:: console
$ pw-cli s 58 ProcessLatency '{ rate = 256 }'
Object: size 32, type Spa:Pod:Object:Param:ProcessLatency (262156), id Spa:Enum:ParamId:ProcessLatency (16)
Prop: key Spa:Pod:Object:Param:ProcessLatency:rate (2), flags 00000000
Int 256
remote 0 node 58 changed
remote 0 port 70 changed
remote 0 port 72 changed
remote 0 port 74 changed
remote 0 port 76 changed
Startup tweaks
^^^^^^^^^^^^^^
Some devices need some time before they can report accurate hardware pointer
positions. In those cases, an extra start delay can be added that is used to
compensate for this startup delay:
.. code-block:: lua
["api.alsa.start-delay"] = 0
It is unsure when this tunable should be used.
IEC958 (S/PDIF) passthrough
^^^^^^^^^^^^^^^^^^^^^^^^^^^
S/PDIF passthrough will only be enabled when the accepted codecs are configured
on the ALSA device.
This can be done in 3 different ways:
1. Use pavucontrol and toggle the codecs in the output advanced section
2. Modify the ``["iec958.codecs"] = "[ PCM DTS AC3 MPEG MPEG2-AAC EAC3 TrueHD DTS-HD ]"``
node property to something.
3. Use ``pw-cli s <node-id> Props '{ iec958Codecs : [ PCM ] }'`` to modify
the codecs at runtime.

View file

@ -1,160 +0,0 @@
.. _config_bluetooth:
Bluetooth configuration
=======================
Using the same format as the :ref:`ALSA monitor <config_alsa>`, the
configuration file ``bluetooth.lua.d/50-bluez-config.lua`` is charged
to configure the Bluetooth devices and nodes created by WirePlumber.
* *bluez_monitor.properties*
A Lua object that contains generic client configuration properties in the
for of key pairs.
Example:
.. code-block:: lua
bluez_monitor.properties = {
["bluez5.enable-msbc"] = true,
}
This example will enable the MSBC codec in connected Bluetooth devices that
support it.
The list of valid properties are:
.. code-block:: lua
["bluez5.enable-sbc-xq"] = true
Enables the SBC-XQ codec in connected Blueooth devices that support it
.. code-block:: lua
["bluez5.enable-msbc"] = true
Enables the MSBC codec in connected Blueooth devices that support it
.. code-block:: lua
["bluez5.enable-hw-volume"] = true
Enables hardware volume controls in Bluetooth devices that support it
.. code-block:: lua
["bluez5.headset-roles"] = "[ hsp_hs hsp_ag hfp_hf hfp_ag ]"
Enabled headset roles (default: [ hsp_hs hfp_ag ]), this property only applies
to native backend. Currently some headsets (Sony WH-1000XM3) are not working
with both hsp_ag and hfp_ag enabled, disable either hsp_ag or hfp_ag to work
around it.
Supported headset roles: ``hsp_hs`` (HSP Headset), ``hsp_ag`` (HSP Audio Gateway),
``hfp_hf`` (HFP Hands-Free) and ``hfp_ag`` (HFP Audio Gateway)
.. code-block:: lua
["bluez5.codecs"] = "[ sbc sbc_xq aac ]"
Enables ``sbc``, ``sbc_zq`` and ``aac`` A2DP codecs.
Supported codecs: ``sbc``, ``sbc_xq``, ``aac``, ``ldac``, ``aptx``,
``aptx_hd``, ``aptx_ll``, ``aptx_ll_duplex``, ``faststream``, ``faststream_duplex``.
All codecs are supported by default.
.. code-block:: lua
["bluez5.hfphsp-backend"] = "native"
HFP/HSP backend (default: native). Available values: ``any``, ``none``,
``hsphfpd``, ``ofono`` or ``native``.
.. code-block:: lua
["bluez5.default.rate"] = 48000
The bluetooth default audio rate.
.. code-block:: lua
["bluez5.default.channels"] = 2
The bluetooth default number of channels.
* *bluez_monitor.rules*
Like in the :ref:`ALSA configuration <config_alsa>`, this is a Lua array that
can contain objects with rules for a Bluetooth device or node.
Those objects have 2 properties. The first one is ``matches``, which allows
users to define rules to match a Bluetooth device or node.
The second property is ``apply_properties``, and it is used to apply
properties on the matched Bluetooth device or node.
Example:
.. code-block:: lua
{
matches = {
{
{ "device.name", "matches", "bluez_card.*" },
},
},
apply_properties = {
["bluez5.auto-connect"] = "[ hfp_hf hsp_hs a2dp_sink ]"
}
}
This will set the auto-connect property to ``hfp_hf``, ``hsp_hs`` and ``a2dp_sink``
on bluetooth devices whose name matches the ``bluez_card.*`` pattern.
A list of valid properties are:
.. code-block:: lua
["bluez5.auto-connect"] = "[ hfp_hf hsp_hs a2dp_sink ]"
Auto-connect device profiles on start up or when only partial profiles have
connected. Disabled by default if the property is not specified.
Supported values are: ``hfp_hf``, ``hsp_hs``, ``a2dp_sink``, ``hfp_ag``,
``hsp_ag`` and ``a2dp_source``.
.. code-block:: lua
["bluez5.hw-volume"] = "[ hfp_ag hsp_ag a2dp_source ]"
Hardware volume controls (default: ``hfp_ag``, ``hsp_ag``, and ``a2dp_source``)
Supported values are: ``hfp_hf``, ``hsp_hs``, ``a2dp_sink``, ``hfp_ag``,
``hsp_ag`` and ``a2dp_source``.
.. code-block:: lua
["bluez5.a2dp.ldac.quality"] = "auto"
LDAC encoding quality.
Available values: ``auto`` (Adaptive Bitrate, default),
``hq`` (High Quality, 990/909kbps), ``sq`` (Standard Quality, 660/606kbps) and
``mq`` (Mobile use Quality, 330/303kbps).
.. code-block:: lua
["bluez5.a2dp.aac.bitratemode"] = 0
AAC variable bitrate mode.
Available values: 0 (cbr, default), 1-5 (quality level).
.. code-block:: lua
["device.profile"] = "a2dp-sink"
Profile connected first.
Available values: ``a2dp-sink`` (default) or ``headset-head-unit``.

View file

@ -1,185 +0,0 @@
.. _config_lua:
Lua Configuration Files
=======================
Lua configuration files are similar to the main configuration file, but they
leverage the Lua language to enable advanced configuration of module arguments
and allow split-file configuration.
There is only one global section that WirePlumber reads from these files: the
**components** table. This table is equivalent to the **context.components**
object on the main configuration file. Its purpose is to list components that
WirePlumber should load on startup.
Every line on the **components** table should be another table that contains
information about the loaded component::
{
"component-name",
type = "component-type",
args = { additional arguments },
optional = true/false,
}
* **component-name**: Should be the name of the component to load
(ex. *"libwireplumber-module-mixer-api"*).
* **component-type**: Should be the type of the component.
Valid component types include:
* ``module``: A WirePlumber shared object module.
* ``script/lua``: A WirePlumber Lua script.
* ``pw_module``: A PipeWire shared object module (loaded on WirePlumber,
not on the PipeWire daemon).
* **args**: Is an optional table that can contain additional arguments to be
passed down to the module or script. Scripts can retrieve these arguments
by declaring a line that reads ``local config = ...`` at the top of the script.
Modules receive these arguments as a GVariant ``a{sv}`` table.
* **optional**: Is a boolean value that specifies whether loading of this
component is optional. The default value is ``false``. If set to ``true``,
then WirePlumber will not fail loading if the component is not found.
Split-File Configuration
------------------------
When a Lua configuration file is loaded, the engine also looks for additional
files in a directory that has the same name as the configuration file and a
``.d`` suffix.
A Lua directory can contain a list of Lua configuration files. Those files are
loaded alphabetically by filename so that user can control the order in which
Lua configuration files are executed.
Lua files in the directory are always loaded *after* the configuration file
that is out of the directory. However, it is perfectly valid to not have any
configuration file out of the directory.
Example hierarchy with files both in and out of the directory
(in the order of loading)::
config.lua
config.lua.d/00-functions.lua
config.lua.d/01-alsa.lua
config.lua.d/10-policy.lua
config.lua.d/99-misc.lua
Example hierarchy with files only in the directory
(in the order of loading)::
config.lua.d/00-functions.lua
config.lua.d/01-alsa.lua
config.lua.d/10-policy.lua
config.lua.d/99-misc.lua
Example of a file using alsa_monitor.rules in a split-file configuration:
.. code-block:: lua
table.insert (alsa_monitor.rules, {
matches = {
{
{ "device.name", "matches", "alsa_card.*" },
},
},
apply_properties = {
["api.alsa.use-acp"] = true,
}
})
Multi-Path Merging
------------------
WirePlumber looks for configuration files in 3 different places, as described
in the :ref:`Locations of files <config_locations>` section. When a split-file
configuration scheme is used, files will be merged from these different locations.
For example, consider these files exist on the filesystem::
/usr/share/wireplumber/config.lua.d/00-functions.lua
/usr/share/wireplumber/config.lua.d/01-alsa.lua
/usr/share/wireplumber/config.lua.d/10-policy.lua
/usr/share/wireplumber/config.lua.d/99-misc.lua
...
/etc/wireplumber/config.lua.d/01-alsa.lua
...
/home/user/.config/wireplumber/config.lua.d/11-policy-extras.lua
In this case, loading ``config.lua`` will result in loading these files
(in this order)::
/usr/share/wireplumber/config.lua.d/00-functions.lua
/etc/wireplumber/config.lua.d/01-alsa.lua
/usr/share/wireplumber/config.lua.d/10-policy.lua
/home/user/.config/wireplumber/config.lua.d/11-policy-extras.lua
/usr/share/wireplumber/config.lua.d/99-misc.lua
This is useful to keep the default configuration in /usr and override it
with host-specific and user-specific parts in /etc and /home respectively.
As an exception to this rule, if the configuration path is overridden with
the ``WIREPLUMBER_CONFIG_DIR`` environment variable, then configuration files
will only be loaded from this path and no merging will happen.
Functions
---------
Because of the nature of these files (they are scripts!), it is more convenient
to manage the **components** table through functions. In the default
configuration files shipped with WirePlumber, there is a file called
``00-functions.lua`` that defines some helper functions to load components.
When loading components through these functions, *duplicate calls are ignored*,
so it is possible to call a function to load a specific component multiple times
and it will only be loaded once.
.. function:: load_module(module, args)
Loads a WirePlumber shared object module.
:param string module: the module name, without the "libwireplumber-module-"
prefix (ex specify "mixer-api" to load "libwireplumber-module-mixer-api")
:param table args: optional module arguments table
.. function:: load_optional_module(module, args)
Loads an optional WirePlumber shared object module. Optional in this case
means that if the module is not present on the filesystem, it will be ignored.
:param string module: the module name, without the "libwireplumber-module-"
prefix (ex specify "mixer-api" to load "libwireplumber-module-mixer-api")
:param table args: optional module arguments table
.. function:: load_pw_module(module)
Loads a PipeWire shared object module
:param string module: the module name, without the "libpipewire-module-"
prefix (ex specify "adapter" to load "libpipewire-module-adapter")
.. function:: load_script(script, args)
Loads a Lua script (a functionality script, not a lua configuration file)
:param string script: the script's filename (ex. "policy-node.lua")
:param table args: optional script arguments table
.. function:: load_monitor(monitor, args)
Loads a Lua monitor script. Monitors are scripts found in the ``monitors/``
directory and their purpose is to monitor and load devices.
:param string monitor: the scripts's name without the directory or the .lua
extension (ex. "alsa" will load "monitors/alsa.lua")
:param table args: optional script arguments table
.. function:: load_access(access, args)
Loads a Lua access script. Access scripts are ones found in the ``access/``
directory and their purpose is to manage application permissions.
:param string access: the scripts's name without the directory or the .lua
extension (ex. "flatpak" will load "access/access-flatpak.lua")
:param table args: optional script arguments table

View file

@ -1,94 +0,0 @@
.. _config_locations:
Locations of files
==================
Location of configuration files
-------------------------------
WirePlumber's default locations of its configuration files are determined at
compile time by the build system. Typically, those end up being
``$XDG_CONFIG_DIR/wireplumber``, ``/etc/wireplumber``, and
``/usr/share/wireplumber``, in that order of priority.
In more detail, the latter two are controlled by the ``--sysconfdir`` and ``--datadir``
meson options. When those are set to an absolute path, such as ``/etc``, the
location of the configuration files is set to be ``$sysconfdir/wireplumber``.
When set to a relative path, such as ``etc``, then the installation prefix (``--prefix``)
is prepended to the path: ``$prefix/$sysconfdir/wireplumber``
The three locations are intended for custom user configuration,
host-specific configuration and distribution-provided configuration,
respectively. At runtime, WirePlumber will search the directories
for the highest-priority directory to contain the needed configuration file.
This allows a user or system administrator to easily override the distribution
provided configuration files by placing an equally named file in the respective
directory.
It is also possible to override the configuration directory by setting the
``WIREPLUMBER_CONFIG_DIR`` environment variable::
WIREPLUMBER_CONFIG_DIR=src/config wireplumber
If ``WIREPLUMBER_CONFIG_DIR`` is set, the default locations are ignored and
configuration files are *only* looked up in this directory.
Location of scripts
-------------------
WirePlumber's default locations of its scripts are the same ones as for the
configuration files, but with the ``scripts`` directory appended.
Typically, these end up being ``$XDG_CONFIG_DIR/wireplumber/scripts``,
``/etc/wireplumber/scripts``, and ``/usr/share/wireplumber/scripts``,
in that order of priority.
The three locations are intended for custom user scripts,
host-specific scripts and distribution-provided scripts, respectively.
At runtime, WirePlumber will search the directories for the highest-priority
directory to contain the needed script.
It is also possible to override the scripts directory by setting the
``WIREPLUMBER_DATA_DIR`` environment variable::
WIREPLUMBER_DATA_DIR=src wireplumber
The "data" directory is a somewhat more generic path that may be used for
other kinds of data files in the future. For scripts, WirePlumber still expects
to find a ``scripts`` subdirectory in this "data" directory, so in the above
example the scripts would be in ``src/scripts``.
If ``WIREPLUMBER_DATA_DIR`` is set, the default locations are ignored and
scripts are *only* looked up in this directory.
Location of modules
-------------------
WirePlumber modules
^^^^^^^^^^^^^^^^^^^
Like with configuration files, WirePlumber's default location of its modules is
determined at compile time by the build system. Typically, it ends up being
``/usr/lib/wireplumber-0.4`` (or ``/usr/lib/<arch-triplet>/wireplumber-0.4`` on
multiarch systems)
In more detail, this is controlled by the ``--libdir`` meson option. When
this is set to an absolute path, such as ``/lib``, the location of the
modules is set to be ``$libdir/wireplumber-$abi_version``. When this is set
to a relative path, such as ``lib``, then the installation prefix (``--prefix``)
is prepended to the path: ``$prefix/$libdir/wireplumber-$abi_version``.
It is possible to override this directory at runtime by setting the
``WIREPLUMBER_MODULE_DIR`` environment variable::
WIREPLUMBER_MODULE_DIR=build/modules wireplumber
PipeWire and SPA modules
^^^^^^^^^^^^^^^^^^^^^^^^
PipeWire and SPA modules are not loaded from the same location as WirePlumber's
modules. They are loaded from the location that PipeWire loads them.
It is also possible to override these locations by using environment variables:
``SPA_PLUGIN_DIR`` and ``PIPEWIRE_MODULE_DIR``. For more details, refer to
PipeWire's documentation.

View file

@ -1,126 +0,0 @@
.. _config_main:
Main configuration file
=======================
The main configuration file is by default called ``wireplumber.conf``. This can
be changed on the command line by passing the ``--config-file`` or ``-c`` option::
wireplumber --config-file=bluetooth.conf
The ``--config-file`` option is useful to run multiple instances of wireplumber
that do separate tasks each. For more information on this subject, see the
:ref:`Multiple Instances <config_multi_instance>` section.
The format of this configuration file is the variant of JSON that is also
used in PipeWire configuration files. Note that this is subject to change
in the future.
All sections are essentially JSON objects. Lines starting with *#* are treated
as comments and ignored. The list of all possible section JSON objects are:
* *context.properties*
Used to define properties to configure the PipeWire context and some modules.
Example::
context.properties = {
application.name = WirePlumber
log.level = 2
}
This sets the daemon's name to *WirePlumber* and the log level to *2*, which
only displays errors and warnings. See the
:ref:`Debug Logging <logging>` section for more details.
* *context.spa-libs*
Used to find spa factory names. It maps a spa factory name regular expression
to a library name that should contain that factory. The object property names
are the regular expression, and the object property values are the actual
library name::
<factory-name regex> = <library-name>
Example::
context.spa-libs = {
api.alsa.* = alsa/libspa-alsa
audio.convert.* = audioconvert/libspa-audioconvert
}
In this example, we instruct wireplumber to only any *api.alsa.** factory name
from the *libspa-alsa* library, and also any *audio.convert.** factory name
from the *libspa-audioconvert* library.
* *context.modules*
Used to load PipeWire modules. This does not affect the PipeWire daemon by any
means. It exists simply to allow loading *libpipewire* modules in the PipeWire
core that runs inside WirePlumber. This is usually useful to load PipeWire
protocol extensions, so that you can export custom objects to PipeWire and
other clients.
Users can also pass key-value pairs if the specific module has arguments, and
a combination of 2 flags: ``ifexists`` flag is given, the module is ignored when
not found; if ``nofail`` is given, module initialization failures are ignored::
{
name = <module-name>
[ args = { <key> = <value> ... } ]
[ flags = [ [ ifexists ] [ nofail ] ]
}
Example::
context.modules = [
{ name = libpipewire-module-adapter }
{
name = libpipewire-module-metadata,
flags = [ ifexists ]
}
]
The above example loads both PipeWire adapter and metadata modules. The
metadata module will be ignored if not found because of its ``ifexists`` flag.
* *context.components*
Used to load WirePlumber components. Components can be either WirePlumber
modules written in C, WirePlumber scripts or other configuration
files::
{ name = <component-name>, type = <component-type> }
Valid component types include:
* ``module``: A WirePlumber shared object module
* ``script/lua``: A WirePlumber Lua script
(requires ``libwireplumber-module-lua-scripting``)
* ``config/lua``: A WirePlumber Lua configuration file
(requires ``libwireplumber-module-lua-scripting``)
Example::
context.components = [
{ name = libwireplumber-module-lua-scripting, type = module }
{ name = main.lua, type = config/lua }
]
This will load the WirePlumber lua-scripting module, dynamically, and then
it will also load any components specified in the ``main.lua`` file.
.. note::
When loading lua configuration files, WirePlumber will also look for
additional files in the directory suffixed with ``.d`` and will load
all of them as well. For example, loading ``example.lua`` will also load
any ``.lua`` files under ``example.lua.d/``. In addition, the presence of the
main file is optional, so it is valid to specify ``example.lua`` in the
component name, while ``example.lua`` doesn't exist, but ``example.lua.d/``
exists instead and has ``.lua`` files to load.
For more information about lua configuration files, see the
:ref:`Lua configuration files <config_lua>` section.

View file

@ -1,11 +0,0 @@
# you need to add here any files you add to the toc directory as well
sphinx_files += files(
'locations.rst',
'main.rst',
'config_lua.rst',
'multi_instance.rst',
'alsa.rst',
'bluetooth.rst',
'policy.rst',
'access.rst',
)

View file

@ -1,45 +0,0 @@
.. _config_multi_instance:
Running multiple instances
==========================
WirePlumber has the ability to run either as a single instance daemon or as
multiple instances, meaning that there can be multiple processes, each one
doing a different task.
In the default configuration, both setups are supported. The default is to run
in single-instance mode.
In single-instance mode, WirePlumber reads ``wireplumber.conf``, which is the
default configuration file, and from there it loads ``main.lua``, ``policy.lua``
and ``bluetooth.lua``, which are lua configuration files (deployed as directories)
that enable all the relevant functionality.
In multi-instance mode, WirePlumber is meant to be started with the
``--config-file`` command line option 3 times:
.. code-block:: console
$ wireplumber --config-file=main.conf
$ wireplumber --config-file=policy.conf
$ wireplumber --config-file=bluetooth.conf
That loads one process which reads ``main.conf``, which then loads ``main.lua``
and enables core functionality. Then another process that reads ``policy.conf``,
which then loads ``policy.lua`` and enables policy functionality... and so on.
To make this easier to work with, a template systemd unit is provided, which is
meant to be started with the name of the main configuration file as a
template argument:
.. code-block:: console
$ systemctl --user disable wireplumber # disable the single instance
$ systemctl --user enable wireplumber@main
$ systemctl --user enable wireplumber@policy
$ systemctl --user enable wireplumber@bluetooth
It is obviously possible to start as many instances as desired, with manually
crafted configuration files, as long as it is ensured that these instances
serve a different purpose and they do not conflict with each other.

View file

@ -1,116 +0,0 @@
.. _config_policy:
Policy Configuration
====================
policy.lua.d/10-default-policy.lua
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file contains generic default policy properties that can be configured.
* *default_policy.policy*
This is a Lua object that contains several properties that change the
behavior of the default WirePlumber policy.
Example:
.. code-block:: lua
default_policy.policy = {
["move"] = true,
}
The above example will set the ``move`` policy property to ``true``.
The list of supported properties are:
.. code-block:: lua
["move"] = true
Moves session items when metadata ``target.node`` changes.
.. code-block:: lua
["follow"] = true
Moves session items to the default device when it has changed.
.. code-block:: lua
["audio.no-dsp"] = false
Set to ``true`` to disable channel splitting & merging on nodes and enable
passthrough of audio in the same format as the format of the device. Note that
this breaks JACK support; it is generally not recommended.
.. code-block:: lua
["duck.level"] = 0.3
How much to lower the volume of lower priority streams when ducking. Note that
this is a linear volume modifier (not cubic as in PulseAudio).
policy.lua.d/50-endpoints-config.lua
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Endpoints are objects that can group multiple clients into different groups or
roles. This is useful if a user wants to apply specific actions when a client
is connected to a particular role/endpoint. This configuration file allows
users to configure those endpoints and their actions.
* *default_policy.policy.roles*
This is a Lua array with objects defining the actions of each role.
Example:
.. code-block:: lua
default_policy.policy.roles = {
["Multimedia"] = {
["alias"] = { "Movie", "Music", "Game" },
["priority"] = 10,
["action.default"] = "mix",
}
["Notification"] = {
["priority"] = 20,
["action.default"] = "duck",
["action.Notification"] = "mix",
}
}
The above example defines actions for both ``Multimedia`` and ``Notification``
roles. Since the Notification role has more priority than the Multimedia
role, when a client connects to the Notification endpoint, it will ``duck``
the volume of all Multimedia clients. If Multiple Notification clients want
to play audio, only the Notifications audio will be mixed.
Possible values of actions are: ``mix`` (Mixes audio),
``duck`` (Mixes and lowers the audio volume) or ``cork`` (Pauses audio).
* *default_policy.policy.endpoints*
This is a Lua array with objects defining the endpoints that the user wants
to create.
Example:
.. code-block:: lua
default_policy.endpoints = {
["endpoint.multimedia"] = {
["media.class"] = "Audio/Sink",
["role"] = "Multimedia",
}
},
["endpoint.notifications"] = {
["media.class"] = "Audio/Sink",
["role"] = "Notification",
}
This example creates 2 endpoints, with names ``endpoint.multimedia`` and
``endpoint.notifications``; and assigned roles ``Multimedia`` and ``Notification``
respectively. Both endpoints have ``Audio/Sink`` media class, and so are only
used for playback.

View file

@ -1,139 +0,0 @@
.. _logging:
Debug Logging
=============
Getting debug messages on the command line is a matter of setting the
``WIREPLUMBER_DEBUG`` environment variable. The generic syntax is:
.. code::
WIREPLUMBER_DEBUG=level:category1,category2,...
``level`` can be one of ``CEWMIDT`` or a numerical log level as listed below.
In either case it defines the minimum debug level to show:
0. critical warnings and fatal errors (``C`` & ``E`` in the log)
1. warnings (``W``)
2. normal messages (``M``)
3. informational messages (``I``)
4. debug messages (``D``)
5. trace messages (``T``)
``category1,category2,...`` is an *optional* comma-separated list of debug
categories to show. Any categories not listed here will *not* appear in the log.
If no categories are specified, then all messages are printed.
Categories support
`glob style patterns <https://developer.gnome.org/glib/stable/glib-Glob-style-pattern-matching.html>`_
containing ``*`` and ``?``, for convenience.
Well known categories include:
- **wireplumber**: messages from the wireplumber daemon
- **pw**: messages from libpipewire & spa plugins
- **wp-***: messages from libwireplumber
- **wp-core**: messages from *WpCore*
- **wp-proxy**: messages from *WpProxy*
- ... and so on ...
- **m-***: messages from wireplumber modules
- **m-default-profile**: messages from *libwireplumber-module-default-profile*
- **m-default-routes**: messages from *libwireplumber-module-default-routes*
- ... and so on ...
- **script/***: messages from scripts
- **script/policy-node**: messages from the *policy-node.lua* script
- ... and so on ...
Examples
--------
Show all messages:
.. code::
WIREPLUMBER_DEBUG=T
Show all messages up to the *debug* level (E, C, W, M, I & D), excluding *trace*:
.. code::
WIREPLUMBER_DEBUG=D
Show all messages up to the *message* level (E, C, W & M),
excluding *info*, *debug* & *trace*
(this is also the default when ``WIREPLUMBER_DEBUG`` is omitted):
.. code::
WIREPLUMBER_DEBUG=2
Show all messages from the wireplumber library:
.. code::
WIREPLUMBER_DEBUG=T:wp-*
Show all messages from ``wp-registry``, libpipewire and all modules:
.. code::
WIREPLUMBER_DEBUG=T:wp-registry,pw,m-*
Relationship with the GLib log handler & G_MESSAGES_DEBUG
---------------------------------------------------------
Older versions of WirePlumber used to use ``G_MESSAGES_DEBUG`` to control their
log output, which is the environment variable that affects GLib's default
log handler.
As of WirePlumber 0.3, ``G_MESSAGES_DEBUG`` is no longer used, since
libwireplumber replaces the default log handler.
If you are writing your own application based on libwireplumber, you can choose
if you want to replace this log handler using the flags passed to
:c:func:`wp_init`.
Relationship with the PipeWire log handler & PIPEWIRE_DEBUG
-----------------------------------------------------------
libpipewire uses the ``PIPEWIRE_DEBUG`` environment variable, with a similar syntax.
WirePlumber replaces the log handler of libpipewire with its own, rendering
``PIPEWIRE_DEBUG`` useless. Instead, you should use ``WIREPLUMBER_DEBUG`` and the
``pw`` category to control log messages from libpipewire & its plugins.
If you are writing your own application based on libwireplumber, you can choose
if you want to replace this log handler using the flags passed to
:c:func:`wp_init`.
Mapping of PipeWire debug levels to WirePlumber
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Both WirePlumber and PipeWire support 6 levels of debug logging, from 0 to 5
PipeWire uses a slightly different semantic for the first 3 levels:
===== ======== ===========
Level PipeWire WirePlumber
===== ======== ===========
0 no log Critical / fatal Errors
1 Errors Warnings
2 Warnings Messages
===== ======== ===========
When PipeWire log messages are printed by the WirePlumber log handler, the
level number stays the same and the semantic changes. PipeWire's errors are
printed in the ``W`` category and PipeWire's warnings are printed in the
``M`` category.
In WirePlumber's (actually GLib's) semantics, this feels more appropriate
because:
- GLib's errors are fatal (``abort()`` is called)
- GLib's critical warnings are assertion failures (i.e. programming mistakes,
not runtime errors)
- PipeWire's errors are neither fatal, nor programming mistakes; they are
just bad situations that are not meant to happen
- GLib's warnings are exactly that: bad runtime situations that are not meant
to happen, so mapping PipeWire errors to GLib warnings makes sense
- The **Messages** log level does not exist in PipeWire, so it can be used to
fill the gap for PipeWire warnings

View file

@ -0,0 +1,30 @@
.. _daemon_configuration:
Configuration
=============
WirePlumber is a heavily modular daemon. By itself, it doesn't do anything
except load its configured components. The actual management logic is
implemented inside those components.
At startup, WirePlumber reads its configuration file (combined with all the
fragments it may have) and loads the components specified in the selected
profile. This configures the operation context. Then, the components take over
and drive the entirety of the daemon's operation.
The sections below describe in more detail the configuration file format and
the various options available.
.. toctree::
:maxdepth: 1
configuration/conf_file.rst
configuration/components_and_profiles.rst
configuration/configuration_option_types.rst
configuration/modifying_configuration.rst
configuration/migration.rst
configuration/features.rst
configuration/settings.rst
configuration/alsa.rst
configuration/bluetooth.rst
configuration/access.rst

View file

@ -0,0 +1,125 @@
.. _config_access:
Access configuration
====================
WirePlumber includes a "client access" policy which defines access control
rules for PipeWire clients.
Rules
-----
This policy can be configured with rules that can be used to match clients and
apply default permissions to them.
Example:
.. code-block::
access.rules = [
{
matches = [
{
access = "flatpak"
media.category = "Manager"
}
]
actions = {
update-props = {
access = "flatpak-manager"
default_permissions = "all",
}
}
}
{
matches = [
{
access = "flatpak"
}
]
actions = {
update-props = {
default_permissions = "rx"
}
}
}
]
Possible permissions are any combination of:
* ``r``: client is allowed to **read** objects, i.e. "see" them on the registry
and list their properties
* ``w``: client is allowed to **write** objects, i.e. call methods that modify
their state
* ``x``: client is allowed to **execute** methods on objects; the ``w`` flag
must also be present to call methods that modify the object
* ``m``: client is allowed to set **metadata** on objects
* ``l``: nodes of this client are allowed to **link** to other nodes that the
client can't "see" (i.e. the client doesn't have ``r`` permission on them)
The special value ``all`` is also supported and it is synonym for ``rwxm``
Permission Managers
-------------------
For more advanced use cases, WirePlumber supports *permission managers* that can
apply per-object permissions dynamically based on rules and object interests.
Permission managers are defined in the ``access.permission-managers`` section
and then referenced by name in ``access.rules``.
Example:
.. code-block::
access.permission-managers = [
{
name = "custom"
default_permissions = "all"
core_permissions = "rx"
rules = [
{
matches = [
{
media.class = "Audio/Source"
}
]
actions = {
set-permissions = "-"
}
}
]
}
]
access.rules = [
{
matches = [
{
application.name = "paplay"
}
]
actions = {
update-props = {
permission_manager_name = "custom"
}
}
}
]
Each permission manager supports the following properties:
* ``name``: (required) a unique name used to reference the manager from
``access.rules``
* ``default_permissions``: the fallback permissions applied to all objects
that don't match any rule (applied as ``PW_ID_ANY``)
* ``core_permissions``: permissions applied specifically to the PipeWire core
object (``PW_ID_CORE``, ID 0). This is useful when you want to allow a
client to interact with the core (e.g. enumerate objects, subscribe to
events) while restricting access to individual objects. If not set, the
``default_permissions`` value is used for the core as well.
* ``rules``: a list of match rules with ``set-permissions`` actions that
grant specific permissions to objects matching the given constraints
When both ``default_permissions`` and ``permission_manager_name`` are set in
a rule's ``update-props`` action, ``default_permissions`` takes precedence and
the permission manager is ignored.

View file

@ -0,0 +1,485 @@
.. _config_alsa:
ALSA configuration
==================
One of the components of WirePlumber is the ALSA monitor. This monitor is
responsible for creating PipeWire devices and nodes for all the ALSA cards that
are available on the system. It also manages the configuration of these devices.
The ALSA monitor is enabled by default and can be disabled using the
``monitor.alsa`` :ref:`feature <config_features>` in the configuration file.
The monitor, as with all device monitors, is implemented as a SPA plugin and is
part of PipeWire. WirePlumber merely loads the plugin and lets it do its work.
The plugin then monitors UDev and creates device and node objects for all the
ALSA cards that are available on the system.
.. note::
One thing worth remembering here is that in ALSA, a "card" represents a
physical sound controller device, and a "device" is a logical access point
that represents a set of inputs and/or outputs that are part of the card. In
PipeWire, a "device" is the direct equivalent of an ALSA "card" and a "node"
is almost equivalent (close, but not quite) of an ALSA "device".
Properties
----------
The ALSA monitor SPA plugin (``api.alsa.enum.udev``) supports properties that
can be used to configure it when it is loaded. These properties can be set in
the ``monitor.alsa.properties`` section of the WirePlumber configuration file.
Example:
.. code-block::
monitor.alsa.properties = {
alsa.use-acp = true
}
.. describe:: alsa.use-acp
A boolean that controls whether the ACP (alsa card profile) code is to be
the default manager of the device. This will probe the device and configure
the available profiles, ports and mixer settings. The code to do this is
taken directly from PulseAudio and provides devices that look and feel
exactly like the PulseAudio devices.
Rules
-----
When device and node objects are created by the ALSA monitor, they can be
configured using rules. These rules allow matching the existing properties of
these objects and updating them with new values. This is the main way of
configuring ALSA device settings.
These rules can be set in the ``monitor.alsa.rules`` section of the WirePlumber
configuration file.
Example:
.. code-block::
monitor.alsa.rules = [
{
matches = [
{
# This matches the value of the 'device.name' property of the device.
device.name = "~alsa_card.*"
}
]
actions = {
update-props = {
# Apply all the desired device settings here.
api.alsa.use-acp = true
}
}
}
{
matches = [
# This matches the value of the 'node.name' property of the node.
{
node.name = "~alsa_output.*"
}
]
actions = {
# Apply all the desired node specific settings here.
update-props = {
node.nick = "My Node"
priority.driver = 100
session.suspend-timeout-seconds = 5
}
}
}
]
Device properties
^^^^^^^^^^^^^^^^^
The following properties can be configured on devices created by the monitor:
.. describe:: api.alsa.use-acp
Use the ACP (alsa card profile) code to manage this device. This will probe
the device and configure the available profiles, ports and mixer settings.
The code to do this is taken directly from PulseAudio and provides devices
that look and feel exactly like the PulseAudio devices.
:Default value: ``true``
:Type: boolean
.. describe:: api.alsa.use-ucm
When ACP is enabled and a UCM configuration is available for a device, by
default it is used instead of the ACP profiles. This option allows you to
disable this and use the ACP profiles instead.
This option does nothing if ``api.alsa.use-acp`` is set to ``false``.
:Default value: ``true``
:Type: boolean
.. describe:: api.alsa.soft-mixer
Setting this option to ``true`` will disable the hardware mixer for volume
control and mute. All volume handling will then use software volume and mute,
leaving the hardware mixer untouched. The hardware mixer will still be used
to mute unused audio paths in the device.
:Type: boolean
.. describe:: api.alsa.ignore-dB
Setting this option to ``true`` will ignore the decibel setting configured by
the driver. Use this when the driver reports wrong settings.
:Type: boolean
.. describe:: device.profile-set
This option can be used to select a custom ACP profile-set name for the
device. This can be configured in UDev rules, but it can also be specified
here. The default is to use "default.conf".
:Type: string
.. describe:: device.profile
The initial active profile name. The default is to start from the "Off"
profile and then let WirePlumber select the best profile based on its
policy.
:Type: string
.. describe:: api.acp.auto-profile
Automatically select the best profile for the device. Normally this option is
disabled because WirePlumber will manage the profile of the device.
WirePlumber can save and load previously selected profiles. Enable this in
custom configurations where the relevant WirePlumber components are disabled.
:Type: boolean
.. describe:: api.acp.auto-port
Automatically select the highest priority port that is available ("port" is a
PulseAudio/ACP term, the equivalent of a "Route" in PipeWire). This is by
default disabled because WirePlumber handles the task of selecting and
restoring Routes. Enable this in custom configurations where the relevant
WirePlumber components are disabled.
:Type: boolean
.. describe:: api.acp.probe-rate
Sets the samplerate used for probing the ALSA devices and collecting the
profiles and ports.
:Type: integer
.. describe:: api.acp.pro-channels
Sets the number of channels to use when probing the "Pro Audio" profile.
Normally, the maximum amount of channels will be used but with this setting
this can be reduced, which can make it possible to use other samplerates on
some devices.
:Type: integer
Some of the other properties that can be configured on devices:
.. describe:: device.nick
A short name for the device.
.. describe:: device.description
A longer, user-friendly name of the device. This will show up in most
user interfaces as the device's name.
.. describe:: device.disabled
Disables the device. PipeWire will remove it from the list of cards or
devices.
:Type: boolean
Node properties
^^^^^^^^^^^^^^^
The following properties can be configured on nodes created by the monitor:
.. describe:: priority.driver
This configures the node driver priority. Nodes with higher priority will be
used as a driver in the graph. Other nodes with lower priority will have to
resample to the driver node when they are joined in the same graph. The
default value is set based on some heuristics.
:Type: integer
.. describe:: priority.session
This configures the priority of the node when selecting a default node
(default sink/source as a link target for streams). Higher priority nodes
will be more likely candidates for becoming the default node.
:Type: integer
.. note::
By default, sources have a ``priority.session`` value around 1600-2000 and
sinks have a value around 600-1000. If you are increasing the priority of
a sink, it is **not advised** to use a value higher than 1500, as it may
cause a sink's monitor to be selected as the default source.
.. describe:: node.pause-on-idle
Pause the node when nothing is linked to it anymore. This is by default false
because some devices make a "pop" sound when they are opened/closed.
The node will normally pause and suspend after a timeout (see below).
:Type: boolean
.. describe:: session.suspend-timeout-seconds
This option configures a different suspend timeout on the node. By default
this is ``5`` seconds. For some devices (HiFi amplifiers, for example) it
might make sense to set a higher timeout because they might require some time
to restart after being idle.
A value of ``0`` disables suspend for a node and will leave the ALSA device
busy. The device can then be manually suspended with
``pactl suspend-sink|source``.
:Type: integer
.. describe:: audio.format
The sample format of the device. By default, PipeWire will use a 32 bits
sample format but a different format can be set here.
:Type: string (``"S16LE"``, ``"S32LE"``, ``"F32LE"``, ...)
.. describe:: audio.rate
The sample rate of the device. By default, the ALSA device will be configured
with the same samplerate as the global graph. If this is not supported, or a
custom value is set here, resampling will be used to match the graph rate.
:Type: integer
.. describe:: audio.channels
The number of channels of the device. By default the channels and their
position are determined by the selected device profile. You can override
this setting here.
:Type: integer
.. describe:: audio.position
The position of the channels. By default the number of channels and their
position are determined by the selected device profile. You can override
this setting here and optionally swap or reconfigure the channel positions.
:Type: array of strings (example: ``["FL", "FR", "LFE", "FC", "RL", "RR"]``)
.. describe:: api.alsa.use-chmap
Use the channel map as reported by the driver. This is disabled by default
because it is often wrong and the ACP code handles this better.
:Type: boolean
.. describe:: api.alsa.disable-mmap
Disable the use of mmap for the ALSA device. By default, PipeWire will access
the memory of the device using mmap. This can be disabled and force the usage
of the slower read and write access modes, in case the mmap support of the
device is not working properly.
:Type: boolean
.. describe:: channelmix.normalize
Normalize the channel volumes when mixing & resampling, making sure that the
original 0 dB level is preserved so that nothing sounds wildly
quieter/louder. This is disabled by default.
:Type: boolean
.. describe:: channelmix.mix-lfe
Creates a "center" channel for X.0 recordings from the front stereo on X.1
setups and pushes some low-frequency/bass from the "center" of X.1 recordings
into the front stereo on X.0 setups. This is disabled by default.
:Type: boolean
.. describe:: monitor.channel-volumes
By default, the volume of the sink/source does not influence the volume on
the monitor ports. Set this option to true to change this. PulseAudio has
inconsistent behaviour regarding this option, it applies channel-volumes only
when the sink/source is using software volumes.
:Type: boolean
.. describe:: node.disabled
Disables the node. Pipewire will remove it from the list of the nodes.
:Type: boolean
ALSA buffer properties
......................
PipeWire by default uses a timer to consume and produce samples to/from ALSA
devices. After every timeout, it queries the hardware pointers of the device and
uses this information to set a new timeout. This works well for most devices,
but there is a class of devices, so called "batch" devices, that need extra
buffering and timing tweaks to work properly. This is because batch devices only
get their hardware pointers updated after each hardware interrupt. When the
hardware interrupt frequency and the timer frequency are aligned, it is possible
for the hardware pointers to be updated just after the timer has expired,
resulting in sometimes wrong timing information being returned by the query. In
contrast, non-batch devices get pointer updates independent of the interrupt.
This means that for batch devices we need to set the interrupt at a sufficiently
high frequency, at the cost of CPU usage, while for non-batch devices we want to
set the interrupt frequency as low as possible to save CPU. For batch devices
we also need to take the extra buffering into account caused by the delayed
updates of the hardware pointers.
.. note::
Most USB devices are batch devices and will be handled as such by PipeWire by
default.
There are 2 tunable parameters to control the buffering and timeouts in a
device:
.. describe:: api.alsa.period-size
This sets the device interrupt to every period-size samples for non-batch
devices and to half of this for batch devices. For batch devices, the other
half of the period-size is used as extra buffering to compensate for the
delayed update. So, for batch devices, there is an additional period-size/2
delay. It makes sense to lower the period-size for batch devices to reduce
this delay.
:Type: integer (samples)
.. describe:: api.alsa.headroom
This adds extra delay between the hardware pointers and software pointers.
In most cases this can be set to 0. For very bad devices or emulated devices
(like in a VM) it might be necessary to increase the headroom value.
:Type: integer (samples)
.. describe:: api.alsa.period-num
This configures the number of periods in the hardware buffer, which controls
its size. Note that this is multiplied by the period of the device to
determine the size, so for batch devices, the total buffer size is
effectively period-num * period-size/2.
:Type: integer
In summary, this is the overview of buffering and timings:
============== ============================================ ==========================================
Property Batch Non-Batch
============== ============================================ ==========================================
IRQ Frequency api.alsa.period-size/2 api.alsa.period-size
Extra Delay api.alsa.headroom + api.alsa.period-size/2 api.alsa.headroom
Buffer Size api.alsa.period-num * api.alsa.period-size/2 api.alsa.period-num * api.alsa.period-size
============== ============================================ ==========================================
Finally, it is possible to disable the batch device tweaks with:
.. describe:: api.alsa.disable-batch
This disables the batch device tweaks. It removes the extra delay added of
period-size/2 if the device can support this. For batch devices it is also a
good idea to lower the period-size (and increase the IRQ frequency) to get
smaller batch updates and lower latency.
:Type: boolean
ALSA extra latency properties
.............................
Extra internal delay in the DAC and ADC converters of the device itself can be
set with the ``latency.internal.*`` properties:
.. code-block::
latency.internal.rate = 256
latency.internal.ns = 0
You can configure a latency in samples (relative to rate with
``latency.internal.rate``) or in nanoseconds (``latency.internal.ns``).
This value will be added to the total reported latency by the node of the device.
You can use a tool like ``jack_iodelay`` to get the number of samples of
internal latency of your device.
This property is also adjustable at runtime with the ``ProcessLatency`` param.
You will need to find the id of the Node you want to change. For example:
Query the current internal latency of an ALSA node with id 58:
.. code-block:: console
$ pw-cli e 58 ProcessLatency
Object: size 80, type Spa:Pod:Object:Param:ProcessLatency (262156), id Spa:Enum:ParamId:ProcessLatency (16)
Prop: key Spa:Pod:Object:Param:ProcessLatency:quantum (1), flags 00000000
Float 0.000000
Prop: key Spa:Pod:Object:Param:ProcessLatency:rate (2), flags 00000000
Int 0
Prop: key Spa:Pod:Object:Param:ProcessLatency:ns (3), flags 00000000
Long 0
Set the internal latency to 256 samples:
.. code-block:: console
$ pw-cli s 58 ProcessLatency '{ rate = 256 }'
Object: size 32, type Spa:Pod:Object:Param:ProcessLatency (262156), id Spa:Enum:ParamId:ProcessLatency (16)
Prop: key Spa:Pod:Object:Param:ProcessLatency:rate (2), flags 00000000
Int 256
remote 0 node 58 changed
remote 0 port 70 changed
remote 0 port 72 changed
remote 0 port 74 changed
remote 0 port 76 changed
Startup tweaks
..............
.. describe:: api.alsa.start-delay
Some devices need some time before they can report accurate hardware pointer
positions. In those cases, an extra start delay can be added to compensate
for this startup delay. This sets the startup delay in samples. The default
is 0.
:Type: integer (samples)
IEC958 (S/PDIF) passthrough
...........................
.. describe:: iec958.codecs
S/PDIF passthrough will only be enabled when the accepted codecs are configured
on the ALSA device. This can be done by setting the list of supported codecs
on this property.
Note that it is possible to also configure this property at runtime, either
with tools like pavucontrol or with the ``pw-cli`` tool, like this:
``pw-cli s <node-id> Props '{ iec958Codecs : [ PCM ] }'``
:Type: array of strings (example: ``[ "PCM", "DTS", "AC3", "EAC3", "TrueHD", "DTS-HD" ]``)

View file

@ -0,0 +1,440 @@
.. _config_bluetooth:
Bluetooth configuration
=======================
Bluetooth audio and MIDI devices are managed by the BlueZ and BlueZ-MIDI
monitors, respectively.
Both monitors are enabled by default and can be disabled using the
``monitor.bluez`` and ``monitor.bluez-midi`` :ref:`features <config_features>`
in the configuration file.
As with all device monitors, both of these monitors are implemented as SPA
plugins and are part of PipeWire. WirePlumber merely loads the plugins and lets
them do their work. These plugins then monitor the BlueZ system-wide D-Bus
service and create device and node objects for all the connected Bluetooth audio
and MIDI devices.
Logind integration
------------------
The BlueZ monitors are integrated with logind to ensure that only one user at a
time can use the Bluetooth audio devices. This is because on most Linux desktop
systems, the graphical login manager (GDM, SDDM, etc.) is running as a separate
user and runs its own instance of PipeWire and Wireplumber. This means that if a
user logs in graphically, the Bluetooth audio devices will be automatically
grabbed by the PipeWire/WirePlumber instance of the graphical login manager,
and the user that logs in will not get access to them.
To overcome this, the BlueZ monitors are integrated with logind and are only
allowed to create device and node objects for Bluetooth audio devices if the
user is currently on the "active" logind session.
In some cases, however, this behavior is not desired. For example, if you
manually switch to a TTY and log in there, you may want to keep the Bluetooth
audio devices connected to the now inactive graphical session. Or you may want
to have a dedicated user that is always allowed to use the Bluetooth audio
devices, regardless of the active logind session, for example for a (possibly
headless) music player daemon.
To disable this behavior, you can set the ``monitor.bluez.seat-monitoring``
:ref:`feature <config_features>` to ``disabled``.
Example configuration :ref:`fragment <config_conf_file_fragments>` file:
.. code-block::
wireplumber.profiles = {
main = {
monitor.bluez.seat-monitoring = disabled
}
}
.. note::
If logind is not installed on the system, this functionality is disabled
automatically.
Monitor Properties
------------------
The BlueZ monitor SPA plugin (``api.bluez5.enum.dbus``) supports properties that
can be used to configure it when it is loaded. These properties can be set in
the ``monitor.bluez.properties`` section of the WirePlumber configuration file.
Example:
.. code-block::
monitor.bluez.properties = {
bluez5.roles = [ a2dp_sink a2dp_source bap_sink bap_source hsp_hs hsp_ag hfp_hf hfp_ag ]
bluez5.codecs = [ sbc sbc_xq aac ]
bluez5.enable-sbc-xq = true
bluez5.hfphsp-backend = "native"
}
.. describe:: bluez5.roles
Enabled roles.
Currently some headsets (e.g. Sony WH-1000XM3) do not work with both
``hsp_ag`` and ``hfp_ag`` enabled, so by default we enable only HFP.
Supported roles:
- ``hsp_hs`` (HSP Headset)
- ``hsp_ag`` (HSP Audio Gateway),
- ``hfp_hf`` (HFP Hands-Free),
- ``hfp_ag`` (HFP Audio Gateway)
- ``a2dp_sink`` (A2DP Audio Sink)
- ``a2dp_source`` (A2DP Audio Source)
- ``bap_sink`` (LE Audio Basic Audio Profile Sink)
- ``bap_source`` (LE Audio Basic Audio Profile Source)
:Default value: ``[ a2dp_sink a2dp_source bap_sink bap_source hfp_hf hfp_ag ]``
:Type: array of strings
.. describe:: bluez5.codecs
Enabled A2DP codecs.
Supported codecs: ``sbc``, ``sbc_xq``, ``aac``, ``ldac``, ``aptx``,
``aptx_hd``, ``aptx_ll``, ``aptx_ll_duplex``, ``faststream``,
``faststream_duplex``, ``lc3plus_h3``, ``opus_05``, ``opus_05_51``,
``opus_05_71``, ``opus_05_duplex``, ``opus_05_pro``, ``lc3``.
:Default value: all available codecs
:Type: array of strings
.. describe:: bluez5.enable-msbc
Enable mSBC codec (wideband speech codec for HFP/HSP).
This does not work on all headsets, so it is enabled based on the hardware
quirks database. By explicitly setting this option you can force it to be
enabled or disabled regardless.
:Default value: ``true``
:Type: boolean
.. describe:: bluez5.enable-sbc-xq
Enable SBC-XQ codec (high quality SBC codec for A2DP).
This does not work on all headsets, so it is enabled based on the hardware
quirks database. By explicitly setting this option you can force it to be
enabled or disabled regardless.
:Default value: ``true``
:Type: boolean
.. describe:: bluez5.enable-hw-volume
Enable hardware volume controls.
This does not work on all headsets, so it is enabled based on the hardware
quirks database. By explicitly setting this option you can force it to be
enabled or disabled regardless.
:Default value: ``true``
:Type: boolean
.. describe:: bluez5.hfphsp-backend
HFP/HSP backend.
Available values: ``any``, ``none``, ``hsphfpd``, ``ofono`` or ``native``.
:Default value: ``native``
:Type: string
.. describe:: bluez5.hfphsp-backend-native-modem
Modem to use for native HFP/HSP backend ModemManager support. When enabled,
PipeWire will forward HFP commands to the specified ModemManager device.
This corresponds to the 'Device' property of the
``org.freedesktop.ModemManager1.Modem`` interface. May also be ``any`` to
use any available modem device.
:Default value: ``none``
:Type: string
.. describe:: bluez5.hw-offload-sco
HFP/HSP hardware offload SCO support.
Using this feature requires a custom WirePlumber script that handles audio
routing in a platform-specific way. See ``tests/examples/bt-pinephone.lua``
for an example.
:Default value: ``false``
:Type: boolean
.. describe:: bluez5.default.rate
The default audio rate for the A2DP codec configuration.
:Default value: ``48000``
:Type: integer
.. describe:: bluez5.default.channels
The default number of channels for the A2DP codec configuration.
:Default value: ``2``
:Type: integer
.. describe:: bluez5.dummy-avrcp-player
Register dummy AVRCP player. Some devices have wrongly functioning volume or
playback controls if this is not enabled. Disabled by default.
:Default value: ``false``
:Type: boolean
.. describe:: Opus Pro Audio mode settings
.. code-block::
bluez5.a2dp.opus.pro.channels = 3
bluez5.a2dp.opus.pro.coupled-streams = 1
bluez5.a2dp.opus.pro.locations = [ FL,FR,LFE ]
bluez5.a2dp.opus.pro.max-bitrate = 600000
bluez5.a2dp.opus.pro.frame-dms = 50
bluez5.a2dp.opus.pro.bidi.channels = 1
bluez5.a2dp.opus.pro.bidi.coupled-streams = 0
bluez5.a2dp.opus.pro.bidi.locations = [ FC ]
bluez5.a2dp.opus.pro.bidi.max-bitrate = 160000
bluez5.a2dp.opus.pro.bidi.frame-dms = 400
Options for the PipeWire-specific multichannel Opus codec, which can be used
to transport audio over Bluetooth between devices running PipeWire.
MIDI Monitor Properties
-----------------------
The BlueZ MIDI monitor SPA plugin (``api.bluez5.midi.enum``) may, in the future,
support properties that can be used to configure it when it is loaded. These
properties can be set in the ``monitor.bluez-midi.properties`` section of the
WirePlumber configuration file. At the moment of writing, there are no
properties that can be set there.
In addition, the BlueZ MIDI monitor supports a list of MIDI server node names
that can be used to create Bluetooth LE MIDI service instances. These
server node names can be set in the ``monitor.bluez-midi.servers`` section of
the WirePlumber configuration file.
Example:
.. code-block::
monitor.bluez-midi.servers = [ "bluez_midi.server" ]
.. note::
Typical BLE MIDI instruments have one service instance, so adding more than
one here may confuse some clients.
Rules
-----
When device and node objects are created by the BlueZ monitor, they can be
configured using rules. These rules allow matching the existing properties of
these objects and updating them with new values. This is the main way of
configuring Bluetooth device settings.
These rules can be set in the ``monitor.bluez.rules`` section of the WirePlumber
configuration file.
Example:
.. code-block::
monitor.bluez.rules = [
{
matches = [
{
## This matches all bluetooth devices.
device.name = "~bluez_card.*"
}
]
actions = {
update-props = {
bluez5.auto-connect = [ hfp_hf hsp_hs a2dp_sink hfp_ag hsp_ag a2dp_source ]
bluez5.hw-volume = [ hfp_hf hsp_hs a2dp_sink hfp_ag hsp_ag a2dp_source ]
bluez5.a2dp.ldac.quality = "auto"
bluez5.a2dp.aac.bitratemode = 0
bluez5.a2dp.opus.pro.application = "audio"
bluez5.a2dp.opus.pro.bidi.application = "audio"
}
}
}
{
matches = [
{
## Matches all sources.
node.name = "~bluez_input.*"
}
{
## Matches all sinks.
node.name = "~bluez_output.*"
}
]
actions = {
update-props = {
bluez5.media-source-role = "input"
# Common node & audio adapter properties may also be set here
node.nick = "My Node"
priority.driver = 100
priority.session = 100
node.pause-on-idle = false
resample.quality = 4
channelmix.normalize = false
channelmix.mix-lfe = false
session.suspend-timeout-seconds = 5
monitor.channel-volumes = false
}
}
}
]
Device properties
^^^^^^^^^^^^^^^^^
The following properties can be set on device objects:
.. describe:: bluez5.auto-connect
Auto-connect device profiles on start up or when only partial profiles have
connected. Disabled by default if the property is not specified.
Supported values are: ``hfp_hf``, ``hsp_hs``, ``a2dp_sink``, ``hfp_ag``,
``hsp_ag`` and ``a2dp_source``.
:Default value: ``[]``
:Type: array of strings
.. describe:: bluez5.hw-volume
Enable hardware volume controls on these profiles.
Supported values are: ``hfp_hf``, ``hsp_hs``, ``a2dp_sink``, ``hfp_ag``,
``hsp_ag`` and ``a2dp_source``.
:Default value: ``[ hfp_ag hsp_ag a2dp_source ]``
:Type: array of strings
.. describe:: bluez5.a2dp.ldac.quality
LDAC encoding quality.
Available values: ``auto`` (Adaptive Bitrate, default), ``hq`` (High
Quality, 990/909kbps), ``sq`` (Standard Quality, 660/606kbps) and ``mq``
(Mobile use Quality, 330/303kbps).
:Default value: ``auto``
:Type: string
.. describe:: bluez5.a2dp.aac.bitratemode
AAC variable bitrate mode.
Available values: 0 (cbr, default), 1-5 (quality level).
:Default value: ``0``
:Type: integer
.. describe:: bluez5.a2dp.opus.pro.application
Opus Pro Audio encoding mode.
Available values: ``audio``, ``voip``, ``lowdelay``.
:Default value: ``audio``
:Type: string
.. describe:: bluez5.a2dp.opus.pro.bidi.application
Opus Pro Audio encoding mode for bidirectional audio.
Available values: ``audio``, ``voip``, ``lowdelay``.
:Default value: ``audio``
:Type: string
.. describe:: device.profile
The profile that is activated initially when the device is connected.
Available values: ``a2dp-sink`` (default) or ``headset-head-unit``.
:Default value: ``a2dp-sink``
:Type: string
Node properties
^^^^^^^^^^^^^^^
The following properties can be set on node objects:
.. describe:: bluez5.media-source-role
Media source role, ``input`` or ``playback``. This controls how a media
source device, such as a smartphone, is used by the system. Defaults to
``playback``, playing the incoming stream out to speakers. Set to ``input``
to use the smartphone as an input for apps (like a microphone).
:Default value: ``playback``
:Type: string
MIDI Rules
----------
Similarly to the above rules, the BlueZ MIDI monitor also supports rules that
can be used to configure MIDI nodes when they are created.
These rules can be set in the ``monitor.bluez-midi.rules`` section of the
WirePlumber configuration file.
Example:
.. code-block::
monitor.bluez-midi.rules = [
{
matches = [
{
node.name = "~bluez_midi.*"
}
]
actions = {
update-props = {
node.nick = "My Node"
priority.driver = 100
priority.session = 100
node.pause-on-idle = false
session.suspend-timeout-seconds = 5
node.latency-offset-msec = 0
}
}
}
]
.. note::
It is possible to also match MIDI server nodes by testing the ``node.name``
property against the server node names that were set in the
``monitor.bluez-midi.servers`` section of the WirePlumber configuration file.
MIDI-specific properties
^^^^^^^^^^^^^^^^^^^^^^^^
.. describe:: node.latency-offset-msec
Latency adjustment to apply on the node. Larger values add a
constant latency, but reduces timing jitter caused by Bluetooth
transport.
:Default value: ``0``
:Type: integer (milliseconds)

View file

@ -0,0 +1,218 @@
.. _config_components_and_profiles:
Components & Profiles
=====================
WirePlumber is organized in components and profiles. Components are
functional parts that provide a specific feature, while profiles are
collections of components that are loaded together to offer a certain
overall experience.
Components
----------
Components are functional parts that provide a specific feature. They can be
described by a name, a type, a feature that they provide and a set of
dependencies, required and optional.
In the configuration file, a component is described as a SPA-JSON object,
in the ``wireplumber.components`` array section, like this:
.. code-block::
{
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> ]
}
Name & arguments
~~~~~~~~~~~~~~~~
The name identifies the resource that this component loads. For example,
it can be a file or a shared library. Depending on the type, the component
may also accept arguments, which are passed on to the resource when it is
loaded.
Types
~~~~~
The main types of components are:
* **script/lua**
A Lua script, which usually contains one or more event hooks and/or
other custom logic. This is the main type of component as WirePlumber's
business logic is mostly written in Lua.
* **module**
A WirePlumber module, which is a shared library that can be loaded
dynamically. Modules usually provide some bundled logic to be consumed by
scripts or some integration between WirePlumber and an external service.
* **pw-module**
A PipeWire module, which is also a shared library that can be loaded
dynamically, but extends the functionality of the underlying *libpipewire*
library. Loading PipeWire modules in the WirePlumber context can be useful
to load custom protocol extensions or to offload some functionality from
the PipeWire daemon.
* **virtual**
Virtual components are just load targets that can be used to pull in
other components by defining dependencies. They do not provide any
functionality by themselves. Note that such components do not have a "name".
* **built-in**
These components are functional parts that are already built into the
WirePlumber library. They provide mostly internal support elements and checks.
Features
~~~~~~~~
A "feature" is a name that we can use to refer to what is being provided
by a component. For example, the ``monitors/alsa.lua`` script provides the
``monitor.alsa`` feature. The feature name is used to refer to the component
when defining dependencies between components and also when defining profiles.
When a component loads successfully, its feature is marked as provided,
otherwise it is not. Whether a feature is provided or not can be checked at
runtime in Lua scripts using the :func:`Core.test_feature` function and in C code
using the :c:func:`wp_core_test_feature` function.
For a list of well-known features, see :ref:`config_features`.
Dependencies
~~~~~~~~~~~~
Each component can "provide" a feature. When the component is loaded, the
feature is marked as provided. Other components can either "require"
or "want" a feature.
If a component "requires" a feature, that means that this feature **must** be
provided before this component is loaded and WirePlumber will try to load the
relevant component that provides that feature if it is not already loaded
(i.e. it will pull in the component). If that other component fails to load,
hence the feature is not provided, the component that requires it will fail
to load as well.
If a component "wants" a feature, that means that this feature would be nice
to have, in the sense that it would offer additional functionality if it
was provided, but it's not strictly needed. WirePlumber will also try to load
the relevant component that provides that feature if it is not already loaded,
meaning that it will also pull in the component. However, if that other
component fails to load, the component that wants it will still be loaded
without error.
Profiles
--------
A profile is a collection of components that are loaded together to offer
a certain overall experience.
Profiles are defined in the configuration file as a SPA-JSON object,
in the ``wireplumber.profiles`` section, like this:
.. code-block::
<profile> = {
<feature name> = [ required | optional | disabled ]
...
}
Each feature can be marked as *required*, *optional* or *disabled*.
* **required**: Loading this profile will pull in the component that can
provide this feature in and if it fails to load, the profile will fail to
load as well.
* **optional**: Loading this profile does not pull in the component that
can provide this feature. If any of the required components either
*requires* or *wants* this feature, then WirePlumber will try to load it.
If it fails to load, the error condition depends on whether this feature was
required or wanted by the component that pulled it in.
* **disabled**: This feature will **not** be loaded, even if it is *wanted*
by some component. If any required component *requires* this feature, then
the profile will fail to load.
By default, all the features provided by all the components in the
``wireplumber.components`` section are considered to be *optional*.
That means that no component will be loaded on an empty profile, since optional
components are not pulled in automatically.
If a feature is marked as *required* in a profile, then the component that
provides that feature will be pulled in, together with all its dependencies,
both required and optional.
.. note::
In essence, all optional features are opt-in by default. To opt out,
you need to mark the feature as *disabled*.
Dependency chain example
------------------------
Consider the following configuration file:
.. code-block::
wireplumber.components = [
{
name = libwireplumber-module-dbus-connection, type = module
provides = support.dbus
}
{
name = libwireplumber-module-reserve-device, type = module
provides = support.reserve-device
requires = [ support.dbus ]
}
{
name = monitors/alsa.lua, type = script/lua
provides = monitor.alsa
wants = [ support.reserve-device ]
}
]
wireplumber.profiles = {
main = {
monitor.alsa = required
}
}
In this example, the ``main`` profile requires the ``monitor.alsa`` feature.
This will cause the ``monitors/alsa.lua`` script to be loaded. Now, since the
``monitors/alsa.lua`` script *wants* the ``support.reserve-device`` feature,
the ``libwireplumber-module-reserve-device`` module will also be pulled in.
And since that one *requires* the ``support.dbus`` feature, the
``libwireplumber-module-dbus-connection`` module will also be pulled in.
However, on a system without D-Bus, a user may want to opt out of the
``libwireplumber-module-dbus-connection`` module. This can be done by marking
the ``support.dbus`` feature as disabled in the profile:
.. code-block::
wireplumber.profiles = {
main = {
monitor.alsa = required
support.dbus = disabled
}
}
Upon doing that, the ``libwireplumber-module-dbus-connection`` module will
not be loaded, causing the ``libwireplumber-module-reserve-device`` module
to not be loaded as well, since it requires the ``support.dbus`` feature.
The ``monitors/alsa.lua`` script will still be loaded, since it only *wants*
the ``support.reserve-device`` feature.

View file

@ -0,0 +1,244 @@
.. _config_conf_file:
The configuration file
======================
WirePlumber's configuration file is by default ``wireplumber.conf`` and resides
in one of the WirePlumber specific
:ref:`configuration file search locations <config_locations>`.
The default configuration file can be changed on the command line by passing
the ``--config-file`` or ``-c`` option:
.. code-block:: bash
$ wireplumber --config-file=custom.conf
.. important::
Starting with WirePlumber 0.5, this is the only file that WirePlumber reads
to load configuration (together with its fragments - see below). In the past,
WirePlumber also used to read Lua configuration files that were referenced
from ``wireplumber.conf`` and all the heavy lifting was done in Lua. This is
no longer the case, and the **Lua configuration files are no longer supported.**
See :ref:`config_migration`.
Note that Lua is still the scripting language for WirePlumber, but it is only
used for actual scripting and not for configuration.
The SPA-JSON Format
-------------------
The format of this configuration file is a variant of JSON that is also
used in PipeWire configuration files (also known as SPA-JSON). The file consists
of a global JSON object that is not explicitly typed, and a list of sections
which are essentially key-value pairs of that global JSON object. Each section
is usually a JSON object, but it can also be a JSON array.
SPA-JSON is a superset of standard JSON, so any valid JSON file is also a valid
SPA-JSON file. However, it is more permissive than standard JSON. First of all,
it allows strings to be typed without quotes (``"``), and it also allows the
character ``=`` as a separator between keys and values in addition to the
standard ``:``. This can make it look similar to INI files or other custom
configuration formats that people are familiar with, which makes it easier for
users to read and edit.
Other deviations from standard JSON include allowing comments (lines starting
with ``#`` are treated as comments) and allowing the separator characters
(``:``, ``=``, ``,``) to appear in excess or abundance. That means that you can
write ``key = value`` or ``key: value`` or ``key value`` and it will be
interpreted the same way. You may also write ``[val1, val2, val3]`` or
``[val1, val2, val3, ]`` or ``[val1 val2 val3]`` and it will be interpreted
the same way. This is allowed because the SPA-JSON parser in fact ignores all
the separator characters (the real separator is the space character).
Examples of valid SPA-JSON files:
.. code-block::
# This is the most common syntax
section1 = {
string-key = value1
number-key = 123
boolean-key = true
}
section2 = [
val1, val2, val3
]
.. code-block::
# Mixed syntax
section1 {
"string-key" = "value1"
number-key: 123
boolean-key true
}
section2 = [
val1, val2 val3,
]
.. code-block::
# Standard JSON (albeit this comment line)
"section1": {
"string-key": "value1",
"number-key": 123,
"boolean-key": true
}
"section2": [
"val1", "val2", "val3"
]
.. _config_conf_file_fragments:
Fragments
---------
Just like PipeWire, WirePlumber supports configuration fragments. This means
that the main configuration file can be split into multiple files, and all of
them will be loaded and merged together. This is mostly useful to allow users
to customize their configuration without having to modify the main file.
When loading the configuration file, WirePlumber will also look for
additional files in the directory that has the same name as the configuration
file suffixed with ``.d`` and will load all of them as well. For example,
loading ``wireplumber.conf`` will also load any ``.conf`` files under
``wireplumber.conf.d/``. This directory is searched in all the configuration
search locations and the fragments are loaded from *all* of them, starting
from the most system-wide locations and moving towards the most user-specific
locations, in alphanumerical order within each location (see also
:ref:`config_locations_fragments`).
When a JSON object appears in multiple files, the properties of the objects are
merged together. When a JSON array appears in multiple files, the arrays are
concatenated together. When merging objects, if specific properties appear in
many of those objects, the last one to be parsed always overwrites previous
ones, unless the value is also an object or array; if it is, then the value is
recursively merged using the same rules.
Sections
--------
WirePlumber reads the following standard sections from the configuration
file:
* *wireplumber.components*
This section is an array that lists components that can be loaded by
WirePlumber. For more information, see :ref:`config_components_and_profiles`.
* *wireplumber.components.rules*
This section is an array containing rules that can be used to modify entries
of the *wireplumber.components* array. This is useful to inject changes
to the components list without having to modify the main configuration file.
* *wireplumber.profiles*
This section is an object that defines profiles that can be loaded by
WirePlumber. For more information, see :ref:`config_components_and_profiles`.
* *wireplumber.settings*
This section is an object that defines settings that can be used to
alter WirePlumber's behavior. For more information, see :ref:`config_settings`.
* *wireplumber.settings.schema*
This section is an object that defines the schema for the settings that
can be listed in *wireplumber.settings*. This is used to validate the
settings when they are modified at runtime. For more information, see
:ref:`config_configuration_option_types`.
In addition, there are many sections that are specific to certain components,
mostly hardware monitors, such as *monitor.alsa.properties*,
*monitor.alsa.rules*, etc. These are documented further on, in the respective
sections of this documentation that describe the configuration options of
these components.
Finally, WirePlumber also reads the following sections, which are parsed
by libpipewire to configure the PipeWire context:
* *context.properties*
Used to define properties to configure the PipeWire context and some modules.
* *context.spa-libs*
Used to find SPA factory names. It maps a SPA factory name regular expression
to a library name that should contain that factory. The object property names
are the regular expressions, and the object property values are the actual
library names:
.. code-block::
<factory-name regex> = <library-name>
For example:
.. code-block::
context.spa-libs = {
api.alsa.* = alsa/libspa-alsa
audio.convert.* = audioconvert/libspa-audioconvert
}
In this example, we instruct wireplumber to lookup any *api.alsa.** factory
in the *libspa-alsa* library, and any *audio.convert.** factory
in the *libspa-audioconvert* library.
.. note::
The default configuration file already contains a list of well-known
factory names and their corresponding libraries. You should only
need to add entries to this section if you are using custom SPA plugins.
* *context.modules*
Used to load PipeWire modules. This does not affect the PipeWire daemon by any
means. It exists simply to allow loading *libpipewire* modules inside
WirePlumber. This is usually useful to load PipeWire protocol extensions,
so that you can export custom objects to PipeWire and other clients.
.. note::
PipeWire modules can also be loaded as :ref:`components <config_components_and_profiles>`,
which may be preferable since it allows you to load them conditionally
based on the profile and component dependencies.
.. admonition:: Remember
Modules listed in *context.modules* are always loaded before attempting a
connection to the PipeWire daemon, while modules listed in
*wireplumber.components* are always loaded after the connection is
established. It is important to load the PipeWire protocol-native module
and any extensions (such as module-metadata) in the *context.modules*
section, so that the connection can be done properly.
Each module is described by a JSON object containing the module's *name*,
its arguments (*args*) and a combination of *flags*, which can be ``ifexists``
and ``nofail``.
.. code-block::
{
name = <module-name>
[ args = { <key> = <value> ... } ]
[ flags = [ [ ifexists ] [ nofail ] ]
}
For example:
.. code-block::
context.modules = [
{ name = libpipewire-module-adapter }
{
name = libpipewire-module-metadata,
flags = [ ifexists ]
}
]
The above example loads both PipeWire adapter and metadata modules. The
metadata module will be ignored if not found because of its ``ifexists`` flag.

View file

@ -0,0 +1,125 @@
.. _config_configuration_option_types:
Configuration option types
==========================
As seen in the previous sections, WirePlumber can be partly configured by
enabling or disabling features, which affect which components are getting
loaded. These components, however, can be further configured to fine-tune their
behavior. This section describes the different types of configuration options
that can be used to configure WirePlumber components.
Dynamic options ("Settings")
----------------------------
Dynamic options (also simply referred to as "settings") are configuration
options that can be changed at runtime. They are typically simple values like
booleans, integers, strings, etc. and are all located under the
``wireplumber.settings`` section in the configuration file. Their purpose is to
allow the user to change simple behavioral aspects of WirePlumber.
As the name suggests, these options are dynamic and can be changed at runtime
using ``wpctl`` or the :ref:`settings_api` API. For example, setting the
``device.routes.default-sink-volume`` setting to ``0.5`` can be done like this:
.. code-block:: bash
$ wpctl settings device.routes.default-sink-volume 0.5
Under the hood, when WirePlumber starts, the ``metadata.sm-settings`` component
(provided by ``libwireplumber-module-settings``) reads this section from the
configuration file and populates the ``sm-settings`` metadata object, which is
exported to PipeWire. In addition, it reads the ``wireplumber.settings.schema``
section and populates the ``schema-sm-settings`` metadata object, which is used
by the API to validate the settings. Any options that are missing from
``wireplumber.settings`` are also populated in ``sm-settings`` from their
default values in the schema. Then the rest of the components read their
configuration options from this metadata object via the :ref:`settings_api` API.
Most of the components that use such dynamic options make sure to listen
to changes in the metadata object so that they can immediately adapt their
behavior. Other components, however, do not react immediately and the changes
only take effect the next time the option is needed. For instance, some options
affect created objects in a way that cannot be changed after the object has been
created, so when the option is changed it applies only to new objects and not
existing ones.
Changing the settings at runtime in the ``sm-settings`` metadata object is
a non-persistent change. The changes will be lost when WirePlumber is
restarted. However, the :ref:`settings_api` API also supports saving settings
to a state file, which will be loaded again when WirePlumber starts and
override the settings from the configuration file. This is done by using yet
another metadata object called ``persistent-sm-settings``. When a setting is
changed in the ``persistent-sm-settings`` metadata object, WirePlumber
automatically saves the change to the state file and also changes the value in
the ``sm-settings`` metadata object immediately.
To make such a persistent change using ``wpctl``, the ``--save`` option can be
used. For example, to set the ``device.routes.default-sink-volume`` setting to
``0.5`` and save it to the state file:
.. code-block:: bash
$ wpctl settings --save device.routes.default-sink-volume 0.5
With ``wpctl``, it is also possible to restore a setting to its default value
(taken from the schema), by using the ``--reset`` option. For example, to reset
the ``device.routes.default-sink-volume`` setting, the following command can be
used:
.. code-block:: bash
$ wpctl settings --reset device.routes.default-sink-volume
In addition, the ``--delete`` option can be used to delete a setting from the
``persistent-sm-settings`` metadata object, which will also remove it from the
state file. After deleting, the value from the ``wireplumber.settings`` section
of the configuration file will be used again. For example, to delete the
``device.routes.default-sink-volume`` setting, the following command can be
used:
.. code-block:: bash
$ wpctl settings --delete device.routes.default-sink-volume
A list of all the available settings can be found in the :ref:`config_settings`
section.
Static options
--------------
Static options are more complex configuration structures that reside only in the
configuration file and cannot be changed at runtime. They are typically used to
configure device monitors and provide rules that match objects and perform
actions such as update their properties.
While these options could also in theory be stored in the metadata object and
be made dynamic, this is not supported because these options are both complex
and therefore hard to change on the command line, but also because they are
typically used to configure objects that are created at startup and cannot be
changed later.
Static options are located in their own top-level sections. Examples of such
sections are ``monitor.alsa.properties`` and ``monitor.alsa.rules`` that are
used to configure the ``monitor.alsa`` component. The next sections of this
documentation describe in detail all the available static options.
Component arguments
~~~~~~~~~~~~~~~~~~~
Components can also be configured statically by passing arguments to them when
they are loaded. This is done by adding an ``arguments`` key to the component
description in the ``wireplumber.components`` section (see
:ref:`config_components_and_profiles`).
The arguments are mostly meant as a way to instantiate multiple instances of the
same module or script with slightly different configuration to create a new
unique component. For example, the ``metadata.lua`` script can be instantiated
multiple times to create multiple metadata objects, each with a different name.
The name of the metadata object is passed as an argument to the script.
While many more static options could be passed as arguments, this is not
recommended because it is not possible to override the arguments by adding
:ref:`fragment<config_conf_file_fragments>` configuration files. Therefore, it
is recommended to use component-specific top-level sections, unless the option
is not meant to be changed by the user.

View file

@ -0,0 +1,157 @@
.. _config_features:
Well-known features
===================
This is a list of some well-known features that can be enabled or
disabled accordingly.
There are many more features actually defined in the configuration file, and it
can be confusing to go through them. This list here is meant to be a quick
reference for the most common ones that actually make sense to be toggled in
a configuration file in order to customize WirePlumber's behavior.
For more information on what features are and how they work, refer to the
previous section: :ref:`config_components_and_profiles`.
Hardware monitors
-----------------
Audio
~~~~~
.. describe:: hardware.audio
Enables bringing up audio hardware.
:wants: ``monitor.alsa``, ``monitor.alsa-midi``
.. describe:: monitor.alsa
Enables the ALSA device monitor.
:wants: ``monitor.alsa.reserve-device``
.. describe:: monitor.alsa.reserve-device
Enables D-Bus device reservation API for ALSA devices.
:requires: ``support.reserve-device``
.. describe:: monitor.alsa-midi
Enables the ALSA MIDI device monitor.
.. describe:: node.software-dsp
Enables software DSP based on pre-configured hardware rules.
See :ref:`policies_software_dsp` for more information.
Bluetooth
~~~~~~~~~
.. describe:: hardware.bluetooth
Enables bringing up bluetooth hardware.
:wants: ``monitor.bluez``, ``monitor.bluez-midi``
.. describe:: monitor.bluez
Enables the BlueZ device monitor.
:wants: ``monitor.bluez.seat-monitoring``
.. describe:: monitor.bluez.seat-monitoring
Enables seat monitoring on the bluetooth monitor.
When enabled, this will make sure that the bluetooth devices are only
enabled on the active seat.
:requires: ``support.logind``
.. describe:: monitor.bluez-midi
Enables the BlueZ MIDI device monitor.
:wants: ``monitor.bluez.seat-monitoring``
Video
~~~~~
.. describe:: hardware.video-capture
Enables bringing up video capture hardware (cameras, hdmi capture devices,
etc.)
:wants: ``monitor.v4l2``, ``monitor.libcamera``
.. describe:: monitor.v4l2
Enables the V4L2 device monitor.
.. describe:: monitor.libcamera
Enables the libcamera device monitor.
Support components
------------------
.. describe:: support.dbus
Provides a D-Bus connection to the session bus. This is needed by some other
support features (see below) but it is generally optional. WirePlumber does
not require a D-Bus connection to work.
On a system where WirePlumber is configured to run system-wide (headless,
embedded, etc), this will most likely fail to load and thus disable all the
other support features that require it. On such systems it makes sense to
disable this feature explicitly, to avoid the overhead of trying to connect
to the session bus.
.. describe:: support.reserve-device
Provides support for the
`D-Bus device reservation API <http://git.0pointer.net/reserve.git/tree/reserve.txt>`_,
allowing the device monitors to reserve devices for exclusive access.
:requires: ``support.dbus``
.. describe:: support.portal-permissionstore
Integrates with the flatpak portal permission store to give appropriate
access permissions to flatpak applications.
:requires: ``support.dbus``
.. describe:: support.logind
Integrates with systemd-logind to enable specific functionality only on the
active seat.
Policies
--------
.. describe:: policy.standard
Enables the standard WirePlumber policy. This includes all the logic
for enabling devices, linking streams, granting permissions to clients,
etc, as appropriate for a desktop system.
.. describe:: policy.role-based
Enables the role based priority system policy. This system creates virtual sinks
that group streams based on their ``media.role`` property, and assigns a
priority to each role. Depending on the priority configuration, lower
priority roles may be corked or ducked when a higher priority role stream
is active.
This policy was designed for automotive and mobile systems and may not work
as expected on desktop systems.
Note that this policy is implemented as a superset of ``policy.standard``,
so ``policy.standard`` should not be disabled when enabling this policy.
:requires: ``policy.standard``

View file

@ -0,0 +1,13 @@
# you need to add here any files you add to the toc directory as well
sphinx_files += files(
'conf_file.rst',
'components_and_profiles.rst',
'configuration_option_types.rst',
'modifying_configuration.rst',
'migration.rst',
'features.rst',
'settings.rst',
'alsa.rst',
'bluetooth.rst',
'access.rst',
)

View file

@ -0,0 +1,305 @@
.. _config_migration:
Migrating configuration from 0.4
================================
The configuration file format has changed in version 0.5. No automatic migration
of old configuration files is performed, so you will have to manually update
them. This document describes the changes and how to update your configuration.
wireplumber.conf
----------------
In WirePlumber 0.4, there used to be a ``.conf`` file, typically
``wireplumber.conf``, using the SPA-JSON format, that would list some Lua
scripts in the ``wireplumber.components`` section. These scripts were of type
``config/lua`` and they were called by default ``main.lua``, ``policy.lua`` and
``bluetooth.lua``.
Typical ``wireplumber.components`` section of a ``wireplumber.conf`` file in 0.4
would look like this:
.. code-block::
wireplumber.components = [
#{ name = <component-name>, type = <component-type> }
#
# WirePlumber components to load
#
# The lua scripting engine
{ name = libwireplumber-module-lua-scripting, type = module }
# The lua configuration file(s)
# Other components are loaded from there
{ name = main.lua, type = config/lua }
{ name = policy.lua, type = config/lua }
{ name = bluetooth.lua, type = config/lua }
]
These Lua "configuration" scripts were then looked up in the standard
configuration directories (``/usr/share/wireplumber``, ``/etc/wireplumber`` and
``~/.config/wireplumber``). The system also supported fragments of these scripts
to be placed in directories called ``main.lua.d``, ``policy.lua.d`` and
``bluetooth.lua.d`` respectively, in the same locations.
.. attention::
Starting with WirePlumber 0.5, Lua "configuration" files are **no longer
supported**.
If you attempt to start it with a ``wireplumber.conf`` that still
lists ``config/lua`` components in its ``wireplumber.components`` section, you
will see the following error message on the output:
Failed to load configuration: The configuration file at '...' is likely an
old WirePlumber 0.4 config and is not supported anymore. Try removing it.
As the message says, to resolve this you should remove the old
``wireplumber.conf`` file from the designated location. This should allow the
new WirePlumber to start using the default configuration that it ships with.
Lua configuration scripts
-------------------------
If you had custom Lua configuration scripts in the standard configuration
directories, such as *"main.lua.d"*, *"policy.lua.d"* or *"bluetooth.lua.d"*,
**you need to port them**.
Locations of files
~~~~~~~~~~~~~~~~~~
The first thing you need to know is that the new files should be placed in the
``~/.config/wireplumber/wireplumber.conf.d/`` directory instead of
``~/.config/wireplumber/main.lua.d/`` and such ...
In addition, since the new files are in the SPA-JSON format, they should have
the ``.conf`` extension instead of ``.lua``.
See also :ref:`config_locations`.
Porting device/node rules
~~~~~~~~~~~~~~~~~~~~~~~~~
One of the most common use-cases for these scripts was to set up properties
for devices and nodes using rules. Here is an example of an old rules script:
.. code-block:: lua
:caption: ~/.config/wireplumber/main.lua.d/51-alsa-pro-audio.lua
local rule = {
matches = {
{
{ "device.name", "matches", "alsa_card.*" },
},
},
apply_properties = {
["api.alsa.use-acp"] = false,
["device.profile"] = "pro-audio",
["api.acp.auto-profile"] = false,
["api.acp.auto-port"] = false,
},
}
table.insert(alsa_monitor.rules, rule)
This equivalent of this script in the new configuration format would look like
this:
.. code-block::
:caption: ~/.config/wireplumber/wireplumber.conf.d/51-alsa-pro-audio.conf
monitor.alsa.rules = [
{
matches = [
{
device.name = "~alsa_card.*"
}
]
actions = {
update-props = {
api.alsa.use-acp = false,
device.profile = "pro-audio"
api.acp.auto-profile = false
api.acp.auto-port = false
}
}
}
]
Another example of Bluetooth node rules:
.. code-block:: lua
:caption: ~/.config/wireplumber/bluetooth.lua.d/51-headphones.lua
local rule = {
matches = {
{
{ "node.name", "equals", "bluez_output.02_11_45_A0_B3_27.a2dp-sink" },
},
},
apply_properties = {
["node.nick"] = "Headphones",
},
}
table.insert(bluez_monitor.rules, rule)
This equivalent of this script in the new configuration format would look like:
.. code-block::
:caption: ~/.config/wireplumber/wireplumber.conf.d/51-headphones.conf
monitor.bluez.rules = [
{
matches = [
{
node.name = "bluez_output.02_11_45_A0_B3_27.a2dp-sink"
}
]
actions = {
update-props = {
node.nick = "Headphones"
}
}
}
]
See also :ref:`config_modifying_configuration_rules`.
Porting properties configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you had configuration scripts that were setting properties in tables such
as ``alsa_monitor.properties`` or ``bluez_monitor.properties``, then in many
cases porting to the new format can be done as follows:
.. code-block:: lua
:caption: ~/.config/wireplumber/bluetooth.lua.d/80-bluez-properties.lua
bluez_monitor.properties["bluez5.roles"] = "[ a2dp_sink a2dp_source bap_sink bap_source hsp_hs hsp_ag hfp_hf hfp_ag ]"
bluez_monitor.properties["bluez5.hfphsp-backend"] = "native"
.. code-block::
:caption: ~/.config/wireplumber/wireplumber.conf.d/80-bluez-properties.conf
monitor.bluez.properties = {
bluez5.roles = [ a2dp_sink a2dp_source bap_sink bap_source hsp_hs hsp_ag hfp_hf hfp_ag ]
bluez5.hfphsp-backend = "native"
}
See also :ref:`config_modifying_configuration_static`.
In a lot of cases, however, these properties have been promoted to become either
:ref:`Settings <config_modifying_configuration_settings>` or
:ref:`Features <config_modifying_configuration_features>`.
Here are some common examples:
Disabling the D-Bus device reservation API in the ALSA monitor:
* Old format:
.. code-block:: lua
:caption: ~/.config/wireplumber/main.lua.d/80-disable-alsa-reserve.lua
alsa_monitor.properties["alsa.reserve"] = false
* New format:
.. code-block::
:caption: ~/.config/wireplumber/wireplumber.conf.d/80-disable-alsa-reserve.conf
wireplumber.profiles = {
main = {
monitor.alsa.reserve-device = disabled
}
}
Disabling seat monitoring via logind in the BlueZ monitor:
* Old format:
.. code-block:: lua
:caption: ~/.config/wireplumber/bluetooth.lua.d/80-disable-logind.lua
bluez_monitor.properties["with-logind"] = false
* New format:
.. code-block::
:caption: ~/.config/wireplumber/wireplumber.conf.d/80-disable-logind.conf
wireplumber.profiles = {
main = {
monitor.bluez.seat-monitoring = disabled
}
}
See also :ref:`config_modifying_configuration_features`.
Linking policy configuration (moved to settings and renamed):
* Old format:
.. code-block:: lua
:caption: ~/.config/wireplumber/policy.lua.d/80-policy.lua
default_policy.policy = {
["move"] = false,
["follow"] = false,
}
* New format:
.. code-block::
:caption: ~/.config/wireplumber/wireplumber.conf.d/80-policy.conf
wireplumber.settings = {
linking.allow-moving-streams = false
linking.follow-default-target = false
}
See also :ref:`config_modifying_configuration_settings` and remember that
settings can also be changed at runtime via :command:`wpctl`.
Loading custom scripts
~~~~~~~~~~~~~~~~~~~~~~
If you had custom Lua scripts that were loaded by the old configuration file,
you need to port the old ``load_script()`` commands into component descriptions.
For example, if you had a script that was loaded like this:
.. code-block:: lua
:caption: ~/.config/wireplumber/main.lua.d/99-my-script.lua
load_script("my-script.lua")
You should now create a new component description in the configuration file
and also make sure to require it in the profile:
.. code-block::
:caption: ~/.config/wireplumber/wireplumber.conf.d/99-my-script.conf
wireplumber.components = [
{
name = my-script.lua, type = script/lua
provides = custom.my-script
}
]
wireplumber.profiles = {
main = {
custom.my-script = required
}
}
.. attention::
Another important thing to mention here is the location of custom scripts. In
0.4, scripts could be loaded in configuration locations such as
``~/.config/wireplumber/scripts/`` and ``/etc/wireplumber/scripts/``. In 0.5,
the XDG base directory specification for data files is honored, so the new
location for custom scripts is ``~/.local/share/wireplumber/scripts/`` and
anything else specified in ``$XDG_DATA_HOME`` and ``$XDG_DATA_DIRS``. See
:ref:`daemon_file_locations` for more information.

View file

@ -0,0 +1,365 @@
.. _config_modifying_configuration:
Modifying configuration
=======================
WirePlumber is a heavily modular daemon that depends on its configuration
file to operate. If you were to start WirePlumber with an empty configuration
file, it would fail to start. This is why the default configuration file is
installed in the system-wide application data directory, which prevents it from
being modified by the user.
It is technically possible, if you wish, to copy the default configuration
file in one of the other :ref:`configuration search locations <config_locations>`
and modify it. However, this is **not recommended**, as it may lead to issues
when upgrading WirePlumber.
In the :ref:`Configuration file <config_conf_file>` section, we saw that
configuration files support fragments, which allow you to override or extend the
default configuration. This is the recommended way to modify the configuration.
Working with fragments
----------------------
The easiest way to add :ref:`fragments <config_conf_file_fragments>` to
modify the default configuration is to create a directory called
``~/.config/wireplumber/wireplumber.conf.d`` and place your fragments there.
All fragment files need to have the ``.conf`` extension and must be valid
SPA-JSON files. The fragments are loaded in alphanumerical order, so you can
control the order in which they are loaded by naming them accordingly. It is
recommended to use a numeric prefix for the file names, e.g.
``10-my-fragment.conf``, ``20-my-other-fragment.conf``, etc., so that you can
easily control the order in which they are loaded.
.. _config_modifying_configuration_features:
Customizing the loaded features
-------------------------------
As seen in the :ref:`Components & Profiles <config_components_and_profiles>`
section, the list of components that are loaded can be customized by enabling or
disabling :ref:`well-known features <config_features>` in the profile that is
in use by WirePlumber.
The default profile of WirePlumber is called ``main``, so a fragment that
enables or disables a specific feature in the default configuration should look
like this:
.. code-block::
wireplumber.profiles = {
main = {
some.feature.name = disabled
some.other.feature.name = required
}
}
Remember that features can be ``required``, ``optional`` or ``disabled``. See
the :ref:`Components & Profiles <config_components_and_profiles>` for details.
.. _config_modifying_configuration_settings:
Modifying dynamic options ("settings")
--------------------------------------
As seen in the :ref:`Configuration option types <config_configuration_option_types>`
section, WirePlumber components can be partly configured with dynamic options
(referred to as "settings"). These settings can either be modified permanently
in the configuration file, or they can be modified at runtime using the
``wpctl`` command-line tool.
To modify a setting in the configuration file, you can use a fragment like this:
.. code-block::
wireplumber.settings = {
some.setting.name = value
}
For example, setting the ``device.routes.default-sink-volume`` setting to
``0.5`` can be done like this:
.. code-block::
wireplumber.settings = {
device.routes.default-sink-volume = 0.5
}
.. note::
Since the configuration file is only read at startup, this will only take
effect after restarting WirePlumber.
If you would prefer to change the setting at runtime, you can use ``wpctl`` as
follows:
.. code-block:: bash
$ wpctl settings device.routes.default-sink-volume 0.5
Updated setting 'device.routes.default-sink-volume' to: 0.5
The above command changes the setting immediately, but for the current
WirePlumber instance only. If you want the setting to be applied every time
WirePlumber is started, you may also use the ``--save`` option:
.. code-block:: bash
$ wpctl settings --save device.routes.default-sink-volume 0.5
Updated and saved setting 'device.routes.default-sink-volume' to: 0.5
This will save the setting persistently in WirePlumber's state storage.
Even though it is not in the configuration file, this saved value will be
applied automatically when WirePlumber is started.
.. attention::
When a setting's value is saved, it will override the value from the
configuration file. Changing the value in the configuration file will
have no effect until the saved value is removed. Use the ``--delete``
switch in ``wpctl`` to remove a saved value (see below).
With ``wpctl``, it is also possible to restore a setting to its default value
(taken from the schema), by using the ``--reset`` option. For example, to reset
the ``device.routes.default-sink-volume`` setting, the following command can be
used:
.. code-block:: bash
$ wpctl settings --reset device.routes.default-sink-volume
Reset setting 'device.routes.default-sink-volume' successfully
$ wpctl settings device.routes.default-sink-volume
Value: 0.064 (Saved: 0.5)
Note that the ``--reset`` option will only reset the setting to its default
value, but it will not remove the saved value from the state file. If you want
to remove the saved value, you can use the ``--delete`` option:
.. code-block:: bash
$ wpctl settings --delete device.routes.default-sink-volume
Deleted setting 'device.routes.default-sink-volume' successfully
$ wpctl settings device.routes.default-sink-volume
Value: 0.064
A list of all the available settings can be found in the :ref:`config_settings`
section.
.. _config_modifying_configuration_static:
Modifying static options
------------------------
Static options always live in their own section of the configuration file.
Sections can be of two types: either a JSON object or a JSON array.
When dealing with a **JSON object**, you can add or modify a key-value pair by
creating a fragment like this:
.. code-block::
wireplumber.some-section = {
some.option = new_value
}
This is similar to what we have seen also above for modifying profile features
and settings (because both are JSON objects).
When dealing with a **JSON array**, any values that you define in a fragment
will be appended to the array. For example, to add a new rule to the
``monitor.alsa.rules`` array, you can create a fragment like this:
.. code-block::
monitor.alsa.rules = [
{
matches = [
{
device.name = "~alsa_card.*"
}
]
actions = {
update-props = {
api.alsa.use-ucm = false
}
}
}
]
This will add a new rule to the ``monitor.alsa.rules`` array, which will
be evaluated **after** all other rules that were parsed before. This is where
the order in which fragments are loaded actually matters.
If you don't want to append a new rule, but rather override the entire array
with a new one, you can do so by using the ``override.`` prefix on the array
name:
.. code-block::
override.monitor.alsa.rules = [
{
matches = [
{
device.name = "~alsa_card.*"
}
]
actions = {
update-props = {
api.alsa.use-ucm = false
}
}
}
]
This will now replace the entire ``monitor.alsa.rules`` array with this new one.
.. attention::
If you want to remove a rule from the array, you will need to override the
whole array with a new one that does not contain the rule you want to remove.
There is no way to remove a specific element from an array using fragments.
Another thing worth remembering here is that this behavior of appending values
to arrays also works in arrays that are nested inside other arrays or objects.
For example, consider this fragment:
.. code-block::
monitor.bluez.properties = {
bluez5.codecs = [ sbc_xq aac ldac ]
}
If this is the first time that the ``bluez5.codecs`` array is being defined, it
will be created with the given values. If it already exists, the given values
will be appended to the existing array. If you want to make sure that this
fragment will override the existing array, you need to use the ``override.``
prefix on the array name:
.. code-block::
monitor.bluez.properties = {
override.bluez5.codecs = [ sbc_xq aac ldac ]
}
The ``override.`` prefix may also be used in JSON object keys, to override the
entire object with a new one. For example, to override the entire
``monitor.bluez.properties`` object, you can use a fragment like this:
.. code-block::
override.monitor.bluez.properties = {
bluez5.codecs = [ sbc_xq aac ldac ]
}
Here, the entire ``monitor.bluez.properties`` object will be replaced with the
new one, and all previous key-value pairs configured will be discarded. This
also means that the ``bluez5.codecs`` array will be replaced with the new one
and does not require the ``override.`` prefix.
.. note::
Even though WirePlumber uses PipeWire's syntax for configuration files, the
``override.`` prefix is a WirePlumber extension and does not work in
PipeWire.
.. _config_modifying_configuration_rules:
Working with rules
------------------
Some of the static option sections in the configuration file are used to define
rules that are evaluated by WirePlumber at runtime. These rules are typically
used to match objects and perform actions on them. For example, the
``monitor.alsa.rules`` section is used to define rules that are evaluated by
the ALSA monitor to match ALSA devices and update their properties.
The syntax of these rules is the same as the syntax of
`PipeWire's rules <https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PipeWire#rules>`_.
A rule is always a JSON object with two keys: ``matches`` and ``actions``. The
``matches`` key is used to define the conditions that need to be met for the
rule to be evaluated as true, and the ``actions`` key is used to define the
actions that are performed when the rule is evaluated as true.
The ``matches`` key is always a JSON array of objects, where each object
defines a condition that needs to be met. Each condition is a list of key-value
pairs, where the key is the name of the property that is being matched, and the
value is the value that the property needs to have. Within a condition, all
the key-value pairs are combined with a logical AND, and all the conditions in
the ``matches`` array are combined with a logical OR.
The ``actions`` key is always a JSON object, where each key-value pair defines
an action that is performed when the rule is evaluated as true. The action
name is specific to the rule and is defined by the rule's documentation, but
most frequently you will see the ``update-props`` action, which is used to
update the properties of the matched object.
For example:
.. code-block::
some.theoretical.rules = [
{
matches = [
{
object.name = "my_object"
object.profile.name = "my_profile"
}
{
object.name = "other_object"
}
]
actions = {
update-props = {
object.tag = "matched_by_my_rule"
}
}
}
]
This rule is equivalent to the following expression:
.. code-block:: python
if (properties["object.name"] == "my_object" and properties["object.profile.name"] == "my_profile") or (properties["object.name"] == "other_object"):
properties["object.tag"] = "matched_by_my_rule"
In the ``matches`` array, it is also possible to use regular expressions to match
property values. For example, to match all nodes with a name that starts with
``my_``, you can use the following condition:
.. code-block::
matches = [
{
node.name = "~my_.*"
}
]
The ``~`` character signifies that the value is a regular expression. The exact
syntax of the regular expressions is the POSIX extended regex syntax, as
described in the `regex (7)` man page.
In addition to regular expressions, you may also use the ``!`` character to
negate a condition. For example, to match all nodes with a name that does not
start with ``my_``, you can use the following condition:
.. code-block::
matches = [
{
node.name = "!~my_.*"
}
]
The ``!`` character can be used with or without a regular expression. For
example, to match all nodes with a name that is not equal to ``my_node``,
you can use the following condition:
.. code-block::
matches = [
{
node.name = "!my_node"
}
]

View file

@ -0,0 +1,228 @@
.. _config_settings:
Well-known settings
===================
This section describes the settings that can be configured on WirePlumber.
Settings can be either configured statically in the configuration file
by setting them under the ``wireplumber.settings`` section, or they can be
configured dynamically at runtime by using metadata.
For more information on what "settings" are and how they work, refer to the
previous section: :ref:`config_configuration_option_types`.
.. describe:: device.restore-profile
When a device profile is changed manually (e.g. via pavucontrol), WirePlumber
stores the selected profile and restores it when the device appears again
(e.g. after a reboot). If this setting is disabled, WirePlumber will always
pick the best profile for the device based on profile priorities and
availability (or custom rules, if any).
:Default value: ``true``
.. describe:: device.restore-routes
When a device route is changed manually (e.g. via pavucontrol), WirePlumber
stores the selected route and restores it when the same profile is
selected for this device. If this setting is disabled, WirePlumber will
always pick the best route for this device profile based on route priorities
and availability (or custom rules, if any).
This setting also enables WirePlumber to restore properties of the device
route when the route is restored. This includes the volume levels of sources
and sinks, as well as the IEC958 codecs selected (for routes that support
encoded streams, such as HDMI).
:Default value: ``true``
.. describe:: device.routes.default-sink-volume
This option allows to set the default volume for sinks that are part of a
device route (e.g. ALSA PCM sinks). This is used when the route is restored
and the sink does not have a previously stored volume.
It is possible to override the value on a per-device basis with a property
(*not* a setting, so this would go into a configuration file) on the device
named ``device.routes.default-sink-volume``.
:Default value: ``0.4 ^ 3`` (40% on the cubic scale)
.. describe:: device.routes.default-source-volume
This option allows to set the default volume for sources that are part of a
device route (e.g. ALSA PCM sources). This is used when the route is restored
and the source does not have a previously stored volume.
It is possible to override the value on a per-device basis with a property
(*not* a setting, so this would go into a configuration file) on the device
named ``device.routes.default-source-volume``.
:Default value: ``1.0`` (100%)
.. describe:: linking.allow-moving-streams
This option allows moving streams by overriding their target via metadata.
When enabled, WirePlumber monitors the "default" metadata for changes in the
``target.object`` key of streams and if this key is set to a valid node name
(``node.name``) or serial (``object.serial``), the stream is moved to that
target node.
This is used by applications such as pavucontrol and is recommended for
compatibility with PulseAudio.
.. note::
On the metadata, the ``target.node`` key is also supported for
compatibility with older versions of PipeWire, but it is deprecated.
Please use the ``target.object`` key instead.
:Default value: ``true``
:See also: ``node.stream.restore-target``
.. describe:: linking.follow-default-target
When a stream was started with the ``target.object`` property, WirePlumber
normally links that stream to that target node and ignores the "default"
target for that direction. However, if this option is enabled, WirePlumber
will check if the designated target node *is* the "default" target and if so,
it will act as if the stream did not have that property.
In practice, this means that if the "default" target changes at runtime,
the stream will be moved to the new "default" target.
This is what Pulseaudio does and is implemented here for compatibility
with some applications that do start with a ``target.object`` property
set to the "default" target and expect the stream to be moved when the
"default" target changes.
Note that this logic is only applied on client (i.e. application) streams
and *not* on filters.
:Default value: ``true``
.. describe:: linking.pause-playback
When an audio sink is removed, pause media players that have streams
playing to it. Pausing is done via MPRIS interface.
:Default value: ``true``
.. describe:: node.features.audio.no-dsp
When this option is set to ``true``, audio nodes will not be configured
in dsp mode, meaning that their channels will *not* be split into separate
ports and that the audio data will *not* be converted to the float 32 format
(F32P). Instead, devices will be configured in passthrough mode and streams
will be configured in convert mode, so that their audio data is converted
directly to the format that the device is expecting.
This may be useful if you are trying to minimize audio processing for an
embedded system, but it is not recommended for general use.
.. warning::
This option **will break** compatibility with JACK applications
and may also break certain patchbay applications. Do not enable, unless
you understand what you are doing.
:Default value: ``false``
.. describe:: node.features.audio.monitor-ports
This enables the creation of "monitor" ports for audio nodes. Monitor ports
are created on nodes that have input ports (i.e. sinks and capture streams)
and allow monitoring of the audio data that is being sent to the node.
This is mostly used by monitoring applications, such as pavucontrol.
:Default value: ``true``
.. describe:: node.features.audio.control-port
This enables the creation of a "control" port for audio nodes. Control ports
allow sending MIDI data to the node, allowing for control of certain node's
parameters (such as volume) via external controllers.
:Default value: ``false``
.. describe:: node.stream.restore-props
WirePlumber stores stream parameters such as volume and mute status for each
client (i.e. application) stream. If this setting is enabled, WirePlumber
will restore the previously stored stream parameters when the stream is
activated. If it is disabled, stream parameters will be initialized to their
default values.
:Default value: ``true``
.. describe:: node.stream.restore-target
When a client (i.e. application) stream is manually moved to a different
target node (e.g. via pavucontrol), the target node is stored by WirePlumber.
If this setting is enabled, WirePlumber will restore the previously stored
target node when the stream is activated.
.. note::
This does not restore manual links made by patchbay applications. This
is only meant to restore the ``target.object`` property in the "default"
metadata, which is manipulated by applications such as pavucontrol when
a stream is moved to a different target.
:Default value: ``true``
:See also: ``linking.allow-moving-streams``
.. describe:: node.stream.default-playback-volume
The default volume for playback streams to be applied when the stream is
activated. This is only applied when ``node.stream.restore-props`` is
``true`` and the stream does not have a previously stored volume.
:Default value: ``1.0``
:Range: ``0.0`` to ``1.0``
.. describe:: node.stream.default-capture-volume
The default volume for capture streams to be applied when the stream is
activated. This is only applied when ``node.stream.restore-props`` is
``true`` and the stream does not have a previously stored volume.
:Default value: ``1.0``
:Range: ``0.0`` to ``1.0``
.. describe:: node.filter.forward-format
When a "filter" pair of nodes (such as echo-cancel or filter-chain) is
linked to a device node that has a different channel map than the filter
nodes, this option allows the channel map of the filter nodes to be changed
to match the channel map of the device node. The change is applied to both
ends of the "filter", so that any streams linked to the filter are also
reconfigured to match the target channel map.
This is useful, for instance, to make sure that an application will be
properly configured to output surround audio to a surround device, even
when going through a filter that was not explicitly configured to have
a surround channel map.
:Default value: ``false``
.. describe:: node.restore-default-targets
This setting enables WirePlumber to store and restore the "default" source
and sink targets of the graph. In PulseAudio terminology, this is also known
as the "fallback" source and sink.
When this setting is enabled, WirePlumber will store the "default" source
and sink targets when they are changed manually (e.g. via pavucontrol) and
restore them when the available nodes change or after a reload/restart.
It will also store a history of past selected "default" targets and restore
previously selected ones if the currently selected are not available.
If this is disabled, WirePlumber will pick the best available source
and sink targets based on their priorities, but it will also respect
manual user selections that are done at runtime - it will just not remember
them so that it can restore them at a later time.
:Default value: ``true``

View file

@ -1,4 +1,4 @@
.. _installing-wireplumber: .. _daemon_installing:
Installing WirePlumber Installing WirePlumber
====================== ======================
@ -8,8 +8,8 @@ Dependencies
In order to compile WirePlumber you will need: In order to compile WirePlumber you will need:
* GLib >= 2.62 * GLib >= 2.68
* PipeWire 0.3 (>= 0.3.43) * PipeWire >= 1.0
* Lua 5.3 or 5.4 * Lua 5.3 or 5.4
Lua is optional in the sense that if it is not found in the system, a bundled Lua is optional in the sense that if it is not found in the system, a bundled

View file

@ -0,0 +1,175 @@
.. _daemon_file_locations:
Locations of WirePlumber's files
================================
.. _config_locations:
Location of configuration files
-------------------------------
WirePlumber's default locations of its configuration files are the following,
in order of priority:
1. ``$XDG_CONFIG_HOME/wireplumber``
2. ``$XDG_CONFIG_DIRS/wireplumber``
3. ``$sysconfdir/wireplumber``
4. ``$XDG_DATA_DIRS/wireplumber``
5. ``$datadir/wireplumber``
Notes:
* ``$syscondir`` and ``$datadir`` refer to
`meson's directory options <https://mesonbuild.com/Builtin-options.html#directories>`_
and are hardcoded at build time
* ``$XDG_`` variables refer to the
`XDG Base Directory Specification <https://specifications.freedesktop.org/basedir-spec/latest/index.html>`_
It is recommended that user specific overrides are placed in
``$XDG_CONFIG_HOME/wireplumber``, while host-specific configuration is placed in
``$XDG_CONFIG_DIRS/wireplumber`` or ``$sysconfdir/wireplumber`` and
distribution-provided configuration is placed in ``$XDG_DATA_DIRS/wireplumber``
or ``$datadir/wireplumber``.
At runtime, WirePlumber will seek out the directory with the highest priority
that contains the required configuration file. This setup allows a user or
system administrator to effortlessly override the configuration files provided
by the distribution. They can achieve this by placing a file with an identical
name in a higher priority directory.
It is also possible to override the configuration directory by setting the
``WIREPLUMBER_CONFIG_DIR`` environment variable:
.. code-block:: bash
WIREPLUMBER_CONFIG_DIR=src/config wireplumber
``WIREPLUMBER_CONFIG_DIR`` supports listing multiple directories, using the
standard path list separator ``:``. If multiple directories are specified,
the first one has the highest priority and the last one has the lowest.
.. note::
When the configuration directory is overridden with
``WIREPLUMBER_CONFIG_DIR``, the default locations are ignored and
configuration files are *only* looked up in the directories specified by this
variable.
.. _config_locations_fragments:
Configuration fragments
^^^^^^^^^^^^^^^^^^^^^^^
WirePlumber also supports configuration fragments. These are configuration files
that are loaded in addition to the main configuration file, allowing to
override or extend the configuration without having to copy the whole file.
See also the :ref:`config_conf_file_fragments` section for semantics.
Configuration fragments are always loaded from subdirectories of the main search
directories that have the same name as the configuration file, with the ``.d``
suffix appended. For example, if WirePlumber loads ``wireplumber.conf``, it will
also load ``wireplumber.conf.d/*.conf``. Note also that the fragment files need
to have the ``.conf`` suffix.
When WirePlumber loads a configuration file from the default locations, it will
also load all configuration fragments that are present in all of the default
locations, but following the reverse order of priority. This allows
configuration fragments that are installed in more system-wide locations to be
overridden by the system administrator or the users.
For example, assuming WirePlumber loads ``wireplumber.conf``, from any of the
search locations, it will also locate and load the following fragments, in this
order:
1. ``$datadir/wireplumber/wireplumber.conf.d/*.conf``
2. ``$XDG_DATA_DIRS/wireplumber/wireplumber.conf.d/*.conf``
3. ``$sysconfdir/wireplumber/wireplumber.conf.d/*.conf``
4. ``$XDG_CONFIG_DIRS/wireplumber/wireplumber.conf.d/*.conf``
5. ``$XDG_CONFIG_HOME/wireplumber/wireplumber.conf.d/*.conf``
Within each search location that contains fragments, the individual fragment
files are opened in alphanumerical order. This can be important to know, because
the parsing order matters in merging. See :ref:`config_conf_file_fragments`
.. note::
When ``WIREPLUMBER_CONFIG_DIR`` is set, the default locations are ignored and
fragment files are *only* looked up in the directories specified by this
variable.
.. _config_locations_scripts:
Location of scripts
-------------------
WirePlumber's default locations of its data files are the following,
in order of priority:
1. ``$XDG_DATA_HOME/wireplumber``
2. ``$XDG_DATA_DIRS/wireplumber``
3. ``$datadir/wireplumber``
At runtime, WirePlumber will search the directories for the highest-priority
directory to contain the needed data file.
Scripts are a specific kind of "data" files and are expected to be located
within a ``scripts`` subdirectory in the above data search locations. The "data"
directory is a somewhat more generic path that may be used for other kinds of
data files in the future.
It is also possible to override the data directory by setting the
``WIREPLUMBER_DATA_DIR`` environment variable:
.. code-block:: bash
WIREPLUMBER_DATA_DIR=src wireplumber
As with the default data directories, script files in particular are expected
to be located within a ``scripts`` subdirectory, so in the above example the
scripts would actually reside in ``src/scripts``.
``WIREPLUMBER_DATA_DIR`` supports listing multiple directories, using the
standard path list separator ``:``. If multiple directories are specified,
the first one has the highest priority and the last one has the lowest.
.. note::
When ``WIREPLUMBER_DATA_DIR`` is set, the default locations are ignored and
scripts are *only* looked up in the directories specified by this variable.
Location of modules
-------------------
WirePlumber modules
^^^^^^^^^^^^^^^^^^^
WirePlumber's default location of its modules is
``$libdir/wireplumber-$api_version``, where ``$libdir`` is set at compile time
by the build system. Typically, it ends up being ``/usr/lib/wireplumber-0.5``
(or ``/usr/lib/<arch-triplet>/wireplumber-0.5`` on multiarch systems)
It is possible to override this directory at runtime by setting the
``WIREPLUMBER_MODULE_DIR`` environment variable:
.. code-block:: bash
WIREPLUMBER_MODULE_DIR=build/modules wireplumber
``WIREPLUMBER_MODULE_DIR`` supports listing multiple directories, using the
standard path list separator ``:``. If multiple directories are specified, the
first one has the highest priority and the last one has the lowest.
.. note::
When ``WIREPLUMBER_MODULE_DIR`` is set, the default locations are ignored and
scripts are *only* looked up in the directories specified by this variable.
PipeWire and SPA modules
^^^^^^^^^^^^^^^^^^^^^^^^
PipeWire and SPA modules are not loaded from the same location as WirePlumber's
modules. They are loaded from the location that PipeWire loads them.
It is also possible to override these locations by using environment variables:
``SPA_PLUGIN_DIR`` and ``PIPEWIRE_MODULE_DIR``. For more details, refer to
PipeWire's documentation.

248
docs/rst/daemon/logging.rst Normal file
View file

@ -0,0 +1,248 @@
.. _daemon_logging:
Debug Logging
=============
WirePlumber is instrumented with log messages in its entire codebase. These
messages are categorized based on two heuristics: the log topic and the log
level.
The log topic is a string that identifies which component of the code this
message is coming from. Well-known topics include:
- **wireplumber**: messages from the wireplumber daemon
- **wp-***: messages from libwireplumber
- **wp-core**: messages from *WpCore*
- **wp-proxy**: messages from *WpProxy*
- ... and so on ...
- **m-***: messages from wireplumber modules
- **m-default-profile**: messages from *libwireplumber-module-default-profile*
- **m-default-routes**: messages from *libwireplumber-module-default-routes*
- ... and so on ...
- **s-***: messages from scripts
- **s-linking**: messages from the *linking/\*.lua* scripts
- **s-default-nodes**: messages from the *default-nodes/\*.lua* scripts
- ... and so on ...
- **pw.***: messages from libpipewire
- **spa.***: messages from spa plugins
- **mod.***: messages from libpipewire modules
- **conn.***: messages to debug the pipewire socket connection
The log level is a value that designates the importance of the message.
The levels that exist in WirePlumber are the following:
- ``F``: *Fatal errors*. These messages represent situations where execution
of the program cannot continue. In the extremely unlikely case that
they appear, these messages also cause the process to be terminated.
- ``E``: *Critical warnings* (or "errors" in the PipeWire terminology).
These messages represent situations where something unexpected has happened
and someone with understanding of the code should probably take a look at it.
These situations are usually programming mistakes or omissions.
This does not necessarily mean that the program is not functioning correctly.
It may mean, though, that the specific part of the program that logged the
message (the plugin, subsystem, ...) may not work optimally.
- ``W``: *Warnings*. These messages represent situations where something has
gone unintentionally wrong, but it was not totally unexpected. The situation
is recovered and the program can continue. In many cases, this warning may
mean that there is something wrong with the configuration or the environment
and may need attention from the user.
- ``N``: *Notices*. These are important messages that the user should notice,
like warnings, but they do not necessarily mean a bad situation.
- ``I``: *Informational messages*. These messages provide information about
the internal operations of the program.
- ``D``: *Debug messages*. These messages provide details about the
internal operations of the program, which can be useful for debugging.
- ``T``: *Traces*. These messages provide very verbose printouts of internal
operations and data that affects these operations. These can be useful for
debugging as well, but it may be best to be enabled only for the topic(s)
that are intended to be debugged, as they can be very big in volume.
By default, WirePlumber logs only messages from levels ``F``, ``E``, ``W``
and ``N``. These messages are printed on the standard error (``stderr``) stream,
or they are logged to the systemd journal, if WirePlumber was started as a
systemd service.
The ``WIREPLUMBER_DEBUG`` environment variable can be used to change which
topics and levels are enabled. The generic syntax is:
.. code::
WIREPLUMBER_DEBUG=[<topic pattern>:]<level>,...,
This is a comma-separated list of topics to enable, paired with a level for
each topic.
``<level>`` can be one of ``FEWNIDT`` or a numerical log level as listed below.
0. fatal errors (``F``)
1. critical warnings (``E``)
2. warnings and notices (``W`` & ``N``)
3. informational messages (``I``)
4. debug messages (``D``)
5. trace messages (``T``)
Each level always includes messages from the previous levels, so for instance
enabling level ``3`` (or ``I``) will also enable messages from levels ``2``
and ``1`` (``N``, ``W``, ``E`` and ``F``)
``<topic pattern>`` is an *optional* description of one or more topics.
This supports
`glob style patterns <https://developer-old.gnome.org/glib/stable/glib-Glob-style-pattern-matching.html>`_
containing ``*`` and ``?``.
If a ``<topic pattern>`` is not specified, then the given ``<level>`` is
considered to be the global log level, which applies to all topics that have
no explicit level specified.
Changing log level at runtime
-----------------------------
The debug log level can be changed at runtime using ``wpctl``:
.. code::
wpctl set-log-level D # enable debug logging for Wireplumber
wpctl set-log-level - # restore default logging for Wireplumber
wpctl set-log-level 0 4 # enable debug logging for Pipewire daemon
wpctl set-log-level 0 - # restore default logging for Pipewire daemon
Equivalently, it is also possible to adjust the logging by setting
``log.level`` in the ``settings`` metadata:
.. code::
pw-metadata -n settings <ID> log.level "D" # WirePlumber logging
pw-metadata -n settings 0 log.level 4 # PipeWire daemon logging
Above, ``<ID>`` should be replaced by the WirePlumber daemon client ID.
Note that PipeWire daemon log levels must be specified by numbers, not
letter codes.
Changing log level via static configuration
-------------------------------------------
If you need to capture logs from WirePlumber at startup or in other circumstances
where changing the level at runtime or setting an environment variable is not
feasible, then you may also set the log level in the configuration file.
The log level changes via the ``log.level`` key in the ``context.properties``
section:
.. code::
context.properties = {
log.level = "D"
}
You may use the same syntax as in ``WIREPLUMBER_DEBUG`` to describe the exact
logging you want to achieve. For instance, to log debug messages from all
scripts and informational messages from everywhere else:
.. code::
context.properties = {
log.level = "I,s-*:D"
}
The easiest way to configure this is to drop a
:ref:`fragment file <config_conf_file_fragments>` that contains just this.
.. code-block:: bash
$ mkdir -p ~/.config/wireplumber/wireplumber.conf.d
$ echo 'context.properties = { log.level = "D" }' > ~/.config/wireplumber/wireplumber.conf.d/log.conf
See also :ref:`config_modifying_configuration`
Examples
--------
Show *all* messages:
.. code::
WIREPLUMBER_DEBUG=T
Show all messages up to the *debug* level (F, E, W, N, I & D), excluding *trace*:
.. code::
WIREPLUMBER_DEBUG=D
Show all messages up to the *notice* level (F, E, W & N),
excluding *info*, *debug* & *trace*
(this is also the default when ``WIREPLUMBER_DEBUG`` is omitted):
.. code::
WIREPLUMBER_DEBUG=2
Show all messages from the wireplumber library (including traces), but only
up to informational messages from other topics:
.. code::
WIREPLUMBER_DEBUG=I,wp-*:T
Show debug messages from ``wp-registry``, libpipewire and all modules, keeping
all other topics up to the *notice* level.
.. code::
WIREPLUMBER_DEBUG=2,wp-registry:4,pw.*:4,m-*:4
Relationship with the GLib log handler & G_MESSAGES_DEBUG
---------------------------------------------------------
Older versions of WirePlumber used to use ``G_MESSAGES_DEBUG`` to control their
log output, which is the environment variable that affects GLib's default
log handler.
As of WirePlumber 0.3, ``G_MESSAGES_DEBUG`` is no longer used, since
libwireplumber replaces the default log handler.
If you are writing your own application based on libwireplumber, you can choose
if you want to replace this log handler using the flags passed to
:c:func:`wp_init`.
Relationship with the PipeWire log handler & PIPEWIRE_DEBUG
-----------------------------------------------------------
libpipewire uses the ``PIPEWIRE_DEBUG`` environment variable, with a similar syntax.
WirePlumber replaces the log handler of libpipewire with its own, rendering
``PIPEWIRE_DEBUG`` useless. Instead, you should use ``WIREPLUMBER_DEBUG``.
All the log topics that apply to libpipewire and its modules / plugins work
the same in ``WIREPLUMBER_DEBUG``.
If you are writing your own application based on libwireplumber, you can choose
if you want to replace this log handler using the flags passed to
:c:func:`wp_init`.
Mapping of PipeWire debug levels to WirePlumber
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PipeWire supports 5 levels of debug logging. WirePlumber, on the other hand,
supports 7 levels. Some levels seem common, but the terminology and the
semantics are slightly different. The following table shows how the various
levels are mapped:
============= =============== ========================
Numeric Level PipeWire WirePlumber
============= =============== ========================
0 no log ``F`` - Fatal Error
1 ``E`` - Error ``E`` - Critical Warning
2 ``W`` - Warning ``W`` - Warning,
``N`` - Notice
3 ``I`` - Info ``I`` - Info
4 ``D`` - Debug ``D`` - Debug
5 ``T`` - Trace ``T`` - Trace
============= =============== ========================

View file

@ -0,0 +1,11 @@
# you need to add here any files you add to the toc directory as well
sphinx_files += files(
'installing.rst',
'running.rst',
'configuration.rst',
'locations.rst',
'logging.rst',
'multi_instance.rst',
)
subdir('configuration')

View file

@ -0,0 +1,88 @@
.. _daemon_multi_instance:
Running multiple instances
==========================
WirePlumber has the ability to run either as a single instance daemon or as
multiple instances, meaning that there can be multiple processes, each one
doing a different task.
The most common use case for such a setup is to separate the graph orchestration
tasks from the device monitoring and object creation ones. This can be useful
for robustness and security reasons, as it allows restarting the device monitors
or running them in different security contexts without affecting the rest of the
session management functionality.
To achieve a multi-instance setup, WirePlumber can be started multiple times
with a different :ref:`profile<config_components_and_profiles>` loaded in each
instance. This can be achieved using the ``--profile`` command line option to
select the profile to load:
.. code-block:: console
$ wireplumber --profile=custom
When no particular profile is specified, the ``main`` profile is loaded.
For multi-instance configuration, the default ``wireplumber.conf`` specifies 4
profiles:
.. describe:: policy
This profile runs all the policy scripts, i.e. ones that monitor changes
in the graph and execute actions to link nodes, select default devices,
create new nodes or configure existing ones differently.
.. describe:: audio
The audio profile runs the ALSA and ALSA MIDI monitors, which make audio &
MIDI devices available to PipeWire.
.. describe:: bluetooth
The bluetooth profile runs the BlueZ and BlueZ MIDI monitors, which enable
Bluetooth audio & MIDI devices and other Bluetooth functionality tied to the
A2DP, HSP, HFP and BAP profiles, using BlueZ.
.. describe:: video-capture
The video-capture profile runs the V4L2 and libcamera monitors, which make
video capture devices, such as cameras and HDMI capture cards, available
to PipeWire.
.. note::
The ``main`` profile includes all the functionality of the ``policy``,
``audio``, ``video-capture`` and ``bluetooth`` profiles combined (i.e. it is
the default for a standard single instance configuration). You should never
load the ``main`` profile alongside these other 4 profiles, as their
functionality will conflict.
.. warning::
Always ensure that the instances you load serve a different purpose and they
do not conflict with each other. Conflicting components executed in parallel
will have undefined behavior.
Systemd integration
-------------------
To make this easier to work with, a template systemd unit is provided, which is
meant to be started with the name of the profile as a template argument:
.. code-block:: console
$ systemctl --user disable wireplumber # disable the "main" profile instance
$ systemctl --user enable wireplumber@policy
$ systemctl --user enable wireplumber@audio
$ systemctl --user enable wireplumber@video-capture
$ systemctl --user enable wireplumber@bluetooth
.. note::
In WirePlumber 0.4, the template argument was the name of the configuration
file to load, since profiles did not exist. In WirePlumber 0.5, the template
argument is the name of the profile and the configuration file is always
``wireplumber.conf``. To change the name of the configuration file you need
to craft custom systemd unit files and use the ``--config-file`` command line
option as needed.

View file

@ -1,4 +1,4 @@
.. _running-wireplumber-daemon: .. _daemon_running:
Running the WirePlumber daemon Running the WirePlumber daemon
============================== ==============================
@ -40,7 +40,7 @@ Synopsis:
$ meson -Dsession-managers="[ 'wireplumber' ]" build $ meson -Dsession-managers="[ 'wireplumber' ]" build
$ ninja -C build $ ninja -C build
$ make run $ make -C build run
Run independently or without installing Run independently or without installing
--------------------------------------- ---------------------------------------

View file

@ -0,0 +1,139 @@
.. _design_events_and_hooks:
Events and Hooks
================
Session management is all about reacting to events and taking necessary
actions. This is why WirePlumber's logic is all built on events and hooks.
Events
------
Events are objects that represent a change that has just happened on a PipeWire
object, or just a trigger for making a decision and potentially taking some
action.
Every event has a source, a subject and some properties, which include the
event type.
* The ``source`` is a reference to the GObject that created this event.
Typically, this is the ``WpStandardEventSource`` plugin.
* The ``subject`` is an *optional* reference to the object that this event
is about. For example, in a ``node-added`` event, the ``subject`` would be
a reference to the ``WpNode`` object that was just added. Some events,
especially those which are used only to trigger actions, do not have a
subject.
* The ``properties`` is a dictionary that contains information about the event,
including the event type, and also includes all the PipeWire properties of the
``subject``, if there is one.
* The ``event.type`` property describes the nature of the event, for example
``node-added`` or ``metadata-changed`` are some valid event types.
Every event also has a priority. Events with a higher priority are processed
before events with a lower priority. When two or more events have the same
priority, they are processed in a first-in-first-out manner. This logic
is defined in the *event dispatcher*.
Events are short-lived objects. They are created at the time that something is
happening and they are destroyed after they get processed. Processing an event
means executing all the hooks that are associated with it. The next section
explains what hooks are and how they are associated with events.
Hooks
-----
Hooks are objects that represent a runnable action that needs to be executed
when a certain event is processed. Every hook, therefore, consists of a
function - synchronous or asynchronous - that can be executed. Additionally,
every hook has a means to associate itself with specific events. This is
normally done by declaring *interest* to specific event properties or
combinations of them.
There are two main types of hooks: ``SimpleEventHook`` and ``AsyncEventHook``.
* ``SimpleEventHook`` contains a single, synchronous function. As soon as this
function is executed, the hook is completed.
* ``AsyncEventHook`` contains multiple functions, combined together in a state
machine using ``WpTransition`` underneath. The hook is completed only after
the state machine reaches its final state and this can take any amount of time
necessary.
Every hook also has a name, which can be an arbitrary string of characters.
Additionally, it has two arrays of names, which declare dependencies between
this hook and others. One array is called ``before`` and the other is called
``after``. The hook names in the ``before`` array specify that this hook must
be executed *before* those other hooks. Similarly, the hook names in the
``after`` array specify that this hook must be executed *after* those other
hooks. Using this mechanism, it is possible to define the order in which
hooks will be executed, for a specific event.
Hooks are long-lived objects. They are created once, registered in the
*event dispatcher*, they are attached on events and detached after their
execution. They don't maintain any internal state, so the actions of the hook
depend solely on the event itself.
The Event Dispatcher
--------------------
The event dispatcher is a (per core) singleton object that processes all events
and also maintains a list of all the registered hooks. It has a method to
*push* events on it, which causes them to be scheduled for processing.
Scheduling of events and hooks
------------------------------
The main idea and reasoning behind this architecture is to have everything
execute in a predefined order and always wait for an action to finish before
executing the next one.
Every event has a *priority* and every hook also has an order of execution that
derives from the inter-dependencies between hooks, which are defined with
``before`` and ``after`` (see above). When an event is pushed on the dispatcher,
the dispatcher goes through all the registered hooks and checks which hooks are
configured to run on this event (their event interest matches the event).
It then makes a list of them, sorted by their order of execution, and stores it
on the event. The event is then added on the dispatcher's list of events, which
is sorted by priority.
For example::
List of events
| event1 (prio 99) -> hook1, hook2, hook3
| event2 (prio 50) -> hook5, hook2, hook4
v
The dispatcher has an internal ``GSource`` that is registered with
``G_PRIORITY_HIGH_IDLE`` priority. When there is at least one event in the
list of events, the source is dispatched. Every time it gets dispatched,
it takes the top-most event (the highest priority one) and executes the highest
priority hook in that event. If the hook executes synchronously, it then takes
the next hook and continues until there are no more hooks on this event;
then it goes to the next event, and so on. If the hook, however, executes
asynchronously, processing stops until the hook finishes; after finishing,
processing resumes like before.
It is important to notice here that the list of events may be modified while
events are getting processed. For example, a device is added; that's a
``device-added`` event. Then a hook is executed to set the profile. That creates
nodes, so a couple of ``node-added`` events... But there is also another hook to
set the route, which was attached on the ``device-added`` event for the device.
Suppose that we give the ``node-added`` events lower priority than the
``device-added`` events, then the ``set-route`` hook will execute right after
the ``set-profile`` and before any ``node-added`` events are processed.
Visually, with sample priorities::
List of events
| "device-added" (prio 20) -> set-profile, set-route
| "node-added" (prio 10) -> restore-stream, create-session-item
v
Obviously, there can also be a case where a newly added event has higher
priority than the event that was being processed before. In that case,
processing the hooks of the original event is stopped until all the hooks from
the higher priority event have been processed. For example, a capture stream
node being added may trigger the "bluetooth autoswitch" hook, which will then
change the profile of a device. Changing the profile also has to trigger setting
a new route and also handling the new device nodes, creating session items for
them... After all this is done, processing the original capture stream
``node-added`` event can continue.

View file

@ -0,0 +1,6 @@
# you need to add here any files you add to the toc directory as well
sphinx_files += files(
'understanding_session_management.rst',
'understanding_wireplumber.rst',
'events_and_hooks.rst',
)

View file

@ -0,0 +1,105 @@
.. _design_understanding_session_management:
Understanding Session Management
================================
The PipeWire session manager is a tool that is tasked to do a lot of things.
Many people understand the term "session manager" as a tool that is responsible
for managing links between nodes, but that is only one of many tasks. To
understand the entirety of its operation, we need to discuss how PipeWire works,
first.
When PipeWire starts, it loads a set of modules that are defined in its
configuration file. These modules provide functionality to PipeWire, otherwise
it is just an empty process that does nothing. Under normal circumstances,
the modules that are loaded on PipeWire's startup contain object *factories*,
plus the native protocol module that allows inter-process communication.
Other than that, PipeWire does not really load or do anything else. This is
where session management begins.
Session management is basically about setting up PipeWire to do something
useful. This is achieved by utilizing PipeWire's exposed object factories to
create some useful objects, then work with their methods to modify and later
destroy them. Such objects include devices, nodes, ports, links and others.
This is a task that requires continuous monitoring and action taking, reacting
on a large number of different events that happen as the system is being used.
High-level areas of operation
-----------------------------
The session management logic, in WirePlumber, is divided into 6 different areas
of operation:
1. Device Enablement
^^^^^^^^^^^^^^^^^^^^
Enabling devices is a fundamental area of operation. It is achieved by using
the device monitor objects (or just "monitors"), which are typically
implemented as SPA plugins in PipeWire, but they are loaded by WirePlumber.
Their task is to discover available media devices and create objects in PipeWire
that offer a way to interact with them.
Well-known monitors include:
- The ALSA monitor, which enables audio devices
- The ALSA MIDI monitor, which enables MIDI devices
- The libcamera monitor, which enables cameras
- The Video4Linux2 (V4L2) monitor, which also enables cameras, but also
other video capture devices through the V4L2 Linux API
- The BlueZ monitor, which enables bluetooth audio devices
2. Device Configuration
^^^^^^^^^^^^^^^^^^^^^^^
Most devices expose complex functionality, from the computer's perspective, that
needs to be managed in order to provide a simple and smooth user experience.
For that reason, for example, audio devices are organized into *profiles* and
*routes*, which allow setting them up to serve a specific use case. These
need to be configured and managed by the session manager.
3. Client Access Control
^^^^^^^^^^^^^^^^^^^^^^^^
When client applications connect to PipeWire, they need to obtain permissions
in order to be able to access the objects exposed by PipeWire and interact
with them. In some circumstances and configurations, the session manager is also
tasked with deciding which permissions should be granted to each client.
4. Node Configuration
^^^^^^^^^^^^^^^^^^^^^
Nodes are the fundamental elements of media processing. They are typically
created either by the device monitors or by client applications. When they are
created, they are in a state where they cannot be linked. Linking them requires
some configuration, such as configuring the media format and subsequently
the number and the type of ports that should be exposed. Additionally, some
properties and metadata related to the node might need to be set according to
user preferences. All of this is taken care of by the session manager.
5. Link Management
^^^^^^^^^^^^^^^^^^
When nodes are finally ready to use, the session manager is also tasked to
decide how they should be linked together in order for media to flow though.
For instance, an audio playback stream node most likely needs to be linked to
the default audio output device node. The session manager then also needs to
create all these links and monitor all conditions that may affect them so that
dynamic re-linking is possible in case something changes
(ex. if a device disconnects). In some cases, device and node configuration
may also need to change as a result of links being created or destroyed.
6. Metadata Management
^^^^^^^^^^^^^^^^^^^^^^
While in operation, PipeWire and WirePlumber both store some additional
properties about objects and their operation in storage that lives outside
these objects. These properties are referred to as "metadata" and they are
stored in "metadata objects". This metadata can be changed externally by tools
such as `pw-metadata`, but also others.
In some circumstances, this metadata needs to interact with logic inside
the session manager. Most notably, selecting the default audio and video inputs
and outputs is done by setting metadata. The session manager then needs to
validate this information, store it and restore it on the next restart, but also
ensure that the default inputs and outputs stay valid and reasonable when
devices are plugged and unplugged dynamically.

View file

@ -0,0 +1,101 @@
.. _design_understanding_wireplumber:
Understanding WirePlumber
=========================
Knowing the fundamentals of session management, let's see here how WirePlumber
is structured.
The library
-----------
WirePlumber is built on top of the `libwireplumber` library, which provides
fundamental building blocks for expressing all the session management logic.
Libwireplumber, which is written in C and based on GObject, wraps the PipeWire
API and offers a higher level and more convenient API. While the WirePlumber
daemon implements the session management logic, the underlying library can also
be utilized outside the scope of the WirePlumber daemon. This allows for the
creation of external tools and GUIs that interact with PipeWire.
Being GObject based, the library is introspectable and can be used from any
language that supports `GObject Introspection <https://gi.readthedocs.io/en/latest/>`_.
The library is also available as a C API.
The object model
^^^^^^^^^^^^^^^^
The most fundamental code contained in the WirePlumber library is the object
model, i.e. its representation of PipeWire's objects.
PipeWire exposes several objects, such nodes and ports, via the IPC protocol
in a manner that is hard to interact with using standard object-oriented
principles, because it is asynchronous. For example, when an object is created,
its existence is announced over the protocol, but its properties are announced
later, on a secondary message. If something needs to react on this object
creation event, it typically needs to access the object's properties, so it
must wait until the properties have been sent. Doing this might sound simple,
and it is, but it becomes a tedious repetitive process to be doing this
everywhere instead of focusing on writing the actual event handling logic.
WirePlumber's library solves this by creating proxy objects that cache all the
information and updates received from PipeWire throughout each object's lifetime.
Then, it makes them available via the :ref:`WpObjectManager <obj_manager_api>`
API, which has the ability to wait until certain information (ex, the
properties) has been cached on each object before announcing it.
Session management utilities
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The library also provides a set of utilities that are useful for session
management. For example, it provides the :ref:`WpSessionItem <session_item_api>`
class that can be used to abstract a part of the graph with some logic attached
to it. It also provides the :ref:`Events & Hooks API <design_events_and_hooks>`,
which is a way to express event handling logic in a declarative way.
Misc utilities
^^^^^^^^^^^^^^
The library also provides a set of miscellaneous utilities that bridge the
PipeWire API with the GObject API, such as :ref:`WpProperties <properties_api>`,
:ref:`WpSpaPod <spa_pod_api>`, :ref:`WpSpaJson <spa_json_api>` and others.
These complement the object model and make it easier to interact with PipeWire
objects.
The daemon
----------
The WirePlumber daemon is implemented on top of the library API and its job is
to host components that implement the session management logic. By itself, it
doesn't do anything except load and activate these components. The actual logic
is implemented inside them.
Modular design ensures that it is possible to swap the implementation of
specific functionality without having to re-implement the rest of it, allowing
flexibility on target-sensitive parts, such as policy management and
making use of non-standard hardware.
There are several kinds of components, each with a different purpose. The two
main kinds are `modules` and `Lua scripts`. See also
:ref:`config_components_and_profiles`.
Modules
^^^^^^^
Modules extend the libwireplumber API for specific purposes, usually to provide
support code or to allow WirePlumber to communicate with external services (ex
D-Bus APIs). They either expose their own APIs via GObject signals (i.e. dynamic
APIs that do not require linking at compile time) or implement certain objects
through interfaces. They are written in C.
Lua scripts
^^^^^^^^^^^
Lua scripts implement most of the session management. The libwireplumber API is
made available in Lua with idiomatic bindings that make it very easy to write
session management logic.
Lua has been chosen because it is a very lightweight scripting language that is
suitable for embedding. It is also very easy to learn and use, as well as bind
it to C code. However, WirePlumber can be easily extended to support scripting
languages other than Lua. The entire Lua scripting system is implemented as a
module.

View file

@ -7,23 +7,54 @@ Table of Contents
:maxdepth: 2 :maxdepth: 2
:caption: The WirePlumber Daemon :caption: The WirePlumber Daemon
installing-wireplumber.rst daemon/installing.rst
running-wireplumber-daemon.rst daemon/running.rst
configuration.rst daemon/configuration.rst
daemon-logging.rst daemon/locations.rst
daemon/logging.rst
daemon/multi_instance.rst
.. toctree::
:maxdepth: 2
:caption: WirePlumber's Design
design/understanding_session_management.rst
design/understanding_wireplumber.rst
design/events_and_hooks.rst
.. toctree::
:maxdepth: 2
:caption: WirePlumber's Policies
policies/linking.rst
policies/smart_filters.rst
policies/software_dsp.rst
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: The WirePlumber Library :caption: The WirePlumber Library
c_api.rst library/c_api.rst
lua_api.rst
.. toctree::
:maxdepth: 2
:caption: Scripting
scripting/lua_api.rst
scripting/existing_scripts.rst
scripting/custom_scripts.rst
.. toctree::
:maxdepth: 2
:caption: Tools
tools/wpctl.rst
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Resources :caption: Resources
contributing.rst resources/contributing.rst
testing.rst resources/testing.rst
community.rst resources/community.rst
releases.rst resources/releases.rst

View file

@ -1,4 +1,4 @@
.. _library_root: .. _library_c_api:
C API Documentation C API Documentation
=================== ===================
@ -23,8 +23,8 @@ C API Documentation
c_api/link_api.rst c_api/link_api.rst
c_api/device_api.rst c_api/device_api.rst
c_api/client_api.rst c_api/client_api.rst
c_api/permission_manager_api.rst
c_api/metadata_api.rst c_api/metadata_api.rst
c_api/endpoint_api.rst
c_api/spa_device_api.rst c_api/spa_device_api.rst
c_api/impl_node_api.rst c_api/impl_node_api.rst
c_api/impl_module_api.rst c_api/impl_module_api.rst
@ -34,7 +34,10 @@ C API Documentation
c_api/spa_pod_api.rst c_api/spa_pod_api.rst
c_api/plugin_api.rst c_api/plugin_api.rst
c_api/component_loader_api.rst c_api/component_loader_api.rst
c_api/settings_api.rst
c_api/conf_api.rst
c_api/session_item_api.rst c_api/session_item_api.rst
c_api/si_interfaces_api.rst c_api/si_interfaces_api.rst
c_api/si_factory_api.rst c_api/si_factory_api.rst
c_api/state_api.rst c_api/state_api.rst
c_api/base_dirs_api.rst

View file

@ -0,0 +1,6 @@
.. _base_dirs_api:
Base Directories File Lookup
============================
.. doxygengroup:: wpbasedirs
:content-only:

View file

@ -7,14 +7,12 @@ Component Loader
digraph inheritance { digraph inheritance {
rankdir=LR; rankdir=LR;
GObject -> WpObject; GInterface -> WpComponentLoader;
WpObject -> WpPlugin;
WpPlugin -> WpComponentLoader;
} }
.. doxygenstruct:: WpComponentLoader .. doxygenstruct:: WpComponentLoader
.. doxygenstruct:: _WpComponentLoaderClass .. doxygenstruct:: _WpComponentLoaderInterface
.. doxygengroup:: wpcomponentloader .. doxygengroup:: wpcomponentloader
:content-only: :content-only:

View file

@ -0,0 +1,16 @@
.. _conf_api:
Static Configuration
====================
.. graphviz::
:align: center
digraph inheritance {
rankdir=LR;
GObject -> WpConf;
}
.. doxygenstruct:: WpConf
.. doxygengroup:: wpconf
:content-only:

View file

@ -7,7 +7,8 @@ Core
digraph inheritance { digraph inheritance {
rankdir=LR; rankdir=LR;
GObject -> WpCore; GObject -> WpObject;
WpObject -> WpCore;
} }
.. doxygenstruct:: WpCore .. doxygenstruct:: WpCore

View file

@ -1,10 +1,11 @@
# you need to add here any files you add to the api directory as well # you need to add here any files you add to the api directory as well
sphinx_files += files( sphinx_files += files(
'base_dirs_api.rst',
'client_api.rst', 'client_api.rst',
'component_loader_api.rst', 'component_loader_api.rst',
'conf_api.rst',
'core_api.rst', 'core_api.rst',
'device_api.rst', 'device_api.rst',
'endpoint_api.rst',
'global_proxy_api.rst', 'global_proxy_api.rst',
'impl_module_api.rst', 'impl_module_api.rst',
'impl_node_api.rst', 'impl_node_api.rst',
@ -17,11 +18,13 @@ sphinx_files += files(
'obj_manager_api.rst', 'obj_manager_api.rst',
'object_api.rst', 'object_api.rst',
'pipewire_object_api.rst', 'pipewire_object_api.rst',
'permission_manager_api.rst',
'plugin_api.rst', 'plugin_api.rst',
'port_api.rst', 'port_api.rst',
'properties_api.rst', 'properties_api.rst',
'proxy_api.rst', 'proxy_api.rst',
'session_item_api.rst', 'session_item_api.rst',
'settings_api.rst',
'si_factory_api.rst', 'si_factory_api.rst',
'si_interfaces_api.rst', 'si_interfaces_api.rst',
'spa_device_api.rst', 'spa_device_api.rst',

View file

@ -7,6 +7,7 @@ PipeWire Metadata
digraph inheritance { digraph inheritance {
rankdir=LR; rankdir=LR;
GBoxed -> WpMetadataItem
GObject -> WpObject; GObject -> WpObject;
WpObject -> WpProxy; WpObject -> WpProxy;
WpProxy -> WpGlobalProxy; WpProxy -> WpGlobalProxy;
@ -14,6 +15,8 @@ PipeWire Metadata
WpMetadata-> WpImplMetadata; WpMetadata-> WpImplMetadata;
} }
.. doxygenstruct:: WpMetadataItem
.. doxygenstruct:: WpMetadata .. doxygenstruct:: WpMetadata
.. doxygenstruct:: WpImplMetadata .. doxygenstruct:: WpImplMetadata

View file

@ -0,0 +1,17 @@
.. _permission_manager_api:
WpPermissionManager
===================
.. graphviz::
:align: center
digraph inheritance {
rankdir=LR;
GObject -> WpObject;
WpObject -> WpPermissionManager;
}
.. doxygenstruct:: WpPermissionManager
.. doxygengroup:: wppermissionmanager
:content-only:

View file

@ -0,0 +1,23 @@
.. _settings_api:
Settings
========
.. graphviz::
:align: center
digraph inheritance {
rankdir=LR;
GBoxed -> WpSettingsSpec;
GBoxed -> WpSettingsItem;
GObject -> WpObject;
WpObject -> WpSettings;
}
.. doxygenstruct:: WpSettingsSpec
.. doxygenstruct:: WpSettingsItem
.. doxygenstruct:: WpSettings
.. doxygengroup:: wpsettings
:content-only:

View file

@ -7,17 +7,12 @@ Session Items Interfaces
digraph inheritance { digraph inheritance {
rankdir=LR; rankdir=LR;
GInterface -> WpSiEndpoint;
GInterface -> WpSiAdapter; GInterface -> WpSiAdapter;
GInterface -> WpSiLinkable; GInterface -> WpSiLinkable;
GInterface -> WpSiLink; GInterface -> WpSiLink;
GInterface -> WpSiAcquisition; GInterface -> WpSiAcquisition;
} }
.. doxygenstruct:: WpSiEndpoint
.. doxygenstruct:: _WpSiEndpointInterface
.. doxygenstruct:: WpSiAdapter .. doxygenstruct:: WpSiAdapter
.. doxygenstruct:: _WpSiAdapterInterface .. doxygenstruct:: _WpSiAdapterInterface

View file

@ -0,0 +1,6 @@
# you need to add here any files you add to the toc directory as well
sphinx_files += files(
'c_api.rst',
)
subdir('c_api')

View file

@ -1,18 +1,12 @@
# you need to add here any files you add to the toc directory as well # you need to add here any files you add to the toc directory as well
sphinx_files += files( sphinx_files += files(
'index.rst', 'index.rst',
'installing-wireplumber.rst',
'running-wireplumber-daemon.rst',
'configuration.rst',
'daemon-logging.rst',
'contributing.rst',
'community.rst',
'testing.rst',
'releases.rst',
'c_api.rst',
'lua_api.rst',
) )
subdir('c_api') subdir('daemon')
subdir('lua_api') subdir('design')
subdir('configuration') subdir('policies')
subdir('library')
subdir('scripting')
subdir('tools')
subdir('resources')

View file

@ -0,0 +1,140 @@
.. _policies_linking:
Linking Policy
==============
Introduction
------------
The linking policy in WirePlumber is the logic charged to link a PipeWire stream
node with a PipeWire device node (most cases), or with another PipeWire stream
node (monitoring applications).
PipeWire stream nodes always have one of the following media classes:
- Stream/Output/Audio: For audio playback applications (Eg pw-play).
- Stream/Input/Audio: For audio capture applications (Eg pw-record).
- Stream/Input/Video: For video capture applications (Eg cheese).
And Pipewire device nodes always have one of the following media classes:
- Audio/Sink: For audio playback devices (Eg Speakers).
- Audio/Source: For audio capture devices (Eg Microphones).
- Video/Source: For video capture devices (Eg Cameras).
By default, since in most cases we want to link a stream node with a device
node, the linking policy logic when linking 2 nodes always follows the following
assignments:
.. graphviz::
digraph nodes {
rankdir=LR;
APS [shape=box label=<audio playback stream<BR/>(Stream/Output/Audio)>];
APD [shape=box label=<audio playback device<BR/>(Audio/Sink)>];
ACS [shape=box label=<audio capture stream<BR/>(Stream/Input/Audio)>];
ACD [shape=box label=<audio capture device<BR/>(Audio/Source)>];
VCS [shape=box label=<video capture stream<BR/>(Stream/Input/Video)>];
VCD [shape=box label=<video capture device<BR/>(Video/Source)>];
APS -> APD;
ACD -> ACS;
VCD -> VCS;
}
After that, once the media class of a device node has been selected for a
particular stream node, and there are more than 1 device node matching such
media class, WirePlumber will select one based on a set of priorities:
First, it will check if there is a default configured device node for the
selected device media class. If there is one, and the node exists, it will link
the stream node with such configured default node. Users can easily configure
default device nodes for all the 3 different device media classes using tools
such as ``pavucontrol`` or ``wpctl``. The logic is implemented in the
``linking/find-default-target.lua`` Lua script.
If there isn't any default node configured, or there is a default node
configured but the node does not exist, WirePlumber will instead select the
best device node available. The best device node is the node with highest
session priority and available routes to the physical device. The logic is
implemented in the ``linking/find-best-target.lua`` Lua script.
If the best node could not be found because the system does not have any,
WirePlumber won't link the stream and will send a "no target node available"
error to the client.
Stream node linking properties
------------------------------
The above default linking logic behavior can be changed by setting specific
properties on the nodes.
.. note::
These properties must be set in the **stream** nodes (not the device nodes),
otherwise they won't have any effect.
- **target.object**:
  The name of the desired node for this stream to be linked with.
  If this property is present, WirePlumber will try to find such node, see if it
  can be linked with the stream, and if so, will use it instead of the default
  node or best node. The logic is implemented in the ``linking/find-defined-target.lua``
  Lua script. Since this property is not set by default, WirePlumber will always
  link stream nodes to the default or best device node found. This property can be
  easily set using tools such as ``pw-play`` with the ``--target`` flag.
  Note that any node name can be specified there, even if the name is not a device
  node name, but another stream node name. If this is the case, WirePlumber will
  link 2 stream nodes together. An example of this case is the monitoring nodes
  created by ``pavucontrol`` to monitor audio of all audio devices and streams.
- **node.dont-reconnect**:
  Boolean indicating whether the stream node should not be reconnected to a new
  node if its current linked node (target) was destroyed or not. By default it
  is set to ``false``, so if the property is not present in the stream node, WirePlumber
  will always try to reconnect the stream node to a new target instead of sending
  an error to the client. The logic is implemented in the ``linking/prepare-link.lua``
  Lua script.
- **node.dont-move**:
  Boolean indicating whether the stream node should not be movable or not at runtime
  using the metadata. If a stream node is not movable, it means that users cannot
  relink the stream node to a new target at runtime (using tools such as ``pavucontrol``
  or ``pw-metadata``) when the stream node is already linked to a different node. By
  default it is set to ``false``, so if the property is not present, WirePlumber will
  always move, and therefore link the stream node to a new target if it is defined and
  updated in the ``target.object`` metadata key.
- **node.dont-fallback**:
  Boolean indicating whether the stream node should not fallback to a different
  target if its defined target does not exist (the one defined with the ``target.object``
  property) or not. Therefore, if this property is set to ``true``, WirePlumber sends
  a "defined target not found" error to the client and will also destroy the stream
  node. By default it is set to ``false``, so if the property is not present in the
  stream node, WirePlumber will always fallback to the default or best target if
  the defined target was not found.
- **node.linger**:
  Boolean indicating whether the stream node should linger or not if its defined
  target was not found and the ``node.dont-fallback`` is set to true. Therefore, if
  this property is set to ``true``, the defined target was not found, and the
  ``node.dont-fallback`` is set to true, WirePlumber won't send a "defined target not found"
  error to the client, and won't destroy the stream node. This is useful if we want
  the stream to wait (without processing any data) until its defined target becomes
  available. By default it is set to ``false``, so if the property is not present in the
  stream node, WirePlumber will always destroy the node and send an error to the client
  if its target was not found and ``node.dont-fallback`` was set to true.
Linking settings
----------------
Apart from the above properties, there are also global settings for the linking
policy. See :ref:`config_settings` for more information, the linking settings
are prefixed with ``linking.``.

View file

@ -0,0 +1,6 @@
# you need to add here any files you add to the toc directory as well
sphinx_files += files(
'linking.rst',
'smart_filters.rst',
'software_dsp.rst',
)

View file

@ -0,0 +1,380 @@
.. _policies_smart_filters:
Smart Filters
=============
Introduction
------------
The smart filters policy allows automatically linking filters together, in a
chain, and tied to a specific target node. This is useful when we want to apply
a specific processing chain to a specific device, for example. When a stream is
about to be linked to a target node that is associated with a smart filter
chain, the policy will automatically link the stream with the first filter in
the chain, and the last filter in the chain with the target node. This is done
transparently to the client, allowing users to define a specific processing
chain for a specific device without having to create setups with virtual sinks
(or sources) that must be explicitly targeted by the clients.
Filters, in general, are nodes that are placed in the middle of the graph and
are used to modify the data that passes through them. For example, the
*echo-cancel*, the *filter-chain*, or the *loopback* nodes are filters.
Filters can be implemented either as a single node or as a pair of nodes with
opposite directions. For example, the *null-audio-sink* node can be configured
to be a single-node filter. On the other hand, the *filter-chain* is a pair of
nodes with opposite directions, where one node captures the audio from the graph
and the other node sends the modified audio back to the graph.
For the purpose of the **smart filters** policy, WirePlumber will only consider
pairs of nodes as filters, not single-node ones. More specifically, a pair of
nodes will be considered to be a filter by WirePlumber if they have the
``node.link-group`` property set to a common value. This property is always set
on pairs of nodes that are internally linked together and is a good indicator
that the nodes are implementing a filter.
That pair of nodes **must** always consist of a *stream* node and a *main* node.
The main node acts as a virtual device, where the data is sent or captured
to/from, and the stream node acts as a regular stream, where the data is sent
or received to/from the next node in the graph. This is designated by their
media class, as shown in the table below:
.. list-table::
:widths: 30 35 35
:header-rows: 1
:stub-columns: 1
* -
- Input filter (virtual sink)
- Output filter (virtual source)
* - Main node
- ``Audio/Sink`` (capture)
- ``Audio/Source`` (playback)
* - Stream node
- ``Stream/Output/Audio`` (playback)
- ``Stream/Input/Audio`` (capture)
For instance, if a smart filter is used between an application playback stream
and the default audio sink, the graph would look like this:
.. graphviz::
digraph nodes {
rankdir=LR;
A [shape=box label=<application stream node<BR/>(Stream/Output/Audio)>];
FM [shape=box label=<filter main node<BR/>(Audio/Sink)>];
FS [shape=box label=<filter stream node<BR/>(Stream/Output/Audio)>];
D [shape=box label=<default device node<BR/>(Audio/Sink)>];
A -> FM;
FS -> D;
subgraph cluster_filter {
style="dotted";
FM; FS;
}
}
The same logic is applied if the smart filter is used between an application
capture stream and the default audio source, it is just all in the opposite
direction. This is how the graph would look like in this case:
.. graphviz::
digraph nodes {
rankdir=LR;
A [shape=box label=<application stream node<BR/>(Stream/Input/Audio)>];
FM [shape=box label=<filter main node<BR/>(Audio/Source)>];
FS [shape=box label=<filter stream node<BR/>(Stream/Input/Audio)>];
D [shape=box label=<default device node<BR/>(Audio/Source)>];
D -> FS;
FM -> A;
subgraph cluster_filter {
style="dotted";
FM; FS;
}
}
When multiple filters have the same direction, they can also be chained together
so that the output of one filter is sent to the input of the next filter. The
next section describes how these chains can be described with properties so that
they are automatically linked by WirePlumber in any way we want.
Filter properties
-----------------
When a filter node is created, WirePlumber will check for the presence of the
following optional node properties on the **main** node:
- **filter.smart**
Boolean indicating whether smart policy will be used for these filter nodes or
not. This is disabled by default, therefore filter nodes will be treated as
regular nodes, without applying any kind of extra logic. On the other hand, if
this property is set to ``true``, automatic (smart) filter policy will be used
when linking them. The properties below will then also apply, providing
further instructions.
- **filter.smart.name**
The unique name of the filter. WirePlumber will use the value of the
``node.link-group`` property as the filter name if this property is not set.
- **filter.smart.disabled**
Boolean indicating whether the filter should be disabled or not. A disabled
filter will never be used under any circumstances. If the property is not set,
WirePlumber will consider the filter as enabled (i.e. disabled = false).
- **filter.smart.targetable**
Boolean indicating whether the filter can be directly linked with clients that
have it defined as a target (Eg: ``pw-play --target <filter-name>``) or not.
This can be useful when a client wants to be linked with a filter that is in
the middle of the chain in order to bypass the filters that are placed before
the selected one. If the property is not set, WirePlumber will consider the
filter not targetable by default, meaning filters will never by bypassed by
clients, and clients will always be linked with the first filter in the chain.
- **filter.smart.target**
A JSON object that defines the matching properties of the filter's target
node. A filter target can never be another filter node (WirePlumber will
ignore it), it must be a device or virtual sink (or source, depending on the
direction of the filter). If this property is not set, WirePlumber will use
the default sink/source as the target.
- **filter.smart.before**
A JSON array containing the names of the filters that are supposed to be
chained after this filter (i.e. this filter here should be chained *before*
those). If not set, WirePlumber will link the filters by order of creation.
- **filter.smart.after**
A JSON array containing the names of the filters that are supposed to be
chained before this filter (i.e. this filter here should be chained *after*
those). If not set, WirePlumber will link the filters by order of creation.
.. note::
These properties must be set on the filter's **main** node, not the stream
node.
As an example, we will describe here how to create 2 loopback filters in
PipeWire's configuration, with names loopback-1 and loopback-2, that will be
linked with the default audio device, and use loopback-2 filter as the last
filter in the chain.
The PipeWire configuration files for the 2 filters should be like this:
- ~/.config/pipewire/pipewire.conf.d/loopback-1.conf:
.. code-block::
:emphasize-lines: 8-11
context.modules = [
{ name = libpipewire-module-loopback
args = {
node.name = loopback-1-sink
node.description = "Loopback 1 Sink"
capture.props = {
audio.position = [ FL FR ]
media.class = Audio/Sink
filter.smart = true
filter.smart.name = loopback-1
filter.smart.before = [ loopback-2 ]
}
playback.props = {
audio.position = [ FL FR ]
node.passive = true
stream.dont-remix = true
}
}
}
]
- ~/.config/pipewire/pipewire.conf.d/loopback-2.conf:
.. code-block::
:emphasize-lines: 8-10
context.modules = [
{ name = libpipewire-module-loopback
args = {
node.name = loopback-2-sink
node.description = "Loopback 2 Sink"
capture.props = {
audio.position = [ FL FR ]
media.class = Audio/Sink
filter.smart = true
filter.smart.name = loopback-2
}
playback.props = {
audio.position = [ FL FR ]
node.passive = true
stream.dont-remix = true
}
}
}
]
After restarting PipeWire to apply the configuration changes, playing a test
wave audio file with paplay to the default device should result in the following
graph:
.. graphviz::
digraph nodes {
rankdir=LR;
paplay [shape=box label=<paplay node<BR/>(Stream/Output/Audio)>];
L1M [shape=box label=<loopback-1 main node<BR/>(Audio/Sink)>];
L1S [shape=box label=<loopback-1 stream node<BR/>(Stream/Output/Audio)>];
L2M [shape=box label=<loopback-2 main node<BR/>(Audio/Sink)>];
L2S [shape=box label=<loopback-2 stream node<BR/>(Stream/Output/Audio)>];
device [shape=box label=<default device node<BR/>(Audio/Sink)>];
paplay -> L1M;
L1S -> L2M;
L2S -> device;
subgraph cluster_filter1 {
style="dotted";
L1M; L1S;
}
subgraph cluster_filter2 {
style="dotted";
L2M; L2S;
}
}
Now, if we remove the ``filter.smart.before = [ loopback-2 ]`` property from the
loopback-1 filter, and add a ``filter.smart.before = [ loopback-1 ]`` property
in the loopback-2 filter configuration file, WirePlumber should link the
loopback-1 filter as the last filter in the chain, like this:
.. graphviz::
digraph nodes {
rankdir=LR;
paplay [shape=box label=<paplay node<BR/>(Stream/Output/Audio)>];
L1M [shape=box label=<loopback-1 main node<BR/>(Audio/Sink)>];
L1S [shape=box label=<loopback-1 stream node<BR/>(Stream/Output/Audio)>];
L2M [shape=box label=<loopback-2 main node<BR/>(Audio/Sink)>];
L2S [shape=box label=<loopback-2 stream node<BR/>(Stream/Output/Audio)>];
device [shape=box label=<default device node<BR/>(Audio/Sink)>];
paplay -> L2M;
L2S -> L1M;
L1S -> device;
subgraph cluster_filter1 {
style="dotted";
L1M; L1S;
}
subgraph cluster_filter2 {
style="dotted";
L2M; L2S;
}
}
In addition, the filters can have different targets. For example, we can define
the filters like this:
- ~/.config/pipewire/pipewire.conf.d/loopback-1.conf:
.. code-block::
:emphasize-lines: 12
context.modules = [
{ name = libpipewire-module-loopback
args = {
node.name = loopback-1-sink
node.description = "Loopback 1 Sink"
capture.props = {
audio.position = [ FL FR ]
media.class = Audio/Sink
filter.smart = true
filter.smart.name = loopback-1
filter.smart.after = [ loopback-2 ]
filter.smart.target = { node.name = "not-default-audio-device" }
}
playback.props = {
audio.position = [ FL FR ]
node.passive = true
stream.dont-remix = true
}
}
}
]
- ~/.config/pipewire/pipewire.conf.d/loopback-2.conf:
.. code-block::
context.modules = [
{ name = libpipewire-module-loopback
args = {
node.name = loopback-2-sink
node.description = "Loopback 2 Sink"
capture.props = {
audio.position = [ FL FR ]
media.class = Audio/Sink
filter.smart = true
filter.smart.name = loopback-2
}
playback.props = {
audio.position = [ FL FR ]
node.passive = true
stream.dont-remix = true
}
}
}
]
In this case, playing a test wave audio file with paplay to the
``not-default-audio-device`` device should result in the following graph:
.. graphviz::
digraph nodes {
rankdir=LR;
paplay [shape=box label=<paplay node<BR/>(Stream/Output/Audio)>];
L1M [shape=box label=<loopback-1 main node<BR/>(Audio/Sink)>];
L1S [shape=box label=<loopback-1 stream node<BR/>(Stream/Output/Audio)>];
L2M [shape=box label=<loopback-2 main node<BR/>(Audio/Sink)>];
L2S [shape=box label=<loopback-2 stream node<BR/>(Stream/Output/Audio)>];
device [shape=box label=<not-default-audio-device node<BR/>(Audio/Sink)>];
paplay -> L2M;
L2S -> L1M;
L1S -> device;
subgraph cluster_filter1 {
style="dotted";
L1M; L1S;
}
subgraph cluster_filter2 {
style="dotted";
L2M; L2S;
}
}
In this configuration, the loopback-1 filter will only be linked if the
application stream is targeting the device node called
"not-default-audio-device".
Filters metadata
----------------
Similar to the default metadata, it is also possible to override the filter
properties using the "filters" metadata object. This allow users to change the
filters policy at runtime.
For example, assuming the id of the *loopback-1* main node is ``40``, we can
disable the filter by setting its ``filter.smart.disabled`` metadata key to
``true`` using the ``pw-metadata`` tool like this:
.. code-block:: bash
$ pw-metadata -n filters 40 "filter.smart.disabled" true Spa:String:JSON
We can also change the target of a filter at runtime:
.. code-block:: bash
$ pw-metadata -n filters 40 "filter.smart.target" "{ node.name = new-target-node-name }" Spa:String:JSON
Every time a key in the filters metadata changes, all filters are unlinked and
re-linked properly, following the new policy.

View file

@ -0,0 +1,106 @@
.. _policies_software_dsp:
Automatic Software DSP
======================
Introduction
------------
WirePlumber provides a mechanism for transparently handling oddball and embedded
devices that require software DSP to be done in userspace. Devices such as smartphones,
TVs, portable speakers, and even some laptops implement an audio subsystem designed
under the assumption that the hardware sink/source will be "backed" by some sort
of transparent DSP mechanism. That is, the hardware device itself should not be
directly accessed, and expects to be sent preprocessed/pre-routed samples. Often,
especially with Android handsets, these samples are preprocessed or pre-routed
by the vendor's proprietary userspace.
WirePlumber's automatic software DSP mechanism aims to replicate this functionality in
a standardised and configurable way. The target device sink/source is hidden from
other PipeWire clients, and a virtual node is linked to it. This virtual
node is then presented to clients as *the* node, allowing implementers to specify
any custom processing or routing in a way that is transparent to users, the kernel,
and the hardware.
Activating
----------
In addition to the ``node.software-dsp.rules`` section, the ``node.software-dsp``
:ref:`feature <config_features>` must be enabled in the desired profile(s).
Matching a node
---------------
Matching rules are specified in ``node.software-dsp.rules``. The ``create-filter``
action specifies behaviour at node insertion. All node properties can be matched
on, including any type-specific properties such as ``alsa.id``.
Configurable properties
-----------------------
.. describe:: filter-graph
SPA-JSON object describing the software DSP node. This is passed as-is as
an argument to ``libpipewire-module-filter-chain``. See the
`filter-chain documentation <https://docs.pipewire.org/page_module_filter_chain.html>`_
for details on what options can be set in this object.
.. note::
The ``target.object`` property of the virtual node should be configured
statically to point to the node matched by the rule.
.. describe:: filter-path
Absolute path to a file on disk storing a SPA-JSON object as plain text. This will be
parsed by WirePlumber into a WpConf object with a single section called
``node.software-dsp.graph``, then passed as-is into ``libpipewire-module-filter-chain``.
.. note::
``filter-graph`` and ``filter-path`` are mutually exclusive, with the former taking
precedence if both are present in the matched rule.
.. describe:: hide-parent
Boolean indicating whether or not the matched node should be hidden from
clients. ``node/software-dsp.lua`` will set the permissions for all clients other
than WirePlumber itself to ``'-'``. This prevents use of the node by any
userspace software except for WirePlumber itself.
Examples
--------
.. code-block::
:caption: wireplumber.conf.d/99-my-dsp.conf
node.software-dsp.rules = [
{
matches = [
{ "node.name" = "alsa_output.platform-sound.HiFi__Speaker__sink" }
{ "alsa.id" = "~WeirdHardware*" } # Wildcard match
]
actions = {
create-filter = {
filter-graph = {} # Virtual node goes here
filter-path = "/path/to/spa.json"
hide-parent = true
}
}
}
]
wireplumber.profiles = {
main = {
node.software-dsp = required
}
}
This will match any sinks with the UCM HiFi Speaker profile set or cards
containing the string "WeirdHardware" at the start of their name.

View file

@ -1,6 +0,0 @@
.. _releases:
Releases
========
.. include:: ../../NEWS.rst

View file

@ -1,4 +1,4 @@
.. _community: .. _resources_community:
Community Resources Community Resources
=================== ===================

View file

@ -1,4 +1,4 @@
.. _contributing: .. _resources_contributing:
Contributing to WirePlumber Contributing to WirePlumber
=========================== ===========================
@ -25,7 +25,7 @@ the indentation settings.
Tests Tests
----- -----
See :ref:`testing` See :ref:`resources_testing`
Running in gdb / valgrind / etc... Running in gdb / valgrind / etc...
---------------------------------- ----------------------------------

View file

@ -0,0 +1,7 @@
# you need to add here any files you add to the toc directory as well
sphinx_files += files(
'contributing.rst',
'testing.rst',
'community.rst',
'releases.rst',
)

View file

@ -0,0 +1,6 @@
.. _resources_releases:
Releases
========
.. include:: ../../../NEWS.rst

View file

@ -1,4 +1,4 @@
.. _testing: .. _resources_testing:
Testing Testing
======= =======
@ -62,16 +62,16 @@ Native API clients
pw-cat pw-cat
^^^^^^ ^^^^^^
Using the default endpoint: Using the default device:
.. code:: console .. code:: console
$ wpctl status # verify the default endpoints $ wpctl status # verify the default device
$ pw-record test.wav $ pw-record test.wav
$ pw-play test.wav $ pw-play test.wav
Using a non-default endpoint: Using a non-default device:
.. code:: console .. code:: console
@ -84,19 +84,18 @@ or
.. code:: console .. code:: console
$ wpctl status # find the capture & playback endpoint ids $ wpctl status # find the capture & playback node ids
$ pw-record --target <endpoint_id> test.wav $ pw-record --target <node_id> test.wav
$ pw-play --target <endpoint_id> test.wav $ pw-play --target <node_id> test.wav
.. note:: .. note::
node ids and endpoint ids can be used interchangeably when specifying node ids can be used interchangeably when specifying targets in all use cases
targets in all use cases
video-play video-play
^^^^^^^^^^ ^^^^^^^^^^
Using the default endpoint: Using the default device:
.. code:: console .. code:: console
@ -104,13 +103,13 @@ Using the default endpoint:
$ ./build/src/examples/video-play $ ./build/src/examples/video-play
Using a non-default endpoint: Using a non-default device:
.. code:: console .. code:: console
$ wpctl status # find the endpoint id from the list $ wpctl status # find the device node id from the list
$ cd path/to/pipewire-source-dir $ cd path/to/pipewire-source-dir
$ ./build/src/examples/video-play <endpoint_id> $ ./build/src/examples/video-play <node_id>
.. tip:: .. tip::
@ -123,11 +122,11 @@ PulseAudio compat API clients
pacat pacat
^^^^^ ^^^^^
Using the default endpoint: Using the default device:
.. code:: console .. code:: console
$ wpctl status # verify the default endpoints $ wpctl status # verify the default device
$ parecord test.wav $ parecord test.wav
$ paplay test.wav $ paplay test.wav
@ -158,29 +157,29 @@ aplay / arecord
``pipewire-alsa/conf/50-pipewire.conf`` in your ``~/.asoundrc`` ``pipewire-alsa/conf/50-pipewire.conf`` in your ``~/.asoundrc``
(or anywhere else, system-wide, where libasound can read it) (or anywhere else, system-wide, where libasound can read it)
Using the default endpoint: Using the default device:
.. code:: console .. code:: console
$ wpctl status # verify the default endpoints $ wpctl status # verify the default devices
$ arecord -D pipewire -f S16_LE -r 48000 test.wav $ arecord -D pipewire -f S16_LE -r 48000 test.wav
$ aplay -D pipewire test.wav $ aplay -D pipewire test.wav
Using a non-default endpoint: Using a non-default device:
.. code:: console .. code:: console
$ wpctl status # find the capture & playback endpoint ids $ wpctl status # find the capture & playback node ids
$ PIPEWIRE_NODE=<endpoint_id> arecord -D pipewire -f S16_LE -r 48000 test.wav $ PIPEWIRE_NODE=<node_id> arecord -D pipewire -f S16_LE -r 48000 test.wav
$ PIPEWIRE_NODE=<endpoint_id> aplay -D pipewire test.wav $ PIPEWIRE_NODE=<node_id> aplay -D pipewire test.wav
or or
.. code:: console .. code:: console
$ wpctl status # find the capture & playback endpoint ids $ wpctl status # find the capture & playback device node ids
$ arecord -D pipewire:NODE=<endpoint_id> -f S16_LE -r 48000 test.wav $ arecord -D pipewire:NODE=<node_id> -f S16_LE -r 48000 test.wav
$ aplay -D pipewire:NODE=<endpoint_id> test.wav $ aplay -D pipewire:NODE=<node_id> test.wav
JACK compat API clients JACK compat API clients
@ -201,15 +200,14 @@ jack_simple_client
.. code:: console .. code:: console
$ wpctl status # find the target endpoint id $ wpctl status # find the target device node id
$ wpctl inspect <endpoint_id> # find the node.id $ wpctl inspect <node_id> # find the node.id
$ PIPEWIRE_NODE=<node_id> pw-jack jack_simple_client $ PIPEWIRE_NODE=<node_id> pw-jack jack_simple_client
.. note:: .. note::
The JACK layer is not controlled by the session manager, it creates its own The JACK layer is not controlled by the session manager, it creates its own
links; which is why it is required to specify a node id (endpoint id will not links; which is why it is required to specify a node id.
work)
Device Reservation Device Reservation
------------------ ------------------
@ -263,7 +261,7 @@ with JACK
3. Wait a few seconds and run ``wpctl status`` to inspect 3. Wait a few seconds and run ``wpctl status`` to inspect
- The devices taken by JACK should no longer be available - The devices taken by JACK should no longer be available
- There should be two *JACK System* endpoints (sink & source) - There should be two *JACK System* nodes (sink & source)
4. Run an audio client on PipeWire (ex ``pw-play test.wav``) 4. Run an audio client on PipeWire (ex ``pw-play test.wav``)
@ -277,7 +275,7 @@ with JACK
6. Wait a few seconds and run ``wpctl status`` to inspect 6. Wait a few seconds and run ``wpctl status`` to inspect
- The devices that were release by JACK should again be available - The devices that were release by JACK should again be available
- There should be no *JACK System* endpoint - There should be no *JACK System* nodes
.. note:: .. note::

View file

@ -0,0 +1,41 @@
.. _scripting_custom_scripts:
Custom Scripts
==============
The locations where WirePlumber searches for scripts is explained in
:ref:`config_locations_scripts`.
Scripts are not loaded automatically; a component muse be defined for them, and
this component must be included in a profile. See
:ref:`config_components_and_profiles`.
Full example
------------
Let's assume that ``~/.local/share/wireplumber/scripts/90-hello-world.lua``
contains the following script:
.. code-block:: lua
log = Log.open_topic("hello-world")
log.info("Hello world")
In order for it to run, we'll define a component and include it in the default
profile by including the following configuration (for example, in
``~/.config/wireplumber/wireplumber.conf.d/90-hello-world.conf``):
.. code-block::
wireplumber.components = [
{
name = "90-hello-world.lua", type = script/lua
provides = hello-world
}
]
wireplumber.profiles = {
main = {
hello-world = required
}
}

View file

@ -0,0 +1,15 @@
.. _scripting_existing_scripts:
Existing Scripts
================
This section documents all the existing lua scripts that are shipped with
WirePlumber, including information on the hooks that they provide and
information on how to extend the logic with additional custom scripts & hooks.
.. toctree::
:maxdepth: 1
existing_scripts/default_nodes.rst
existing_scripts/device.rst
existing_scripts/linking.rst

View file

@ -0,0 +1,3 @@
.. _existing_scripts_default_nodes:
.. include:: ../../../../src/scripts/default-nodes/README.rst

View file

@ -0,0 +1,3 @@
.. _existing_scripts_device:
.. include:: ../../../../src/scripts/device/README.rst

View file

@ -0,0 +1,3 @@
.. _existing_scripts_linking:
.. include:: ../../../../src/scripts/linking/README.rst

View file

@ -0,0 +1,6 @@
# you need to add here any files you add to the toc directory as well
sphinx_files += files(
'default_nodes.rst',
'device.rst',
'linking.rst',
)

View file

@ -1,4 +1,4 @@
.. _lua_api: .. _scripting_lua_api:
Lua API Documentation Lua API Documentation
===================== =====================

View file

@ -8,6 +8,17 @@ object is not exposed to the scripts.
For some functionality, though, the following static functions are exposed. For some functionality, though, the following static functions are exposed.
.. function:: Core.get_properties()
Binds :c:func:`wp_core_get_properties`
Returns a table with the properties of the core. These are the same
properties that appear on WirePlumber's *client* object in the PipeWire
global registry.
:returns: the properties of the core
:rtype: table
.. function:: Core.get_info() .. function:: Core.get_info()
Returns a table with information about the core. The table contains Returns a table with information about the core. The table contains
@ -120,3 +131,14 @@ For some functionality, though, the following static functions are exposed.
the api plugins to load, if they are not already loaded the api plugins to load, if they are not already loaded
:param callback: the function to call after the plugins have been loaded; :param callback: the function to call after the plugins have been loaded;
this function takes references to the plugins as parameters this function takes references to the plugins as parameters
.. function:: Core.test_feature()
Binds :c:func:`wp_core_test_feature`
Tests if the specified feature is provided in the current WirePlumber
configuration.
:param string feature: the name of the feature to test
:returns: true if the feature is provided, false otherwise
:rtype: boolean

Some files were not shown because too many files have changed in this diff Show more