Bielefeld devblog@posteo.de

Select your language

RoonMatrix Part 14: Local web server for Apple Music and Spotify

To be able to display track information from Apple Music or Spotify on the RoonMatrix in addition to Roon, you need a appropriate PHP script on any computer that should provide such information in the network, and a web server running on this computer.
This is currently only possible on MacOS, because the PHP script in turn has to call up an AppleScript in order to get the required information from the Apple Music or Spotify app. But, Applescript is not available on Windows.

The required PHP and Python files (with embedded AppleScript) can be found on Github: download.

The files from the 'websites' folder are copied on the computer in the corresponding folders, which provide or should provide the web content in the local network.

In MacOS this is in the corresponding user folder in: /Users/USERNAME/websites.

Now a few paths have to be adjusted in the files.

In now_playing.php, line 59: 

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

BENUTZERNAME(USERNAME): The user name of the logged -in user must be entered here.

 

Possibly the right access rights via command line (terminal) must then be set so that the files can also be executed.

In order for the python script to execute a AppleScript, a Python library is required, which you have to install under Python 3.8 :

It was tested by me under MacOS with Python 3.8.16.

The Python library is located in the folder Python plugins of the Github Repo.

Please copy this to your own MacOS computer, unpack, and then install it via terminal:

cd py-applescript-master
python3 setup.py install

If the installation has worked, you can use this command to display the version information of the plugin:

pip3 show py-applescript

The Foundation Library may still be missing on the Mac named  pyobjc, so that the plugin can be installed.

You install this as follows:

pip3 install -U pyobjc

 

Is PHP already installed on your computer?

If not, then you can e.g. install Homebrew . I tested the scripts with PHP Version 8.4.2 .
brew install php@8.4

Now the virtual hosts still have to be configured. The file for this is located in: /opt/Homebrew/etc/httpd/extra/httpd-vhosts.conf.

This should look roughly like this for RoonMatrix:

# 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>

Attention: here must  BENUTZERNAME(USERNAME) be replaced with the actual user name.

The web server is configured in the following file:  

/opt/Homebrew/etc/httpd/httpd.conf

The sample files can also be found on Github and can be easily adjusted.

Attention: here must  BENUTZERNAME(USERNAME) also be replaced several times with the actual user name.

After a restart of the computer (or by starting the web server via command line), the web server should run with PHP.

To check this, write a phpinfo.php file with the following content in the directory /Users/USERNAME/websites/roonmatrix/:

<?php phpinfo() ?>

Now call the PHP script via web browser: http://www.roonmatrix.test/phpinfo.php

The website should display the web server configuration, which looks like this:

After the test, you should delete this file again, because it generally represents a security risk, as many internals are exposed here.

 

If both Python, PHP, as well as the PHP and Python Script, as well as the AppleScript plugin for Python were correctly installed, the script can be executed locally at the following URL:  http://www.roonmatrix.test/now_playing.php

The PHP script can also be tested via command line:

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

If there are problems when calling up the page, this could also be due to the MacOS security settings, which have been extended for some time.

An error message in this kind could be the result:

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

The required code signing is missing here. You can fix the problem by terminal command.

With this command you can check whether there is a signing:  
codesign -dv /Users/USERNAME/.pyenv/versions/3.8.16/bin/python

Execute codesignation:
============================================================================================================;
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

Depending on the installed PHP and Python version, the paths can vary!  

Then you have to approach the correct path by starting from a lower path and navigating through the folder tree until you have found the correct path - or you use terminal commands to track down the correct path.

 

Sometimes you also have to reset the security settings if the required right settings are not requested, namely with:
tccutil reset AppleEvents
tccutil reset SystemPolicyAllFiles

If you then call up the PHP script, MacOS may ask whether you want to give the webserver/script the necessary rights.

You should allow this, otherwise the script will be blocked.

If the problem continues, the script may have to be provided with a signature. How to do this may have to be clarified even more precisely.

Further error messages can look like this:

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

In this example there is a problem with the automation rights under MacOS Monterey 12.7.5.
In System Settings / Privacy & Security, navigate to area automation, there are settings for httpd. There must be permission items for Music, Spotify and System Events.


If this is not the case, the now_playing.php script which now_playing.py via Python 3.8 starts, does not work or be blocked.
In order to activate Apple music and Spotify rights, the PHP script now_playing_add_httpd_automation_rights.php must be executed in the web browser.

This script can also be found on Github.
If system events are missing, you may get an error: -10810, the Apache2 web server runs with other rights than the user account.
To fix this, you have to replace this in the httpd.conf :


User _www
Group _www

Change to:
User your-username
Group staff

Then just start the script again.
After that, the php script now_playing.php should also work.
Afterwards the changes in /etc/apache2/httpd.conf should be reset to:
User _www
Group _www

 

If there are still problems, you should check whether the AppleScript can be executed directly via Apple ScriptEditor (located in System/Applications/Utilities/).

You may have to do this, otherwise (i.e. when calling up the Applescript by Python) the dialog for the required rights settings does not appear.

 

If the script can now be executed correctly, the script should display a result.

Without started Apple Music or Spotify app, the result looks like something like this:

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

 

For example, if the Apple Music and the Spotify app plays a song, the result looks like this:

[{'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)'}]

 

If everything works for you as described, this part is done.
Now all you have to do is enter the web server URL in the configuration file (roon_api.ini) to call the PHP script automatically in intervals.

It's easier to do this via the  RoonMatrix app, then you can save yourself the cumbersome manual configure in the INI file and edit these settings completely in the app's configuration editor.

The manual setup via SSH and terminal works as follows:
ssh This email address is being protected from spambots. You need JavaScript enabled to view it. (insert the IP address of your Roonmatrix here)


Now you have to enter the password: This is by default: rmuserpw0815.


Important: You should definitely change this password later.
The easiest way to do this is directly in the app's configuration editor.

After login, edit the ini file:

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

 

Now scroll to the section area [WEBSERVERS] to the setting zones, and enter the name and the URL to the PHP script on your computer.

For example, it looks like this:
zones = [{'name':'MacStudio','url':'http://macstudio.local/roonmatrix/now_playing.php'}]

The setting to activate the retrieval of data from the web server:

webservers_show = True

After a restart of the RoonMatrix, the currently played title of Apple Music or Spotify should be displayed on the device.

You may still have to allow the access to the web server in the firewall. Because this is a local url in your network, this should be unnecessary in most cases.

 

 

Log in to comment