Search code examples
spotifylibspotify

libspotify: What can I and can't I do with image IDs?


Various libspotify API functions deal with image IDs:

These all return an image ID as a const byte*:

sp_album_cover
sp_artist_portrait
sp_artistbrowse_portrait
sp_image_image_id

sp_image_create takes an image ID parameter as const byte[20], while sp_playlist_get_image takes an image ID parameter as byte[20] and fills it with an image ID value.

In this question, a Spotify employee says both that the content of the image ID is opaque and that the size of 20 is not necessarily an accurate length for the image ID: libspotify API: image ID format?

sp_image_create takes 20 bytes long image_id parameter. Does that mean the maximum length of image id is 20 bytes?

No. sp_subscribers is another example of where we've put a fake number in for the compiler. The contents of an image id pointer are opaque and likely to change between releases. Don't write code that makes assumptions about them, because it'll break.

However, in order to use sp_playlist_get_image, the caller needs to allocate the array to store the image ID. This seems to be inconsistent advice, or is at least surprising. Which of the following is true?

  • Interpretation A: Image IDs will always be exactly 20 bytes.
  • Interpretation B: Image IDs might be of any length up to 20 bytes.
  • Interpretation C: Image IDs might be of any length, but the image IDs returned by sp_playlist_get_image are guaranteed to be no more than 20 bytes.
  • Interpretation D: Image IDs might be of any length and sp_playlist_get_image cannot be used safely at all.

I think the answer to the linked question rules out A and probably B, so I think the answer is probably C, as frustrating as that is. An utter pessimist might go with D.

I'm interested because I'm trying to write a safer and higher-level .NET wrapper than the existing libspotify.net, and I'm unsure how to present image IDs in managed code. I think the only thing for it is to have two alternative implementations - one with a 20 byte buffer that represents an image ID returned from sp_playlist_get_image, and one with an IntPtr that represents an image ID returned from anything else. If the library made sufficient guarantees about the size and nature of an image ID I could always use my own buffer and copy into it when necessary, but I fear it's looking unlikely that libspotify makes guarantees anywhere near strong enough to allow this.


Solution

  • For the current release of libSpotify, Interpretation C is correct for that specific call. Since it takes byte[20], the function guarantees that if you allocate 20 bytes, you'll always have enough for the playlist's image ID. If that guarantee changes in the future the function signature will be changed, assuming we haven't made it work like everything else by then.

    Your hybrid solution actually sounds the best for now, considering the state of that API. Using IntPtr where you can will be a lot more future-proof when that nasty sp_playlist_get_image goes away.

    I hope your project goes well — we've been wanting a decent .NET wrapper for ages but have never had the time to do the whole thing ourselves. If it's open source, I'll gladly contribute.