diff options
Diffstat (limited to 'src/component/volume.rs')
-rw-r--r-- | src/component/volume.rs | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/component/volume.rs b/src/component/volume.rs new file mode 100644 index 0000000..2cc7600 --- /dev/null +++ b/src/component/volume.rs @@ -0,0 +1,71 @@ +use std::sync::Arc; + +use tokio::sync::{mpsc::Sender, Mutex}; +use zbus::Connection; + +use crate::{ + dbus::player::{PlaybackStatus, PlayerProxy}, + i3bar::{Block, Click}, + Error, +}; + +use super::{Button, Component, Update}; + +pub struct Volume; + +impl Component for Volume { + const NAME: &'static str = "volume"; + type Updater = Self; + type Colorer = PlaybackStatus; + type Handler = Self; +} + +impl Update for Volume { + type Value = Option<f64>; + + async fn listen(tx: Sender<Self::Value>, proxy: PlayerProxy<'_>) -> Result<(), Error> { + use futures_util::StreamExt; + + tx.send(proxy.volume().await.ok()).await?; + let mut stream = proxy.receive_volume_changed().await; + while let Some(signal) = stream.next().await { + if let Ok(value) = signal.get().await { + tx.send(Some(value)).await?; + } + } + Ok(()) + } + + async fn update(value: Self::Value, block: Arc<Mutex<Block>>) -> Result<bool, Error> { + let mut block = block.lock().await; + block.full_text = match value.map(|v| (v * 100_f64) as u32) { + Some(v @ 66..) => format!(" {v}% "), + Some(v @ 33..) => format!(" {v}% "), + Some(v @ 0..) => format!(" {v}% "), + None => " ".to_string(), + }; + + Ok(true) + } +} + +impl Button for Volume { + async fn handle(conn: Connection, click: Click) -> Result<(), Error> { + let Some(name) = click.instance else { + return Ok(()); + }; + + let proxy = PlayerProxy::builder(&conn) + .destination(name)? + .build() + .await?; + + match (click.button, proxy.volume().await) { + (4, Ok(v)) if proxy.can_control().await? => proxy.set_volume(v + 0.05).await?, + (5, Ok(v)) if proxy.can_control().await? => proxy.set_volume(v - 0.05).await?, + _ => (), + } + + Ok(()) + } +} |