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

View File

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

View File

@ -2,7 +2,7 @@ use failure::Error;
use gtk;
use gtk::prelude::*;
use hammond_data::Podcast;
use hammond_data::{Podcast, PodcastCoverQuery};
use hammond_data::dbqueries;
use app::Action;
@ -57,7 +57,7 @@ impl ShowsPopulated {
let ignore = get_ignored_shows()?;
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);
self.flowbox.add(&flowbox_child.child);
});
@ -116,23 +116,23 @@ impl Default for ShowsChild {
}
impl ShowsChild {
pub fn new(pd: Arc<Podcast>) -> ShowsChild {
pub fn new(pd: Podcast) -> ShowsChild {
let child = ShowsChild::default();
child.init(pd);
child
}
fn init(&self, pd: Arc<Podcast>) {
fn init(&self, pd: Podcast) {
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)
}
WidgetExt::set_name(&self.child, &pd.id().to_string());
}
fn set_cover(&self, pd: Arc<Podcast>) -> Result<(), Error> {
set_image_from_path(&self.cover, &pd.clone().into(), 256)
fn set_cover(&self, pd: Arc<PodcastCoverQuery>) -> Result<(), Error> {
set_image_from_path(&self.cover, pd, 256)
}
}

View File

@ -113,7 +113,7 @@ impl ShowWidget {
/// Set the show cover.
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.