diff options
author | Toby Vincent <tobyv@tobyvin.dev> | 2024-07-21 17:04:19 -0500 |
---|---|---|
committer | Toby Vincent <tobyv@tobyvin.dev> | 2024-07-21 17:04:19 -0500 |
commit | 642557c36d5f431e09afd2c3989617af05e6f72b (patch) | |
tree | 133c9ef1a9e0a3244cf0fd3958e2712d6cc52cef /src/component.rs | |
parent | 06dadd8cfc92b4276d44a203cb33c7b08daab308 (diff) |
perf: add component block init and output actions
Diffstat (limited to 'src/component.rs')
-rw-r--r-- | src/component.rs | 111 |
1 files changed, 61 insertions, 50 deletions
diff --git a/src/component.rs b/src/component.rs index 3c294b3..e06f2cb 100644 --- a/src/component.rs +++ b/src/component.rs @@ -1,6 +1,6 @@ use std::{ future::Future, - io::{BufReader, Read}, + io::{BufReader, Read, Write}, marker::Send, sync::Arc, }; @@ -35,10 +35,11 @@ mod title; mod volume; pub trait Component: Send + 'static { - const NAME: &'static str; type Updater: Update; type Colorer: Update; type Handler: Button; + + fn initialize() -> Block; } pub trait Runner: Component + private::Sealed { @@ -48,7 +49,9 @@ pub trait Runner: Component + private::Sealed { let conn = Connection::session().await?; - let listeners = tokio::spawn(Self::listeners(conn.clone())); + let writer = std::io::stdout(); + + let listeners = tokio::spawn(Self::listeners(conn.clone(), writer)); let buf_reader = BufReader::new(reader); for click in buf_reader @@ -63,79 +66,79 @@ pub trait Runner: Component + private::Sealed { } } - fn listeners(conn: Connection) -> impl Future<Output = Result<(), Error>> + Send { + fn listeners<W: Write + Send>( + conn: Connection, + mut writer: W, + ) -> impl Future<Output = Result<(), Error>> + Send { async move { - use futures_util::StreamExt; - 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?; - - tokio::spawn(async move { - let mut last = proxy - .player_names() - .await? - .into_iter() - .find(|s| s.split('.').nth(3).is_some_and(|s| !IGNORED.contains(&s))) - .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(Self::initialize())); - let block = Arc::new(Mutex::new(Block { - name: Some(format!("mpris-{}", Self::NAME)), - ..Default::default() - })); + tokio::spawn(Self::active_listener(conn.clone(), tx_player)); loop { - let updated = tokio::select! { + let output = tokio::select! { Some(name) = rx_player.recv() => { join_set.shutdown().await; let mut block = block.lock().await; - block.full_text = String::new(); - block.instance = None; + *block = Self::initialize(); if !name.is_empty() { block.instance.clone_from(&Some(name.clone())); let proxy = PlayerProxy::builder(&conn) - .destination(name)? + .destination(name.clone())? .build() .await?; join_set.spawn(<Self::Colorer as Update>::listen(tx_status.clone(), proxy.clone())); join_set.spawn(<Self::Updater as Update>::listen(tx_value.clone(), proxy)); - false - } else { - true } + Output::Clear } Some(color) = rx_status.recv() => <Self::Colorer as Update>::update(color, block.clone()).await?, Some(value) = rx_value.recv() => <Self::Updater as Update>::update(value, block.clone()).await? }; - if updated { - let s = block.lock().await; - s.write_stdout()?; + match output { + Output::Print => (block.lock().await).write_to(&mut writer)?, + Output::Clear => writer.write_all(&[b'\n'])?, + Output::Skip => continue, } + + writer.flush()?; } } } + + fn active_listener( + conn: Connection, + tx: Sender<String>, + ) -> impl std::future::Future<Output = Result<(), Error>> + Send { + use futures_util::StreamExt; + + async move { + let proxy = PlayerctldProxy::builder(&conn).build().await?; + let mut last = String::new(); + let mut stream = proxy.receive_player_names_changed().await; + while let Some(signal) = stream.next().await { + let name = signal + .get() + .await? + .into_iter() + .find(|s| s.split('.').nth(3).is_some_and(|s| !IGNORED.contains(&s))) + .unwrap_or_default(); + if name != last { + last.clone_from(&name); + tx.send(name).await?; + } + } + Ok(()) + } + } } impl<T: Component> Runner for T {} @@ -146,6 +149,14 @@ mod private { impl<T: super::Component> Sealed for T {} } +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub enum Output { + Print, + Clear, + #[default] + Skip, +} + pub trait Update: Send + 'static { type Value: Send; @@ -157,7 +168,7 @@ pub trait Update: Send + 'static { fn update( value: Self::Value, block: Arc<Mutex<Block>>, - ) -> impl Future<Output = Result<bool, Error>> + Send; + ) -> impl Future<Output = Result<Output, Error>> + Send; } impl Update for () { @@ -167,8 +178,8 @@ impl Update for () { Ok(()) } - async fn update(_: Self::Value, _: Arc<Mutex<Block>>) -> Result<bool, Error> { - Ok(false) + async fn update(_: Self::Value, _: Arc<Mutex<Block>>) -> Result<Output, Error> { + Ok(Output::Skip) } } @@ -199,11 +210,11 @@ impl Update for PlaybackStatus { async fn update( (color, background): Self::Value, block: Arc<Mutex<Block>>, - ) -> Result<bool, Error> { + ) -> Result<Output, Error> { let mut block = block.lock().await; block.color = color; block.background = background; - Ok(true) + Ok(Output::Print) } } |