rs_blocks/blocks/
volume.rs

1// Copyright ⓒ 2019-2021 Lewis Belcher
2// Licensed under the MIT license (see LICENSE or <http://opensource.org/licenses/MIT>).
3// All files in the project carrying such notice may not be copied, modified, or
4// distributed except according to those terms
5
6//! # Volume block
7//!
8//! Use this block to get volume monitoring in the status bar.
9//!
10//! Typical configuration:
11//!
12//! ```toml
13//! [volume]
14//! ```
15//!
16//! ## Configuration options
17//!
18//! - `name`: Name of the block (must be unique)
19//! - `period`: Default update period in seconds (extra updates may occur on
20//!    event changes etc)
21//! - `update_signal`: Used to define what signal to listen on for immediate
22//!    retriggering of updates
23
24use 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}