From 081bc5d0275da646b2af212d2f66a29a3f2f0a49 Mon Sep 17 00:00:00 2001 From: "Simon A. Eugster" Date: Sun, 5 Apr 2026 16:54:46 +0200 Subject: [PATCH] docs: Add user overview docs for PipeWire --- Dockerfile | 51 +++++ doc/Doxyfile.in | 1 + ...ewire-object-types-relationship.drawio.png | Bin 0 -> 32680 bytes doc/dox/overview-for-users.md | 216 ++++++++++++++++++ doc/meson.build | 1 + doc/tree.dox | 1 + 6 files changed, 270 insertions(+) create mode 100644 Dockerfile create mode 100644 doc/dox/media/pipewire-object-types-relationship.drawio.png create mode 100644 doc/dox/overview-for-users.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..8642cab99 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,51 @@ +# Build environment for PipeWire +# +# To build the image and tag it with “pw”: +# docker build . -t pw +# +# To run the container with the current directory mounted (so you can build inside the container): +# docker run -it --rm -v $(pwd):/repo pw +# +# In the container, to build docs and not too much else, set up the build directory in “builddir”: +# meson setup builddir --reconfigure --auto-features=disabled -Ddocs=enabled -Dsession-managers=[] -Dflatpak=disabled -Ddbus=disabled -Dpipewire-alsa=disabled +# +# Once configured, build the configured components: +# cd builddir +# meson compile + + +FROM ubuntu:24.04 + +RUN DEBIAN_FRONTEND=noninteractive apt-get update \ + && apt-get -y install \ + debhelper-compat \ + findutils \ + git \ + libapparmor-dev \ + libasound2-dev \ + libavcodec-dev \ + libavfilter-dev \ + libavformat-dev \ + libdbus-1-dev \ + libbluetooth-dev \ + libglib2.0-dev \ + libgstreamer1.0-dev \ + libgstreamer-plugins-base1.0-dev \ + libsbc-dev \ + libsdl2-dev \ + libsnapd-glib-dev \ + libudev-dev \ + libva-dev \ + libx11-dev \ + meson \ + ninja-build \ + pkg-config \ + python3-docutils \ + systemd + +RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \ + doxygen + +USER ubuntu +WORKDIR /repo + diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index f8cdbf528..c241f9abd 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -58,6 +58,7 @@ PREDEFINED = PA_C_DECL_BEGIN= \ SPA_NORETURN \ SPA_RESTRICT HTML_EXTRA_STYLESHEET = @cssfiles@ +IMAGE_PATH = "@top_srcdir@/doc/dox/media/" MAX_INITIALIZER_LINES = 1 SORT_MEMBER_DOCS = NO diff --git a/doc/dox/media/pipewire-object-types-relationship.drawio.png b/doc/dox/media/pipewire-object-types-relationship.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..adf7e95a8ce045a05144bc9e6762e4b35c226eb1 GIT binary patch literal 32680 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

