Hallo zusammen,
das hier beschriebene Setup hat nach einem apt upgrade irgendwie nicht mehr so richtig funktioniert.
Die Verbindung zu den Bluetooth-Lautsprecher machten dabei Probleme. Da das Stretch heute auch nicht mehr taufrisch ist, entschied ich mich ein Bookworm zu installieren und das gleiche Setup aufzusetzen.
Woran es am Ende gelegen hat, vermag ich mangels weiterer Nachforschungen im alten Betriebssystem nicht zu sagen.
Jetzt ergab sich amüsanterweise nach dem BT-Koppeln ein Problem beim Pulseaudio-Part. Die Sinks konnten nicht gefunden werden! Da habe ich erst mal doof geschaut.![]()
Mittlerweile gibt es ja auch Pipewire, welches z.B. im Hintergrund mit Pulseaudio-Bibliotheken läuft. Kann man das so sagen? Ich schreib's jetzt einfach mal so.
Also habe ich mich an das Pipewire rangemacht, da es ja auch moderner ist.
Zusätzlich zum alten Setup habe ich noch ein paar UDEV-Regel hinterlegt, um möglichst viel zu automatisieren.
Ziel ist wieder, zwei Bluetooth-Lautsprecher als Stereo-Paar, die sich automatisch koppen; Musik kommt vom mpd.
Diese Pakete habe ich drauf:
pi@raspi-3:~ $ dpkg -l | grep blue
ii bluez 5.66-1+rpt1+deb12u1 armhf Bluetooth tools and daemons
ii bluez-firmware 1.2-9+rpt3 all Firmware for Bluetooth devices
ii libbluetooth3:armhf 5.66-1+rpt1+deb12u1 armhf Library to use the BlueZ Linux Bluetooth stack
ii libspa-0.2-bluetooth:armhf 0.3.65-3+rpt8+deb12u1 armhf libraries for the PipeWire multimedia server - bluetooth plugins
ii pi-bluetooth 0.1.20 all Raspberry Pi 3 bluetooth
pi@raspi-3:~ $ dpkg -l| grep pipewire
ii libpipewire-0.3-0:armhf 0.3.65-3+rpt8+deb12u1 armhf libraries for the PipeWire multimedia server
ii libpipewire-0.3-common 0.3.65-3+rpt8+deb12u1 all libraries for the PipeWire multimedia server - common files
ii libpipewire-0.3-modules:armhf 0.3.65-3+rpt8+deb12u1 armhf libraries for the PipeWire multimedia server - modules
ii pipewire:armhf 0.3.65-3+rpt8+deb12u1 armhf audio and video processing engine multimedia server
ii pipewire-bin 0.3.65-3+rpt8+deb12u1 armhf PipeWire multimedia server - programs
ii pipewire-pulse 0.3.65-3+rpt8+deb12u1 armhf PipeWire PulseAudio daemon
pi@raspi-3:~ $ dpkg -l| grep pulse
ii libpulse0:armhf 16.1+dfsg1-2+rpt1 armhf PulseAudio client libraries
ii libpulsedsp:armhf 16.1+dfsg1-2+rpt1 armhf PulseAudio OSS pre-load library
ii pipewire-pulse 0.3.65-3+rpt8+deb12u1 armhf PipeWire PulseAudio daemon
ii pulseaudio-utils 16.1+dfsg1-2+rpt1 armhf Command line tools for the PulseAudio sound server
pi@raspi-3:~ $ dpkg -l| grep wirepl
ii libwireplumber-0.4-0:armhf 0.4.13-1 armhf Shared libraries for WirePlumber
ii wireplumber 0.4.13-1 armhf modular session / policy manager for PipeWire
Display More
Wie schon gehabt, wird mit zwei Bluetooth-Adaptern in den USB-Ports gearbeitet; also ein BT-Adapter pro BT-Lautsprecher.
Das Koppeln der Lautsprecher ist wieder im bluetoothctl auszuführen:
bluetoothctl
select <Adapter 1>
scan on
(Lautsprecher sichtbar machen)
pair <Lautsprecher 1>
trust <Lautsprecher 1>
connect <Lautsprecher 1>
select <Adapter 2>
...
exit
Damit sind die Burschen gespeichert und werden später erkannt, wenn man diese einschaltet.
Aus irgendeinem Grund, vernahm ich da immer mal wieder Ladehemmungen: Ein Lautsprecher verband sich sofort, der andere irgendwie nie, obwohl ge-pair-trust-ed. Dann ging es wieder auch mal.
Ein manuelles connect im bluetoothctl geht aber immer ohne Probleme.
Daher habe ich einfach eine UDEV-Regel hinterlegt, die wenn sich einer verbindet, der andere per Skript auch "nach-"verbunden wird.
Also gucken wir erst mal, was im UDEV passiert, wenn wir die Lautsprecher anschalten und verbinden; zuvor also:
Da geht 'ne ganze Menge ab, interessant ist aber nur das was unter der ACTION=add stattfindet; exemplarisch für einen Lautsprecher:
UDEV [5456.826007] add /devices/virtual/input/input19 (input)
ACTION=add
DEVPATH=/devices/virtual/input/input19
SUBSYSTEM=input
PRODUCT=5/a/ffff/ffff
NAME="JBL Flip 4 (AVRCP)"
PHYS="00:1a:7d:da:71:13"
PROP=0
EV=100007
KEY=2fc800 1452 0 0 0 0 10300 49e8 c00 e1680 f f8100000 10000ffc
REL=0
MODALIAS=input:b0005v000ApFFFFeFFFF-e0,1,2,14,k71,72,73,8A,8B,A3,A5,A6,A7,A8,AB,AE,C8,C9,D0,161,164,166,16A,16C,18B,18E,18F,190,191,192,193,195,ramlsfw
SEQNUM=2183
USEC_INITIALIZED=5456818407
ID_INPUT=1
ID_INPUT_KEY=1
ID_BUS=bluetooth
TAGS=:seat:
CURRENT_TAGS=:seat:
Display More
Daraus generieren wir jeweils eine UDEV-Regel, welche auf Subsystem Input, Action Add und eine Phys-Adresse schielt, die den anderen Lautsprecher connected, falls noch nicht erfolgt:
cat /etc/udev/rules.d/90-flip1.rules
SUBSYSTEM=="input", ACTION=="add", ATTR{phys}=="00:1a:7d:da:71:13", RUN+="/home/pi/apps/connect-flip-2.sh"
cat /etc/udev/rules.d/90-flip2.rules
ACTION=="add", SUBSYSTEM=="input", ATTR{phys}=="00:15:83:4a:1c:67", RUN+="/home/pi/apps/connect-flip-1.sh"
Hierbei habe ich ganz schön rumeiern müssen. Das Netz gibt viel her, aber dass man das {phys} klein schreiben muss, das war echt scher rauszufinden. Oder ich hatte es überlesen.
Der Inhalt der /home/pi/apps/connect-flip-2.sh:
#!/bin/bash
sleep 2
bluetoothctl <<EOF
select 00:1A:7D:DA:71:13 #<--- <Adapter 2>
connect 5C:FB:7C:26:2C:8E #<----<Achtung: Nicht identisch mit {phys} aus udev-Regel
EOF
Die Datei connect-flip-1.sh wird analog erstellt; Adressen sind anzupassen.
Kommen wir nun endlich zum Pipewire.
Hier gibt es zwei Session Manager: Pipewire Media Session und Wireplumber, wobei letzter empfohlen wird.
Alle wichtigen Infos zu Bookworm findet man hier: https://wiki.debian.org/PipeWire#Debian_12
Unter pi wird der Pipewire-Dienst aktiviert und gestartet:
Nachdem Reboot kann man gucken, ob dieser on ist:
pi@raspi-3:~ $ LANG=C pactl info | grep '^Server Name'
Server Name: PulseAudio (on PipeWire 0.3.65)
Nun müssen noch ein paar Konfigurationen vorgenommen werden.
pi@raspi-3:~ $ cat /etc/pulse/default.pa
#default.pa wurde nachträglich erstellt
#https://wiki.archlinux.org/title/Bluetooth_headset#Setting_up_auto_connection
#Automatically switch to newly-connected devices
load-module module-switch-on-connect
pi@raspi-3:~ $ cat /etc/pulse/system.pa
#default.pa wurde nachträglich erstellt
#https://wiki.archlinux.org/title/Bluetooth#PulseAudio
#Damit man Bluetooth unter Pulse nutzen kann
load-module module-bluetooth-policy
load-module module-bluetooth-discover
pi@raspi-3:~ $ cat /etc/pipewire/pipewire-pulse.conf.d/50-network-party.conf
#50-network-party.conf wurde nachträglich erstellt
#https://wiki.archlinux.org/title/PipeWire#Sharing_audio_devices_with_computers_on_the_network
context.exec = [
{ path = "pactl" args = "load-module module-native-protocol-tcp" }
]
Machen wir an der Stelle auch gleich die Verbindung vom mpd komplett.
In /etc/mpd.conf muss rein:
Ist an dieser Stelle zwar nicht verbindungsrelevant, aber mein finaler Sink soll SimOut heißen.
Nachdem Neustart von pipewire kann der SimOut gebaut werden:
Dafür habe ich ein Skript geschrieben. Es schaut,
- ob beide Lautsprecher per Bluetooth connnected sind,
- löscht alle alten SimOut, falls vorhanden (Man kann mehrere erstellen.) und
- erstellt einen neuen SimOut als Default-Device.
pi@raspi-3:~/apps $ cat pwSimOuter.sh
#!/bin/bash
declare -i eins
declare -i zwei
eins=$(bluetoothctl <<EOF | grep -c '5C_FB_7C_26_51_10'
menu endpoint
list
EOF
)
zwei=$(bluetoothctl <<EOF | grep -c '5C_FB_7C_26_2C_8E'
menu endpoint
list
EOF
)
if [ $eins == "1" ] && [ $zwei == "1" ];
then
while pactl list sinks short | grep 'SimOut'
do
/bin/pw-cli destroy SimOut
done
/bin/pw-cli create-node adapter '{ factory.name=support.null-audio-sink node.name="SimOut" node.description="SimOut" media.class=Audio/Sink object.linger=true audio.position=[FL FR] }'
sleep 0.25
/bin/pw-link "SimOut:monitor_FL" bluez_output.5C_FB_7C_26_2C_8E.1:playback_FL
sleep 0.25
/bin/pw-link "SimOut:monitor_FR" bluez_output.5C_FB_7C_26_51_10.1:playback_FR
sleep 0.25
/bin/pactl set-default-sink `pactl list sinks short | grep "SimOut" | egrep -o '[0-9]*' | head -1`
/bin/mplayer -ao pulse /home/pi/bibo-bobi.flac
fi
Display More
Um das Skript nicht manuell starten zu müssen, wird in die oben schon behandelten connect-flip-1 und 2.sh folgende Zeile ergänzt.
Dadurch wird als User pi das Skript pwSimOuter.sh gestartet, sobald sich ein Lautsprecher verbindet.
Außerdem kann ich das Skript per Knöppchen von einer anderen Anwendung aus starten; z.B. Fhem.
Vorausgesetzung ist, eine sudoers-Anpassung:
pi@raspi-3:~ $ sudo cat /etc/sudoers.d/020_fhem-nopasswd
fhem ALL=(ALL) NOPASSWD: /home/pi/apps/pwSimOuter.sh
Um nochmal zu gucken, ob alles passt, kann man:
pi@raspi-3:~ $ wpctl status
PipeWire 'pipewire-0' [0.3.65, pi@raspi-3, cookie:912978372]
└─ Clients:
31. pipewire [0.3.65, pi@raspi-3, pid:833]
33. WirePlumber [0.3.65, pi@raspi-3, pid:832]
34. WirePlumber [export] [0.3.65, pi@raspi-3, pid:832]
86. Music Player Daemon [0.3.65, pi@raspi-3, pid:656]
97. wpctl [0.3.65, pi@raspi-3, pid:30573]
Audio
├─ Devices:
│ 55. Internes Audio [alsa]
│ 56. Internes Audio [alsa]
│ 78. JBL Flip 4 [bluez5]
│ 87. JBL Flip 4 [bluez5]
│
├─ Sinks:
│ 71. Internes Audio Stereo [vol: 0.40]
│ 73. JBL Flip 4 [vol: 0.94]
│ * 85. SimOut [vol: 1.00]
│ 91. JBL Flip 4 [vol: 0.91]
│
├─ Sink endpoints:
│
├─ Sources:
│
├─ Source endpoints:
│
└─ Streams:
79. Music Player Daemon
75. output_FR > SimOut:playback_FR [active]
90. output_FL > SimOut:playback_FL [active]
Video
├─ Devices:
│ 40. bcm2835-codec-decode [v4l2]
│ 41. bcm2835-codec-encode [v4l2]
│ 42. bcm2835-codec-isp [v4l2]
│ 43. bcm2835-codec-image_fx [v4l2]
│ 44. bcm2835-codec-encode_image [v4l2]
│ 45. bcm2835-isp [v4l2]
│ 46. bcm2835-isp [v4l2]
│ 47. bcm2835-isp [v4l2]
│ 48. bcm2835-isp [v4l2]
│ 49. bcm2835-isp [v4l2]
│ 50. bcm2835-isp [v4l2]
│ 51. bcm2835-isp [v4l2]
│ 52. bcm2835-isp [v4l2]
│ 53. unicam [v4l2]
│ 54. unicam [v4l2]
│
├─ Sinks:
│
├─ Sink endpoints:
│
├─ Sources:
│ 57. bcm2835-isp (V4L2)
│ 59. bcm2835-isp (V4L2)
│ 61. bcm2835-isp (V4L2)
│ 63. bcm2835-isp (V4L2)
│ 65. unicam (V4L2)
│
├─ Source endpoints:
│
└─ Streams:
Settings
└─ Default Configured Node Names:
0. Audio/Sink SimOut
Display More
Die Lautstärke kann man manuell am Lautsprecher oder per
einstellen. Geht natürlich auch in pwSimOuter-sh.
bzw.
pi@raspi-3:~ $ pactl list sinks short
72 alsa_output.platform-bcm2835_audio.stereo-fallback PipeWire s16le 2ch 48000Hz SUSPENDED
425 bluez_output.5C_FB_7C_26_2C_8E.1 PipeWire s16le 2ch 48000Hz RUNNING
492 bluez_output.5C_FB_7C_26_51_10.1 PipeWire s16le 2ch 48000Hz RUNNING
503 SimOut PipeWire float32le 2ch 48000Hz RUNNING
Puh, damit müsste alles niedergeschrieben sein.
Mir ist folgendes sehr Positives aufgefallen. Beim alten Pulseaudio gab es Probleme mit der Stabilität, wenn man die Lautsprecher abschaltete ohne vorher den MPD zu stoppen. Man konnte die Lautsprecher nicht einfach an und ausschalten. Tat man dies, musste der MPD komplett restarted werden. Bei Pipewire ist dies nicht der Fall! Das hier beschriebene Procedere läuft mit einem Lautsprecher und wenn man den zweiten später dazuschaltet, wird der combined-Sink aktualisiert und wie von Zauberhand Stereo ausgegeben. ![]()
Ich hoffe, mein Aufsatz hier hilft noch jemandem.
Feedback is welcome!