diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 139 |
1 files changed, 90 insertions, 49 deletions
@@ -1,68 +1,109 @@ -use dbus::{ - player::{PlaybackStatus, PlayerProxy}, - playerctld::PlayerctldProxy, -}; -pub use error::{Error, Result}; +use std::sync::Arc; use futures_util::StreamExt; -use tokio::sync::mpsc::Sender; +use tokio::{sync::Mutex, task::JoinSet}; +use zbus::Connection; -pub mod color; +pub use crate::{ + component::{Button, Component, Update}, + error::{Error, Result}, +}; +use crate::{ + dbus::{player::PlayerProxy, playerctld::PlayerctldProxy}, + i3bar::{Block, Click}, +}; + +pub mod component; pub mod dbus; pub mod error; pub mod i3bar; -const BLACK: &str = "#1d2021"; -const YELLOW: &str = "#fabd2f"; -const CYAN: &str = "#8ec07c"; - const IGNORED: [&str; 2] = ["playerctld", "kdeconnect"]; -impl From<PlaybackStatus> for (Option<String>, Option<String>) { - fn from(value: PlaybackStatus) -> Self { - match value { - PlaybackStatus::Playing => (Some(BLACK.into()), Some(CYAN.into())), - PlaybackStatus::Paused => (Some(BLACK.into()), Some(YELLOW.into())), - PlaybackStatus::Stopped => (None, None), - } - } -} +pub async fn run<C>(mut block: Block) -> Result<(), Error> +where + C: Component, +{ + let conn = Connection::session().await?; -pub async fn color_listener( - tx: Sender<(Option<String>, Option<String>)>, - proxy: PlayerProxy<'_>, -) -> Result<()> { - let mut stream = proxy.receive_playback_status_changed().await; - while let Some(signal) = stream.next().await { - if let Ok(value) = signal.get().await { - tx.send(value.into()).await?; - } + block.name = Some(format!("mpris-{}", C::NAME)); + tokio::spawn(listeners::<C>(conn.clone(), block)); + + for click in std::io::stdin() + .lines() + .map_while(Result::ok) + .flat_map(|s| serde_json::from_str::<Click>(&s)) + { + <<C as Component>::Handler as Button>::handle(conn.clone(), click).await?; } + Ok(()) } -pub async fn player_listener(tx: Sender<String>, proxy: PlayerctldProxy<'_>) -> Result<(), Error> { - let mut last = proxy - .player_names() - .await? - .into_iter() - .next() - .unwrap_or_default(); +async fn listeners<C>(conn: Connection, block: Block) -> Result<(), Error> +where + C: Component, +{ + let mut join_set = JoinSet::new(); + + let (tx_player, mut rx_player) = tokio::sync::mpsc::channel(128); + let (tx_status, mut rx_status) = tokio::sync::mpsc::channel(128); + let (tx_value, mut rx_value) = tokio::sync::mpsc::channel(128); + + let proxy = PlayerctldProxy::builder(&conn).build().await?; - tx.send(last.clone()).await?; + tokio::spawn(async move { + let mut last = proxy + .player_names() + .await? + .into_iter() + .next() + .unwrap_or_default(); + tx_player.send(last.clone()).await?; + let mut stream = proxy.receive_active_player_change_end().await?; + while let Some(signal) = stream.next().await { + let name = signal.args()?.name.to_owned(); + if name != last + && name + .split('.') + .nth(3) + .is_some_and(|s| !IGNORED.contains(&s)) + { + last.clone_from(&name); + tx_player.send(name).await?; + } + } + Result::<_, Error>::Ok(()) + }); + + let block = Arc::new(Mutex::new(block)); - let mut stream = proxy.receive_active_player_change_end().await?; - while let Some(signal) = stream.next().await { - let name = signal.args()?.name.to_owned(); - if name != last - && name - .split('.') - .nth(3) - .is_some_and(|s| !IGNORED.contains(&s)) - { - last.clone_from(&name); - tx.send(name).await?; + loop { + let updated = tokio::select! { + Some(name) = rx_player.recv() => { + join_set.shutdown().await; + if name.is_empty() { + let mut block = block.lock().await; + block.full_text = String::new(); + block.instance = None; + true + } else { + let proxy = PlayerProxy::builder(&conn) + .destination(name)? + .build() + .await?; + join_set.spawn(<<C as Component>::Colorer as Update>::listen(tx_status.clone(), proxy.clone())); + join_set.spawn(<<C as Component>::Updater as Update>::listen(tx_value.clone(), proxy)); + false + } + } + Some(color) = rx_status.recv() => <<C as Component>::Colorer as Update>::update(color, block.clone()).await?, + Some(value) = rx_value.recv() => <<C as Component>::Updater as Update>::update(value, block.clone()).await? + }; + + if updated { + let s = block.lock().await; + s.write_stdout()?; } } - Ok(()) } |