Commit | Line | Data |
---|---|---|
12bd87b0 | 1 | use dbus::arg; |
baedbc7e JC |
2 | use dbus::blocking::stdintf::org_freedesktop_dbus::PropertiesPropertiesChanged; |
3 | use dbus::blocking::Connection; | |
4 | use dbus::message::Message; | |
1e52c28e JC |
5 | use std::collections::HashMap; |
6 | use std::sync::{Arc, Mutex}; | |
baedbc7e JC |
7 | use std::time::Duration; |
8 | ||
12bd87b0 JC |
9 | // Custom signal type impl |
10 | // Mostly copied from library examples | |
11 | #[derive(Debug)] | |
12 | pub struct ComJacobCasperMailUnreadCount { | |
13 | pub count: u32, | |
14 | } | |
15 | ||
16 | impl arg::AppendAll for ComJacobCasperMailUnreadCount { | |
17 | fn append(&self, iter: &mut arg::IterAppend) { | |
18 | arg::RefArg::append(&self.count, iter); | |
19 | } | |
20 | } | |
21 | ||
22 | impl 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 | ||
30 | impl dbus::message::SignalArgs for ComJacobCasperMailUnreadCount { | |
31 | const NAME: &'static str = "UnreadCount"; | |
32 | const INTERFACE: &'static str = "com.jacobcasper.Mail"; | |
33 | } | |
34 | ||
ddaab88f | 35 | fn 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 | 44 | fn 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 | } |