mod block; use tokio::signal::unix::{signal, SignalKind}; use tokio::time::{sleep, Duration}; use tokio::sync::mpsc; use tokio::task; use itertools::Itertools; use xcb::x; use mpris::PlayerFinder; use block::*; fn setup_mpris_event_listener() -> mpsc::Receiver<()> { let (tx, rx) = mpsc::channel::<()>(10); task::spawn_blocking(move || { let finder = PlayerFinder::new().expect("Could not create finder"); loop { let player = match finder.find_active() { Ok(player) => player, Err(_) => { std::thread::sleep(std::time::Duration::from_secs(5)); continue; }, }; println!("Player found: {}", player.identity()); let mut events = player.events().expect("Could not listen for events"); loop { if let Some(_event) = events.next() { tx.blocking_send(()).expect("Can't send"); } else { println!("Player lost"); break; } } } }); rx } #[tokio::main] async fn main() -> Result<(), Box> { let (conn, screen_num) = xcb::Connection::connect(None)?; // Fetch the `x::Setup` and get the main `x::Screen` object. let setup = conn.get_setup(); let screen = setup.roots().nth(screen_num as usize).unwrap(); let blocks: Vec> = vec![ Box::new(Music {}), Box::new(Volume {}), Box::new(Temp {}), //Box::new(Mem {}), Box::new(Date { format: "%A %d %B | %H:%M".to_string(), }), ]; let mut sigusr1 = signal(SignalKind::user_defined1())?; let mut mpris_rx = setup_mpris_event_listener(); loop { let status_bar: String = blocks .iter() .map(|block| block.display()) .intersperse(" | ".to_string()) .collect(); let status_bar = format!(" {} ", status_bar); conn.send_request(&x::ChangeProperty { mode: x::PropMode::Replace, window: screen.root(), property: x::ATOM_WM_NAME, r#type: x::ATOM_STRING, data: status_bar.as_bytes(), }); conn.flush()?; tokio::select! { _ = sleep(Duration::from_secs(1)) => {}, _ = sigusr1.recv() => {}, _ = mpris_rx.recv() => {}, } } }