diff --git a/Cargo.toml b/Cargo.toml index 97489b6..853e18e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,12 @@ -workspace = { members = [ "sdk/rust","dim_plugins/example_rust", "dim_plugins/clock", "dim_plugins/counter", "dim_plugins/battery"] } +[workspace] +members = [ + "sdk/rust/dim_sdk", + "dim_plugins/example_rust", + "dim_plugins/clock", + "dim_plugins/counter", + "dim_plugins/battery", +] + [package] name = "dim" version = "0.1.0" diff --git a/compile_commands.json b/compile_commands.json index d4490f2..9da0ed5 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -1,14 +1,14 @@ [ { - "directory": "/home/xomf/git-stuff/dim2/dim/dim_plugins/example_c", + "directory": "/home/mcorange/.dwm/sources/dim/dim_plugins/example_c", "arguments": [ "gcc", "-c", "-o", - "/home/xomf/git-stuff/dim2/dim/target/objects/example_c/main.o", + "/home/mcorange/.dwm/sources/dim/target/objects/example_c/main.o", "src/main.c", "-pie", - "-I/home/xomf/git-stuff/dim2/dim/sdk/c_cxx", + "-I/home/mcorange/.dwm/sources/dim/sdk/c_cxx", "-fPIC" ], "file": "src/main.c" diff --git a/dim_plugins/battery/Cargo.toml b/dim_plugins/battery/Cargo.toml index abd9a7c..a4bc6a1 100644 --- a/dim_plugins/battery/Cargo.toml +++ b/dim_plugins/battery/Cargo.toml @@ -8,5 +8,5 @@ crate-type=["cdylib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -dim_sdk = {path="../../sdk/rust/"} -lazy_static = "1.4.0" \ No newline at end of file +dim_sdk = {path="../../sdk/rust/dim_sdk"} +lazy_static = "1.4.0" diff --git a/dim_plugins/battery/src/lib.rs b/dim_plugins/battery/src/lib.rs index 2b3e0cd..ee5fb6b 100644 --- a/dim_plugins/battery/src/lib.rs +++ b/dim_plugins/battery/src/lib.rs @@ -1,5 +1,5 @@ use std::fmt::Write; -use dim_sdk::{plugin_info, DimPlugin}; +use dim_sdk::{plugin_info, Context, DimPlugin}; use std::fs::read_to_string; plugin_info!( @@ -20,7 +20,7 @@ impl Plug { } impl DimPlugin for Plug { - fn init(&mut self) { + fn init(&mut self, _ctx: Context) { } fn poll(&mut self, f: &mut dim_sdk::CBuffer) -> dim_sdk::Result<()> { let contents = read_to_string("/sys/class/power_supply/BAT0/capacity")?; diff --git a/dim_plugins/clock/Cargo.toml b/dim_plugins/clock/Cargo.toml index 21b2a21..b1319e8 100644 --- a/dim_plugins/clock/Cargo.toml +++ b/dim_plugins/clock/Cargo.toml @@ -9,6 +9,6 @@ crate-type=["cdylib"] [dependencies] chrono = "0.4.38" -dim_sdk = {path="../../sdk/rust/"} +dim_sdk = {path="../../sdk/rust/dim_sdk"} lazy_static = "1.4.0" log = "0.4.21" diff --git a/dim_plugins/clock/src/lib.rs b/dim_plugins/clock/src/lib.rs index 9da2601..41f3cd5 100644 --- a/dim_plugins/clock/src/lib.rs +++ b/dim_plugins/clock/src/lib.rs @@ -1,13 +1,14 @@ use std::fmt::Write; use chrono::prelude::*; -use dim_sdk::{plugin_info, DimPlugin}; +use dim_sdk::{plugin_info, Context, DimPlugin}; plugin_info!( Plug, // Your main global structs name that implements `DimPlugin` "clock", // Plugin name "0.0.0", // Plugin Version (leave empty for none) "GPLv3" // Plugin license (leave empty for none) - ); +); + struct Plug { } @@ -20,9 +21,7 @@ impl Plug { } impl DimPlugin for Plug { - fn init(&mut self) { - } - + fn init(&mut self, _ctx: Context) {} fn poll(&mut self, f: &mut dim_sdk::CBuffer) -> dim_sdk::Result<()> { let local: DateTime = Local::now(); let formatted_time = local.format("%H:%M (%Y-%m-%d)").to_string(); @@ -30,14 +29,9 @@ impl DimPlugin for Plug { write!(f, "Time: {}", formatted_time)?; Ok(()) } - fn pre_reload(&mut self) { - - } - fn post_reload(&mut self) { - - } - fn free(&mut self) { - } + fn pre_reload(&mut self) {} + fn post_reload(&mut self) {} + fn free(&mut self) {} } diff --git a/dim_plugins/counter/Cargo.toml b/dim_plugins/counter/Cargo.toml index 6369347..d162f52 100644 --- a/dim_plugins/counter/Cargo.toml +++ b/dim_plugins/counter/Cargo.toml @@ -9,5 +9,5 @@ crate-type=["cdylib"] [dependencies] chrono = "0.4.38" -dim_sdk = {path="../../sdk/rust/"} +dim_sdk = {path="../../sdk/rust/dim_sdk"} lazy_static = "1.4.0" diff --git a/dim_plugins/counter/src/lib.rs b/dim_plugins/counter/src/lib.rs index 99049b8..b8266c5 100644 --- a/dim_plugins/counter/src/lib.rs +++ b/dim_plugins/counter/src/lib.rs @@ -1,5 +1,5 @@ use std::fmt::Write; -use dim_sdk::{plugin_info, DimPlugin}; +use dim_sdk::{plugin_info, Context, DimPlugin}; use chrono::{NaiveDate, Local}; plugin_info!( @@ -21,7 +21,7 @@ impl Plug { } impl DimPlugin for Plug { - fn init(&mut self) {} + fn init(&mut self, _ctx: Context) {} fn poll(&mut self, f: &mut dim_sdk::CBuffer) -> dim_sdk::Result<()> { let start_date = NaiveDate::from_ymd_opt(2024, 3, 8).expect("Invalid date"); diff --git a/dim_plugins/example_c/src/main.c b/dim_plugins/example_c/src/main.c index 99eb7bf..428458a 100644 --- a/dim_plugins/example_c/src/main.c +++ b/dim_plugins/example_c/src/main.c @@ -13,7 +13,8 @@ typedef struct plug_t { plug_t* p = {0}; -void plug_init() { +void plug_init(plug_ctx_t* ctx) { + (void) ctx; p = malloc(sizeof(plug_t)); assert(p != NULL && "Buy more ram KEKW"); p->count = 0; diff --git a/dim_plugins/example_rust/Cargo.toml b/dim_plugins/example_rust/Cargo.toml index f40ff42..730ee59 100644 --- a/dim_plugins/example_rust/Cargo.toml +++ b/dim_plugins/example_rust/Cargo.toml @@ -8,5 +8,5 @@ crate-type=["cdylib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -dim_sdk = {path="../../sdk/rust/"} -lazy_static = "1.4.0" \ No newline at end of file +dim_sdk = {path="../../sdk/rust/dim_sdk"} +lazy_static = "1.4.0" diff --git a/dim_plugins/example_rust/src/lib.rs b/dim_plugins/example_rust/src/lib.rs index f9a5257..022bc1e 100644 --- a/dim_plugins/example_rust/src/lib.rs +++ b/dim_plugins/example_rust/src/lib.rs @@ -1,5 +1,5 @@ use std::fmt::Write; -use dim_sdk::{plugin_info, DimPlugin}; +use dim_sdk::{plugin_info, Context, DimPlugin}; plugin_info!( Plug, // Your main global structs name that implements `DimPlugin` @@ -21,7 +21,7 @@ impl Plug { } impl DimPlugin for Plug { - fn init(&mut self) { + fn init(&mut self, _ctx: Context) { // Initialise data, this will run once, it will not run again after reload } fn poll(&mut self, f: &mut dim_sdk::CBuffer) -> dim_sdk::Result<()> { diff --git a/sdk/c_cxx/dim_sdk.h b/sdk/c_cxx/dim_sdk.h index f5053ad..dfa026f 100644 --- a/sdk/c_cxx/dim_sdk.h +++ b/sdk/c_cxx/dim_sdk.h @@ -10,6 +10,10 @@ typedef struct plug_info_t { char* license; } plug_info_t; +typedef struct plug_ctx_t { + char* config_dir; +} plug_ctx_t; + #define PLUG_INFO(_name, _version, _license) \ static plug_info_t PLUG_INFO_VAR = { .name=(_name), .version=(_version), .license=(_license)}; \ void* plug_get_info() { \ @@ -22,7 +26,7 @@ void* plug_get_info() { \ #define PLUG_LICENSE(s) volatile char* PLUG_LICENSE = (s); -void plug_init(); // Loads when DIM initialises +void plug_init(plug_ctx_t*); // Loads when DIM initialises void* plug_pre_reload(); // Return a pointer to save state void plug_post_reload(void*); // returns the same pointer after reload void plug_poll(char*, size_t); // Write the message to `buf` with max `size` characters diff --git a/sdk/rust/Cargo.toml b/sdk/rust/dim_sdk/Cargo.toml similarity index 100% rename from sdk/rust/Cargo.toml rename to sdk/rust/dim_sdk/Cargo.toml diff --git a/sdk/rust/src/c_buffer.rs b/sdk/rust/dim_sdk/src/c_buffer.rs similarity index 100% rename from sdk/rust/src/c_buffer.rs rename to sdk/rust/dim_sdk/src/c_buffer.rs diff --git a/sdk/rust/dim_sdk/src/context.rs b/sdk/rust/dim_sdk/src/context.rs new file mode 100644 index 0000000..2f3eef7 --- /dev/null +++ b/sdk/rust/dim_sdk/src/context.rs @@ -0,0 +1,25 @@ +use std::{ffi::{c_char, CStr}, path::PathBuf}; + + +#[repr(C)] +pub struct ContextRaw { + pub config_dir: *const c_char +} + +#[derive(Debug, Clone)] +pub struct Context { + pub config_dir: PathBuf +} + +impl Context { + pub fn new(cr: *const ContextRaw) -> Self { + let config_dir = unsafe { + let v = CStr::from_ptr((*cr).config_dir); + PathBuf::from(v.to_string_lossy().to_string()) + }; + + Self { + config_dir + } + } +} diff --git a/sdk/rust/src/lib.rs b/sdk/rust/dim_sdk/src/lib.rs similarity index 80% rename from sdk/rust/src/lib.rs rename to sdk/rust/dim_sdk/src/lib.rs index 2a6688f..8b4fbf5 100644 --- a/sdk/rust/src/lib.rs +++ b/sdk/rust/dim_sdk/src/lib.rs @@ -4,14 +4,15 @@ mod magic; mod c_buffer; mod plugin_info; +mod context; pub use c_buffer::*; pub use plugin_info::*; - pub use anyhow::Result; +pub use context::*; pub trait DimPlugin { - fn init(&mut self); + fn init(&mut self, ctx: Context); fn pre_reload(&mut self); fn post_reload(&mut self); fn poll(&mut self, f: &mut CBuffer) -> Result<()>; @@ -23,3 +24,4 @@ pub trait DimPlugin { + diff --git a/sdk/rust/src/magic.rs b/sdk/rust/dim_sdk/src/magic.rs similarity index 90% rename from sdk/rust/src/magic.rs rename to sdk/rust/dim_sdk/src/magic.rs index b1153df..8256fc8 100644 --- a/sdk/rust/src/magic.rs +++ b/sdk/rust/dim_sdk/src/magic.rs @@ -15,10 +15,12 @@ macro_rules! plugin_info { } #[no_mangle] - unsafe extern "C" fn plug_init() { + unsafe extern "C" fn plug_init(ctx: *const $crate::ContextRaw) { PLUG = std::alloc::alloc(std::alloc::Layout::new::<$typ>()) as *mut $typ; *PLUG = Plug::new(); - (&mut *PLUG).init(); + + let ctx = $crate::Context::new(ctx); + (&mut *PLUG).init(ctx); } #[no_mangle] diff --git a/sdk/rust/src/plugin_info.rs b/sdk/rust/dim_sdk/src/plugin_info.rs similarity index 100% rename from sdk/rust/src/plugin_info.rs rename to sdk/rust/dim_sdk/src/plugin_info.rs diff --git a/src/config.rs b/src/config.rs index 01a5779..f68727a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -21,14 +21,14 @@ pub struct ConfigPlugins { impl Config { pub fn new(path: &Path) -> Result { - let path = path.join("main.toml"); + let cfg_path = path.join("main.toml"); - if !path.exists() { + if !cfg_path.exists() { println!("ERROR: {:?} doesnt exist", path); } let mut cfg: Self = toml::from_str( - &std::fs::read_to_string(&path)? + &std::fs::read_to_string(&cfg_path)? )?; cfg.config_dir = path.to_path_buf(); diff --git a/src/main.rs b/src/main.rs index 943b550..fd5810f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,13 @@ #![allow(internal_features)] #![feature(core_intrinsics)] -use std::{process::ExitCode, time::Duration}; - +use std::{ffi::c_char, process::ExitCode, time::Duration}; use clap::Parser; mod display; mod plugman; mod config; +mod util; #[derive(Debug, Parser)] struct CliArgs { @@ -19,6 +19,8 @@ struct CliArgs { pub debug: bool } +#[allow(non_camel_case_types)] +pub type c_str = *const c_char; // TODO: Clean up main function // TODO: Make ffi safe abstraction for logger @@ -57,7 +59,7 @@ fn main() -> ExitCode { return ExitCode::from(3); } - pm.init_plugins(); + pm.init_plugins(&config); loop { let vals = pm.poll_plugins(); diff --git a/src/plugman/mod.rs b/src/plugman/mod.rs index 257adf9..66be77b 100644 --- a/src/plugman/mod.rs +++ b/src/plugman/mod.rs @@ -49,9 +49,9 @@ impl PlugMan { Ok(()) } - pub fn init_plugins(&mut self) { + pub fn init_plugins(&mut self, cfg: &crate::config::Config) { for plugin in &self.plugins { - plugin.init(); + plugin.init(cfg); } } diff --git a/src/plugman/plugin/context.rs b/src/plugman/plugin/context.rs new file mode 100644 index 0000000..bd74d38 --- /dev/null +++ b/src/plugman/plugin/context.rs @@ -0,0 +1,31 @@ +use std::ffi::{c_char, CString}; + +pub struct PluginContextContainer { + pub inner: PluginContext, + _config_dir: CString +} + + +#[repr(C)] +pub struct PluginContext { + pub config_dir: *const c_char +} + +impl PluginContext { + pub fn new(config_dir: &CString) -> Self { + Self { + config_dir: config_dir.as_ptr() + } + } +} + + +impl PluginContextContainer { + pub fn new(config_dir: &String) -> Self { + let _config_dir = CString::new(config_dir.clone()).unwrap(); + Self { + inner: PluginContext::new(&_config_dir), + _config_dir, + } + } +} diff --git a/src/plugman/plugin/loader.rs b/src/plugman/plugin/loader.rs new file mode 100644 index 0000000..38add1a --- /dev/null +++ b/src/plugman/plugin/loader.rs @@ -0,0 +1,42 @@ +use std::ffi::c_char; + +use dlopen::raw::Library; + +use super::{context::PluginContext, Plugin, PluginInfo}; + + +#[derive(Debug, Clone, Copy)] +pub struct PluginSyms { + pub(super) init: unsafe extern "C" fn(ctx: *const PluginContext), + pub(super) pre_reload: unsafe extern "C" fn() -> *const (), + pub(super) post_reload: unsafe extern "C" fn(state: *const ()), + pub(super) poll: unsafe extern "C" fn(buf: *mut c_char, len: usize), + pub(super) free: unsafe extern "C" fn(), + pub(super) get_info: unsafe extern "C" fn() -> *const PluginInfo, +} + +impl Plugin { + pub fn reload_symbols(&mut self) -> Result<(), dlopen::Error> { + log::debug!("Loading {:?}", self.path); + let lib = Library::open(&self.path)?; + let symbols = PluginSyms { + init: unsafe { lib.symbol("plug_init")? }, + pre_reload: unsafe { lib.symbol("plug_pre_reload")? }, + post_reload: unsafe { lib.symbol("plug_post_reload")? }, + poll: unsafe { lib.symbol("plug_poll")? }, + free: unsafe { lib.symbol("plug_free")? }, + + get_info: unsafe { lib.symbol("plug_get_info")? }, + }; + unsafe { + if (symbols.get_info)().is_null() { + log::error!("Info fields for plugin {:?} are null", self.path); + self.disable(); + } + } + + self.syms = Some(symbols); + self.lib = Some(lib); + Ok(()) + } +} diff --git a/src/plugman/plugin.rs b/src/plugman/plugin/mod.rs similarity index 63% rename from src/plugman/plugin.rs rename to src/plugman/plugin/mod.rs index ec70d59..e209015 100644 --- a/src/plugman/plugin.rs +++ b/src/plugman/plugin/mod.rs @@ -2,32 +2,30 @@ use std::{alloc::Layout, ffi::{c_char, CStr}, path::PathBuf}; use dlopen::raw::Library; -#[derive(Debug, Clone, Copy,)] -pub struct PluginSyms { - init: unsafe extern "C" fn(), - pre_reload: unsafe extern "C" fn() -> *const (), - post_reload: unsafe extern "C" fn(state: *const ()), - poll: unsafe extern "C" fn(buf: *mut i8, len: usize), - free: unsafe extern "C" fn(), - get_info: unsafe extern "C" fn() -> *const PluginInfo, -} +use crate::{c_str, config::Config}; + +use self::context::{PluginContext, PluginContextContainer}; + +pub mod loader; +pub mod context; #[repr(C)] pub struct PluginInfo { - name: *const c_char, - version: *const c_char, - license: *const c_char, + name: c_str, + version: c_str, + license: c_str, } #[derive(Debug, Default)] pub struct Plugin { - syms: Option, + syms: Option, path: PathBuf, lib: Option, enabled: bool, } + impl Plugin { pub fn load(path: PathBuf) -> Result { let mut s = Self::default(); @@ -36,37 +34,17 @@ impl Plugin { s.reload_symbols()?; Ok(s) } - - fn reload_symbols(&mut self) -> Result<(), dlopen::Error> { - log::debug!("Loading {:?}", self.path); - let lib = Library::open(&self.path)?; - let symbols = PluginSyms { - init: unsafe { lib.symbol("plug_init")? }, - pre_reload: unsafe { lib.symbol("plug_pre_reload")? }, - post_reload: unsafe { lib.symbol("plug_post_reload")? }, - poll: unsafe { lib.symbol("plug_poll")? }, - free: unsafe { lib.symbol("plug_free")? }, - - get_info: unsafe { lib.symbol("plug_get_info")? }, - }; - unsafe { - if (symbols.get_info)().is_null() { - log::error!("Info fields for plugin {:?} are null", self.path); - self.disable(); - } - } - - self.syms = Some(symbols); - self.lib = Some(lib); - Ok(()) - } - pub fn syms(&self) -> PluginSyms { + + pub fn syms(&self) -> loader::PluginSyms { self.syms.unwrap() } - pub fn init(&self) { + pub fn init(&self, cfg: &Config) { unsafe { - (self.syms().init)() + let conf_dir = &cfg.config_dir.join(self.name()).to_string_lossy().to_string(); + + let ctx = PluginContextContainer::new(conf_dir); + (self.syms().init)(&ctx.inner as *const PluginContext) } } pub fn reload(&mut self) -> Result<(), dlopen::Error> { diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..e69de29