• Welcome to ASR. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

A python script for CamillaDSP does not work when launched by an udev rule

stemag

Member
Joined
Nov 1, 2022
Messages
36
Likes
29
My digital audio chain is as follows:
piCorePlayer 8.2.0 RPi4 --> latest DiepPi running CamillaDSP on RPi4 --> USB DAC

I use the following udev rule to launch a python script when the USB DAC becomes available (e.g. after switching from the optical input to the USB input):
Code:
SUBSYSTEM=="usb", ACTION=="add", ENV{ID_VENDOR_ID}=="152a", ENV{ID_MODEL_ID}=="85dd", RUN+="/usr/bin/su dietpi -c '/usr/bin/python3 /home/dietpi/myscript.py'"

The script uses the pycamilladsp library to communicate with CamillaDSP via a websocket.
The rule triggers as expected but, unfortunately, the script produces the following IOError:
Code:
[Errno 110] Connection timed out

I verified that camilladsp is not restarted, as its pid stays the same.
Note that the script runs quite well if launched in a dietpi user terminal.

Any help would be much appreciated.
 
Last edited:
The python script looks something like this:
Python:
#!/usr/bin/python3

import sys
from camilladsp import CamillaConnection, CamillaError

c = CamillaConnection("127.0.0.1", 1234)

msg = ""

try:
    c.connect()

    rate = c.get_capture_rate()

    print("Sample Rate = {}".format(rate))


except ConnectionRefusedError as e:
    msg = "Can't connect to CamillaDSP, is it running? Error:" + str(e)
    retry = True
except camilladsp.CamillaError as e:
    msg = "CamillaDSP replied with error:" + str(e)
    retry = True
except IOError as e:
    msg = "Websocket is not connected:" + str(e)
    retry = True
finally:
    print(msg)
    c.disconnect()

I could not solve the problem. I suspect that it is caused by security measures that prevent certain operations.
I ended up getting the udev rule to send a message on a local fifo. The process that receives the message then launches the python script.
This is the rule under /etc/udev/rules.d:
Code:
SUBSYSTEM=="usb", ACTION=="bind", ENV{ID_VENDOR_ID}=="152a", ENV{ID_MODEL_ID}=="85dd", RUN+="/usr/bin/su dietpi -c '/usr/bin/echo dac_is_ready > /tmp/usb_event.fifo
Obviously, the ID_VENDOR_ID and ID_MODEL_ID parameters are those of my DAC (Topping DO100).
And this is the bash script of the receiving process:
Bash:
#!/bin/sh
#
FIFO="/tmp/usb_event.fifo

rm -f $FIFO >/dev/null
mkfifo $FIFO

while true
    do
        if read event < $FIFO
        then
            case $event in
            dac_is_ready)
                echo $(date) "DAC is available for playback"
                /usr/bin/python3 /home/dietpi/myscript.py
                ;;
            *)
                echo "Unknown event"
            esac
      fi
done

A bit tricky, but it works. I hope this will help those who are experiencing the same issue.
 
Last edited:
$man udev
Note that running programs that access the network or mount/unmount filesystems is not allowed inside of udev rules, due to the default sandbox that is enforced on systemd-udevd.service.
 
$man udev
Note that running programs that access the network or mount/unmount filesystems is not allowed inside of udev rules, due to the default sandbox that is enforced on systemd-udevd.service.
I suspected something like this. thanks for the information.
 
Maybe using the SYSTEMD_WANTS property would be more systemd-isch than the hack with at. It is mentioned also in the manpage and commonly used for running units when a device appears.

Also telling systemd to start a unit directly would be an alternative, as in https://unix.stackexchange.com/a/550281
 
Maybe using the SYSTEMD_WANTS property would be more systemd-isch than the hack with at. It is mentioned also in the manpage and commonly used for running units when a device appears.
That seems interesting. Would yuo please elaborate a little? Thank you.
 
This is an example of systemd-style integration of udev with the linux usb gadget https://www.collabora.com/news-and-...-and-how-to-integrate-it-with-systemd-part-1/ - upon appearance of the device the gadget configuration gets called. You should be able to call your python script from the service unit. Since it's a full-blown unit, not just a quick script to satisfy udev requirements, maybe you can put more functionality into your python controller.
 
Back
Top Bottom