summaryrefslogtreecommitdiffstats
path: root/src/listener.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/listener.rs')
-rw-r--r--src/listener.rs115
1 files changed, 61 insertions, 54 deletions
diff --git a/src/listener.rs b/src/listener.rs
index 88efb6c..5f86d18 100644
--- a/src/listener.rs
+++ b/src/listener.rs
@@ -1,8 +1,7 @@
use std::{ops::ControlFlow, sync::LazyLock, time::Duration};
-use tokio::task::JoinHandle;
use tokio_stream::StreamExt;
-use zbus::{proxy::PropertyChanged, Connection};
+use zbus::{names::UniqueName, proxy::PropertyChanged, Connection};
use crate::{
dbus::player::{Metadata, PlaybackStatus, PlayerProxy},
@@ -22,80 +21,88 @@ static COLORS: LazyLock<[String; 3]> = LazyLock::new(|| {
});
pub async fn listeners(conn: Connection, blocks: State) -> Result<(), Error> {
- let proxy = PlayerProxy::builder(&conn)
- .destination("org.mpris.MediaPlayer2.playerctld")?
- .build()
- .await?;
-
- let mut rotator: Option<JoinHandle<Result<(), Error>>> = None;
- let mut old_title = String::new();
-
- let mut metadata = proxy.receive_metadata_changed().await;
- let mut prev = proxy.receive_can_go_previous_changed().await;
- let mut play = proxy.receive_playback_status_changed().await;
- let mut next = proxy.receive_can_go_next_changed().await;
- let mut volume = proxy.receive_volume_changed().await;
-
loop {
- tokio::select! {
- Some(prop) = metadata.next() => handle_metadata(prop, blocks.clone(), &mut old_title, &mut rotator).await,
- Some(prop) = prev.next() => handle_prev_next(prop, blocks.clone(), BlockKind::Prev).await,
- Some(prop) = play.next() => handle_play(prop, blocks.clone()).await,
- Some(prop) = next.next() => handle_prev_next(prop, blocks.clone(), BlockKind::Next).await,
- Some(prop) = volume.next() => handle_volume(prop, blocks.clone()).await,
- else => {
- eprintln!("Failed to get next property");
- break
+ let player_proxy = PlayerProxy::builder(&conn)
+ .destination("org.mpris.MediaPlayer2.playerctld")?
+ .build()
+ .await?;
+
+ //let mut rotator: Option<JoinHandle<Result<(), Error>>> = None;
+ let mut old_title = String::new();
+ let mut chars: Vec<char> = Vec::new();
+
+ let mut owner_changed = player_proxy.inner().receive_owner_changed().await?;
+ let mut metadata = player_proxy.receive_metadata_changed().await;
+ let mut prev = player_proxy.receive_can_go_previous_changed().await;
+ let mut play = player_proxy.receive_playback_status_changed().await;
+ let mut next = player_proxy.receive_can_go_next_changed().await;
+ let mut volume = player_proxy.receive_volume_changed().await;
+
+ loop {
+ let control_flow = tokio::select! {
+ Some(prop) = owner_changed.next() => handle_owner_changed(prop).await,
+ Some(prop) = metadata.next() => handle_metadata(prop, blocks.clone(), &mut old_title, &mut chars).await,
+ Some(prop) = prev.next() => handle_prev_next(prop, blocks.clone(), BlockKind::Prev).await,
+ Some(prop) = play.next() => handle_play(prop, blocks.clone()).await,
+ Some(prop) = next.next() => handle_prev_next(prop, blocks.clone(), BlockKind::Next).await,
+ Some(prop) = volume.next() => handle_volume(prop, blocks.clone()).await,
+ _ = tokio::time::sleep(TICK_RATE), if chars.len() > 10 => {
+ chars.rotate_left(1);
+ handle_title(&chars, blocks.clone()).await
+ }
+ };
+
+ match control_flow {
+ ControlFlow::Continue(_) => blocks.notify.notify_one(),
+ ControlFlow::Break(res) => {
+ res?;
+ break;
+ }
}
-
- };
-
- blocks.notify.notify_one();
+ }
}
-
- Ok(())
}
-async fn title_rotator(blocks: State, title: String) -> Result<(), Error> {
- let mut interval = tokio::time::interval(TICK_RATE);
- let mut chars = title.chars().collect::<Vec<char>>();
- chars.push(' ');
- let full_text = String::from_iter(chars[0..10].iter());
+async fn handle_owner_changed(prop: Option<UniqueName<'static>>) -> ControlFlow<Result<(), Error>> {
+ if prop.is_none() {
+ ControlFlow::Break(Ok(()))
+ } else {
+ ControlFlow::Continue(())
+ }
+}
+async fn handle_title(title: &[char], blocks: State) -> ControlFlow<Result<(), Error>> {
let block = &mut blocks.value.write().await[BlockKind::Title as usize];
- block.min_width = Some(MinWidth::Text(full_text.len() + 1));
- block.full_text = full_text;
- block.enabled = false;
+ block.full_text = String::from_iter(title.iter().take(10));
+ block.min_width = Some(MinWidth::Text(block.full_text.len() + 1));
+ block.enabled = true;
- loop {
- interval.tick().await;
- let block = &mut blocks.value.write().await[BlockKind::Title as usize];
- block.full_text = String::from_iter(chars[0..10].iter());
- chars.rotate_left(1);
- }
+ ControlFlow::Continue(())
}
async fn handle_metadata(
prop: PropertyChanged<'_, Metadata>,
blocks: State,
old_title: &mut String,
- rotator: &mut Option<JoinHandle<Result<(), Error>>>,
+ chars: &mut Vec<char>,
) -> ControlFlow<Result<(), Error>> {
- let title = match prop.get().await.map(|m| m.title) {
+ let title = match prop
+ .get()
+ .await
+ .map(|m| m.title)
+ .inspect_err(|err| eprintln!("{err}"))
+ {
Ok(Some(s)) if *old_title != s => s,
_ => return ControlFlow::Continue(()),
};
old_title.clone_from(&title);
- rotator.take().into_iter().for_each(|h| h.abort());
+
+ *chars = title.chars().collect::<Vec<char>>();
+ handle_title(chars, blocks).await;
if title.len() >= 10 {
- *rotator = Some(tokio::spawn(title_rotator(blocks.clone(), title)));
- } else {
- let block = &mut blocks.value.write().await[BlockKind::Title as usize];
- block.min_width = Some(MinWidth::Text(title.len() + 1));
- block.full_text = title;
- block.enabled = true;
+ chars.push(' ');
}
ControlFlow::Continue(())