summaryrefslogtreecommitdiffstats
path: root/src/component.rs
diff options
context:
space:
mode:
authorToby Vincent <tobyv@tobyvin.dev>2024-07-21 17:04:19 -0500
committerToby Vincent <tobyv@tobyvin.dev>2024-07-21 17:04:19 -0500
commit642557c36d5f431e09afd2c3989617af05e6f72b (patch)
tree133c9ef1a9e0a3244cf0fd3958e2712d6cc52cef /src/component.rs
parent06dadd8cfc92b4276d44a203cb33c7b08daab308 (diff)
perf: add component block init and output actions
Diffstat (limited to 'src/component.rs')
-rw-r--r--src/component.rs111
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)
}
}