Put date and time in xsetroot name
[xsetrootd.git] / src / main.rs
index 1d8624e..4aec86b 100644 (file)
@@ -1,19 +1,99 @@
+use dbus::arg;
 use dbus::blocking::stdintf::org_freedesktop_dbus::PropertiesPropertiesChanged;
 use dbus::blocking::Connection;
 use dbus::message::Message;
+use std::collections::HashMap;
+use std::process::Command;
+use std::sync::{Arc, Mutex};
+use std::thread;
 use std::time::Duration;
 
+// Custom signal type impl
+// Mostly copied from library examples
+#[derive(Debug)]
+pub struct ComJacobCasperMailUnreadCount {
+    pub count: u32,
+}
+
+impl arg::AppendAll for ComJacobCasperMailUnreadCount {
+    fn append(&self, iter: &mut arg::IterAppend) {
+        arg::RefArg::append(&self.count, iter);
+    }
+}
+
+impl arg::ReadAll for ComJacobCasperMailUnreadCount {
+    fn read(iter: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
+        Ok(ComJacobCasperMailUnreadCount {
+            count: iter.read()?,
+        })
+    }
+}
+
+impl dbus::message::SignalArgs for ComJacobCasperMailUnreadCount {
+    const NAME: &'static str = "UnreadCount";
+    const INTERFACE: &'static str = "com.jacobcasper.Mail";
+}
+
+fn get_local_time_string() -> std::string::String {
+    use chrono::prelude::*;
+    let local_time = chrono::prelude::Local::now();
+    return format!(
+        "{}-{}-{:02} {}:{}",
+        local_time.year(),
+        local_time.month(),
+        local_time.day(),
+        local_time.hour(),
+        local_time.minute(),
+    );
+}
+
+fn update_map(arc_map: Arc<Mutex<HashMap<String, String>>>, key: &str, val: &str) {
+    let clone_arc = arc_map.clone();
+    let mut map = clone_arc.lock().unwrap();
+    map.insert(String::from(key), String::from(val));
+    let _ = Command::new("xsetroot")
+        .arg("-name")
+        .arg(format!(
+            "[🔊 {title} - {artist}] | âœ‰ {unread_count} | {date_time}",
+            title = map.get("title").unwrap_or(&String::from("")),
+            artist = map.get("artist").unwrap_or(&String::from("")),
+            unread_count = map.get("unread_count").unwrap_or(&String::from("?")),
+            date_time = map.get("date_time").unwrap_or(&get_local_time_string()),
+        ))
+        .spawn();
+}
+
 fn main() -> Result<(), Box<dyn std::error::Error>> {
+    let arc_locked_xset_map = Arc::new(Mutex::new(HashMap::new()));
     let conn = Connection::new_session()?;
 
-    let proxy = conn.with_proxy(
+    let mail_proxy = conn.with_proxy(
+        "com.jacobcasper.Mail",
+        "/com/jacobcasper/Mail/Unread",
+        Duration::from_millis(5000),
+    );
+
+    let mail_match_map = arc_locked_xset_map.clone();
+    let _ = mail_proxy.match_signal(
+        move |m: ComJacobCasperMailUnreadCount, _: &Connection, _: &Message| {
+            update_map(
+                mail_match_map.clone(),
+                "unread_count",
+                m.count.to_string().as_str(),
+            );
+            true
+        },
+    );
+
+    let spotify_proxy = conn.with_proxy(
         "org.mpris.MediaPlayer2.spotify",
         "/org/mpris/MediaPlayer2",
         Duration::from_millis(5000),
     );
 
-    let _ = proxy.match_signal(
-        |pc: PropertiesPropertiesChanged, _: &Connection, _: &Message| {
+    let spotify_match_map = arc_locked_xset_map.clone();
+    let _ = spotify_proxy.match_signal(
+        move |pc: PropertiesPropertiesChanged, _: &Connection, _: &Message| {
             pc.changed_properties["Metadata"]
                 .0
                 .as_iter()
@@ -28,8 +108,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                                 // Variant holding a variant that should just be a Vec<&str> I
                                 // believe. This is _the recommended_ way to do this by the author.
                                 let inner_value = value?.as_iter()?.next()?.as_iter()?.next()?;
-                                let artist = String::from(inner_value.as_str()?);
-                                println!("artist: {}", artist);
+                                let artist = inner_value.as_str()?;
+                                update_map(spotify_match_map.clone(), "artist", artist);
+                            }
+                            "xesam:title" => {
+                                let title = value?.as_iter()?.next()?.as_str()?;
+                                update_map(spotify_match_map.clone(), "title", title);
                             }
                             _ => (),
                         }
@@ -40,6 +124,24 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
         },
     );
 
+    let date_time_map = arc_locked_xset_map.clone();
+    let _ = thread::spawn(move || -> Result<(), std::time::SystemTimeError> {
+        let mut last_run_at = std::time::SystemTime::now();
+        loop {
+            let sys_time = std::time::SystemTime::now();
+            let elapsed_time = sys_time.duration_since(last_run_at)?;
+            if elapsed_time.as_secs() > 60 {
+                last_run_at = sys_time;
+                update_map(
+                    date_time_map.clone(),
+                    "date_time",
+                    get_local_time_string().as_str(),
+                );
+            }
+            thread::sleep(Duration::from_millis(5000));
+        }
+    });
+
     loop {
         conn.process(Duration::from_millis(1000))?;
     }