borine / bluealsa-monitor

Helper script for managing ALSA configurations with BlueALSA
The Unlicense
0 stars 0 forks source link

aplay -L does not list BT device #1

Closed gearhead closed 2 years ago

gearhead commented 2 years ago

Built bluealsa from git (Version 3.1.0.r90.g0c9d8c1) and this repo as well (Version r15.f07fdd6) I have bluealsa, bluealsa-aplay and bluealsa-monitor running. I do not know if I am expecting the right thing, but my expectation is that if all 3 are running and I connect a headphone that it will show up in 'aplay -L'. I do not get that. Do I understand correctly?

I did make one change to your bluealsa-monitor.service file. I added a 'User=http' to it and bluealsa-aplay.service as we have many services running as user http, though no user is logged in. Bluealsa is still being run as a service as root (it will not run as http). I am guessing that permissions or ownership is the problem? Will this allow the permissions to be set properly?

I have the config file in http's home directory. I have a /etc/dbus-1/system.d/bluealsa.conf file which was installed with the latest bluealsa package I built.

As user http:

$ pwd
/srv/http
$ cat .local/bluealsa-monitor/asoundrc
# DO NOT EDIT - automatically managed by bluealsa-monitor service
bluealsa.default.capture.pcm {
type asym
capture.pcm "pcm.bluealsa:PROFILE=a2dp"
playback.pcm {
@func refer
name "bluealsa.default.playback.fallback"
default sysdefault
}
hint.show on
hint.description "Capture: Bluetooth default, Playback: sysdefault"
}
bluealsa.default.playback.pcm {
type asym
capture.pcm {
@func refer
name "bluealsa.default.capture.fallback"
default sysdefault
}
playback.pcm "pcm.bluealsa:PROFILE=a2dp"
hint.show on
hint.description "Capture: sysdefault, Playback: Bluetooth default"
}
bluealsa.default.duplex.pcm {
type empty
slave.pcm "pcm.bluealsa:PROFILE=a2dp"
hint.show on
hint.description "Bluetooth default"
}
namehint.ctl.bluealsa "bluealsa|BlueALSA global control device"~$ cat .local/bluealsa-monitor/asoundrc
# DO NOT EDIT - automatically managed by bluealsa-monitor service
bluealsa.default.capture.pcm {
type asym
capture.pcm "pcm.bluealsa:PROFILE=a2dp"
playback.pcm {
@func refer
name "bluealsa.default.playback.fallback"
default sysdefault
}
hint.show on
hint.description "Capture: Bluetooth default, Playback: sysdefault"
}
bluealsa.default.playback.pcm {
type asym
capture.pcm {
@func refer
name "bluealsa.default.capture.fallback"
default sysdefault
}
playback.pcm "pcm.bluealsa:PROFILE=a2dp"
hint.show on
hint.description "Capture: sysdefault, Playback: Bluetooth default"
}
bluealsa.default.duplex.pcm {
type empty
slave.pcm "pcm.bluealsa:PROFILE=a2dp"
hint.show on
hint.description "Bluetooth default"
}
namehint.ctl.bluealsa "bluealsa|BlueALSA global control device"

With bluealsa-aplay, I get this: $ bluealsa-aplay -l List of PLAYBACK Bluetooth Devices bluealsa-aplay: W: Couldn't get BlueZ device properties: Rejected send message, 3 matched rules; type="method_call", sender=":1.313" (uid=33 pid=7626 comm="bluealsa-aplay -l ") interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply="0" destination="org.bluez" (uid=0 pid=305 comm="/usr/lib/bluetooth/bluetoothd ") : 70:BF:92:D8:82:84 [], A2DP (SBC): S16_LE 2 channels 48000 Hz SCO (CVSD): S16_LE 1 channel 8000 Hz List of CAPTURE Bluetooth Devices bluealsa-aplay: W: Couldn't get BlueZ device properties: Rejected send message, 3 matched rules; type="method_call", sender=":1.313" (uid=33 pid=7626 comm="bluealsa-aplay -l ") interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply="0" destination="org.bluez" (uid=0 pid=305 comm="/usr/lib/bluetooth/bluetoothd ") : 70:BF:92:D8:82:84 [], SCO (CVSD): S16_LE 1 channel 8000 Hz

