Skip to content
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

[WIP] Album Art and Binary Responses #49

Closed
wants to merge 13 commits into from
Closed

[WIP] Album Art and Binary Responses #49

wants to merge 13 commits into from

Conversation

CMurtagh-LGTM
Copy link

@CMurtagh-LGTM CMurtagh-LGTM commented Jan 11, 2022

resolves #17.

Adds the albumart, readpicture and binartlimit commands, and the ability to respond with binary data.

I need help working out how to get the location of local images with the information given to a command.

Also needs tests.

@kingosticks
Copy link
Member

I've not looked at this PR properly yet but have you seen https://docs.mopidy.com/en/latest/api/ext/#mopidy.ext.Extension.get_cache_dir ?

@CMurtagh-LGTM
Copy link
Author

CMurtagh-LGTM commented Jan 14, 2022

I've not looked at this PR properly yet but have you seen https://docs.mopidy.com/en/latest/api/ext/#mopidy.ext.Extension.get_cache_dir ?

For this I would need to explicitly import from mopidy-local and somehow gain access to the config object.

@kingosticks
Copy link
Member

Before you go any further with the cache, what's the aim? To avoid redownloading the image for each of the MPD client's chunked requests? If so, does it need to be on disk or is it better in memory and better as part of the connection context? I'm wary of caching anything in a frontend. Especially for long periods of time.

@kingosticks
Copy link
Member

And there should be nothing backed specific in a frontend e.g. the mopidy-local stuff doesn't belong in here. But I'll have a proper look later.

@kingosticks
Copy link
Member

Hm re the import, ok definitely not. I must have misunderstood what you were doing here.

@CMurtagh-LGTM
Copy link
Author

Before you go any further with the cache, what's the aim? To avoid redownloading the image for each of the MPD client's chunked requests? If so, does it need to be on disk or is it better in memory and better as part of the connection context? I'm wary of caching anything in a frontend. Especially for long periods of time.

Currently it only saves the latest image in memory, it replaces this each time a new image is requested.

And there should be nothing backed specific in a frontend e.g. the mopidy-local stuff doesn't belong in here. But I'll have a proper look later.

It would be nice if mopidy.core had a function that asked the backend for the actual image. I can't think of any other way that would not be backend specific.

@kingosticks
Copy link
Member

kingosticks commented Jan 14, 2022

Ok so yes, I misunderstood why you were trying to find the cache directory, I thought you were saving stuff there rather than trying to work out where the local backend was keeping things. I blame trying to read it on a mobile.

Doesn't Mopidy-Local's get_images() provide an HTTP URI to the image which can be downloaded, just like any other backend? Why do we need to treat it differently? Am I remembering this wrong?! (I don't have it installed anywhere right now).

It would be nice if mopidy.core had a function that asked the backend for the actual image. I can't think of any other way that would not be backend specific.

For nearly all backends it would have to download the image, just as you are doing here. Except core doesn't have any MPD context and so it'd be harder to work out what was actually in use (when caching, which it would still need to do). And this core method seems specific to Mopidy-MPD, I don't think this would be generally useful.

Currently it only saves the latest image in memory, it replaces this each time a new image is requested.

This should be per-context. Imagine two different clients (or one client with two active connections) requesting different images at the same time .

@girst
Copy link
Member

girst commented Jan 14, 2022

two thoughts:

  • do we need to bring in a new and large dependency (requests)? IMO, urllib.request from the stdlib would do plenty for the use case here.
  • instead of downloading the full image and caching it to just return parts of it, we could use the Range header to only request the part we want to return right now.
from urllib.request import Request, urlopen
with urlopen(Request(image_uri, headers={'range': f'bytes={offset}-{offset+context.binary_limit-1}'})) as r:
    bytes = r.read(context.binary_limit)
    # length = r.headers.get('content-length')

@kingosticks
Copy link
Member

kingosticks commented Jan 14, 2022

  • Requests vs urlib, good point.
  • 99% of the time the client is going to want all parts. I would imagine multiple small requests are going to be slower overall but removing caching sounds nice. Guess we could test both implementations. If we wanted to be really clever we'd do a range request for the first one and return that, and then get the whole thing afterwards in the background, doubt it is worth the bother though.

@kingosticks
Copy link
Member

kingosticks commented Jan 14, 2022

Doesn't Mopidy-Local's get_images() provide an HTTP URI to the image which can be downloaded, just like any other backend? Why do we need to treat it differently? Am I remembering this wrong?! (I don't have it installed anywhere right now).

Yes, this is how it works. It provides relative URIs. i.e. /local/0c24d58571fdbe999ad1809ed65d8bc7-75x65.jpeg and we can GET these. However, unless I am missing something, Mopidy-MPD doesn't know the server's root URI so it is stuck. We could fix Mopidy-Local to output absolute image URIs.

But then none of this works if Mopidy-HTTP is not enabled. Which is ugly. And solved by loading the images directly from the disk, like you were doing. Although we an't assume we know where those files are. Or that Mopidy-Local hasnt changed and moved them.

@girst
Copy link
Member

girst commented Jan 14, 2022 via email

@kingosticks
Copy link
Member

I was hoping to avoid guessing what the hostname was.

does mopidy-local have a way to get the bind address?

I think I have a way but it's too hacky to even consider.

I'm almost coming round to the idea of core.library.get_image_raw()...

Comment on lines +108 to +110
with open(
os.path.join(data_path, extension, "images", file), "rb"
) as image_file:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if the file doesn't exist or we don't have read permissions?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is an excellent point, I'll worry about this once we decide on what we're doing.

@djmattyg007
Copy link

do we need to bring in a new and large dependency (requests)? IMO, urllib.request from the stdlib would do plenty for the use case here.

What's wrong with a dependency on requests? The Mopidy core already has a hard dependency on it. Everything else already has a transitive dependency on it.

mopidy_mpd/protocol/music_db.py Outdated Show resolved Hide resolved
mopidy_mpd/protocol/music_db.py Outdated Show resolved Hide resolved
mopidy_mpd/protocol/music_db.py Outdated Show resolved Hide resolved
mopidy_mpd/session.py Outdated Show resolved Hide resolved
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support MPD albumart and readpicture command
4 participants