[niepce] rust+engine: port thumbnail cache to Rust
- From: Hubert Figuière <hub src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [niepce] rust+engine: port thumbnail cache to Rust
- Date: Wed, 5 Feb 2020 02:01:45 +0000 (UTC)
commit cb0a81d31726b96f75a2c707f224e14d171d4719
Author: Hubert Figuière <hub figuiere net>
Date: Tue Feb 4 00:57:39 2020 -0500
rust+engine: port thumbnail cache to Rust
- remove thumbnail notifications and merge them with lib notifications
Cargo.lock | 3 +
crates/npc-engine/Cargo.toml | 2 +
crates/npc-engine/build.rs | 1 +
crates/npc-engine/src/lib.rs | 2 +
crates/npc-engine/src/library/mod.rs | 1 +
crates/npc-engine/src/library/notification.rs | 31 +++
crates/npc-engine/src/library/queriedcontent.rs | 4 +
crates/npc-engine/src/library/thumbnail_cache.rs | 238 +++++++++++++++++++++
crates/npc-fwk/Cargo.toml | 3 +-
crates/npc-fwk/build.rs | 1 +
crates/npc-fwk/src/lib.rs | 1 +
crates/npc-fwk/src/toolkit/gdk_utils.rs | 142 ++++++++++++
crates/npc-fwk/src/toolkit/mimetype.rs | 7 +-
crates/npc-fwk/src/toolkit/mod.rs | 2 +
.../npc-fwk/src/toolkit/movieutils.rs | 34 +--
crates/npc-fwk/src/toolkit/thumbnail.rs | 227 ++++++++++++++++++++
src/Makefile.am | 2 +
src/engine/Makefile.am | 1 -
src/engine/importer/cameraimporter.cpp | 4 +-
src/engine/importer/directoryimporter.cpp | 3 +-
src/engine/importer/iimporter.hpp | 6 +-
src/engine/library/thumbnailcache.cpp | 154 -------------
src/engine/library/thumbnailcache.hpp | 86 --------
src/fwk/toolkit/Makefile.am | 1 -
src/fwk/toolkit/gphoto.cpp | 7 +-
src/fwk/toolkit/gphoto.hpp | 5 +-
src/fwk/toolkit/movieutils.cpp | 49 -----
src/fwk/toolkit/movieutils.hpp | 43 ----
src/fwk/toolkit/notificationcenter.cpp | 26 +--
src/fwk/toolkit/notificationcenter.hpp | 7 +-
src/fwk/toolkit/thumbnail.cpp | 219 +------------------
src/fwk/toolkit/thumbnail.hpp | 34 +--
src/libraryclient/libraryclient.cpp | 9 +-
src/libraryclient/libraryclient.hpp | 8 +-
src/niepce/Makefile.am | 1 -
src/niepce/notificationcenter.cpp | 40 +---
src/niepce/notificationcenter.hpp | 11 +-
src/niepce/notifications.hpp | 34 ---
src/niepce/ui/dialogs/importdialog.cpp | 6 +-
src/niepce/ui/dialogs/importdialog.hpp | 3 +-
src/niepce/ui/filmstripcontroller.cpp | 2 -
src/niepce/ui/imageliststore.cpp | 38 ++--
src/niepce/ui/imageliststore.hpp | 4 +-
src/niepce/ui/moduleshell.cpp | 1 -
src/niepce/ui/niepcewindow.cpp | 10 +-
45 files changed, 742 insertions(+), 771 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index af6b017..6a4bf62 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -606,6 +606,8 @@ dependencies = [
"cbindgen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"exempi 2.5.0 (git+https://github.com/hfiguiere/exempi-rs.git?rev=53cfc05)",
+ "gdk-pixbuf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdk-pixbuf-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"npc-fwk 0.1.0",
@@ -624,6 +626,7 @@ dependencies = [
"exempi 2.5.0 (git+https://github.com/hfiguiere/exempi-rs.git?rev=53cfc05)",
"gdk 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk-pixbuf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdk-pixbuf-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gio 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gio-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/crates/npc-engine/Cargo.toml b/crates/npc-engine/Cargo.toml
index 0b22aab..0f1125a 100644
--- a/crates/npc-engine/Cargo.toml
+++ b/crates/npc-engine/Cargo.toml
@@ -10,6 +10,8 @@ build = "build.rs"
[dependencies]
chrono = "0.4.0"
exempi = { version = "2.5.0", git = "https://github.com/hfiguiere/exempi-rs.git", rev="53cfc05" }
+gdk-pixbuf-sys = "*"
+gdk-pixbuf = "*"
glib = "*"
libc = "0.2.39"
rusqlite = { version = "0.14.0", features = ["functions"] }
diff --git a/crates/npc-engine/build.rs b/crates/npc-engine/build.rs
index ae2ae9c..63776b0 100644
--- a/crates/npc-engine/build.rs
+++ b/crates/npc-engine/build.rs
@@ -70,6 +70,7 @@ fn main() {
.with_parse_deps(true)
.with_parse_exclude(&["exempi", "chrono", "multimap"])
.include_item("Managed")
+ .exclude_item("GdkPixbuf")
.exclude_item("GtkWindow")
.exclude_item("GtkToolbar")
.exclude_item("GFileInfo")
diff --git a/crates/npc-engine/src/lib.rs b/crates/npc-engine/src/lib.rs
index 6602e78..e489fa4 100644
--- a/crates/npc-engine/src/lib.rs
+++ b/crates/npc-engine/src/lib.rs
@@ -20,6 +20,8 @@
extern crate glib;
#[macro_use]
extern crate try_opt;
+extern crate gdk_pixbuf;
+extern crate gdk_pixbuf_sys;
#[macro_use]
extern crate npc_fwk;
diff --git a/crates/npc-engine/src/library/mod.rs b/crates/npc-engine/src/library/mod.rs
index ead2f6c..f65967b 100644
--- a/crates/npc-engine/src/library/mod.rs
+++ b/crates/npc-engine/src/library/mod.rs
@@ -2,3 +2,4 @@ pub mod commands;
pub mod notification;
pub mod op;
pub mod queriedcontent;
+pub mod thumbnail_cache;
diff --git a/crates/npc-engine/src/library/notification.rs b/crates/npc-engine/src/library/notification.rs
index 72531e6..4da84b0 100644
--- a/crates/npc-engine/src/library/notification.rs
+++ b/crates/npc-engine/src/library/notification.rs
@@ -17,10 +17,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+use gdk_pixbuf;
+use gdk_pixbuf_sys;
+use glib::translate::*;
+
use super::queriedcontent::QueriedContent;
use crate::db::libfile::FileStatus;
use crate::db::{Keyword, Label, LibFolder, LibMetadata, LibraryId};
use npc_fwk::base::PropertyIndex;
+use npc_fwk::toolkit::thumbnail;
use npc_fwk::toolkit::PortableChannel;
use npc_fwk::PropertyValue;
@@ -50,6 +55,7 @@ pub enum NotificationType {
XMP_NEEDS_UPDATE,
FILE_MOVED,
FILE_STATUS_CHANGED,
+ ThumbnailLoaded,
}
#[repr(C)]
@@ -87,6 +93,15 @@ impl MetadataChange {
}
}
+#[repr(C)]
+#[derive(Clone)]
+pub struct Thumbnail {
+ pub id: LibraryId,
+ pub width: i32,
+ pub height: i32,
+ pub pix: thumbnail::Thumbnail,
+}
+
#[no_mangle]
pub unsafe extern "C" fn metadatachange_get_id(meta: *const MetadataChange) -> LibraryId {
(*meta).id
@@ -126,6 +141,7 @@ pub enum LibNotification {
MetadataChanged(MetadataChange),
MetadataQueried(LibMetadata),
XmpNeedsUpdate,
+ ThumbnailLoaded(Thumbnail),
}
/// Send a notification for the file status change.
@@ -183,6 +199,7 @@ pub unsafe extern "C" fn engine_library_notification_type(
Some(&LibNotification::MetadataChanged(_)) => NotificationType::METADATA_CHANGED,
Some(&LibNotification::MetadataQueried(_)) => NotificationType::METADATA_QUERIED,
Some(&LibNotification::XmpNeedsUpdate) => NotificationType::XMP_NEEDS_UPDATE,
+ Some(&LibNotification::ThumbnailLoaded(_)) => NotificationType::ThumbnailLoaded,
None => unreachable!(),
}
}
@@ -196,6 +213,7 @@ pub unsafe extern "C" fn engine_library_notification_get_id(
Some(&LibNotification::FolderDeleted(id)) => id,
Some(&LibNotification::LabelDeleted(id)) => id,
Some(&LibNotification::FileStatusChanged(ref changed)) => changed.id,
+ Some(&LibNotification::ThumbnailLoaded(ref thumbnail)) => thumbnail.id,
_ => unreachable!(),
}
}
@@ -295,3 +313,16 @@ pub unsafe extern "C" fn engine_library_notification_get_content(
_ => unreachable!(),
}
}
+
+#[no_mangle]
+pub unsafe extern "C" fn engine_library_notification_get_pixbuf(
+ n: *const LibNotification,
+) -> *mut gdk_pixbuf_sys::GdkPixbuf {
+ match n.as_ref() {
+ Some(&LibNotification::ThumbnailLoaded(ref thumbnail)) => {
+ let pixbuf: gdk_pixbuf::Pixbuf = thumbnail.pix.clone().into();
+ pixbuf.to_glib_full()
+ }
+ _ => unreachable!(),
+ }
+}
diff --git a/crates/npc-engine/src/library/queriedcontent.rs b/crates/npc-engine/src/library/queriedcontent.rs
index 09ddfed..6a84430 100644
--- a/crates/npc-engine/src/library/queriedcontent.rs
+++ b/crates/npc-engine/src/library/queriedcontent.rs
@@ -38,6 +38,10 @@ impl QueriedContent {
pub fn push(&mut self, f: LibFile) {
self.content.push(f);
}
+
+ pub fn get_content(&self) -> &Vec<LibFile> {
+ &self.content
+ }
}
#[no_mangle]
diff --git a/crates/npc-engine/src/library/thumbnail_cache.rs
b/crates/npc-engine/src/library/thumbnail_cache.rs
new file mode 100644
index 0000000..0b5067b
--- /dev/null
+++ b/crates/npc-engine/src/library/thumbnail_cache.rs
@@ -0,0 +1,238 @@
+/*
+ * niepce - library/thumbnail_cache.rs
+ *
+ * Copyright (C) 2020 Hubert Figuière
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+use libc::c_char;
+use std::cmp;
+use std::collections::VecDeque;
+use std::ffi::CStr;
+use std::fs;
+use std::path::{Path, PathBuf};
+use std::sync;
+use std::sync::atomic;
+use std::thread;
+
+use gdk_pixbuf;
+use glib;
+
+use crate::db::libfile::{FileStatus, LibFile};
+use crate::db::LibraryId;
+use crate::library::notification;
+use crate::library::notification::LibNotification::{FileStatusChanged, ThumbnailLoaded};
+use crate::library::notification::{FileStatusChange, LcChannel, LibNotification};
+use crate::library::queriedcontent::QueriedContent;
+use npc_fwk::toolkit::thumbnail::Thumbnail;
+
+/// Thumbnail task
+struct ThumbnailTask {
+ /// Requested width.
+ width: i32,
+ /// Requested height.
+ height: i32,
+ /// File to generate thumbnail for.
+ file: LibFile,
+}
+
+impl ThumbnailTask {
+ /// Create a new ThumbnailTask
+ pub fn new(file: LibFile, width: i32, height: i32) -> Self {
+ ThumbnailTask {
+ file,
+ width,
+ height,
+ }
+ }
+}
+
+fn get_thumbnail(f: &LibFile, w: i32, h: i32, cached: &Path) -> Thumbnail {
+ let filename = f.path();
+ if ThumbnailCache::is_thumbnail_cached(filename, cached) {
+ dbg_out!("thumbnail for {:?} is cached!", filename);
+ return Thumbnail::from(gdk_pixbuf::Pixbuf::new_from_file(cached).ok());
+ }
+
+ dbg_out!("creating thumbnail for {:?}", filename);
+ if let Some(cached_dir) = cached.parent() {
+ if let Err(err) = fs::create_dir_all(cached_dir) {
+ err_out!("Coudln't create directories for {:?}: {}", cached, err);
+ }
+ }
+
+ let thumbnail = Thumbnail::thumbnail_file(filename, w, h, f.orientation());
+ if thumbnail.ok() {
+ thumbnail.save(cached, "png");
+ } else {
+ dbg_out!("couldn't get the thumbnail for {:?}", filename);
+ }
+ return thumbnail;
+}
+
+type Tasks = sync::Arc<(sync::Mutex<VecDeque<ThumbnailTask>>, sync::Condvar)>;
+type Running = sync::Arc<atomic::AtomicBool>;
+
+pub struct ThumbnailCache {
+ cache_dir: PathBuf,
+ tasks: Tasks,
+ running: Running,
+ sender: glib::Sender<LibNotification>,
+}
+
+impl ThumbnailCache {
+ fn new(dir: &Path, sender: glib::Sender<LibNotification>) -> Self {
+ Self {
+ cache_dir: PathBuf::from(dir),
+ tasks: sync::Arc::new((sync::Mutex::new(VecDeque::new()), sync::Condvar::new())),
+ running: sync::Arc::new(atomic::AtomicBool::new(false)),
+ sender,
+ }
+ }
+
+ fn execute(task: ThumbnailTask, cache_dir: &Path, sender: glib::Sender<LibNotification>) {
+ let w = task.width;
+ let h = task.height;
+ let libfile = task.file;
+
+ let path = libfile.path();
+ let id = libfile.id();
+ let dest = Self::path_for_thumbnail(path, id, cmp::max(w, h), cache_dir);
+
+ let pix = get_thumbnail(&libfile, w, h, &dest);
+ if !path.is_file() {
+ dbg_out!("file doesn't exist");
+ if let Err(err) = sender.send(FileStatusChanged(FileStatusChange {
+ id,
+ status: FileStatus::Missing,
+ })) {
+ err_out!("Sending file status change notification failed: {}", err);
+ }
+ }
+
+ if !pix.ok() {
+ return;
+ }
+ // notify the thumbnail
+ if let Err(err) = sender.send(ThumbnailLoaded(notification::Thumbnail {
+ id,
+ width: pix.get_width(),
+ height: pix.get_height(),
+ pix,
+ })) {
+ err_out!("Sending thumbnail notification failed: {}", err);
+ }
+ }
+
+ fn main(
+ running: &Running,
+ tasks: &Tasks,
+ cache_dir: PathBuf,
+ sender: glib::Sender<LibNotification>,
+ ) {
+ while running.load(atomic::Ordering::Relaxed) {
+ let elem: Option<ThumbnailTask>;
+ {
+ let mut queue = tasks.0.lock().unwrap();
+ if !queue.is_empty() {
+ elem = queue.pop_front();
+ } else {
+ elem = None;
+ }
+ }
+
+ if let Some(task) = elem {
+ Self::execute(task, &cache_dir, sender.clone());
+ }
+
+ let queue = tasks.0.lock().unwrap();
+ if queue.is_empty() {
+ running.store(false, atomic::Ordering::Relaxed);
+ }
+ }
+ }
+
+ fn schedule(&self, task: ThumbnailTask) {
+ if let Ok(ref mut q) = self.tasks.0.lock() {
+ q.push_back(task);
+ if !self.running.load(atomic::Ordering::Relaxed) {
+ self.running.store(true, atomic::Ordering::Relaxed);
+ let running = self.running.clone();
+ let tasks = self.tasks.clone();
+ let cache_dir = self.cache_dir.clone();
+ let sender = self.sender.clone();
+ thread::spawn(move || {
+ Self::main(&running, &tasks, cache_dir, sender);
+ });
+ }
+ }
+ }
+
+ pub fn request(&self, fl: &Vec<LibFile>) {
+ for f in fl {
+ self.schedule(ThumbnailTask::new(f.clone(), 160, 160));
+ }
+ }
+
+ pub fn is_thumbnail_cached(_file: &Path, thumb: &Path) -> bool {
+ thumb.is_file()
+ }
+
+ pub fn path_for_thumbnail(
+ filename: &Path,
+ id: LibraryId,
+ size: i32,
+ cache_dir: &Path,
+ ) -> PathBuf {
+ let base_name = filename.file_name().and_then(|f| f.to_str()).unwrap(); // XXX fatal if fails.
+ let thumb_name = format!("{}-{}.png", id, base_name);
+ let mut path = PathBuf::from(Self::dir_for_thumbnail(size, cache_dir));
+ path.push(thumb_name);
+ path
+ }
+
+ pub fn dir_for_thumbnail(size: i32, cache_dir: &Path) -> PathBuf {
+ let subdir = if size == 0 {
+ "full".to_string()
+ } else {
+ size.to_string()
+ };
+ let mut dir = PathBuf::from(cache_dir);
+ dir.push(subdir);
+ dir
+ }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn engine_library_thumbnail_cache_new(
+ dir: *const c_char,
+ channel: *const LcChannel,
+) -> *mut ThumbnailCache {
+ let path = PathBuf::from(&*CStr::from_ptr(dir).to_string_lossy());
+ Box::into_raw(Box::new(ThumbnailCache::new(&path, (*channel).0.clone())))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn engine_library_thumbnail_cache_delete(obj: *mut ThumbnailCache) {
+ Box::from_raw(obj);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn engine_library_thumbnail_cache_request(
+ self_: &mut ThumbnailCache,
+ content: &QueriedContent,
+) {
+ self_.request(content.get_content())
+}
diff --git a/crates/npc-fwk/Cargo.toml b/crates/npc-fwk/Cargo.toml
index 33df4f6..c64c25e 100644
--- a/crates/npc-fwk/Cargo.toml
+++ b/crates/npc-fwk/Cargo.toml
@@ -17,7 +17,8 @@ glib-sys = "*"
glib = { version = "^0.9.0" }
gtk-sys = "*"
gdk = "^0.12.0"
-gdk-pixbuf = "0.8.0"
+gdk-pixbuf-sys = "*"
+gdk-pixbuf = { version = "0.8.0", features = [ "v2_32" ] }
gtk = { version = "^0.8.0", git = "https://github.com/hfiguiere/gtk.git", branch = "0.8.0-p1" }
libc = "0.2.39"
multimap = "0.4.0"
diff --git a/crates/npc-fwk/build.rs b/crates/npc-fwk/build.rs
index 1850b30..2f11988 100644
--- a/crates/npc-fwk/build.rs
+++ b/crates/npc-fwk/build.rs
@@ -16,6 +16,7 @@ fn main() {
.with_language(cbindgen::Language::Cxx)
.with_parse_deps(true)
.with_parse_exclude(&["exempi", "chrono", "multimap"])
+ .exclude_item("GdkPixbuf")
.exclude_item("GtkDrawingArea")
.exclude_item("GtkWidget")
.exclude_item("GtkWindow")
diff --git a/crates/npc-fwk/src/lib.rs b/crates/npc-fwk/src/lib.rs
index 1c2899d..8ddd2af 100644
--- a/crates/npc-fwk/src/lib.rs
+++ b/crates/npc-fwk/src/lib.rs
@@ -21,6 +21,7 @@ extern crate chrono;
extern crate exempi;
extern crate gdk;
extern crate gdk_pixbuf;
+extern crate gdk_pixbuf_sys;
extern crate gio;
extern crate gio_sys;
#[macro_use]
diff --git a/crates/npc-fwk/src/toolkit/gdk_utils.rs b/crates/npc-fwk/src/toolkit/gdk_utils.rs
index 2ff9da6..6f1bbd4 100644
--- a/crates/npc-fwk/src/toolkit/gdk_utils.rs
+++ b/crates/npc-fwk/src/toolkit/gdk_utils.rs
@@ -17,10 +17,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+use libc::c_char;
use std::cmp;
+use std::path::Path;
+use std::slice;
use gdk_pixbuf;
+use gdk_pixbuf::prelude::*;
+use glib::translate::*;
+/// Scale the pixbuf to fit in a square of %dim pixels
pub fn gdkpixbuf_scale_to_fit(
pix: Option<&gdk_pixbuf::Pixbuf>,
dim: i32,
@@ -41,3 +47,139 @@ pub fn gdkpixbuf_scale_to_fit(
None
}
}
+
+/// Rotate the pixbuf according to the Exif orientation value
+pub fn gdkpixbuf_exif_rotate(
+ pix: Option<&gdk_pixbuf::Pixbuf>,
+ orientation: i32,
+) -> Option<gdk_pixbuf::Pixbuf> {
+ match orientation {
+ 0 | 1 => pix.map(|p| p.clone()),
+ 2 => pix.and_then(|p| p.flip(true)),
+ 3 => pix.and_then(|p| p.rotate_simple(gdk_pixbuf::PixbufRotation::Upsidedown)),
+ 4 => pix
+ .and_then(|p| p.rotate_simple(gdk_pixbuf::PixbufRotation::Upsidedown))
+ .and_then(|p| p.flip(true)),
+ 5 => pix
+ .and_then(|p| p.rotate_simple(gdk_pixbuf::PixbufRotation::Clockwise))
+ .and_then(|p| p.flip(false)),
+ 6 => pix.and_then(|p| p.rotate_simple(gdk_pixbuf::PixbufRotation::Clockwise)),
+ 7 => pix
+ .and_then(|p| p.rotate_simple(gdk_pixbuf::PixbufRotation::Counterclockwise))
+ .and_then(|p| p.flip(false)),
+ 8 => pix.and_then(|p| p.rotate_simple(gdk_pixbuf::PixbufRotation::Counterclockwise)),
+ _ => None,
+ }
+}
+
+// XXX bindgen
+#[repr(i32)]
+#[allow(dead_code)]
+enum ORDataType {
+ None = 0,
+ Pixmap8RGB,
+ Pixmap16RGB,
+ JPEG,
+ TIFF,
+ PNG,
+ RAW,
+ CompressedRAW,
+ Unknown,
+}
+
+#[repr(C)]
+struct ORThumbnail {
+ a: i32,
+}
+#[repr(C)]
+struct ORRawFile {
+ a: i32,
+}
+
+// XXX bindgen these too
+extern "C" {
+ fn or_rawfile_new(path: *const c_char, type_: i32) -> *mut ORRawFile;
+ fn or_rawfile_get_orientation(rawfile: *const ORRawFile) -> i32;
+ fn or_rawfile_get_thumbnail(
+ rawfile: *const ORRawFile,
+ size: u32,
+ thumbnail: *mut ORThumbnail,
+ ) -> i32;
+ fn or_rawfile_release(rawfile: *mut ORRawFile) -> i32;
+ fn or_thumbnail_new() -> *mut ORThumbnail;
+ fn or_thumbnail_release(thumbnail: *mut ORThumbnail) -> i32;
+ fn or_thumbnail_format(thumbnail: *const ORThumbnail) -> ORDataType;
+ fn or_thumbnail_data(thumbnail: *const ORThumbnail) -> *const u8;
+ fn or_thumbnail_data_size(thumbnail: *const ORThumbnail) -> usize;
+ fn or_thumbnail_dimensions(thumbnail: *const ORThumbnail, x: *mut u32, y: *mut u32);
+}
+
+fn thumbnail_to_pixbuf(
+ thumbnail: *const ORThumbnail,
+ orientation: i32,
+) -> Option<gdk_pixbuf::Pixbuf> {
+ let format = unsafe { or_thumbnail_format(thumbnail) };
+ let buf_size = unsafe { or_thumbnail_data_size(thumbnail) };
+ let buf = unsafe { slice::from_raw_parts(or_thumbnail_data(thumbnail), buf_size) };
+
+ let pixbuf = match format {
+ ORDataType::Pixmap8RGB => {
+ let mut x: u32 = 0;
+ let mut y: u32 = 0;
+ unsafe { or_thumbnail_dimensions(thumbnail, &mut x, &mut y) };
+
+ let bytes = glib::Bytes::from(buf);
+ Some(gdk_pixbuf::Pixbuf::new_from_bytes(
+ &bytes,
+ gdk_pixbuf::Colorspace::Rgb,
+ false,
+ 8,
+ x as i32,
+ y as i32,
+ x as i32 * 3,
+ ))
+ }
+ ORDataType::JPEG | ORDataType::TIFF | ORDataType::PNG => {
+ let loader = gdk_pixbuf::PixbufLoader::new();
+
+ if let Err(err) = loader.write(buf) {
+ err_out!("loader write error: {}", err);
+ }
+
+ if let Err(err) = loader.close() {
+ err_out!("loader close error: {}", err);
+ }
+ loader.get_pixbuf()
+ }
+ _ => None,
+ };
+
+ gdkpixbuf_exif_rotate(pixbuf.as_ref(), orientation)
+}
+
+/// Extract the thumbnail from libopenraw
+pub fn openraw_extract_rotated_thumbnail<P: AsRef<Path>>(
+ path: P,
+ dim: u32,
+) -> Option<gdk_pixbuf::Pixbuf> {
+ let mut pixbuf = None;
+ let rf = unsafe { or_rawfile_new(path.as_ref().to_glib_none().0, 0) };
+ if !rf.is_null() {
+ let orientation = unsafe { or_rawfile_get_orientation(rf) };
+
+ let thumbnail = unsafe { or_thumbnail_new() };
+ let err = unsafe { or_rawfile_get_thumbnail(rf, dim, thumbnail) };
+ if err == 0 {
+ pixbuf = thumbnail_to_pixbuf(thumbnail, orientation);
+ } else {
+ err_out!("or_get_extract_thumbnail() failed with {}.", err);
+ }
+ let err = unsafe { or_thumbnail_release(thumbnail) };
+ if err != 0 {
+ err_out!("or_thumbnail_release() failed with {}", err);
+ }
+ unsafe { or_rawfile_release(rf) };
+ }
+
+ pixbuf
+}
diff --git a/crates/npc-fwk/src/toolkit/mimetype.rs b/crates/npc-fwk/src/toolkit/mimetype.rs
index 4d47033..c03b187 100644
--- a/crates/npc-fwk/src/toolkit/mimetype.rs
+++ b/crates/npc-fwk/src/toolkit/mimetype.rs
@@ -20,8 +20,8 @@
use gio;
use gio::prelude::*;
-use std::path::Path;
use std::convert::AsRef;
+use std::path::Path;
#[derive(PartialEq, Copy, Clone, Debug)]
pub enum IsRaw {
@@ -56,8 +56,7 @@ pub fn guess_type(gmtype: &str) -> MType {
}
/// Guess the type from a file
-fn guess_type_for_file<P: AsRef<Path>>(p: P) -> MType
-{
+fn guess_type_for_file<P: AsRef<Path>>(p: P) -> MType {
let path = p.as_ref();
let file = gio::File::new_for_path(path);
let cancellable: Option<&gio::Cancellable> = None;
@@ -129,7 +128,7 @@ mod tests {
assert_eq!(
guess_type_for_file("/foo/bar/img_0001.cr2"),
MType::Image(IsRaw::Yes)
- );
+ );
assert!(mimetype.is_image());
assert!(mimetype.is_digicam_raw());
}
diff --git a/crates/npc-fwk/src/toolkit/mod.rs b/crates/npc-fwk/src/toolkit/mod.rs
index fa78c5d..f3d6331 100644
--- a/crates/npc-fwk/src/toolkit/mod.rs
+++ b/crates/npc-fwk/src/toolkit/mod.rs
@@ -20,6 +20,8 @@
pub mod clickable_cell_renderer;
pub mod gdk_utils;
pub mod mimetype;
+pub mod movieutils;
+pub mod thumbnail;
pub mod widgets;
pub type Sender<T> = glib::Sender<T>;
diff --git a/src/engine/library/thumbnailnotification.hpp b/crates/npc-fwk/src/toolkit/movieutils.rs
similarity index 53%
rename from src/engine/library/thumbnailnotification.hpp
rename to crates/npc-fwk/src/toolkit/movieutils.rs
index 0877a9a..42a0e8d 100644
--- a/src/engine/library/thumbnailnotification.hpp
+++ b/crates/npc-fwk/src/toolkit/movieutils.rs
@@ -1,7 +1,7 @@
/*
- * niepce - engine/library/thumbnailnotification.hpp
+ * niepce - npc-fwk/toolkit/movieutils.rs
*
- * Copyright (C) 2007-2017 Hubert Figuiere
+ * Copyright (C) 2020 Hubert Figuière
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,21 +17,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+use std::cmp;
+use std::path::Path;
+use std::process::Command;
-#pragma once
-
-#include "fwk/toolkit/thumbnail.hpp"
-
-#include "rust_bindings.hpp"
-
-namespace eng {
-
-struct ThumbnailNotification
+pub fn thumbnail_movie<S, D>(source: S, w: i32, h: i32, dest: D) -> bool
+where
+ S: AsRef<Path> + std::fmt::Debug,
+ D: AsRef<Path>,
{
- eng::library_id_t id;
- int width;
- int height;
- fwk::Thumbnail pixmap;
-};
-
+ let status = Command::new("totem-video-thumbnailer")
+ .arg("-s")
+ .arg(format!("{}", cmp::max(w, h)))
+ .arg(source.as_ref().as_os_str())
+ .arg(dest.as_ref().as_os_str())
+ .status()
+ .expect(&format!("Failed to thumbnail {:?}", source));
+ status.success()
}
diff --git a/crates/npc-fwk/src/toolkit/thumbnail.rs b/crates/npc-fwk/src/toolkit/thumbnail.rs
new file mode 100644
index 0000000..9b2a6af
--- /dev/null
+++ b/crates/npc-fwk/src/toolkit/thumbnail.rs
@@ -0,0 +1,227 @@
+/*
+ * niepce - toolkit/thumbnail.rs
+ *
+ * Copyright (C) 2020 Hubert Figuière
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+use libc::c_char;
+use std::cmp;
+use std::convert::From;
+use std::ffi::CStr;
+use std::fs;
+use std::path::{Path, PathBuf};
+
+use gdk_pixbuf;
+use gdk_pixbuf::Colorspace;
+use glib;
+use glib::translate::*;
+
+use super::gdk_utils;
+use super::mimetype::MimeType;
+use super::movieutils;
+
+#[derive(Clone)]
+pub struct Thumbnail {
+ bytes: Vec<u8>,
+ width: i32,
+ height: i32,
+ stride: i32,
+ bits_per_sample: i32,
+ has_alpha: bool,
+ colorspace: Colorspace,
+}
+
+impl Default for Thumbnail {
+ fn default() -> Self {
+ Self {
+ bytes: vec![],
+ width: 0,
+ height: 0,
+ stride: 0,
+ bits_per_sample: 0,
+ has_alpha: false,
+ colorspace: Colorspace::Rgb,
+ }
+ }
+}
+
+impl Thumbnail {
+ /// Return true if there is a pixbuf
+ pub fn ok(&self) -> bool {
+ self.bytes.len() > 0
+ }
+
+ /// Get the width of the pixbuf. 0 if None
+ pub fn get_width(&self) -> i32 {
+ self.width
+ }
+
+ /// Get the height of the pixbuf. 0 if None
+ pub fn get_height(&self) -> i32 {
+ self.height
+ }
+
+ /// Make a gdk_pixbuf::Pixbuf out of the Thumbnail
+ fn make_pixbuf(&self) -> Option<gdk_pixbuf::Pixbuf> {
+ if self.ok() {
+ // XXX figure out the allocation here.
+ // Ideally we should have this shared
+ // Also this is duplicated with Into()
+ Some(gdk_pixbuf::Pixbuf::new_from_bytes(
+ &glib::Bytes::from(&self.bytes),
+ self.colorspace,
+ self.has_alpha,
+ self.bits_per_sample,
+ self.width,
+ self.height,
+ self.stride,
+ ))
+ } else {
+ None
+ }
+ }
+
+ pub fn save<P: AsRef<Path> + std::fmt::Debug>(&self, path: P, format: &str) {
+ if let Some(pixbuf) = &self.make_pixbuf() {
+ if let Err(err) = pixbuf.savev(&path, format, &[]) {
+ err_out!("Failed to save pixbuf {:?}: {}", &path, err);
+ }
+ }
+ }
+
+ pub fn thumbnail_file<P: AsRef<Path>>(path: P, w: i32, h: i32, orientation: i32) -> Self {
+ let filename = path.as_ref();
+ let mime_type = MimeType::new(filename);
+ dbg_out!("MIME type {:?}", mime_type);
+
+ let mut pix: Option<gdk_pixbuf::Pixbuf> = None;
+
+ if mime_type.is_unknown() {
+ dbg_out!("unknown file type {:?}", filename);
+ } else if mime_type.is_movie() {
+ // XXX FIXME
+ dbg_out!("video thumbnail");
+ if let Some(mut cached) = glib::get_tmp_dir() {
+ cached.push("temp-1234");
+ if movieutils::thumbnail_movie(filename, w, h, &cached) {
+ pix = gdk_pixbuf::Pixbuf::new_from_file_at_size(&cached, w, h).ok();
+ if let Err(err) = fs::remove_file(&cached) {
+ err_out!("Remove temporary file {:?} failed: {}", &cached, err);
+ }
+ }
+ }
+ if pix.is_none() {
+ err_out!("exception thumbnailing video ");
+ }
+ } else if !mime_type.is_image() {
+ dbg_out!("not an image type");
+ } else if !mime_type.is_digicam_raw() {
+ dbg_out!("not a raw type, trying GdkPixbuf loaders");
+ match gdk_pixbuf::Pixbuf::new_from_file_at_size(filename, w, h) {
+ Ok(ref pixbuf) => {
+ pix = gdk_utils::gdkpixbuf_exif_rotate(Some(pixbuf), orientation);
+ }
+ Err(err) => err_out!("exception thumbnailing image: {}", err),
+ }
+ } else {
+ dbg_out!("trying raw loader");
+ pix = gdk_utils::openraw_extract_rotated_thumbnail(filename, cmp::min(w, h) as u32);
+ if let Some(ref pixbuf) = pix {
+ if (w < pixbuf.get_width()) || (h < pixbuf.get_height()) {
+ pix = gdk_utils::gdkpixbuf_scale_to_fit(Some(pixbuf), cmp::min(w, h));
+ }
+ } else {
+ err_out!("raw loader failed");
+ }
+ }
+
+ Thumbnail::from(pix)
+ }
+}
+
+impl From<Option<gdk_pixbuf::Pixbuf>> for Thumbnail {
+ fn from(pixbuf: Option<gdk_pixbuf::Pixbuf>) -> Self {
+ if let Some(pixbuf) = pixbuf {
+ if let Some(bytes) = pixbuf.read_pixel_bytes() {
+ let width = pixbuf.get_width();
+ let height = pixbuf.get_height();
+ let stride = pixbuf.get_rowstride();
+ let bits_per_sample = pixbuf.get_bits_per_sample();
+ let colorspace = pixbuf.get_colorspace();
+ let has_alpha = pixbuf.get_has_alpha();
+ return Self {
+ width,
+ height,
+ stride,
+ bits_per_sample,
+ colorspace,
+ has_alpha,
+ bytes: Vec::from(bytes.as_ref()),
+ };
+ }
+ }
+ Self::default()
+ }
+}
+
+impl Into<gdk_pixbuf::Pixbuf> for Thumbnail {
+ fn into(self) -> gdk_pixbuf::Pixbuf {
+ gdk_pixbuf::Pixbuf::new_from_bytes(
+ &glib::Bytes::from(&self.bytes),
+ self.colorspace,
+ self.has_alpha,
+ self.bits_per_sample,
+ self.width,
+ self.height,
+ self.stride,
+ )
+ }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn fwk_toolkit_thumbnail_file(
+ filename: *const c_char,
+ w: i32,
+ h: i32,
+ orientation: i32,
+) -> *mut Thumbnail {
+ Box::into_raw(Box::new(Thumbnail::thumbnail_file(
+ &PathBuf::from(&*CStr::from_ptr(filename).to_string_lossy()),
+ w,
+ h,
+ orientation,
+ )))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn fwk_toolkit_thumbnail_delete(obj: *mut Thumbnail) {
+ Box::from_raw(obj);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn fwk_toolkit_thumbnail_from_pixbuf(
+ pixbuf: *mut gdk_pixbuf_sys::GdkPixbuf,
+) -> *mut Thumbnail {
+ let pixbuf: Option<gdk_pixbuf::Pixbuf> = from_glib_none(pixbuf);
+ Box::into_raw(Box::new(Thumbnail::from(pixbuf)))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn fwk_toolkit_thumbnail_to_pixbuf(
+ self_: &Thumbnail,
+) -> *mut gdk_pixbuf_sys::GdkPixbuf {
+ self_.make_pixbuf().to_glib_full()
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 04e156a..8a99b80 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,6 +24,7 @@ RUST_SOURCES = \
@top_srcdir@/crates/npc-engine/src/library/notification.rs \
@top_srcdir@/crates/npc-engine/src/library/queriedcontent.rs \
@top_srcdir@/crates/npc-engine/src/library/op.rs \
+ @top_srcdir@/crates/npc-engine/src/library/thumbnail_cache.rs \
@top_srcdir@/crates/npc-engine/src/lib.rs \
@top_srcdir@/crates/npc-fwk/Cargo.toml \
@top_srcdir@/crates/npc-fwk/build.rs \
@@ -39,6 +40,7 @@ RUST_SOURCES = \
@top_srcdir@/crates/npc-fwk/src/toolkit/gdk_utils.rs \
@top_srcdir@/crates/npc-fwk/src/toolkit/mimetype.rs \
@top_srcdir@/crates/npc-fwk/src/toolkit/mod.rs \
+ @top_srcdir@/crates/npc-fwk/src/toolkit/thumbnail.rs \
@top_srcdir@/crates/npc-fwk/src/toolkit/widgets/mod.rs \
@top_srcdir@/crates/npc-fwk/src/toolkit/widgets/rating_label.rs \
@top_srcdir@/crates/npc-fwk/src/utils/exempi.rs \
diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am
index fbbd293..98a3c00 100644
--- a/src/engine/Makefile.am
+++ b/src/engine/Makefile.am
@@ -28,7 +28,6 @@ libniepceengine_a_SOURCES = \
db/properties.hpp db/properties.cpp \
db/properties-def.hpp \
library/clienttypes.hpp \
- library/thumbnailcache.hpp library/thumbnailcache.cpp \
library/thumbnailnotification.hpp \
importer/iimporter.hpp \
importer/directoryimporter.hpp \
diff --git a/src/engine/importer/cameraimporter.cpp b/src/engine/importer/cameraimporter.cpp
index 2dfefe4..e17e855 100644
--- a/src/engine/importer/cameraimporter.cpp
+++ b/src/engine/importer/cameraimporter.cpp
@@ -2,7 +2,7 @@
/*
* niepce - engine/importer/cameraimporter.cpp
*
- * Copyright (C) 2017 Hubert Figuière
+ * Copyright (C) 2017-2020 Hubert Figuière
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -94,7 +94,7 @@ bool CameraImporter::get_previews_for(const std::string& source,
if (ensure_camera_open(source)) {
for (auto path: paths) {
DBG_OUT("want thumbnail %s", path.c_str());
- fwk::Thumbnail thumbnail = m_camera->get_preview(path);
+ fwk::ThumbnailPtr thumbnail = m_camera->get_preview(path);
callback(path, thumbnail);
}
diff --git a/src/engine/importer/directoryimporter.cpp b/src/engine/importer/directoryimporter.cpp
index 2a031ba..cf0e628 100644
--- a/src/engine/importer/directoryimporter.cpp
+++ b/src/engine/importer/directoryimporter.cpp
@@ -84,7 +84,8 @@ bool DirectoryImporter::get_previews_for(const std::string& /*source*/,
{
for (auto path : paths) {
DBG_OUT("path %s", path.c_str());
- auto thumbnail = fwk::Thumbnail::thumbnail_file(path, 160, 160, 0);
+ auto thumbnail =
+ fwk::thumbnail_wrap(ffi::fwk_toolkit_thumbnail_file(path.c_str(), 160, 160, 0));
callback(path, thumbnail);
}
return true;
diff --git a/src/engine/importer/iimporter.hpp b/src/engine/importer/iimporter.hpp
index 5db673f..e2236d1 100644
--- a/src/engine/importer/iimporter.hpp
+++ b/src/engine/importer/iimporter.hpp
@@ -1,7 +1,7 @@
/*
* niepce - engine/importer/iimporter.hpp
*
- * Copyright (C) 2014-2017 Hubert Figuière
+ * Copyright (C) 2014-2020 Hubert Figuière
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,8 +28,6 @@
#include "fwk/utils/files.hpp"
#include "engine/importer/importedfile.hpp"
-#include "rust_bindings.hpp"
-
namespace eng {
/**
@@ -49,7 +47,7 @@ public:
const SourceContentReady& callback) = 0;
typedef std::function<void (const std::string& path,
- const fwk::Thumbnail&)> PreviewReady;
+ const fwk::ThumbnailPtr&)> PreviewReady;
virtual bool get_previews_for(const std::string& source,
const std::list<std::string>& paths,
const PreviewReady& callback) = 0;
diff --git a/src/fwk/toolkit/Makefile.am b/src/fwk/toolkit/Makefile.am
index b7b135f..9a07269 100644
--- a/src/fwk/toolkit/Makefile.am
+++ b/src/fwk/toolkit/Makefile.am
@@ -41,7 +41,6 @@ libniepceframework_a_SOURCES = configuration.hpp configuration.cpp \
mapcontroller.hpp mapcontroller.cpp \
notification.hpp \
mimetype.hpp mimetype.cpp \
- movieutils.hpp movieutils.cpp \
imageloader.hpp imageloader.cpp \
notificationcenter.hpp notificationcenter.cpp \
configdatabinder.hpp configdatabinder.cpp \
diff --git a/src/fwk/toolkit/gphoto.cpp b/src/fwk/toolkit/gphoto.cpp
index 67ff051..c2b7eea 100644
--- a/src/fwk/toolkit/gphoto.cpp
+++ b/src/fwk/toolkit/gphoto.cpp
@@ -39,7 +39,6 @@
#include "fwk/utils/files.hpp"
#include "fwk/utils/pathutils.hpp"
#include "fwk/toolkit/gdkutils.hpp"
-#include "fwk/toolkit/thumbnail.hpp"
#include "gphoto.hpp"
@@ -360,9 +359,9 @@ std::list<std::pair<std::string, std::string>> GpCamera::list_content() const
return files;
}
-fwk::Thumbnail GpCamera::get_preview(const std::string& path) const
+fwk::ThumbnailPtr GpCamera::get_preview(const std::string& path) const
{
- fwk::Thumbnail thumbnail;
+ fwk::ThumbnailPtr thumbnail;
std::string folder = fwk::path_dirname(path);
std::string name = fwk::path_basename(path);
@@ -407,7 +406,7 @@ fwk::Thumbnail GpCamera::get_preview(const std::string& path) const
unlink(exif_path.c_str());
}
#endif
- thumbnail = fwk::Thumbnail(pix);
+ thumbnail = fwk::thumbnail_wrap(ffi::fwk_toolkit_thumbnail_from_pixbuf(pix->gobj()));
}
return thumbnail;
diff --git a/src/fwk/toolkit/gphoto.hpp b/src/fwk/toolkit/gphoto.hpp
index 615cae0..b10a7b5 100644
--- a/src/fwk/toolkit/gphoto.hpp
+++ b/src/fwk/toolkit/gphoto.hpp
@@ -31,11 +31,10 @@
#include "fwk/base/option.hpp"
#include "fwk/base/singleton.hpp"
#include "fwk/base/util.hpp"
+#include "fwk/toolkit/thumbnail.hpp"
namespace fwk {
-class Thumbnail;
-
namespace gp {
typedef std::unique_ptr<CameraFile, decltype(&gp_file_unref)> CameraFilePtr;
@@ -111,7 +110,7 @@ public:
bool close();
bool try_unmount_camera();
std::list<std::pair<std::string, std::string>> list_content() const;
- fwk::Thumbnail get_preview(const std::string& path) const;
+ fwk::ThumbnailPtr get_preview(const std::string& path) const;
bool download_file(const std::string& folder, const std::string& file,
const std::string& dest);
private:
diff --git a/src/fwk/toolkit/notificationcenter.cpp b/src/fwk/toolkit/notificationcenter.cpp
index e495c3e..329175c 100644
--- a/src/fwk/toolkit/notificationcenter.cpp
+++ b/src/fwk/toolkit/notificationcenter.cpp
@@ -31,47 +31,23 @@ namespace fwk {
class NotificationCenter::Priv
{
public:
- uint64_t m_id;
Glib::Dispatcher m_dispatcher;
fwk::MtQueue< Notification::Ptr > m_notificationQueue;
std::map< int, subscription_t > m_subscribers;
};
-typedef fwk::Singleton<std::map<uint64_t, std::weak_ptr<NotificationCenter>>> NotificationCenterRegistry;
-
-std::weak_ptr<NotificationCenter> NotificationCenter::get_nc(uint64_t notif_id)
-{
- auto iter = NotificationCenterRegistry::obj().find(notif_id);
- if (iter == NotificationCenterRegistry::obj().end()) {
- return NotificationCenter::Ptr();
- }
- return iter->second;
-}
-
-NotificationCenter::NotificationCenter(uint64_t notif_id)
+NotificationCenter::NotificationCenter()
: p( new Priv )
{
- p->m_id = notif_id;
p->m_dispatcher.connect(
sigc::mem_fun(this, &NotificationCenter::_dispatch));
}
NotificationCenter::~NotificationCenter()
{
- NotificationCenterRegistry::obj().erase(p->m_id);
delete p;
}
-void NotificationCenter::attach()
-{
- NotificationCenterRegistry::obj()[p->m_id] = shared_from_this();
-}
-
-uint64_t NotificationCenter::id() const
-{
- return p->m_id;
-}
-
void NotificationCenter::subscribe(int type, const subscriber_t & s)
{
// TODO make sure it is not yet subscribed
diff --git a/src/fwk/toolkit/notificationcenter.hpp b/src/fwk/toolkit/notificationcenter.hpp
index f75fd2f..bf259aa 100644
--- a/src/fwk/toolkit/notificationcenter.hpp
+++ b/src/fwk/toolkit/notificationcenter.hpp
@@ -39,19 +39,14 @@ public:
~NotificationCenter();
- uint64_t id() const;
-
// called from out of thread
void post(Notification::Ptr && n);
void subscribe(int type, const subscriber_t & );
void unsubscribe(int type, const subscriber_t & );
- static std::weak_ptr<NotificationCenter> get_nc(uint64_t notif_id);
-
protected:
- NotificationCenter(uint64_t notif_id);
- void attach();
+ NotificationCenter();
private:
typedef sigc::signal<void, Notification::Ptr> subscription_t;
diff --git a/src/fwk/toolkit/thumbnail.cpp b/src/fwk/toolkit/thumbnail.cpp
index 8ff1f0d..0a7f63f 100644
--- a/src/fwk/toolkit/thumbnail.cpp
+++ b/src/fwk/toolkit/thumbnail.cpp
@@ -2,7 +2,7 @@
/*
* niepce - fwk/toolkit/thumbnail.cpp
*
- * Copyright (C) 2017-2019 Hubert Figuière
+ * Copyright (C) 2017-2020 Hubert Figuière
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,224 +20,11 @@
#include "thumbnail.hpp"
-#include <glibmm/miscutils.h>
-#include <libopenraw/libopenraw.h>
-
-#include "fwk/base/debug.hpp"
-#include "fwk/toolkit/mimetype.hpp"
-#include "fwk/toolkit/gdkutils.hpp"
-#include "fwk/toolkit/movieutils.hpp"
-
namespace fwk {
-namespace {
-
-static void pixbuf_free(guchar* data, gpointer u)
-{
- (void)u;
- free(data);
-}
-
-/**
- * Returns a retained GdkPixbuf
- */
-static GdkPixbuf* rotate_pixbuf(GdkPixbuf* tmp, int32_t orientation)
-{
- GdkPixbuf* pixbuf = nullptr;
- switch (orientation) {
- case 0:
- case 1:
- pixbuf = (GdkPixbuf*)g_object_ref(tmp);
- break;
- case 2:
- pixbuf = gdk_pixbuf_flip(tmp, TRUE);
- break;
- case 3:
- pixbuf = gdk_pixbuf_rotate_simple(tmp, GDK_PIXBUF_ROTATE_UPSIDEDOWN);
- break;
- case 4: {
- GdkPixbuf* rotated =
- gdk_pixbuf_rotate_simple(tmp, GDK_PIXBUF_ROTATE_UPSIDEDOWN);
- pixbuf = gdk_pixbuf_flip(rotated, TRUE);
- g_object_unref(rotated);
- break;
- }
- case 5: {
- GdkPixbuf* rotated =
- gdk_pixbuf_rotate_simple(tmp, GDK_PIXBUF_ROTATE_CLOCKWISE);
- pixbuf = gdk_pixbuf_flip(rotated, FALSE);
- g_object_unref(rotated);
- break;
- }
- case 6:
- pixbuf = gdk_pixbuf_rotate_simple(tmp, GDK_PIXBUF_ROTATE_CLOCKWISE);
- break;
- case 7: {
- GdkPixbuf* rotated =
- gdk_pixbuf_rotate_simple(tmp, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
- pixbuf = gdk_pixbuf_flip(rotated, FALSE);
- g_object_unref(rotated);
- break;
- }
- case 8:
- pixbuf =
- gdk_pixbuf_rotate_simple(tmp, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
- break;
- default:
- break;
- }
- return pixbuf;
-}
-
-static GdkPixbuf* thumbnail_to_pixbuf(ORThumbnailRef thumbnail,
- int32_t orientation)
-{
- GdkPixbuf* tmp = nullptr;
- GdkPixbuf* pixbuf = nullptr;
-
- const guchar* buf;
- or_data_type format = or_thumbnail_format(thumbnail);
- buf = (const guchar*)or_thumbnail_data(thumbnail);
-
- switch (format) {
- case OR_DATA_TYPE_PIXMAP_8RGB: {
- uint32_t x, y;
- size_t buf_size;
- guchar* data;
-
- buf_size = or_thumbnail_data_size(thumbnail);
- data = (guchar*)malloc(buf_size);
- memcpy(data, buf, buf_size);
- or_thumbnail_dimensions(thumbnail, &x, &y);
-
- tmp = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, FALSE, 8, x, y,
- x * 3, pixbuf_free, nullptr);
- break;
- }
- case OR_DATA_TYPE_JPEG:
- case OR_DATA_TYPE_TIFF:
- case OR_DATA_TYPE_PNG: {
- GdkPixbufLoader* loader = nullptr;
- size_t count = or_thumbnail_data_size(thumbnail);
- loader = gdk_pixbuf_loader_new();
- if (loader != nullptr) {
- GError* error = nullptr;
- if (!gdk_pixbuf_loader_write(loader, buf, count, &error) && error) {
- ERR_OUT("loader write error: %s", error->message);
- g_error_free(error);
- error = nullptr;
- }
- if (!gdk_pixbuf_loader_close(loader, &error) && error) {
- ERR_OUT("loader close error: %s", error->message);
- g_error_free(error);
- }
- tmp = gdk_pixbuf_loader_get_pixbuf(loader);
- g_object_ref(tmp);
- g_object_unref(loader);
- }
- break;
- }
- default:
- break;
- }
- pixbuf = rotate_pixbuf(tmp, orientation);
- g_object_unref(tmp);
- return pixbuf;
-}
-
-static GdkPixbuf* gdkpixbuf_extract_rotated_thumbnail(const char* path,
- uint32_t preferred_size)
+ThumbnailPtr thumbnail_wrap(ffi::Thumbnail* t)
{
- ORRawFileRef rf;
- int32_t orientation = 0;
- GdkPixbuf* pixbuf = nullptr;
- or_error err = OR_ERROR_NONE;
- ORThumbnailRef thumbnail = nullptr;
- gboolean rotate = TRUE;
-
- rf = or_rawfile_new(path, OR_RAWFILE_TYPE_UNKNOWN);
- if (rf) {
- if (rotate) {
- orientation = or_rawfile_get_orientation(rf);
- }
- thumbnail = or_thumbnail_new();
- err = or_rawfile_get_thumbnail(rf, preferred_size, thumbnail);
- if (err == OR_ERROR_NONE) {
- pixbuf = thumbnail_to_pixbuf(thumbnail, orientation);
- } else {
- ERR_OUT("or_get_extract_thumbnail() failed with %d.", err);
- }
- err = or_thumbnail_release(thumbnail);
- if (err != OR_ERROR_NONE) {
- ERR_OUT("or_thumbnail_release() failed with %d", err);
- }
- or_rawfile_release(rf);
- }
-
- return pixbuf;
-}
-
-}
-
-Thumbnail::Thumbnail(const Glib::RefPtr<Gdk::Pixbuf>& pixbuf)
- : m_pixbuf(pixbuf)
-{
-}
-
-void Thumbnail::save(const std::string& path, const std::string& format)
-{
- if (m_pixbuf) {
- m_pixbuf->save(path, format);
- }
-}
-
-Thumbnail Thumbnail::thumbnail_file(const std::string& filename,
- int w, int h, int32_t orientation)
-{
- fwk::MimeType mime_type(filename);
- DBG_OUT("MIME type %s", mime_type.string().c_str());
-
- Glib::RefPtr<Gdk::Pixbuf> pix;
-
- if(mime_type.isUnknown()) {
- DBG_OUT("unknown file type %s", filename.c_str());
- } else if(mime_type.isMovie()) {
- try {
- // XXX FIXME
- std::string cached = Glib::get_tmp_dir() + "/temp-1234";
- if(fwk::thumbnail_movie(filename, w, h, cached)) {
- pix = Gdk::Pixbuf::create_from_file(cached, w, h, true);
- unlink(cached.c_str());
- }
- }
- catch(const Glib::Error & e) {
- ERR_OUT("exception thumbnailing video %s", e.what().c_str());
- }
- } else if(!mime_type.isImage()) {
- DBG_OUT("not an image type");
- } else if(!mime_type.isDigicamRaw()) {
- DBG_OUT("not a raw type, trying GdkPixbuf loaders");
- try {
- pix = Gdk::Pixbuf::create_from_file(filename, w, h, true);
- if(pix) {
- pix = fwk::gdkpixbuf_exif_rotate(pix, orientation);
- }
- }
- catch(const Glib::Error & e) {
- ERR_OUT("exception thumbnailing image %s", e.what().c_str());
- }
- } else {
- GdkPixbuf *pixbuf = gdkpixbuf_extract_rotated_thumbnail(filename.c_str(),
- std::min(w, h));
- if(pixbuf) {
- pix = Glib::wrap(pixbuf, true); // take ownership
- if((w < pix->get_width()) || (h < pix->get_height())) {
- pix = fwk::gdkpixbuf_scale_to_fit(pix, std::min(w,h));
- }
- }
- }
-
- return Thumbnail(pix);
+ return ThumbnailPtr(t, &ffi::fwk_toolkit_thumbnail_delete);
}
}
diff --git a/src/fwk/toolkit/thumbnail.hpp b/src/fwk/toolkit/thumbnail.hpp
index dc6c384..bb576f6 100644
--- a/src/fwk/toolkit/thumbnail.hpp
+++ b/src/fwk/toolkit/thumbnail.hpp
@@ -20,39 +20,13 @@
#pragma once
-#include <stdint.h>
-
-#include <string>
-
-#include <gdkmm/pixbuf.h>
+#include <memory>
+#include "rust_bindings.hpp"
namespace fwk {
-class Thumbnail {
-public:
- Thumbnail() = default;
- Thumbnail(const Glib::RefPtr<Gdk::Pixbuf>& pixbuf);
-
- bool ok() const {
- return !!m_pixbuf;
- }
-
- int get_width() const {
- return m_pixbuf->get_width();
- }
- int get_height() const {
- return m_pixbuf->get_height();
- }
- const Glib::RefPtr<Gdk::Pixbuf>& pixbuf() const {
- return m_pixbuf;
- }
-
- void save(const std::string& path, const std::string& format);
-
- static Thumbnail thumbnail_file(const std::string& path, int w, int h, int32_t orientation);
+typedef std::shared_ptr<ffi::Thumbnail> ThumbnailPtr;
-private:
- Glib::RefPtr<Gdk::Pixbuf> m_pixbuf;
-};
+ThumbnailPtr thumbnail_wrap(ffi::Thumbnail *);
}
diff --git a/src/libraryclient/libraryclient.cpp b/src/libraryclient/libraryclient.cpp
index 0f8b9d9..67018c2 100644
--- a/src/libraryclient/libraryclient.cpp
+++ b/src/libraryclient/libraryclient.cpp
@@ -1,7 +1,7 @@
/*
* niepce - libraryclient/libraryclient.cpp
*
- * Copyright (C) 2007-2019 Hubert Figuière
+ * Copyright (C) 2007-2020 Hubert Figuière
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,17 +32,20 @@ namespace libraryclient {
const char * s_thumbcacheDirname = "thumbcache";
LibraryClient::LibraryClient(const fwk::Moniker & moniker,
- const std::shared_ptr<ffi::LcChannel>& channel, uint64_t notif_id)
+ const std::shared_ptr<ffi::LcChannel>& channel)
: m_client(
ffi::libraryclient_new(moniker.path().c_str(), channel.get()),
ffi::libraryclient_delete)
- , m_thumbnailCache(moniker.path() + "/" + s_thumbcacheDirname, notif_id)
+ , m_thumbnailCache(ffi::engine_library_thumbnail_cache_new(
+ std::string(moniker.path() + "/" + s_thumbcacheDirname).c_str(),
+ channel.get()))
, m_uidataprovider(new UIDataProvider())
{
}
LibraryClient::~LibraryClient()
{
+ ffi::engine_library_thumbnail_cache_delete(m_thumbnailCache);
}
}
diff --git a/src/libraryclient/libraryclient.hpp b/src/libraryclient/libraryclient.hpp
index 6a6b2df..a169530 100644
--- a/src/libraryclient/libraryclient.hpp
+++ b/src/libraryclient/libraryclient.hpp
@@ -22,7 +22,6 @@
#include <string>
#include <memory>
-#include "engine/library/thumbnailcache.hpp"
#include "uidataprovider.hpp"
#include "rust_bindings.hpp"
@@ -39,11 +38,10 @@ public:
LibraryClient() = delete;
LibraryClient& operator=(const LibraryClient&) = delete;
- LibraryClient(const fwk::Moniker & moniker, const std::shared_ptr<ffi::LcChannel>& channel,
- uint64_t notif_id);
+ LibraryClient(const fwk::Moniker & moniker, const std::shared_ptr<ffi::LcChannel>& channel);
virtual ~LibraryClient();
- eng::ThumbnailCache & thumbnailCache()
+ ffi::ThumbnailCache* thumbnailCache()
{ return m_thumbnailCache; }
const UIDataProviderPtr& getDataProvider() const
@@ -55,7 +53,7 @@ public:
private:
std::shared_ptr<ffi::LibraryClientWrapper> m_client;
- eng::ThumbnailCache m_thumbnailCache;
+ ffi::ThumbnailCache* m_thumbnailCache;
UIDataProviderPtr m_uidataprovider;
};
diff --git a/src/niepce/Makefile.am b/src/niepce/Makefile.am
index 90a476a..8cda28a 100644
--- a/src/niepce/Makefile.am
+++ b/src/niepce/Makefile.am
@@ -48,7 +48,6 @@ BUILT_SOURCES = \
niepce_SOURCES = \
notificationcenter.hpp notificationcenter.cpp \
- notifications.hpp \
npc-resources.c \
npc-resources.h \
main.cpp
diff --git a/src/niepce/notificationcenter.cpp b/src/niepce/notificationcenter.cpp
index c1fcee4..c1b375d 100644
--- a/src/niepce/notificationcenter.cpp
+++ b/src/niepce/notificationcenter.cpp
@@ -20,7 +20,6 @@
#include <boost/any.hpp>
#include "fwk/base/debug.hpp"
-#include "niepce/notifications.hpp"
#include "niepce/notificationcenter.hpp"
namespace niepce {
@@ -36,12 +35,9 @@ int32_t NotificationCenter::channel_callback(const eng::LibNotification *notific
return 1;
}
-NotificationCenter::NotificationCenter(uint64_t notif_id)
- : fwk::NotificationCenter(notif_id)
- , m_channel(ffi::lcchannel_new(&channel_callback, this), ffi::lcchannel_delete)
+NotificationCenter::NotificationCenter()
+ : m_channel(ffi::lcchannel_new(&channel_callback, this), ffi::lcchannel_delete)
{
- subscribe(NOTIFICATION_THUMBNAIL,
- sigc::mem_fun(*this, &NotificationCenter::dispatch_notification));
}
NotificationCenter::~NotificationCenter()
@@ -54,38 +50,6 @@ void NotificationCenter::dispatch_lib_notification(const eng::LibNotification *n
signal_lib_notification(*n);
}
-void NotificationCenter::dispatch_notification(const fwk::Notification::Ptr &n) const
-{
- try {
- switch(n->type()) {
- case NOTIFICATION_THUMBNAIL:
- {
- eng::ThumbnailNotification tn
- = boost::any_cast<eng::ThumbnailNotification>(n->data());
- signal_thumbnail_notification(tn);
- break;
- }
- default:
- ERR_OUT("Unhandled notification type %d", n->type());
- break;
- }
- }
- catch(const boost::bad_any_cast & e)
- {
- ERR_OUT("improper notification data: %s", e.what());
- }
- catch(const std::exception & e)
- {
- ERR_OUT("other exception notification type %d of %s: %s", n->type(),
- n->data().type().name(),
- e.what());
- }
- catch(...)
- {
- ERR_OUT("unknown exception");
- }
-}
-
}
/*
Local Variables:
diff --git a/src/niepce/notificationcenter.hpp b/src/niepce/notificationcenter.hpp
index 69ffa19..f96f807 100644
--- a/src/niepce/notificationcenter.hpp
+++ b/src/niepce/notificationcenter.hpp
@@ -23,7 +23,8 @@
#include <sigc++/signal.h>
#include "fwk/toolkit/notificationcenter.hpp"
-#include "engine/library/thumbnailnotification.hpp"
+
+#include "rust_bindings.hpp"
namespace niepce {
@@ -34,20 +35,18 @@ public:
~NotificationCenter();
typedef std::shared_ptr<NotificationCenter> Ptr;
- static Ptr make(uint64_t notif_id)
+ static Ptr make()
{
- Ptr nc = Ptr(new NotificationCenter(notif_id));
- nc->attach();
+ Ptr nc = Ptr(new NotificationCenter());
return nc;
}
sigc::signal<void, const eng::LibNotification &> signal_lib_notification;
- sigc::signal<void, const eng::ThumbnailNotification &> signal_thumbnail_notification;
const std::shared_ptr<ffi::LcChannel>& get_channel() const
{ return m_channel; };
protected:
- NotificationCenter(uint64_t notif_id);
+ NotificationCenter();
private:
static int32_t channel_callback(const eng::LibNotification *notification, void *data);
diff --git a/src/niepce/ui/dialogs/importdialog.cpp b/src/niepce/ui/dialogs/importdialog.cpp
index 7480a50..354ce30 100644
--- a/src/niepce/ui/dialogs/importdialog.cpp
+++ b/src/niepce/ui/dialogs/importdialog.cpp
@@ -210,7 +210,7 @@ void ImportDialog::append_files_to_import()
[this, importer, source, paths] () {
return importer->get_previews_for(
source, paths,
- [this] (const std::string& path, const fwk::Thumbnail& thumbnail) {
+ [this] (const std::string& path, const fwk::ThumbnailPtr& thumbnail) {
this->m_previews_to_import.send_data(
std::make_pair(path, thumbnail));
});
@@ -224,7 +224,9 @@ void ImportDialog::preview_received()
auto preview = result.unwrap();
auto iter = m_images_list_map.find(preview.first);
if (iter != m_images_list_map.end()) {
- iter->second->set_value(m_grid_columns.pixbuf, preview.second.pixbuf());
+ iter->second->set_value(m_grid_columns.pixbuf,
+ Glib::wrap(ffi::fwk_toolkit_thumbnail_to_pixbuf(
+ preview.second.get())));
}
}
}
diff --git a/src/niepce/ui/dialogs/importdialog.hpp b/src/niepce/ui/dialogs/importdialog.hpp
index c66bd79..d4cc2b7 100644
--- a/src/niepce/ui/dialogs/importdialog.hpp
+++ b/src/niepce/ui/dialogs/importdialog.hpp
@@ -46,7 +46,6 @@ class Stack;
namespace fwk {
class ImageGridView;
-class Thumbnail;
}
namespace eng {
@@ -120,7 +119,7 @@ private:
MetaDataPaneController::Ptr m_metadata_pane;
fwk::UIResultSingle<std::list<eng::ImportedFilePtr>> m_files_to_import;
- fwk::UIResults<std::pair<std::string, fwk::Thumbnail>> m_previews_to_import;
+ fwk::UIResults<std::pair<std::string, fwk::ThumbnailPtr>> m_previews_to_import;
};
}
diff --git a/src/niepce/ui/filmstripcontroller.cpp b/src/niepce/ui/filmstripcontroller.cpp
index 1d63895..555fff1 100644
--- a/src/niepce/ui/filmstripcontroller.cpp
+++ b/src/niepce/ui/filmstripcontroller.cpp
@@ -20,8 +20,6 @@
#include <gtkmm/iconview.h>
-#include "niepce/notifications.hpp"
-#include "engine/library/thumbnailnotification.hpp"
#include "fwk/base/debug.hpp"
#include "filmstripcontroller.hpp"
diff --git a/src/niepce/ui/imageliststore.cpp b/src/niepce/ui/imageliststore.cpp
index 800b7cc..678a8f6 100644
--- a/src/niepce/ui/imageliststore.cpp
+++ b/src/niepce/ui/imageliststore.cpp
@@ -26,7 +26,6 @@
#include "fwk/base/debug.hpp"
#include "fwk/toolkit/application.hpp"
#include "fwk/toolkit/gdkutils.hpp"
-#include "niepce/notifications.hpp"
#include "niepcewindow.hpp"
#include "rust_bindings.hpp"
@@ -136,7 +135,7 @@ void ImageListStore::on_lib_notification(const eng::LibNotification &ln)
case eng::NotificationType::FOLDER_CONTENT_QUERIED:
case eng::NotificationType::KEYWORD_CONTENT_QUERIED:
{
- auto content = engine_library_notification_get_content(&ln);
+ auto content = ffi::engine_library_notification_get_content(&ln);
if (type == eng::NotificationType::FOLDER_CONTENT_QUERIED) {
m_current_folder = ffi::engine_queried_content_id(content);
m_current_keyword = 0;
@@ -153,7 +152,7 @@ void ImageListStore::on_lib_notification(const eng::LibNotification &ln)
l->push_back(f);
}
// at that point clear the cache because the icon view is populated.
- getLibraryClient()->thumbnailCache().request(*l);
+ ffi::engine_library_thumbnail_cache_request(getLibraryClient()->thumbnailCache(), content);
break;
}
case eng::NotificationType::FILE_MOVED:
@@ -218,27 +217,28 @@ void ImageListStore::on_lib_notification(const eng::LibNotification &ln)
ffi::libraryclient_process_xmp_update_queue(getLibraryClient()->client(), write_xmp);
break;
}
+ case eng::NotificationType::ThumbnailLoaded:
+ {
+ auto id = engine_library_notification_get_id(&ln);
+ auto iter = m_idmap.find(id);
+ if(iter != m_idmap.end()) {
+ // found the icon view item
+ auto pixbuf = engine_library_notification_get_pixbuf(&ln);
+ // About the ownership:
+ // The Glib::wrap below will claim it.
+ ffi::npc_image_list_store_set_tnail(
+ m_store, iter->second.gobj(), pixbuf,
+ fwk::gdkpixbuf_scale_to_fit(Glib::wrap(pixbuf), 100)->gobj());
+ }
+ else {
+ DBG_OUT("row %Ld not found", (long long)id);
+ }
+ }
default:
break;
}
}
-void ImageListStore::on_tnail_notification(const eng::ThumbnailNotification &tn)
-{
- std::map<eng::library_id_t, Gtk::TreeIter>::iterator iter
- = m_idmap.find( tn.id );
- if(iter != m_idmap.end()) {
- // found the icon view item
- auto pixbuf = tn.pixmap.pixbuf();
- ffi::npc_image_list_store_set_tnail(
- m_store, iter->second.gobj(), pixbuf->gobj(),
- fwk::gdkpixbuf_scale_to_fit(pixbuf, 100)->gobj());
- }
- else {
- DBG_OUT("row %Ld not found", (long long)tn.id);
- }
-}
-
libraryclient::LibraryClientPtr ImageListStore::getLibraryClient()
{
ModuleShell::Ptr shell = std::dynamic_pointer_cast<ModuleShell>(m_controller.lock());
diff --git a/src/niepce/ui/imageliststore.hpp b/src/niepce/ui/imageliststore.hpp
index 0276f1f..1c51b87 100644
--- a/src/niepce/ui/imageliststore.hpp
+++ b/src/niepce/ui/imageliststore.hpp
@@ -1,7 +1,7 @@
/*
* niepce - ui/imageliststore.h
*
- * Copyright (C) 2008-2020 Hubert Figuiere
+ * Copyright (C) 2008-2020 Hubert Figuière
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +25,6 @@
#include "fwk/base/propertybag.hpp"
#include "fwk/toolkit/controller.hpp"
#include "engine/db/libfile.hpp"
-#include "engine/library/thumbnailnotification.hpp"
#include "libraryclient/libraryclient.hpp"
namespace ui {
@@ -74,7 +73,6 @@ public:
// Should be called when the content will change
void clear_content();
void on_lib_notification(const eng::LibNotification &n);
- void on_tnail_notification(const eng::ThumbnailNotification &n);
private:
/// Add the LibFile to the model
diff --git a/src/niepce/ui/moduleshell.cpp b/src/niepce/ui/moduleshell.cpp
index a91e6b0..bc4604f 100644
--- a/src/niepce/ui/moduleshell.cpp
+++ b/src/niepce/ui/moduleshell.cpp
@@ -25,7 +25,6 @@
#include <gtkmm/cellrenderer.h>
#include "fwk/base/debug.hpp"
-#include "niepce/notifications.hpp"
#include "engine/db/libfile.hpp"
#include "fwk/toolkit/application.hpp"
#include "fwk/toolkit/gtkutils.hpp"
diff --git a/src/niepce/ui/niepcewindow.cpp b/src/niepce/ui/niepcewindow.cpp
index 7de3b77..e9ab2b9 100644
--- a/src/niepce/ui/niepcewindow.cpp
+++ b/src/niepce/ui/niepcewindow.cpp
@@ -28,7 +28,6 @@
#include <gtkmm/separator.h>
#include <gtkmm/filechooserdialog.h>
-#include "niepce/notifications.hpp"
#include "niepce/notificationcenter.hpp"
#include "fwk/base/debug.hpp"
#include "fwk/base/moniker.hpp"
@@ -126,11 +125,6 @@ NiepceWindow::_createModuleShell()
.connect(sigc::mem_fun(
*m_moduleshell->get_map_module(),
&mapm::MapModule::on_lib_notification));
- m_notifcenter->signal_thumbnail_notification
- .connect(sigc::mem_fun(
- m_moduleshell->get_list_store().get(),
- &ImageListStore::on_tnail_notification));
-
// workspace treeview
auto workspace_actions = Gio::SimpleActionGroup::create();
@@ -190,7 +184,7 @@ NiepceWindow::buildWidget()
init_actions();
- m_notifcenter = niepce::NotificationCenter::make(reinterpret_cast<uint64_t>(this));
+ m_notifcenter = niepce::NotificationCenter::make();
Glib::ustring name("org.gnome.Niepce");
set_icon_from_theme(name);
@@ -376,7 +370,7 @@ bool NiepceWindow::open_library(const std::string & libMoniker)
fwk::Moniker mon = fwk::Moniker(libMoniker);
m_libClient
= LibraryClientPtr(new LibraryClient(
- mon, m_notifcenter->get_channel(), m_notifcenter->id()));
+ mon, m_notifcenter->get_channel()));
// XXX ensure the library is open.
set_title(libMoniker);
m_library_cfg
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]