- (defun b/get-volume-level (&optional mic)
- "Returns the current system sound volume.
-If MIC is non-nil, it returns the microphone volume instead."
- (string-to-number
- (string-trim
- (shell-command-to-string
- (mapconcat
- #'identity
- `("pamixer" ,(when mic "--default-source") "--get-volume")
- " ")))))
-
- (defun b/set-volume-level (level &optional mic)
- "Set the system sound volume to LEVEL.
-If MIC is non-nil, set the volume level for the microphone
-instead."
- (let ((v (if mic 'b/volume-level-mic 'b/volume-level)))
- (eval `(setq ,v ,level))))
-
- (defun b/get-volume-mute (&optional mic)
- "Returns t if system sound is currently muted.
-If MIC is non-nil, it instead returns t if the microphone is
-muted."
- (string=
- "true"
- (string-trim
- (shell-command-to-string
- (mapconcat
- #'identity
- `("pamixer" ,(when mic "--default-source") "--get-mute")
- " ")))))
-
- (defun b/set-volume-mute (mute &optional mic)
- "Set the system sound mutedness to MUTE.
-If MIC is non-nil, set the mutedness for the microphone instead."
- (let ((v (if mic 'b/volume-mute-mic 'b/volume-mute)))
- (eval `(setq ,v ,mute))))
-
- (defvar b/volume-level (b/get-volume-level))
- (defvar b/volume-mute (b/get-volume-mute))
- (defvar b/volume-level-mic (b/get-volume-level 'mic))
- (defvar b/volume-mute-mic (b/get-volume-mute 'mic))
+ (defvar b/volume-level 0)
+ (defvar b/volume-mute nil)
+ (defvar b/volume-level-mic 0)
+ (defvar b/volume-mute-mic nil)
+
+ (defun b/volume-get (&optional use-default-source)
+ "Get the default sink volume and mute state.
+If USE-DEFAULT-SOURCE is non-nill, use the default source (e.g. a
+microphone) instead of the default sink."
+ (pcase (split-string ; expecting: <mute> <volume> (e.g. true 15)
+ (string-trim
+ (shell-command-to-string
+ (mapconcat
+ #'identity
+ `("pamixer"
+ ,(when use-default-source "--default-source")
+ "--get-volume"
+ "--get-mute")
+ " "))))
+ (`(,m ,v)
+ (let ((mute (string= "true" m))
+ (volume (string-to-number v)))
+ `(,mute ,volume)))))
+
+ (defun b/volume-update ()
+ "Update system sound volume as displayed in mode-line."
+ (let ((changed))
+ (pcase (b/volume-get)
+ (`(,mute ,volume)
+ (unless (eq mute b/volume-mute)
+ (setq b/volume-mute mute
+ changed t))
+ (unless (= volume b/volume-level)
+ (setq b/volume-level volume
+ changed t))))
+ (pcase (b/volume-get 'mic)
+ (`(,mute ,volume)
+ (unless (eq mute b/volume-mute-mic)
+ (setq b/volume-mute-mic mute
+ changed t))
+ (unless (= volume b/volume-level-mic)
+ (setq b/volume-level-mic volume
+ changed t))))
+ (when changed
+ (force-mode-line-update))))
+
+ (defvar b/volume-timer (run-at-time nil 5 #'b/volume-update))