Compare commits
No commits in common. "6dd22fe0c31624d5756ff3c146bce19a59994749" and "7f6920507cc844664863363f29bb2a79ef208d6b" have entirely different histories.
6dd22fe0c3
...
7f6920507c
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,6 +1,4 @@
|
||||||
/target
|
/target
|
||||||
/plugins
|
/plugins
|
||||||
/.cache
|
/.cache
|
||||||
/config/*
|
|
||||||
!/config/main.template.toml
|
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
|
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -592,18 +592,6 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "volume"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"dim_sdk",
|
|
||||||
"lazy_static",
|
|
||||||
"regex",
|
|
||||||
"serde",
|
|
||||||
"toml",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.92"
|
version = "0.2.92"
|
||||||
|
|
|
@ -5,7 +5,6 @@ members = [
|
||||||
"dim_plugins/clock",
|
"dim_plugins/clock",
|
||||||
"dim_plugins/counter",
|
"dim_plugins/counter",
|
||||||
"dim_plugins/battery",
|
"dim_plugins/battery",
|
||||||
"dim_plugins/volume",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
|
|
55
\
55
\
|
@ -1,55 +0,0 @@
|
||||||
// Lord have mercy on me
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! plugin_info {
|
|
||||||
($typ:ty, $name:literal, $version:literal, $license:literal) => {
|
|
||||||
|
|
||||||
lazy_static::lazy_static!(
|
|
||||||
static ref PLUGIN_INFO: $crate::PluginInfo = $crate::PluginInfo::new($name, $version, $license);
|
|
||||||
);
|
|
||||||
|
|
||||||
static mut PLUG: *mut $typ = std::ptr::null_mut() as *mut $typ;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern "C" fn plug_get_info() -> *const std::ffi::c_void {
|
|
||||||
PLUGIN_INFO.get_raw_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern "C" fn plug_init(ctx: *const $crate::ContextRaw) {
|
|
||||||
PLUG = std::alloc::alloc(std::alloc::Layout::new::<$typ>()) as *mut $typ;
|
|
||||||
*PLUG = <$typ>::new();
|
|
||||||
|
|
||||||
let ctx = $crate::Context::new(ctx);
|
|
||||||
(&mut *PLUG).init(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern "C" fn plug_pre_reload() -> *mut $typ {
|
|
||||||
//TODO: Untested
|
|
||||||
(&mut *PLUG).pre_reload();
|
|
||||||
return PLUG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern "C" fn plug_post_reload(state: *mut $typ) {
|
|
||||||
//TODO: Untested
|
|
||||||
PLUG = state;
|
|
||||||
(&mut *PLUG).post_reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern "C" fn plug_poll(buf: *mut i8, len: std::ffi::c_uint) {
|
|
||||||
let mut buf = $crate::CBuffer::from_raw_parts_mut(buf, len as usize);
|
|
||||||
if let Err(_e) = (&mut *PLUG).poll(&mut buf) {
|
|
||||||
// TODO: Handle error maybe?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern "C" fn plug_free() {
|
|
||||||
std::alloc::dealloc(PLUG as *mut u8, std::alloc::Layout::new::<$typ>());
|
|
||||||
(&mut *PLUG).free();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -5,11 +5,10 @@ use std::fs::read_to_string;
|
||||||
plugin_info!(
|
plugin_info!(
|
||||||
Plug, // Your main global structs name that implements `DimPlugin`
|
Plug, // Your main global structs name that implements `DimPlugin`
|
||||||
"battery", // Plugin name
|
"battery", // Plugin name
|
||||||
"1.0.0", // Plugin Version (leave empty for none)
|
"0.0.0", // Plugin Version (leave empty for none)
|
||||||
"GPLv3" // Plugin license (leave empty for none)
|
"GPLv3" // Plugin license (leave empty for none)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Plug {
|
struct Plug {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@ use dim_sdk::{plugin_info, Context, DimPlugin};
|
||||||
plugin_info!(
|
plugin_info!(
|
||||||
Plug, // Your main global structs name that implements `DimPlugin`
|
Plug, // Your main global structs name that implements `DimPlugin`
|
||||||
"clock", // Plugin name
|
"clock", // Plugin name
|
||||||
"1.0.0", // Plugin Version (leave empty for none)
|
"0.0.0", // Plugin Version (leave empty for none)
|
||||||
"GPLv3" // Plugin license (leave empty for none)
|
"GPLv3" // Plugin license (leave empty for none)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Plug {
|
struct Plug {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,10 @@ use chrono::{NaiveDate, Local};
|
||||||
plugin_info!(
|
plugin_info!(
|
||||||
Plug, // Your main global structs name that implements `DimPlugin`
|
Plug, // Your main global structs name that implements `DimPlugin`
|
||||||
"counter", // Plugin name
|
"counter", // Plugin name
|
||||||
"1.0.0", // Plugin Version (leave empty for none)
|
"0.0.0", // Plugin Version (leave empty for none)
|
||||||
"GPLv3" // Plugin license (leave empty for none)
|
"GPLv3" // Plugin license (leave empty for none)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Plug {
|
struct Plug {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ plugin_info!(
|
||||||
"GPLv3" // Plugin license (leave empty for none)
|
"GPLv3" // Plugin license (leave empty for none)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Plug {
|
struct Plug {
|
||||||
counter: usize,
|
counter: usize,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "volume"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type=["cdylib"]
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
anyhow = "1.0.86"
|
|
||||||
dim_sdk = {path="../../sdk/rust/dim_sdk"}
|
|
||||||
lazy_static = "1.4.0"
|
|
||||||
regex = "1.10.5"
|
|
||||||
serde = { version = "1.0.203", features = ["derive"] }
|
|
||||||
toml = "0.8.14"
|
|
|
@ -1,17 +0,0 @@
|
||||||
# Must match package name in Cargo.toml
|
|
||||||
PLUGIN_NAME=volume
|
|
||||||
# `release` or `debug`
|
|
||||||
TYPE=release
|
|
||||||
|
|
||||||
build: $(PLUGIN_DIR)/$(PLUGIN_NAME).dim
|
|
||||||
|
|
||||||
$(PLUGIN_DIR)/$(PLUGIN_NAME).dim: $(OBJECT_DIR)/$(PLUGIN_NAME)/$(TYPE)/lib$(PLUGIN_NAME).so
|
|
||||||
@mkdir -p $(dir $@)
|
|
||||||
cp $^ $@
|
|
||||||
|
|
||||||
$(OBJECT_DIR)/$(PLUGIN_NAME)/$(TYPE)/lib$(PLUGIN_NAME).so:
|
|
||||||
@mkdir -p $(dir $@)
|
|
||||||
cargo build --release --target-dir $(OBJECT_DIR)/$(PLUGIN_NAME)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[commands]
|
|
||||||
get_volume="pactl get-sink-volume @DEFAULT_SINK@"
|
|
||||||
get_volume_regex=".* (?<vol>[0-9]{1,3})%.*"
|
|
|
@ -1,37 +0,0 @@
|
||||||
use std::path::Path;
|
|
||||||
use anyhow::Result;
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
const DEFAULT_CFG: &'static str = include_str!("../config.template.toml");
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
|
||||||
pub struct Config {
|
|
||||||
pub commands: ConfigCommands,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
|
||||||
pub struct ConfigCommands {
|
|
||||||
pub get_volume: String,
|
|
||||||
pub get_volume_regex: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config {
|
|
||||||
pub fn parse(p: &Path) -> Result<Self> {
|
|
||||||
if !p.exists() {
|
|
||||||
std::fs::write(p, DEFAULT_CFG)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let c = std::fs::read_to_string(p)?;
|
|
||||||
Ok(toml::from_str(c.as_str())?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
commands: ConfigCommands {
|
|
||||||
get_volume: String::new(),
|
|
||||||
get_volume_regex: String::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
use std::{fmt::Write, path::PathBuf, process::Stdio};
|
|
||||||
use dim_sdk::{plugin_info, Context, DimPlugin};
|
|
||||||
use std::fs::read_to_string;
|
|
||||||
|
|
||||||
mod config;
|
|
||||||
|
|
||||||
plugin_info!(
|
|
||||||
Plug, // Your main global structs name that implements `DimPlugin`
|
|
||||||
"volume", // Plugin name
|
|
||||||
"1.0.0", // Plugin Version (leave empty for none)
|
|
||||||
"GPLv3" // Plugin license (leave empty for none)
|
|
||||||
);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Plug {
|
|
||||||
cfg: config::Config,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Plug {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
cfg: config::Config::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DimPlugin for Plug {
|
|
||||||
fn init(&mut self, ctx: Context) {
|
|
||||||
match config::Config::parse(&ctx.config_dir.join("config.toml")) {
|
|
||||||
Ok(c) => self.cfg = c,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("ERROR: Failed to open config file: {e}");
|
|
||||||
// TODO: Add function to disable the plugin
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn poll(&mut self, f: &mut dim_sdk::CBuffer) -> dim_sdk::Result<()> {
|
|
||||||
let mut proc = {
|
|
||||||
let mut p = std::process::Command::new("sh");
|
|
||||||
p.arg("-c");
|
|
||||||
p.arg(&self.cfg.commands.get_volume);
|
|
||||||
p.stdout(Stdio::piped());
|
|
||||||
p
|
|
||||||
};
|
|
||||||
|
|
||||||
let output = String::from_utf8(proc.output()?.stdout)?;
|
|
||||||
let re = regex::Regex::new(&self.cfg.commands.get_volume_regex)?;
|
|
||||||
|
|
||||||
if let Some(caps) = re.captures(&output) {
|
|
||||||
let volume = &caps["vol"];
|
|
||||||
write!(f, "Vol: {volume}%")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn pre_reload(&mut self) {
|
|
||||||
}
|
|
||||||
fn post_reload(&mut self) {
|
|
||||||
|
|
||||||
}
|
|
||||||
fn free(&mut self) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod magic;
|
mod magic;
|
||||||
mod c_buffer;
|
mod c_buffer;
|
||||||
|
@ -10,7 +11,7 @@ pub use plugin_info::*;
|
||||||
pub use anyhow::Result;
|
pub use anyhow::Result;
|
||||||
pub use context::*;
|
pub use context::*;
|
||||||
|
|
||||||
pub trait DimPlugin: Clone {
|
pub trait DimPlugin {
|
||||||
fn init(&mut self, ctx: Context);
|
fn init(&mut self, ctx: Context);
|
||||||
fn pre_reload(&mut self);
|
fn pre_reload(&mut self);
|
||||||
fn post_reload(&mut self);
|
fn post_reload(&mut self);
|
||||||
|
|
|
@ -7,7 +7,7 @@ macro_rules! plugin_info {
|
||||||
static ref PLUGIN_INFO: $crate::PluginInfo = $crate::PluginInfo::new($name, $version, $license);
|
static ref PLUGIN_INFO: $crate::PluginInfo = $crate::PluginInfo::new($name, $version, $license);
|
||||||
);
|
);
|
||||||
|
|
||||||
static mut PLUG: Option<$typ> = None as Option<$typ>;
|
static mut PLUG: *mut $typ = std::ptr::null_mut() as *mut $typ;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn plug_get_info() -> *const std::ffi::c_void {
|
unsafe extern "C" fn plug_get_info() -> *const std::ffi::c_void {
|
||||||
|
@ -16,59 +16,39 @@ macro_rules! plugin_info {
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn plug_init(ctx: *const $crate::ContextRaw) {
|
unsafe extern "C" fn plug_init(ctx: *const $crate::ContextRaw) {
|
||||||
//PLUG = std::alloc::alloc(std::alloc::Layout::new::<$typ>()) as *mut $typ;
|
PLUG = std::alloc::alloc(std::alloc::Layout::new::<$typ>()) as *mut $typ;
|
||||||
PLUG = Some(Plug::new());
|
*PLUG = Plug::new();
|
||||||
|
|
||||||
let ctx = $crate::Context::new(ctx);
|
let ctx = $crate::Context::new(ctx);
|
||||||
if let Some(p) = &mut PLUG {
|
(&mut *PLUG).init(ctx);
|
||||||
p.init(ctx)
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn plug_pre_reload() -> *mut $typ {
|
unsafe extern "C" fn plug_pre_reload() -> *mut $typ {
|
||||||
//TODO: Untested
|
//TODO: Untested
|
||||||
if let Some(p) = &mut PLUG {
|
(&mut *PLUG).pre_reload();
|
||||||
p.pre_reload();
|
return PLUG;
|
||||||
return p as *mut $typ;
|
|
||||||
}
|
|
||||||
unreachable!();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn plug_post_reload(state: *mut $typ) {
|
unsafe extern "C" fn plug_post_reload(state: *mut $typ) {
|
||||||
PLUG = Some((*state).clone());
|
//TODO: Untested
|
||||||
|
PLUG = state;
|
||||||
if let Some(p) = &mut PLUG {
|
(&mut *PLUG).post_reload();
|
||||||
p.post_reload();
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
//TODO: Untested
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn plug_poll(buf: *mut i8, len: std::ffi::c_uint) {
|
unsafe extern "C" fn plug_poll(buf: *mut i8, len: std::ffi::c_uint) {
|
||||||
let mut buf = $crate::CBuffer::from_raw_parts_mut(buf, len as usize);
|
let mut buf = $crate::CBuffer::from_raw_parts_mut(buf, len as usize);
|
||||||
if let Some(p) = &mut PLUG {
|
if let Err(_e) = (&mut *PLUG).poll(&mut buf) {
|
||||||
if let Err(_e) = p.poll(&mut buf) {
|
// TODO: Handle error maybe?
|
||||||
// TODO: Handle error maybe?
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn plug_free() {
|
unsafe extern "C" fn plug_free() {
|
||||||
if let Some(p) = &mut PLUG {
|
std::alloc::dealloc(PLUG as *mut u8, std::alloc::Layout::new::<$typ>());
|
||||||
// std::alloc::dealloc(PLUG as *mut u8, std::alloc::Layout::new::<$typ>());
|
(&mut *PLUG).free();
|
||||||
p.free();
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,7 +26,6 @@ pub type c_str = *const c_char;
|
||||||
// TODO: Make ffi safe abstraction for logger
|
// TODO: Make ffi safe abstraction for logger
|
||||||
// TODO: Set up ipc with unix sockets
|
// TODO: Set up ipc with unix sockets
|
||||||
// TODO: Allow sending messages command -> running DIM instance -> plugin with ipc
|
// TODO: Allow sending messages command -> running DIM instance -> plugin with ipc
|
||||||
// TODO: Clickable bar: https://dwm.suckless.org/patches/statuscmd/
|
|
||||||
// TODO: Run code through clippy
|
// TODO: Run code through clippy
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
let ca = CliArgs::parse();
|
let ca = CliArgs::parse();
|
||||||
|
|
|
@ -40,11 +40,10 @@ impl Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(&self, cfg: &Config) {
|
pub fn init(&self, cfg: &Config) {
|
||||||
let conf_dir = &cfg.config_dir.join(self.name()).to_string_lossy().to_string();
|
|
||||||
let _ = std::fs::create_dir(&conf_dir); // dont care
|
|
||||||
let ctx = PluginContextContainer::new(conf_dir);
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
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)
|
(self.syms().init)(&ctx.inner as *const PluginContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user