From 38a5fd7e8feb2e8c69ffb4dfd7d9acf1c8cad06f Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Wed, 20 Jul 2022 00:00:49 +0200
Subject: [PATCH] RUST: Should be able to link Rust code in lektord

---
 CMakeLists.txt                           | 38 ++++++++++++++------
 src/rust/.gitignore                      |  3 ++
 src/rust/liblektor-rs/.cargo/config.toml |  2 ++
 src/rust/liblektor-rs/Cargo.toml         | 10 ++++++
 src/rust/liblektor-rs/src/database.rs    | 45 ++++++++++++++++++++++++
 src/rust/liblektor-rs/src/lib.rs         |  8 +++++
 src/rust/liblektor-rs/src/mkv.rs         | 12 +++++++
 src/rust/rs_repo/.cargo/config.toml      |  2 ++
 src/rust/rs_repo/Cargo.toml              |  8 +++++
 src/rust/rs_repo/src/lib.rs              |  8 +++++
 10 files changed, 126 insertions(+), 10 deletions(-)
 create mode 100644 src/rust/.gitignore
 create mode 100644 src/rust/liblektor-rs/.cargo/config.toml
 create mode 100644 src/rust/liblektor-rs/Cargo.toml
 create mode 100644 src/rust/liblektor-rs/src/database.rs
 create mode 100644 src/rust/liblektor-rs/src/lib.rs
 create mode 100644 src/rust/liblektor-rs/src/mkv.rs
 create mode 100644 src/rust/rs_repo/.cargo/config.toml
 create mode 100644 src/rust/rs_repo/Cargo.toml
 create mode 100644 src/rust/rs_repo/src/lib.rs

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b87e20ce..a2293516 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,9 +16,10 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 set(THREADS_PREFER_PTHREAD_FLAG     ON)
 set(CMAKE_COLOR_MAKEFILE            ON)
 
-include(TestBigEndian)  # Needed for endianness tests
-include(FindOpenMP)     # Test OpenMP support
-include(GNUInstallDirs) # Needed for installation things
+include(TestBigEndian)   # Needed for endianness tests
+include(FindOpenMP)      # Test OpenMP support
+include(GNUInstallDirs)  # Needed for installation things
+include(ExternalProject) # Enable ExternalProject CMake module
 
 ###         ###
 # TEST OPENMP #
@@ -100,6 +101,7 @@ set(CMAKE_AUTORCC ON)
 
 find_program(MKVPROPEDIT mkvpropedit REQUIRED)   # To DL karas and apply metadata
 find_program(XXD         xxd         REQUIRED)   # To embed the sqlite db schemas into the binary
+find_program(CARGO       cargo       REQUIRED)   # For rust things
 
 message(STATUS "The installation prefix is ${CMAKE_INSTALL_PREFIX}")
 
@@ -333,17 +335,10 @@ target_include_directories(lektord PRIVATE
     ${CURL_INCLUDE_DIRS}
 )
 
