owntone / owntone-server

Linux/FreeBSD DAAP (iTunes) and MPD audio server with support for AirPlay 1 and 2 speakers (multiroom), Apple Remote (and compatibles), Chromecast, Spotify and internet radio.
https://owntone.github.io/owntone-server
GNU General Public License v2.0
2.05k stars 235 forks source link

Spotify Saved feature #225

Closed snizzleorg closed 7 years ago

snizzleorg commented 8 years ago

Since spotify did away with starring tracks and albums and replaced it with the save feature it has become more complicated to add tracks to forked-daapd. The only way currently is to add a specific song to a playlist. It would be nice if forked-daapd could somehow read which tracks/albums are saved in spotify and add these to the library.

Playlists could still be left intact and act as playlists. Right now I have hundreds of playlists just so I have the respective albums in my forked-daapd library which makes the playlists somewhat cluttered and un-usable for "real" playlists

ejurgensen commented 8 years ago

I’m absolutely with you on this, but it is a bit challenging. Spotify has two (relevant) API’s:

libspotify: Supports playback, no support for saved tracks, is in not being maintained web api: No support for playback, supports saved tracks, is being maintained

Currently, forked-daapd uses just libspotify – obviously playback support is a “must-have”. To support saved tracks, forked-daapd would need to use both. That can probably be done, but would require some work. That work is at risk of being wasted if Spotify decides to kill libspotify, and doesn’t add playback support to the web api. Not that I expect they will do that, but you never know.

So I think both I and @chme are interested in adding support for the web api, but we are also a bit hesitant.

snizzleorg commented 8 years ago

Thats what spotify says about libspotify:

Important! LibSpotify and CocoaLibSpotify are no longer under active development on any platform and are considered deprecated. If you are building applications for iOS or Android, please use the iOS SDK or Android SDK. We hope to be able to provide you with a new library for other platforms during 2016.

Until then, you can still download these libraries and provision new keys for your project. However, please be aware that we cannot offer active support or guarantee future functionality on LibSpotify or CocoaLibSpotify.

https://developer.spotify.com/technologies/libspotify/

So maybe there will be a new API this year...

chme commented 8 years ago

Last year the announcement said "later this year" (2015), let's hope they really publish the new api this year (and that it has support for spotify connect).

chme commented 8 years ago

You may find this article interesting (i did): https://jodal.no/2016/02/18/guide-to-poor-api-management/

ejurgensen commented 8 years ago

Yes, very interesting article, and couldn't agree more. Also interesting to see the face behind Mopidy. I don't have high hopes about this, it seems that Spotify has its focus elsewhere.

snizzleorg commented 7 years ago

I found this: maybe this is relevant: https://github.com/plietar/librespot

ejurgensen commented 7 years ago

As I mentioned, I am experimenting with a mixture of libspotify and the web api to get the features forked-daapd needs from each. If you would like to test it, you can now do so from the branch: https://github.com/ejurgensen/forked-daapd/tree/spwebapi

When you have compiled and started forked-daapd (where I assume you are already logged in with libspotify), getting your saved tracks loaded is actually quite simple:

  1. Navigate to http://forked-daapd.local:3689/oauth
  2. Enter credentials for the UI: Username is "admin" and password is "unused" (unless you set something else in the config)
  3. Click the link, which will send you to accounts.spotify.com, where you must give forked-daapd library priviliges
  4. Spotify redirects you back. Some browsers will give a warning about a redirection to a local address, but that is exactly what we want in this case, so click continue
  5. Wait while forked-daapd loads your saved tracks

The saved tracks and albums will appear in Remote et al just like normal tracks and albums. I haven't made any special playlists for them.

Since this is still work in progress there are some caveats you should know:

  1. Spotify's web api has no push functionality, so forked-daapd cannot be notified when you add a new saved track. So you have to manually do the above (except the spotify.com step will be invisible the second time), which will reload all saved tracks. I can't really think of a good solution of this problem, tbh.
  2. If you restart forked-daapd all the saved tracks will be gone and you have to do the above again. I will get that fixed.
  3. When tracks have been added through the above they stay, even if you remove them in Spotify and repeat the above. So a forked-daapd restart is required to get rid of them.
  4. The "time_added" is currently not supported.
  5. The UI is really bare-bones (but hey it's forked-daapd's first UI).

Let me know if you run into other issues.

snizzleorg commented 7 years ago

@ejurgensen thanks for that - I'm away from home so I will ry to get this running on my mac. So far I failed using docker for this since it seems that docker on mac is not bridging the network adapter so I don't see the docker network on the mac correctly. I will try to use a virtual machine next...

ejurgensen commented 7 years ago

I've made a few modifications so that saved tracks should now stay through restart, and they should also be removed when removed from the Spotify library. The development branch for this is now spwebapi2, so I hope you both will give that a try.

ejurgensen commented 7 years ago

I've merged the branch into master, maybe more people are interested in trying this feature. The ui is still quite ugly, so one of the next steps might be adding a proper web gui for forked-daapd.

chme commented 7 years ago

Hi Espen,

i started taking a closer look at the spotifywebapi. Two things i noticed thus far:

ejurgensen commented 7 years ago

Not sure what could be the cause of the mDNS problem. Of course, if you have two instances of forked-daapd running on the same network there will be a name clash. Otherwise "dig" may tell something? Here is the output on my network:

$ dig forked-daapd.local @224.0.0.251 -p 5353

; <<>> DiG 9.9.5-3ubuntu0.10-Ubuntu <<>> forked-daapd.local @224.0.0.251 -p 5353
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56609
;; flags: qr aa; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;forked-daapd.local.        IN  A

;; ANSWER SECTION:
forked-daapd.local. 10  IN  CNAME   jessie.local.
jessie.local.       10  IN  HINFO   "ARMV7L" "LINUX"
jessie.local.       10  IN  AAAA    fd60:1a0c:940c:0:fc3c:16a4:955d:4833
jessie.local.       10  IN  AAAA    fd60:1a0c:940c::bb9
jessie.local.       10  IN  A   192.168.1.174

;; Query time: 8 msec
;; SERVER: 192.168.1.174#5353(224.0.0.251)
;; WHEN: Sun Dec 11 12:58:36 CET 2016
;; MSG SIZE  rcvd: 154

Good to hear that the refresh token can be used. That will make a lot of things more flexible. Will check the branch later.