rs_blocks/blocks/
volume.rs1use crate::blocks::{Block, Configure, Message, Sender};
25use crate::utils;
26use serde::Deserialize;
27use std::thread;
28
29#[derive(Configure, Deserialize)]
30pub struct Volume {
31 #[serde(default = "default_name")]
32 name: String,
33 #[serde(default = "default_period")]
34 period: f32,
35 #[serde(default = "default_update_signal")]
36 update_signal: i32,
37}
38
39fn default_name() -> String {
40 "volume".to_string()
41}
42
43fn default_period() -> f32 {
44 10.0
45}
46
47fn default_update_signal() -> i32 {
48 signal_hook::SIGUSR2
49}
50
51impl Sender for Volume {
52 fn add_sender(&self, s: crossbeam_channel::Sender<Message>) -> anyhow::Result<()> {
53 let name = self.get_name();
54 let re = regex::Regex::new(r"(?P<mute>\d)\n(?P<volume>\d+)").unwrap();
55 let mut block = Block::new(self.name.clone(), true);
56 let mut monitor = utils::monitor_command("pulsemixer", &["--get-mute", "--get-volume"], self.period);
57 let recv = utils::wait_for_signal(self.update_signal, self.period);
58
59 thread::spawn(move || loop {
60 let output = monitor.read();
61 block.full_text = Some(if let Some(captures) = re.captures(&output) {
62 if captures.name("mute").unwrap().as_str() == "0" {
63 format!(" {}%", captures.name("volume").unwrap().as_str())
64 } else {
65 "".to_string()
66 }
67 } else {
68 output
69 });
70 s.send((name.clone(), block.to_string())).unwrap();
71 recv.recv().unwrap();
72 });
73
74 Ok(())
75 }
76}