decode image to pixbuf in blocking threads

This commit is contained in:
psykose 2024-12-01 19:23:14 +01:00
parent e7f84a4076
commit b2165e370b
Signed by: psykose
SSH key fingerprint: SHA256:pRMVjV3kRB6zl+wNx+sV8KoMnPqQAW6v8dNCxsCGZv8
4 changed files with 45 additions and 32 deletions

16
Cargo.lock generated
View file

@ -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"

View file

@ -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);
}));
}

View file

@ -56,10 +56,10 @@ glib::wrapper! {
impl Album {
fn semaphore(&self) -> &Rc<Semaphore> {
// 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));

View file

@ -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