Thank you for your donation!


Cloudsmith graciously provides open-source package management and distribution for our project.


Alternative renderers and metadata
#1
[2020-06-03: Updates to Airplay and Squeezelite bullets]
[2020-06-09: Update to Spotify bullet; remove topical reference to SpaceX launch.]

Those with long memories may recall my little side project two years ago to display the output of currentsong.txt on an  Odroid Show2. http://moodeaudio.org/forum/showthread.php?tid=211&pid=1563#pid1563.

The thread started by @mancio61's post about Airplay metadata reminded me of this project---I could use it easily to monitor whether the shairport-sync metadata reader is still unreliable as it was when Tim dropped it from moOde. [NOTE- the second part of Tim's reply holds true regardless.]

Once I had that thought, I figured I should review the metadata situation with all the alternative renderers:
  • Bluetooth - nothing to see here. Nada, zilch, nichts, rien, niente. Move along.

  • Airplay - looks to be straightforward to update currentsong.txt from the metadata reader as discussed in the referenced thread.

    Update: The shairport-sync-metadata-reader seems to be working for grabbing Artist/Album/Track/Genre from the stream in a human-readable form as well as tokenized status info not so readable. The metadata items may be updated asynchronously so one may have to buffer until all the values are current.

  • Spotify - should be possible but doesn't look straightforward. The maintainers of the librespot repo seem unwilling to make a firm decision about metadata [1].  I know, on the other hand, the jivelite addon to piCorePlayer shows metadata in a local display and pCP uses librespot. Trouble is, librespot is coded in Rust, jivelite is coded in Lua/C, and they apparently communicate via shared memory. I'm progressing v-e-r-y slowly through the code and haven't had any aha moments yet. Maybe someone has found better documentation than is in the repo?
    Update: looks like I mispoke. The piCorePlayer is fed by a LMS server and the Spotify service is handled by the 3rd-party "Spotty" plugin for LMS. Same reverse-engineering problem, just different location.
  • Squeezelite - undecided. I've looked through the configuration settings for my LMS server and for the squeezelite renderer and haven't found a magic bullet. At the same time, I see LMS slips an Icy-Metadata tag into its stream to the player once in a while. Might this be the tip of an iceburg or is it just a bit of flotsam?

    Update: Thanks to @mancio61's recent posts here I've uncovered a Logitech Media Server Telnet interface even more detailed than MPD's. The documentation is buried two layers down in the help screen within the LMS executable (!). The commands appear also to be the basis of the HTTP API documented at http://tutoriels.domotique-store.fr/cont...-http.html. It's my judgment that the Telnet interface would be the better choice to integrate into a player which displays metadata for the currently playing track and possibly it's status: play/pause/stop.

  • UPnP/DLNA - this one is a slam dunk. upmpdcli already feeds MPD all it needs and currentsong.txt is automatically updated using existing moOde mechanism.
 
Regards,
Kent

[1] the subject keeps coming up in the issues log. The response seems to be, put it in librespotd, but the librespotd repo hasn't be touched since it was created two years ago. Curiously, the companion librespot-java repo explicitly proclaims "this implementation provides a useful API to request metadata". After all, if I have the SpotifyURI for the current track (along with authentication credentials), I can directly query the Spotify API for the metadata; the local client should do it for me.
Reply
#2
WRT Spotify, I think Volumio is now using Spocon (which wraps librespot-java) which not only displays metadata/artwork, but is also gapless.  Gapless Spotify support is the one thing that keeps me from moving Moode into "full production".
Reply
#3
(06-01-2020, 11:36 PM)exocet Wrote: WRT Spotify, I think Volumio is now using Spocon (which wraps librespot-java) which not only displays metadata/artwork, but is also gapless.  Gapless Spotify support is the one thing that keeps me from moving Moode into "full production".

Sweet, spocon is a Debian-based package with an MIT license. It's not in the Raspbian distro so requires a bit more effort to use.

OTOH librespot-java has an Apache license, not an MIT license like librespot has. Not sure what implications that would have for Tim.

Thanks for the pointer.

Regards,
Kent
Reply
#4
The java thing is just a point-in-time work around. The librespot devs have already made the commits to enable gapless in the core librespot repo. They just haven't tagged a release yet.
https://github.com/librespot-org/librespot

My preference is to wait until they do a release then I'll integrate it into moOde :-)
Enjoy the Music!
moodeaudio.org | Mastodon Feed | GitHub
Reply
#5
(06-02-2020, 12:48 AM)Tim Curtis Wrote: The java thing is just a point-in-time work around. The librespot devs have already made the commits to enable gapless in the core librespot repo. They just haven't tagged a release yet.
https://github.com/librespot-org/librespot

My preference is to wait until they do a release then I'll integrate it into moOde :-)

Certainly true vis-a-vis gapless, which is the more compelling issue for most users.

