Bielefeld devblog@posteo.de

Sprache auswählen

Coverplayer Teil 3: Lokaler Webserver für Apple Music und Spotify

Um neben Roon auch das Cover und die Track-Informationen von Apple Music oder Spotify auf dem Coverplayer anzeigen zu können, benötigt man auf jedem Computer, welcher solche Informationen im Netzwerk zur Verfügung stellen soll, ein entsprechendes PHP-Skript, und einen auf diesem Computer laufenden Webserver.
Das ist momentan nur unter macOS möglich, da das PHP-Script wiederum ein AppleScript aufrufen muss, um an die benötigten Informationen von der Apple Music oder Spotify App zu gelangen.

Die benötigten PHP- und Python-Files (mit eingebettetem AppleScript) kann man sich via Github herunterladen.

Die Dateien aus dem Ordner 'websites' werden auf dem Computer in den enstsprechenden Ordner kopiert, welcher die Webinhalte im lokalen Netzwerk zur Verfügung stellt, oder stellen soll.

Bei macOS ist das im entsprechenden Benutzerordner in: /Users/USERNAME/websites.

Nun müssen in den Dateien noch ein paar Pfade angepasst werden.

In now_playing.php, Zeile 59: 

echo shell_exec("/Users/USERNAME/.pyenv/shims/python /Users/USERNAME/websites/python/now_playing.py"); 

BENUTZERNAME(USERNAME): Hier muss der Benutzername des eingeloggten Benutzers eingetragen werden.

 

Möglicherweise müssen im Anschluss daran noch die passende Zugriffsrechte per Kommandozeile (Terminal) gesetzt werden, damit die Dateien auch ausgeführt werden dürfen.

Damit das Python-Script überhaupt ein AppleScript ausführen kann, wird eine Python Bibliothek benötigt, welche man unter Python 3.8 installieren muss:

Getestet wurde es von mir unter macOS mit Python 3.8.16.

Die Python Bibliothek befindet sich im Ordner python plugins des Github repos.

Diese bitte auf den eigenen macOS Computer kopieren, entpacken, und dann via Terminal installieren:

cd py-applescript-master
python3 setup.py install

Wenn die Installation funktioniert hat, kann man mit diesem Befehl die Versionsinformationen des Plugins anzeigen lassen:

pip3 show py-applescript

Eventuell fehlt auf dem Mac noch die Foundation Library pyobjc, damit das Plugin installiert werden kann.

Dieses installierst du wie folgt:

pip3 install -U pyobjc

 

Ist auf deinem Computer bereits PHP installiert?

Wenn nein, dann kann man diesen z.B. via Homebrew installieren. Ich habe die Scripts mit PHP Version 8.4.2 getestet.
brew install php@8.4

Nun müssen noch die virtuellen Hosts konfiguriert werden. Die Datei hierfür befindet sich in: /opt/homebrew/etc/httpd/extra/httpd-vhosts.conf.

Diese sollte für Coverplayer in etwa so aussehen:

# Virtual Hosts
#
# Required modules: mod_log_config

# If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
#
# Please see the documentation at 
# <URL:http://httpd.apache.org/docs/2.4/vhosts/>
# for further details before you try to setup virtual hosts.
#
# You may use the command line option '-S' to verify your virtual host
# configuration.

#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not
# match a ServerName or ServerAlias in any <VirtualHost> block.
#
<VirtualHost *:80>
    ServerAdmin admin@localhost
    DocumentRoot "/Users/USERNAME/websites"
    ServerName localhost
    ErrorLog "/opt/homebrew/var/log/httpd/localhost-error_log"
    CustomLog "/opt/homebrew/var/log/httpd/localhost-access_log" common
</VirtualHost>

<VirtualHost *:80>
    ServerAdmin admin@localhost
    DocumentRoot "/Users/USERNAME/websites/roonmatrix"
    ServerName roonmatrix.test
    ServerAlias www.roonmatrix.test
    ErrorLog "/opt/homebrew/var/log/httpd/roonmatrix.test-error_log"
    CustomLog "/opt/homebrew/var/log/httpd/roonmatrix.test-access_log" common
</VirtualHost>

Achtung: Hier muss BENUTZERNAME(USERNAME) mit dem tatsächlichen Benutzernamen ersetzt werden.

Der Webserver wird in der folgenden Datei konfiguriert: 

/opt/homebrew/etc/httpd/httpd.conf

Die Beispieldateien findet man ebenfalls auf Github und können recht einfach angepasst werden.

