1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
use std::{fmt::Display, str::FromStr, sync::Arc};
use i3bar::Block;
use tokio::sync::{Notify, RwLock};
pub use crate::error::{Error, Result};
pub mod dbus;
pub mod error;
pub mod i3bar;
pub mod listener;
pub mod handler {
use zbus::Connection;
use crate::{
dbus::{media_player2::MediaPlayer2Proxy, player::PlayerProxy},
BlockKind, Error,
};
pub async fn handlers(
conn: Connection,
mut rx: tokio::sync::mpsc::Receiver<(BlockKind, u8)>,
) -> Result<(), Error> {
let player_proxy = PlayerProxy::builder(&conn)
.destination("org.mpris.MediaPlayer2.playerctld")?
.build()
.await?;
let mpris_proxy = MediaPlayer2Proxy::builder(&conn)
.destination("org.mpris.MediaPlayer2.playerctld")?
.build()
.await?;
while let Some(click) = rx.recv().await {
if let Err(err) = handle_click(&player_proxy, &mpris_proxy, click).await {
eprintln!("{err}")
}
}
Ok(())
}
pub async fn handle_click(
player: &PlayerProxy<'_>,
mpris: &MediaPlayer2Proxy<'_>,
click: (BlockKind, u8),
) -> Result<(), Error> {
// TODO: Show notification with metadata on `(BlockKind::Title, 1)`
match click {
(BlockKind::Icon, 1) if mpris.can_raise().await? => mpris.raise().await?,
(BlockKind::Prev, 1) if player.can_go_previous().await? => player.previous().await?,
(BlockKind::Prev, 3) if player.can_seek().await? => player.seek(-5_000_000).await?,
(BlockKind::Play, 1) if player.can_pause().await? => player.play_pause().await?,
(BlockKind::Next, 1) if player.can_go_next().await? => player.next().await?,
(BlockKind::Next, 3) if player.can_seek().await? => player.seek(5_000_000).await?,
(BlockKind::Volume, 4) => update_volume(player, -0.05).await?,
(BlockKind::Volume, 5) => update_volume(player, 0.05).await?,
_ => {}
}
Ok(())
}
pub async fn update_volume(proxy: &PlayerProxy<'_>, delta: f64) -> Result<(), Error> {
if let Ok(vol) = proxy.volume().await {
proxy.set_volume(vol + delta).await?
}
Ok(())
}
}
pub type State = Arc<Watcher<[Block; 6]>>;
#[derive(Default)]
pub struct Watcher<T> {
pub value: RwLock<T>,
pub notify: Notify,
}
impl<T> Watcher<T> {
pub fn new(value: T) -> Self {
Self {
value: RwLock::new(value),
notify: Notify::new(),
}
}
}
#[repr(u8)]
pub enum BlockKind {
Icon,
Title,
Prev,
Play,
Next,
Volume,
}
impl Display for BlockKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BlockKind::Icon => write!(f, "icon"),
BlockKind::Title => write!(f, "title"),
BlockKind::Prev => write!(f, "prev"),
BlockKind::Play => write!(f, "play"),
BlockKind::Next => write!(f, "next"),
BlockKind::Volume => write!(f, "volume"),
}
}
}
impl FromStr for BlockKind {
type Err = Error;
fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
match s {
"icon" => Ok(Self::Icon),
"title" => Ok(Self::Title),
"prev" => Ok(Self::Prev),
"play" => Ok(Self::Play),
"next" => Ok(Self::Next),
"volume" => Ok(Self::Volume),
s => Err(Error::InvalidKind(s.to_owned())),
}
}
}
|