How to delay camillaDSP service start until the HDMI playback device is available?

I have configured camillaDSP to start automatically as a service on my rPi4 (bookworm) but it always fails to open the HDMI playback device on startup.

Looking at the logs this seems to be because the ALSA hdmi playback device it is not (yet) available. If I restart the service manually after the boot it then always succeeds.

Unsuccessful service start at boot:
2024-01-11 11:40:26.391688 DEBUG [src/alsadevice.rs:334] Available Playback devices: [("hw:Loopback,0,0", "Loopback, ... <<< no mention of vc4hdmi0 !!!
2024-01-11 11:40:26.402195 ERROR [src/bin.rs:286] Playback error: ALSA function 'snd_pcm_open' failed with error 'EINVAL: Invalid argument'
Successful manual service restart a short time later:
2024-01-11 11:45:35.986926 DEBUG [src/alsadevice.rs:334] Available Playback devices: ... [("hw:vc4hdmi0,0,0", ... <<< vc4hdmi0 available
2024-01-11 11:45:35.991679 DEBUG [src/alsadevice.rs:352] Playback: supported channels, min: 2, max: 8, list: [2, 3, 4, 5, 6, 7, 8]
...
2024-01-11 11:45:35.992523 DEBUG [src/alsadevice.rs:392] Playback device "hdmi:vc4hdmi0,0" successfully opened

Is there a way to make the camillaDSP service start conditional on the ALSA HDMI device enumeration (preferred) or just to add a delay by trial and error (horrible)?

At the moment my /lib/systemd/system/camilladsp.service just waits for syslog:

[Unit]
After=syslog.target

Update

Funny how describing the problem focuses the mind... Immediately after posting I found out how to just delay any service start... and it all works as expected and hoped for, but I would still much prefer to avoid ad-hoc delays by using a suitable "After" rule!

If no better (e.g. "After") solution turns up, then here is how to fix it with a delay in the /lib/systemd/system/camilladsp.service:
[Service]
ExecStartPre=/bin/sleep 5
 
Last edited:
  • Thank You
Reactions: danhilu
I assume the os device to target is "/dev/dri/card0"

I'll give this all a try but...
  • Does this risk starting before "syslog"? (I assume not due to the U in udev)
  • Does this guarantee to fix the problem? Is the device visible in ALSA environment as soon as the os device appears, or at least before udev triggers?
Thanks
 
I assume the os device to target is "/dev/dri/card0"
Alsa devices are in /dev/snd/cardXX.
Does this risk starting before "syslog"? (I assume not due to the U in udev)
I am afraid I do not understand, why?
Does this guarantee to fix the problem? Is the device visible in ALSA environment as soon as the os device appears, or at least before udev triggers?
udev is a user-space daemon (today part of systemd) which manages the dev virtual filesystem in /dev, based on uevent messages sent from the kernel and on its rules. See e.g. https://en.wikipedia.org/wiki/Udev + lots of info online.

A device is "visible in ALSA environment" when its /dev/snd/... device file is created. "ALSA environment" is just a library alsa-lib (libasound2...), linked to executables using alsa (clients). Clients must enumerate/check for the available devices (via alsalib, of course). If a client wants to know a new device was created (e.g. pulseaudio), it must listen to udev events - https://stackoverflow.com/questions/36975381/alsa-callback-when-new-card-device-is-added .

Using udev rules for actions on newly created/removed/anything devices is the standard method.
 
Alsa devices are in /dev/snd/cardXX.
Thanks. This is the key to my puzzle: That alsa devices are indeed represented in the file-system! (I couldn't "find" any devices matching the alsa names like "hdmi" "Loopback" etc. so I assumed they were some sort of user-space objects interfaced via the alsa library.)

My next puzzle... Which snd devices correspond to the alsa "hdmi0/1" devices?
$ ls -l /dev/snd
total 0
drwxr-xr-x 2 root root 120 Jan 12 00:52 by-path
crw-rw---- 1 root audio 116, 6 Jan 12 00:52 controlC0
crw-rw---- 1 root audio 116, 8 Jan 12 00:52 controlC1
crw-rw---- 1 root audio 116, 10 Jan 12 00:52 controlC2
crw-rw---- 1 root audio 116, 12 Jan 12 00:52 controlC3
crw-rw---- 1 root audio 116, 3 Jan 12 00:52 pcmC0D0c
crw-rw---- 1 root audio 116, 2 Jan 12 00:52 pcmC0D0p
crw-rw---- 1 root audio 116, 5 Jan 12 00:52 pcmC0D1c
crw-rw---- 1 root audio 116, 4 Jan 12 00:52 pcmC0D1p
crw-rw---- 1 root audio 116, 7 Jan 12 00:52 pcmC1D0p
crw-rw---- 1 root audio 116, 9 Jan 12 00:52 pcmC2D0p
crw-rw---- 1 root audio 116, 11 Jan 12 00:52 pcmC3D0p
crw-rw---- 1 root audio 116, 1 Jan 12 00:52 seq
crw-rw---- 1 root audio 116, 33 Jan 12 00:52 timer
 
I have configured camillaDSP to start automatically as a service on my rPi4 (bookworm) but it always fails to open the HDMI playback device on startup.
[..]
[Service]
ExecStartPre=/bin/sleep 5

Hi @oomzay, thank you for your message. I had the same issue, camilladsp was systematically dead after boot, and I had to stop / start it once with systemctl first after each boot. Your solution initially solved my problem (ExecStartPre=/bin/sleep 5 in /lib/systemd/system/camilladsp.service). Thank you to have posted it.

I have dug into the hints proposed by @phofman's with the udev rule, which is even better, but was less obvious.
Here the solution which seems to solve my issue - up to now. I am far from an expert and have made very few tests.
1. "aplay -l" gives me "card 1: PCH [HDA Intel PCH], device 3: HDMI 0 [BenQ GW2780]" (this is for me only obviously)
2. "ls -l /dev/snd" gives me "pcmC1D3p" (above Card 1, Device 3, p for Playback)
3. I've created the file /etc/systemd/system/hdmi-audio.path with the content as follows
[Path]
PathExists=/dev/snd/pcmC1D3p
Unit=camilladsp.service
[Install]
WantedBy=multi-user.target
4. I have activated the dependency mechanism by:
sudo systemctl enable hdmi-audio.path
sudo systemctl start hdmi-audio.path
5. And I have removed @oomzay's "ExecStartPre=/bin/sleep 5" from camilladsp.service

camilladsp now keeps starting when hdmi is present. No need for 5 seconds delay. Very limited test yet, but at least camilladsp becomes operationnal after boot.
 
Thank you @phofman.

daniel@Wyse-5070:~$ ls -l /dev/snd/by-path
total 0
lrwxrwxrwx 1 root root 12 Jan 13 09:23 pci-0000:00:0e.0 -> ../controlC1
lrwxrwxrwx 1 root root 12 Jan 13 09:23 platform-snd_aloop.0 -> ../controlC0

I undersand you suggest I replace "PathExists=/dev/snd/pcmC1D3p" by "PathExists=/dev/snd/by-path/pci-0000:00:0e.0" in the /etc/systemd/system/hdmi-audio.path file. Now done. Seems to work, with even less tests. I however have not been able to find out what "pci-0000:00:0e.0" represents, I'll have to dig into this, I'd very much appreciate some pointers here.
 
I undersand you suggest I replace "PathExists=/dev/snd/pcmC1D3p" by "PathExists=/dev/snd/by-path/pci-0000:00:0e.0"
Yes. It means PCI address of the audio device, as listed e.g. by lspci. It's a fairly stable identification, copilot says:

In the output of the lspci command, the Bus, Device, and Function numbers are used to uniquely identify each PCI device in the system. Here is what each term means:

1. Bus Number:
- The bus number indicates which PCI bus the device is connected to. A system can have multiple PCI buses, each with its own unique number. The bus number helps to identify which specific bus the device is on.

2. Device Number:
- The device number is used to identify a specific device on a particular PCI bus. Each bus can support up to 32 devices, and each device is assigned a unique number from 0 to 31.

3. Function Number:
- The function number identifies a specific function within a PCI device. Some PCI devices can perform multiple functions, and each function is assigned a unique number from 0 to 7. If a device supports only a single function, the function number is typically 0.

The combination of Bus, Device, and Function numbers forms a unique identifier for each PCI device in the system. This is usually represented in the format bus:device.function, for example, 00:1f.2.

### Example
Code:
$ lspci
00:1f.2 SATA controller: Intel Corporation 82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (rev 03)

In this example:
  • 00 is the bus number.
  • 1f is the device number.
  • 2 is the function number.

This unique identifier helps the system and users to locate and manage specific PCI devices.
 
  • Thank You
Reactions: danhilu
Update: the configuration based on @phofman indication above, which I have detailed in message #7 above, is running now for about 3 weeks unchanged on my Dell Wyse headless ubuntu server connected by HDMI to my RX-V1700 Yamaha Receiver. Both second hand here on Ricardo in Switzerland, total aboutt 110€. Works like a charm, HDMI connection is always active when needed, even if the Receiver is not connected to an ouput HDMI screen. I had to add a "DisplayPort to HDMI" cable since the Dell Wyse5070 has no HDMI out - another 8€ or so. Thank you all for the help here.