Pipewire (built from source, not from RPi repo)

Howdy!

In my search for an easier solution to be able to interact with more than just a single sound card at a time I tried Pipewire. I’ve built it from git (apt repo had quite an old version). It took some fiddling with systemd’s service files (pipewire runs as a user service, where everything else runs as a system service).

It appears mostly to work now. With the default ZynADAC card selected in the webconf tool, I can:

  1. Capture/play to USB headset using UI of Zynthian (as soon as I insert USB headset it shows up in the Sound Capture/Sound Playback menu
  2. With the addition of g_audio I can use Zynthian as a USB sound interface connected to my laptop.

Somewhat minor issues:

  1. Zynthian gets confused by midi ports now - whenever a synth is added - controls do not work until I re-patch it in Patchage properly. Shouldn’t be hard to fix.
  2. MOD-UI gets confused by names of devices/ports and UI breaks. Looks like it is due to different cards having same name for ports and MOD-UI using only port name as ID, not card+port name. Should be fixable upstream.
  3. Probably related to #1 - zynthian doesn’t automatically connect added synths to sound output - i have to manually select it in the settings of the layer.

Obvisouly, usage of multiple cards comes with latencies and other potential issues. But at the same time, using pipewire allowed me to quickly connect USB headphones I had lying around. And I hope I will figure out Bluetooth soon too. Recording digital audio via USB-C sounds like a good option to have (delay there quite significant, so it is not good use for live performance).

What yalls opinion about that setup? Is it something Zynthian might adopt? If so - I could try resolve issues in Zynthian and MOD-UI around port names. But I wanted to make sure it is worth the time.

1 Like

I think it was @Baggypants who brought Pipewire to our attention. It looks interesting and I have wanted to play with it but initial attempt was thwarted and have had other commitments since. It is interesting to hear you say it has higher latency (than jack?). It is imperative that we strive to reduce latency from the current value which is just on the edge of acceptability for many. If you have a recipe to make Pipewire work in Zynthian then do please share so we can make our own assessment. If it is (relatively) easy to install I might just have another look.

Sorry, I was not clear - latencies show up when, for example, I am putting audio into ZynADAC’s Audio In, route it to USB-C and listen to it on my laptop. Since USB-C audio interface implemented in software, there are obvious delays one would expect.

In regular situation of midi or audio into ZynADAC and output from ZynADAC - no noticeable latency so far.

I am still poking it trying to get it work right without launching console. Once I nail it down, I will try it again with brand new image to make sure I did not miss steps. Once that done - I can post steps to replicate my setup using stock SD image.

Read the website, precisely what is it? And what is it doing?

It is acting as the sound and video layer between hardware drivers and userspace applications, similar to what jack does for audio only. It implements samplerate conversion to allow multiple hardware to be used freely within the routing graph. It allows any source of audio / video to be used within that graph, e.g. web browser output. The workflow sounds great but I wonder how successful they have been at implementing it, particularly around latency and performance (xruns). If this is some magic that reimplements jack in a more efficient way then great! I am sceptical it has yet done that. It does provide a jack compatibility layer which should make it a drop in replacement for jack.

AAh right. another community arrives at graphs :smiley:
Make them properly structured and we have hardware environment snapshots. :smiley:

The cut and dried test to my understanding is how well it performs in real world situations, if it can hold a USB Source synced against an on board sound card.

Perhaps, I should see if it aids my USB Guitar lead, back of this list thou’

Yes - that is exactly what @averagejoe is trying to do - combine multiple audio interfaces. It is a similar problem to using the onboard sound for headphones. It would be good if this works better than jack + alsa_in / alsa_out.

Philosophically it feels more considered.

Get’s struck by passing raven whilst in a rather reflective mood …

I tried to put together steps necessary to get pipewire working on Zynthian. It requires VNC access to use Patchage to correct some errors (most importantly - disconnect midi_ctrl output)

Install building dependencies:

apt install -y ninja-build libudev-dev libavahi-client-dev libusb-dev libcap-dev libbluetooth-dev libsbc-dev librtaudio-dev libusb-1.0-0-dev libgstreamer1.0-dev libcamera-dev libwebrtc-audio-processing-dev libwebrtc-audio-processing1 libsystemd-dev libfdk-aac-dev rtkit
pip3 install meson

Install pipewire

https://github.com/PipeWire/pipewire.git
cd pipewire
meson setup builddir -Dprefix=/usr -Dsystemd-system-service=enabled -Dsystemd-user-service=disabled -Dpipewire-alsa=enabled -Dpipewire-jack=enabled -Djack-devel=true -Dlibusb=enabled
ninja -C builddir
cd builddir
meson install
cp -r /usr/share/pipewire /etc

Add override for jack2 service
systemctl edit jack2

[Service]
ExecStart=
Type=simple
ExecStartPre=/usr/bin/timeout 5s /usr/local/bin/jack_wait -w
ExecStart=/usr/local/bin/jack_wait -w
Restart=
Restart=on-failure

Fix user error when starting pipewire-* services
systemctl edit pipewire.socket

[Socket]
SocketUser=pipewire
SocketGroup=pipewire

systemctl edit pipewire.service

[Service]
User=

systemctl edit pipewire-media-session.service

[Service]
User=

Reload all systemd services
systemctl daemon-reload

Enable pipewire services
systemctl enable pipewire pipewire-media-session

Enable JACK emulation

echo "/usr/lib/arm-linux-gnueabihf/pipewire-0.3/jack/" > /etc/ld.so.conf.d/00-pipewire-jack.conf
ldconfig

Pipewire configuration tweaks:

Better naming of sound cards in /etc/pipewire/media-session.d/alsa-monitor.conf (at the end of the file but before “]”)

    {
        matches = [{ alsa.card_name = "snd_rpi_hifiberry_dacplusadcpro" }]
        actions = { update-props = { node.description = "System" }}
    }
    {
        matches = [{ alsa.card_name = "bcm2835 Headphones" }]
        actions = { update-props = { node.description = "Headphones" }}
    }
    {
        matches = [{ alsa.card_name = "bcm2835 HDMI 1" }]
        actions = { update-props = { node.description = "HDMI 1" }}
    }

