Playing with pipewire

dos2unix

Well-Known Member
Joined
May 3, 2019
Messages
3,700
Reaction score
3,533
Credits
32,987
I don't think this is really a tutorial so much as just finding out about some things.

I didn't realize this until today when I was logged in as two different user accounts on the same computer.
When using an application that uses pipewire (almost all audio applications) the current user owns the process. However, each logged in user has its instance of pipewire.


Code:
ray@abdTower1:~$ ps -eo pid,uid,gid,user,comm,label | grep pipewire
2216  1000  1000 rg pipewire unconfined_t

This can also be seen with lsof
Code:
ray@abdTower1:~$ lsof | grep -E '/dev/snd|/dev/video*|/dev/media*'
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
pipewire  53799 rg     44u   CHR  116,9      0t0  913 /dev/snd/controlC0
pipewire  53799 rg     83u   CHR   81,0      0t0  884 /dev/video0
wireplumb 53801 rg     24u   CHR  116,9      0t0  913 /dev/snd/controlC0

On my distro (I haven't checked any other distros at this time) the configuration file /usr/share/pipewire/pipewire.conf is owned by root.
A handy command to check the current configuration is...
Code:
ray@absTower1:~$ pw-config
{
  "config.path": "/usr/share/pipewire/pipewire.conf",
  "override.config.path": "~/.config/pipewire/pipewire.conf.d/loops.conf"
}

Looking at the source code...Pipewire consists of around 30k lines of code in the C programming language.
How to see what pipewire modules you have...

Code:
ray@absTower1:~$ ls -la /usr/lib64/pipewire-0.3/
-rwxr-xr-x. 1 root root  28296 Nov 26 01:00 libpipewire-module-access.so
-rwxr-xr-x. 1 root root  98808 Nov 26 01:00 libpipewire-module-avb.so

How to see what plugins you have installed...
Code:
ray@absTower1:~$ ls -la /usr/lib64/spa-0.2/
drwxr-xr-x. 1 root root     28 Dec 11 12:13 alsa
drwxr-xr-x. 1 root root    420 Dec 11 12:13 bluez5
...

I discovered a command called "pw-top". It's like top, but just for pipewire processes.
Code:
ray@absTower1:~$ pw-top
S   ID  QUANT   RATE    WAIT    BUSY  FORMAT         NAME                                                                                                                              
R   90    512  48000 139.8us  23.0us  S16LE 2 48000  bluez_output..
R   99    900  48000  66.7us  37.7us  F32LE 2 48000  + Firefox
R  112   4320  48000 105.5us  11.4us  S16LE 2 48000  + Videos

Quantum (QUANT) can be thought of as the number of audio samples (buffer size) to be processed each graph cycle. This varies depending on the device type and can be configured or negotiated via configuration files. For example, the Videos application has a buffer size of 4320 samples, while the Bluetooth output node has only 512.

Rate (RATE) is the graph processing frequency. In the above output, the graph operates at 48 kHz, meaning each second the graph can process 48,000 samples.

The ratio between Quantum and Rate is the latency in seconds. In the case of Bluetooth headsets, the latency is 11 ms, while for the Videos app it is 90 ms. The pw-top man page provides links to better explanations. Understanding these indicators can help boost performance.

Another handy command is..
Code:
ray@absTower1:~$ pw-cli h
Available commands:
    help | h                Show this help
    load-module | lm        Load a module.
    unload-module | um      Unload a module.
    connect | con           Connect to a remote.
    disconnect | dis        Disconnect from a remote.
    list-remotes | lr       List connected remotes.
    switch-remote | sr      Switch between current remotes.
    list-objects | ls       List objects or current remote.
    info | i                Get info about an object.
    create-device | cd      Create a device from a factory.
    create-node | cn        Create a node from a factory.
    destroy | d             Destroy a global object.
    create-link | cl        Create a link between nodes.
    export-node | en        Export a local node
    enum-params | e         Enumerate params of an object
    set-param | s           Set param of an object
    permissions | sp        Set permissions for a client
    get-permissions | gp    Get permissions of a client
    send-command | c        Send a command <object-id>
    quit | q                Quit

Now I haven't tried all of these out yet, but it's interesting just to see what you do with pipewire.

Finally there a graph command as well. (You may need to install loupe)
Code:
ray@absTower1:~$ pw-dot --detail --all
ray@absTower1:~$ dot -Tpng pw.dot -o pw.png
ray@absTower1:~$ loupe pw.png

Pipewire comes with a module called protocol-pulse. The module has a separate systemd socket-activated user service. This emulates a PulseAudio server for compatibility with a large range of clients still using the PulseAudio libraries.

Code:
ray@absTower1:~$ ls -laZ /run/user/1000/pulse/native
srw-rw-rw-. rg rg user_tmp_t:s0 /run/user/1000/pulse/native

I am finding out more and more about this as I go. This would be a good candidate for a part 2.
 


My only interaction with pipewire has been on the odd occasion when it ha failed to proceed.

It has recently been added by Linux Mint to the latest iteration. ...22.1

To check which sound server is running, the following command is used:

Code:
inxi -A

On my pc it returns:

brian@brian-desktop:~$ inxi -A
Audio:
Device-1: Intel 100 Series/C230 Series Family HD Audio driver: snd_hda_intel
Device-2: Logitech Z Cinéma driver: hid-generic,snd-usb-audio,usbhid
type: USB
API: ALSA v: k6.8.0-53-generic status: kernel-api
Server-1: PipeWire v: 1.0.5 status: active
brian@brian-desktop:~$
......... Because I am running Linux Mint 22.1

If, after a fresh install etc, it is a problem getting the sound to work, it is feasible to go back to the older sound server, called PulseAudio. The following command will achieve that for you::

Code:
apt purge pipewire pipewire-bin
systemctl enable --user pulseaudio
sudo reboot
 
it is feasible to go back to the older sound server, called PulseAudio

You know me. I like the newer stuff. I will agree many times going with the newer stuff is more difficult and requires more resources. This is not so with pipewire. People who want to keep their distro's small and lightweight, take note.
pipewire uses less resources than alsa/pulseaudio, as a rule it uses about 10-15% less RAM. It has MUCH less latency,
and takes up less space on your hard drive. The other thing you lose, when going with newer applications, is backwards compatibility. But since pipewire has backwards compatibility with all alsa/pulse modules, it supports everything they support.
Also (as of Feb 2025) about 72 devices and sound-chips that alsa/pulse does not support.

It's more configurable, and individual users can have their own configurations instead of having to use global configurations like alsa/pulse force you to do. Now this probably only affects you if you are in a band, or a studio recording technician, but because it uses less resources, I can record more tracks, while playing more channels on the same computer than I can with alsa/pulse.

If you all you do is listen to streaming audio, mp3's and youtube videos, you probably won't notice much difference.

For a long time (at least 30 years or so) Apple/Mac has owned the recording studio. It's one area where they blow Windows out of the water. But for the first time in a long time, Linux is starting to make some inroads here.
 
I don't think this is really a tutorial so much as just finding out about some things.

What distro are you running PipeWire on?

I'm curious because on my Debian 12.9 distro I experience aggravating audio dropouts on many different apps. Pipewire-pulse may be the culprit.

But I love PipeWire, in general.

I'll likely ask about that in a separate post, rather than hijack this thread.
 
Thanks, bookmarked. I'm likely going to need this thread as a reference come next install coz Debian 13's apparently pushing PipeWire beyond Gnome (default), Mint onboarded it (actually I think it was since 22) and Fedora has been on it a couple of years (3?)... So I'm out of places to actually hide. I guess I could go to the lesser "standard" distros... but that breaks everything else. Really, it's Debian-, Fedora- and sometimes Arch-families for most "alien" apps (which I need for my job). So instead of bleating, I'll suck it up, bookmark this thread and start messing on a VM with passthrough on my soundcard.
 
Some Distro's have something called WirePlumber. Wireplumber is the session and policy manager for Pipewire. It has its own systemd user service.

Session managers save the current state of open audio applications along with their connections, allowing sessions to be easily restored without having to manually open each application, load individual settings files, and reconnect all connections

The operating system is a complex dynamic system. A lot of things can happen; for example, you can plug in your headphones any time, or you can switch between video and audio streaming. There appears to be a need for a separate controller to react to the various multimedia events. This controller or manager is Wireplumber.

There are some utilities, like wpctl and wpexec, a few configuration files, and quite a lot of Lua files in the scripts folder.
I have confess, I wasn't really a Lua fan, but it's growing on me. It seems there are too many new languages to learn these days.

Code:
ray@LianLi:~$ rpm -ql wireplumber
/usr/bin/wireplumber
/usr/bin/wpctl
/usr/bin/wpexec
/usr/share/wireplumber/wireplumber.conf
/usr/lib/systemd/user/wireplumber.service
/usr/share/wireplumber/scripts/client/access-default.lua
...

It also has it's own shared libraries.
Code:
ray@LianLi:~$ ls -l /usr/lib64/wireplumber-0.5/
-rwxr-xr-x. root libwireplumber-module-dbus-connection.so
-rwxr-xr-x. root libwireplumber-module-logind.so
-rwxr-xr-x. root libwireplumber-module-standard-event-source.so
...

Two utilities are available in the wireplumber package.

wpexec contains the execution context; you will see it in use in some Lua executable files.
wpctl allows the dynamic modification of settings. To check all available settings, use wpctl settings.

There are also some configuration files.
Code:
ray@LianLi:~$ cat /usr/share/wireplumber/wireplumber.conf
context.spa-libs = { ... }
context.modules = [ ... ]
wireplumber.profiles = { ... }
wireplumber.components = [ ... ]
wireplumber.components.rules = [ ... ]
wireplumber.settings.schema = { ... }

Here is an example of how to disable a feature in the main profile
Code:
cat <<EOF > ~/.config/wireplumber/wireplumber.conf.d/50.conf
wireplumber.profiles = {
  main = {
    hardware.video-capture = disabled
  } }
EOF

ray@LianLi:~$ systemctl --user restart wireplumber.service

Don't forget to change it back after you test it.

Wireplumber interacts with Pipewire via metadata objects. Let’s use wpctl settings to change one of the well-known settings, like the default sink volume.

Code:
ray@LianLi:~$ wpctl settings device.routes.default-sink-volume 0.23
ray@LianLi:~$ pw-metadata -n sm-settings 0 device.routes.default-sink-volume
Found "sm-settings" metadata 36
update: id:0 key:'device.routes.default-sink-volume' value:'0.23' type:'Spa:String:JSON'
...

Notice that using pw-metadata shows Pipewire has the updated value for this setting. To make the setting persistent across restarts, we can save it in the Wireplumber persistent state.

Code:
ray@LianLi:~$ wpctl settings --save device.routes.default-sink-volume 0.23
ray@LianLi:~$ cat ~/.local/state/wireplumber/*
device.routes.default-sink-volume=0.23
...

You can find the source code for this at...

Here is an an example written in Lua to list all streaming nodes.
Code:
cat <<EOF > ~/.local/share/wireplumber/scripts/10-medialog.lua
log = Log.open_topic("logger-media")

node_om = ObjectManager {
  Interest {
    type = "node",
    Constraint { "media.class",
                 "matches",
                 "Stream/Output/Audio", type = "pw-global"
               }
  }
}

node_om:connect("object-added", function (om, node)
  log:notice(node, "Process [" .. node.properties["application.process.binary"] ..
  "] -- [" .. node.properties["media.name"] .. "]"
)
end)

node_om:activate()
EOF

We can include this as a separate Wireplumber feature and then restart the wireplumber.service and verify using journalctl :

Code:
cat <<EOF > ~/.config/wireplumber/wireplumber.conf.d/70-media.conf
wireplumber.components = [
  {
    name = "10-medialog.lua", type = script/lua
    provides = logger-media
  }
]

wireplumber.profiles = {
  main = {
    logger-media = required
  }
}
EOF


ray@LianLi:~$ systemctl --user restart wireplumber.service
ray@LianLi:~$ journalctl --user -u wireplumber.service -g logger-media

12:38:00 logger-media: <WpNode:99:0x564>
Process [gnome-shell] -- [bell-window-system]
12:38:00 logger-media: <WpNode:87:0x564>
Process [firefox] -- [The Careful Ones - I'm Not Lost]
You can also execute the lua scripts individually by including the shebang #!/usr/bin/wpexec as the first line.
This should be enough to get you started, but there is a lot more information at...

 
Last edited:


Members online


Top