summary history branches tags files
commit:dabe4bed73eaed28dda7463e766cfcc0c80c008c
author:quantum-byte
committer:Trevor Bentley
date:Mon Feb 13 03:56:25 2023 +0100
parents:670e63a30684f8b99220dcbd1e0e69284a2271f1
Added audio detection support for pulseaudio via pacmd
diff --git a/README.md b/README.md
line changes: +1/-0
index 61d876a..b31a8a7
--- a/README.md
+++ b/README.md
@@ -83,6 +83,7 @@ Follow systemd instructions, and port circadian.service to whatever format you w
     * xssstate
     * xprintidle
     * netstat
+    * pacmd
     * rustc + cargo (if building locally)
 * Should already have
     * grep

diff --git a/src/main.rs b/src/main.rs
line changes: +32/-4
index ea6ef66..16edda8
--- a/src/main.rs
+++ b/src/main.rs
@@ -504,7 +504,7 @@ fn exist_net_connection(conn: NetConnection) -> ExistResult {
 }
 
 /// Determine whether audio is actively playing on any ALSA interface.
-fn exist_audio() -> ExistResult {
+fn exist_audio_alsa() -> ExistResult {
     let mut count = 0;
     for device in glob("/proc/asound/card*/pcm*/sub*/status")? {
         if let Ok(path) = device {
@@ -514,7 +514,7 @@ fn exist_audio() -> ExistResult {
                 .stdout(Stdio::piped()).spawn()?;
             let _ = cat_output.wait()?;
             let stdout = cat_output.stdout
-                .ok_or(CircadianError("pacmd failed".to_string()))?;
+                .ok_or(CircadianError("cat /proc/asound/* failed".to_string()))?;
             let output = Command::new("grep")
                 .arg("state:")
                 .stdin(stdout)
@@ -529,6 +529,34 @@ fn exist_audio() -> ExistResult {
     Ok(count > 0)
 }
 
+/// Determine whether audio is actively playing on any Pulseaudio interface.
+fn exist_audio_pulseaudio() -> ExistResult {
+    let mut count = 0;
+    let mut cat_output = Command::new("pacmd")
+        .arg("list-sink-inputs")
+        .stderr(Stdio::null())
+        .stdout(Stdio::piped()).spawn()?;
+    let _ = cat_output.wait()?;
+    let stdout = cat_output.stdout
+        .ok_or(CircadianError("pacmd failed".to_string()))?;
+    let output = Command::new("grep")
+        .arg("state: RUNNING") // Does not includes CORKED == Paused audio
+        .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 exist_audio() -> ExistResult {
+    let audio_alsa = exist_audio_alsa();
+    let audio_pulseaudio = exist_audio_pulseaudio();
+    Ok(*audio_alsa.as_ref().unwrap_or(&false) || *audio_pulseaudio.as_ref().unwrap_or(&false))
+}
+
 struct CircadianLaunchOptions {
     config_file: String,
     //script_dir: String,
@@ -850,8 +878,8 @@ fn main() {
         println!("'netstat' command required by ssh/smb/nfs_block failed.  Exiting.");
         std::process::exit(1);
         }
-    if config.audio_block && exist_audio().is_err() {
-        println!("'/proc/asound/' required by audio_block is unreadable.  Exiting.");
+    if config.audio_block && (exist_audio_alsa().is_err() && exist_audio_pulseaudio().is_err())  {
+        println!("'/proc/asound/' and pacmd required by audio_block is unreadable. Exiting.");
         std::process::exit(1);
     }
     if config.process_block.len() > 0 && exist_process("").is_err() {