diff --git a/dim_plugins/volume/Cargo.toml b/dim_plugins/volume/Cargo.toml new file mode 100644 index 0000000..f429b4e --- /dev/null +++ b/dim_plugins/volume/Cargo.toml @@ -0,0 +1,16 @@ +[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" diff --git a/dim_plugins/volume/Makefile b/dim_plugins/volume/Makefile new file mode 100644 index 0000000..87c482a --- /dev/null +++ b/dim_plugins/volume/Makefile @@ -0,0 +1,17 @@ +# 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) + + + diff --git a/dim_plugins/volume/config.template.toml b/dim_plugins/volume/config.template.toml new file mode 100644 index 0000000..0b0a6ad --- /dev/null +++ b/dim_plugins/volume/config.template.toml @@ -0,0 +1,3 @@ +[commands] +get_volume="pactl get-sink-volume @DEFAULT_SINK@" +get_volume_regex=".* (?[0-9]{1,3})%.*" diff --git a/dim_plugins/volume/src/config.rs b/dim_plugins/volume/src/config.rs new file mode 100644 index 0000000..8e0b269 --- /dev/null +++ b/dim_plugins/volume/src/config.rs @@ -0,0 +1,37 @@ +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 { + 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() + } + } + } + +} diff --git a/dim_plugins/volume/src/lib.rs b/dim_plugins/volume/src/lib.rs new file mode 100644 index 0000000..c5bfac2 --- /dev/null +++ b/dim_plugins/volume/src/lib.rs @@ -0,0 +1,68 @@ +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) { + + } +} + + + +