main.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. mod block;
  2. use tokio::signal::unix::{signal, SignalKind};
  3. use tokio::time::{sleep, Duration};
  4. use tokio::sync::mpsc;
  5. use tokio::task;
  6. use itertools::Itertools;
  7. use xcb::x;
  8. use mpris::PlayerFinder;
  9. use block::*;
  10. fn setup_mpris_event_listener() -> mpsc::Receiver<()> {
  11. let (tx, rx) = mpsc::channel::<()>(10);
  12. task::spawn_blocking(move || {
  13. let finder = PlayerFinder::new().expect("Could not create finder");
  14. loop {
  15. let player = match finder.find_active() {
  16. Ok(player) => player,
  17. Err(_) => {
  18. std::thread::sleep(std::time::Duration::from_secs(5));
  19. continue;
  20. },
  21. };
  22. println!("Player found: {}", player.identity());
  23. let mut events = player.events().expect("Could not listen for events");
  24. loop {
  25. if let Some(_event) = events.next() {
  26. tx.blocking_send(()).expect("Can't send");
  27. } else {
  28. println!("Player lost");
  29. break;
  30. }
  31. }
  32. }
  33. });
  34. rx
  35. }
  36. #[tokio::main]
  37. async fn main() -> Result<(), Box<dyn std::error::Error>> {
  38. let (conn, screen_num) = xcb::Connection::connect(None)?;
  39. // Fetch the `x::Setup` and get the main `x::Screen` object.
  40. let setup = conn.get_setup();
  41. let screen = setup.roots().nth(screen_num as usize).unwrap();
  42. let blocks: Vec<Box<dyn Block>> = vec![
  43. Box::new(Music {}),
  44. Box::new(Volume {}),
  45. Box::new(Temp {}),
  46. //Box::new(Mem {}),
  47. Box::new(Date {
  48. format: "%A %d %B | %H:%M".to_string(),
  49. }),
  50. ];
  51. let mut sigusr1 = signal(SignalKind::user_defined1())?;
  52. let mut mpris_rx = setup_mpris_event_listener();
  53. loop {
  54. let status_bar: String = blocks
  55. .iter()
  56. .map(|block| block.display())
  57. .intersperse(" | ".to_string())
  58. .collect();
  59. let status_bar = format!(" {} ", status_bar);
  60. conn.send_request(&x::ChangeProperty {
  61. mode: x::PropMode::Replace,
  62. window: screen.root(),
  63. property: x::ATOM_WM_NAME,
  64. r#type: x::ATOM_STRING,
  65. data: status_bar.as_bytes(),
  66. });
  67. conn.flush()?;
  68. tokio::select! {
  69. _ = sleep(Duration::from_secs(1)) => {},
  70. _ = sigusr1.recv() => {},
  71. _ = mpris_rx.recv() => {},
  72. }
  73. }
  74. }