-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for Spotify Connect #17
Comments
I g uess both Volumio and Mopidy being music player daemons basically means they hog the audio ouput device and don't give things like raspotify a look in. You should probably just install raspotify onto a fresh Raspbian and see how you go with that: https://github.com/dtcooper/raspotify All of the display code we've got working thus far is Mopidy/mpd-centric and wont work with Raspotify. There surely must be a way to query Librespot for the currently playing song/album art/etc though. |
Okay it looks like librespot (the grunt behind raspotify) supports an The event type and releated track IDs are saved to environment variables: So all that remains - okay so this isn't exactly trivial - is to write a small Python handler that:
|
This all said. VolumIO should work- I guess you set up the DAC in the System settings? I think the missing link is the enable pin. If you can edit |
Thank you for talking your time and writing such a detailed response.
I looked for something called "dtoverlay=hifiberry-dac" as used for pirate audio but did not add First of all I will try to get Rasbian + raspotify + sound output working and then look into the rest but I guess this goes way over my head. |
I've been curious about this too and just had a quick go at getting Spotify Connect playing through the Pirate Audo DAC via Raspotify. Turns out all I needed to do run the "Easy" installation instructions as detailed in the Raspotify project page and then change the options in the config file to use the correct audio device, which in my case was:
The LCD and buttons don't function doing it this way, but to anyone who just wants a basic way of controlling what Pirate Audio is playing via Spotify Connect, it doesn't seem like a bad solution. This also doesn't touch Mopidy, but this might be moot as what's playing can now be controlled from the Spotify client on any desktop or mobile device. |
Did you add |
Hey, no probs. That's where I added it, yep. |
+1 |
Does raspotify show the media info on the LCD? |
Sadly no. I still think that a real Spotify Connect integration would be so useful. |
+1 I actually think this would be a great feature. |
Oh no, same happened to me. I thought it would support Spotify Conect, too. It would be awesome if it would. |
I think full Spotify Connect integration is probably something that needs to be handled in Mopidy Spotify. See this- somewhat dated (and locked)- thread here: mopidy/mopidy-spotify#14 This slightly more current thread suggests that Raspotify and Mopidy can potentially better co-exist by pausing MPD when Raspotify is active. Although this would not include any visual indication of what's playing on screen (as mentioned above)- https://discourse.mopidy.com/t/mopidy-spotify-connect-raspotify/2397 That's, at least, a good start but getting Raspotify "now playing" to co-exist on a screen that's actively being driven by Mopidy will be quite tricky. I'm imaging a new SD card to set up Mopidy and Raspotify side-by-side to see how bad it is. Least I can do is some discovery on how much of a headache this might be. I'm a Spotify user myself and can appreciate the desire to "beam" music to it 😆 Nothing I do will be as slick as direct Mopidy integration though. Some time later....Welp! I just wasted about an hour discovering that Mopidy's BUT I have come up with the most devious and contrived of scripts: #!/bin/bash
if [ "$PLAYER_EVENT" = "start" ]; then
mpc clear
mpc add spotify:track:$TRACK_ID
mpc play
sleep 1
mpc pause
elif [ "$PLAYER_EVENT" = "change" ]; then
mpc clear
mpc add spotify:track:$TRACK_ID
mpc play
sleep 1
mpc pause
elif [ "$PLAYER_EVENT" = "stop" ]; then
mpc play
elif [ "$PLAYER_EVENT" = "volume_set" ]; then
mpc_volume=$(($VOLUME * 100 / 65536))
mpc volume $mpc_volume
fi You will need to
Now that's working I'll explain the ridiculous script above...
You will need to put this somewhere like
And add: Mine looks like this because I'm playing audio out of the Pi's headphone jack in both cases:
Now when you play a song via Spotify Connect, Raspotify will call this hook, add it to Mopidy, play it so that it shows on the LCD and then pause it. I've tested this with my Spotify account set up on a Pi 4 and it appears to work. In fact I can play on Mopidy and Raspotify simultaneously if I want a clashing horrible racket. I'll type this up more coherently when it's not 11pm, but I feel I'm onto something here. Edit: I have updated the script so that it syncs Raspotify volume changes over to Mopidy, alas I don't think it's possibly to sync the other way, but this does mean your Raspotify volume shows on the LCD. ThoughtsIt's not very robust! I've been trying to sync the playing track better... but it really doesn't work well. People who just want to use Spotify Connect and not Mopidy should speak up, because I suspect I can build something leaner that doesn't involve Mopidy at all. The big difficulty there is sourcing the album art and track information, however. Right now Mopidy (even for those who don't necessarily want to use it directly) is a really good way to grab full details from a spotify Track ID. Rolling that from scratch wont be so fun. |
Thank you so much for your help @Gadgetoid ! I would'nt need Mopidy to be happy with my setup. :) Using my Raspi and the Pirate Audio as a Spotify Connect device with visible Track details and being able to control the volume etc. would be awesome for me. |
Okay, take 2- no Mopidy edition. This is VERY BETA and needs A LOT OF WORK. Right now it displays track info and album art (caching art locally) but does not show volume/transport information. It will probably never support the buttons, since that requires a much more complex Spotify authentication context- but maybe that's feasible as a bigger, separate project. (I think this whole script could run totally separate of anything else and just use You will need to (possibly incomplete): Go to https://developer.spotify.com/dashboard and set up a new app. Grab your Client ID and Secret and keep them handy.
Make sure your
Make sure you restart
Save this script in #!/bin/bash
exec >> /home/pi/spotipy/hook.log
exec 2>&1
echo "Changing track: $TRACK_ID"
if [ "$PLAYER_EVENT" = "start" ]; then
echo $TRACK_ID > /tmp/spotify_album_display
elif [ "$PLAYER_EVENT" = "change" ]; then
echo $TRACK_ID > /tmp/spotify_album_display
elif [ "$PLAYER_EVENT" = "stop" ]; then
echo $TRACK_ID > /tmp/spotify_album_display
elif [ "$PLAYER_EVENT" = "volume_set" ]; then
sleep 0.1
fi Save this script in import time
import os
import requests
from pathlib import Path
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
import spotipy.util as util
import unittest.mock as mock
import argparse
import sys
FIFO_NAME = "/tmp/spotify_album_display"
class Display():
"""Base class to represent a pidi display output."""
# pylint: disable=too-many-instance-attributes
def __init__(self, args=None):
"""Initialise a new display."""
self._size = args.size
self._title = ''
self._shuffle = False
self._repeat = False
self._state = ''
self._volume = 0
self._progress = 0
self._elapsed = 0
self._title = ''
self._album = ''
self._artist = ''
def update_album_art(self, input_file):
"""Update the display album art."""
raise NotImplementedError
def update_overlay(self, shuffle, repeat, state, volume,
progress, elapsed, title, album, artist):
"""Update the display transport information."""
# pylint: disable=too-many-arguments
self._shuffle = shuffle
self._repeat = repeat
self._state = state
self._volume = volume
self._progress = progress
self._elapsed = elapsed
self._title = title
self._album = album
self._artist = artist
def redraw(self):
"""Redraw the display."""
raise NotImplementedError
def add_args(argparse): # pylint: disable=no-self-argument
"""Expand argparse instance with display-specific args."""
try:
os.unlink(FIFO_NAME)
except (IOError, OSError):
pass
os.mkfifo(FIFO_NAME)
os.chmod(FIFO_NAME, 0o777)
mock_display = mock.Mock()
mock_display.Display = Display
sys.modules["pidi.display"] = mock_display
import pidi_display_st7789
parser = argparse.ArgumentParser()
pidi_display_st7789.DisplayST7789.add_args(parser)
args = parser.parse_args()
args.size = 240
display = pidi_display_st7789.DisplayST7789(args)
auth_manager = SpotifyClientCredentials()
spotify = spotipy.Spotify(auth_manager=auth_manager)
with open(FIFO_NAME, "r") as fifo:
while True:
track_id = fifo.read().strip()
if len(track_id) == 0:
time.sleep(0.1)
continue
track = spotify.track(track_id)
image_url = None
album_id = track["album"]["id"]
album_name = track["album"]["name"]
artist_name = track["album"]["artists"][0]["name"]
track_name = track["name"]
for image in track["album"]["images"]:
if image["height"] == 300:
image_url = image["url"]
image_cache_path = Path(f"/home/pi/spotipy/cache/{album_id}.png")
if not image_cache_path.is_file():
print("Missing cached image, loading now..")
image = requests.get(image_url)
with open(image_cache_path, "wb") as f:
f.write(image.content)
display.update_album_art(image_cache_path)
display.update_overlay(
False,
False,
"play",
1,
0,
0,
track_name,
album_name,
artist_name
)
# Crossfade album art fudge
for x in range(30):
display.redraw()
time.sleep(1.0 / 30) Now grab your Client ID and Secret from before and set them on your env, or save them into a script for easier setup:
Run
The display should light up with whatever was last written to it. Test that the front end works by firing a track ID into the fifo:
You should see the album art and track info update on Pirate Audio with the song Ember by Kubbi. Now connect to Raspotify and change some tracks to see if it works. |
That's awesome @Gadgetoid . I really appreciate your help. To be honest the whole RPi, Linux, ssh etc. thing is fairly new to me. But I will definetely try to make it work and want to use the whole project to get a deeper understanding of everything. |
What I did: I can't connect through Spotify Connect when "--onevent /home/pi/spotipy/hook.sh" is added. When I add only OPTIONS="--device hw:1,0" I can connect properly. BUT: I can hear no audio through lineout. Do I need to install audio/video drivers for the Pirate Audio which normally would be included in pirate-audio/mopidy? Before starting from scratch it worked fine with Raspotify and Mopidy combined. Also, when I run art.py: |
Ah looks like you need to run Edit: Done a lot of work on this, and new code incoming shortly. Was important to me that volume/transport at least kinda matched and that the album art crossfade worked properly. |
Updated code replaces For the time being you will have to run it like so:
It will need the same auth as documented above. This has:
I have no idea how librespot/Raspotify volume works. We could do local volume control but it would not sync up with Spotify Connect volume... ie if you turn the volume down locally you'll never be able to turn it back up again. I feel like the A/B X/Y buttons should do something but since they can't control Spotify at all... I'm really not sure what that should be. |
Wow - I am really grateful and impressed how quickly you can hack something like this. I've already learned a lot today. I hope it is okay, to ask so many questions. Is started with adding
to /boot/config.txt. Afterwards I executed the following:
Then I added
and executed
Afterwards I executed:
Somehow the Terminal gets unresponsive at this point
Also the problem persists, that I can't connect through Spotify Connect when "--onevent /home/pi/spotipy/hook.sh" is added. When I add only OPTIONS="--device hw:1,0" I can connect properly. |
You're most of the way there! I should mention that to test I encountered the problem with adding a hook, where I wasn't able to log in. It could be that Raspotify cannot run Try: And make sure your Edit: I should clarify that |
Shouldn't the new script generate the new hook.sh? Or do I still have to sudo nano generate it? Is it correct that "python3 -m pidi_spotify" kind of freezes with open 5?
|
You'll have to copy the "hook.sh" from the So assumping you're somewhere like: And try: (and yes |
oh boy! that did it. and it works really good. 😍 |
So at the moment the whole thing only works while "python3 -m pidi_spotify" is running, right? This is what you meant when you wrote that you haven't turned it into a system-service-like-thingy just yet, right? |
That's correct! Yes. I need to create a way to configure pidi_spotify and write a script to run it as a service. You can probably create a script called #!/bin/bash
cd /home/pi/pidi_spotify
export SPOTIPY_CLIENT_ID="YOUR CLIENT ID"
export SPOTIPY_CLIENT_SECRET="YOUR CLIENT SECRET"
python3 -m pidi_spotify Then add it to your crontab by typing:
And then adding:
When it's finished I hope Edit (again): thanks for running through these steps and trying this early, it really helps me identify the sticking points and build a better application. Thanks to you I've no doubt (once I've actually finished this thing anyway) a lot of people will be enjoying slick album art display soon! |
Right I've added instructions to the PiDi Spotify repository. Any other questions/issues/suggestions/requests then please raise them in a new issue over there: https://github.com/pimoroni/pidi-spotify For those wanting to use Raspotify/Spotify Connect with Mopidy then you will still need to use my first soution above which I will re-iterate here:
Then use the below script as your
Save this as #!/bin/bash
if [ "$PLAYER_EVENT" = "start" ]; then
mpc clear
mpc add spotify:track:$TRACK_ID
mpc play
sleep 1
mpc pause
elif [ "$PLAYER_EVENT" = "change" ]; then
mpc clear
mpc add spotify:track:$TRACK_ID
mpc play
sleep 1
mpc pause
elif [ "$PLAYER_EVENT" = "stop" ]; then
mpc play
elif [ "$PLAYER_EVENT" = "volume_set" ]; then
mpc_volume=$(($VOLUME * 100 / 65536))
mpc volume $mpc_volume
fi |
pidi-spotify and raspotify are now all I need for Spotify on my pirate-audio-enabled Pi 2; that and shairport-sync for Airplay. Thank you @Gadgetoid! |
I bought a Pirate Audio device because I thought it supports Spotify Connect but it turns out I can stream Spotify to it but no via Spotify Connect.
I could not find a way to add Spotify Connect to Mopidy.
I tried achieving this with Volumio since it supports external displays and GPIO control via plugins and also Spotify Connect but I could not even get the sound output to work.
To summarize I think Spotify Connect would be a great feature but I am unable to get it working.
The text was updated successfully, but these errors were encountered: