• WANTED: Happy members who like to discuss audio and other topics related to our interest. Desire to learn and share knowledge of science required. 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
32
Likes
24
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