From b2165e370b012ba1cfc178fd8fe2ba24a2e17edb Mon Sep 17 00:00:00 2001 From: psykose Date: Sun, 1 Dec 2024 19:23:14 +0100 Subject: [PATCH] decode image to pixbuf in blocking threads --- Cargo.lock | 16 +++++++-------- src/model/song.rs | 10 +++++++--- src/ui/album_carousel/album.rs | 15 +++++++++----- src/ui/window.rs | 36 +++++++++++++++++++--------------- 4 files changed, 45 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 586e121..1430d8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -691,9 +691,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" dependencies = [ "event-listener", "pin-project-lite", @@ -1549,9 +1549,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -2205,7 +2205,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "rustls", "socket2", "thiserror 2.0.3", @@ -2223,7 +2223,7 @@ dependencies = [ "getrandom", "rand", "ring", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "rustls", "rustls-pki-types", "slab", @@ -2434,9 +2434,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc_version" diff --git a/src/model/song.rs b/src/model/song.rs index d336528..4d72b36 100644 --- a/src/model/song.rs +++ b/src/model/song.rs @@ -101,12 +101,17 @@ impl Song { *thumbnail_loading = Some(glib::spawn_future_local(async move { let _permit = SEM.acquire().await.unwrap(); - let pixbuf = match api + let texture = match api // see pixel-size in play_queue_song.blp .cover_art(&id, Some(50 * scale_factor)) .await { - Ok(image) => audrey::util::image_to_pixbuf(image), + Ok(image) => gtk::gio::spawn_blocking(|| { + let pixbuf = audrey::util::image_to_pixbuf(image); + gdk::Texture::for_pixbuf(&pixbuf) + }) + .await + .expect("glib blocking join failed"), Err(err) => { event!( Level::ERROR, @@ -122,7 +127,6 @@ impl Song { Some(song) => song, }; - let texture = gdk::Texture::for_pixbuf(&pixbuf); song.set_thumbnail(texture); })); } diff --git a/src/ui/album_carousel/album.rs b/src/ui/album_carousel/album.rs index 06a2ddb..3db5888 100644 --- a/src/ui/album_carousel/album.rs +++ b/src/ui/album_carousel/album.rs @@ -56,10 +56,10 @@ glib::wrapper! { impl Album { fn semaphore(&self) -> &Rc { - // only load 5 at a time + // only load 10 at a time self.imp() .semaphore - .get_or_init(|| Rc::new(Semaphore::new(5))) + .get_or_init(|| Rc::new(Semaphore::new(10))) } pub fn bind(&self, client: &crate::wrappers::Client, album: &model::Album) { @@ -74,8 +74,13 @@ impl Album { let _permit = sem.acquire().await.unwrap(); // see pixel-size in album_carousel_album.blp - let pixbuf = match client.cover_art(&id, Some(160 * scale_factor)).await { - Ok(image) => audrey::util::image_to_pixbuf(image), + let texture = match client.cover_art(&id, Some(160 * scale_factor)).await { + Ok(image) => gtk::gio::spawn_blocking(|| { + let pixbuf = audrey::util::image_to_pixbuf(image); + gdk::Texture::for_pixbuf(&pixbuf) + }) + .await + .expect("glib blocking join failed"), Err(err) => { event!(Level::ERROR, "could not fetch cover for album {id}: {err}"); return; @@ -83,7 +88,7 @@ impl Album { }; let this = this.upgrade().unwrap(); - this.set_cover_art(Some(gdk::Texture::for_pixbuf(&pixbuf))); + this.set_cover_art(Some(texture)); }); self.imp().cover_art_loading.replace(Some(handle)); diff --git a/src/ui/window.rs b/src/ui/window.rs index 8998e9c..46e3673 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -792,29 +792,33 @@ mod imp { }, ); - let pixbuf = audrey::util::image_to_pixbuf(image); + let (texture, palette) = gtk::gio::spawn_blocking(move || { + let pixbuf = audrey::util::image_to_pixbuf(image); + let texture = gdk::Texture::for_pixbuf(&pixbuf); + // from amberol + let palette = color_thief::get_palette( + pixbuf.pixel_bytes().unwrap().as_ref(), + if pixbuf.has_alpha() { + color_thief::ColorFormat::Rgba + } else { + color_thief::ColorFormat::Rgb + }, + 8, + 3, + ) + .unwrap(); + + (texture, palette) + }) + .await + .expect("glib blocking join failed"); match window.song() { Some(song) if song.id() == song_id => { - let texture = gdk::Texture::for_pixbuf(&pixbuf); - window.remove_css_class("loading-cover"); window.set_playing_cover_art(Some(&texture.into())); window.imp().cover_art_buffering().stop(); - // from amberol - let palette = color_thief::get_palette( - pixbuf.pixel_bytes().unwrap().as_ref(), - if pixbuf.has_alpha() { - color_thief::ColorFormat::Rgba - } else { - color_thief::ColorFormat::Rgb - }, - 8, - 3, - ) - .unwrap(); - let mut css = String::new(); css.push_str(":root {"); for (i, color) in palette