[niepce] npc-fwk: bind Thumbnail with cxx



commit ecfa330bc2d7631da37dc57620dc26b88302bfdb
Author: Hubert Figuière <hub figuiere net>
Date:   Sat Oct 15 12:47:40 2022 -0400

    npc-fwk: bind Thumbnail with cxx

 crates/npc-fwk/src/lib.rs                 | 39 +++++++++++++++++++++
 crates/npc-fwk/src/toolkit/thumbnail.rs   | 56 ++-----------------------------
 src/engine/importer/cameraimporter.cpp    |  8 +++--
 src/engine/importer/directoryimporter.cpp |  7 ++--
 src/engine/importer/iimporter.hpp         |  7 ++--
 src/fwk/toolkit/Makefile.am               |  1 -
 src/fwk/toolkit/gphoto.cpp                |  7 ++--
 src/fwk/toolkit/gphoto.hpp                |  6 ++--
 src/fwk/toolkit/thumbnail.cpp             | 30 -----------------
 src/fwk/toolkit/thumbnail.hpp             | 32 ------------------
 src/fwk/toolkit/uiresult.hpp              | 20 +++++++----
 src/niepce/ui/dialogs/importdialog.cpp    | 17 +++++-----
 src/niepce/ui/dialogs/importdialog.hpp    |  1 -
 src/rust_bindings.hpp                     |  2 ++
 14 files changed, 82 insertions(+), 151 deletions(-)
---
diff --git a/crates/npc-fwk/src/lib.rs b/crates/npc-fwk/src/lib.rs
index 006c5bda..69dc9db1 100644
--- a/crates/npc-fwk/src/lib.rs
+++ b/crates/npc-fwk/src/lib.rs
@@ -44,7 +44,15 @@ pub fn init() {
     rexiv2::initialize().expect("Unable to initialize rexiv2");
 }
 
+// C++ bridge
+
+use std::ffi::c_char;
+
+use gdk_pixbuf_sys::GdkPixbuf;
+use glib::translate::*;
+
 use crate::base::date::Date;
