-
Notifications
You must be signed in to change notification settings - Fork 0
/
volume.lisp
134 lines (108 loc) · 4.45 KB
/
volume.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
(uiop:define-package :stumpwm-init/volume
(:use :cl :iterate)
(:export #:adjust-volume #:set-volume #:toggle-mute #:mute #:unmute #:volume-10+ #:volume-10-)
(:import-from :stumpwm-init/shell-command
#:collect-process-output-to-string #:collect-process-error-to-string)
(:import-from :stumpwm
#:defcommand #:message))
(cl:in-package :stumpwm-init/volume)
(defun program-exists-p (name)
(handler-case (sb-ext:run-program name '("--version")
:search t
:wait t
:output nil
:error nil
:input nil)
(error (e) (declare (ignorable e)) nil)
(:no-error (proc) (declare (ignorable proc)) t)))
(defparameter *pamixer-program*
(find-if #'program-exists-p '("pamixer")))
(defparameter *pulsemixer-program*
(find-if #'program-exists-p '("pulsemixer")))
(declaim (ftype (function (string &rest string) (values string &optional))
run-program-return-error-or-output))
(defun run-program-return-error-or-output (program &rest args)
(let* ((process (sb-ext:run-program program args
:search t
:wait t
:output :stream
:error :stream
:input nil))
(output (collect-process-output-to-string process))
(error (collect-process-error-to-string process)))
(if (> (length error) 0)
error
output)))
(declaim (ftype (function (&rest string) (values string &optional))
pamixer))
(defun pamixer (&rest args)
(if *pamixer-program*
(apply #'run-program-return-error-or-output *pamixer-program* args)
(error "pamixer not installed")))
(declaim (ftype (function (&rest string) (values string &optional))
pulsemixer))
(defun pulsemixer (&rest args)
(if *pulsemixer-program*
(apply #'run-program-return-error-or-output *pulsemixer-program* args)
(error "pulsemixer not installed")))
(defun mixerp (mixer)
(ecase mixer
((pulse pulsemixer) (not (not *pulsemixer-program*)))
((pa pamixer) (not (not *pamixer-program*)))))
(defun call-mixer-program-case (alist)
(iter (for (mixer . func) in alist)
(when (mixerp mixer) (return (funcall func)))
(finally (error "No applicable mixer found"))))
(defmacro mixer-case (&body clauses)
(flet ((transform-clause (clause)
(destructuring-bind (mixer &body then) clause
`(cons ',mixer (lambda () (,mixer ,@then))))))
`(call-mixer-program-case (list ,@(mapcar #'transform-clause clauses)))))
(defcommand show-volume () ()
(message "~a" (mixer-case
(pamixer "--get-volume-human")
(pulsemixer "--get-volume")))
(values))
(declaim (ftype (function (unsigned-byte) (values string &optional))
increase-volume decrease-volume))
(defun increase-volume (delta)
(mixer-case
(pamixer "--increase" (prin1-to-string delta) "--allow-boost")
(pulsemixer "--change-volume" (concatenate 'string "+" (prin1-to-string delta)))))
(defun decrease-volume (delta)
(mixer-case
(pamixer "--decrease" (prin1-to-string delta) "--allow-boost")
(pulsemixer "--change-volume" (concatenate 'string "-" (prin1-to-string delta)))))
(defcommand adjust-volume (delta) ((:number "volume delta (%): "))
"increase or decrease system volume by DELTA
DELTA should be an integer representing a positive or negative percentage."
(if (< delta 0)
(decrease-volume (abs delta))
(increase-volume delta))
(show-volume))
(defcommand set-volume (target) ((:number "absolute volume (%): "))
"set system volume to TARGET
TARGET should be a non-negative integer representing a percentage."
(mixer-case
(pamixer "--set-volume" (prin1-to-string target) "--allow-boost")
(pulsemixer "--set-volume" (prin1-to-string target)))
(show-volume))
(defcommand toggle-mute () ()
(mixer-case
(pamixer "--toggle-mute")
(pulsemixer "--toggle-mute"))
(show-volume))
(defcommand mute () ()
(mixer-case
(pamixer "--mute")
(pulsemixer "--mute"))
(show-volume))
(defcommand unmute () ()
(mixer-case
(pamixer "--unmute")
(pulsemixer "--unmute"))
(show-volume))
(defcommand volume-10+ () ()
(adjust-volume 10))
(defcommand volume-10- () ()
(adjust-volume -10))