a9T#2pnlRHQ++d~G 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 literal 0 HcmV?d00001 diff --git a/doc/dox/overview-for-users.md b/doc/dox/overview-for-users.md new file mode 100644 index 000000000..31893225a --- /dev/null +++ b/doc/dox/overview-for-users.md @@ -0,0 +1,216 @@ +\page page_overview_for_users Overview for Users + +While the \ref page_overview page describes PipeWire on a technical level for programmers, +this page is intended for end users working with (and not programming on) PipeWire. + +# PipeWire + +- [docs.pipewire.org: PipeWire docs](https://docs.pipewire.org/) – that’s this page +- [pipewire.pages.freedesktop.org: WirePlumber docs](https://pipewire.pages.freedesktop.org/wireplumber/) – WirePlumber reference +- [gitlab.freedesktop.org Wiki](https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/home) with guides and links to other docs +- [wiki.archlinux.org: ArchLinux docs](https://wiki.archlinux.org/title/PipeWire) with tool list and examples + +PipeWire is a multimedia framework for Linux. The Kernel uses ALSA, and applications can either use ALSA directly +(but only one application send sound to an ALSA output at the same time), or use a different backend like JACK, +PulseAudio, or (the newest) PipeWire. All those backends do not have the single client limitation and provide +additional features. + +PipeWire uses a powerful graph based approach for routing application freely between producers and consumers. + +PipeWire provides a PulseAudio API (and others like JACK), so clients relying on PulseAudio still work, +they just use the PulseAudio API provided by PipeWire. Therefore, PulseAudio tools like `pavucontrol` still work +(see PulseAudio section below). + + +## PipeWire overview + +Normally, a system with PipeWire also runs WirePlumber. + +**PipeWire** only *provides* the functionality for transporting and transforming audio and video. It is *used* by a session manager. + +There is one PipeWire *server* which is used by a number of PipeWire *clients* (the processes that produce/consume multimedia). +PipeWire, as well as WirePlumber, run in *userspace,* so interfacing with them with `systemd` (and `journald` etc.) +happens in *user context* with the `--user` flag, for example +`systemctl --user status pipewire.service` or `journalctl --user -fu wireplumber.service`. + +**WirePlumber** provides [Session Management](https://pipewire.pages.freedesktop.org/wireplumber/design/understanding_session_management.html): It enables new devices when they appear on ALSA, creates and configures nodes, +create links between nodes to route sound from an application to a consumer, etc. + +### Terminology + +For a more technical description, see \ref page_overview. + +* **Nodes** produce and/or consume data, for example a stereo output to a headset (consumes), an audio player (produces), + a reverb effect filter (consumes, then produces modified audio), etc. +* **Ports** are the connectors on nodes where data enters or exits. A stereo output sound card has two input ports + typically labeled `FL` and `FR` for front left and front right, which may receive data from `vlc` which has + two output ports `FL` and `FR`. (Physically, the sound card can have a stereo jack output, for example, but that is not in the scope of PipeWire.) +* **Links** connect two ports. Audio/Video data only flows when there is a link between ports. + Ports can have multiple incoming/outgoing links, so PipeWire can e.g. send the same `vlc` audio stream to the stereo headset + and a bluetooth headset and an audio recorder. +* **Devices** represent e.g. ALSA PCM sound cards. They have *Profiles*, and the active profile defines properties + like channel setup. For example, a sound card can have a `stereo` profile where only two ports are exposed, + or a `surround7.1` profile with 8 ports available. + +Nodes have various properties like name/description, a vendor (if available), an ID (changes between restart, therefore use `node.name` or `device.name`), etc. +Some specific properties: + +* `media.class` describes the type of the node. A sound card (a *device* in PipeWire) has media class `Audio/Device` + with corresponding `Audio/Source` input and `Audio/Sink` output nodes. A process producing audio is `Stream/Output/Audio`. + +Relationships between different object types (`type` property): + +![Object type relationship](pipewire-object-types-relationship.drawio.png) + +```mermaid +flowchart LR + C[PipeWire:Interface:Client] + D[PipeWire:Interface:Device] + N[PipeWire:Interface:Node] + P[PipeWire:Interface:Port] + L[PipeWire:Interface:Link] + CO[PipeWire:Interface:Core] + M[PipeWire:Interface:Module] + SC[PipeWire:Interface:SecurityContext] + PR[PipeWire:Interface:Profiler] + PM[PipeWire:Interface:Metadata] + N -- target.object --> C + N -- target.object --> D + L -- input + output port --> P + L -- input + output node --> N + +``` + + + +### PipeWire Tools + +* [List of PipeWire programs](https://docs.pipewire.org/page_programs.html) + +This is just a short selection of tools. + +[qpwgraph](https://gitlab.freedesktop.org/rncbc/qpwgraph) gives a quick visual overview over the current system configuration with nodes and links between them. +It also allows creating and deleting links on the fly. + +`pw-dump` dumps the whole configuration (json dump all, nodes etc) + +`pw-cli` allows to query and configure PipeWire, for example setting a sound card profile with +`pw-cli s Profile CARD_ID '{index: PROFILE_ID, save: true}'`, or in interactive mode. +*Important:* In interactive mode, do *not* use quotes around JSON data. + +`wpctl` interfaces with WirePlumber, for example `wpctl status` shows an ASCII representation of the nodes, sources, sinks, and routing. + +### WirePlumber + +WirePlumber creates links based on defaults and priorities as described in [Linking Policy](https://pipewire.pages.freedesktop.org/wireplumber/policies/linking.html). +For example, when an application starts audio playback, it links to the default sound output like the Bluetooth headset. +If that output disappears, it dynamically chooses the next suitable output device. + +### Configuration files and rules + +* [PipeWire docs: configuration overview](https://docs.pipewire.org/page_config.html) + +Both PipeWire and WirePlumber have a set of config files for configuring different parts. They use the same format. + +Rules in config file can define default outputs for specific nodes (e.g. VLC sound always goes to the 7.1 sound card). +[ArchLinux: WirePlumber](https://wiki.archlinux.org/title/WirePlumber) gives a short introduction to using them. + +**PipeWire server configuration** configures the PipeWire instance, defines which modules PipeWire should load, adds device rules, etc. + +* Location: `pipewire/pipewire.conf` +* Docs: [pipewire.conf](https://docs.pipewire.org/page_man_pipewire_conf_5.html) +* Configures: `context.exec`, `context.modules`, `context.properties`, `context.spa-libs`, `device.rules`, `node.rules` + +**PipeWire client configuration** contains configuration for PipeWire and ALSA clients, e.g. if VLC uses the PipeWire or ALSA backend, +its runtime behaviour can be modified with this configuration. +Example: A stream rule defines to always route `vlc` sound output to Bluetooth earbuds and `pw-play` to a stereo headset. + +* Location: `pipewire/client.conf`, for example `~/.config/pipewire/client.conf.d/` +* Docs: [client.conf](https://docs.pipewire.org/page_man_pipewire-client_conf_5.html) and [PipeWire object property reference](https://docs.pipewire.org/page_man_pipewire-props_7.html) (also contains WirePlumber related options!) +* Configures: `alsa.properties`, `alsa.rules`, `stream.properties`, `stream.rules` + +**PulseAudio/JACK configuration** contains configuration for PipeWire’s PulseAudio and JACK servers. + +* Docs: [pipewire-pulse.conf](https://docs.pipewire.org/page_man_pipewire-pulse_conf_5.html), [jack.conf](https://docs.pipewire.org/page_man_pipewire-jack_conf_5.html) + +**WirePlumber configuration** configures general WirePlumber aspects (should it even bring up ALSA devices +or save/restore user settings configured with e.g. `pavucontrol`) and also ALSA/Bluetooth monitor aspects +(choosing a default profile like Stereo or 7.1, setting device priorities that affect default routing, setting device properties, etc.). + +* Location: `wireplumber.conf`, e.g. `~/.config/wireplumber/wireplumber.conf.d/` + +* Docs: [WirePlumber daemon configuration](https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration.html) and more like [ALSA configuration](https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/alsa.html) +* Configures: `context`, `device`, `linking`, `wireplumber`, `monitor` (like `monitor.alsa.properties`, `monitor.alsa.rules`), `node` (like `node.software-dsp`),`support`, `policy` + + + +#### Writing Rules and Examples + +Rules can use regular expression when strings start with `~`, as explained in [PipeWire: Working with rules](https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/modifying_configuration.html#working-with-rules). + +```text +# Goes to ~/.config/wireplumber/wireplumber.conf.d/wireplumber-default-device.conf +# Restart wireplumber.service so it loads the rules +# This sample rule increases the priority of the stereo output on a Raspberry Pi, +# so it is used by default. +monitor.alsa.rules = [ + { + matches = [ + { + node.name = "alsa_output.platform-fe00b840.mailbox.stereo-fallback" + } + ] + actions = { + update-props = { + priority.driver = 3000 + priority.session = 3000 + } + } + } +] + +``` + +```text +# Goes to ~/.config/pipewire/client.conf.d/default-pw-play-output.conf +# Restart wireplumber.service so it loads the rules +# This sample rule uses a specific sound card for playback with pw-play. +# If it does not exist, WirePlumber takes the next suitable one. +stream.rules = [ + { + matches = [ + { + application.name = "pw-play" + } + ] + actions = { + update-props = { + target.object = "alsa_output.usb-PreSonus_Audio_AudioBox_USB-01.pro-output-0" + } + } + } +] + +``` + + + +### Debugging + +* Setting WirePlumber log level: https://pipewire.pages.freedesktop.org/wireplumber/daemon/logging.html +* `pw-play --target [ID|node.name] myfile.mp3` plays a sound file and tries to use the given target; useful for trying to find out the correct target +* [Automatically Link Pipewire Nodes with Wireplumber](https://bennett.dev/auto-link-pipewire-ports-wireplumber/) + + + +## PulseAudio API + +* [Migrating from PulseAudio to PipeWire](https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Migrate-PulseAudio) +* [PulseAudio clients and usage](https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PulseAudio) for PipeWire + + Many PulseAudio tools also work for PipeWire, like: + +* `pavucontrol` (GUI to configure sound cards, select profiles, etc.) +* `pactl` (CLI configuration tool, e.g. for setting the default audio sink) +* `paplay` and `parecord` for playing and recording audio + diff --git a/doc/meson.build b/doc/meson.build index e5c2936dc..3cbbb572d 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -50,6 +50,7 @@ extra_docs = [ 'tree.dox', 'dox/index.dox', 'dox/overview.dox', + 'dox/overview-for-users.md', 'dox/modules.dox', 'dox/pulse-modules.dox', 'dox/programs/index.md', diff --git a/doc/tree.dox b/doc/tree.dox index f62bc62dd..418e7dc7a 100644 --- a/doc/tree.dox +++ b/doc/tree.dox @@ -124,6 +124,7 @@ Support interfaces provided by host \} \page page_overview +\page page_overview_for_users \page page_config \page page_programs \page page_modules