Compare commits
3 Commits
v0.4.1
..
75601305e2
| Author | SHA1 | Date | |
|---|---|---|---|
| 75601305e2 | |||
| 52cc041c42 | |||
| cb8b641447 |
Generated
+1
-1
@@ -572,7 +572,7 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fluxo-rs"
|
name = "fluxo-rs"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bluer",
|
"bluer",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "fluxo-rs"
|
name = "fluxo-rs"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -29,40 +29,49 @@ backlight = 13
|
|||||||
dnd = 14
|
dnd = 14
|
||||||
|
|
||||||
[network]
|
[network]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {interface}, {ip}, {rx}, {tx}
|
# tokens: {interface}, {ip}, {rx}, {tx}
|
||||||
format = "{interface} ({ip}): {rx:^4.1} MB/s {tx:^4.1} MB/s"
|
format = "{interface} ({ip}): {rx:^4.1} MB/s {tx:^4.1} MB/s"
|
||||||
|
|
||||||
[cpu]
|
[cpu]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {usage}, {temp}, {model}
|
# tokens: {usage}, {temp}, {model}
|
||||||
format = "CPU: {usage:^4.1}% {temp:^4.1}C"
|
format = "CPU: {usage:^4.1}% {temp:^4.1}C"
|
||||||
|
|
||||||
[memory]
|
[memory]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {used}, {total}
|
# tokens: {used}, {total}
|
||||||
format = "MEM: {used:^4.1}/{total:^4.1}GB"
|
format = "MEM: {used:^4.1}/{total:^4.1}GB"
|
||||||
|
|
||||||
[gpu]
|
[gpu]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {usage}, {vram_used}, {vram_total}, {temp}
|
# tokens: {usage}, {vram_used}, {vram_total}, {temp}
|
||||||
format_amd = "AMD: {usage:>3.0}% {vram_used:>4.1}/{vram_total:>4.1}GB {temp:>4.1}C"
|
format_amd = "AMD: {usage:>3.0}% {vram_used:>4.1}/{vram_total:>4.1}GB {temp:>4.1}C"
|
||||||
format_intel = "iGPU: {usage:>3.0}%"
|
format_intel = "iGPU: {usage:>3.0}%"
|
||||||
format_nvidia = "NV: {usage:>3.0}% {vram_used:>4.1}/{vram_total:>4.1}GB {temp:>4.1}C"
|
format_nvidia = "NV: {usage:>3.0}% {vram_used:>4.1}/{vram_total:>4.1}GB {temp:>4.1}C"
|
||||||
|
|
||||||
[sys]
|
[sys]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {uptime}, {load1}, {load5}, {load15}, {procs}
|
# tokens: {uptime}, {load1}, {load5}, {load15}, {procs}
|
||||||
format = "UP: {uptime} LOAD: {load1:^3.1} "
|
format = "UP: {uptime} LOAD: {load1:^3.1} "
|
||||||
|
|
||||||
[disk]
|
[disk]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {mount}, {used}, {total}
|
# tokens: {mount}, {used}, {total}
|
||||||
format = "{mount} {used:^3.0}/{total:^3.0}G"
|
format = "{mount} {used:^3.0}/{total:^3.0}G"
|
||||||
|
|
||||||
[pool]
|
[pool]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {used}, {total}
|
# tokens: {used}, {total}
|
||||||
format = "{used:>4.0}G / {total:>4.0}G"
|
format = "{used:>4.0}G / {total:>4.0}G"
|
||||||
|
|
||||||
[power]
|
[power]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {percentage}, {icon}
|
# tokens: {percentage}, {icon}
|
||||||
format = "{percentage:>3}% {icon}"
|
format = "{percentage:>3}% {icon}"
|
||||||
|
|
||||||
[audio]
|
[audio]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {name}, {volume}, {icon}
|
# tokens: {name}, {volume}, {icon}
|
||||||
format_sink_unmuted = "{name} {volume:>3}% {icon}"
|
format_sink_unmuted = "{name} {volume:>3}% {icon}"
|
||||||
format_sink_muted = "{name} {icon}"
|
format_sink_muted = "{name} {icon}"
|
||||||
@@ -70,6 +79,7 @@ format_source_unmuted = "{name} {volume:>3}% {icon}"
|
|||||||
format_source_muted = "{name} {icon}"
|
format_source_muted = "{name} {icon}"
|
||||||
|
|
||||||
[bt]
|
[bt]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {alias}, {mac}, {left}, {right}, {anc}
|
# tokens: {alias}, {mac}, {left}, {right}, {anc}
|
||||||
format_plugin = "{alias} [{left}|{right}] {anc} "
|
format_plugin = "{alias} [{left}|{right}] {anc} "
|
||||||
format_connected = " {alias}"
|
format_connected = " {alias}"
|
||||||
@@ -77,21 +87,26 @@ format_disconnected = " Disconnected"
|
|||||||
format_disabled = " Off"
|
format_disabled = " Off"
|
||||||
|
|
||||||
[game]
|
[game]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
format_active = "<span size='large'></span>"
|
format_active = "<span size='large'></span>"
|
||||||
format_inactive = "<span size='large'></span>"
|
format_inactive = "<span size='large'></span>"
|
||||||
|
|
||||||
[mpris]
|
[mpris]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {artist}, {title}, {album}, {status_icon}
|
# tokens: {artist}, {title}, {album}, {status_icon}
|
||||||
format = "{status_icon} {artist} - {title}"
|
format = "{status_icon} {artist} - {title}"
|
||||||
|
|
||||||
[backlight]
|
[backlight]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {percentage}, {icon}
|
# tokens: {percentage}, {icon}
|
||||||
format = "{percentage:>3}% {icon}"
|
format = "{percentage:>3}% {icon}"
|
||||||
|
|
||||||
[keyboard]
|
[keyboard]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
# tokens: {layout}
|
# tokens: {layout}
|
||||||
format = "{layout}"
|
format = "{layout}"
|
||||||
|
|
||||||
[dnd]
|
[dnd]
|
||||||
|
# enabled = false # set to false to disable this module at runtime
|
||||||
format_dnd = "<span size='large'></span>"
|
format_dnd = "<span size='large'></span>"
|
||||||
format_normal = "<span size='large'></span>"
|
format_normal = "<span size='large'></span>"
|
||||||
|
|||||||
@@ -91,12 +91,15 @@ pub struct SignalsConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct NetworkConfig {
|
pub struct NetworkConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NetworkConfig {
|
impl Default for NetworkConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "{interface} ({ip}): {rx:>5.2} MB/s {tx:>5.2} MB/s".to_string(),
|
format: "{interface} ({ip}): {rx:>5.2} MB/s {tx:>5.2} MB/s".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,12 +107,15 @@ impl Default for NetworkConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct CpuConfig {
|
pub struct CpuConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CpuConfig {
|
impl Default for CpuConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "CPU: {usage:>4.1}% {temp:>4.1}C".to_string(),
|
format: "CPU: {usage:>4.1}% {temp:>4.1}C".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,12 +123,15 @@ impl Default for CpuConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct MemoryConfig {
|
pub struct MemoryConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MemoryConfig {
|
impl Default for MemoryConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "{used:>5.2}/{total:>5.2}GB".to_string(),
|
format: "{used:>5.2}/{total:>5.2}GB".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,6 +139,8 @@ impl Default for MemoryConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct GpuConfig {
|
pub struct GpuConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format_amd: String,
|
pub format_amd: String,
|
||||||
pub format_intel: String,
|
pub format_intel: String,
|
||||||
pub format_nvidia: String,
|
pub format_nvidia: String,
|
||||||
@@ -138,6 +149,7 @@ pub struct GpuConfig {
|
|||||||
impl Default for GpuConfig {
|
impl Default for GpuConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format_amd: "AMD: {usage:>3.0}% {vram_used:>4.1}/{vram_total:>4.1}GB {temp:>4.1}C"
|
format_amd: "AMD: {usage:>3.0}% {vram_used:>4.1}/{vram_total:>4.1}GB {temp:>4.1}C"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
format_intel: "iGPU: {usage:>3.0}%".to_string(),
|
format_intel: "iGPU: {usage:>3.0}%".to_string(),
|
||||||
@@ -149,12 +161,15 @@ impl Default for GpuConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct SysConfig {
|
pub struct SysConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SysConfig {
|
impl Default for SysConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "UP: {uptime} | LOAD: {load1:>4.2} {load5:>4.2} {load15:>4.2}".to_string(),
|
format: "UP: {uptime} | LOAD: {load1:>4.2} {load5:>4.2} {load15:>4.2}".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,12 +177,15 @@ impl Default for SysConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct DiskConfig {
|
pub struct DiskConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for DiskConfig {
|
impl Default for DiskConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "{mount} {used:>5.1}/{total:>5.1}G".to_string(),
|
format: "{mount} {used:>5.1}/{total:>5.1}G".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,12 +193,15 @@ impl Default for DiskConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct PoolConfig {
|
pub struct PoolConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PoolConfig {
|
impl Default for PoolConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "{used:>4.0}G / {total:>4.0}G".to_string(),
|
format: "{used:>4.0}G / {total:>4.0}G".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,12 +209,15 @@ impl Default for PoolConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct PowerConfig {
|
pub struct PowerConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PowerConfig {
|
impl Default for PowerConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "{percentage:>3}% {icon}".to_string(),
|
format: "{percentage:>3}% {icon}".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,6 +225,8 @@ impl Default for PowerConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct AudioConfig {
|
pub struct AudioConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format_sink_unmuted: String,
|
pub format_sink_unmuted: String,
|
||||||
pub format_sink_muted: String,
|
pub format_sink_muted: String,
|
||||||
pub format_source_unmuted: String,
|
pub format_source_unmuted: String,
|
||||||
@@ -210,6 +236,7 @@ pub struct AudioConfig {
|
|||||||
impl Default for AudioConfig {
|
impl Default for AudioConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format_sink_unmuted: "{name} {volume:>3}% {icon}".to_string(),
|
format_sink_unmuted: "{name} {volume:>3}% {icon}".to_string(),
|
||||||
format_sink_muted: "{name} {icon}".to_string(),
|
format_sink_muted: "{name} {icon}".to_string(),
|
||||||
format_source_unmuted: "{name} {volume:>3}% {icon}".to_string(),
|
format_source_unmuted: "{name} {volume:>3}% {icon}".to_string(),
|
||||||
@@ -220,6 +247,8 @@ impl Default for AudioConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct BtConfig {
|
pub struct BtConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format_connected: String,
|
pub format_connected: String,
|
||||||
pub format_plugin: String,
|
pub format_plugin: String,
|
||||||
pub format_disconnected: String,
|
pub format_disconnected: String,
|
||||||
@@ -229,6 +258,7 @@ pub struct BtConfig {
|
|||||||
impl Default for BtConfig {
|
impl Default for BtConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format_connected: "{alias} ".to_string(),
|
format_connected: "{alias} ".to_string(),
|
||||||
format_plugin: "{alias} [{left}|{right}] {anc} ".to_string(),
|
format_plugin: "{alias} [{left}|{right}] {anc} ".to_string(),
|
||||||
format_disconnected: "".to_string(),
|
format_disconnected: "".to_string(),
|
||||||
@@ -239,6 +269,8 @@ impl Default for BtConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct GameConfig {
|
pub struct GameConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format_active: String,
|
pub format_active: String,
|
||||||
pub format_inactive: String,
|
pub format_inactive: String,
|
||||||
}
|
}
|
||||||
@@ -246,6 +278,7 @@ pub struct GameConfig {
|
|||||||
impl Default for GameConfig {
|
impl Default for GameConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format_active: "<span size='large'></span>".to_string(),
|
format_active: "<span size='large'></span>".to_string(),
|
||||||
format_inactive: "<span size='large'></span>".to_string(),
|
format_inactive: "<span size='large'></span>".to_string(),
|
||||||
}
|
}
|
||||||
@@ -254,12 +287,15 @@ impl Default for GameConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct MprisConfig {
|
pub struct MprisConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MprisConfig {
|
impl Default for MprisConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "{status_icon} {artist} - {title}".to_string(),
|
format: "{status_icon} {artist} - {title}".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,12 +303,15 @@ impl Default for MprisConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct BacklightConfig {
|
pub struct BacklightConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BacklightConfig {
|
impl Default for BacklightConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "{percentage:>3}% {icon}".to_string(),
|
format: "{percentage:>3}% {icon}".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,12 +319,15 @@ impl Default for BacklightConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct KeyboardConfig {
|
pub struct KeyboardConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for KeyboardConfig {
|
impl Default for KeyboardConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format: "{layout}".to_string(),
|
format: "{layout}".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,13 +335,20 @@ impl Default for KeyboardConfig {
|
|||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct DndConfig {
|
pub struct DndConfig {
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub enabled: bool,
|
||||||
pub format_dnd: String,
|
pub format_dnd: String,
|
||||||
pub format_normal: String,
|
pub format_normal: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_true() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for DndConfig {
|
impl Default for DndConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: true,
|
||||||
format_dnd: "<span size='large'></span>".to_string(),
|
format_dnd: "<span size='large'></span>".to_string(),
|
||||||
format_normal: "<span size='large'></span>".to_string(),
|
format_normal: "<span size='large'></span>".to_string(),
|
||||||
}
|
}
|
||||||
@@ -325,6 +374,44 @@ fn validate_format(label: &str, format_str: &str, known_tokens: &[&str]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
/// Check if a module is enabled in the configuration.
|
||||||
|
/// Returns false if the module is explicitly disabled; true if enabled or unknown.
|
||||||
|
pub fn is_module_enabled(&self, module_name: &str) -> bool {
|
||||||
|
match module_name {
|
||||||
|
#[cfg(feature = "mod-network")]
|
||||||
|
"net" | "network" => self.network.enabled,
|
||||||
|
#[cfg(feature = "mod-hardware")]
|
||||||
|
"cpu" => self.cpu.enabled,
|
||||||
|
#[cfg(feature = "mod-hardware")]
|
||||||
|
"mem" | "memory" => self.memory.enabled,
|
||||||
|
#[cfg(feature = "mod-hardware")]
|
||||||
|
"gpu" => self.gpu.enabled,
|
||||||
|
#[cfg(feature = "mod-hardware")]
|
||||||
|
"sys" => self.sys.enabled,
|
||||||
|
#[cfg(feature = "mod-hardware")]
|
||||||
|
"disk" => self.disk.enabled,
|
||||||
|
#[cfg(feature = "mod-hardware")]
|
||||||
|
"pool" | "btrfs" => self.pool.enabled,
|
||||||
|
#[cfg(feature = "mod-hardware")]
|
||||||
|
"power" => self.power.enabled,
|
||||||
|
#[cfg(feature = "mod-hardware")]
|
||||||
|
"game" => self.game.enabled,
|
||||||
|
#[cfg(feature = "mod-audio")]
|
||||||
|
"vol" | "audio" | "mic" => self.audio.enabled,
|
||||||
|
#[cfg(feature = "mod-bt")]
|
||||||
|
"bt" | "bluetooth" => self.bt.enabled,
|
||||||
|
#[cfg(feature = "mod-dbus")]
|
||||||
|
"mpris" => self.mpris.enabled,
|
||||||
|
#[cfg(feature = "mod-dbus")]
|
||||||
|
"backlight" => self.backlight.enabled,
|
||||||
|
#[cfg(feature = "mod-dbus")]
|
||||||
|
"kbd" | "keyboard" => self.keyboard.enabled,
|
||||||
|
#[cfg(feature = "mod-dbus")]
|
||||||
|
"dnd" => self.dnd.enabled,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn validate(&self) {
|
pub fn validate(&self) {
|
||||||
#[cfg(feature = "mod-network")]
|
#[cfg(feature = "mod-network")]
|
||||||
validate_format(
|
validate_format(
|
||||||
|
|||||||
+50
-37
@@ -183,7 +183,7 @@ pub async fn run_daemon(config_path: Option<PathBuf>) -> Result<()> {
|
|||||||
|
|
||||||
// 1. Network Task
|
// 1. Network Task
|
||||||
#[cfg(feature = "mod-network")]
|
#[cfg(feature = "mod-network")]
|
||||||
{
|
if config.read().await.network.enabled {
|
||||||
let token = cancel_token.clone();
|
let token = cancel_token.clone();
|
||||||
let net_health = Arc::clone(&health);
|
let net_health = Arc::clone(&health);
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
@@ -206,48 +206,58 @@ pub async fn run_daemon(config_path: Option<PathBuf>) -> Result<()> {
|
|||||||
// 2. Fast Hardware Task (CPU, Mem, Load)
|
// 2. Fast Hardware Task (CPU, Mem, Load)
|
||||||
#[cfg(feature = "mod-hardware")]
|
#[cfg(feature = "mod-hardware")]
|
||||||
{
|
{
|
||||||
let token = cancel_token.clone();
|
let cfg = config.read().await;
|
||||||
let hw_health = Arc::clone(&health);
|
let fast_enabled = cfg.cpu.enabled || cfg.memory.enabled || cfg.sys.enabled;
|
||||||
tokio::spawn(async move {
|
drop(cfg);
|
||||||
info!("Starting Fast Hardware polling task");
|
if fast_enabled {
|
||||||
let mut daemon = HardwareDaemon::new();
|
let token = cancel_token.clone();
|
||||||
loop {
|
let hw_health = Arc::clone(&health);
|
||||||
if !crate::health::is_poll_in_backoff("cpu", &hw_health).await {
|
tokio::spawn(async move {
|
||||||
daemon.poll_fast(&cpu_tx, &mem_tx, &sys_tx).await;
|
info!("Starting Fast Hardware polling task");
|
||||||
|
let mut daemon = HardwareDaemon::new();
|
||||||
|
loop {
|
||||||
|
if !crate::health::is_poll_in_backoff("cpu", &hw_health).await {
|
||||||
|
daemon.poll_fast(&cpu_tx, &mem_tx, &sys_tx).await;
|
||||||
|
}
|
||||||
|
tokio::select! {
|
||||||
|
_ = token.cancelled() => break,
|
||||||
|
_ = sleep(Duration::from_secs(1)) => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tokio::select! {
|
info!("Fast Hardware task shut down.");
|
||||||
_ = token.cancelled() => break,
|
});
|
||||||
_ = sleep(Duration::from_secs(1)) => {}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
info!("Fast Hardware task shut down.");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Slow Hardware Task (GPU, Disks)
|
// 3. Slow Hardware Task (GPU, Disks)
|
||||||
#[cfg(feature = "mod-hardware")]
|
#[cfg(feature = "mod-hardware")]
|
||||||
{
|
{
|
||||||
let token = cancel_token.clone();
|
let cfg = config.read().await;
|
||||||
let slow_health = Arc::clone(&health);
|
let slow_enabled = cfg.gpu.enabled || cfg.disk.enabled;
|
||||||
tokio::spawn(async move {
|
drop(cfg);
|
||||||
info!("Starting Slow Hardware polling task");
|
if slow_enabled {
|
||||||
let mut daemon = HardwareDaemon::new();
|
let token = cancel_token.clone();
|
||||||
loop {
|
let slow_health = Arc::clone(&health);
|
||||||
if !crate::health::is_poll_in_backoff("gpu", &slow_health).await {
|
tokio::spawn(async move {
|
||||||
daemon.poll_slow(&gpu_tx, &disks_tx).await;
|
info!("Starting Slow Hardware polling task");
|
||||||
|
let mut daemon = HardwareDaemon::new();
|
||||||
|
loop {
|
||||||
|
if !crate::health::is_poll_in_backoff("gpu", &slow_health).await {
|
||||||
|
daemon.poll_slow(&gpu_tx, &disks_tx).await;
|
||||||
|
}
|
||||||
|
tokio::select! {
|
||||||
|
_ = token.cancelled() => break,
|
||||||
|
_ = sleep(Duration::from_secs(5)) => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tokio::select! {
|
info!("Slow Hardware task shut down.");
|
||||||
_ = token.cancelled() => break,
|
});
|
||||||
_ = sleep(Duration::from_secs(5)) => {}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
info!("Slow Hardware task shut down.");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Bluetooth Task
|
// 4. Bluetooth Task
|
||||||
#[cfg(feature = "mod-bt")]
|
#[cfg(feature = "mod-bt")]
|
||||||
{
|
if config.read().await.bt.enabled {
|
||||||
let token = cancel_token.clone();
|
let token = cancel_token.clone();
|
||||||
let bt_health = Arc::clone(&health);
|
let bt_health = Arc::clone(&health);
|
||||||
let poll_config = Arc::clone(&config);
|
let poll_config = Arc::clone(&config);
|
||||||
@@ -272,35 +282,35 @@ pub async fn run_daemon(config_path: Option<PathBuf>) -> Result<()> {
|
|||||||
|
|
||||||
// 5. Audio Thread (Event driven)
|
// 5. Audio Thread (Event driven)
|
||||||
#[cfg(feature = "mod-audio")]
|
#[cfg(feature = "mod-audio")]
|
||||||
{
|
if config.read().await.audio.enabled {
|
||||||
let audio_daemon = AudioDaemon::new();
|
let audio_daemon = AudioDaemon::new();
|
||||||
audio_daemon.start(&audio_tx, audio_cmd_rx);
|
audio_daemon.start(&audio_tx, audio_cmd_rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5.1 Backlight Thread (Event driven)
|
// 5.1 Backlight Thread (Event driven)
|
||||||
#[cfg(feature = "mod-dbus")]
|
#[cfg(feature = "mod-dbus")]
|
||||||
{
|
if config.read().await.backlight.enabled {
|
||||||
let backlight_daemon = BacklightDaemon::new();
|
let backlight_daemon = BacklightDaemon::new();
|
||||||
backlight_daemon.start(backlight_tx);
|
backlight_daemon.start(backlight_tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5.2 Keyboard Thread (Event driven)
|
// 5.2 Keyboard Thread (Event driven)
|
||||||
#[cfg(feature = "mod-dbus")]
|
#[cfg(feature = "mod-dbus")]
|
||||||
{
|
if config.read().await.keyboard.enabled {
|
||||||
let keyboard_daemon = KeyboardDaemon::new();
|
let keyboard_daemon = KeyboardDaemon::new();
|
||||||
keyboard_daemon.start(keyboard_tx);
|
keyboard_daemon.start(keyboard_tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5.3 DND Thread (Event driven)
|
// 5.3 DND Thread (Event driven)
|
||||||
#[cfg(feature = "mod-dbus")]
|
#[cfg(feature = "mod-dbus")]
|
||||||
{
|
if config.read().await.dnd.enabled {
|
||||||
let dnd_daemon = DndDaemon::new();
|
let dnd_daemon = DndDaemon::new();
|
||||||
dnd_daemon.start(dnd_tx);
|
dnd_daemon.start(dnd_tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5.4 MPRIS Thread
|
// 5.4 MPRIS Thread
|
||||||
#[cfg(feature = "mod-dbus")]
|
#[cfg(feature = "mod-dbus")]
|
||||||
{
|
if config.read().await.mpris.enabled {
|
||||||
let mpris_daemon = MprisDaemon::new();
|
let mpris_daemon = MprisDaemon::new();
|
||||||
mpris_daemon.start(mpris_tx);
|
mpris_daemon.start(mpris_tx);
|
||||||
}
|
}
|
||||||
@@ -416,6 +426,9 @@ async fn handle_request(
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(output) => serde_json::to_string(&output).unwrap_or_else(|_| "{}".to_string()),
|
Ok(output) => serde_json::to_string(&output).unwrap_or_else(|_| "{}".to_string()),
|
||||||
|
Err(crate::error::FluxoError::Disabled(_)) => {
|
||||||
|
"{\"text\":\"\",\"tooltip\":\"Module disabled\",\"class\":\"disabled\"}".to_string()
|
||||||
|
}
|
||||||
Err(e) => crate::health::error_response(module_name, &e, cached_output),
|
Err(e) => crate::health::error_response(module_name, &e, cached_output),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ pub enum FluxoError {
|
|||||||
#[error("Serialization error: {0}")]
|
#[error("Serialization error: {0}")]
|
||||||
Serialization(#[from] serde_json::Error),
|
Serialization(#[from] serde_json::Error),
|
||||||
|
|
||||||
|
#[error("Module disabled: {0}")]
|
||||||
|
Disabled(String),
|
||||||
|
|
||||||
#[error("Other error: {0}")]
|
#[error("Other error: {0}")]
|
||||||
Other(#[from] anyhow::Error),
|
Other(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ pub async fn update_health(
|
|||||||
health.backoff_until = None;
|
health.backoff_until = None;
|
||||||
health.last_successful_output = Some(output.clone());
|
health.last_successful_output = Some(output.clone());
|
||||||
}
|
}
|
||||||
|
Err(crate::error::FluxoError::Disabled(_)) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
health.consecutive_failures += 1;
|
health.consecutive_failures += 1;
|
||||||
health.last_failure = Some(Instant::now());
|
health.last_failure = Some(Instant::now());
|
||||||
|
|||||||
+48
-48
@@ -29,19 +29,19 @@ impl WaybarModule for DndModule {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Try toggling SwayNC
|
// Try toggling SwayNC
|
||||||
if let Ok(proxy) = SwayncControlProxy::new(&connection).await {
|
if let Ok(proxy) = SwayncControlProxy::new(&connection).await
|
||||||
if let Ok(is_dnd) = proxy.dnd().await {
|
&& let Ok(is_dnd) = proxy.dnd().await
|
||||||
let _ = proxy.set_dnd(!is_dnd).await;
|
{
|
||||||
return Ok(WaybarOutput::default());
|
let _ = proxy.set_dnd(!is_dnd).await;
|
||||||
}
|
return Ok(WaybarOutput::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try toggling Dunst
|
// Try toggling Dunst
|
||||||
if let Ok(proxy) = DunstControlProxy::new(&connection).await {
|
if let Ok(proxy) = DunstControlProxy::new(&connection).await
|
||||||
if let Ok(is_paused) = proxy.paused().await {
|
&& let Ok(is_paused) = proxy.paused().await
|
||||||
let _ = proxy.set_paused(!is_paused).await;
|
{
|
||||||
return Ok(WaybarOutput::default());
|
let _ = proxy.set_paused(!is_paused).await;
|
||||||
}
|
return Ok(WaybarOutput::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(crate::error::FluxoError::Module {
|
return Err(crate::error::FluxoError::Module {
|
||||||
@@ -118,52 +118,52 @@ impl DndDaemon {
|
|||||||
info!("Connected to D-Bus for DND monitoring");
|
info!("Connected to D-Bus for DND monitoring");
|
||||||
|
|
||||||
// Try SwayNC
|
// Try SwayNC
|
||||||
if let Ok(proxy) = SwayncControlProxy::new(&connection).await {
|
if let Ok(proxy) = SwayncControlProxy::new(&connection).await
|
||||||
if let Ok(is_dnd) = proxy.dnd().await {
|
&& let Ok(is_dnd) = proxy.dnd().await
|
||||||
debug!("Found SwayNC, using it for DND state.");
|
{
|
||||||
let _ = tx.send(DndState { is_dnd });
|
debug!("Found SwayNC, using it for DND state.");
|
||||||
|
let _ = tx.send(DndState { is_dnd });
|
||||||
|
|
||||||
if let Ok(props_proxy) = PropertiesProxy::builder(&connection)
|
if let Ok(props_proxy) = PropertiesProxy::builder(&connection)
|
||||||
.destination("org.erikreider.swaync.control")?
|
.destination("org.erikreider.swaync.control")?
|
||||||
.path("/org/erikreider/swaync/control")?
|
.path("/org/erikreider/swaync/control")?
|
||||||
.build()
|
.build()
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
let mut stream = props_proxy.receive_properties_changed().await?;
|
let mut stream = props_proxy.receive_properties_changed().await?;
|
||||||
while let Some(signal) = stream.next().await {
|
while let Some(signal) = stream.next().await {
|
||||||
let args = signal.args()?;
|
let args = signal.args()?;
|
||||||
if args.interface_name == "org.erikreider.swaync.control"
|
if args.interface_name == "org.erikreider.swaync.control"
|
||||||
&& let Some(val) = args.changed_properties.get("dnd")
|
&& let Some(val) = args.changed_properties.get("dnd")
|
||||||
&& let Ok(is_dnd) = bool::try_from(val)
|
&& let Ok(is_dnd) = bool::try_from(val)
|
||||||
{
|
{
|
||||||
let _ = tx.send(DndState { is_dnd });
|
let _ = tx.send(DndState { is_dnd });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try Dunst
|
// Try Dunst
|
||||||
if let Ok(proxy) = DunstControlProxy::new(&connection).await {
|
if let Ok(proxy) = DunstControlProxy::new(&connection).await
|
||||||
if let Ok(is_dnd) = proxy.paused().await {
|
&& let Ok(is_dnd) = proxy.paused().await
|
||||||
debug!("Found Dunst, using it for DND state.");
|
{
|
||||||
let _ = tx.send(DndState { is_dnd });
|
debug!("Found Dunst, using it for DND state.");
|
||||||
|
let _ = tx.send(DndState { is_dnd });
|
||||||
|
|
||||||
if let Ok(props_proxy) = PropertiesProxy::builder(&connection)
|
if let Ok(props_proxy) = PropertiesProxy::builder(&connection)
|
||||||
.destination("org.freedesktop.Notifications")?
|
.destination("org.freedesktop.Notifications")?
|
||||||
.path("/org/freedesktop/Notifications")?
|
.path("/org/freedesktop/Notifications")?
|
||||||
.build()
|
.build()
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
let mut stream = props_proxy.receive_properties_changed().await?;
|
let mut stream = props_proxy.receive_properties_changed().await?;
|
||||||
while let Some(signal) = stream.next().await {
|
while let Some(signal) = stream.next().await {
|
||||||
let args = signal.args()?;
|
let args = signal.args()?;
|
||||||
if args.interface_name == "org.dunstproject.cmd0"
|
if args.interface_name == "org.dunstproject.cmd0"
|
||||||
&& let Some(val) = args.changed_properties.get("paused")
|
&& let Some(val) = args.changed_properties.get("paused")
|
||||||
&& let Ok(is_dnd) = bool::try_from(val)
|
&& let Ok(is_dnd) = bool::try_from(val)
|
||||||
{
|
{
|
||||||
let _ = tx.send(DndState { is_dnd });
|
let _ = tx.send(DndState { is_dnd });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ pub async fn dispatch(
|
|||||||
#[allow(unused)] state: &AppReceivers,
|
#[allow(unused)] state: &AppReceivers,
|
||||||
#[allow(unused)] args: &[&str],
|
#[allow(unused)] args: &[&str],
|
||||||
) -> FluxoResult<WaybarOutput> {
|
) -> FluxoResult<WaybarOutput> {
|
||||||
|
if !config.is_module_enabled(module_name) {
|
||||||
|
return Err(FluxoError::Disabled(module_name.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
match module_name {
|
match module_name {
|
||||||
#[cfg(feature = "mod-network")]
|
#[cfg(feature = "mod-network")]
|
||||||
"net" | "network" => {
|
"net" | "network" => {
|
||||||
|
|||||||
Reference in New Issue
Block a user