My curiosity centers on the sidebar issue of the passage of metadata: what did the librespot-java developer(s) do and why is it (apparently) not an answer for the librespot developers?

Regards,
Kent
Reply
#6
Good question on how the Java librespot project does metadata.

The challenge is how to get the metadata and art work from these external players into the Moode UI and have it be as reliable as MPD metadata. Past attempts at Airplay metadata were not successful.
Enjoy the Music!
moodeaudio.org | Mastodon Feed | GitHub
Reply
#7
Hi, today I made some experiments with the shairport-sync-metadata and shairport-sync-metadata-reader program that I linked in the original thread. I install the service following the instructions, and now, when something is sent to the RPi through AirPlay (e.g. using the Tidal app on my iPhone), I'm able to see the results of the reader on the console (only Album Name, Artist and Title track are catched, but is better than nothing...).

Ok, now I try to extend the python script that populate my OLED display, in order to get the output of the reader , parse it and print the info on it. Maybe for a Linux expert shall be an easy task , but I'm literally a goat on Linux, so my temptative to do it failed.

I create a simple script to test the stuff. The idea is to run in asynch way a subprocess, passing the command "cat /tmp/shairport-sync-metadata | shairport-sync-metadata-reader > currentairplaysong.txt" in order to redirect the output of the reader to a file. Then, in a loop, read the file and extract from it the info (title, artist,...).
I tried with subprocess.Popen(cmd) but it fails...
Is there a simple way in Python to directly get asynocronusly the result the shairport-sync-metadata-reader (that I supposed to be a PIPE)?

Something like (in metacode):

p = openPIPE (result of shairport-sync-metadata-reader)
while true
line = p.readlines()
key,val = extract(line)
send key,val to display...
end while

I know that it shall be a very basic piece of code, but, as I said, never worked with Linux in my life ...
Help !!
Thanks in advance
Andrea
Reply
#8
[Please don't hijack threads. You have already started a thread for your project. My purpose in creating this thread was to have a place to focus on the topic of getting metadata  from alternative renderers without hijacking your thread in turn. That's why I created it here in the "Community>Uncatagorized" section and not, e.g., in the "moOde audio player>Support" section..]

I suggest you read all of https://appcodelabs.com/show-artist-song...spberry-pi (skipping the part about the display itself since you have your own code for that) and try exercising the Python module presented in the "writing the code" section (again, without the part about the display).

Apart from the need to redefine the render() function to fit your display code, that code would seem to do pretty much what you just outlined. I did this myself the other day to see how the metadata varied as I tried different combinations of connecting/disconnecting Airplay sources, selecting tracks, starting and stopping playback. The cut-down code I used follows.

There are some interesting anomalies as tracks change because the metadata dribbles in.

Regards,
Kent

Code:
#!/usr/bin/env python3
# @TheOldPresbyope
# this code was copied from
# https://appcodelabs.com/show-artist-song-metadata-using-airplay-on-raspberry-pi
# and modified to print to console as if it were a three-line display

# NOTE - doesn't clear previous value of specific key when no new value is received

import sys
import re

# a device isn't needed but let's define a dummy just
# to keep the same render() syntax as in the original code
device = "null"

artist = ""
track = ""
album = ""

def extract(line):
   m = re.match('^(Title|Artist|Album Name): \"(.*?)\"\.$', line)
   if m:
       return m.group(1), m.group(2)
   else:
       return None, None

def update(key, val):
   global artist, album, track
   if key == "Artist":
       artist = val
   elif key == "Album Name":
       album = val
   elif key == "Title":
        track = val

def render(device):
   # print to console instead of writing output to a device
   # use an ASCII escape sequence to imitate a three-line display
   print("\u001b[2J")
   print("Artist: " + artist)
   print("Album Name: " + album)
   print("Title: " + track)

# Create devices
   # deleted all the device code

# Welcome message
   # No, let's not

# Main loop
try:
   while True:
       line = sys.stdin.readline()
       key, val = extract(line)
       if key and val:
           update(key, val)
           render(device)

except KeyboardInterrupt:
   sys.stdout.flush()
   pass
Reply
#9
Kent, I apologize , you're right. I wrote in the wrong thread, hope it will not happen again.
Thanks for the suggestion (this is exactly the way I modified the python script cutting the "device" part)

Ciao, Andrea
Reply
#10
(05-31-2020, 03:04 PM)TheOldPresbyope Wrote:
    .......
  • Squeezelite - undecided. I've looked through the configuration settings for my LMS server and for the squeezelite renderer and haven't found a magic bullet. At the same time, I see LMS slips an Icy-Metadata tag into its stream to the player once in a while. Might this be the tip of an iceburg or is it just a bit of flotsam?

    .....

Hi Kent,
it can help, in the Python script that I use currently to update my display, there's a part, that I never used (SQUEEZELITE = False...) , dedicated to Squeezelite, able to retrieve music info from LMS Server (try to attach it but with no success)
Reply


Forum Jump: