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
129
|
use std::{collections::VecDeque, io::Write};
use tokio::{
sync::mpsc::{Receiver, Sender},
task::{AbortHandle, JoinHandle, JoinSet},
};
use zbus::{names::OwnedBusName, Connection};
use crate::{
components::Component,
dbus::player::{PlaybackStatus, PlayerProxy},
i3bar::Block,
Result,
};
const BLACK: &str = "#1d2021";
const YELLOW: &str = "#fabd2f";
const CYAN: &str = "#8ec07c";
pub enum Command {
Shift,
Raise(String),
}
#[derive(Debug)]
pub struct Player {
pub name: OwnedBusName,
pub handle: JoinHandle<Result<()>>,
pub tx: Sender<(u8, usize)>,
}
#[derive(Debug, Clone)]
pub enum Event {
Add(OwnedBusName),
Remove(OwnedBusName),
Shift,
}
pub async fn listener<T: Component>(
conn: Connection,
mut rx: Receiver<Event>,
component: &'static T,
) -> Result<()> {
let mut players: VecDeque<OwnedBusName> = VecDeque::new();
let mut active: Option<OwnedBusName> = Default::default();
let mut listener: Option<AbortHandle> = None;
let mut printer: Option<AbortHandle> = None;
let mut join_set = JoinSet::new();
while let Some(value) = rx.recv().await {
match value {
Event::Add(name) => {
let player_proxy = PlayerProxy::builder(&conn)
.destination(name.clone())?
.build()
.await?;
match player_proxy.playback_status().await? {
PlaybackStatus::Playing => players.push_front(name),
PlaybackStatus::Paused => players.push_back(name),
PlaybackStatus::Stopped => players.push_back(name),
}
}
Event::Remove(name) => {
if let Some(index) = players.iter().position(|p| *p == name) {
players.remove(index);
}
}
Event::Shift if !players.is_empty() => players.rotate_left(1),
_ => {}
};
if players.front() != active.as_ref() {
if active.is_some() {
if let Some(h) = listener.take() {
h.abort();
}
if let Some(h) = printer.take() {
h.abort();
}
active = None;
}
if let Some(name) = players.front().cloned() {
let proxy = PlayerProxy::builder(&conn)
.destination(name.clone())?
.build()
.await?;
let (tx, mut rx): (Sender<Block>, _) = tokio::sync::mpsc::channel(128);
let conn = conn.clone();
listener = Some(join_set.spawn(component.listen(proxy, tx.clone())));
printer = Some(join_set.spawn(async move {
while let Some(mut block) = rx.recv().await {
let proxy = PlayerProxy::builder(&conn)
.destination(name.clone())?
.build()
.await?;
match proxy.playback_status().await? {
PlaybackStatus::Playing => {
block.color = Some(BLACK.into());
block.background = Some(CYAN.into())
}
PlaybackStatus::Paused => {
block.color = Some(BLACK.into());
block.background = Some(YELLOW.into())
}
_ => {}
};
block.instance = name.as_str().to_owned();
block.instance = name.as_str().to_owned();
let mut w = std::io::stdout().lock();
let mut v = serde_json::to_vec(&block)?;
v.push(b'\n');
w.write_all(&v)?;
w.flush()?;
}
Ok(())
}));
}
}
}
Ok(())
}
|