use std::sync::Arc; use tokio::sync::{mpsc::Sender, Mutex}; use crate::{ dbus::player::{PlaybackStatus, PlayerProxy}, i3bar::Block, Error, }; pub trait Update: Send + 'static { type Value: Send; fn listen( tx: Sender, proxy: PlayerProxy<'_>, ) -> impl std::future::Future> + Send; fn update( value: Self::Value, block: Arc>, ) -> impl std::future::Future> + Send; } pub trait Button { fn handle( conn: zbus::Connection, click: crate::i3bar::Click, ) -> impl std::future::Future> + Send; } pub trait Component: Send + 'static { const NAME: &'static str; type Updater: Update; type Colorer: Update; type Handler: Button; } impl Update for () { type Value = (); async fn listen(_: Sender, _: PlayerProxy<'_>) -> Result<(), Error> { Ok(()) } async fn update(_: Self::Value, _: Arc>) -> Result { Ok(false) } } impl Button for () { async fn handle(_: zbus::Connection, _: crate::i3bar::Click) -> Result<(), Error> { Ok(()) } } impl Update for PlaybackStatus { type Value = (Option, Option); async fn listen(tx: Sender, proxy: PlayerProxy<'_>) -> Result<(), Error> { use futures_util::StreamExt; let black = std::env::var("BASE16_COLOR_00_HEX").ok(); let cyan = std::env::var("BASE16_COLOR_0C_HEX").ok(); let yellow = std::env::var("BASE16_COLOR_0A_HEX").ok(); let mut stream = proxy.receive_playback_status_changed().await; while let Some(signal) = stream.next().await { if let Ok(value) = signal.get().await { let val = match value { PlaybackStatus::Playing => (black.clone(), cyan.clone()), PlaybackStatus::Paused => (black.clone(), yellow.clone()), PlaybackStatus::Stopped => (None, None), }; tx.send(val).await?; } } Ok(()) } async fn update( (color, background): Self::Value, block: Arc>, ) -> Result { let mut block = block.lock().await; block.color = color; block.background = background; Ok(true) } }