You are not logged in.
Pages: 1
I'm trying to use udev and systemd to change my audio output to hdmi when hdmi is plugged in and change it back when it is removed. After reading around it seems that firing off a systemd service from udev is the right why to do it. Currently this is what I have:
Udev rule:
cat /etc/udev/rules.d/hdmi_sound.rules ~
KERNEL=="card0", SUBSYSTEM=="drm", ACTION=="change", ENV{SYSTEMD_WANTS}=="hdmitoggle.service"
Systemd service:
cat /etc/systemd/system/hdmitoggle.service ~
[Unit]
Description=Toggle audio when hdmi inserted or removed
[Service]
ExecStart=/etc/pulse/hdmi-toggle.sh
User=georgia
Script:
cat /etc/pulse/hdmi-toggle.sh ~
#! /bin/bash
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>/home/georgia/log.out 2>&1
#export PULSE_RUNTIME_PATH="/run/user/1000/pulse/"
#export DISPLAY=:0
read hdmi_status < /sys/class/drm/card0-HDMI-A-1/status
echo $hdmi_status
if [[ $hdmi_status == "connected" ]]; then
echo "trying to set to hdmi"
pacmd "set-card-profile 0 output:hdmi-stereo"
else
echo "trying to set to analog"
pacmd "set-card-profile 0 output:analog-stereo"
fi
The first three lines set the rest of the script to redirect stdout to ~/log.out. The confusing thing is the systemd service seems to only get run on boot (it is not enabled) and is not run when I unplug or plug in the hdmi. There is also an issue whereby pacmd doesn't seem to be able to see the PulseAudio daemon but this could be because it is getting called during boot.
I should note that the script works fine when just run normally. Also the contents of ~/log.out are (after the service runs during boot):
cat log.out ~
/etc/pulse/hdmi-toggle.sh: line 8: /sys/class/drm/card0-HDMI-A-1/status: No such file or directory
trying to set to analog
No PulseAudio daemon running, or not running as session daemon.
log.out looks like this after just running it normally:
disconnected
trying to set to analog
Last edited by thelollies (2014-07-28 05:21:12)
Offline
I've never been very good with udev rules - but that one just doesn't seem right. It doesn't do anything. The last element is just a further match criteria so the rule is only processed when there is already an environment variable with that name and value.
You could replace that systemd part with a RUN+= call to your script - though I don't know if this is the best way.
EDIT: I just did some research - and I may be mostly wrong about the above ... except for the difference between the double and single equals. So at very least you'll need to change that.
Last edited by Trilby (2014-07-27 23:01:03)
"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" - Richard Stallman
Offline
Admittedly I've never written a udev rule before, I assumed that the systemd_wants part was firing off the service. I modified it from here: http://jasonwryan.com/blog/2014/01/20/udev/
Offline
Well JWR definitely knows better than me - but I still suspect the double quotesequals (edit dumd typo) may be a typo in his blog. See here: http://www.reactivated.net/writing_udev_rules.html#env
Last edited by Trilby (2014-07-30 19:59:15)
"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" - Richard Stallman
Offline
Ah I see what you're saying, I've changed it to single =. Unfortunately the script still doesn't seem to be run (I realised I had the service enabled so I've disabled it and it no longer runs on boot which is good).
It now looks like:
cat /etc/udev/rules.d/hdmi_sound.rules ~
KERNEL=="card0", SUBSYSTEM=="drm", ACTION=="change", ENV{SYSTEMD_WANTS}="hdmitoggle.service"
I should add that this is the result of running udevadm monitor whilst I plug in and then unplug the hdmi:
KERNEL[313.446792] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV [313.448608] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
KERNEL[313.560896] change /devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight (backlight)
UDEV [313.561469] change /devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight (backlight)
KERNEL[314.287011] change /devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight (backlight)
UDEV [314.287933] change /devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight (backlight)
KERNEL[319.444255] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV [319.446045] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
KERNEL[319.534471] change /devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight (backlight)
UDEV [319.535301] change /devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight (backlight)
KERNEL[320.283677] change /devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight (backlight)
UDEV [320.284648] change /devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight (backlight)
Last edited by thelollies (2014-07-27 23:16:12)
Offline
Hi, could you try it with this for systemd
Btw. you can log with syslog or journal(which is standard)
[Unit]
Description=Toggle audio when hdmi inserted or removed
[Service]
ExecStart=/etc/pulse/hdmi-toggle.sh
Type=oneshot
RemainAfterExit=yes
StandardOutput=syslog
User=georgia
[Install]
WantedBy=multi-user.target
Offline
Hi, could you try it with this for systemd
Btw. you can log with syslog or journal(which is standard)[Unit] Description=Toggle audio when hdmi inserted or removed [Service] ExecStart=/etc/pulse/hdmi-toggle.sh Type=oneshot RemainAfterExit=yes StandardOutput=syslog User=georgia [Install] WantedBy=multi-user.target
No luck. After rebooting and trying again the hdmi still doesn't trigger the script. I'm not even sure the udev rule is running the service, is there a way to verify this? If I run
udevadm test --action="change" /devices/pci0000:00/0000:00:02.0/drm/card0
the log.out file is not generated and nothing appears in
systemctl status hdmitoggle.service -l
Offline
I found that I needed to tag my udev rule but this still didn't help. In the end I started to doubt whether handing off to a systemd service which in turn hands off to a script made sense so decided to go back to using RUN+= to run a script straight from UDEV. I tinkered with my script and managed to get it working through udev, the end product:
cat /etc/pulse/hdmitoggle.sh
#! /bin/bash
printenv
export PULSE_RUNTIME_PATH="/run/user/1000/pulse/"
export DISPLAY=:0
read hdmi_status < /sys/class/drm/card0-HDMI-A-1/status
echo $hdmi_status
sleep 1
if [[ $hdmi_status == "connected" ]]; then
pacmd set-card-profile 0 "output:hdmi-stereo"
else
pacmd set-card-profile 0 "output:analog-stereo"
fi
cat /etc/udev/rules.d/10-local.rules
SUBSYSTEM=="drm", ACTION=="change", RUN+="/bin/bash /etc/pulse/hdmitoggle.sh"
Offline
The reason you would hand it off to systemd is because udev does not handle any long running processes. So if you script happens to get stuck somewhere, udev will actually just kill it.
That said, I know others who have used RUN+="/path/to/script" just fine for this type of thing.
Offline
Yeah that's why I went down the systemd path in the first place until it occured to me that my script should only run for a very short amount of time. For future reference, any idea why I couldn't get the systemd handoff working correctly? At best it only ran once (at boot).
Offline
Pages: 1