-target_link_libraries(lektord PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
-
 target_compile_definitions(lektord PRIVATE ${common_DEFINITIONS})
 target_compile_definitions(lkt     PRIVATE ${common_DEFINITIONS})
 target_compile_definitions(luka    PRIVATE ${common_DEFINITIONS})
 
-# TODO: The common header should be the OS header...
-# target_precompile_headers(lektord  PRIVATE ${common_HEADERS})
-# target_precompile_headers(lkt      PRIVATE ${common_HEADERS})
-# target_precompile_headers(luka     PRIVATE ${common_HEADERS})
-
 target_compile_options(lektord PRIVATE ${COMMON_C_FLAGS} ${${CMAKE_C_COMPILER_ID}_C_FLAGS} ${${CMAKE_CXX_COMPILER_ID}_CXX_FLAGS})
 target_compile_definitions(lektord PRIVATE
     QT_DISABLE_DEPRECATED_BEFORE=0x050F00
@@ -358,6 +353,29 @@ target_compile_options(luka PRIVATE ${COMMON_C_FLAGS} ${${CMAKE_C_COMPILER_ID}_C
 set_property(TARGET lektord PROPERTY CXX_STANDARD 20)
 set_property(TARGET luka    PROPERTY CXX_STANDARD 20)
 
+set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/Rust)
+
+ExternalProject_Add(liblektor_rs
+    DOWNLOAD_COMMAND  ""
+    CONFIGURE_COMMAND ""
+    SOURCE_DIR        "${CMAKE_SOURCE_DIR}/src/rust/liblektor-rs"
+    BUILD_COMMAND     "${CARGO}" build
+    COMMAND           "${CARGO}" build
+    INSTALL_COMMAND   ""
+    BUILD_BYPRODUCTS  "${CMAKE_SOURCE_DIR}/src/rust/liblektor-rs/target/debug/liblektor_rs.a"
+    BUILD_ALWAYS      1
+    BUILD_IN_SOURCE   1
+    LOG_BUILD         1
+)
+
+add_dependencies(lektord liblektor_rs)
+
+target_link_libraries(lektord
+    PRIVATE
+    "${CMAKE_SOURCE_DIR}/src/rust/liblektor-rs/target/debug/liblektor_rs.a"
+    Qt${QT_VERSION_MAJOR}::Widgets
+)
+
 ###                    ###
 # THE INSTALL DIRECTIVES #
 ###                    ###
diff --git a/src/rust/.gitignore b/src/rust/.gitignore
new file mode 100644
index 00000000..f0041132
--- /dev/null
+++ b/src/rust/.gitignore
@@ -0,0 +1,3 @@
+target/
+.rustc_info.json
+Cargo.lock
diff --git a/src/rust/liblektor-rs/.cargo/config.toml b/src/rust/liblektor-rs/.cargo/config.toml
new file mode 100644
index 00000000..9823a4d5
--- /dev/null
+++ b/src/rust/liblektor-rs/.cargo/config.toml
@@ -0,0 +1,2 @@
+[build]
+target-dir = "target"
\ No newline at end of file
diff --git a/src/rust/liblektor-rs/Cargo.toml b/src/rust/liblektor-rs/Cargo.toml
new file mode 100644
index 00000000..5ffadb98
--- /dev/null
+++ b/src/rust/liblektor-rs/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name    = "lektor-rs"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = ["staticlib"]
+
+[dependencies]
+libc = "0.2.0"
diff --git a/src/rust/liblektor-rs/src/database.rs b/src/rust/liblektor-rs/src/database.rs
new file mode 100644
index 00000000..8ddcedc1
--- /dev/null
+++ b/src/rust/liblektor-rs/src/database.rs
@@ -0,0 +1,45 @@
+use crate::*;
+
+pub(crate) type LktDbPtr = *mut c_void;
+
+#[repr(C)]
+pub(crate) struct LktQueueState {
+    volume: c_int,
+    paused: c_int,
+    random: c_int,
+    repeat: c_int,
+    single: c_int,
+    current: c_int,
+    duration: c_int,
+    consume: c_int,
+    length: c_int,
+}
+
+extern "C" {
+    pub(crate) fn database_queue_toggle_pause(db: LktDbPtr) -> c_void;
+
+    /* Update stuff */
+    pub(crate) fn database_get_update(
+        db: LktDbPtr,
+        timestamp: *mut c_long,
+        job: *mut c_long,
+        current: *mut c_int,
+    ) -> c_void;
+    pub(crate) fn database_stamp(db: LktDbPtr) -> c_void;
+    pub(crate) fn database_updated(db: LktDbPtr) -> c_void;
+    pub(crate) fn database_deleted_kara(
+        db: LktDbPtr,
+        kara_id: *mut *mut c_int,
+        len: *mut size_t,
+    ) -> c_void;
+    pub(crate) fn database_total_playtime(db: LktDbPtr, seconds: *mut u64) -> c_void;
+
+    /* Get information on the queue and currently playing kara */
+    pub(crate) fn database_queue_state(db: LktDbPtr, res: *mut LktQueueState) -> bool;
+    pub(crate) fn database_queue_current_kara(
+        db: LktDbPtr,
+        res: *mut mkv::LktKaraMetadata,
+        id: *mut c_int,
+    ) -> bool;
+    pub(crate) fn database_queue_playtime(db: LktDbPtr, seconds: *mut u64) -> c_void;
+}
diff --git a/src/rust/liblektor-rs/src/lib.rs b/src/rust/liblektor-rs/src/lib.rs
new file mode 100644
index 00000000..40c8ae63
--- /dev/null
+++ b/src/rust/liblektor-rs/src/lib.rs
@@ -0,0 +1,8 @@
+#![allow(dead_code)]
+
+mod database;
+mod mkv;
+
+pub(crate) use libc::{c_char, c_int, c_long, c_void, size_t};
+
+pub const LEKTOR_TAG_MAX: usize = 256;
diff --git a/src/rust/liblektor-rs/src/mkv.rs b/src/rust/liblektor-rs/src/mkv.rs
new file mode 100644
index 00000000..3770013e
--- /dev/null
+++ b/src/rust/liblektor-rs/src/mkv.rs
@@ -0,0 +1,12 @@
+use crate::*;
+
+#[repr(C)]
+pub(crate) struct LktKaraMetadata {
+    song_name: [c_char; LEKTOR_TAG_MAX],
+    source_name: [c_char; LEKTOR_TAG_MAX],
+    category: [c_char; LEKTOR_TAG_MAX],
+    language: [c_char; LEKTOR_TAG_MAX],
+    author_name: [c_char; LEKTOR_TAG_MAX],
+    song_type: [c_char; LEKTOR_TAG_MAX],
+    song_number: c_int,
+}
diff --git a/src/rust/rs_repo/.cargo/config.toml b/src/rust/rs_repo/.cargo/config.toml
new file mode 100644
index 00000000..9823a4d5
--- /dev/null
+++ b/src/rust/rs_repo/.cargo/config.toml
@@ -0,0 +1,2 @@
+[build]
+target-dir = "target"
\ No newline at end of file
diff --git a/src/rust/rs_repo/Cargo.toml b/src/rust/rs_repo/Cargo.toml
new file mode 100644
index 00000000..82627373
--- /dev/null
+++ b/src/rust/rs_repo/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name    = "rs_repo"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+lib_lkt_rs = { path = "../lektord-rs" }
+libc       = "0.2.0"
diff --git a/src/rust/rs_repo/src/lib.rs b/src/rust/rs_repo/src/lib.rs
new file mode 100644
index 00000000..1b4a90c9
--- /dev/null
+++ b/src/rust/rs_repo/src/lib.rs
@@ -0,0 +1,8 @@
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn it_works() {
+        let result = 2 + 2;
+        assert_eq!(result, 4);
+    }
+}
-- 
GitLab