[niepce] libraryclient+rust: LibraryClient written in Rust



commit e63bab90d55f9104da85a2f53e521b3a75a31a4e
Author: Hubert Figuière <hub figuiere net>
Date:   Sun Oct 8 11:12:40 2017 -0400

    libraryclient+rust: LibraryClient written in Rust
    
    - commands.rs no longer export C function
    - no more LocalLibraryServer
    - remove C++ Library code.

 src/engine/Makefile.am                             |   11 -
 src/engine/db/filebundle.rs                        |   11 +-
 src/engine/db/library.cpp                          |   38 ---
 src/engine/db/library.hpp                          |   45 ----
 src/engine/db/library.rs                           |   22 +--
 src/engine/db/mod.rs                               |    1 +
 src/engine/library/commands.rs                     |   85 ++-----
 src/engine/library/mod.rs                          |    1 +
 src/engine/library/op.cpp                          |   47 ----
 src/engine/library/op.hpp                          |   61 -----
 src/engine/library/{opqueue.hpp => op.rs}          |   27 +-
 src/engine/library/test_opqueue.cpp                |   49 ----
 src/lib.rs                                         |    1 +
 src/libraryclient/Makefile.am                      |    6 -
 src/libraryclient/clientimpl.cpp                   |  120 +++------
 src/libraryclient/clientimpl.hpp                   |   53 ++--
 src/libraryclient/clientimpl.rs                    |  271 ++++++++++++++++++++
 src/libraryclient/libraryclient.cpp                |   65 ++---
 src/libraryclient/libraryclient.hpp                |   32 +--
 src/libraryclient/locallibraryserver.cpp           |   33 ---
 src/libraryclient/locallibraryserver.hpp           |   49 ----
 .../clienttypes.hpp => libraryclient/mod.rs}       |   12 +-
 src/libraryclient/test_worker.cpp                  |   52 ----
 src/niepce/ui/dialogs/editlabels.cpp               |    5 +-
 src/rust_bindings.hpp                              |    1 -
 25 files changed, 433 insertions(+), 665 deletions(-)
---
diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am
index 1538b8c..830a903 100644
--- a/src/engine/Makefile.am
+++ b/src/engine/Makefile.am
@@ -1,11 +1,8 @@
 
-
 AM_CPPFLAGS = -I$(top_srcdir)/src/  @FRAMEWORK_CFLAGS@ \
        @GPHOTO_CFLAGS@ \
        $(NULL)
 
-TESTS = test_opqueue
-
 TEST_LIBS =  \
        libniepceengine.a \
        $(top_builddir)/target/debug/libniepce_rust.a \
@@ -19,16 +16,9 @@ TEST_LIBS =  \
        -ldl \
        $(NULL)
 
-
-check_PROGRAMS = test_opqueue
-
-test_opqueue_SOURCES = library/test_opqueue.cpp library/opqueue.hpp
-test_opqueue_LDADD = $(TEST_LIBS)
-
 noinst_LIBRARIES = libniepceengine.a libniepceengineglue.a
 
 libniepceengine_a_SOURCES = \
-       db/library.hpp db/library.cpp \
        db/libfile.hpp db/libfile.cpp \
        db/libfolder.hpp db/libfolder.cpp \
        db/label.hpp db/label.cpp \
@@ -40,7 +30,6 @@ libniepceengine_a_SOURCES = \
        db/properties.hpp db/properties.cpp \
        db/properties-def.hpp \
        library/clienttypes.hpp \
-       library/op.hpp library/op.cpp  \
        library/thumbnailcache.hpp library/thumbnailcache.cpp \
        library/thumbnailnotification.hpp \
        importer/iimporter.hpp \
diff --git a/src/engine/db/filebundle.rs b/src/engine/db/filebundle.rs
index 4ba08cf..50d2b6b 100644
--- a/src/engine/db/filebundle.rs
+++ b/src/engine/db/filebundle.rs
@@ -41,13 +41,16 @@ impl FileBundle {
         }
     }
 
