HTTP API : Retreiving list of entire library

Continuing from the discussion I started on GitHub. The client I develop (rompr) needs a way to retrieve the full contents of mopidy’s library as a list of Track models. Currently I do this using a search with no parameters, which very nicely returns all local tracks and all tracks in spotify playlists. Now that this behaviour is deprecated I can see no way to make my client work any more.

Let me explain a little why I do this. I know that maintaining a database of tracks away from Mopidy may seem like a wierd idea. However I do it for several reasons.

  1. Sorting of badly-tagged local tracks. I can detect badly tagged compilations, sort almost untagged files into albums, and generally make neatness out of untidy music collections. This is the reason I wrote rompr, the code to do it is at the very heart of the application. Removing it would amount to a 50% rewrite.
  2. I can do playcounts, tags, and ratings.
  3. More than that, I can count plays for tracks which are not in mopidy’s library - eg tracks that are played as the result of a spotify search.
  4. I can use all this data to generate ‘smart’ playlists.
  5. I can add tracks on-the-fly. If I’m listening to something that’s not in my library (eg a SoundCloud track I found by searching, Spotify tracks, or etc) I can just hit a button and add it directly into my music collection. I don’t make much use of playlists. I like libraries.
  6. Now that mopidy returns track info for radio stations, if I’m listening to the radio and hear something I like, I can rate it. Rompr will search for it on Spotify and add it to my collection, or to my ‘Wishlist’ if it can’t find it.

So it’s about building a music collection that spans all my music sources and presenting it as a library, like my old CD collection but in browser form. Mopidy is the perfect backend for this but it’s looking like I’m not going to be able to do it any more.

I’ve experimented with get_distinct(‘albumartist’), which might go some way to providing a new way to do this, but I get an error from Mopidy saying the result is not JSON serializable. Also the docs seem to indicate that this is another command I might be best avoiding using. I’ve also tried library.lookup(null, [‘local’]) to try and get all local tracks, but get no results.

Any thoughts from the devs? I’d really like a single-hit command to do this.

Sadly for you we are mostly actively working against this use case as it’s kinda a pain for us. Problem being backends where “all” the music doesn’t make sense such as Spotify. For local tracks this of course is less of an issue. We’ve also had a lot of bad experience with certain MPD clients trying to be “smart”, like taking a search for “foo fighters” and turning it into a search for “fo” so they can do a client side search, which does not at all work with streaming services…

Also the use case of just using Mopidy as a “dumb” backend isn’t something we’ve been trying to support, from our point of view we would normally just stick things into a Mopidy extension and take it from there.

I’m not quite sure where we want to go with respect to catering to rompr’s needs, as I’m sure you understand even something aiming to be as generic as Mopidy still needs to limit it’s scope at some point. So basically I don’t have any answer for you despite having trying to think about this for a while.

As for the JSON serializable part, that sounds like a bug if you can still reproduce and narrow it down.

I see what you’re saying. But it’s very disappointing that you’re actually removing functionality. Why not leave it as it is for those backends that currently support it? Mopidy-Spotify currently does something very sensible. For those backends that don’t want to support it, or where it makes no sense, don’t support it. That’s the current state and I’m fine with that. Local-JSON, Spotify, GMusic, Beets, BeetsLocal and a couple more I think all support this currently.

I don’t see this as using Mopidy as a dumb backend. What I’m doing is providing what I believe is the most user-freindly GUI onto a highly functional server, using the server’s features to display its information in a helpful way. Bear in mind my client also supports mpd. For the kind of rating and tagging I’m describing there’s no support possible in mpd so making it via a mopidy extension would disadvantage half the user base. (MPD does have it’s ‘stickers’ database but there are exactly zero clients that use it, indicating that server-side support for that kind of thing is not popular or useful).

Anyway, if you are definitely not going to keep the functionality the way it is then I must request that you remove Rompr from your list of supported clients, as Rompr without the music collection is just another dumb frontend and I don’t want to deal with the support requests.

So far 1.x you are safe as we are discouraging the use (perhaps a bit to force-ably), but for 2.x I do think we will remove the empty search behavior. What we might do instead is something like what we did for supporting MPD list commands, that is add a extra backend method specifically for that use case. We would “just” need to figure out some sane way of doing without memory use going through the roof when people come along with databases with hundreds of thousands of tracks. Ideally we could stream results, but getting that to play nice with pykka might be tricky.

So like I said for 1.x we aren’t going to break this, for 2.x I suspect we will change things, but we’ve not decided if we will provide an alternative.

Well with 1.0.4 it’s already broken with mopidy-spotify.

File "/usr/local/lib/python2.7/site-packages/mopidy_spotify/library.py", line 269, in _get_all_tracks
for playlist in self.backend.playlists.playlists:
AttributeError: 'SpotifyPlaylistsProvider' object has no attribute 'playlists'

I’ve not bothered raising it as a bug because as you say, it’s deprecated. But it has completely broken rompr so if it’s not going to be fixed I must repeat my request to remove rompr from your supported clients list.

FYI: https://github.com/mopidy/mopidy-spotify/commit/8e7e9b492cd90c1bb4079611850d881078741eb0 fixes this, and we would have unbroken it much sooner if we actually got a bug report about that we had regressed.

Though we haven’t yet released a Mopidy-Spotify 1.3.1 with this fix as nobody has complained about it.

Thanks for the heads up. I only discovered it just before making my post and assumed that you wouldn’t be fixing deprecated functionality.

A couple of my users have complained about it, it just took me this long to get around to investigating.

We just released Mopidy-Spotify 1.4.0 which includes the fix for the empty search regression.

I’ve done some experiments and I’ve found a way I can achieve this, in fact in a better way, by using the MPD protocol and iterating over user-selected folders using the ‘lsinfo’ command.

So I think I’m going to ‘regress’ Rompr to use only the MPD protocol, this makes more sense for me and thanks to your recent work on the mpd frontend there’s very little that doesn’t work.

On the subject, what do you think about the idea of extending the mpd output to include a little more mopidy-specific information? I’ve found it very easy to alter translator.py to output, for example, album URIs and Images in track results. This of course is not part of the mpd specification but it hasn’t broken any client I’ve tested with. I just output ‘AlbumUri’ and ‘AlbumImage’ as extra lines in the mpd output. This is extremely useful info for a client to have.