Achtung: Hier muss BENUTZERNAME(USERNAME) ebenfalls und mehrfach mit dem tatsächlichen Benutzernamen ersetzt werden.

Nach einem Neustart des Rechners (oder indem man den Webserver via Kommandozeile startet), sollte der Webserver mit PHP laufen.

Um das zu überprüfen, schreibe eine phpinfo.php Datei mit folgendem Inhalt in das Verzeichnis /Users/USERNAME/websites/roonmatrix/:

<?php phpinfo() ?>

Rufe das PHP Script nun per Webbrowser auf: http://www.roonmatrix.test/phpinfo.php

Die Webseite sollte die Webserver-Konfiguration anzeigen, welche in etwa so aussieht:

Nach dem Test sollte man diese Datei wieder löschen, da sie generell ein Sicherheitsrisiko darstellt, da hier viele Interna preisgegeben werden.

 

Wenn sowohl Python, PHP, als auch das PHP- und Python Script, sowie das Applescript-Plugin für Python korrekt installiert wurden, kann man unter der folgenden Adresse das Script lokal ausführen:  http://www.roonmatrix.test/now_playing.php

Das PHP-Script kann man auch via Kommandozeile testen:

curl http://www.roonmatrix.test/now_playing.php

Falls es beim Aufruf der Seite Probleme gibt, könnte das auch an den seit einiger Zeit verschärften Sicherheitseinstellungen von macOS liegen.

Eine Fehlermeldung in dieser Art könnte die Folge sein:

tccutil: executable_is_endpoint_security_client failed for path file:///Users/USERNAME/.pyenv/versions/3.8.19/bin/python with error: code object is not signed at all

Hier fehlt die geforderte Codesignierung. Das Problem kann man per Terminalbefehl beheben.

Mit diesem Befehl kann man prüfen, ob eine Signierung vorliegt: 
codesign -dv /Users/USERNAME/.pyenv/versions/3.8.16/bin/python

Codesignierung durchführen:
=======================================================================================
codesign --sign "USERNAME CA" --force --keychain ~/Library/Keychains/ /usr/local/Cellar/php/8.3.7/lib/httpd/modules/libphp.so
codesign --sign "USERNAME CA" --force --keychain ~/Library/Keychains/ /usr/local/opt/php@8.1/lib/httpd/modules/libphp.so
codesign --sign "USERNAME CA" --force --keychain ~/Library/Keychains/ /Users/USERNAME/.pyenv/versions/3.8.16/bin/python

Je nach installierter PHP- und Python-Version können die Pfade unterschiedlich sein! 

Dann muss man sich an den korrekten Pfad herantasten, indem man von einem niedriger liegenden Pfad startet, und durch den Ordnerbaum navigiert, bis man den korrekten Pfad gefunden hat - oder man verwendet Terminalbefehle um den korrekten Pfad aufzuspüren.

 

Manchmal muss man auch die Sicherheitseinstellungen zurücksetzen, falls die erforderlichen Rechtefreigaben nicht erfragt werden, und zwar mit:
tccutil reset AppleEvents
tccutil reset SystemPolicyAllFiles

Wenn man dann das PHP-Script aufruft, fragt macOS u.U. nach, ob man dem Webserver/Script die benötigten Rechte geben möchte.

Das sollte man erlauben, da sonst das Script geblockt wird.

Falls das Problem weiterhin auftritt, muss evtl. das Script mit einer Signatur versehen werden. Wie das geht, muss u.U. noch genauer geklärt werden.

Weitere Fehlermeldungen können ungefähr so aussehen:

Traceback (most recent call last):
  File "/Users/USERNAME/python/now_playing.py", line 61, in <module>
    output = tell_iTunes.call('Playing')
  File "/Library/Python/3.9/site-packages/py_applescript-1.0.3-py3.9.egg/applescript/__init__.py", line 110, in call
  File "/Library/Python/3.9/site-packages/py_applescript-1.0.3-py3.9.egg/applescript/__init__.py", line 65, in _unpackresult
applescript.ScriptError: An error of type -10810 has occurred. (-10810) range=90-97


Traceback (most recent call last):
  File "/Users/USERNAME/python/now_playing.py", line 61, in <module>
    output = tell_iTunes.run()
  File "/Users/USERNAME/.pyenv/versions/3.8.19/lib/python3.8/site-packages/applescript/__init__.py", line 90, in run
    return self._unpackresult(*self._script.executeAndReturnError_(None))
  File "/Users/USERNAME/.pyenv/versions/3.8.19/lib/python3.8/site-packages/applescript/__init__.py", line 65, in _unpackresult
    raise ScriptError(errorinfo)
