diff options
Diffstat (limited to 'src/listener.rs')
-rw-r--r-- | src/listener.rs | 115 |
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(()) |