Disable ALSA sequencer module in /etc/pipewire/media-session.d/media-session.conf:

with-audio = [
    [...]
    #alsa-seq
    [...]
]

And finally - reboot.

Current problems:

  • If hifiberry card is named “system” above (lower case) - it is not visible in the “Audio Output to” list. Also, “jack_lsp -A” shows “system” port is aliased to HDMI for some reason.

  • If RPi’s headphones card is named “Headphones” above - it is not visible in the “Audio Output to” list

  • MOD-UI is not working when started from Zynthian - it crashes “mod-host” service with:
    /usr/local/bin/jack_load: symbol lookup error: /usr/local/bin/jack_load: undefined symbol: jack_internal_client_load
    This likely happens because Zynthian checks jack outputs results to detect mod-ui finished loading. And jack_internal_client_load appears to be not implemented in jack emulation libraries of pipewire.

To disable these changes:

systemctl disable pipewire pipewire-media-session
rm /etc/ld.so.conf.d/00-pipewire-jack.conf
rm /etc/systemd/system/jack2.service.d/override.conf
reboot
4 Likes

So after playing with it a bit more I certainly like the flexibility pipewire offers. But since pipewire was made with multiple devices in mind, it doesn’t do some things that other JACK software expecting. One of these is the interconnection between different sources and sinks.

For example, we launch jack_capture when we start record. By default it tries to record from system:playback_* I believe, which would not exist on a system with multiple cards, since each card would be named differently.

For that particular issue adding an option to what to record into Zynthian UI probably is necessary.

And perhaps, some kinds of patching UI, that restores itself when connecting different nodes… For example, when manually patching, I connect all output to HiFiBerry’s playback_1/2 ports, and then connect HiFiBerry’s monitor ports to jackpeak and Headphones… It would make sense to connect jack_capture to it as well…

Not sure where all of it fits in the longterm Zynthian vision… Do you guys see multi-device usage, or realistically, you guys will stick with single-card and JACK2 as a foundation of it?

Found workaround for MIDI breaking - disabled alsa.seq module in media-session.conf (I’ve updated steps above to include this fix).

1 Like