Spotify Integration with Local Extension

I’d like to create an extension to solve an organization problem of mine. I have most of my music stored locally. However since Spotify came out I’ve started to use that more and more. However spotify’s organizational features are no up to snuff. I much prefer the file system based browser provided by mopidy. So I’ve come up with a general work around. I’d like to add local files are spotify URIs. This means my local library would contain an example.spotify file. The file would contain the spotify URI for meta data lookup and play back. It’s my understanding this is possible using a combination of things.

First, this requires some plugin to gstreamer to provide metadata for new .spotify files when mopidy local scan happens. I’m not sure if this is the best way, but it seems like the most obvious path. Next the extension would need a custom playback provider that implements the translate_uri to the Spotify URI in the file for hand off to the existing mopidy-spotify plugin. I’m not sure if this would work because the files in local directory would already have a local: URI. Is it possible to register a backend before the existing local libary attempts to translate the URI?

Does anyone have some experience working with this stuff? I’m new to python (but an experience programmer) with no knowledge of Gstreamer either. There’s many completely new pieces so any guidance is appreciated. Thanks!

If i understand you correctly you ultimatly want a mopidy client to represent your collection in a genre/artist/album/track navigation tree. This is a common request with different approaches.

Let me elaborate a bit.

  1. Listing
    It basically lists all genre/artist/album/performer/composer/year etc. over all backends and navigates down from there.
    This is the old mpd way of doing things, as it pretty much only is working for local backends. Listing all spotify artists is not something you want to do. This is why empty queries now are deprecated.
    To still enable listings for mpd client a new method get_distinct has been introduced.
    With this method correctly implemented in a local Backend a mpd client like ncmpcpp that supports listings comes very close to what you want to achieve.
    It lists all Artists from you local BE.
    Now when you click on an Artist a query for that artist is run over all BE and you see your local and the spotify albums for that artist. So you only have to make sure, that only one song with the artist (or genre/year etc.) that you want to brose in spotify is present in your local files and Voila goal achieved.

2.) Browsing
Browsing is different from list in that it is specific to a Backend. Each BE implements its own Browse Tree. As different streaming BE have rather different browsable options, this is the preferred way of doing things now. AFAIK clients using the http protocol are limited to this method. If you don’t insist on a view over all BE, but to browse over spotifys tracks in more structured way you could tinker with the browse code in Mopidy-Spotify. This is probably the easiest and cleanest option.

Also you could write non local entries in a local BE repository like Mopidy-Local-Sqlite or Mopidy-BeetsLocal. But i dont think this is the best way of doing things.

3.) Caching
This is an approach as done by the web client rompr. The client maintains it own database of all songs and presents a consistent interface over all BE. Unfortunately the new mopidy version broke this approach, but you could checkout a setup with a pre mopidy v1.0 server. It does exactly what you want to achieve.
A similar approach i have been thinking about is to have a caching BE. This would be filled with a list of specific queries to specific BE giving more control than the previous mentioned approaches.
This BE that could be browsed or queried by caching clients like rompr.

HTH

I’m working on adding get_distinct() support to Mopidy-Spotify 2. At the root level, it uses all the tracks in all your playlists as the basis for the returned data. Since get_distinct() returns a lot less data than what the old implementation did, this actually works quite nicely and returns a result within a couple of seconds for my quite large playlist collection.

For get_distinct() calls with a a query, the response is based upon a Spotify search, so for any artist you have in your local collection, get_distinct() will also search Spotify for that artist when you drill down into the client’s tree views.

That sounds great.
BTW: Is get_distinct() only used by mpd clients or is it also available for http client?

There’s no differentiation between what’s available to HTTP clients and Mopidy’s MPD frontend, but the docs for get_distinct() declares that:

This has mainly been added to support the list commands the MPD protocol supports in a more sane fashion. Other frontends are not recommended to use this method.
https://docs.mopidy.com/en/latest/api/core/#mopidy.core.LibraryController.get_distinct

I see, interesting.
So it is mainly mpd clients that support listings like ncmpcpp or MPDroid et. al. that will profit from Mopidy-Spotifys get_distinct().
Now i am curious, as to why it is not recommended.
Any pointers to the discussion?

I don’t think that having local understand .spotify files is the way to go. What would make more sense is having local understand playlists formats such as m3u, pls etc or perhaps strm files. So instead of doing something very specific for Spotify we get a simple way to add URIs to any backend into local. Starting with just strm files would likely also be easier as one file would map to the one URI it contains making it much easier to add support for this.

Not true. I have zero interest in that organizational structure because I’ve never seen it work for me. I’d like to use my own structure which I maintain via folders on the FS. The local browser displays it correctly and is easy to navigate. My goal solution is to have music coming any source (spotify in this case) browsable by the same structure. I think this generally invalidates your 1, 2, & 3 points because the same centered around the artist/album/track structure. Sorry for being unclear.

This sounds like a feasible solution. In my case I already have m3u files for each directory, but how would such a thing look in the local browser? What a playlist be displayed as a folder, or would it be in playlists only? I like this idea because it supports any URI (local/spotify/soundcloud/whatever).