Using udev to play sounds upon USB insertion

[quote=“cacaedu, post:1, topic:5299, full:true”]
Hello everyone!

I’m using Lubuntu to test on an old machine.

I can’t hear any sound when some event happens (notification, USB insertion, etc.).

The sounds (Ogg Vorbis audio files) exist in /usr/share/sounds/freedesktop/stereo, but they are not linked to any event - at least that’s what it seems.

How can I link these audio files to events like notification, USB insertion or system shutdown, for example?

Do I have to write any script?

I asked Gemini and received the following response:

"Here’s how you can create a script to play a sound when a USB device is inserted in Lubuntu, along with explanations to help you understand the process:

Create the Sound File

Choose a sound: Select a short, distinct sound file (e.g., a “ding” or a notification chime). You can find free sound effects online.
Save the sound: Save the sound file in a location where it won’t be accidentally deleted. A good place would be a dedicated folder in your home directory, like ~/sounds/usb_insert.wav.

Create the Script

Open a text editor: Use a text editor like nano or mousepad to create a new file. Let’s name it usb_sound.sh.
Paste the code: Copy and paste the following code into the file:

Bash

#!/bin/bash
Play the sound file

aplay ~/sounds/usb_insert.wav &
Optional: Display a notification
notify-send “USB Device Inserted” “A sound has been played.”

Explanation:
#!/bin/bash: This line tells the system to use Bash to execute the script.
aplay ~/sounds/usb_insert.wav &: This line plays the sound file using the aplay command. The & symbol runs the command in the background so it doesn’t block other actions.
notify-send “USB Device Inserted” “A sound has been played.”: This line is optional. It displays a notification on your screen when the USB is inserted.

Save the file: Save the usb_sound.sh file in a convenient location, such as ~/scripts/.

Make the Script Executable

Open a terminal: Open the Lubuntu terminal.
Navigate to the directory: Use the cd command to navigate to the directory where you saved the script (e.g., cd ~/scripts).
Make it executable: Use the following command to make the script executable:

Bash

chmod +x usb_sound.sh

Configure udev Rules

Create a udev rule file: Open a text editor as administrator (you might need to use sudo) and create a new file named 99-usb-sound.rules in the /etc/udev/rules.d/ directory.
Paste the rule: Copy and paste the following rule into the file:

SUBSYSTEM==“usb”, ACTION==“add”, ENV{UDISKS_PRESENT}!=“1”, RUN+=“/home/yourusername/scripts/usb_sound.sh”

Explanation:
SUBSYSTEM==“usb”: This matches events related to USB devices.
ACTION==“add”: This matches the event of a USB device being added.
ENV{UDISKS_PRESENT}!=“1”: This condition is optional. It prevents the sound from playing if the USB device is a storage device that’s automatically mounted by udisks.
RUN+=“/home/yourusername/scripts/usb_sound.sh”: This specifies the script to run when the rule is matched. Important: Replace /home/yourusername/scripts/usb_sound.sh with the actual path to your script.

Save the file: Save the 99-usb-sound.rules file.

Reload udev Rules

Open a terminal: Open the Lubuntu terminal.
Reload the rules: Use the following command to reload the udev rules:

Bash

sudo udevadm control --reload-rules

Test the Script

Insert a USB device: Insert a USB device into your computer.
Listen for the sound: You should hear the sound file playing. If you included the notification, you should also see it on your screen.

Troubleshooting

Sound not playing:
Double-check the path to the sound file in the script.
Make sure the sound file is in a format that aplay supports (e.g., WAV).
Check the volume level.
Script not executing:
Make sure the script is executable (chmod +x).
Double-check the path to the script in the udev rule.
Check the udev logs for any errors (sudo udevadm monitor --udev).

Let me know if you have any other question."

I did all this and it didn’t work.

Thanks

Carlos-Lubuntu

Edited the title to be a bit more descriptive.

“No System Sounds” could draw (and them mislead) a lot of unrelated future readers.

I think perhaps we’re conflating things. udev is for managing device events, not any events at all. It doesn’t deal with notifications, except those triggered by device events. So if you’re trying to drop an audio file and expect every single notification to somehow use it, that’s really not correct thinking.

That said, what is your ultimate goal here? And if it’s just USB devices, which ones?

Also, I assume you can actually hear sounds (i.e. that aplay command works as expected)?

2 Likes

Hello @wxl !

Yes, the paplay command (not aplay) works fine. My system uses Pulse Audio. The problem is that I want to play the audio when, for example, I insert a USB. In other words, I have to link an audio to the “USB insertion” event.

Do you know how to do this?

Another thing: doesn’t Lubuntu have sounds linked to startup, shutdown, media insertions, etc. by default?

Carlos-Lubuntu

Which USB, though? I mean, I have a USB mouse. Are you only talking about storage devices? Are you talking about particular storage devices?

And, no, we don’t have sounds related to everything. That would be rather annoying in my mind!

Hello.

