summaryrefslogtreecommitdiffstats
path: root/src/bin
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/icon.rs78
-rw-r--r--src/bin/next.rs97
-rw-r--r--src/bin/play.rs129
-rw-r--r--src/bin/prev.rs97
-rw-r--r--src/bin/title.rs183
-rw-r--r--src/bin/volume.rs109
6 files changed, 338 insertions, 355 deletions
diff --git a/src/bin/icon.rs b/src/bin/icon.rs
index 6f2487f..4ffaaae 100644
--- a/src/bin/icon.rs
+++ b/src/bin/icon.rs
@@ -1,54 +1,52 @@
-use std::sync::Arc;
-
use i3blocks::{
- color_listener,
- dbus::{player::PlayerProxy, playerctld::PlayerctldProxy},
- i3bar::Block,
- player_listener,
+ dbus::{media_player2::MediaPlayer2Proxy, player::PlaybackStatus, playerctld::PlayerctldProxy},
+ i3bar::{Block, Click},
+ Button, Component, Error,
};
-use tokio::{sync::Mutex, task::JoinSet};
use zbus::Connection;
#[tokio::main]
async fn main() -> Result<(), main_error::MainError> {
- 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 conn = Connection::session().await?;
- let proxy = PlayerctldProxy::builder(&conn).build().await?;
-
- tokio::spawn(player_listener(tx_player, proxy));
-
- let status: Arc<Mutex<Block>> = Arc::new(Mutex::new(Block {
+ i3blocks::run::<Icon>(Block {
full_text: " 󰝚 ".into(),
..Default::default()
- }));
+ })
+ .await
+ .map_err(Into::into)
+}
- loop {
- tokio::select! {
- Some(name) = rx_player.recv() => {
- join_set.shutdown().await;
- if name.is_empty() {
- let mut status = status.lock().await;
- status.full_text = Default::default();
- } else {
- let proxy = PlayerProxy::builder(&conn)
- .destination(name)?
- .build()
- .await?;
- join_set.spawn(color_listener(tx_status.clone(), proxy.clone()));
- }
- }
- Some((color, background)) = rx_status.recv() => {
- let mut status = status.lock().await;
- status.color = color;
- status.background = background;
+pub struct Icon;
+
+impl Component for Icon {
+ const NAME: &'static str = "icon";
+ type Updater = ();
+ type Colorer = PlaybackStatus;
+ type Handler = Self;
+}
+
+impl Button for Icon {
+ async fn handle(conn: Connection, click: Click) -> Result<(), Error> {
+ let Some(name) = click.instance else {
+ return Ok(());
+ };
+
+ let proxy = MediaPlayer2Proxy::builder(&conn)
+ .destination(name)?
+ .build()
+ .await?;
+
+ match click.button {
+ 3 => {
+ PlayerctldProxy::builder(&conn)
+ .build()
+ .await?
+ .shift()
+ .await?;
}
+ 1 if proxy.can_raise().await? => proxy.raise().await?,
+ _ => {}
}
- let s = status.lock().await;
- s.write_stdout()?;
+ Ok(())
}
}
diff --git a/src/bin/next.rs b/src/bin/next.rs
index 108432c..2e3fd95 100644
--- a/src/bin/next.rs
+++ b/src/bin/next.rs
@@ -1,72 +1,69 @@
use std::sync::Arc;
-use futures_util::StreamExt;
use i3blocks::{
- color_listener,
- dbus::{player::PlayerProxy, playerctld::PlayerctldProxy},
- i3bar::Block,
- player_listener, Error,
-};
-use tokio::{
- sync::{mpsc::Sender, Mutex},
- task::JoinSet,
+ dbus::player::{PlaybackStatus, PlayerProxy},
+ i3bar::{Block, Click},
+ Button, Component, Error, Update,
};
+use tokio::sync::{mpsc::Sender, Mutex};
use zbus::Connection;
#[tokio::main]
async fn main() -> Result<(), main_error::MainError> {
- let mut join_set = JoinSet::new();
+ i3blocks::run::<Next>(Default::default())
+ .await
+ .map_err(Into::into)
+}
- 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);
+pub struct Next;
- let conn = Connection::session().await?;
- let proxy = PlayerctldProxy::builder(&conn).build().await?;
+impl Component for Next {
+ const NAME: &'static str = "next";
+ type Updater = Self;
+ type Colorer = PlaybackStatus;
+ type Handler = Self;
+}
- tokio::spawn(player_listener(tx_player, proxy));
+impl Update for Next {
+ type Value = bool;
- let status: Arc<Mutex<Block>> = Default::default();
+ async fn listen(tx: Sender<Self::Value>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
+ use futures_util::StreamExt;
- loop {
- tokio::select! {
- Some(name) = rx_player.recv() => {
- join_set.shutdown().await;
- if name.is_empty() {
- let mut status = status.lock().await;
- status.full_text = Default::default();
- } else {
- let proxy = PlayerProxy::builder(&conn)
- .destination(name)?
- .build()
- .await?;
- join_set.spawn(color_listener(tx_status.clone(), proxy.clone()));
- join_set.spawn(value_listener(tx_value.clone(), proxy));
- }
- }
- Some((color, background)) = rx_status.recv() => {
- let mut status = status.lock().await;
- status.color = color;
- status.background = background;
- }
- Some(value) = rx_value.recv() => {
- let mut status = status.lock().await;
- status.full_text = value.then_some( " 󰒭 ".into()).unwrap_or_default()
+ tx.send(proxy.can_go_previous().await?).await?;
+ let mut stream = proxy.receive_can_go_previous_changed().await;
+ while let Some(signal) = stream.next().await {
+ if let Ok(value) = signal.get().await {
+ tx.send(value).await?;
}
}
+ Ok(())
+ }
- let s = status.lock().await;
- s.write_stdout()?;
+ async fn update(value: Self::Value, block: Arc<Mutex<Block>>) -> Result<bool, Error> {
+ let mut block = block.lock().await;
+ block.full_text = value.then_some(" 󰒭 ".into()).unwrap_or_default();
+ Ok(true)
}
}
-pub async fn value_listener(tx: Sender<bool>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
- tx.send(proxy.can_go_next().await?).await?;
- let mut stream = proxy.receive_can_go_next_changed().await;
- while let Some(signal) = stream.next().await {
- if let Ok(value) = signal.get().await {
- tx.send(value).await?;
+impl Button for Next {
+ async fn handle(conn: Connection, click: Click) -> Result<(), Error> {
+ let Some(name) = click.instance else {
+ return Ok(());
+ };
+
+ let proxy = PlayerProxy::builder(&conn)
+ .destination(name)?
+ .build()
+ .await?;
+
+ match click.button {
+ 1 if proxy.can_go_next().await? => proxy.next().await?,
+ 3 if proxy.can_seek().await? => proxy.seek(5000).await?,
+ _ => {}
}
+
+ Ok(())
}
- Ok(())
}
diff --git a/src/bin/play.rs b/src/bin/play.rs
index 0863b7a..bf4f489 100644
--- a/src/bin/play.rs
+++ b/src/bin/play.rs
@@ -1,96 +1,79 @@
use std::sync::Arc;
-use futures_util::StreamExt;
use i3blocks::{
- dbus::{
- player::{PlaybackStatus, PlayerProxy},
- playerctld::PlayerctldProxy,
- },
- i3bar::Block,
- Error,
-};
-use tokio::{
- sync::{mpsc::Sender, Mutex},
- task::JoinSet,
+ dbus::player::{PlaybackStatus, PlayerProxy},
+ i3bar::{Block, Click},
+ Button, Component, Error, Update,
};
+use tokio::sync::{mpsc::Sender, Mutex};
use zbus::Connection;
#[tokio::main]
async fn main() -> Result<(), main_error::MainError> {
- let mut join_set = JoinSet::new();
+ i3blocks::run::<Play>(Default::default())
+ .await
+ .map_err(Into::into)
+}
- let (tx_player, mut rx_player) = tokio::sync::mpsc::channel(128);
- let (tx_value, mut rx_value) = tokio::sync::mpsc::channel(128);
+pub struct Play;
- let conn = Connection::session().await?;
- let proxy = PlayerctldProxy::builder(&conn).build().await?;
+impl Component for Play {
+ const NAME: &'static str = "play";
+ type Updater = Self;
+ type Colorer = ();
+ type Handler = Self;
+}
- tokio::spawn(player_listener(tx_player, proxy));
+impl Update for Play {
+ type Value = PlaybackStatus;
- let status: Arc<Mutex<Block>> = Default::default();
+ async fn listen(tx: Sender<Self::Value>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
+ use futures_util::StreamExt;
- loop {
- tokio::select! {
- Some(name) = rx_player.recv() => {
- println!("name: {name:?}");
- join_set.shutdown().await;
- if name.is_empty() {
- let mut status = status.lock().await;
- status.full_text = Default::default();
- } else {
- let proxy = PlayerProxy::builder(&conn)
- .destination(name)?
- .build()
- .await?;
- join_set.spawn(value_listener(tx_value.clone(), proxy));
- }
- }
- Some(value) = rx_value.recv() => {
- println!("value: {value:?}");
- let mut status = status.lock().await;
- let (color, background) = value.into();
- status.color = color;
- status.background = background;
- status.full_text = match value {
- PlaybackStatus::Playing => " 󰏤 ",
- _ => " 󰐊 ",
- }.into();
+ tx.send(proxy.playback_status().await?).await?;
+ let mut stream = proxy.receive_playback_status_changed().await;
+ while let Some(signal) = stream.next().await {
+ if let Ok(value) = signal.get().await {
+ tx.send(value).await?;
}
}
-
- let s = status.lock().await;
- s.write_stdout()?;
+ Ok(())
}
-}
-pub async fn value_listener(
- tx: Sender<PlaybackStatus>,
- proxy: PlayerProxy<'_>,
-) -> Result<(), Error> {
- tx.send(proxy.playback_status().await?).await?;
- let mut stream = proxy.receive_playback_status_changed().await;
- while let Some(signal) = stream.next().await {
- if let Ok(value) = signal.get().await {
- tx.send(value).await?;
- }
+ async fn update(value: Self::Value, block: Arc<Mutex<Block>>) -> Result<bool, Error> {
+ 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 (full_text, color, background) = match value {
+ PlaybackStatus::Playing => (" 󰏤 ", black.clone(), cyan.clone()),
+ PlaybackStatus::Paused => (" 󰐊 ", black.clone(), yellow.clone()),
+ PlaybackStatus::Stopped => (" 󰐊 ", None, None),
+ };
+
+ let mut block = block.lock().await;
+ block.full_text = full_text.into();
+ block.color = color;
+ block.background = background;
+ Ok(true)
}
- Ok(())
}
-async fn player_listener(tx: Sender<String>, proxy: PlayerctldProxy<'_>) -> Result<(), Error> {
- tx.send(
- proxy
- .player_names()
- .await?
- .into_iter()
- .next()
- .unwrap_or_default(),
- )
- .await?;
+impl Button for Play {
+ async fn handle(conn: Connection, click: Click) -> Result<(), Error> {
+ let Some(name) = click.instance else {
+ return Ok(());
+ };
+
+ if click.button == 1 {
+ PlayerProxy::builder(&conn)
+ .destination(name)?
+ .build()
+ .await?
+ .play_pause()
+ .await?
+ }
- let mut stream = proxy.receive_active_player_change_begin().await?;
- while let Some(signal) = stream.next().await {
- tx.send(signal.args()?.name.to_owned()).await?;
+ Ok(())
}
- Ok(())
}
diff --git a/src/bin/prev.rs b/src/bin/prev.rs
index f7f8dd9..7eec6c3 100644
--- a/src/bin/prev.rs
+++ b/src/bin/prev.rs
@@ -1,72 +1,69 @@
use std::sync::Arc;
-use futures_util::StreamExt;
use i3blocks::{
- color_listener,
- dbus::{player::PlayerProxy, playerctld::PlayerctldProxy},
- i3bar::Block,
- player_listener, Error,
-};
-use tokio::{
- sync::{mpsc::Sender, Mutex},
- task::JoinSet,
+ dbus::player::{PlaybackStatus, PlayerProxy},
+ i3bar::{Block, Click},
+ Button, Component, Error, Update,
};
+use tokio::sync::{mpsc::Sender, Mutex};
use zbus::Connection;
#[tokio::main]
async fn main() -> Result<(), main_error::MainError> {
- let mut join_set = JoinSet::new();
+ i3blocks::run::<Previous>(Default::default())
+ .await
+ .map_err(Into::into)
+}
- 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);
+pub struct Previous;
- let conn = Connection::session().await?;
- let proxy = PlayerctldProxy::builder(&conn).build().await?;
+impl Component for Previous {
+ const NAME: &'static str = "previous";
+ type Updater = Self;
+ type Colorer = PlaybackStatus;
+ type Handler = Self;
+}
- tokio::spawn(player_listener(tx_player, proxy));
+impl Update for Previous {
+ type Value = bool;
- let status: Arc<Mutex<Block>> = Default::default();
+ async fn listen(tx: Sender<Self::Value>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
+ use futures_util::StreamExt;
- loop {
- tokio::select! {
- Some(name) = rx_player.recv() => {
- join_set.shutdown().await;
- if name.is_empty() {
- let mut status = status.lock().await;
- status.full_text = Default::default();
- } else {
- let proxy = PlayerProxy::builder(&conn)
- .destination(name)?
- .build()
- .await?;
- join_set.spawn(color_listener(tx_status.clone(), proxy.clone()));
- join_set.spawn(value_listener(tx_value.clone(), proxy));
- }
- }
- Some((color, background)) = rx_status.recv() => {
- let mut status = status.lock().await;
- status.color = color;
- status.background = background;
- }
- Some(value) = rx_value.recv() => {
- let mut status = status.lock().await;
- status.full_text = value.then_some( " 󰒮 ".into()).unwrap_or_default()
+ tx.send(proxy.can_go_previous().await?).await?;
+ let mut stream = proxy.receive_can_go_previous_changed().await;
+ while let Some(signal) = stream.next().await {
+ if let Ok(value) = signal.get().await {
+ tx.send(value).await?;
}
}
+ Ok(())
+ }
- let s = status.lock().await;
- s.write_stdout()?;
+ async fn update(value: Self::Value, block: Arc<Mutex<Block>>) -> Result<bool, Error> {
+ let mut block = block.lock().await;
+ block.full_text = value.then_some(" 󰒮 ".into()).unwrap_or_default();
+ Ok(true)
}
}
-pub async fn value_listener(tx: Sender<bool>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
- tx.send(proxy.can_go_previous().await?).await?;
- let mut stream = proxy.receive_can_go_previous_changed().await;
- while let Some(signal) = stream.next().await {
- if let Ok(value) = signal.get().await {
- tx.send(value).await?;
+impl Button for Previous {
+ async fn handle(conn: Connection, click: Click) -> Result<(), Error> {
+ let Some(name) = click.instance else {
+ return Ok(());
+ };
+
+ let proxy = PlayerProxy::builder(&conn)
+ .destination(name)?
+ .build()
+ .await?;
+
+ match click.button {
+ 1 if proxy.can_go_previous().await? => proxy.previous().await?,
+ 3 if proxy.can_seek().await? => proxy.seek(-5000).await?,
+ _ => {}
}
+
+ Ok(())
}
- Ok(())
}
diff --git a/src/bin/title.rs b/src/bin/title.rs
index 165e715..3daee26 100644
--- a/src/bin/title.rs
+++ b/src/bin/title.rs
@@ -1,113 +1,120 @@
-use std::{sync::Arc, time::Duration};
+use std::{collections::HashMap, sync::Arc, time::Duration};
-use futures_util::StreamExt;
use i3blocks::{
- color_listener,
- dbus::{player::PlayerProxy, playerctld::PlayerctldProxy},
+ dbus::player::{PlaybackStatus, PlayerProxy},
i3bar::Block,
- player_listener, Error,
+ Component, Error, Update,
};
use tokio::{
sync::{mpsc::Sender, Mutex},
task::{AbortHandle, JoinSet},
};
-use zbus::Connection;
+use zbus::zvariant::OwnedValue;
const TICK_RATE: Duration = Duration::from_millis(500);
#[tokio::main]
async fn main() -> Result<(), main_error::MainError> {
- 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 conn = Connection::session().await?;
- let proxy = PlayerctldProxy::builder(&conn).build().await?;
-
- tokio::spawn(player_listener(tx_player, proxy));
-
- let status: Arc<Mutex<Block>> = Default::default();
- let mut rotator: Option<AbortHandle> = None;
-
- let mut interval = tokio::time::interval(TICK_RATE);
- let mut chars = Vec::new();
-
- loop {
- tokio::select! {
- Some(name) = rx_player.recv() => {
- join_set.shutdown().await;
- if name.is_empty() {
- let mut status = status.lock().await;
- status.full_text = Default::default();
- } else {
- let proxy = PlayerProxy::builder(&conn)
- .destination(name)?
- .build()
- .await?;
- join_set.spawn(color_listener(tx_status.clone(), proxy.clone()));
- join_set.spawn(value_listener(tx_value.clone(), proxy));
- }
- }
- Some((color, background)) = rx_status.recv() => {
- let mut status = status.lock().await;
- status.color = color;
- status.background = background;
- }
- Some(mut value) = rx_value.recv() => {
- if let Some(h) = rotator.take() {
- h.abort();
- }
+ i3blocks::run::<Title>(Default::default())
+ .await
+ .map_err(Into::into)
+}
- value.push(' ');
- if value.len() >= 10 {
- chars = value.chars().collect::<Vec<char>>();
- let mut status = status.lock().await;
- status.full_text = format!("{} ", String::from_iter(chars[0..10].iter()));
- } else {
- chars = Default::default();
- let mut status = status.lock().await;
- status.full_text = value;
- }
- }
- _ = interval.tick(), if !chars.is_empty() => {
- let mut status = status.lock().await;
- status.full_text = format!("{} ", String::from_iter(chars[0..10].iter()));
- chars.rotate_left(1);
+pub struct Title;
+
+impl Component for Title {
+ const NAME: &'static str = "title";
+ type Updater = Self;
+ type Colorer = PlaybackStatus;
+ type Handler = ();
+}
+
+impl Update for Title {
+ type Value = String;
+
+ async fn listen(tx: Sender<Self::Value>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
+ use futures_util::StreamExt;
+
+ let mut join_set = JoinSet::new();
+ let mut rotator = None;
+ let mut old_title = None;
+
+ Self::handle_metadata(
+ tx.clone(),
+ proxy.metadata().await?,
+ &mut old_title,
+ &mut rotator,
+ &mut join_set,
+ )
+ .await?;
+
+ let mut stream = proxy.receive_metadata_changed().await;
+ while let Some(signal) = stream.next().await {
+ if let Ok(metadata) = signal.get().await {
+ Self::handle_metadata(
+ tx.clone(),
+ metadata,
+ &mut old_title,
+ &mut rotator,
+ &mut join_set,
+ )
+ .await?;
}
}
+ Ok(())
+ }
+
+ async fn update(mut value: Self::Value, block: Arc<Mutex<Block>>) -> Result<bool, Error> {
+ value.push(' ');
+ let mut block = block.lock().await;
+ block.full_text = value;
- let s = status.lock().await;
- s.write_stdout()?;
+ Ok(true)
}
}
-pub async fn value_listener(tx: Sender<String>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
- let mut old_title = if let Some(value) = proxy.metadata().await?.get("xesam:title") {
- let title: String = value.try_to_owned()?.try_into()?;
- tx.send(title.clone()).await?;
- Some(title)
- } else {
- None
- };
-
- let mut stream = proxy.receive_metadata_changed().await;
- while let Some(signal) = stream.next().await {
- if let Ok(value) = signal.get().await {
- let Some(owned_value) = value.get("xesam:title") else {
- continue;
- };
-
- let title: String = owned_value.try_to_owned()?.try_into()?;
-
- if old_title.as_ref().is_some_and(|s| *s == title) {
- continue;
- }
+impl Title {
+ async fn handle_metadata(
+ tx: Sender<<<Self as Component>::Updater as Update>::Value>,
+ metadata: HashMap<String, OwnedValue>,
+ old_title: &mut Option<String>,
+ rotator: &mut Option<AbortHandle>,
+ join_set: &mut JoinSet<Result<(), Error>>,
+ ) -> Result<(), Error> {
+ let Some(owned_value) = metadata.get("xesam:title") else {
+ return Ok(());
+ };
+
+ let title: String = owned_value.try_to_owned()?.try_into()?;
+
+ if old_title.as_ref().is_some_and(|s| *s == title) {
+ return Ok(());
+ }
+
+ if let Some(h) = rotator.take() {
+ h.abort();
+ };
- old_title = Some(title.clone());
+ *old_title = Some(title.clone());
+
+ if title.len() >= 10 {
+ let mut chars = title.clone().chars().collect::<Vec<char>>();
+ let tx = tx.clone();
+
+ *rotator = Some(join_set.spawn(async move {
+ let mut interval = tokio::time::interval(TICK_RATE);
+ loop {
+ interval.tick().await;
+ tx.send(format!("{} ", String::from_iter(chars[0..10].iter())))
+ .await
+ .unwrap();
+ chars.rotate_left(1);
+ }
+ }));
+ } else {
tx.send(title).await?;
}
+
+ Ok(())
}
- Ok(())
}
diff --git a/src/bin/volume.rs b/src/bin/volume.rs
index 5e9d1d1..b5182b3 100644
--- a/src/bin/volume.rs
+++ b/src/bin/volume.rs
@@ -1,76 +1,77 @@
use std::sync::Arc;
-use futures_util::StreamExt;
use i3blocks::{
- color_listener,
- dbus::{player::PlayerProxy, playerctld::PlayerctldProxy},
- i3bar::Block,
- player_listener, Error,
-};
-use tokio::{
- sync::{mpsc::Sender, Mutex},
- task::JoinSet,
+ dbus::player::{PlaybackStatus, PlayerProxy},
+ i3bar::{Block, Click},
+ Button, Component, Error, Update,
};
+use tokio::sync::{mpsc::Sender, Mutex};
use zbus::Connection;
#[tokio::main]
async fn main() -> Result<(), main_error::MainError> {
- let mut join_set = JoinSet::new();
+ i3blocks::run::<Volume>(Default::default())
+ .await
+ .map_err(Into::into)
+}
- 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);
+pub struct Volume;
- let conn = Connection::session().await?;
- let proxy = PlayerctldProxy::builder(&conn).build().await?;
+impl Component for Volume {
+ const NAME: &'static str = "volume";
+ type Updater = Self;
+ type Colorer = PlaybackStatus;
+ type Handler = Self;
+}
- tokio::spawn(player_listener(tx_player, proxy));
+impl Update for Volume {
+ type Value = f64;
- let status: Arc<Mutex<Block>> = Default::default();
+ async fn listen(tx: Sender<Self::Value>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
+ use futures_util::StreamExt;
- loop {
- tokio::select! {
- Some(name) = rx_player.recv() => {
- join_set.shutdown().await;
- if name.is_empty() {
- let mut status = status.lock().await;
- status.full_text = Default::default();
- } else {
- let proxy = PlayerProxy::builder(&conn)
- .destination(name)?
- .build()
- .await?;
- join_set.spawn(color_listener(tx_status.clone(), proxy.clone()));
- join_set.spawn(value_listener(tx_value.clone(), proxy));
- }
- }
- Some((color, background)) = rx_status.recv() => {
- let mut status = status.lock().await;
- status.color = color;
- status.background = background;
- }
- Some(value) = rx_value.recv() => {
- let mut status = status.lock().await;
- status.full_text = match (value * 100_f64) as u32 {
- v @ 66.. => format!("󰕾 {v}% "),
- v @ 33.. => format!("󰖀 {v}% "),
- v @ 0.. => format!("󰕿 {v}% "),
- };
+ tx.send(proxy.volume().await?).await?;
+ let mut stream = proxy.receive_volume_changed().await;
+ while let Some(signal) = stream.next().await {
+ if let Ok(value) = signal.get().await {
+ tx.send(value).await?;
}
}
+ Ok(())
+ }
- let s = status.lock().await;
- s.write_stdout()?;
+ async fn update(value: Self::Value, block: Arc<Mutex<Block>>) -> Result<bool, Error> {
+ let mut block = block.lock().await;
+ block.full_text = match (value * 100_f64) as u32 {
+ v @ 66.. => format!("󰕾 {v}% "),
+ v @ 33.. => format!("󰖀 {v}% "),
+ v @ 0.. => format!("󰕿 {v}% "),
+ };
+ Ok(true)
}
}
-pub async fn value_listener(tx: Sender<f64>, proxy: PlayerProxy<'_>) -> Result<(), Error> {
- tx.send(proxy.volume().await?).await?;
- let mut stream = proxy.receive_volume_changed().await;
- while let Some(signal) = stream.next().await {
- if let Ok(value) = signal.get().await {
- tx.send(value).await?;
+impl Button for Volume {
+ async fn handle(conn: Connection, click: Click) -> Result<(), Error> {
+ let Some(name) = click.instance else {
+ return Ok(());
+ };
+
+ let proxy = PlayerProxy::builder(&conn)
+ .destination(name)?
+ .build()
+ .await?;
+
+ match click.button {
+ 4 if proxy.can_control().await? => {
+ proxy.set_volume(proxy.volume().await? - 0.05).await?
+ }
+ 5 if proxy.can_control().await? => {
+ proxy.set_volume(proxy.volume().await? + 0.05).await?
+ }
+ _ => {}
}
+
+ Ok(())
}
- Ok(())
}