mod ipc; mod manager; mod socket; use std::{env, io::Read}; use anyhow::{Context, Result, anyhow}; use microxdg::Xdg; use niri_tag::Config; fn main() -> Result<()> { // try to read a config let xdg = Xdg::new()?; let mut config_dir = xdg.config()?; config_dir.push("niri-tag"); config_dir.push("config.toml"); let config = std::fs::File::open(config_dir) .map_err(|e| anyhow!(e)) .and_then(|mut f| { let mut buf = String::new(); f.read_to_string(&mut buf).map_err(|e| anyhow!(e))?; Ok(buf) }) .and_then(|buf| toml::from_str::(&buf).map_err(|e| anyhow!(e))) .inspect_err(|e| tracing::error!("Using default config due to: {}", e)) .unwrap_or_default(); // let systemd know we're ready let _ = libsystemd::daemon::notify(false, &[libsystemd::daemon::NotifyState::Ready])?; // debug stuff tracing_subscriber::fmt() .with_max_level(tracing::Level::DEBUG) .init(); let span = if env::var("NIRI_TAG_DEBUG").is_ok() { tracing::span!(tracing::Level::DEBUG, "main") } else { tracing::span!(tracing::Level::INFO, "main") }; let _ = span.enter(); // spawn socket consumer for niri event stream let (niri_tx, niri_rx) = smol::channel::unbounded(); smol::spawn(ipc::event_consumer(niri_tx)).detach(); // spawn socket listener for ipc let (ipc_tx, ipc_rx) = smol::channel::unbounded(); smol::spawn(ipc::ipc_provider(ipc_tx)).detach(); // spawn socket listener for events let (event_tx, event_rx) = smol::channel::unbounded(); let (fullstate_tx, fullstate_rx) = smol::channel::unbounded(); smol::spawn(ipc::event_provider(event_rx, fullstate_tx)).detach(); // begin managing niri tags smol::block_on(async { let niri_tag = manager::NiriTag::new(config, event_tx) .await .context("Initialising niri tag manager") .unwrap(); niri_tag.manage_tags(niri_rx, ipc_rx, fullstate_rx).await }) }