Listen for custom mail count signal
[xsetrootd.git] / src / main.rs
CommitLineData
12bd87b0 1use dbus::arg;
baedbc7e
JC
2use dbus::blocking::stdintf::org_freedesktop_dbus::PropertiesPropertiesChanged;
3use dbus::blocking::Connection;
4use dbus::message::Message;
1e52c28e
JC
5use std::collections::HashMap;
6use std::sync::{Arc, Mutex};
baedbc7e
JC
7use std::time::Duration;
8
12bd87b0
JC
9// Custom signal type impl
10// Mostly copied from library examples
11#[derive(Debug)]
12pub struct ComJacobCasperMailUnreadCount {
13 pub count: u32,
14}
15
16impl arg::AppendAll for ComJacobCasperMailUnreadCount {
17 fn append(&self, iter: &mut arg::IterAppend) {
18 arg::RefArg::append(&self.count, iter);
19 }
20}
21
22impl arg::ReadAll for ComJacobCasperMailUnreadCount {
23 fn read(iter: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
24 Ok(ComJacobCasperMailUnreadCount {
25 count: iter.read()?,
26 })
27 }
28}
29
30impl dbus::message::SignalArgs for ComJacobCasperMailUnreadCount {
31 const NAME: &'static str = "UnreadCount";
32 const INTERFACE: &'static str = "com.jacobcasper.Mail";
33}
34
ddaab88f 35fn update_map(arc_map: Arc<Mutex<HashMap<String, String>>>, key: &str, val: &str) {
1e52c28e
JC
36 let clone_arc = arc_map.clone();
37 let mut map = clone_arc.lock().unwrap();
ddaab88f 38 map.insert(String::from(key), String::from(val));
1e52c28e
JC
39 for (k, v) in &*map {
40 println! {"{}: {}", k.clone(), v.clone()};
41 }
42}
43
baedbc7e 44fn main() -> Result<(), Box<dyn std::error::Error>> {
1e52c28e 45 let arc_locked_xset_map = Arc::new(Mutex::new(HashMap::new()));
baedbc7e
JC
46 let conn = Connection::new_session()?;
47
12bd87b0
JC
48 let mail_proxy = conn.with_proxy(
49 "com.jacobcasper.Mail",
50 "/com/jacobcasper/Mail/Unread",
51 Duration::from_millis(5000),
52 );
53
54 let mail_match_map = arc_locked_xset_map.clone();
55 let _ = mail_proxy.match_signal(
56 move |m: ComJacobCasperMailUnreadCount, _: &Connection, _: &Message| {
57 update_map(
58 mail_match_map.clone(),
59 "unread_count",
60 m.count.to_string().as_str(),
61 );
62 true
63 },
64 );
65
66 let spotify_proxy = conn.with_proxy(
baedbc7e
JC
67 "org.mpris.MediaPlayer2.spotify",
68 "/org/mpris/MediaPlayer2",
69 Duration::from_millis(5000),
70 );
71
16683530 72 let spotify_match_map = arc_locked_xset_map.clone();
12bd87b0 73 let _ = spotify_proxy.match_signal(
1e52c28e 74 move |pc: PropertiesPropertiesChanged, _: &Connection, _: &Message| {
79b46cd5
JC
75 pc.changed_properties["Metadata"]
76 .0
77 .as_iter()
78 .and_then(|mut iter| {
79 // Iterating over a RefArg goes key, value, key, value... Insane honestly.
80 while let Some(key) = iter.next() {
81 let key_str = key.as_str()?;
82 let value = iter.next();
83
84 match key_str {
85 "xesam:artist" => {
86 // Variant holding a variant that should just be a Vec<&str> I
87 // believe. This is _the recommended_ way to do this by the author.
88 let inner_value = value?.as_iter()?.next()?.as_iter()?.next()?;
ddaab88f 89 let artist = inner_value.as_str()?;
16683530 90 update_map(spotify_match_map.clone(), "artist", artist);
79b46cd5 91 }
b710f9dc 92 "xesam:title" => {
1e52c28e 93 let title = value?.as_iter()?.next()?.as_str()?;
16683530 94 update_map(spotify_match_map.clone(), "title", title);
b710f9dc 95 }
79b46cd5
JC
96 _ => (),
97 }
98 }
99 Some(())
100 });
baedbc7e
JC
101 true
102 },
103 );
104
105 loop {
106 conn.process(Duration::from_millis(1000))?;
107 }
108}