summaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: 26b578433e9c9beb7bf6ebd6c8fa036f699fbb89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use std::process::Stdio;

use i3blocks_mpris::{
    i3bar::{Block, Click},
    listener::listeners,
    Blocks,
};
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};

#[tokio::main]
async fn main() -> Result<(), main_error::MainError> {
    let args = std::env::args().skip(1).collect::<Vec<_>>();
    let mut child = tokio::process::Command::new("i3blocks")
        .args(args)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()?;

    let mut stdout = tokio::io::stdout();
    let mut stdin = BufReader::new(tokio::io::stdin()).lines();

    let mut child_stdin = child.stdin.take().unwrap();
    let mut child_stdout = BufReader::new(child.stdout.take().unwrap()).lines();

    let blocks: Blocks = Blocks::default();

    let blocks2 = blocks.clone();
    tokio::spawn(async move {
        blocks2.value.write().await[0] = Some(Block {
            name: Some("mpris-icon".into()),
            full_text: " 󰝚  ".into(),
            separator: Some(false),
            separator_block_width: Some(0),
            ..Default::default()
        });
        blocks2.notify.notify_one();
    });

    tokio::spawn(listeners(blocks.clone()));

    let mut mpris_blocks = String::new();
    let mut other_blocks = String::new();

    loop {
        tokio::select! {
            _ = blocks.notify.notified() => {
                mpris_blocks = blocks
                    .value
                    .read()
                    .await
                    .iter()
                    .map(serde_json::to_string)
                    .collect::<Result<Vec<_>, _>>()?
                    .join(",");
            }
            Ok(Some(line)) = child_stdout.next_line() => other_blocks = line,
            Ok(Some(line)) = stdin.next_line() => match serde_json::from_str::<Click>(&line) {
                Err(_) => continue,
                Ok(Click { name: Some(name), button, .. }) if name.starts_with("mpris-") => println!("{name}, {button}"),
                Ok(click) => {
                    let mut s = serde_json::to_vec(&click)?;
                    s.push(b'\n');
                    child_stdin.write_all(&s).await?;
                }
            },
            else => break,
        }

        let mut output = other_blocks.replace(r#"{"name":"mpris","full_text":""}"#, &mpris_blocks);
        output.push('\n');
        stdout.write_all(output.as_bytes()).await?;
    }

    Ok(())
}