The device in question is attached and shows no errors when I look for it as root:

# bluealsa-aplay -l
**** List of PLAYBACK Bluetooth Devices ****
hci0: 70:BF:92:D8:82:84 [Jabra Evolve2 65], audio-headset
  A2DP (SBC): S16_LE 2 channels 48000 Hz
  SCO (CVSD): S16_LE 1 channel 8000 Hz
**** List of CAPTURE Bluetooth Devices ****
hci0: 70:BF:92:D8:82:84 [Jabra Evolve2 65], audio-headset
  SCO (CVSD): S16_LE 1 channel 8000 Hz

but alsa does not know about it:

# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Headphones [bcm2835 Headphones], device 0: bcm2835 Headphones [bcm2835 Headphones]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7
card 1: sndrpihifiberry [snd_rpi_hifiberry_dacplus], device 0: HiFiBerry DAC+ Pro HiFi pcm512x-hifi-0 [HiFiBerry DAC+ Pro HiFi pcm512x-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
# aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
lavrate
    Rate Converter Plugin Using Libav/FFmpeg Library
samplerate
    Rate Converter Plugin Using Samplerate Library
speexrate
    Rate Converter Plugin Using Speex Resampler
jack
    JACK Audio Connection Kit
oss
    Open Sound System
pipewire
    PipeWire Sound Server
pulse
    PulseAudio Sound Server
speex
    Plugin using Speex DSP (resample, agc, denoise, echo, dereverb)
upmix
    Plugin for channel upmix (4,6,8)
vdownmix
    Plugin for channel downmix (stereo) with a simple spacialization
default:CARD=Headphones
    bcm2835 Headphones, bcm2835 Headphones
    Default Audio Device
sysdefault:CARD=Headphones
    bcm2835 Headphones, bcm2835 Headphones
    Default Audio Device
usbstream:CARD=Headphones
    bcm2835 Headphones
    USB Stream Output
default:CARD=sndrpihifiberry
    snd_rpi_hifiberry_dacplus, HiFiBerry DAC+ Pro HiFi pcm512x-hifi-0
    Default Audio Device
sysdefault:CARD=sndrpihifiberry
    snd_rpi_hifiberry_dacplus, HiFiBerry DAC+ Pro HiFi pcm512x-hifi-0
    Default Audio Device
usbstream:CARD=sndrpihifiberry
    snd_rpi_hifiberry_dacplus
    USB Stream Output

and as user http, it also has errors:

$ bluealsa-aplay -L
bluealsa-aplay: W: Couldn't get BlueZ device properties: Rejected send message, 3 matched rules; type="method_call", sender=":1.315" (uid=33 pid=7688 comm="bluealsa-aplay -L ") interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply="0" destination="org.bluez" (uid=0 pid=305 comm="/usr/lib/bluetooth/bluetoothd ")
bluealsa:SRV=org.bluealsa,DEV=70:BF:92:D8:82:84,PROFILE=a2dp
    , , playback
    A2DP (SBC): S16_LE 2 channels 48000 Hz
bluealsa:SRV=org.bluealsa,DEV=70:BF:92:D8:82:84,PROFILE=sco
    , , playback
    SCO (CVSD): S16_LE 1 channel 8000 Hz
bluealsa:SRV=org.bluealsa,DEV=70:BF:92:D8:82:84,PROFILE=sco
    , , capture
    SCO (CVSD): S16_LE 1 channel 8000 Hz
borine commented 2 years ago

Well, you definitely have D-Bus permission issues for the http user, that will prevent both bluealsa-aplay and bluealsa-cli from functioning correctly. My guess is that either user http is not a member of the audio group, or you have not restarted the D-Bus daemon to make it re-read the group membership. If that guess is wrong, then its difficult for me to see exactly what is wrong - I am not an expert at troubleshooting D-Bus errors.

Also, I am surprised that the bluealsa-monitor data file is being placed under ~http/.local/ - when used with systemd the user temporary runtime data directory ($XDG_RUNTIME_DIR) is normally /run/user/$(id -u http)/

borine commented 2 years ago

So I think the lack of $XDG_RUNTIME_DIR is because this is a system session, not a user session. I'll have to think of a better location for the data file in this case - possibly /var, or maybe there is a way to have the .system file tell systemd to create a directory under /run before it starts the service. The reason I would prefer to avoid /home is that is most likely on the sdcard, whereas I think we should be using a tmpfs for this data.

gearhead commented 2 years ago

Thanks for looking into this. I did check and bluealsa is a member of the audio group:

# groups http
audio render video weston-launch http

I have run around in circles with weston witha similar issue as weston is also designed to be run as a user yet in our 'kiosk' type setup it needs to be started by the system. To do all this, I set XDG and other environment variables like I do when I start weston/luakit. when I start it, I first start weston and need to go through gyrations with it, then need to start luakit and can start it as http user/group.

in the weston.service I created, I use this:

...
Group=http  # systemd will allow me to set the group
RuntimeDirectory=weston
RuntimeDirectoryMode=0755
Environment="XDG_RUNTIME_DIR=/run/weston"
ExecStart=/usr/bin/weston --tty=1 --log=/var/log/runeaudio/weston.log --config=/srv/http/.config/weston.ini --modules=systemd-notify.so
ExecStartPost=/usr/bin/chown -R http:http /run/weston/  # need to change ownership after the folder is created 

then when I start luakit, it can start as user http but I have to manually set the environment

[Service]
Type=simple
User=http
Group=http
WorkingDirectory=/srv/http
Environment="HOME=/srv/http"
Environment="XDG_RUNTIME_DIR=/run/weston"
Environment="WAYLAND_DISPLAY=wayland-0"
Environment="XDG_SESSION_TYPE=wayland"
Environment="GDK_BACKEND=wayland"
ExecStartPre=/bin/sleep 2
ExecStart=/usr/bin/luakit localhost

I can try something similar to this with bluealsa-monitor and see how far I get.

gearhead commented 2 years ago

I tried this and get what I think is what it is 'supposed' to be, but you will have to guide me a bit...

[Unit]
Description=Bluealsa PCM manager
Documentation=https://github.com/borine/bluealsa-monitor

[Service]
Type=simple
Group=http
RuntimeDirectory=bluealsa-monitor
RuntimeDirectoryMode=0755
Environment="XDG_RUNTIME_DIR=/run"
Environment="HOME=/srv/http"
ExecStart=/usr/bin/bluealsa-monitor
ExecStartPost=/usr/bin/chown -R http:http /run/bluealsa-monitor

[Install]
WantedBy=default.target

This starts without error but still nothing under aplay -l and I get this file structure so asoundrc is not owned by http. Maybe I need to wait a second then chown it... :

# ls -al /run/bluealsa-monitor/
total 4
drwxr-xr-x  2 http http   60 Jan 31 10:03 .
drwxrwxrwx 29 root root  660 Jan 31 10:03 ..
-rw-r--r--  1 root http 1253 Jan 31 10:04 asoundrc
gearhead commented 2 years ago

I added a delay in the service file ExecStartPost=/bin/sleep 2 and now I get the /run/bluealsa-monitor set as I think it needs to be and no errors showing with bluealsa-monitor:

# ls -al /run/bluealsa-monitor/
total 4
drwxr-xr-x  2 http http   60 Jan 31 10:12 .
drwxrwxrwx 29 root root  660 Jan 31 10:03 ..
-rw-r--r--  1 http http 1253 Jan 31 10:13 asoundrc

I attached my headphones and they show up in bluealsa-aplay -l but not in aplay -l. I did verify that my folder with the config is in /srv/http/.config/environment.d/bluealsa-monitor-env.conf and is owned by http.

I do get this in the journal but do not know if they mean anything substantial to this experiment:

Jan 31 10:27:53 rune64 bluetoothd[301]: src/profile.c:ext_connect() Headset Voice gateway failed connect to 70:BF:92:D8:82:84: Connection refused (111)
Jan 31 10:27:53 rune64 bluetoothd[301]: Endpoint registered: sender=:1.8 path=/org/bluez/hci0/A2DP/SBC/source/3
Jan 31 10:27:53 rune64 bluealsa[396]: /usr/bin/bluealsa: W: Unsupported AT message: SET: command:+CLIP, value:1
Jan 31 10:27:53 rune64 kernel: input: Jabra Evolve2 65 (AVRCP) as /devices/virtual/input/input1
Jan 31 10:27:54 rune64 systemd-logind[2479]: Watching system buttons on /dev/input/event1 (Jabra Evolve2 65 (AVRCP))
borine commented 2 years ago

You are now running bluealsa-monitor as root - is that intentional? Previously you had User=http in the .service file. The script here has not been security-checked for running as root, so I have no idea what kind of risk you are running here.

Please can you confirm what user account you run bluealsa under, and also post the contents of /run/bluealsa-monitor/asoundrc when the headphones are connected; and also how have you set the environment variable ALSA_CONFIG_PATH - the user that runs aplay must have that set correctly in the environment. The example bluealsa-monitor-env.conffile given in the source is for use with user sessions, not system sessions. One way to fix the environment for all users is to create the file /etc/environment.d/99-bluealsa-monitor.conf with the contents:

ALSA_CONFIG_PATH=/usr/share/alsa/alsa.conf:/run/bluealsa-monitor/asoundrc
gearhead commented 2 years ago

I have not set ALSA_CONFIG_PATH anywhere that I am aware of. Running as I noted above, the contents of the asoundrc under /run/bluealsa-monitor are the basic config plus:

# cat /run/bluealsa-monitor/asoundrc
...
namehint.pcm.bluealsa70BF92D88284scoOutput "bluealsa:DEV=70:BF:92:D8:82:84,PROFILE=sco|Jabra Evolve2 65, HFP (CVSD)|IOIDOutput"
namehint.ctl.bluealsa70BF92D88284 "bluealsa:DEV=70:BF:92:D8:82:84|Jabra Evolve2 65 control device"
namehint.pcm.bluealsa70BF92D88284scoInput "bluealsa:DEV=70:BF:92:D8:82:84,PROFILE=sco|Jabra Evolve2 65, HFP (CVSD)|IOIDInput"
namehint.pcm.bluealsa70BF92D88284a2dpOutput "bluealsa:DEV=70:BF:92:D8:82:84,PROFILE=a2dp|Jabra Evolve2 65, A2DP (SBC)|IOIDOutput"

I set the user back to User=http for security concerns and restarted. I verified that the structure under /run is all still owned by http. I deleted the conf under /srv/http/.config created a /etc/environment.d directory then put in the suggested info in 99-bluealsa-monitor.conf

# cat /etc/environment.d/99-bluealsa-monitor.conf
ALSA_CONFIG_PATH=/usr/share/alsa/alsa.conf:/run/bluealsa-monitor/asoundrc

and restarted and now nothing useful appears in /run/bluealsa-monitor/asoundrc. For some reason, it must be running as root for the info to appear in /run/bluealsa-monitor/asoundrc. I still get nothing in aplay -l or aplay -L. When I change the *.service back to running bluealsa-monitor as root, the asoundrc populates, but I still get nothing in 'aplay -l'.

borine commented 2 years ago

For some reason, it must be running as root for the info to appear

Ok that's something to do with systemd. More reading required. My suspicion is that the RuntimeDirectory= setting is being applied as user http, so is failing. There must be some way to fix that, but I don't know what it is yet.

I still get nothing in 'aplay -l'

Please can you report the result of

echo $ALSA_CONFIG_PATH

from the terminal in which you are running aplay -l

You may need to reboot to get the new environment applied to user sessions.

borine commented 2 years ago

I've just run a test on my system. /usr/local/lib/systemd/system/bluealsa-monitor.service

[Unit]
Description=Bluealsa PCM manager
Documentation=https://github.com/borine/bluealsa-monitor

[Service]
Type=simple
User=http
Group=http
RuntimeDirectory=bluealsa-monitor
RuntimeDirectoryMode=0755
Environment="XDG_RUNTIME_DIR=/run"
ExecStart=/usr/bin/bluealsa-monitor

[Install]
WantedBy=default.target
$ groups http
http: http audio

/etc/environment.d/99-bluealsa-monitor.conf

ALSA_CONFIG_PATH=/usr/share/alsa/alsa.conf:/run/bluealsa-monitor/asoundrc

reboot to force the revised global environment setting

sudo systemctl start bluealsa-monitor.service
$ ls -l /run/bluealsa-monitor
-rw-r--r-- 1 http http 1245 Jan 31 18:38 asoundrc

connect bluetooth speaker

$ cat /run/bluealsa-monitor/asoundrc
# DO NOT EDIT - automatically managed by bluealsa-monitor service
bluealsa.default.capture.pcm {
type asym
capture.pcm "pcm.bluealsa:PROFILE=a2dp"
playback.pcm {
@func refer
name "bluealsa.default.playback.fallback"
default sysdefault
}
hint.show on
hint.description "Capture: Bluetooth default, Playback: sysdefault"
}
bluealsa.default.playback.pcm {
type asym
capture.pcm {
@func refer
name "bluealsa.default.capture.fallback"
default sysdefault
}
playback.pcm "pcm.bluealsa:PROFILE=a2dp"
hint.show on
hint.description "Capture: sysdefault, Playback: Bluetooth default"
}
bluealsa.default.duplex.pcm {
type empty
slave.pcm "pcm.bluealsa:PROFILE=a2dp"
hint.show on
hint.description "Bluetooth default"
}
namehint.ctl.bluealsa "bluealsa|DESCBlueALSA global control device"

namehint.pcm.bluealsa5CF3709BFB1AscoOutput "bluealsa:DEV=5C:F3:70:9B:FB:1A,PROFILE=sco|DESCmusicroom, HFP (CVSD)|IOIDOutput"
namehint.ctl.bluealsa5CF3709BFB1A "bluealsa:DEV=5C:F3:70:9B:FB:1A|DESCmusicroom control device"
namehint.pcm.bluealsa5CF3709BFB1AscoInput "bluealsa:DEV=5C:F3:70:9B:FB:1A,PROFILE=sco|DESCmusicroom, HFP (CVSD)|IOIDInput"
namehint.pcm.bluealsa5CF3709BFB1Aa2dpOutput "bluealsa:DEV=5C:F3:70:9B:FB:1A,PROFILE=a2dp|DESCmusicroom, A2DP (SBC)|IOIDOutput"
$ echo $ALSA_CONFIG_PATH
/usr/share/alsa/alsa.conf:/run/bluealsa-monitor/asoundrc
$ aplay -L
surround21
    2.1 Surround output to Front and Subwoofer speakers
surround40
    4.0 Surround output to Front and Rear speakers
surround41
    4.1 Surround output to Front, Rear and Subwoofer speakers
surround50
    5.0 Surround output to Front, Center and Rear speakers
surround51
    5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71
    7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
default
    Default Audio Device
usbstream:CARD=PCH
    HDA Intel PCH
    USB Stream Output
bluealsa:DEV=5C:F3:70:9B:FB:1A,PROFILE=sco
    musicroom, HFP (CVSD)
bluealsa:DEV=5C:F3:70:9B:FB:1A,PROFILE=a2dp
    musicroom, A2DP (SBC)

So, everything "just works". !!!

gearhead commented 2 years ago

I edited my system to be like you show. I am really close, but my ALSA_CONFIG_PATH is not set. I am running arch linux and it is supposed to be set by the /etc/environment.d/99-bluealsa-monitor.conf, but when I check it is not (as http or as root):

$ echo $ALSA_CONFIG_PATH

If I set it in /etc/environment instead of environment.d/99-bluealsa-monitor.conf, it does seem to set it:

# cat /etc/environment
#
# This file is parsed by pam_env module
#
# Syntax: simple "KEY=VAL" pairs on separate lines
#
ALSA_CONFIG_PATH=/usr/share/alsa/alsa.conf:/run/bluealsa-monitor/asoundrc

and reboot it shows (as either http or root):

$ echo $ALSA_CONFIG_PATH
/usr/share/alsa/alsa.conf:/run/bluealsa-monitor/asoundrc

If I then reboot and reconnect my speaker, I can 'see' it as root:

# bluealsa-aplay -l
**** List of PLAYBACK Bluetooth Devices ****
hci0: 70:BF:92:D8:82:84 [Jabra Evolve2 65], audio-headset
  A2DP (SBC): S16_LE 2 channels 48000 Hz
  SCO (CVSD): S16_LE 1 channel 8000 Hz
**** List of CAPTURE Bluetooth Devices ****
hci0: 70:BF:92:D8:82:84 [Jabra Evolve2 65], audio-headset
  SCO (CVSD): S16_LE 1 channel 8000 Hz

but as user http, it gives an error:

$ bluealsa-aplay -l
**** List of PLAYBACK Bluetooth Devices ****
bluealsa-aplay: W: Couldn't get BlueZ device properties: Rejected send message, 3 matched rules; type="method_call", sender=":1.168" (uid=33 pid=2860 comm="bluealsa-aplay -l ") interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply="0" destination="org.bluez" (uid=0 pid=301 comm="/usr/lib/bluetooth/bluetoothd ")
: 70:BF:92:D8:82:84 [],
  A2DP (SBC): S16_LE 2 channels 48000 Hz
  SCO (CVSD): S16_LE 1 channel 8000 Hz
**** List of CAPTURE Bluetooth Devices ****
bluealsa-aplay: W: Couldn't get BlueZ device properties: Rejected send message, 3 matched rules; type="method_call", sender=":1.168" (uid=33 pid=2860 comm="bluealsa-aplay -l ") interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply="0" destination="org.bluez" (uid=0 pid=301 comm="/usr/lib/bluetooth/bluetoothd ")
: 70:BF:92:D8:82:84 [],
  SCO (CVSD): S16_LE 1 channel 8000 Hz

and the /run/bluealsa-monitor/asoundrc shows nothing added.

It feels really close...

borine commented 2 years ago

Rejected send message, ... destination="org.bluez" ...

So user http is not allowed to send messages to org.bluez. Surprisingly, this is the first time I have realized that in a default install bluealsa-aplay -L only works for users who are members of the bluetooth group; perhaps that needs to be mentioned in the BlueALSA docs.

A quick fix would be to create a new d-bus config file: /etc/dbus-1/system-local.conf

<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>

  <policy user="http">
    <allow send_destination="org.bluez"/>
  </policy>

</busconfig>

Tell dbus to read the new config:

$ sudo systemctl reload dbus

(or reboot if that does not work)

Beware that user http can then administer bluetooth to some extent (eg run programs like bluetoothctl) which needs careful thought, and most likely would not be allowed by a responsible distribution manager.

gearhead commented 2 years ago

That does it, at least I think so. I added that system-local.conf to the folder /etc/dbus-1/systemd/ because that is where the other *.conf files are. Is that OK or should it be the one directory up? When I did that and connected my headphones, they show up:

# aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
(SNIP)...
bluealsa:DEV=70:BF:92:D8:82:84,PROFILE=sco
    Jabra Evolve2 65, HFP (CVSD)
bluealsa:DEV=70:BF:92:D8:82:84,PROFILE=a2dp
    Jabra Evolve2 65, A2DP (SBC)

They do not show up with aplay -l, though. Are they supposed to? Can I make them show up there? I ask this as out script that enables the outputs for the various players all parse aplay -l for the outputs.

borine commented 2 years ago

They do not show up with aplay -l

Correct. aplay -l lists only hardware sound cards. There is no way to get software devices such as bluealsa, jack, pipewire, pulse etc to be listed by that command.

gearhead commented 2 years ago

well, with that, I think it is done. Thanks for the help. IMO, this should be bundled with bluealsa as it is a huge help. I will plug a but with the udev integration as we need to trigger a refresh anyway on our install, but this gives us most of the information we need.