applescript.ScriptError: Not authorized to send Apple events to Music. (-1743) app='Music' range=318-325

Es gibt in diesem Beispiel ein Problem mit den Automationsrechten unter macos Monterey 12.7.5.
In Systemeinstellungen/Sicherheit & Datenschutz/ muss im Bereich Automation für httpd jeweils eine Freigabe von Musik, Spotify und System Events bestehen.


Ist das nicht der Fall, dann kann das now_playing.php script welches now_playing.py via Python 3.8 startet, nicht funktionieren bzw. wird geblockt.
Um Apple Musik und Spotify freizuschalten, muss das PHP-Skript now_playing_add_httpd_automation_rights.php einmal im Webbrowser aufgerufen werden.

Auch dieses Script findet man auf Github.
Falls System Events fehlt, und man einen Error -10810 erhält, läuft der Apache2 Webserver mit anderen Rechten als dem Useraccount.
Um das zu fixen, muss man in httpd.conf den 


User _www
Group _www

ändern in:
User dein-benutzername
Group staff

Dann das Skript einfach nochmal starten.
Danach sollte auch das php skript now_playing.php funktionieren.
Im Anschluss sollten dann die Änderungen in /etc/apache2/httpd.conf wieder zurückgesetzt werden auf:
User _www
Group _www

 

Falls es weiterhin Probleme gibt, dann solltest du prüfen, ob man das AppleScript direkt per Apple Skripteditor (findest du in System/Applications/Utilities/) aufrufen kann.

Das muss man u.U. machen, da sonst (also beim Aufruf des Applescript durch Python) der Dialog für die benötigte Rechte-Freigabe nicht erscheint.

 

Wenn das Skript nun korrekt ausgeführt werden kann, sollte das Skript ein Ergebnis ausgeben.

Ohne gestartete Apple Music oder Spotify App sieht das Ergebnis in etwas so aus:

[{"zone": "Apple Music", "status": "not running"},{"zone": "Spotify", "status": "not running"}]

 

Wenn z.B. die Apple Music und die Spotify App einen Song abspielt, sieht das Ergebnis beispielsweise so aus:

[{"zone": "Apple Music", "artist": "Pink Floyd", "album": "Dark Side of the Moon", "track": "Speak to Me - Breathe"},{"zone": "Spotify", "artist": "Underworld", "album": "1992 - 2012", "track": "Born Slippy (Nuxx)"}]

 

Wenn das bei dir bis hierhin alles wie beschrieben funktioniert, dann ist dieser Teil geschafft.
Nun musst du nur noch in der Konfigurationsdatei (roon_api.ini) die Webserver url zum Aufruf des PHP-Scripts eintragen.

Einfacher geht das über die RoonMatrix App, dann kannst du dir das umständliche manuelle konfigurieren in der Ini-Datei ersparen, und setzt diese Einstellungen komplett im Konfigurationseditor der App um.

Das manuelle Setup via SSH und Terminal geht folgendermassen:
ssh Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein. (hier die IP-Adresse deines Coverplayers einfügen)


Nun musst du das Passwort eingeben: Das ist per Voreinstellung: cpuserpw0815.


Wichtig: Dieses Passwort solltest du später unbedingt ändern.
Das geht am einfachsten direkt im Konfigurationseditor der App.

Nach dem Login, die ini Datei editieren:

sudo nano /usr/local/Roon/etc/roon_api.ini

 

Nun scrolle zum Abschnitt Bereich [WEBSERVERS] in die Einstellung zones, und trage hier den Namen und die Url zu dem PHP-Script auf deinem Rechner ein.

Das sieht dann beispielsweise so aus:
zones = [{'name':'MacStudio','url':'http://macstudio.local/roonmatrix/now_playing.php'}]

Die Einstellung um den Abruf der Daten vom Webserver zu aktivieren:

webservers_show = True

Nach einem Neustart des Coverplayers sollte nun auch der momentan abgespielte Titel von Apple Music oder Spotify auf dem Gerät angezeigt werden.

Möglicherweise musst du noch in der Firewall den Zugriff auf den Webserver freigeben. Da es sich hier um eine lokale Seite in deinem Netzwerk handelt, sollte das in den meisten Fällen unnötig sein.

 

 

Anmelden