Compare commits

..

2 commits

Author SHA1 Message Date
4241bbeab4 cover works agen 2024-11-05 12:19:40 +01:00
904cf0c55e wip cover art loading 2024-11-05 12:19:40 +01:00
4 changed files with 57 additions and 2 deletions

1
Cargo.lock generated
View file

@ -220,6 +220,7 @@ dependencies = [
"async-channel",
"base16ct",
"bindgen",
"bytes",
"chrono",
"event-listener",
"futures",

View file

@ -7,6 +7,7 @@ edition = "2021"
adw = { version = "0.7.0", package = "libadwaita", features = ["v1_6"] }
async-channel = "2.3.1"
base16ct = { version = "0.2.0", features = ["std"] }
bytes = "1.8.0"
chrono = { version = "0.4.38", features = ["serde"] }
event-listener = "5.3.1"
futures = "0.3.31"

View file

@ -178,7 +178,30 @@ impl Client {
}
pub fn cover_art_url(&self, id: &str) -> url::Url {
self.url(&["rest", "coverArt"], &[("id", id)])
self.url(&["rest", "getCoverArt"], &[("id", id)])
}
pub async fn cover_art(&self, id: &str) -> Result<bytes::Bytes, Error> {
let (sender, receiver) = async_channel::bounded(1);
let future = self.client.get(self.cover_art_url(id)).send();
runtime().spawn(async move {
async fn perform(
response: Result<reqwest::Response, reqwest::Error>,
) -> Result<bytes::Bytes, Error> {
Ok(response?.error_for_status()?.bytes().await?)
}
sender
.send(perform(future.await).await)
.await
.expect("could not send cover art bytes back to the main loop");
});
receiver
.recv()
.await
.expect("could not receive cover art bytes from tokio")
}
pub fn stream_url(&self, id: &str) -> url::Url {

View file

@ -61,6 +61,8 @@ mod imp {
pub(crate) initial_setup_handle: RefCell<Option<JoinHandle<()>>>,
mpv_event_loop_handle: RefCell<Option<JoinHandle<()>>>, // really !, not ()
zbus_executor_loop_handle: RefCell<Option<JoinHandle<()>>>, // same
loading_cover_handle: RefCell<Option<JoinHandle<()>>>,
}
impl Default for Window {
@ -111,6 +113,8 @@ mod imp {
initial_setup_handle: Default::default(),
mpv_event_loop_handle: Default::default(),
zbus_executor_loop_handle: Default::default(),
loading_cover_handle: Default::default(),
}
}
}
@ -205,7 +209,31 @@ mod imp {
event!(Level::INFO, "start file event");
window.notify("song");
window.imp().buffering_start();
// TODO: load cover art
let window2 = window.clone();
let song_id = window.song().unwrap().id();
window
.imp()
.loading_cover_handle
.replace(Some(glib::spawn_future_local(async move {
let api = window2.imp().api.borrow().as_ref().unwrap().clone();
let bytes =
api
.cover_art(&song_id)
.await
.expect("could not load cover art for song {song_id}");
match window2.song() {
Some(song) if song.id() == song_id => {
let texture = gdk::Texture::from_bytes(&glib::Bytes::from_owned(bytes)).expect(
"could not create texture from cover art for {song_id}",
);
window2.set_playing_cover_art(Some(texture));
}
_ => { event!(Level::WARN, "was too late to fetch cover for song {song_id}") },
}
})))
.map(|handle| handle.abort());
}
Event::Hook(event) => match event.reply_userdata {
@ -284,6 +312,8 @@ mod imp {
// cancel queued seek always
window.imp().queued_seek.set(None);
window.set_playing_cover_art(None::<gdk::Texture>);
}
_ => event!(Level::DEBUG, "unhandled {event:?}"),