summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/video-audio-recording.el135
-rw-r--r--tests/test-video-audio-recording--get-available-mics.el18
-rw-r--r--tests/test-video-audio-recording--get-available-sinks.el16
-rw-r--r--tests/test-video-audio-recording-quick-setup.el174
4 files changed, 146 insertions, 197 deletions
diff --git a/modules/video-audio-recording.el b/modules/video-audio-recording.el
index d5c59cb7..f3cfbca0 100644
--- a/modules/video-audio-recording.el
+++ b/modules/video-audio-recording.el
@@ -31,7 +31,7 @@
;; ===========
;; 1. Press C-; r s to run quick setup
;; 2. Pick a microphone from the list
-;; 3. Pick an audio output — 󰕾 marks sinks with active audio
+;; 3. Pick an audio output — [active - running] means audio is flowing
;; 4. Press C-; r a to start/stop audio recording
;; 5. Recording starts - you'll see 󰍬 in your modeline
;; 6. Press C-; r a again to stop (🔴 disappears)
@@ -45,8 +45,8 @@
;;
;; C-; r s (cj/recording-quick-setup) - RECOMMENDED
;; Two-step setup: pick a mic, then pick an audio output (sink).
-;; Sinks show 󰕾/󰖁 icons indicating active/inactive audio streams.
-;; Active sinks are sorted to the top for easy selection.
+;; Both steps show device state: [active - running], [active - idle],
+;; or [inactive - suspended]. Sorted running → idle → suspended.
;;
;; C-; r S (cj/recording-select-devices) - ADVANCED
;; Manual selection: choose mic and monitor separately.
@@ -299,32 +299,25 @@ OUTPUT should be the full output of `pactl list sources'."
(nreverse sources)))
(defun cj/recording--get-available-mics ()
- "Return available microphone sources as (name . description) alist.
+ "Return available microphone sources as list of (name description state).
Filters out monitor sources and muted devices. Uses the friendly
description from PulseAudio (e.g. \"Jabra SPEAK 510 Mono\") rather
-than the raw device name."
+than the raw device name. State is the PulseAudio state string
+\(RUNNING, IDLE, or SUSPENDED)."
(let* ((output (shell-command-to-string "pactl list sources 2>/dev/null"))
(sources (cj/recording--parse-pactl-sources-verbose output))
(mics nil))
(dolist (source sources)
(let ((name (nth 0 source))
(desc (nth 1 source))
- (mute (nth 2 source)))
+ (mute (nth 2 source))
+ (state (nth 3 source)))
;; Include non-monitor, non-muted sources
(when (and (not (string-match-p "\\.monitor$" name))
(not (equal mute "yes")))
- (push (cons name (or desc name)) mics))))
+ (push (list name (or desc name) state) mics))))
(nreverse mics)))
-(defun cj/recording--mic-active-p (source-name)
- "Return non-nil if SOURCE-NAME is actively in use (RUNNING state).
-Checks `pactl list sources short' for the source's current state."
- (let ((output (shell-command-to-string "pactl list sources short 2>/dev/null")))
- (cl-some (lambda (line)
- (and (string-match-p (regexp-quote source-name) line)
- (string-match-p "RUNNING" line)))
- (split-string output "\n" t))))
-
(defun cj/recording--parse-pactl-sinks-verbose (output)
"Parse verbose `pactl list sinks' OUTPUT into structured list.
Returns list of (name description mute state) tuples.
@@ -358,30 +351,22 @@ OUTPUT should be the full output of `pactl list sinks'."
(nreverse sinks)))
(defun cj/recording--get-available-sinks ()
- "Return available audio sinks as (name . description) alist.
+ "Return available audio sinks as list of (name description state).
Filters out muted sinks. Uses the friendly description from
-PulseAudio (e.g. \"JDS Labs Element IV Analog Stereo\")."
+PulseAudio (e.g. \"JDS Labs Element IV Analog Stereo\"). State is
+the PulseAudio state string (RUNNING, IDLE, or SUSPENDED)."
(let* ((output (shell-command-to-string "pactl list sinks 2>/dev/null"))
(sinks (cj/recording--parse-pactl-sinks-verbose output))
(result nil))
(dolist (sink sinks)
(let ((name (nth 0 sink))
(desc (nth 1 sink))
- (mute (nth 2 sink)))
+ (mute (nth 2 sink))
+ (state (nth 3 sink)))
(when (not (equal mute "yes"))
- (push (cons name (or desc name)) result))))
+ (push (list name (or desc name) state) result))))
(nreverse result)))
-(defun cj/recording--sink-active-p (sink-name)
- "Return non-nil if SINK-NAME has active audio streams.
-Resolves the sink name to its index via `pactl list sinks short',
-then checks `pactl list sink-inputs' for connected streams."
- (let* ((sinks-output (shell-command-to-string "pactl list sinks short 2>/dev/null"))
- (sink-index (cj/recording--get-sink-index sink-name sinks-output))
- (sink-inputs (shell-command-to-string "pactl list sink-inputs 2>/dev/null")))
- (and sink-index
- (cj/recording--sink-has-active-audio-p sink-index sink-inputs))))
-
;;; ============================================================
;;; Device Selection UI
;;; ============================================================
@@ -524,14 +509,48 @@ since recording needs both to capture your voice and system audio."
devices)
(nreverse result)))
+(defun cj/recording--state-sort-key (state)
+ "Return a numeric sort key for PulseAudio STATE.
+Lower values sort first: RUNNING (0) → IDLE (1) → SUSPENDED (2)."
+ (pcase (upcase (or state ""))
+ ("RUNNING" 0)
+ ("IDLE" 1)
+ (_ 2)))
+
+(defun cj/recording--state-label (state)
+ "Return a human-readable label for PulseAudio STATE.
+RUNNING and IDLE are active states; SUSPENDED is inactive."
+ (pcase (upcase (or state ""))
+ ("RUNNING" "[active - running]")
+ ("IDLE" "[active - idle]")
+ (_ "[inactive - suspended]")))
+
+(defun cj/recording--label-devices (devices)
+ "Build labeled (label . name) alist from DEVICES for `completing-read'.
+DEVICES is a list of (name description state) as returned by
+`cj/recording--get-available-mics' or `cj/recording--get-available-sinks'.
+Labels are formatted as \"Description [active - running]\" etc.
+Sorted: running → idle → suspended."
+ (let* ((labeled (mapcar
+ (lambda (dev)
+ (let* ((name (nth 0 dev))
+ (desc (nth 1 dev))
+ (state (nth 2 dev))
+ (label (concat desc " " (cj/recording--state-label state))))
+ (list label name (cj/recording--state-sort-key state))))
+ devices))
+ (sorted (sort labeled (lambda (a b) (< (nth 2 a) (nth 2 b))))))
+ (mapcar (lambda (entry) (cons (nth 0 entry) (nth 1 entry))) sorted)))
+
(defun cj/recording-quick-setup ()
"Quick device setup for recording — two-step mic + sink selection.
-Step 1: Pick a microphone. Mics in use by an app (RUNNING) show
-a green 󰍬 icon and are sorted to the top; idle mics show dim 󰍬.
-Step 2: Pick an audio output (sink) to monitor. Sinks with active
-audio streams show green 󰕾 and are sorted to the top; idle sinks
-show dim 󰖀. The chosen sink's .monitor source is set as the
-system audio device.
+Step 1: Pick a microphone. Each mic shows its PulseAudio state:
+ [active - running] = an app is using this mic right now
+ [active - idle] = recently used, still open
+ [inactive - suspended] = no app has this mic open
+Step 2: Pick an audio output (sink) to monitor, with the same
+state labels. Devices are sorted running → idle → suspended.
+The chosen sink's .monitor source is set as the system audio device.
This approach is portable across systems — plug in a new mic, run this
command, and it appears in the list. No hardware-specific configuration
@@ -539,26 +558,9 @@ needed."
(interactive)
;; Step 1: Mic selection
(let* ((mics (cj/recording--get-available-mics))
- (mic-labels
- (mapcar
- (lambda (mic)
- (let* ((name (car mic))
- (desc (cdr mic))
- (active (cj/recording--mic-active-p name))
- (icon "󰍬")
- (face (if active '(:foreground "#50fa7b") '(:foreground "#6272a4")))
- (label (concat (propertize icon 'face face) " " desc)))
- (list label name active)))
- mics))
- ;; Sort active mics to top
- (sorted-mics (sort mic-labels
- (lambda (a b)
- (and (nth 2 a) (not (nth 2 b))))))
- (mic-alist (mapcar (lambda (entry)
- (cons (nth 0 entry) (nth 1 entry)))
- sorted-mics))
- (mic-alist-with-cancel (append mic-alist '(("Cancel" . nil)))))
- (if (null mic-alist)
+ (mic-entries (cj/recording--label-devices mics))
+ (mic-alist-with-cancel (append mic-entries '(("Cancel" . nil)))))
+ (if (null mic-entries)
(user-error "No microphones found. Is a mic plugged in and unmuted?")
(let* ((mic-choice (completing-read "Select microphone: "
(lambda (string pred action)
@@ -571,25 +573,8 @@ needed."
(user-error "Device setup cancelled")
;; Step 2: Sink selection
(let* ((sinks (cj/recording--get-available-sinks))
- (sink-labels
- (mapcar
- (lambda (sink)
- (let* ((name (car sink))
- (desc (cdr sink))
- (active (cj/recording--sink-active-p name))
- (icon (if active "󰕾" "󰖀"))
- (face (if active '(:foreground "#50fa7b") '(:foreground "#6272a4")))
- (label (concat (propertize icon 'face face) " " desc)))
- (list label name active)))
- sinks))
- ;; Sort active sinks to top
- (sorted-labels (sort sink-labels
- (lambda (a b)
- (and (nth 2 a) (not (nth 2 b))))))
- (sink-alist (mapcar (lambda (entry)
- (cons (nth 0 entry) (nth 1 entry)))
- sorted-labels))
- (sink-alist-with-cancel (append sink-alist '(("Cancel" . nil))))
+ (sink-entries (cj/recording--label-devices sinks))
+ (sink-alist-with-cancel (append sink-entries '(("Cancel" . nil))))
(sink-choice (completing-read "Select audio output to monitor: "
(lambda (string pred action)
(if (eq action 'metadata)
diff --git a/tests/test-video-audio-recording--get-available-mics.el b/tests/test-video-audio-recording--get-available-mics.el
index 2fea0d7a..de9335af 100644
--- a/tests/test-video-audio-recording--get-available-mics.el
+++ b/tests/test-video-audio-recording--get-available-mics.el
@@ -6,6 +6,7 @@
;; - Monitor sources are excluded (they capture output, not input)
;; - Muted sources are excluded
;; - Friendly descriptions from PulseAudio are used
+;; - PulseAudio state is included
;;; Code:
@@ -38,7 +39,7 @@ Each source is (name description mute state)."
("alsa_output.usb-Jabra.monitor" "Monitor of Jabra" "no" "SUSPENDED"))))))
(let ((mics (cj/recording--get-available-mics)))
(should (= 1 (length mics)))
- (should (equal "alsa_input.usb-Jabra.mono" (car (car mics)))))))
+ (should (equal "alsa_input.usb-Jabra.mono" (nth 0 (car mics)))))))
(ert-deftest test-video-audio-recording--get-available-mics-normal-filters-muted ()
"Test that muted sources are excluded from mic list."
@@ -49,16 +50,25 @@ Each source is (name description mute state)."
("muted-mic" "Muted Mic" "yes" "SUSPENDED"))))))
(let ((mics (cj/recording--get-available-mics)))
(should (= 1 (length mics)))
- (should (equal "active-mic" (car (car mics)))))))
+ (should (equal "active-mic" (nth 0 (car mics)))))))
(ert-deftest test-video-audio-recording--get-available-mics-normal-uses-descriptions ()
- "Test that friendly descriptions are returned as cdr."
+ "Test that friendly descriptions are returned as second element."
(cl-letf (((symbol-function 'shell-command-to-string)
(lambda (_cmd)
(test-mics--make-pactl-output
'(("raw-device-name" "Friendly Device Name" "no" "IDLE"))))))
(let ((mics (cj/recording--get-available-mics)))
- (should (equal "Friendly Device Name" (cdr (car mics)))))))
+ (should (equal "Friendly Device Name" (nth 1 (car mics)))))))
+
+(ert-deftest test-video-audio-recording--get-available-mics-normal-includes-state ()
+ "Test that PulseAudio state is returned as third element."
+ (cl-letf (((symbol-function 'shell-command-to-string)
+ (lambda (_cmd)
+ (test-mics--make-pactl-output
+ '(("mic-a" "Mic A" "no" "RUNNING"))))))
+ (let ((mics (cj/recording--get-available-mics)))
+ (should (equal "RUNNING" (nth 2 (car mics)))))))
(ert-deftest test-video-audio-recording--get-available-mics-normal-multiple-mics ()
"Test that multiple non-muted, non-monitor mics are returned."
diff --git a/tests/test-video-audio-recording--get-available-sinks.el b/tests/test-video-audio-recording--get-available-sinks.el
index 540c4f0f..a8e7ad6a 100644
--- a/tests/test-video-audio-recording--get-available-sinks.el
+++ b/tests/test-video-audio-recording--get-available-sinks.el
@@ -5,6 +5,7 @@
;; Verifies that available sinks are discovered correctly:
;; - Muted sinks are excluded
;; - Friendly descriptions from PulseAudio are used
+;; - PulseAudio state is included
;;; Code:
@@ -37,16 +38,25 @@ Each sink is (name description mute state)."
("muted-sink" "Muted Sink" "yes" "SUSPENDED"))))))
(let ((sinks (cj/recording--get-available-sinks)))
(should (= 1 (length sinks)))
- (should (equal "active-sink" (car (car sinks)))))))
+ (should (equal "active-sink" (nth 0 (car sinks)))))))
(ert-deftest test-get-available-sinks-normal-uses-descriptions ()
- "Test that friendly descriptions are returned as cdr."
+ "Test that friendly descriptions are returned as second element."
(cl-letf (((symbol-function 'shell-command-to-string)
(lambda (_cmd)
(test-sinks--make-pactl-output
'(("raw-sink-name" "Friendly Sink Name" "no" "IDLE"))))))
(let ((sinks (cj/recording--get-available-sinks)))
- (should (equal "Friendly Sink Name" (cdr (car sinks)))))))
+ (should (equal "Friendly Sink Name" (nth 1 (car sinks)))))))
+
+(ert-deftest test-get-available-sinks-normal-includes-state ()
+ "Test that PulseAudio state is returned as third element."
+ (cl-letf (((symbol-function 'shell-command-to-string)
+ (lambda (_cmd)
+ (test-sinks--make-pactl-output
+ '(("sink-a" "Sink A" "no" "RUNNING"))))))
+ (let ((sinks (cj/recording--get-available-sinks)))
+ (should (equal "RUNNING" (nth 2 (car sinks)))))))
(ert-deftest test-get-available-sinks-normal-multiple-sinks ()
"Test that multiple non-muted sinks are returned."
diff --git a/tests/test-video-audio-recording-quick-setup.el b/tests/test-video-audio-recording-quick-setup.el
index f082f86a..23314bd5 100644
--- a/tests/test-video-audio-recording-quick-setup.el
+++ b/tests/test-video-audio-recording-quick-setup.el
@@ -3,8 +3,10 @@
;;; Commentary:
;; Unit tests for cj/recording-quick-setup function.
;; The quick setup is a two-step flow:
-;; Step 1: Pick a microphone (with active/inactive indicators)
-;; Step 2: Pick an audio output (sink) with active/inactive indicators
+;; Step 1: Pick a microphone (with state labels)
+;; Step 2: Pick an audio output (sink) with state labels
+;; Both steps show [active - running], [active - idle], or
+;; [inactive - suspended] after the device description.
;; The chosen sink's .monitor source is set as the system audio device.
;;; Code:
@@ -37,14 +39,10 @@
(test-quick-setup-setup)
(unwind-protect
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("jabra-input" . "Jabra SPEAK 510 Mono")
- ("builtin-input" . "Built-in Analog"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil))
+ (lambda () '(("jabra-input" "Jabra SPEAK 510 Mono" "SUSPENDED")
+ ("builtin-input" "Built-in Analog" "SUSPENDED"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("jds-labs" . "JDS Labs Element IV"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (_name) nil))
+ (lambda () '(("jds-labs" "JDS Labs Element IV" "RUNNING"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
(car (all-completions "" table)))))
@@ -57,13 +55,9 @@
(test-quick-setup-setup)
(unwind-protect
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("jabra-input" . "Jabra SPEAK 510 Mono"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil))
+ (lambda () '(("jabra-input" "Jabra SPEAK 510 Mono" "SUSPENDED"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("alsa_output.usb-JDS_Labs-00.analog-stereo" . "JDS Labs Element IV"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (_name) nil))
+ (lambda () '(("alsa_output.usb-JDS_Labs-00.analog-stereo" "JDS Labs Element IV" "RUNNING"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
(car (all-completions "" table)))))
@@ -78,13 +72,9 @@
(unwind-protect
(let ((call-count 0))
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("mic-1" . "Mic One"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil))
+ (lambda () '(("mic-1" "Mic One" "SUSPENDED"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("sink-1" . "Sink One"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (_name) nil))
+ (lambda () '(("sink-1" "Sink One" "SUSPENDED"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
(setq call-count (1+ call-count))
@@ -93,21 +83,16 @@
(should (= 2 call-count))))
(test-quick-setup-teardown)))
-(ert-deftest test-video-audio-recording-quick-setup-normal-active-mic-indicator ()
- "Test that active mics get the green mic icon in their label."
+(ert-deftest test-video-audio-recording-quick-setup-normal-running-label ()
+ "Test that RUNNING devices show [active - running] label."
(test-quick-setup-setup)
(unwind-protect
(let ((mic-candidates nil)
(call-count 0))
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("active-mic" . "Active Mic")
- ("idle-mic" . "Idle Mic"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (name) (equal name "active-mic")))
+ (lambda () '(("mic-1" "Running Mic" "RUNNING"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("sink-1" . "Sink One"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (_name) nil))
+ (lambda () '(("sink-1" "Sink One" "SUSPENDED"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
(setq call-count (1+ call-count))
@@ -116,99 +101,78 @@
(setq mic-candidates candidates))
(car candidates)))))
(cj/recording-quick-setup)
- ;; Both should have 󰍬 icon
- (should (cl-some (lambda (c) (and (string-match-p "Active Mic" c)
- (string-match-p "󰍬" c)))
- mic-candidates))
- (should (cl-some (lambda (c) (and (string-match-p "Idle Mic" c)
- (string-match-p "󰍬" c)))
+ (should (cl-some (lambda (c) (string-match-p "\\[active - running\\]" c))
mic-candidates))))
(test-quick-setup-teardown)))
-(ert-deftest test-video-audio-recording-quick-setup-normal-active-mic-sorted-first ()
- "Test that active mics are sorted to the top of the list."
+(ert-deftest test-video-audio-recording-quick-setup-normal-idle-label ()
+ "Test that IDLE devices show [active - idle] label."
(test-quick-setup-setup)
(unwind-protect
- (let ((mic-candidates nil)
+ (let ((sink-candidates nil)
(call-count 0))
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("idle-mic" . "Idle Mic")
- ("active-mic" . "Active Mic"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (name) (equal name "active-mic")))
+ (lambda () '(("mic-1" "Mic One" "SUSPENDED"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("sink-1" . "Sink One"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (_name) nil))
+ (lambda () '(("sink-1" "Idle Sink" "IDLE"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
(setq call-count (1+ call-count))
(let ((candidates (all-completions "" table)))
- (when (= call-count 1)
- (setq mic-candidates candidates))
+ (when (= call-count 2)
+ (setq sink-candidates candidates))
(car candidates)))))
(cj/recording-quick-setup)
- ;; First candidate should be the active mic
- (should (string-match-p "Active Mic" (car mic-candidates)))))
+ (should (cl-some (lambda (c) (string-match-p "\\[active - idle\\]" c))
+ sink-candidates))))
(test-quick-setup-teardown)))
-(ert-deftest test-video-audio-recording-quick-setup-normal-active-sink-indicator ()
- "Test that active sinks get 󰕾 and inactive sinks get 󰖀."
+(ert-deftest test-video-audio-recording-quick-setup-normal-suspended-label ()
+ "Test that SUSPENDED devices show [inactive - suspended] label."
(test-quick-setup-setup)
(unwind-protect
- (let ((sink-candidates nil)
+ (let ((mic-candidates nil)
(call-count 0))
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("mic-1" . "Mic One"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil))
+ (lambda () '(("mic-1" "Suspended Mic" "SUSPENDED"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("active-sink" . "Active Sink")
- ("inactive-sink" . "Inactive Sink"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (name) (equal name "active-sink")))
+ (lambda () '(("sink-1" "Sink One" "SUSPENDED"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
(setq call-count (1+ call-count))
(let ((candidates (all-completions "" table)))
- (when (= call-count 2)
- (setq sink-candidates candidates))
+ (when (= call-count 1)
+ (setq mic-candidates candidates))
(car candidates)))))
(cj/recording-quick-setup)
- ;; Active sink should have 󰕾 icon
- (should (cl-some (lambda (c) (and (string-match-p "Active Sink" c)
- (string-match-p "󰕾" c)))
- sink-candidates))
- ;; Inactive sink should have 󰖀 icon
- (should (cl-some (lambda (c) (and (string-match-p "Inactive Sink" c)
- (string-match-p "󰖀" c)))
- sink-candidates))))
+ (should (cl-some (lambda (c) (string-match-p "\\[inactive - suspended\\]" c))
+ mic-candidates))))
(test-quick-setup-teardown)))
-(ert-deftest test-video-audio-recording-quick-setup-normal-active-sorted-first ()
- "Test that active sinks are sorted to the top of the list."
+(ert-deftest test-video-audio-recording-quick-setup-normal-sorted-by-state ()
+ "Test that devices are sorted running → idle → suspended."
(test-quick-setup-setup)
(unwind-protect
- (let ((sink-candidates nil))
+ (let ((mic-candidates nil)
+ (call-count 0))
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("mic-1" . "Mic One"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil))
+ (lambda () '(("suspended-mic" "Suspended Mic" "SUSPENDED")
+ ("running-mic" "Running Mic" "RUNNING")
+ ("idle-mic" "Idle Mic" "IDLE"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("inactive-sink" . "Inactive Sink")
- ("active-sink" . "Active Sink"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (name) (equal name "active-sink")))
+ (lambda () '(("sink-1" "Sink One" "SUSPENDED"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
+ (setq call-count (1+ call-count))
(let ((candidates (all-completions "" table)))
- (when (cl-some (lambda (c) (string-match-p "Sink" c)) candidates)
- (setq sink-candidates candidates))
+ (when (= call-count 1)
+ (setq mic-candidates candidates))
(car candidates)))))
(cj/recording-quick-setup)
- ;; First non-Cancel candidate should be the active sink
- (let ((first-sink (car sink-candidates)))
- (should (string-match-p "Active Sink" first-sink)))))
+ ;; First should be running, then idle, then suspended
+ (should (string-match-p "Running Mic" (nth 0 mic-candidates)))
+ (should (string-match-p "Idle Mic" (nth 1 mic-candidates)))
+ (should (string-match-p "Suspended Mic" (nth 2 mic-candidates)))))
(test-quick-setup-teardown)))
(ert-deftest test-video-audio-recording-quick-setup-normal-confirmation-message ()
@@ -217,13 +181,9 @@
(unwind-protect
(let ((message-text nil))
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("jabra-input" . "Jabra SPEAK 510 Mono"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil))
+ (lambda () '(("jabra-input" "Jabra SPEAK 510 Mono" "RUNNING"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("jds-labs.analog-stereo" . "JDS Labs Element IV"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (_name) nil))
+ (lambda () '(("jds-labs.analog-stereo" "JDS Labs Element IV" "RUNNING"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
(car (all-completions "" table))))
@@ -243,13 +203,9 @@
(unwind-protect
(let ((read-called 0))
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("sole-mic" . "Only Mic Available"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil))
+ (lambda () '(("sole-mic" "Only Mic Available" "SUSPENDED"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("sole-sink" . "Only Sink"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (_name) nil))
+ (lambda () '(("sole-sink" "Only Sink" "SUSPENDED"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
(setq read-called (1+ read-called))
@@ -266,13 +222,9 @@
(test-quick-setup-setup)
(unwind-protect
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("jabra-input" . "Jabra SPEAK 510 Mono"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil))
+ (lambda () '(("jabra-input" "Jabra SPEAK 510 Mono" "SUSPENDED"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("sink-1" . "Sink One"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (_name) nil))
+ (lambda () '(("sink-1" "Sink One" "SUSPENDED"))))
((symbol-function 'completing-read)
(lambda (_prompt _choices &rest _args)
"Cancel")))
@@ -287,13 +239,9 @@
(unwind-protect
(let ((call-count 0))
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () '(("jabra-input" . "Jabra SPEAK 510 Mono"))))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil))
+ (lambda () '(("jabra-input" "Jabra SPEAK 510 Mono" "SUSPENDED"))))
((symbol-function 'cj/recording--get-available-sinks)
- (lambda () '(("sink-1" . "Sink One"))))
- ((symbol-function 'cj/recording--sink-active-p)
- (lambda (_name) nil))
+ (lambda () '(("sink-1" "Sink One" "SUSPENDED"))))
((symbol-function 'completing-read)
(lambda (_prompt table &rest _args)
(setq call-count (1+ call-count))
@@ -311,9 +259,7 @@
(test-quick-setup-setup)
(unwind-protect
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () nil))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil)))
+ (lambda () nil)))
(should-error (cj/recording-quick-setup) :type 'user-error))
(test-quick-setup-teardown)))
@@ -322,9 +268,7 @@
(test-quick-setup-setup)
(unwind-protect
(cl-letf (((symbol-function 'cj/recording--get-available-mics)
- (lambda () nil))
- ((symbol-function 'cj/recording--mic-active-p)
- (lambda (_name) nil)))
+ (lambda () nil)))
(condition-case err
(cj/recording-quick-setup)
(user-error