2. Zone eines DENON-AVRs mit separatem AirPlay
DENON-AV-Receiver sind cool, denn sie klingen gut und man kann die netzwerkfähigen Geräte vollständig über eine HTTP-API steuern, welche DENON auch offenlegt.
Wie es sich für netzwerkfähige AV-Receiver gehört, machen die Modelle von DENEN auch AirPlay. Die Titelinformationen werden auf dem Display und ggf. auf dem Fernseher angezeigt, inklusive Album-Cover. Außerdem lässt sich die Receiver-Lautstärke vom iOS-/OS X-Gerät aus steuern, die Fernbedienung des Receivers ist auch vollständig nutzbar.
Das ganze hat leider nur einen kleinen Haken: viele DENON-Receiver besitzen zusätzliche Lautsprecheranschlüsse für eine zweite Zone, sodass man z.B. die Küche mit Radio beschallen kann, während im Wohnzimmer ein Film läuft.
Die Spotify-Connect-/Mediaserver- und AirPlay-Funktionalität des Receivers ist jedoch intern über einen einzigen Eingang mit dem Verstärker-Teil des Receivers verbunden, die separate Nutzung von zwei AirPlay-Instanzen oder Airplay und Spotify-Connect zusammen funktioniert also nicht; es wird auch nur ein AirPlay- und ein Spotify-Device im Netzwerk angekündigt.
Enter Raspberry Pi
Das AirPlay-Protokoll ist schon lange reverseengineert worden und es gibt einige OpenSource-Implementierungen. Die meines Erachtens beste ist Shairport-Sync. Shairport-Sync ist ein Fork des Originals, welches erstmals funktionierendes AirPlay aus dem reverseengineerten Protokoll umsetzte. Es unterstützt – im Gegensatz zum Original – auch den Teil des Protokolls, der für eine synchrone Wiedergabe auf mehreren Geräten sorgt. Zudem kann es die Metadaten vom Abspieldenden Gerät empfangen und hat auch sonst noch einige nützliche Funktionen unter der Haube.
Zunächst benötigt ihr einen Raspberry Pi mit aktualisierten Repositories. Und wir werden root. Weil ich zu faul bin, immer wieder sudo einzutippen.
$ sudo su $ apt-get update $ apt-get upgrade
Da ich in diesem Tutorial davon ausgehe, dass ihr Raspbian GNU/Linux 8.0 (jessie) oder neuer laufen habt, wollen wir nun erstmal schauen, ob das gegeben ist:
$ apt-get install lsb-release $ lsb_release -a
Zunächst sollten wir mal unser Audio-Setup anschauen. Zuerst geben wir dem System aber noch ein Dummy-Adio-Device. Warum erfahrt ihr weiter unten.
modprobe snd-dummy
Damit der Pi das bei jedem Start automatisch macht, packen wir das ganze noch in die modules-Datei:
echo "snd-dummy" >> /etc/modules
Nun schauen wir, welche Audio-Devices es so im System gibt. Falls ihr eine USB-Soundkarte verwenden wollt, wäre jetzt ein guter Zeitpunkt, um sie anzustecken.
$ aplay -l **** List of PLAYBACK Hardware Devices **** card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA] 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 0: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: Dummy [Dummy], device 0: Dummy PCM [Dummy PCM] 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
Wie ihr seht, ist der analoge Part der Pi-onboard-Soundkarte hier card0 und device0; die Dummy-Soundkarte, die wir eben angelegt haben, ist card1 und device0.
Wir merken uns das für später.
Nun brauchen wir git, um shairport-sync clonen zu können und ein paar Pakete, mit denen wir es anschließend kompilieren:
$ apt-get install git screen autoconf libtool libdaemon-dev libasound2-dev libpopt-dev libconfig-dev avahi-daemon libavahi-client-dev libssl-dev
Jetzt legen wir uns erstmal einen Order für das ganze Gedöns an und wechseln in diesen:
$ mkdir airplay/ $ cd airplay
Dann clonen wir den shit und gehen in dessen Ordner:
$ git clone https://github.com/mikebrady/shairport-sync.git $ cd shairport-sync/
conf-File generieren und ausführen:
$ autoreconf -i -f $ ./configure --with-alsa --with-avahi --with-ssl=openssl --with-systemd
Maken und – wenn keine Fehler aufgetreten sind – installen:
$ make $ make install
Nun machen wir noch ein paar User-Dinge und sagen systemd, dass es Shairport-Sync beim Booten starten soll:
$ getent group shairport-sync &>/dev/null || groupadd -r shairport-sync >/dev/null $ getent passwd shairport-sync &> /dev/null || useradd -r -M -g shairport-sync -s /usr/bin/nologin -G audio shairport-sync >/dev/null $ systemctl enable shairport-sync
In der Shairport-Sync-Konfigurationsdatei (/etc/shairport-sync.conf) kann man nun alles Mögliche nach Belieben konfigurieren. Die Optionen sind alle in Kommentaren erklärt. Unter /etc/shairport-sync.conf.sample findet ihr eine Datei mit Beispieloptionen.
Zeile 44–51 der Konfigurationsdatei definiert ein paar Parameter zur Audio-Hardware. Hier kommen nun die Card- und Device-IDs zum Einsatz, die wir oben nachgeschaut haben:
In Zeile 46 definieren wir das Gerät, auf dem Shairport-Sync Audio ausgeben soll. Die beiden Nullen stehen dabei für die Card und das Device.
output_device = "hw:0,0";
In Zeile 47 und 48 geben wir nun aber einen abweichenden Mixer an: den der Dummy-Soundkarte. Hier reicht die Nummer der Card (1) und der Name des Mixer-Reglers (standardmäßig „Master“):
mixer_control_name = "Master"; mixer_device = "hw:1";
Nun einmal
$ reboot
…en und schauen, ob AirPlay schon funzt.
Was nun passieren sollte:
Shairport sollte auf dem internen Audio-Port des Raspberry Pi Audio abspielen. Wenn man die Lautstärke z.B. am iPhone verstellt, sollte sich die Lautstärke jedoch nicht verändern. Warum? Genau: Wir haben Shairport ja gesagt, dass es den Regler der Dummy-Soundkarte verschieben soll, wenn es Lautstärkeänderungen gibt.
Kontrollieren kann man das mit
$ alsamixer
Hier sieht man nun wahrscheinlich einen einzelnen Regler, den des Raspberry-Audioports. Mit [Up] und [Down] kann man nun die Lautstärke verstellen.
Die AirPlay-Lautstärke sollte diesen Regler nicht verstellen.
Mit [F6] kann man auf die Dummy-Soundkarte wechseln. Diese hat ein paar mehr Regler, aber uns interessiert nur der Master ganz links. Dieser sollte die AirPlay-Lautstärke widerspiegeln. Probiert's aus, es aktualisiert sich live.
Vielleicht fragt ihr euch, warum wir den ganzen Scheiß hier machen. Ganz einfach:
Wir wollen dreierlei Dinge erreichen:
- Wir wollen, dass Shairport den Receiver bzw. dessen zweite Zone startet, sobald man beginnt, etwas abzuspielen. Außerdem sollte die zweite Zone noch auf den Eingang geschaltet werden, an dem der Raspberry Pi angeschlossen ist.
- Wenn AirPlay endet (Playlist vorbei oder lang genug Pause), soll der Receiver wieder abgeschaltet werden.
- Die Lautstärke, die man über das iGerät einstellt, soll nicht die Raspberry-Soundkarte regeln. Stattdessen sollen diese Lautstärkeeinstellungen an den DENON-Receiver weitergegeben werden.
Wenn Shairport funktioniert, legen wir erstmal einen Ordner für die Scripts an, die wir gleich verwenden werden:
$ mkdir /usr/local/scripts
In diesen Ordner zunächst folgendes Script:
/usr/local/scripts/airplaytrigger:
#!/bin/bash ZONEURL='http://avr.local/MainZone/index.put.asp' amixer -c 0 sset PCM 93% if [[ $1 == 'start' ]]; then curl $ZONEURL --data 'cmd0=PutZone_OnOff%2FON&ZoneName=ZONE2' > /dev/null 2> /dev/null curl $ZONEURL --data 'cmd0=PutZone_InputFunction%2FGAME&ZoneName=ZONE2' > /dev/null 2> /dev/null elif [[ $1 == 'stop' ]]; then curl $ZONEURL --data 'cmd0=PutZone_OnOff%2FOFF&ZoneName=ZONE2' > /dev/null 2> /dev/null fi
(Auch ausführbar machen…)
$ chmod -x /usr/local/scripts/airplaytrigger
Die fettgedruckten Teile des Script müsst ihr ggf. ändern:
ZONEURL='http://avr.local/MainZone/index.put.asp'
Statt „avr.local“ tragt ihr hier die Adresse eures Receivers ein.
amixer -c 0 sset PCM 93%
„-c 0“ repräsentiert hier die Card-ID der Soundkarte, auf der Shairport Audio abspielen soll (in meinem Fall die interne Soundkarte des Pi, die bei mir die Nummer 0 hat). Dieser Befehl setzt die Lautstärke des PCM-Reglers dieser Karte bei jeder AirPlay-Session auf 93%. 93% ist die prozentuale Lautstärke, die mir der alsamixer anzeigt, wenn der Regler auf 75/100 gesetzt ist. Für mein Setup ist das ein guter Wert, ggf. ist für euch 100% oder 50% besser.
curl $ZONEURL --data 'cmd0=PutZone_InputFunction%2FGAME&ZoneName=ZONE2' > /dev/null 2> /dev/null
„GAME“ ist der Name des Inputs, den ihr am Receiver für den Raspberry Pi verwendet. Evtl. ist das ein analoger Eingang, wenn ihr eine fancyge Soundkarte benutzt, empfehle ich jedoch, eine S/PDIF oder Toslink-Verbindung zu nutzen. Im Webinterface des Receivers kann man die Eingänge an der Rückseite dem Entsprechenden Input zuordnen. Man kann die Inputs auch umbenennen.
In den Bildern sieht man, dass ich den Input „Game“ in „ExtAirplay“ umbenannt und dann „ExtAirplay“ den 1. analogen Eingang zugeordnet habe.
Obwohl der Input jetzt „ExtAirplay“ heißt, muss in der HTTP-API der Originalname genutzt werden –> GAME.
Shairport Scripts aufrufen lassen
Nun sagen wir Shairport in seinen Einstellugnen unter /etc/shairport-sync.conf, dass es dieses Script aufrufen soll, wenn AirPlay beginnt und endet.
Zeile 33–39:
{ run_this_before_play_begins = "/usr/local/scripts/airplaytrigger start"; run_this_after_play_ends = "/usr/local/scripts/airplaytrigger stop"; wait_for_completion = "yes"; allow_session_interruption = "yes"; session_timeout = 30; };
An den Optionen
allow_session_interruption = "yes";
und
session_timeout = 30;
könnt ihr selbst mal ein bisschen rumspielen.
Nach einem
$ reboot
sollte sich der Receiver schon automatisch ein- und ausschalten.
Lautstärke an den Receiver übergeben
Hierfür legt ihr nun ein weiteres Script an:
/usr/local/scripts/airplayvolume:
#!/bin/bash OLDVOL=0% while : ; do NOWVOL=$(awk -F"[][]" '/dB/ { print $2 }' <(amixer -c 1 sget Master) | head -n 1) if [[ $NOWVOL != $OLDVOL ]]; then VOLUME=${NOWVOL::-1} VOLUME=$(expr $(expr 700 \* $VOLUME \* -1 + 80000) / 1000 \* -1) echo "Changing to ${NOWVOL} / ${VOLUME} dB" curl -m 0.5 "http://avr.local/MainZone/index.put.asp" --data "cmd0=PutMasterVolumeSet/${VOLUME}.0&ZoneName=ZONE2" > /dev/null 2> /dev/null OLDVOL=$NOWVOL fi sleep 0.1 done
(Auch ausführbar machen…)
$ chmod -x /usr/local/scripts/airplayvolume
In diesem Script müsst ihr folgendes anpassen:
NOWVOL=$(awk -F"[][]" '/dB/ { print $2 }' <(amixer -c 1 sget Master) | head -n 1)
„-c 1“ ist die Nummer der Dummy-Soundkarte. Ihr habt vielleicht eine andere Nummer.
„Master“ ist der Name des Reglers.
curl -m 0.5 "http://avr.local/MainZone/index.put.asp" --data "cmd0=PutMasterVolumeSet/${VOLUME}.0&ZoneName=ZONE2" > /dev/null 2> /dev/null
„avr.local“ solltet ihr durch die Adresse eures Receivers ersetzen.
Beim Booten ausführen
Dieses Script muss nun beim Start ausgeführt werden. Dafür gibt es verschiedenste Wege, der schnellste und dreckigste ist, es in einem screen aus /etc/rc.local heraus zu starten.
Danach sollte diese Datei in etwa so aussehen:
#!/bin/sh -e #[…] screen -dmS airplayvolume /usr/local/scripts/airplayvolume exit 0
(Das „exit 0“ muss ganz am Ende stehen…)
Ein
reboot
zum Schluss. Jetzt könnt ihr eure zweite Zone separat beschallen.
Yey. \o/