-    pub fn filter_bundles(mut files: Vec<String>) -> Vec<FileBundle> {
+    pub fn filter_bundles(files: &Vec<String>) -> Vec<FileBundle> {
         let mut bundles: Vec<FileBundle> = vec!();
-        files.sort();
+        let mut sorted_files : Vec<&String> = files
+            .iter()
+            .collect();
+        sorted_files.sort();
         let mut current_base = OsString::new();
         let mut current_bundle: Option<FileBundle> = None;
 
-        for f in files {
+        for f in sorted_files {
             let path = Path::new(&f);
             if let Some(basename) = path.file_stem() {
                 if basename == current_base {
@@ -133,7 +136,7 @@ mod test {
         thelist.push(String::from("/foo/bar/dcs_0001.nef"));
         thelist.push(String::from("/foo/bar/dcs_0001.xmp"));
 
-        let bundles_list = FileBundle::filter_bundles(thelist);
+        let bundles_list = FileBundle::filter_bundles(&thelist);
 
         assert!(bundles_list.len() == 2);
         let mut iter = bundles_list.iter();
diff --git a/src/engine/db/library.rs b/src/engine/db/library.rs
index 498aba2..3ed3dbd 100644
--- a/src/engine/db/library.rs
+++ b/src/engine/db/library.rs
@@ -17,12 +17,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-use libc::c_char;
 use std::path::{
     Path,
     PathBuf
 };
-use std::ffi::CStr;
 use std::fs::File;
 use std::io::Write;
 use rusqlite;
@@ -46,7 +44,7 @@ use fwk::PropertyValue;
 use root::eng::NiepceProperties as Np;
 
 #[repr(i32)]
-#[derive(PartialEq,Clone)]
+#[derive(PartialEq,Clone,Copy)]
 pub enum Managed {
     NO = 0,
     YES = 1
@@ -825,24 +823,6 @@ impl Library {
     }
 }
 
-#[no_mangle]
-pub extern "C" fn engine_db_library_new(path: *const c_char, notif_id: u64) -> *mut Library {
-    let l = Box::new(
-        Library::new(PathBuf::from(&*unsafe { CStr::from_ptr(path) }.to_string_lossy()),
-                     notif_id));
-    Box::into_raw(l)
-}
-
-#[no_mangle]
-pub extern "C" fn engine_db_library_delete(l: *mut Library) {
-    unsafe { Box::from_raw(l); }
-}
-
-#[no_mangle]
-pub extern "C" fn engine_db_library_ok(l: &Library) -> bool {
-    l.is_ok()
-}
-
 #[cfg(test)]
 mod test {
     use std::path::Path;
diff --git a/src/engine/db/mod.rs b/src/engine/db/mod.rs
index 927b303..c379659 100644
--- a/src/engine/db/mod.rs
+++ b/src/engine/db/mod.rs
@@ -33,6 +33,7 @@ pub use self::label::Label;
 pub use self::libmetadata::LibMetadata;
 pub use self::libfolder::LibFolder;
 pub use self::keyword::Keyword;
+pub use self::library::Library;
 
 
 use rusqlite;
diff --git a/src/engine/library/commands.rs b/src/engine/library/commands.rs
index d28f46b..641f332 100644
--- a/src/engine/library/commands.rs
+++ b/src/engine/library/commands.rs
@@ -17,8 +17,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-use libc::c_char;
-use std::ffi::CStr;
 use std::os::raw::c_void;
 use std::path::Path;
 
@@ -39,10 +37,8 @@ use super::notification::{
     MetadataChange,
 };
 use root::eng::NiepceProperties as Np;
-use root::fwk::FileList;
 
-#[no_mangle]
-pub extern "C" fn cmd_list_all_keywords(lib: &Library) -> bool {
+pub fn cmd_list_all_keywords(lib: &Library) -> bool {
     let list = lib.get_all_keywords();
     // XXX change this to "LoadKeywords"
     for kw in list {
@@ -51,8 +47,7 @@ pub extern "C" fn cmd_list_all_keywords(lib: &Library) -> bool {
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_list_all_folders(lib: &Library) -> bool {
+pub fn cmd_list_all_folders(lib: &Library) -> bool {
     let list = lib.get_all_folders();
     // XXX change this to "LoadedFodlers"
     for folder in list {
@@ -61,16 +56,13 @@ pub extern "C" fn cmd_list_all_folders(lib: &Library) -> bool {
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_import_file(lib: &Library, file_path: *const c_char, manage: Managed) -> bool {
+pub fn cmd_import_file(lib: &Library, path: &str, manage: Managed) -> bool {
     dbg_assert!(manage == Managed::NO, "managing file is currently unsupported");
 
-    let path = String::from(unsafe { CStr::from_ptr(file_path) }.to_string_lossy());
-
     let mut bundle = FileBundle::new();
-    bundle.add(&path);
+    bundle.add(path);
 
-    let folder = Path::new(&path).parent().unwrap_or(Path::new(""));
+    let folder = Path::new(path).parent().unwrap_or(Path::new(""));
 
     let libfolder: LibFolder;
     match lib.get_folder(&*folder.to_string_lossy()) {
@@ -91,28 +83,17 @@ pub extern "C" fn cmd_import_file(lib: &Library, file_path: *const c_char, manag
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_import_files(lib: &Library, folder: *const c_char, cfiles: &mut FileList,
+pub fn cmd_import_files(lib: &Library, folder: &str, files: &Vec<String>,
                         manage: Managed) -> bool {
     dbg_assert!(manage == Managed::NO, "managing file is currently unsupported");
 
-    let mut files: Vec<String> = vec!();
-    {
-        let len = unsafe { cfiles.size() };
-        for i in 0..len {
-            let f = unsafe { cfiles.at_cstr(i) };
-            let cstr = unsafe { CStr::from_ptr(f) }.to_string_lossy();
-            files.push(String::from(cstr));
-        }
-    }
     let bundles = FileBundle::filter_bundles(files);
     let libfolder: LibFolder;
-    let folder = unsafe { CStr::from_ptr(folder) }.to_string_lossy();
-    match lib.get_folder(&folder) {
+    match lib.get_folder(folder) {
         Some(lf) =>
             libfolder = lf,
         _ => {
-            if let Some(lf) = lib.add_folder(&folder) {
+            if let Some(lf) = lib.add_folder(folder) {
                 libfolder = lf.clone();
                 lib.notify(Box::new(LibNotification::AddedFolder(lf)));
             } else {
@@ -128,8 +109,7 @@ pub extern "C" fn cmd_import_files(lib: &Library, folder: *const c_char, cfiles:
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_request_metadata(lib: &Library, file_id: LibraryId) -> bool {
+pub fn cmd_request_metadata(lib: &Library, file_id: LibraryId) -> bool {
     if let Some(lm) = lib.get_metadata(file_id) {
         lib.notify(Box::new(LibNotification::MetadataQueried(lm)));
         return true;
@@ -137,8 +117,7 @@ pub extern "C" fn cmd_request_metadata(lib: &Library, file_id: LibraryId) -> boo
     false
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_query_folder_content(lib: &Library, folder_id: LibraryId) -> bool {
+pub fn cmd_query_folder_content(lib: &Library, folder_id: LibraryId) -> bool {
     let fl = lib.get_folder_content(folder_id);
     let mut value = Box::new(
         LibNotification::FolderContentQueried(unsafe { Content::new(folder_id) }));
@@ -151,8 +130,7 @@ pub extern "C" fn cmd_query_folder_content(lib: &Library, folder_id: LibraryId)
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_set_metadata(lib: &Library, id: LibraryId, meta: Np,
+pub fn cmd_set_metadata(lib: &Library, id: LibraryId, meta: Np,
                         value: &PropertyValue) -> bool {
     lib.set_metadata(id, meta, value);
     lib.notify(Box::new(LibNotification::MetadataChanged(
@@ -160,16 +138,14 @@ pub extern "C" fn cmd_set_metadata(lib: &Library, id: LibraryId, meta: Np,
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_count_folder(lib: &Library, folder_id: LibraryId) -> bool {
+pub fn cmd_count_folder(lib: &Library, folder_id: LibraryId) -> bool {
     let count = lib.count_folder(folder_id);
     lib.notify(Box::new(LibNotification::FolderCounted(
         FolderCount{folder: folder_id, count: count})));
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_query_keyword_content(lib: &Library, keyword_id: LibraryId) -> bool {
+pub fn cmd_query_keyword_content(lib: &Library, keyword_id: LibraryId) -> bool {
     let fl = lib.get_keyword_content(keyword_id);
     let mut content = unsafe { Content::new(keyword_id) };
     for f in fl {
@@ -179,13 +155,11 @@ pub extern "C" fn cmd_query_keyword_content(lib: &Library, keyword_id: LibraryId
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_write_metadata(lib: &Library, file_id: LibraryId) -> bool {
+pub fn cmd_write_metadata(lib: &Library, file_id: LibraryId) -> bool {
     lib.write_metadata(file_id)
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_move_file_to_folder(lib: &Library, file_id: LibraryId, from: LibraryId,
+pub fn cmd_move_file_to_folder(lib: &Library, file_id: LibraryId, from: LibraryId,
                                to: LibraryId) -> bool {
 
     if lib.move_file_to_folder(file_id, to) {
@@ -200,8 +174,7 @@ pub extern "C" fn cmd_move_file_to_folder(lib: &Library, file_id: LibraryId, fro
     false
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_list_all_labels(lib: &Library) -> bool {
+pub fn cmd_list_all_labels(lib: &Library) -> bool {
     let l = lib.get_all_labels();
     // XXX change this notification type
     for label in l {
@@ -210,37 +183,29 @@ pub extern "C" fn cmd_list_all_labels(lib: &Library) -> bool {
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_create_label(lib: &Library, name: *const c_char, colour: *const c_char) -> bool {
-    let name = unsafe { CStr::from_ptr(name) }.to_string_lossy();
-    let colour = unsafe { CStr::from_ptr(colour) }.to_string_lossy();
-    let id = lib.add_label(&name, &colour);
+pub fn cmd_create_label(lib: &Library, name: &str, colour: &str) -> bool {
+    let id = lib.add_label(name, colour);
     if id != -1 {
-        let l = Label::new(id, &name, &colour);
+        let l = Label::new(id, name, colour);
         lib.notify(Box::new(LibNotification::AddedLabel(l)));
     }
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_delete_label(lib: &Library, label_id: LibraryId) -> bool {
+pub fn cmd_delete_label(lib: &Library, label_id: LibraryId) -> bool {
     lib.delete_label(label_id);
     lib.notify(Box::new(LibNotification::LabelDeleted(label_id)));
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_update_label(lib: &Library, label_id: LibraryId, name: *const c_char,
-                        colour: *const c_char) -> bool {
-    let name = unsafe { CStr::from_ptr(name) }.to_string_lossy();
-    let colour = unsafe { CStr::from_ptr(colour) }.to_string_lossy();
-    lib.update_label(label_id, &name, &colour);
-    let label = Label::new(label_id, &name, &colour);
+pub fn cmd_update_label(lib: &Library, label_id: LibraryId, name: &str,
+                        colour: &str) -> bool {
+    lib.update_label(label_id, name, colour);
+    let label = Label::new(label_id, name, colour);
     lib.notify(Box::new(LibNotification::LabelChanged(label)));
     true
 }
 
-#[no_mangle]
-pub extern "C" fn cmd_process_xmp_update_queue(lib: &Library, write_xmp: bool) -> bool {
+pub fn cmd_process_xmp_update_queue(lib: &Library, write_xmp: bool) -> bool {
     lib.process_xmp_update_queue(write_xmp)
 }
diff --git a/src/engine/library/mod.rs b/src/engine/library/mod.rs
index d36c58e..8d3e68d 100644
--- a/src/engine/library/mod.rs
+++ b/src/engine/library/mod.rs
@@ -2,3 +2,4 @@
 
 pub mod commands;
 pub mod notification;
+pub mod op;
diff --git a/src/engine/library/opqueue.hpp b/src/engine/library/op.rs
similarity index 61%
rename from src/engine/library/opqueue.hpp
rename to src/engine/library/op.rs
index 8241499..6863530 100644
--- a/src/engine/library/opqueue.hpp
+++ b/src/engine/library/op.rs
@@ -1,7 +1,7 @@
 /*
- * niepce - library/opqueue.h
+ * niepce - engine/library/op.rs
  *
- * Copyright (C) 2007 Hubert Figuiere
+ * Copyright (C) 2017 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,19 +17,22 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+use std::sync::Arc;
 
+use engine::db::Library;
 
-#ifndef __NIEPCE_LIBRARY_OPQUEUE_H__
-#define __NIEPCE_LIBRARY_OPQUEUE_H__
 
+pub struct Op {
+    op: Arc<Fn(&Library) -> bool + Send + Sync + 'static>
+}
 
-#include "fwk/utils/mtqueue.hpp"
-#include "op.hpp"
-
-namespace eng {
-
-       typedef fwk::MtQueue< Op::Ptr > OpQueue;
+impl Op {
+    pub fn new<F>(f: F) -> Op
+        where F: Fn(&Library) -> bool + Send + Sync + 'static {
+        Op { op: Arc::new(f) }
+    }
 
+    pub fn execute(self, lib: &Library) -> bool {
+        (self.op)(lib)
+    }
 }
-
-#endif
diff --git a/src/lib.rs b/src/lib.rs
index a46cf05..5917a20 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -27,6 +27,7 @@ extern crate rusqlite;
 #[macro_use]
 pub mod fwk;
 pub mod engine;
+pub mod libraryclient;
 pub mod capi;
 
 include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
diff --git a/src/libraryclient/Makefile.am b/src/libraryclient/Makefile.am
index f9c2877..458a216 100644
--- a/src/libraryclient/Makefile.am
+++ b/src/libraryclient/Makefile.am
@@ -4,8 +4,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src @FRAMEWORK_CFLAGS@
 
 noinst_LIBRARIES = liblibraryclient.a
 
-check_PROGRAMS = test_worker
-TESTS = test_worker
 TEST_LIBS =  \
        liblibraryclient.a \
        $(top_builddir)/src/engine/libniepceengine.a \
@@ -20,11 +18,7 @@ TEST_LIBS =  \
        -ldl \
        $(NULL)
 
-test_worker_SOURCES = test_worker.cpp
-test_worker_LDADD = $(TEST_LIBS)
-
 liblibraryclient_a_SOURCES = libraryclient.hpp  libraryclient.cpp \
        clientimpl.hpp clientimpl.cpp \
-       locallibraryserver.hpp locallibraryserver.cpp \
        uidataprovider.hpp uidataprovider.cpp \
        $(NULL)
diff --git a/src/libraryclient/clientimpl.cpp b/src/libraryclient/clientimpl.cpp
index 3a3aa40..d964ec7 100644
--- a/src/libraryclient/clientimpl.cpp
+++ b/src/libraryclient/clientimpl.cpp
@@ -19,17 +19,13 @@
 
 #include "fwk/base/debug.hpp"
 #include "fwk/utils/files.hpp"
-#include "engine/library/op.hpp"
 #include "libraryclient.hpp"
 #include "clientimpl.hpp"
-#include "locallibraryserver.hpp"
 
 #include "rust_bindings.hpp"
 
 using fwk::FileListPtr;
-using eng::Op;
 using eng::Managed;
-using eng::tid_t;
 
 namespace libraryclient {
 
@@ -40,8 +36,8 @@ std::unique_ptr<ClientImpl> ClientImpl::makeClientImpl(const fwk::Moniker & moni
 }
 
 ClientImpl::ClientImpl(const fwk::Moniker & moniker, uint64_t notif_id)
-    : m_moniker(moniker),
-      m_localLibrary(new LocalLibraryServer(moniker.path(), notif_id))
+    : m_moniker(moniker)
+    , m_impl(ffi::libraryclient_clientimpl_new(moniker.path().c_str(), notif_id))
 {
     DBG_OUT("creating implementation with moniker %s",
             moniker.c_str());
@@ -49,147 +45,107 @@ ClientImpl::ClientImpl(const fwk::Moniker & moniker, uint64_t notif_id)
 
 ClientImpl::~ClientImpl()
 {
+    ffi::libraryclient_clientimpl_delete(m_impl);
 }
 
 bool ClientImpl::ok() const
 {
-    return m_localLibrary && m_localLibrary->ok();
+    return m_impl;
 }
 
-/**
-   Schedule an operation.
-   @param func the function to schedule
-   @return the tid
- */
-tid_t ClientImpl::schedule_op(const Op::Function & func)
-{
-    tid_t id = LibraryClient::newTid();
-    Op::Ptr op(new Op(id, func));
-    m_localLibrary->schedule(op);
-    return id;
-}
-
-tid_t ClientImpl::getAllKeywords()
+void ClientImpl::getAllKeywords()
 {
-    return schedule_op(&ffi::cmd_list_all_keywords);
+    ffi::libraryclient_clientimpl_get_all_keywords(m_impl);
 }
 
-
-tid_t ClientImpl::getAllFolders()
+void ClientImpl::getAllFolders()
 {
-    return schedule_op(&ffi::cmd_list_all_folders);
+    ffi::libraryclient_clientimpl_get_all_folders(m_impl);
 }
 
-tid_t ClientImpl::queryFolderContent(eng::library_id_t folder_id)
+void ClientImpl::queryFolderContent(eng::library_id_t folder_id)
 {
-    return schedule_op([folder_id](const auto& lib) {
-            return ffi::cmd_query_folder_content(lib, folder_id);
-        });
+    ffi::libraryclient_clientimpl_query_folder_content(m_impl, folder_id);
 }
 
-
-tid_t ClientImpl::countFolder(eng::library_id_t folder_id)
+void ClientImpl::countFolder(eng::library_id_t folder_id)
 {
-    return schedule_op([folder_id](const auto& lib) {
-            return ffi::cmd_count_folder(lib, folder_id);
-        });
+    ffi::libraryclient_clientimpl_count_folder(m_impl, folder_id);
 }
 
 
-tid_t ClientImpl::queryKeywordContent(eng::library_id_t keyword_id)
+void ClientImpl::queryKeywordContent(eng::library_id_t keyword_id)
 {
-    return schedule_op([keyword_id](const auto& lib) {
-            return ffi::cmd_query_keyword_content(lib, keyword_id);
-        });
+    ffi::libraryclient_clientimpl_query_keyword_content(m_impl, keyword_id);
 }
 
 
-tid_t ClientImpl::requestMetadata(eng::library_id_t file_id)
+void ClientImpl::requestMetadata(eng::library_id_t file_id)
 {
-    return schedule_op([file_id](const auto& lib) {
-            return ffi::cmd_request_metadata(lib, file_id);
-        });
+    ffi::libraryclient_clientimpl_request_metadata(m_impl, file_id);
 }
 
 
-tid_t ClientImpl::setMetadata(eng::library_id_t file_id, eng::Np meta,
+void ClientImpl::setMetadata(eng::library_id_t file_id, eng::Np meta,
                               const fwk::PropertyValuePtr & value)
 {
-    return schedule_op([file_id, meta, value](const auto& lib) {
-            return ffi::cmd_set_metadata(lib, file_id, meta, value.get());
-        });
+    ffi::libraryclient_clientimpl_set_metadata(m_impl, file_id, meta, value.get());
 }
 
-tid_t ClientImpl::write_metadata(eng::library_id_t file_id)
+void ClientImpl::write_metadata(eng::library_id_t file_id)
 {
-    return schedule_op([file_id](const auto& lib) {
-            return ffi::cmd_write_metadata(lib, file_id);
-        });
+    ffi::libraryclient_clientimpl_write_metadata(m_impl, file_id);
 }
 
-tid_t ClientImpl::moveFileToFolder(eng::library_id_t file_id,
+void ClientImpl::moveFileToFolder(eng::library_id_t file_id,
                                    eng::library_id_t from_folder_id,
                                    eng::library_id_t to_folder_id)
 {
-    return schedule_op([file_id, from_folder_id, to_folder_id](const auto& lib) {
-            return ffi::cmd_move_file_to_folder(lib, file_id, from_folder_id, to_folder_id);
-        });
+    ffi::libraryclient_clientimpl_move_file_to_folder(m_impl, file_id, from_folder_id,
+                                                      to_folder_id);
 }
 
-
-tid_t ClientImpl::getAllLabels()
+void ClientImpl::getAllLabels()
 {
-    return schedule_op(&ffi::cmd_list_all_labels);
+    ffi::libraryclient_clientimpl_get_all_labels(m_impl);
 }
 
-
-tid_t ClientImpl::createLabel(const std::string & s, const std::string & colour)
+void ClientImpl::createLabel(const std::string & s, const std::string & colour)
 {
-    return schedule_op([s, colour](const auto& lib) {
-            return ffi::cmd_create_label(lib, s.c_str(), colour.c_str());
-        });
+    ffi::libraryclient_clientimpl_create_label(m_impl, s.c_str(), colour.c_str());
 }
 
-tid_t ClientImpl::deleteLabel(int label_id)
+void ClientImpl::deleteLabel(int label_id)
 {
-    return schedule_op([label_id](const auto& lib) {
-            return ffi::cmd_delete_label(lib, label_id);
-        });
+    ffi::libraryclient_clientimpl_delete_label(m_impl, label_id);
 }
 
-tid_t ClientImpl::updateLabel(eng::library_id_t label_id,
+void ClientImpl::updateLabel(eng::library_id_t label_id,
                               const std::string & new_name,
                               const std::string & new_colour)
 {
-    return schedule_op([label_id, new_name, new_colour](const auto& lib) {
-            return ffi::cmd_update_label(lib, label_id, new_name.c_str(), new_colour.c_str());
-        });
+    ffi::libraryclient_clientimpl_update_label(m_impl, label_id,
+                                               new_name.c_str(), new_colour.c_str());
 }
 
 
-tid_t ClientImpl::processXmpUpdateQueue(bool write_xmp)
+void ClientImpl::processXmpUpdateQueue(bool write_xmp)
 {
-    return schedule_op([write_xmp](const auto& lib) {
-            return ffi::cmd_process_xmp_update_queue(lib, write_xmp);
-        });
+    ffi::libraryclient_clientimpl_process_xmp_update_queue(m_impl, write_xmp);
 }
 
-tid_t ClientImpl::importFile(const std::string & path, Managed manage)
+void ClientImpl::importFile(const std::string & path, Managed manage)
 {
-    return schedule_op([path, manage](const auto& lib) {
-            return ffi::cmd_import_file(lib, path.c_str(), manage);
-        });
+    ffi::libraryclient_clientimpl_import_file(m_impl, path.c_str(), manage);
 }
 
-tid_t ClientImpl::importFromDirectory(const std::string & dir, Managed manage)
+void ClientImpl::importFromDirectory(const std::string & dir, Managed manage)
 {
     FileListPtr files;
 
     files = fwk::FileList::getFilesFromDirectory(dir, &fwk::filter_none);
 
-    return schedule_op([dir, files, manage](const auto& lib) {
-            return ffi::cmd_import_files(lib, dir.c_str(), files.get(), manage);
-        });
+    ffi::libraryclient_clientimpl_import_files(m_impl, dir.c_str(), files.get(), manage);
 }
 
 }
diff --git a/src/libraryclient/clientimpl.hpp b/src/libraryclient/clientimpl.hpp
index 7ad1b6b..3cb11d5 100644
--- a/src/libraryclient/clientimpl.hpp
+++ b/src/libraryclient/clientimpl.hpp
@@ -1,7 +1,7 @@
 /*
  * niepce - libraryclient/clientimpl.hpp
  *
- * Copyright (C) 2007-2015 Hubert Figuière
+ * Copyright (C) 2007-2017 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,12 +24,10 @@
 #include <string>
 
 #include "fwk/base/moniker.hpp"
-#include "engine/library/clienttypes.hpp"
-#include "engine/library/op.hpp"
 
-namespace libraryclient {
+#include "rust_bindings.hpp"
 
-class LocalLibraryServer;
+namespace libraryclient {
 
 class ClientImpl
 {
@@ -41,37 +39,34 @@ public:
     virtual ~ClientImpl();
     bool ok() const;
 
-    eng::tid_t getAllKeywords();
-    eng::tid_t queryKeywordContent(eng::library_id_t id);
-    eng::tid_t getAllFolders();
-    eng::tid_t queryFolderContent(eng::library_id_t id);
-    eng::tid_t countFolder(eng::library_id_t id);
-    eng::tid_t requestMetadata(eng::library_id_t id);
-    eng::tid_t setMetadata(eng::library_id_t id, eng::Np meta,
-                           const fwk::PropertyValuePtr & value);
-    eng::tid_t write_metadata(eng::library_id_t file_id);
+    void getAllKeywords();
+    void queryKeywordContent(eng::library_id_t id);
+    void getAllFolders();
+    void queryFolderContent(eng::library_id_t id);
+    void countFolder(eng::library_id_t id);
+    void requestMetadata(eng::library_id_t id);
+    void setMetadata(eng::library_id_t id, eng::Np meta,
+                     const fwk::PropertyValuePtr & value);
+    void write_metadata(eng::library_id_t file_id);
 
-    eng::tid_t moveFileToFolder(eng::library_id_t file_id,
-                                eng::library_id_t from_folder_id,
-                                eng::library_id_t to_folder_id);
+    void moveFileToFolder(eng::library_id_t file_id,
+                          eng::library_id_t from_folder_id,
+                          eng::library_id_t to_folder_id);
 
-    eng::tid_t getAllLabels();
-    eng::tid_t createLabel(const std::string & s, const std::string & color);
-    eng::tid_t deleteLabel(int id);
-    eng::tid_t updateLabel(eng::library_id_t id, const std::string & new_name,
-                           const std::string & new_color);
+    void getAllLabels();
+    void createLabel(const std::string & s, const std::string & color);
+    void deleteLabel(int id);
+    void updateLabel(eng::library_id_t id, const std::string & new_name,
+                     const std::string & new_color);
 
-    eng::tid_t processXmpUpdateQueue(bool write_xmp);
+    void processXmpUpdateQueue(bool write_xmp);
 
-    eng::tid_t importFile(const std::string & path, eng::Managed manage);
-    eng::tid_t importFromDirectory(const std::string & dir, eng::Managed manage);
+    void importFile(const std::string & path, eng::Managed manage);
+    void importFromDirectory(const std::string & dir, eng::Managed manage);
 
 protected:
     const fwk::Moniker m_moniker;
-    std::unique_ptr<LocalLibraryServer> m_localLibrary;
-private:
-    /** do the dirty work of scheduling the op */
-    eng::tid_t schedule_op(const eng::Op::Function & func);
+    ffi::ClientImpl* m_impl;
 };
 
 }
diff --git a/src/libraryclient/clientimpl.rs b/src/libraryclient/clientimpl.rs
new file mode 100644
index 0000000..9b990fb
--- /dev/null
+++ b/src/libraryclient/clientimpl.rs
@@ -0,0 +1,271 @@
+/*
+ * niepce - libraryclient/clientimpl.rs
+ *
+ * Copyright (C) 2017 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::collections::VecDeque;
+use std::ffi::CStr;
+use std::path::PathBuf;
+use std::sync;
+use std::sync::atomic;
+use std::thread;
+
+use fwk::base::propertyvalue::PropertyValue;
+use engine::db::{Library, LibraryId};
+use engine::db::library::Managed;
+use engine::library::op::Op;
+use engine::library::commands;
+use root::fwk::FileList;
+use root::eng::NiepceProperties as Np;
+
+
+pub struct ClientImpl {
+    terminate: sync::Arc<atomic::AtomicBool>,
+    tasks: sync::Arc<(sync::Mutex<VecDeque<Op>>, sync::Condvar)>,
+}
+
+impl Drop for ClientImpl {
+    fn drop(&mut self) {
+        self.stop();
+    }
+}
+
+impl ClientImpl {
+
+    pub fn new(dir: PathBuf, notif_id: u64) -> ClientImpl {
+        let tasks = sync::Arc::new((sync::Mutex::new(VecDeque::new()), sync::Condvar::new()));
+        let mut terminate = sync::Arc::new(atomic::AtomicBool::new(false));
+        let tasks2 = tasks.clone();
+        let terminate2 = terminate.clone();
+
+        /* let thread = */ thread::spawn(move || {
+            let library = Library::new(dir, notif_id);
+            Self::main(&mut terminate, tasks, &library);
+        });
+
+
+        ClientImpl {
+            terminate: terminate2,
+            tasks: tasks2,
+        }
+    }
+
+    fn stop(&mut self) {
+        self.terminate.store(true, atomic::Ordering::Relaxed);
+        self.tasks.1.notify_one();
+    }
+
+    fn main(terminate: &mut sync::Arc<atomic::AtomicBool>,
+            tasks: sync::Arc<(sync::Mutex<VecDeque<Op>>, sync::Condvar)>,
+            library: &Library) {
+
+        while !terminate.load(atomic::Ordering::Relaxed) {
+
+            let elem: Option<Op>;
+            {
+                let mut queue = tasks.0.lock().unwrap();
+                if !queue.is_empty() {
+                    elem = queue.pop_front();
+                } else {
+                    elem = None;
+                }
+            }
+
+            if let Some(op) = elem {
+                op.execute(library);
+            }
+
+            let queue = tasks.0.lock().unwrap();
+            if queue.is_empty() {
+                if let Err(err) = tasks.1.wait(queue) {
+                    err_out!("queue lock poisonned: {}", err);
+                    break;
+                }
+            }
+        }
+    }
+
+    pub fn schedule_op<F>(&mut self, f: F)
+        where F: Fn(&Library) -> bool + Send + Sync + 'static {
+
+        let op = Op::new(f);
+
+        let mut queue = self.tasks.0.lock().unwrap();
+        queue.push_back(op);
+        self.tasks.1.notify_all();
+    }
+
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_new(path: *const c_char, notif_id: u64) -> *mut ClientImpl {
+    let dir = PathBuf::from(&*unsafe { CStr::from_ptr(path) }.to_string_lossy());
+    Box::into_raw(Box::new(ClientImpl::new(dir, notif_id)))
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_delete(obj: *mut ClientImpl) {
+    unsafe { Box::from_raw(obj); }
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_get_all_keywords(client: &mut ClientImpl) {
+    client.schedule_op(move |lib| {
+        commands::cmd_list_all_keywords(&lib)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_get_all_folders(client: &mut ClientImpl) {
+    client.schedule_op(move |lib| {
+        commands::cmd_list_all_folders(&lib)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_query_folder_content(client: &mut ClientImpl,
+                                                                folder_id: LibraryId) {
+    client.schedule_op(move |lib| {
+        commands::cmd_query_folder_content(&lib, folder_id)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_count_folder(client: &mut ClientImpl,
+                                                        folder_id: LibraryId) {
+    client.schedule_op(move |lib| {
+        commands::cmd_count_folder(&lib, folder_id)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_query_keyword_content(client: &mut ClientImpl,
+                                                                 keyword_id: LibraryId) {
+    client.schedule_op(move |lib| {
+        commands::cmd_query_keyword_content(&lib, keyword_id)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_request_metadata(client: &mut ClientImpl,
+                                                            file_id: LibraryId) {
+    client.schedule_op(move |lib| {
+        commands::cmd_request_metadata(&lib, file_id)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_set_metadata(client: &mut ClientImpl,
+                                                        file_id: LibraryId,
+                                                        meta: Np, value: &PropertyValue) {
+    let value2 = value.clone();
+    client.schedule_op(move |lib| {
+        commands::cmd_set_metadata(&lib, file_id, meta, &value2)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_write_metadata(client: &mut ClientImpl,
+                                                          file_id: LibraryId) {
+    client.schedule_op(move |lib| {
+        commands::cmd_write_metadata(&lib, file_id)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_move_file_to_folder(client: &mut ClientImpl,
+                                                               file_id: LibraryId,
+                                                               from: LibraryId,
+                                                               to: LibraryId) {
+    client.schedule_op(move |lib| {
+        commands::cmd_move_file_to_folder(&lib, file_id, from, to)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_get_all_labels(client: &mut ClientImpl) {
+    client.schedule_op(move |lib| {
+        commands::cmd_list_all_labels(&lib)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_create_label(client: &mut ClientImpl,
+                                                        s: *const c_char, c: *const c_char) {
+    let name = unsafe { CStr::from_ptr(s) }.to_string_lossy();
+    let colour = unsafe { CStr::from_ptr(c) }.to_string_lossy();
+    client.schedule_op(move |lib| {
+        commands::cmd_create_label(&lib, &name, &colour)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_delete_label(client: &mut ClientImpl,
+                                                        label_id: LibraryId) {
+    client.schedule_op(move |lib| {
+        commands::cmd_delete_label(&lib, label_id)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_update_label(client: &mut ClientImpl,
+                                                        label_id: LibraryId,
+                                                        s: *const c_char, c: *const c_char) {
+    let name = unsafe { CStr::from_ptr(s) }.to_string_lossy();
+    let colour = unsafe { CStr::from_ptr(c) }.to_string_lossy();
+    client.schedule_op(move |lib| {
+        commands::cmd_update_label(&lib, label_id, &name, &colour)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_process_xmp_update_queue(client: &mut ClientImpl,
+                                                                    write_xmp: bool) {
+    client.schedule_op(move |lib| {
+        commands::cmd_process_xmp_update_queue(&lib, write_xmp)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_import_file(client: &mut ClientImpl,
+                                                       file_path: *const c_char,
+                                                       manage: Managed) {
+    let path = String::from(unsafe { CStr::from_ptr(file_path) }.to_string_lossy());
+    client.schedule_op(move |lib| {
+        commands::cmd_import_file(&lib, &path, manage)
+    });
+}
+
+#[no_mangle]
+pub extern "C" fn libraryclient_clientimpl_import_files(client: &mut ClientImpl,
+                                                        dir: *const c_char, cfiles: &mut FileList,
+                                                        manage: Managed) {
+    let folder = unsafe { CStr::from_ptr(dir) }.to_string_lossy();
+    let mut files: Vec<String> = vec!();
+    {
+        let len = unsafe { cfiles.size() };
+        for i in 0..len {
+            let f = unsafe { cfiles.at_cstr(i) };
+            let cstr = unsafe { CStr::from_ptr(f) }.to_string_lossy();
+            files.push(String::from(cstr));
+        }
+    }
+    client.schedule_op(move |lib| {
+        commands::cmd_import_files(&lib, &folder, &files, manage)
+    });
+}
diff --git a/src/libraryclient/libraryclient.cpp b/src/libraryclient/libraryclient.cpp
index 6837ea5..5863f82 100644
--- a/src/libraryclient/libraryclient.cpp
+++ b/src/libraryclient/libraryclient.cpp
@@ -24,7 +24,6 @@
 #include "clientimpl.hpp"
 #include "uidataprovider.hpp"
 
-using eng::tid_t;
 using eng::library_id_t;
 
 namespace libraryclient {
@@ -49,91 +48,83 @@ bool LibraryClient::ok() const
     return m_pImpl && m_pImpl->ok();
 }
 
-tid_t LibraryClient::newTid()
+void LibraryClient::getAllKeywords()
 {
-    static tid_t id = 0;
-    id++;
-    return id;
+    m_pImpl->getAllKeywords();
 }
 
 
-tid_t LibraryClient::getAllKeywords()
+void LibraryClient::getAllFolders()
 {
-    return m_pImpl->getAllKeywords();
+    m_pImpl->getAllFolders();
 }
 
-
-tid_t LibraryClient::getAllFolders()
-{
-    return m_pImpl->getAllFolders();
-}
-
-tid_t LibraryClient::queryFolderContent(eng::library_id_t id)
+void LibraryClient::queryFolderContent(eng::library_id_t id)
 {
-    return m_pImpl->queryFolderContent(id);
+    m_pImpl->queryFolderContent(id);
 }
 
-tid_t LibraryClient::queryKeywordContent(eng::library_id_t id)
+void LibraryClient::queryKeywordContent(eng::library_id_t id)
 {
-    return m_pImpl->queryKeywordContent(id);
+    m_pImpl->queryKeywordContent(id);
 }
 
-eng::tid_t LibraryClient::countFolder(library_id_t id)
+void LibraryClient::countFolder(library_id_t id)
 {
-    return m_pImpl->countFolder(id);
+    m_pImpl->countFolder(id);
 }
 
-eng::tid_t LibraryClient::requestMetadata(eng::library_id_t id)
+void LibraryClient::requestMetadata(eng::library_id_t id)
 {
-    return m_pImpl->requestMetadata(id);
+    m_pImpl->requestMetadata(id);
 }
 
 /** set the metadata */
-eng::tid_t LibraryClient::setMetadata(library_id_t id, fwk::PropertyIndex meta,
+void LibraryClient::setMetadata(library_id_t id, fwk::PropertyIndex meta,
                                       const fwk::PropertyValuePtr & value)
 {
-    return m_pImpl->setMetadata(id, static_cast<eng::Np>(meta), value);
+    m_pImpl->setMetadata(id, static_cast<eng::Np>(meta), value);
 }
 
-eng::tid_t LibraryClient::write_metadata(eng::library_id_t id)
+void LibraryClient::write_metadata(eng::library_id_t id)
 {
-    return m_pImpl->write_metadata(id);
+    m_pImpl->write_metadata(id);
 }
 
 
-eng::tid_t LibraryClient::moveFileToFolder(eng::library_id_t file_id, eng::library_id_t from_folder,
+void LibraryClient::moveFileToFolder(eng::library_id_t file_id, eng::library_id_t from_folder,
                                            eng::library_id_t to_folder)
 {
-    return m_pImpl->moveFileToFolder(file_id, from_folder, to_folder);
+    m_pImpl->moveFileToFolder(file_id, from_folder, to_folder);
 }
 
-eng::tid_t LibraryClient::getAllLabels()
+void LibraryClient::getAllLabels()
 {
-    return m_pImpl->getAllLabels();
+    m_pImpl->getAllLabels();
 }
 
 
-eng::tid_t LibraryClient::createLabel(const std::string & s, const std::string & color)
+void LibraryClient::createLabel(const std::string & s, const std::string & color)
 {
-    return m_pImpl->createLabel(s, color);
+    m_pImpl->createLabel(s, color);
 }
 
 
-eng::tid_t LibraryClient::deleteLabel(int id)
+void LibraryClient::deleteLabel(int id)
 {
-    return m_pImpl->deleteLabel(id);
+    m_pImpl->deleteLabel(id);
 }
 
 
-eng::tid_t LibraryClient::updateLabel(library_id_t id, const std::string & new_name,
+void LibraryClient::updateLabel(library_id_t id, const std::string & new_name,
                                           const std::string & new_color)
 {
-    return m_pImpl->updateLabel(id, new_name, new_color);
+    m_pImpl->updateLabel(id, new_name, new_color);
 }
 
-eng::tid_t LibraryClient::processXmpUpdateQueue(bool write_xmp)
+void LibraryClient::processXmpUpdateQueue(bool write_xmp)
 {
-    return m_pImpl->processXmpUpdateQueue(write_xmp);
+    m_pImpl->processXmpUpdateQueue(write_xmp);
 }
 
 void LibraryClient::importFile(const std::string & path, eng::Managed manage)
diff --git a/src/libraryclient/libraryclient.hpp b/src/libraryclient/libraryclient.hpp
index 93d072e..a94f3bc 100644
--- a/src/libraryclient/libraryclient.hpp
+++ b/src/libraryclient/libraryclient.hpp
@@ -25,7 +25,6 @@
 
 #include "fwk/base/propertybag.hpp"
 #include "fwk/base/util.hpp"
-#include "engine/library/clienttypes.hpp"
 #include "engine/library/thumbnailcache.hpp"
 
 namespace fwk {
@@ -48,38 +47,35 @@ public:
     // @return false in case of error.
     bool ok() const;
 
-    static eng::tid_t newTid();
     /** get all the keywords
-     * @return transaction ID
      */
-    eng::tid_t getAllKeywords();
+    void getAllKeywords();
     /** get all the folder
-     * @return transaction ID
      */
-    eng::tid_t getAllFolders();
+    void getAllFolders();
 
-    eng::tid_t queryFolderContent(eng::library_id_t id);
-    eng::tid_t queryKeywordContent(eng::library_id_t id);
-    eng::tid_t countFolder(eng::library_id_t id);
-    eng::tid_t requestMetadata(eng::library_id_t id);
+    void queryFolderContent(eng::library_id_t id);
+    void queryKeywordContent(eng::library_id_t id);
+    void countFolder(eng::library_id_t id);
+    void requestMetadata(eng::library_id_t id);
 
     /** set the metadata */
-    eng::tid_t setMetadata(eng::library_id_t id, fwk::PropertyIndex meta,
+    void setMetadata(eng::library_id_t id, fwk::PropertyIndex meta,
                            const fwk::PropertyValuePtr & value);
-    eng::tid_t moveFileToFolder(eng::library_id_t file_id, eng::library_id_t from_folder,
+    void moveFileToFolder(eng::library_id_t file_id, eng::library_id_t from_folder,
                                 eng::library_id_t to_folder);
-    eng::tid_t write_metadata(eng::library_id_t file_id);
+    void write_metadata(eng::library_id_t file_id);
 
     /** get all the labels */
-    eng::tid_t getAllLabels();
-    eng::tid_t createLabel(const std::string & s, const std::string & color);
-    eng::tid_t deleteLabel(int id);
+    void getAllLabels();
+    void createLabel(const std::string & s, const std::string & color);
+    void deleteLabel(int id);
     /** update a label */
-    eng::tid_t updateLabel(eng::library_id_t id, const std::string & new_name,
+    void updateLabel(eng::library_id_t id, const std::string & new_name,
                            const std::string & new_color);
 
     /** tell to process the Xmp update Queue */
-    eng::tid_t processXmpUpdateQueue(bool write_xmp);
+    void processXmpUpdateQueue(bool write_xmp);
 
     /** Import file
      * @param path the file path
diff --git a/src/engine/library/clienttypes.hpp b/src/libraryclient/mod.rs
similarity index 80%
rename from src/engine/library/clienttypes.hpp
rename to src/libraryclient/mod.rs
index 7a0e0e2..973f02e 100644
--- a/src/engine/library/clienttypes.hpp
+++ b/src/libraryclient/mod.rs
@@ -1,7 +1,7 @@
 /*
- * niepce - library/clienttypes.h
+ * niepce - libraryclient/mod.rs
  *
- * Copyright (C) 2007-2017 Hubert Figuiere
+ * Copyright (C) 2017 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,10 +17,4 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#pragma once
-
-namespace eng {
-
-typedef int32_t tid_t; /**< transaction ID */
-
-}
+pub mod clientimpl;
diff --git a/src/niepce/ui/dialogs/editlabels.cpp b/src/niepce/ui/dialogs/editlabels.cpp
index 4e20050..bb786f4 100644
--- a/src/niepce/ui/dialogs/editlabels.cpp
+++ b/src/niepce/ui/dialogs/editlabels.cpp
@@ -132,7 +132,10 @@ void EditLabels::update_labels(int /*response*/)
             } else {
                 undo->new_command<int>(
                     [libclient, new_name, new_colour] () {
-                        return libclient->createLabel(new_name, new_colour);
+                        libclient->createLabel(new_name, new_colour);
+                        return 0; // XXX this is wrong. This was wrong before/
+                        // We need to figure out how to get he new label id to be able
+                        // To cancel it.
                     },
                     [libclient] (int label) {
                         libclient->deleteLabel(label);
diff --git a/src/rust_bindings.hpp b/src/rust_bindings.hpp
index 26e91a8..6016971 100644
--- a/src/rust_bindings.hpp
+++ b/src/rust_bindings.hpp
@@ -53,7 +53,6 @@ typedef ffi::RgbColour RgbColour;
 namespace eng {
 typedef ffi::LibraryId library_id_t; // XXX change this to LibraryId
 typedef ffi::FileType FileType;
-typedef ffi::Library Library;
 typedef ffi::Keyword Keyword;
 typedef ffi::LibFile LibFile;
 typedef ffi::LibFolder LibFolder;



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