summary history branches tags files
commit:f444ce6aac14fd7028c8884f840ae06ac4a08b5a
author:Trevor Bentley
committer:Trevor Bentley
date:Mon Nov 13 19:22:50 2017 +0100
parents:f53a9c8eff1e911d4aef00446185b3a6059be367
Add audio detection.  First stab at a config file format.
diff --git a/Cargo.lock b/Cargo.lock
line changes: +7/-0
index 5a0c2a9..a5b4ef7
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,7 @@
 name = "circadian"
 version = "0.1.0"
 dependencies = [
+ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -14,6 +15,11 @@ dependencies = [
 ]
 
 [[package]]
+name = "glob"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "lazy_static"
 version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -77,6 +83,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
 "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
+"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5"
 "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
 "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"

diff --git a/Cargo.toml b/Cargo.toml
line changes: +2/-0
index e02ff3e..f1c76dd
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,3 +8,5 @@ lto = true
 
 [dependencies]
 regex = "0.2"
+glob = "0.2.11"
+rust-ini = "0.10.0"

diff --git a/resources/circadian.conf.in b/resources/circadian.conf.in
line changes: +118/-0
index 0000000..9e40882
--- /dev/null
+++ b/resources/circadian.conf.in
@@ -0,0 +1,118 @@
+##
+## Heuristics
+##
+## Options used to detect whether the system is idle.
+##
+[heuristics]
+# Whether TTY input on *any* TTY blocks idle.  This includes X terminals,
+# virtual terminals, SSH sessions, etc.  Resets whenever a TTY determines
+# that it has input, which is typically keypresses.
+#
+# Monitors the idle column of the 'w' command.
+#
+# Default: yes
+tty_input = yes
+
+# Whether X11 idle detection is used, the specifics of which are determined
+# by your particular combination of window/display manager.  This is normally
+# any user input device (keyboard, mouse), but can additionally be reset
+# by certain programs.  Typically, any program that prevents the screensaver
+# from displaying will also reset this.
+#
+# Monitors xprintidle and xssstate
+#
+# Default: yes
+x11_input = yes
+
+# Whether active SSH connections block the system from being idle.  Both
+# inbound and outbound connections will prevent the system from going idle
+# if this is 'yes'.
+#
+# Monitors netstat
+#
+# Default: yes
+ssh_block = yes
+
+# Whether active Samba connections block the system from being idle.
+#
+# Monitors netstat
+#
+# Default: yes
+smb_block = yes
+
+# Whether active audio playback blocks the system from being idle.
+#
+# Monitors /proc/asound
+#
+# Default: yes
+audio_block = yes
+
+# Max CPU load for the past minute to be considered idle.  This is the
+# unscaled load, can go above 1.0 even on non-maxed multi-core systems.
+# Set to 999.0 or comment out to disable.
+#
+# Monitors uptime
+#
+# Default: 0.5
+max_cpu_load = 0.5
+
+# Specific processes that block the system from being considered idle if
+# they are running.  Supply as a comma separated list.  Basic regex is
+# permitted, and the format "^full-process-name$" is recommended.
+#
+# Monitors pgrep
+#
+# Example:
+#   process_block = mplayer,vlc
+#
+# Default: some common file transfer utils
+process_block = ^dd$,^rsync$,^apt-get$,^dpkg$,^cp$,^mv$
+
+[actions]
+# How long the system must be idle before the idle action is taken.
+#
+# NOTE: only the '*_input' heuristics need to be continuously idle without
+# interruption.  The other heuristics only need to be true instantaneously
+# after idle_time has passed.  (ex: with an idle_time of 1 hour, the mouse
+# must not move at all for 1 hour, but SSH connections can come and go
+# during that hour.  The on_idle command will run the next time that _at least_
+# 1 hour has gone by without mouse movement, and no SSH connections are
+# currently active.)
+#
+# Suffix:
+#  <none> - seconds
+#  m - minutes
+#  h - hours
+#
+# Default: 120 minutes
+idle_time = 120m
+
+# Time of day (in local timezone) to automatically wake the machine if it
+# is sleeping.  Specify in 24-hour time format with a colon.  Leave blank
+# or comment out for no wake time.
+#
+# This depends on the hardware RTC being enabled and supported by your kernel.
+#
+# Example:
+#   auto_wake = 16:00
+#
+# Default: disabled
+auto_wake =
+
+# Command to execute when the system is determined to have been idle for at
+# least idle_time.  Typically a suspend or hibernate command.
+#
+# Common options:
+#  * pm-suspend
+#  * pm-hibernate
+#  * pm-suspend-hybrid
+#  * systemctl suspend
+#  * systemctl hibernate
+#  * dbus-send --system --print-reply --dest="org.freedesktop.UPower" \
+#      /org/freedesktop/UPower org.freedesktop.UPower.Suspend
+#
+# Default: pm-suspend
+on_idle = ""
+
+# Command to execute after waking from a sleep.
+on_wake = ""

diff --git a/src/main.rs b/src/main.rs
line changes: +38/-0
index 2d79bed..6ee6a77
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,9 @@
 extern crate regex;
 use regex::Regex;
 
+extern crate glob;
+use glob::glob;
+
 use std::error::Error;
 use std::process::Stdio;
 use std::process::Command;
@@ -26,6 +29,16 @@ impl From<std::num::ParseIntError> for CircadianError {
         CircadianError(error.description().to_owned())
     }
 }
+impl From<std::string::FromUtf8Error> for CircadianError {
+    fn from(error: std::string::FromUtf8Error) -> Self {
+        CircadianError(error.description().to_owned())
+    }
+}
+impl From<glob::PatternError> for CircadianError {
+    fn from(error: glob::PatternError) -> Self {
+        CircadianError(error.description().to_owned())
+    }
+}
 
 type IdleResult = Result<u32, CircadianError>;
 type ThreshResult = Result<bool, CircadianError>;
@@ -198,6 +211,30 @@ fn exist_net_connection(conn: NetConnection) -> ExistResult {
     Ok(connections.len() > 0)
 }
 
+fn exist_audio() -> ExistResult {
+    let mut count = 0;
+    for device in glob("/proc/asound/card*/pcm*/sub*/status")? {
+        if let Ok(path) = device {
+            let output = Command::new("cat")
+                .arg(path)
+                .stderr(Stdio::null())
+                .stdout(Stdio::piped()).spawn()?;
+            let stdout = output.stdout
+                .ok_or(CircadianError("pacmd failed".to_string()))?;
+            let output = Command::new("grep")
+                .arg("state:")
+                .stdin(stdout)
+                .output()?;
+            let output_str = String::from_utf8(output.stdout)?;
+            let lines: Vec<&str> = output_str.split("\n")
+                .filter(|l| l.len() > 0)
+                .collect();
+            count += lines.len();
+        }
+    }
+    Ok(count > 0)
+}
+
 fn main() {
     println!("Hello, world!");
     println!("Sec: {:?}", parse_w_time("10.45s"));
@@ -211,6 +248,7 @@ fn main() {
         println!("ssh: {:?}", exist_net_connection(NetConnection::SSH));
         println!("smb: {:?}", exist_net_connection(NetConnection::SMB));
         println!("iotop: {:?}", exist_process("^iotop$"));
+        println!("audio: {:?}", exist_audio());
         std::thread::sleep(std::time::Duration::from_millis(2000));
     }
 }