Implement async loading of the Show covers.

This commit is contained in:
Jordan Petridis 2018-03-28 22:41:45 +03:00
parent daa8f15ce9
commit badcbc32c6
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6
4 changed files with 40 additions and 21 deletions

View File

@ -2,6 +2,7 @@
use gdk_pixbuf::Pixbuf; use gdk_pixbuf::Pixbuf;
use gio::{Settings, SettingsExt}; use gio::{Settings, SettingsExt};
use glib;
use gtk; use gtk;
use gtk::prelude::*; use gtk::prelude::*;
@ -21,7 +22,7 @@ use hammond_downloader::downloader;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::sync::{Mutex, RwLock}; use std::sync::{Mutex, RwLock};
use std::sync::Arc; use std::sync::Arc;
use std::sync::mpsc::Sender; use std::sync::mpsc::*;
use std::thread; use std::thread;
use app::Action; use app::Action;
@ -142,7 +143,7 @@ lazy_static! {
// TODO: maybe use something that would just scale to requested size? // TODO: maybe use something that would just scale to requested size?
pub fn set_image_from_path( pub fn set_image_from_path(
image: &gtk::Image, image: &gtk::Image,
pd: &PodcastCoverQuery, pd: Arc<PodcastCoverQuery>,
size: u32, size: u32,
) -> Result<(), Error> { ) -> Result<(), Error> {
{ {
@ -158,13 +159,30 @@ pub fn set_image_from_path(
} }
} }
let img_path = downloader::cache_image(pd)?; let (sender, receiver) = channel();
let px = Pixbuf::new_from_file_at_scale(&img_path, size as i32, size as i32, true)?; let pd_ = pd.clone();
let mut hashmap = CACHED_PIXBUFS thread::spawn(move || {
.write() sender.send(downloader::cache_image(&pd_)).unwrap();
.map_err(|_| format_err!("Failed to lock pixbuf mutex."))?; });
hashmap.insert((pd.id(), size), Mutex::new(SendCell::new(px.clone())));
image.set_from_pixbuf(&px); let image = image.clone();
gtk::timeout_add(200, move || {
if let Ok(path) = receiver.try_recv() {
if let Ok(path) = path {
if let Ok(px) =
Pixbuf::new_from_file_at_scale(&path, size as i32, size as i32, true)
{
if let Ok(mut hashmap) = CACHED_PIXBUFS.write() {
hashmap.insert((pd.id(), size), Mutex::new(SendCell::new(px.clone())));
image.set_from_pixbuf(&px);
}
}
}
glib::Continue(false)
} else {
glib::Continue(true)
}
});
Ok(()) Ok(())
} }

View File

@ -10,6 +10,7 @@ use app::Action;
use utils::{get_ignored_shows, set_image_from_path}; use utils::{get_ignored_shows, set_image_from_path};
use widgets::EpisodeWidget; use widgets::EpisodeWidget;
use std::sync::Arc;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -227,7 +228,7 @@ impl EpisodesViewWidget {
} }
fn set_cover(&self, podcast_id: i32) -> Result<(), Error> { fn set_cover(&self, podcast_id: i32) -> Result<(), Error> {
let pd = dbqueries::get_podcast_cover_from_id(podcast_id)?; let pd = Arc::new(dbqueries::get_podcast_cover_from_id(podcast_id)?);
set_image_from_path(&self.image, &pd, 64) set_image_from_path(&self.image, pd, 64)
} }
} }

View File

@ -2,7 +2,7 @@ use failure::Error;
use gtk; use gtk;
use gtk::prelude::*; use gtk::prelude::*;
use hammond_data::Podcast; use hammond_data::{Podcast, PodcastCoverQuery};
use hammond_data::dbqueries; use hammond_data::dbqueries;
use app::Action; use app::Action;
@ -57,7 +57,7 @@ impl ShowsPopulated {
let ignore = get_ignored_shows()?; let ignore = get_ignored_shows()?;
let podcasts = dbqueries::get_podcasts_filter(&ignore)?; let podcasts = dbqueries::get_podcasts_filter(&ignore)?;
podcasts.into_iter().map(Arc::new).for_each(|parent| { podcasts.into_iter().for_each(|parent| {
let flowbox_child = ShowsChild::new(parent); let flowbox_child = ShowsChild::new(parent);
self.flowbox.add(&flowbox_child.child); self.flowbox.add(&flowbox_child.child);
}); });
@ -116,23 +116,23 @@ impl Default for ShowsChild {
} }
impl ShowsChild { impl ShowsChild {
pub fn new(pd: Arc<Podcast>) -> ShowsChild { pub fn new(pd: Podcast) -> ShowsChild {
let child = ShowsChild::default(); let child = ShowsChild::default();
child.init(pd); child.init(pd);
child child
} }
fn init(&self, pd: Arc<Podcast>) { fn init(&self, pd: Podcast) {
self.container.set_tooltip_text(pd.title()); self.container.set_tooltip_text(pd.title());
WidgetExt::set_name(&self.child, &pd.id().to_string());
if let Err(err) = self.set_cover(pd.clone()) { let pd = Arc::new(pd.into());
if let Err(err) = self.set_cover(pd) {
error!("Failed to set a cover: {}", err) error!("Failed to set a cover: {}", err)
} }
WidgetExt::set_name(&self.child, &pd.id().to_string());
} }
fn set_cover(&self, pd: Arc<Podcast>) -> Result<(), Error> { fn set_cover(&self, pd: Arc<PodcastCoverQuery>) -> Result<(), Error> {
set_image_from_path(&self.cover, &pd.clone().into(), 256) set_image_from_path(&self.cover, pd, 256)
} }
} }

View File

@ -113,7 +113,7 @@ impl ShowWidget {
/// Set the show cover. /// Set the show cover.
fn set_cover(&self, pd: Arc<Podcast>) -> Result<(), Error> { fn set_cover(&self, pd: Arc<Podcast>) -> Result<(), Error> {
set_image_from_path(&self.cover, &pd.into(), 128) set_image_from_path(&self.cover, Arc::new(pd.into()), 128)
} }
/// Set the descripton text. /// Set the descripton text.