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; async fn listen(tx: Sender, 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>) -> Result { 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(()) } }