+use crate::toolkit::thumbnail::Thumbnail;
 use crate::toolkit::Configuration;
 
 fn make_config_path(file: &str) -> String {
@@ -71,6 +79,26 @@ pub fn fraction_to_decimal_(value: &str) -> f64 {
     fraction_to_decimal(value).unwrap_or(f64::NAN)
 }
 
+pub fn thumbnail_for_file(path: &str, w: i32, h: i32, orientation: i32) -> Box<Thumbnail> {
+    Box::new(Thumbnail::thumbnail_file(path, w, h, orientation))
+}
+
+/// Create a %Thumbnail from a %GdkPixbuf
+///
+/// The resulting object must be freed by %fwk_toolkit_thumbnail_delete
+///
+/// # Safety
+/// Dereference the pointer
+unsafe fn thumbnail_from_pixbuf(pixbuf: *mut c_char) -> Box<Thumbnail> {
+    let pixbuf: Option<gdk_pixbuf::Pixbuf> = from_glib_none(pixbuf as *mut GdkPixbuf);
+    Box::new(Thumbnail::from(pixbuf))
+}
+
+fn thumbnail_to_pixbuf(self_: &Thumbnail) -> *mut c_char {
+    let pixbuf: *mut GdkPixbuf = self_.make_pixbuf().to_glib_full();
+    pixbuf as *mut c_char
+}
+
 #[cxx::bridge(namespace = "fwk")]
 mod ffi {
     struct SharedConfiguration {
@@ -113,4 +141,15 @@ mod ffi {
     }
 
     impl Box<Date> {}
+
+    extern "Rust" {
+        type Thumbnail;
+
+        #[cxx_name = "Thumbnail_for_file"]
+        fn thumbnail_for_file(path: &str, w: i32, h: i32, orientation: i32) -> Box<Thumbnail>;
+        #[cxx_name = "Thumbnail_from_pixbuf"]
+        unsafe fn thumbnail_from_pixbuf(pixbuf: *mut c_char) -> Box<Thumbnail>;
+        #[cxx_name = "Thumbnail_to_pixbuf"]
+        fn thumbnail_to_pixbuf(self_: &Thumbnail) -> *mut c_char;
+    }
 }
diff --git a/crates/npc-fwk/src/toolkit/thumbnail.rs b/crates/npc-fwk/src/toolkit/thumbnail.rs
index fdc082e2..ce262ae9 100644
--- a/crates/npc-fwk/src/toolkit/thumbnail.rs
+++ b/crates/npc-fwk/src/toolkit/thumbnail.rs
@@ -1,7 +1,7 @@
 /*
  * niepce - toolkit/thumbnail.rs
  *
- * Copyright (C) 2020 Hubert Figuière
+ * Copyright (C) 2020-2022 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,15 +17,12 @@
  * 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 std::path::Path;
 
 use gdk_pixbuf::Colorspace;
-use glib::translate::*;
 
 use super::gdk_utils;
 use super::mimetype::MimeType;
@@ -176,52 +173,3 @@ impl From<&Thumbnail> for gdk_pixbuf::Pixbuf {
         )
     }
 }
-
-/// Generate the %Thumbnail for the file
-///
-/// # Safety
-/// Dereference filename pointer (C string)
-#[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,
-    )))
-}
-
-/// Delete the %Thumbnail object
-///
-/// # Safety
-/// Dereference the pointer
-#[no_mangle]
-pub unsafe extern "C" fn fwk_toolkit_thumbnail_delete(obj: *mut Thumbnail) {
-    drop(Box::from_raw(obj));
-}
-
-/// Create a %Thumbnail from a %GdkPixbuf
-///
-/// The resulting object must be freed by %fwk_toolkit_thumbnail_delete
-///
-/// # Safety
-/// Dereference the pointer
-#[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 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/engine/importer/cameraimporter.cpp b/src/engine/importer/cameraimporter.cpp
index 402e098a..4a6d3b98 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-2020 Hubert Figuière
+ * Copyright (C) 2017-2022 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,8 +94,10 @@ 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::ThumbnailPtr thumbnail = m_camera->get_preview(path);
-            callback(path, thumbnail);
+            auto thumbnail = m_camera->get_preview(path);
+            if (thumbnail.has_value()) {
+                callback(std::move(path), std::move(thumbnail.value()));
+            }
         }
 
         return true;
diff --git a/src/engine/importer/directoryimporter.cpp b/src/engine/importer/directoryimporter.cpp
index 2a35dddd..2e37caa5 100644
--- a/src/engine/importer/directoryimporter.cpp
+++ b/src/engine/importer/directoryimporter.cpp
@@ -2,7 +2,7 @@
 /*
  * niepce - engine/importer/directoryimporter.cpp
  *
- * Copyright (C) 2014-2020 Hubert Figuière
+ * Copyright (C) 2014-2022 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
@@ -91,9 +91,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_wrap(ffi::fwk_toolkit_thumbnail_file(path.c_str(), 160, 160, 0));
-        callback(path, thumbnail);
+        auto thumbnail = fwk::Thumbnail_for_file(path, 160, 160, 0);
+        callback(std::move(path), std::move(thumbnail));
     }
     return true;
 }
diff --git a/src/engine/importer/iimporter.hpp b/src/engine/importer/iimporter.hpp
index e2236d12..267a493d 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-2020 Hubert Figuière
+ * Copyright (C) 2014-2022 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
@@ -24,7 +24,6 @@
 #include <list>
 #include <functional>
 
-#include "fwk/toolkit/thumbnail.hpp"
 #include "fwk/utils/files.hpp"
 #include "engine/importer/importedfile.hpp"
 
@@ -46,8 +45,8 @@ public:
     virtual bool list_source_content(const std::string& source,
                                      const SourceContentReady& callback) = 0;
 
-    typedef std::function<void (const std::string& path,
-                                const fwk::ThumbnailPtr&)> PreviewReady;
+    typedef std::function<void (std::string&& path,
+                                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 d070f783..0a4e7993 100644
--- a/src/fwk/toolkit/Makefile.am
+++ b/src/fwk/toolkit/Makefile.am
@@ -42,7 +42,6 @@ libniepceframework_a_SOURCES = \
        controller.hpp controller.cpp \
        uicontroller.hpp uicontroller.cpp \
        uiresult.hpp uiresult.cpp \
-       thumbnail.hpp thumbnail.cpp \
        mapcontroller.hpp mapcontroller.cpp \
        notification.hpp \
        mimetype.hpp mimetype.cpp \
diff --git a/src/fwk/toolkit/gphoto.cpp b/src/fwk/toolkit/gphoto.cpp
index 68a6c421..50a7edae 100644
--- a/src/fwk/toolkit/gphoto.cpp
+++ b/src/fwk/toolkit/gphoto.cpp
@@ -359,9 +359,8 @@ std::list<std::pair<std::string, std::string>> GpCamera::list_content() const
     return files;
 }
 
-fwk::ThumbnailPtr GpCamera::get_preview(const std::string& path) const
+std::optional<fwk::ThumbnailPtr> GpCamera::get_preview(const std::string& path) const
 {
-    fwk::ThumbnailPtr thumbnail;
     std::string folder = fwk::path_dirname(path);
     std::string name = fwk::path_basename(path);
 
@@ -406,10 +405,10 @@ fwk::ThumbnailPtr GpCamera::get_preview(const std::string& path) const
             unlink(exif_path.c_str());
         }
 #endif
-        thumbnail = fwk::thumbnail_wrap(ffi::fwk_toolkit_thumbnail_from_pixbuf(pix->gobj()));
+        return std::optional<fwk::ThumbnailPtr>(fwk::Thumbnail_from_pixbuf((char*)pix->gobj()));
     }
 
-    return thumbnail;
+    return std::nullopt;
 }
 
 bool GpCamera::download_file(const std::string& folder, const std::string& file,
diff --git a/src/fwk/toolkit/gphoto.hpp b/src/fwk/toolkit/gphoto.hpp
index b10a7b5b..9616ba3f 100644
--- a/src/fwk/toolkit/gphoto.hpp
+++ b/src/fwk/toolkit/gphoto.hpp
@@ -2,7 +2,7 @@
 /*
  * niepce - fwk/toolkit/gphoto.hpp
  *
- * Copyright (C) 2009-2017 Hubert Figuiere
+ * Copyright (C) 2009-2022 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
@@ -23,6 +23,7 @@
 #include <list>
 #include <string>
 #include <memory>
+#include <optional>
 
 #include <gphoto2-camera.h>
 #include <gphoto2-port-info-list.h>
@@ -31,7 +32,6 @@
 #include "fwk/base/option.hpp"
 #include "fwk/base/singleton.hpp"
 #include "fwk/base/util.hpp"
-#include "fwk/toolkit/thumbnail.hpp"
 
 namespace fwk {
 
@@ -110,7 +110,7 @@ public:
     bool close();
     bool try_unmount_camera();
     std::list<std::pair<std::string, std::string>> list_content() const;
-    fwk::ThumbnailPtr get_preview(const std::string& path) const;
+    std::optional<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/uiresult.hpp b/src/fwk/toolkit/uiresult.hpp
index 4c60e30c..46121758 100644
--- a/src/fwk/toolkit/uiresult.hpp
+++ b/src/fwk/toolkit/uiresult.hpp
@@ -22,11 +22,10 @@
 
 #include <deque>
 #include <mutex>
+#include <memory>
 
 #include <glibmm/dispatcher.h>
 
-#include "fwk/base/option.hpp"
-
 namespace fwk {
 
 /** @brief Fetch a "result" asynchronously */
@@ -76,28 +75,35 @@ class UIResults
     : public UIResult
 {
 public:
+    typedef T value_type;
+
     void clear() override {
         m_data.clear();
     }
 
-    void send_data(T&& d) {
+    void send_data(std::shared_ptr<T>&& d) {
         {
             std::lock_guard<std::mutex> lock(m_data_mutex);
             m_data.push_back(std::move(d));
         }
         m_notifier.emit();
     }
-    Option<T> recv_data() {
+
+    std::shared_ptr<T> recv_data() {
         std::lock_guard<std::mutex> lock(m_data_mutex);
         if (m_data.empty()) {
-            return Option<T>();
+            return std::shared_ptr<T>();
         }
-        auto result = Option<T>(m_data.front());
+        auto result = m_data.front();
         m_data.pop_front();
         return result;
     }
 private:
-    std::deque<T> m_data;
+    // the value_type has to be a shared_ptr
+    // otherwise it will mysteriously fail build
+    // with a non-default constructible T.
+    // There may be other solutions.
+    std::deque<std::shared_ptr<T>> m_data;
 };
 
 }
diff --git a/src/niepce/ui/dialogs/importdialog.cpp b/src/niepce/ui/dialogs/importdialog.cpp
index e76701b3..706ca8cc 100644
--- a/src/niepce/ui/dialogs/importdialog.cpp
+++ b/src/niepce/ui/dialogs/importdialog.cpp
@@ -17,6 +17,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <memory>
+
 #include <glibmm/miscutils.h>
 #include <gtkmm/button.h>
 #include <gtkmm/checkbutton.h>
@@ -213,23 +215,22 @@ void ImportDialog::append_files_to_import()
         [this, importer, source, paths] () {
             return importer->get_previews_for(
                 source, paths,
-                [this] (const std::string& path, const fwk::ThumbnailPtr& thumbnail) {
+                [this] (std::string&& path, fwk::ThumbnailPtr&& thumbnail) {
                     this->m_previews_to_import.send_data(
-                        std::make_pair(path, thumbnail));
+                        std::shared_ptr<decltype(this->m_previews_to_import)::value_type>(new 
std::pair(std::move(path), std::move(thumbnail))));
                 });
         });
 }
 
 void ImportDialog::preview_received()
 {
-    auto result = m_previews_to_import.recv_data();
-    if (!result.empty()) {
-        auto preview = result.unwrap();
-        auto iter = m_images_list_map.find(preview.first);
+    auto preview = m_previews_to_import.recv_data();
+    if (preview) {
+        auto iter = m_images_list_map.find(preview->first);
         if (iter != m_images_list_map.end()) {
             iter->second->set_value(m_grid_columns.pixbuf,
-                                    Glib::wrap(ffi::fwk_toolkit_thumbnail_to_pixbuf(
-                                                   preview.second.get())));
+                                    Glib::wrap((GdkPixbuf*)fwk::Thumbnail_to_pixbuf(
+                                                   *preview->second)));
         }
     }
 }
diff --git a/src/niepce/ui/dialogs/importdialog.hpp b/src/niepce/ui/dialogs/importdialog.hpp
index 2be884e2..df4dd0ec 100644
--- a/src/niepce/ui/dialogs/importdialog.hpp
+++ b/src/niepce/ui/dialogs/importdialog.hpp
@@ -30,7 +30,6 @@
 #include "fwk/toolkit/gtkutils.hpp"
 #include "fwk/toolkit/dialog.hpp"
 #include "fwk/toolkit/uiresult.hpp"
-#include "fwk/toolkit/thumbnail.hpp"
 #include "metadatapanecontroller.hpp"
 #include "importers/iimporterui.hpp"
 
diff --git a/src/rust_bindings.hpp b/src/rust_bindings.hpp
index 27a3967b..27d036ce 100644
--- a/src/rust_bindings.hpp
+++ b/src/rust_bindings.hpp
@@ -43,6 +43,8 @@ struct NiepcePropertySet;
 namespace fwk {
 typedef std::shared_ptr<SharedConfiguration> ConfigurationPtr;
 typedef rust::Box<fwk::Date> DatePtr;
+typedef rust::Box<Thumbnail> ThumbnailPtr;
+
 typedef ffi::PropertyValue PropertyValue;
 typedef ffi::NiepcePropertyBag PropertyBag;
 typedef ffi::NiepcePropertySet PropertySet;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]