atagen

headroom

public
Star0
Watch0
da174e47c3dfe446a07b3dd77fdfcd414277a44e
1
ssh://brewery@pls.lobotomise.me:33/atagen/headroom.git
crates/headroom-gui/src/main.rsRust67 lines2.2 KB
1
//! `headroom-gui` — native gpu-accelerated monitor for the headroom
2
//! daemon, built on [iced](https://iced.rs). additive and optional, with
3
//! full control parity with the ratatui tui (route/bypass/per-app/profile)
4
//! by mouse + keyboard; ships as its own nix package, separate from the
5
//! daemon. build from the nix dev shell (supplies iced's system libs).
6
7
mod app;
8
mod io;
9
10
use std::path::PathBuf;
11
12
use crate::app::HeadroomApp;
13
14
fn main() -> anyhow::Result<()> {
15
    init_tracing();
16
17
    let socket = parse_socket_arg();
18
19
    // connect + initial fetch before opening any window, so a dead daemon
20
    // fails fast. the reader thread lives inside the returned `Bootstrap`;
21
    // the iced `subscription` poll tick drains its channel.
22
    let bootstrap = io::start(socket)?;
23
24
    // iced's `BootFn` is `Fn` (callable repeatedly) but `Bootstrap` owns a
25
    // receiver and is single-use; stash it and `take()` on the first boot.
26
    let boot = std::sync::Mutex::new(Some(bootstrap));
27
28
    iced::application(
29
        move || HeadroomApp::new(boot.lock().unwrap().take().expect("boot runs once")),
30
        HeadroomApp::update,
31
        HeadroomApp::view,
32
    )
33
    .title(HeadroomApp::title)
34
    .subscription(HeadroomApp::subscription)
35
    .theme(|_state: &HeadroomApp| iced::Theme::Dark)
36
    .window_size(iced::Size::new(900.0, 680.0))
37
    .run()
38
    .map_err(|e| anyhow::anyhow!("iced: {e}"))?;
39
40
    Ok(())
41
}
42
43
/// minimal `--socket <path>` parsing — the only flag, so no clap.
44
fn parse_socket_arg() -> Option<PathBuf> {
45
    let mut args = std::env::args().skip(1);
46
    while let Some(arg) = args.next() {
47
        match arg.as_str() {
48
            "--socket" => return args.next().map(PathBuf::from),
49
            other => {
50
                if let Some(path) = other.strip_prefix("--socket=") {
51
                    return Some(PathBuf::from(path));
52
                }
53
            }
54
        }
55
    }
56
    None
57
}
58
59
fn init_tracing() {
60
    tracing_subscriber::fmt()
61
        .with_env_filter(
62
            tracing_subscriber::EnvFilter::try_from_default_env()
63
                .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("headroom_gui=info")),
64
        )
65
        .with_writer(std::io::stderr)
66
        .init();
67
}