summaryrefslogtreecommitdiffstats
path: root/src/printer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/printer.rs')
-rw-r--r--src/printer.rs201
1 files changed, 70 insertions, 131 deletions
diff --git a/src/printer.rs b/src/printer.rs
index db5a554..5a6b0ae 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -1,8 +1,9 @@
-use std::{collections::HashMap, io::Write, sync::Arc, time::Duration};
+use std::{collections::HashMap, sync::Arc, time::Duration};
use futures_util::stream::StreamExt;
+use serde::{Deserialize, Serialize};
use tokio::{
- sync::{Mutex, Notify},
+ sync::{watch::Sender, Mutex},
task::{JoinHandle, JoinSet},
};
use zbus::{proxy::PropertyStream, zvariant::OwnedValue};
@@ -21,226 +22,163 @@ const BLACK: &str = "#1d2021";
const YELLOW: &str = "#fabd2f";
const CYAN: &str = "#8ec07c";
-#[derive(Debug, Clone)]
-pub enum Signal {
- Print,
-}
-
-pub async fn printer(proxy: PlayerProxy<'static>) -> Result<()> {
+pub async fn printer(
+ proxy: PlayerProxy<'static>,
+ wtx: tokio::sync::watch::Sender<Status>,
+) -> Result<()> {
let mut join_set: JoinSet<Result<()>> = JoinSet::new();
let mut rotator = None;
- let notify = Arc::new(Notify::new());
-
- let status = Arc::new(Mutex::new(Status {
- title: None,
+ let status = Status {
can_go_previous: proxy.can_go_previous().await.unwrap_or_default(),
playback_status: proxy.playback_status().await.unwrap_or_default(),
can_go_next: proxy.can_go_next().await.unwrap_or_default(),
volume: proxy.volume().await.ok(),
- indexes: Vec::new(),
- }));
+ ..Default::default()
+ };
+
+ wtx.send_modify(|s| *s = status);
process_metadata(
- notify.clone(),
- status.clone(),
+ wtx.clone(),
proxy.metadata().await?,
&mut rotator,
+ &mut None,
)
.await;
- notify.notify_one();
-
join_set.spawn(metadata(
- notify.clone(),
+ wtx.clone(),
proxy.receive_metadata_changed().await,
- status.clone(),
rotator,
));
join_set.spawn(can_go_previous(
- notify.clone(),
+ wtx.clone(),
proxy.receive_can_go_previous_changed().await,
- status.clone(),
));
join_set.spawn(playback_state(
- notify.clone(),
+ wtx.clone(),
proxy.receive_playback_status_changed().await,
- status.clone(),
));
join_set.spawn(can_go_next(
- notify.clone(),
+ wtx.clone(),
proxy.receive_can_go_next_changed().await,
- status.clone(),
));
- join_set.spawn(volume(
- notify.clone(),
- proxy.receive_volume_changed().await,
- status.clone(),
- ));
+ join_set.spawn(volume(wtx.clone(), proxy.receive_volume_changed().await));
- loop {
- notify.notified().await;
- let mut status = status.lock().await;
-
- //let (color, background) = match proxy.playback_status().await.ok() {
- // Some(PlaybackStatus::Playing) => (Some(BLACK.into()), Some(CYAN.into())),
- // Some(PlaybackStatus::Paused) => (Some(BLACK.into()), Some(YELLOW.into())),
- // Some(PlaybackStatus::Stopped) => (None, None),
- //};
-
- //let s = match instance {
- // Instance::Icon => " 󰝚 ",
- // Instance::Title => &status.title,
- // Instance::Prev => " 󰒮 ",
- // Instance::Play => " 󰏤 ",
- // Instance::Pause => " 󰐊 ",
- // Instance::Next => " 󰒭 ",
- // Instance::Volume => {
- // if let Some(volume) = self.volume.map(|v| (v * 100_f64) as u32) {
- // match volume {
- // v @ 66.. => &format!("󰕾 {v}% "),
- // v @ 33.. => &format!("󰖀 {v}% "),
- // v @ 0.. => &format!("󰕿 {v}% "),
- // }
- // }
- // }
- //};
- //
- //let block = Block {
- // full_text,
- // ..Default::default()
- //};
-
- let mut w = std::io::stdout().lock();
- let mut v = serde_json::to_vec(&status.build()).unwrap();
- v.push(b'\n');
- w.write_all(&v)?;
- w.flush()?;
+ while let Some(res) = join_set.join_next().await {
+ res??;
}
+
+ Ok(())
}
async fn process_metadata(
- notify: Arc<Notify>,
- status_lock: StatusLock,
+ wtx: Sender<Status>,
metadata: HashMap<String, OwnedValue>,
rotator: &mut Option<JoinHandle<Result<()>>>,
-) -> Option<()> {
- let title: String = metadata
- .get("xesam:title")?
- .try_to_owned()
- .ok()?
- .try_into()
- .ok()?;
-
- if (status_lock.lock().await)
- .title
- .as_ref()
- .is_some_and(|s| *s == title)
- {
- return None;
+ old_title: &mut Option<String>,
+) {
+ let title: Option<String> = metadata
+ .get("xesam:title")
+ .and_then(|o| o.try_to_owned().ok())
+ .and_then(|o| o.try_into().ok());
+
+ if *old_title == title {
+ return;
}
- if let Some(h) = rotator.take() {
- h.abort()
+ *old_title = title.clone();
+ let Some(title) = title else {
+ wtx.send_modify(|s| {
+ s.title = None;
+ });
+ return;
};
- let status = status_lock.clone();
-
if title.len() > 10 {
+ if let Some(h) = rotator.take() {
+ h.abort()
+ };
+
+ let wtx = wtx.clone();
*rotator = Some(tokio::spawn(async move {
let mut interval = tokio::time::interval(TICK_RATE);
let mut chars = title.chars().collect::<Vec<char>>();
chars.push(' ');
loop {
interval.tick().await;
- let mut status = status.lock().await;
- status.title = Some(chars[0..10].iter().collect());
- notify.notify_one();
+ wtx.send_modify(|s| s.title = Some(chars[0..10].iter().collect()));
chars.rotate_left(1);
}
}));
} else {
- let mut status = status.lock().await;
- status.title = Some(title);
- notify.notify_one();
+ wtx.send_modify(|s| s.title = Some(title));
}
-
- Some(())
}
async fn metadata(
- notify: Arc<Notify>,
+ wtx: Sender<Status>,
mut stream: PropertyStream<'_, HashMap<String, OwnedValue>>,
- status_lock: StatusLock,
mut rotator: Option<JoinHandle<Result<()>>>,
) -> Result<()> {
+ let mut old_title = None;
while let Some(signal) = stream.next().await {
if let Ok(metadata) = signal.get().await {
- process_metadata(notify.clone(), status_lock.clone(), metadata, &mut rotator).await;
+ process_metadata(wtx.clone(), metadata, &mut rotator, &mut old_title).await
};
}
Ok(())
}
-async fn can_go_previous(
- notify: Arc<Notify>,
- mut stream: PropertyStream<'_, bool>,
- status_lock: StatusLock,
-) -> Result<()> {
+async fn can_go_previous(wtx: Sender<Status>, mut stream: PropertyStream<'_, bool>) -> Result<()> {
while let Some(signal) = stream.next().await {
if let Ok(val) = signal.get().await {
- let mut status = status_lock.lock().await;
- status.can_go_previous = val;
- notify.notify_one();
+ wtx.send_modify(|status| status.can_go_previous = val);
};
}
Ok(())
}
async fn playback_state(
- notify: Arc<Notify>,
+ wtx: Sender<Status>,
mut stream: PropertyStream<'_, PlaybackStatus>,
- status_lock: StatusLock,
) -> Result<()> {
while let Some(signal) = stream.next().await {
if let Ok(val) = signal.get().await {
- let mut status = status_lock.lock().await;
- status.playback_status = val;
- notify.notify_one();
+ let (color, background) = match val {
+ PlaybackStatus::Playing => (Some(BLACK.into()), Some(CYAN.into())),
+ PlaybackStatus::Paused => (Some(BLACK.into()), Some(YELLOW.into())),
+ PlaybackStatus::Stopped => (None, None),
+ };
+
+ wtx.send_modify(|status| {
+ status.playback_status = val;
+ status.color = color;
+ status.background = background;
+ });
}
}
Ok(())
}
-async fn can_go_next(
- notify: Arc<Notify>,
- mut stream: PropertyStream<'_, bool>,
- status_lock: StatusLock,
-) -> Result<()> {
+async fn can_go_next(wtx: Sender<Status>, mut stream: PropertyStream<'_, bool>) -> Result<()> {
while let Some(signal) = stream.next().await {
if let Ok(val) = signal.get().await {
- let mut status = status_lock.lock().await;
- status.can_go_next = val;
- notify.notify_one();
+ wtx.send_modify(|status| status.can_go_next = val);
};
}
Ok(())
}
-async fn volume(
- notify: Arc<Notify>,
- mut stream: PropertyStream<'_, f64>,
- status_lock: StatusLock,
-) -> Result<()> {
+async fn volume(wtx: Sender<Status>, mut stream: PropertyStream<'_, f64>) -> Result<()> {
while let Some(signal) = stream.next().await {
if let Ok(val) = signal.get().await {
- let mut status = status_lock.lock().await;
- status.volume = Some(val);
- notify.notify_one();
+ wtx.send_modify(|status| status.volume = Some(val));
};
}
Ok(())
@@ -258,14 +196,15 @@ pub enum Component {
Space,
}
-#[derive(Debug, Clone, Default)]
+#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Status {
title: Option<String>,
can_go_previous: bool,
playback_status: PlaybackStatus,
can_go_next: bool,
volume: Option<f64>,
- indexes: Vec<(usize, Component)>,
+ color: Option<String>,
+ background: Option<String>,
}
impl Status {