summaryrefslogtreecommitdiffstats
path: root/src/component.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/component.rs')
-rw-r--r--src/component.rs232
1 files changed, 0 insertions, 232 deletions
diff --git a/src/component.rs b/src/component.rs
deleted file mode 100644
index e06f2cb..0000000
--- a/src/component.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-use std::{
- future::Future,
- io::{BufReader, Read, Write},
- marker::Send,
- sync::Arc,
-};
-
-use tokio::{
- sync::{mpsc::Sender, Mutex},
- task::JoinSet,
-};
-use zbus::Connection;
-
-use crate::{
- dbus::{
- player::{PlaybackStatus, PlayerProxy},
- playerctld::PlayerctldProxy,
- },
- i3bar::{Block, Click},
- Error, IGNORED,
-};
-
-pub use icon::Icon;
-pub use next::Next;
-pub use play::Play;
-pub use prev::Prev;
-pub use title::Title;
-pub use volume::Volume;
-
-mod icon;
-mod next;
-mod play;
-mod prev;
-mod title;
-mod volume;
-
-pub trait Component: Send + 'static {
- type Updater: Update;
- type Colorer: Update;
- type Handler: Button;
-
- fn initialize() -> Block;
-}
-
-pub trait Runner: Component + private::Sealed {
- fn run<R: Read + Send>(reader: R) -> impl Future<Output = Result<(), Error>> + Send {
- async move {
- use std::io::BufRead;
-
- let conn = Connection::session().await?;
-
- 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
- .lines()
- .map_while(Result::ok)
- .flat_map(|s| serde_json::from_str::<Click>(&s))
- {
- let _ = <Self::Handler as Button>::handle(conn.clone(), click).await;
- }
-
- listeners.await?
- }
- }
-
- fn listeners<W: Write + Send>(
- conn: Connection,
- mut writer: W,
- ) -> impl Future<Output = Result<(), Error>> + Send {
- async move {
- 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 block = Arc::new(Mutex::new(Self::initialize()));
-
- tokio::spawn(Self::active_listener(conn.clone(), tx_player));
-
- loop {
- let output = tokio::select! {
- Some(name) = rx_player.recv() => {
- join_set.shutdown().await;
-
- let mut block = block.lock().await;
- *block = Self::initialize();
- if !name.is_empty() {
- block.instance.clone_from(&Some(name.clone()));
- let proxy = PlayerProxy::builder(&conn)
- .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));
- }
- 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?
- };
-
- 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 {}
-
-mod private {
- pub trait Sealed {}
-
- 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;
-
- fn listen(
- tx: Sender<Self::Value>,
- proxy: PlayerProxy<'_>,
- ) -> impl Future<Output = Result<(), Error>> + Send;
-
- fn update(
- value: Self::Value,
- block: Arc<Mutex<Block>>,
- ) -> impl Future<Output = Result<Output, Error>> + Send;
-}
-
-impl Update for () {
- type Value = ();
-
- async fn listen(_: Sender<Self::Value>, _: PlayerProxy<'_>) -> Result<(), Error> {
- Ok(())
- }
-
- async fn update(_: Self::Value, _: Arc<Mutex<Block>>) -> Result<Output, Error> {
- Ok(Output::Skip)
- }
-}
-
-impl Update for PlaybackStatus {
- type Value = (Option<String>, Option<String>);
-
- async fn listen(tx: Sender<Self::Value>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
- use futures_util::StreamExt;
-
- let black = std::env::var("BASE16_COLOR_00_HEX").ok();
- let cyan = std::env::var("BASE16_COLOR_0C_HEX").ok();
- let yellow = std::env::var("BASE16_COLOR_0A_HEX").ok();
-
- let mut stream = proxy.receive_playback_status_changed().await;
- while let Some(signal) = stream.next().await {
- if let Ok(value) = signal.get().await {
- let val = match value {
- PlaybackStatus::Playing => (black.clone(), cyan.clone()),
- PlaybackStatus::Paused => (black.clone(), yellow.clone()),
- PlaybackStatus::Stopped => (None, None),
- };
- tx.send(val).await?;
- }
- }
- Ok(())
- }
-
- async fn update(
- (color, background): Self::Value,
- block: Arc<Mutex<Block>>,
- ) -> Result<Output, Error> {
- let mut block = block.lock().await;
- block.color = color;
- block.background = background;
- Ok(Output::Print)
- }
-}
-
-pub trait Button {
- fn handle(
- conn: zbus::Connection,
- click: crate::i3bar::Click,
- ) -> impl Future<Output = Result<(), Error>> + Send;
-}
-
-impl Button for () {
- async fn handle(_: zbus::Connection, _: crate::i3bar::Click) -> Result<(), Error> {
- Ok(())
- }
-}