1 Commits

Author SHA1 Message Date
nvrl 230604dae3 changed bin name to fluxo
Release / Build and Release (push) Successful in 2m53s
2026-04-07 12:01:54 +02:00
7 changed files with 82 additions and 33 deletions
+10 -10
View File
@@ -64,31 +64,31 @@ jobs:
VERSION: ${{ steps.get_version.outputs.VERSION }}
TAG: ${{ steps.get_version.outputs.TAG }}
run: |
PKG="fluxo-rs_${VERSION}_amd64"
PKG="fluxo_${VERSION}_amd64"
mkdir -p "${PKG}/DEBIAN"
mkdir -p "${PKG}/usr/bin"
cp target/release/fluxo-rs "${PKG}/usr/bin/"
strip "${PKG}/usr/bin/fluxo-rs"
cp target/release/fluxo "${PKG}/usr/bin/"
strip "${PKG}/usr/bin/fluxo"
printf '%s\n' \
"Package: fluxo-rs" \
"Package: fluxo" \
"Version: ${VERSION}" \
"Section: utils" \
"Priority: optional" \
"Architecture: amd64" \
"Maintainer: fluxo-rs contributors" \
"Maintainer: fluxo contributors" \
"Description: High-performance daemon/client for Waybar custom modules" \
" fluxo-rs is a compiled Rust daemon that polls system metrics and" \
" fluxo is a compiled Rust daemon that polls system metrics and" \
" serves formatted JSON output to Waybar custom modules over a Unix" \
" domain socket. Replaces shell scripts with a single binary." \
> "${PKG}/DEBIAN/control"
dpkg-deb --build "${PKG}"
mv "${PKG}.deb" "fluxo-rs-${TAG}-amd64.deb"
echo "Built: fluxo-rs-${TAG}-amd64.deb"
mv "${PKG}.deb" "fluxo-${TAG}-amd64.deb"
echo "Built: fluxo-${TAG}-amd64.deb"
- name: Create Release and Upload Assets
if: steps.check_release.outputs.EXISTS == 'false'
@@ -101,8 +101,8 @@ jobs:
Commit: ${{ github.sha }}
Branch: ${{ github.ref_name }}
files: |
fluxo-rs-${{ steps.get_version.outputs.TAG }}-amd64.deb
target/release/fluxo-rs
fluxo-${{ steps.get_version.outputs.TAG }}-amd64.deb
target/release/fluxo
draft: false
prerelease: false
env:
Generated
+1 -1
View File
@@ -572,7 +572,7 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
[[package]]
name = "fluxo-rs"
version = "0.5.2"
version = "0.5.3"
dependencies = [
"anyhow",
"bluer",
+5 -1
View File
@@ -1,8 +1,12 @@
[package]
name = "fluxo-rs"
version = "0.5.2"
version = "0.5.3"
edition = "2024"
[[bin]]
name = "fluxo"
path = "src/main.rs"
[features]
default = ["mod-audio", "mod-bt", "mod-network", "mod-hardware", "mod-dbus"]
mod-audio = ["dep:libpulse-binding"]
+13 -13
View File
@@ -1,13 +1,13 @@
# fluxo-rs
# fluxo
`fluxo-rs` is a high-performance system metrics daemon and client designed specifically for Waybar. It entirely replaces standard shell scripts with a compiled Rust binary that collects data via a background polling loop and serves it over a Unix socket.
`fluxo` is a high-performance system metrics daemon and client designed specifically for Waybar. It entirely replaces standard shell scripts with a compiled Rust binary that collects data via a background polling loop and serves it over a Unix socket.
With its **100% Native, Content-Based Event-Driven Architecture**, it consumes effectively 0% CPU while idle and signals Waybar to redraw *only* when the rendered UI text or icons physically change.
## Key Features
- **100% Native Architecture**: Zero shell-outs or subprocesses. Uses `bluer` for Bluetooth, `libpulse-binding` for audio, `zbus` for MPRIS/DND, and `notify` for backlight.
- **Content-Based Event Signaling**: `fluxo-rs` evaluates your custom configuration formats internally. It only sends a `SIGRTMIN+X` signal to Waybar if the resulting string or CSS class has actually changed, eliminating pointless re-renders from raw polling fluctuations.
- **Content-Based Event Signaling**: `fluxo` evaluates your custom configuration formats internally. It only sends a `SIGRTMIN+X` signal to Waybar if the resulting string or CSS class has actually changed, eliminating pointless re-renders from raw polling fluctuations.
- **Zero-Latency Interactions**: Direct library bindings mean that when you change your volume or connect a Bluetooth device via the CLI, the daemon updates instantly.
- **Circuit Breaker (Failsafe)**: Automatically detects failing modules and enters a "Cool down" state, preventing resource waste and log spam. Fallback caching keeps your bar looking clean even during brief failures.
- **Multi-threaded Polling**: Decoupled Tokio subsystem threads ensure that a hang in one system (e.g., a slow GPU probe) never freezes your Waybar.
@@ -37,7 +37,7 @@ With its **100% Native, Content-Based Event-Driven Architecture**, it consumes e
1. **Build**: `cargo build --release`
2. **Configure**: Create `~/.config/fluxo/config.toml` (see `example.config.toml`). Ensure you map your `[signals]`.
3. **Daemon**: Start `fluxo-rs daemon`. It is highly recommended to run this as a systemd user service.
3. **Daemon**: Start `fluxo daemon`. It is highly recommended to run this as a systemd user service.
## Waybar Configuration
@@ -45,21 +45,21 @@ To achieve zero-latency updates and zero-polling CPU usage, set `interval: 0` on
```jsonc
"custom/volume": {
"exec": "fluxo-rs vol",
"exec": "fluxo vol",
"return-type": "json",
"interval": 0,
"signal": 8, // Must match the value in config.toml [signals]
"on-click": "fluxo-rs vol mute",
"on-scroll-up": "fluxo-rs vol up 1",
"on-scroll-down": "fluxo-rs vol down 1",
"on-click-right": "fluxo-rs vol cycle"
"on-click": "fluxo vol mute",
"on-scroll-up": "fluxo vol up 1",
"on-scroll-down": "fluxo vol down 1",
"on-click-right": "fluxo vol cycle"
},
"custom/bluetooth-audio": {
"format": "{}",
"return-type": "json",
"exec": "fluxo-rs bt",
"on-click": "fluxo-rs bt menu",
"on-click-right": "fluxo-rs bt cycle_mode",
"exec": "fluxo bt",
"on-click": "fluxo bt menu",
"on-click-right": "fluxo bt cycle_mode",
"signal": 9,
"interval": 0,
"tooltip": true
@@ -70,5 +70,5 @@ To achieve zero-latency updates and zero-polling CPU usage, set `interval: 0` on
Start the daemon with `RUST_LOG=debug` to see detailed logs of library interactions and circuit breaker status:
```bash
RUST_LOG=debug fluxo-rs daemon
RUST_LOG=debug fluxo daemon
```
+4 -3
View File
@@ -466,11 +466,12 @@ fn print_module_detail(m: &ModuleHelp) {
println!("\x1b[1mFORMAT TOKENS:\x1b[0m (for use in config.toml format strings)\n");
let max_token = m.tokens.iter().map(|(t, _)| t.len()).max().unwrap_or(0);
for (token, desc) in m.tokens {
let padded = format!("{{{}}}", token);
println!(
" \x1b[33m{{{:<width$}}}\x1b[0m {}",
token,
" \x1b[33m{:<width$}\x1b[0m {}",
padded,
desc,
width = max_token
width = max_token + 2 // +2 for the braces
);
}
println!();
+48 -4
View File
@@ -30,20 +30,49 @@ mod signaler;
mod state;
mod utils;
use clap::{Parser, Subcommand};
use clap::{Parser, Subcommand, ValueEnum};
use std::path::PathBuf;
use std::process;
use tracing::{error, info};
use tracing_subscriber::{EnvFilter, fmt, prelude::*};
#[derive(Clone, ValueEnum)]
enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}
impl From<LogLevel> for tracing::Level {
fn from(level: LogLevel) -> Self {
match level {
LogLevel::Trace => tracing::Level::TRACE,
LogLevel::Debug => tracing::Level::DEBUG,
LogLevel::Info => tracing::Level::INFO,
LogLevel::Warn => tracing::Level::WARN,
LogLevel::Error => tracing::Level::ERROR,
}
}
}
#[derive(Parser)]
#[command(name = "fluxo")]
#[command(about = "A high-performance daemon/client for Waybar custom modules", long_about = None)]
#[command(disable_help_subcommand = true)]
#[command(disable_help_subcommand = true, disable_help_flag = true)]
struct Cli {
#[command(subcommand)]
command: Option<Commands>,
/// Print help information
#[arg(short, long, global = true)]
help: bool,
/// Set the log level (trace, debug, info, warn, error)
#[arg(long, global = true, value_enum)]
loglevel: Option<LogLevel>,
/// Module name to query or interact with
module: Option<String>,
@@ -70,12 +99,27 @@ enum Commands {
}
fn main() {
let cli = Cli::parse();
// Explicit --loglevel takes priority, then RUST_LOG env var, then a
// sensible default: INFO for the daemon, WARN for client commands.
let default_level = if let Some(level) = &cli.loglevel {
tracing::Level::from(level.clone())
} else if matches!(&cli.command, Some(Commands::Daemon { .. })) {
tracing::Level::INFO
} else {
tracing::Level::WARN
};
tracing_subscriber::registry()
.with(fmt::layer().with_target(false).pretty())
.with(EnvFilter::from_default_env().add_directive(tracing::Level::INFO.into()))
.with(EnvFilter::from_default_env().add_directive(default_level.into()))
.init();
let cli = Cli::parse();
if cli.help {
help::print_help(None);
return;
}
if let Some(command) = &cli.command {
match command {
+1 -1
View File
@@ -58,7 +58,7 @@ impl AudioDaemon {
ThreadedMainloop::new().expect("Failed to create pulse threaded mainloop");
let mut context =
Context::new(&mainloop, "fluxo-rs").expect("Failed to create pulse context");
Context::new(&mainloop, "fluxo").expect("Failed to create pulse context");
context
.connect(None, ContextFlag::NOFLAGS, None)