Commit 4999f0b9 authored by Daniel García Moreno's avatar Daniel García Moreno

stickers: gif with timeout_add

parent e55bc350
......@@ -11,7 +11,7 @@ use util::cache_dir_path;
pub fn get_thumb_async(bk: &Backend, media: String, tx: Sender<String>) -> Result<(), Error> {
let baseu = bk.get_base_url()?;
thread::spawn(move || {
semaphore!(bk.limit_threads, {
match thumb!(&baseu, &media) {
Ok(fname) => {
tx.send(fname).unwrap();
......@@ -25,6 +25,23 @@ pub fn get_thumb_async(bk: &Backend, media: String, tx: Sender<String>) -> Resul
Ok(())
}
pub fn get_media_async(bk: &Backend, media: String, tx: Sender<String>) -> Result<(), Error> {
let baseu = bk.get_base_url()?;
semaphore!(bk.limit_threads, {
match media!(&baseu, &media) {
Ok(fname) => {
tx.send(fname).unwrap();
}
Err(_) => {
tx.send(String::from("")).unwrap();
}
};
});
Ok(())
}
pub fn get_media(bk: &Backend, media: String) -> Result<(), Error> {
let baseu = bk.get_base_url()?;
......
......@@ -276,6 +276,10 @@ impl Backend {
let r = media::get_thumb_async(self, media, ctx);
bkerror!(r, tx, BKResponse::CommandError);
}
Ok(BKCommand::GetMediaAsync(media, ctx)) => {
let r = media::get_media_async(self, media, ctx);
bkerror!(r, tx, BKResponse::CommandError);
}
Ok(BKCommand::GetMedia(media)) => {
let r = media::get_media(self, media);
bkerror!(r, tx, BKResponse::CommandError);
......
......@@ -32,6 +32,7 @@ pub enum BKCommand {
GetMessageContext(Message),
GetRoomAvatar(String),
GetThumbAsync(String, Sender<String>),
GetMediaAsync(String, Sender<String>),
GetFileAsync(String, Sender<String>),
GetAvatarAsync(Option<Member>, Sender<String>),
GetMedia(String),
......
......@@ -16,36 +16,6 @@ use types::Member;
use self::serde_json::Value as JsonValue;
macro_rules! semaphore {
($cv: expr, $blk: block) => {{
let thread_count = $cv.clone();
thread::spawn(move || {
// waiting, less than 20 threads at the same time
// this is a semaphore
// TODO: use std::sync::Semaphore when it's on stable version
// https://doc.rust-lang.org/1.1.0/std/sync/struct.Semaphore.html
let &(ref num, ref cvar) = &*thread_count;
{
let mut start = num.lock().unwrap();
while *start >= 20 {
start = cvar.wait(start).unwrap()
}
*start += 1;
}
$blk
// freeing the cvar for new threads
{
let mut counter = num.lock().unwrap();
*counter -= 1;
}
cvar.notify_one();
});
}}
}
pub fn get_username(bk: &Backend) -> Result<(), Error> {
let id = bk.data.lock().unwrap().user_id.clone();
let url = bk.url(&format!("profile/{}/displayname", id.clone()), vec![])?;
......
......@@ -59,6 +59,36 @@ pub enum AvatarMode {
}
macro_rules! semaphore {
($cv: expr, $blk: block) => {{
let thread_count = $cv.clone();
thread::spawn(move || {
// waiting, less than 20 threads at the same time
// this is a semaphore
// TODO: use std::sync::Semaphore when it's on stable version
// https://doc.rust-lang.org/1.1.0/std/sync/struct.Semaphore.html
let &(ref num, ref cvar) = &*thread_count;
{
let mut start = num.lock().unwrap();
while *start >= 20 {
start = cvar.wait(start).unwrap()
}
*start += 1;
}
$blk
// freeing the cvar for new threads
{
let mut counter = num.lock().unwrap();
*counter -= 1;
}
cvar.notify_one();
});
}}
}
#[macro_export]
macro_rules! identicon {
($userid: expr, $name: expr) => { draw_identicon($userid, $name, AvatarMode::Circle) }
......
......@@ -30,7 +30,7 @@ use types::StickerGroup;
use types::Sticker;
use types::Message;
use util::load_thumb;
use util::{load_async, Thumb};
impl AppOp {
......@@ -176,7 +176,7 @@ impl AppOp {
let backend = self.backend.clone();
let (w, h) = img.size;
load_thumb(&backend, &img.thumbnail.clone(), &image, (size, h * size / w));
load_async(&backend, &img.thumbnail.clone(), &image, (size, h * size / w), Thumb(false));
}
content.show_all();
......
extern crate glib;
extern crate cairo;
extern crate gtk;
extern crate gdk;
......@@ -11,6 +12,8 @@ use std::sync::mpsc::TryRecvError;
use backend::BKCommand;
use self::gdk_pixbuf::Pixbuf;
use self::gdk_pixbuf::PixbufExt;
use self::gdk_pixbuf::PixbufAnimation;
use self::gdk_pixbuf::PixbufAnimationExt;
use failure::Error;
use self::gdk::ContextExt;
......@@ -67,9 +70,11 @@ pub fn markup_text(s: &str) -> String {
markup_links(&html_escape(s))
}
pub struct Thumb(pub bool);
/// If `path` starts with mxc this func download the img async, in other case the image is loaded
/// in the `image` widget scaled to size
pub fn load_thumb(backend: &Sender<BKCommand>, path: &str, img: &gtk::Image, size: (i32, i32)) {
pub fn load_async(backend: &Sender<BKCommand>, path: &str, img: &gtk::Image, size: (i32, i32), Thumb(thumb): Thumb) {
let pixbuf: Option<Pixbuf>;
if path.starts_with("mxc:") {
......@@ -83,7 +88,11 @@ pub fn load_thumb(backend: &Sender<BKCommand>, path: &str, img: &gtk::Image, siz
// asyn load
let (tx, rx): (Sender<String>, Receiver<String>) = channel();
backend.send(BKCommand::GetThumbAsync(path.to_string(), tx)).unwrap();
let command = match thumb {
false => BKCommand::GetMediaAsync(path.to_string(), tx),
true => BKCommand::GetThumbAsync(path.to_string(), tx),
};
backend.send(command).unwrap();
let im = img.clone();
gtk::timeout_add(50, move || match rx.try_recv() {
Err(TryRecvError::Empty) => gtk::Continue(true),
......@@ -93,7 +102,7 @@ pub fn load_thumb(backend: &Sender<BKCommand>, path: &str, img: &gtk::Image, siz
if let Ok(pix) = Pixbuf::new_from_file_at_scale(&f, size.0, size.1, true) {
im.set_from_pixbuf(&pix);
} else {
im.set_from_file(f);
load_animation(&f, &im, size);
}
gtk::Continue(false)
}
......@@ -105,6 +114,26 @@ pub fn load_thumb(backend: &Sender<BKCommand>, path: &str, img: &gtk::Image, siz
if let Some(pix) = pixbuf {
img.set_from_pixbuf(&pix);
} else {
img.set_from_file(path);
load_animation(path, &img, size);
}
}
pub fn load_animation(fname: &str, image: &gtk::Image, size: (i32, i32)) {
let res = PixbufAnimation::new_from_file(fname);
if res.is_err() {
return;
}
let anim = res.unwrap();
let iter = anim.get_iter(&glib::get_current_time());
let im = image.clone();
gtk::timeout_add(iter.get_delay_time() as u32, move || {
iter.advance(&glib::get_current_time());
let pix = iter.get_pixbuf();
// TODO: calc size
if let Some(scaled) = pix.scale_simple(size.0, size.1, gdk_pixbuf::InterpType::Bilinear) {
im.set_from_pixbuf(&scaled);
}
gtk::Continue(true)
});
}
......@@ -13,8 +13,8 @@ use self::chrono::prelude::*;
use backend::BKCommand;
use fractal_api as api;
use util;
use util::markup_text;
use util::{load_async, Thumb};
use std::path::Path;
......@@ -266,7 +266,7 @@ impl<'a> MessageBox<'a> {
let url = msg.url.clone().unwrap_or_default();
let backend = self.op.backend.clone();
util::load_thumb(&backend, &msg.thumb.clone().unwrap_or_default(), &image, (600, 400));
load_async(&backend, &msg.thumb.clone().unwrap_or_default(), &image, (600, 400), Thumb(true));
//let img = image.clone();
viewbtn.connect_clicked(move |_| {
......@@ -288,7 +288,7 @@ impl<'a> MessageBox<'a> {
let image = gtk::Image::new();
let backend = self.op.backend.clone();
util::load_thumb(&backend, &msg.thumb.clone().unwrap_or_default(), &image, (200, 200));
load_async(&backend, &msg.url.clone().unwrap_or_default(), &image, (200, 200), Thumb(false));
image.set_tooltip_text(&self.msg.body[..]);
bx.add(&image);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment