What I want is to be able to consistently tell apart multiple USB sound cards, identify them by the USB port they're plugged in and use that knowledge to play a sound on a speciffic sound card in my Java program.
So far I'm stuck on the first part - identify sound cards by the USB port.
First thing I did is to follow advice in this question and use the Udev rules to assign names to sound cards with the script from this site
These are the Udev rules I added
KERNEL=="controlC[0-9]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", NAME="snd/%c{1}"
KERNEL=="hwC[D0-9]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", NAME="snd/%c{1}"
KERNEL=="midiC[D0-9]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", NAME="snd/%c{1}"
KERNEL=="pcmC[D0-9cp]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", NAME="snd/%c{1}"
and these are the contents of alsa_name.pl
use strict;
use warnings;
#
my $alsaname = $ARGV[0]; #udev called us with this argument (%k)
my $physdevpath = $ENV{PHYSDEVPATH}; #udev put this in our environment
my $alsanum = "cucu";
#you can find the physdevpath of a device with "udevinfo -a -p $(udevinfo -q path -n /dev/snd/pcmC0D0c)"
#
#
$physdevpath =~ s/.*\/([^\/]*)/$1/; #eliminate until last slash (/)
$physdevpath =~ s/([^:]*):.*/$1/; #eliminate from colon (:) to end_of_line
#
if($physdevpath eq "1-1.3.1")
{
$alsanum="11";
}
if($physdevpath eq "1-1.3.2")
{
$alsanum="12";
}
if($physdevpath eq "1-1.3.3")
{
$alsanum="13";
}
if($physdevpath eq "1-1.3.4")
{
$alsanum="14";
}
#
if($alsanum ne "cucu")
{
$alsaname=~ s/(.*)C([0-9]+)(.*)/$1C$alsanum$3/;
}
#
print $alsaname;
exit 0;
Now, when I plug my USB sound card and look at /var/log/syslog I see that it doesn't exactly work:
NAME="snd/%c{1}" ignored, kernel device nodes cannot be renamed; please fix it in /etc/udev/rules.d/99-com.rules:16
I tried to modify my Udev rules based on this repository which provides an Udev rule:
SUBSYSTEM!="sound", GOTO="my_usb_audio_end"
ACTION!="add", GOTO="my_usb_audio_end"
DEVPATH=="/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/sound/card?", ATTR{id}="SPEAKER"
DEVPATH=="/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/sound/card?", ATTR{id}="HEADSET"
LABEL="my_usb_audio_end"
So I used my previous script and modified my rule:
KERNEL=="pcmC[D0-9cp]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", ATTR{id}="snd/%c{1}
but now syslog tells me:
error opening ATTR{some_very_long_id} for writing: Permission denied
I also tried this answer and did
KERNEL=="pcmC[D0-9cp]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", SYMLINK+="snd/%c{1}
I don't see any errors in syslog, which I suppose is good, but when I list playback devices with aplay -l, all I see is
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
and nothing changes, regardles of which USB port I plug it in. I also see no useful/distinguishable info in my Java program using AudioSystem.getMixerInfo()
Is my approach correct and I'm just missing some detail, or this is completely wrong direction?