I’m talking about unspecified USB storage media. For example, any USB stick with music, videos, etc. Just like on Mint or Ubuntu systems. In them, you don’t need to specify anything when inserting a USB stick.

As for whether sounds are annoying, that depends on the individual, of course. Now, they can be very useful, for example, to notify you when a download is finished while you’re doing something else or to notify you about an important email.

That’s my intention about sounds in Lubuntu.

AFAIK then you’ll want your udev rule to use SUBSYSTEM="block".

For everything else, you should create a new topic for each new thing you want to add a sound for because they’re not all going to be the same.

1 Like

Ok. Thanks for your time.

This right there says why you’re not hearing anything when connecting a thumbdrive. Ubuntu and all variants except for server and probably core use udisks2 for automatic mounting.

Anyway, udev scripts are supposed to be very short and quick things, anything that takes more then a few miliseconds should really not be a udev rule because you’re holding up all processing of udev rules.

I’d probably either look into watching udisks2 via dbus and triggering the sound if a new drive comes up in ‘/org/freedesktop/UDisks2/drives/’ (that is not easy to do in a shell script, Python on the other hand could easily do it) or I’d make the udev rule create a file and have a separate script watching a specific directory for new files via inotifywait and then play a sound and remove the file. Or you could just watch /media/$USER/ and play the sound when a new directory is created (which udisks2 does as part of the automounting process) and you could even play a different sound when a directory is removed (when udisks2 unmounts the thumbdrive).

1 Like

Hi @hdd-gehrke!

I’m not using ENV{UDISKS_PRESENT}!=“1”. I’m just using SUBSYSTEM==“block”, ACTION==“change”, RUN+=“/usr/local/bin/toca_usb.sh” in the .rules file. I tried USB and block as SUBSYSTEM values ​​and change and add as ACTION values. Nothing happened.

Regarding your solution, do you know how to implement it?

Carlos_Lubuntu

You should take a look at the udevadm monitor command, it also has several switches so it can output stuff in a way you can directly re-use in rules … just watch which vars get triggered on insertion/removal …

If you’re using paplay as you mention that may be another problem - udev rules are running as root and might not have access to the pulse audio server; that’s why the original script uses aplay (ALSA, communicates directly with the sound hardware).

As far as my solution goes …

#!/bin/bash
while read dir event name rest ; do 
  if [[ $event == 'CREATE,ISDIR' ]] ; then 
    echo $name created;  # put the command to play the 'Device connected' sound here
  fi;
  if [[ $event == 'DELETE,ISDIR' ]] ; then 
    echo $name removed;   # put the command to play the 'Device disconnected' sound here
  fi ;
done < <(inotifywait -m -e create -e delete /media/$USER)

It uses inotifywait in monitor-mode to wait for create and delete events in /media/$USER. This of course means it will not play a sound if something goes wrong while mounting or unmounting the file system on your device …

Put this in a file, put in the commands to play your audio files instead of the ‘echo’-commands, make the file executable, create a desktop file for it, and put the desktop file in ~/.config/autostart/.

No udev rules needed, but if your system brings up a file manager when a new storage device is connected - as mine does - then the acoustic notification is kind of superfluous …

Most desktop environment have a mechanism for system sounds - Gnome does (libcanberra + GSound), XFCE can use the same mechanism with a bit of tweaking, KDE has it’s own, … - but LUbuntu uses lxqt which wants to be especially light weight and foregoes bells and whistles …

2 Likes

With the great help of @hdd-gehrke and Gemini, I put together the 3 codes below.

PLAY USB INSERTION SOUND

#!/bin/bash

# Start the script in the background
/home/my_user/Desktop/usb-sound.sh &

# Save the PID to a file
echo $! > /tmp/usb-sound.pid

echo "Script started in the background. PID: $!"

STOP THE SCRIPT

#!/bin/bash

# Read the PID file
PID=$(cat /tmp/usb-sound.pid)

# Kill the process
kill $PID

# Remove the PID file
rm /tmp/usb-sound.pid

echo "Script completed."

USB SOUND FILE

#!/bin/bash

trap "echo 'finishing script...' && exit" INT TERM # Trap for SIGINT and SIGTERM

while read -r dir event name; do
# Get the full path of the file/folder
filepath="$dir/$name"

if [[ "$event" == "CREATE,ISDIR" ]]; then
paplay /usr/share/sounds/freedesktop/stereo/service-login.oga # Sound to play
elif [[ "$event" == "DELETE,ISDIR" ]]; then
paplay /usr/share/sounds/freedesktop/stereo/service-logout.oga # Different sound to remove (change to the desired sound)
fi
done < <(inotifywait -m -e create -e delete /media/$USER)

My idea with this was “how to solve this problem/code challenge” as well as hearing the sound at certain times for certain events.

Carlos-Lubuntu

Why separate start and stop scripts ? You can get the pid of the running shell with “$$” in the main script and put that in the .pid file. You could also put a check for the existence of such a file at the start of the main script, kill the old instance and exit.