diff --git a/README.org b/README.org index a6c40b2..c9982a0 100644 --- a/README.org +++ b/README.org @@ -77,6 +77,7 @@ Advertise your module here, open a PR and include a org-mode link! - [[./media/amixer/README.org][amixer]] :: Manipulate the volume using amixer - [[./media/stump-radio/README.org][stump-radio]] :: Minimalistic mplayer-based radio for StumpWM. - [[./media/stump-volume-control/README.org][stump-volume-control]] :: Minimalistic amixer-based volume control for StumpWM. +- [[./media/stumpwm-sndioctl/README.md][stumpwm-sndioctl]] :: Interface to OpenBSD's sndioctl for StumpWM. ** Minor Modes - [[./minor-mode/mpd/README.org][mpd]] :: Displays information about the music player daemon (MPD). - [[./minor-mode/notifications/README.org][notifications]] :: A notification library that sends notifications to the modeline via stumpish or from stumpwm itself. diff --git a/media/stumpwm-sndioctl/README.md b/media/stumpwm-sndioctl/README.md new file mode 100644 index 0000000..6601771 --- /dev/null +++ b/media/stumpwm-sndioctl/README.md @@ -0,0 +1,38 @@ +# stumpwm-sndioctl + +stumpwm-sndioctl adds some features to StumpWM so you can control the +volume using OpenBSD's sndioctl, and have it show you pretty messages +as you make changes. + +After loading the module, add something like this to your StumpWM config: +``` +(define-key *top-map* (kbd "XF86AudioMute") "toggle-mute") +(define-key *top-map* (kbd "XF86AudioLowerVolume") "volume-down") +(define-key *top-map* (kbd "XF86AudioRaiseVolume") "volume-up") +``` +The code is documented in Lisp style (i.e. self documenting), see +`stumpwm-sndioctl.lisp` for all the knobs you can turn. + +You can find the upstream repo at: + +https://github.com/fagg/stumpwm-sndioctl + +## License + +Copyright 2021, Dr Ashton Fagg + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted, provided that the +above copyright notice and this permission notice appear in all +copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + diff --git a/media/stumpwm-sndioctl/package.lisp b/media/stumpwm-sndioctl/package.lisp new file mode 100644 index 0000000..da3b861 --- /dev/null +++ b/media/stumpwm-sndioctl/package.lisp @@ -0,0 +1,28 @@ +;;;; package.lisp + +;;;; Copyright 2021, Dr Ashton Fagg +;;;; +;;;; Permission to use, copy, modify, and/or distribute this software for +;;;; any purpose with or without fee is hereby granted, provided that the +;;;; above copyright notice and this permission notice appear in all +;;;; copies. +;;;; +;;;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +;;;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +;;;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +;;;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +;;;; DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +;;;; PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +;;;; TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +;;;; PERFORMANCE OF THIS SOFTWARE. + +(defpackage #:stumpwm-sndioctl + (:use #:cl #:stumpwm) + (:export #:*terse* + #:*step* + #:volume-up + #:volume-down + #:toggle-mute + #:set-mute + #:unset-mute)) + diff --git a/media/stumpwm-sndioctl/stumpwm-sndioctl.asd b/media/stumpwm-sndioctl/stumpwm-sndioctl.asd new file mode 100644 index 0000000..103fcb2 --- /dev/null +++ b/media/stumpwm-sndioctl/stumpwm-sndioctl.asd @@ -0,0 +1,28 @@ +;;;; stump-sndioctl.asd + +;;;; Copyright 2021, Dr Ashton Fagg +;;;; +;;;; Permission to use, copy, modify, and/or distribute this software for +;;;; any purpose with or without fee is hereby granted, provided that the +;;;; above copyright notice and this permission notice appear in all +;;;; copies. +;;;; +;;;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +;;;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +;;;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +;;;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +;;;; DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +;;;; PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +;;;; TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +;;;; PERFORMANCE OF THIS SOFTWARE. + +(asdf:defsystem #:stumpwm-sndioctl + :description "Interface to OpenBSD's sndioctl from StumpWM." + :author "Dr Ashton Fagg " + :license "ISC"" + :version "0.0.1" + :homepage "https://github.com/fagg/stumpwm-sndioctl" + :serial t + :depends-on (#:stumpwm) + :components ((:file "package") + (:file "stumpwm-sndioctl"))) diff --git a/media/stumpwm-sndioctl/stumpwm-sndioctl.lisp b/media/stumpwm-sndioctl/stumpwm-sndioctl.lisp new file mode 100644 index 0000000..ab8251c --- /dev/null +++ b/media/stumpwm-sndioctl/stumpwm-sndioctl.lisp @@ -0,0 +1,88 @@ +;;;; stumpwm-sndioctl.lisp + +;;;; Copyright 2021, Dr Ashton Fagg +;;;; +;;;; Permission to use, copy, modify, and/or distribute this software for +;;;; any purpose with or without fee is hereby granted, provided that the +;;;; above copyright notice and this permission notice appear in all +;;;; copies. +;;;; +;;;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +;;;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +;;;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +;;;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +;;;; DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +;;;; PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +;;;; TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +;;;; PERFORMANCE OF THIS SOFTWARE. + + +(in-package #:stumpwm-sndioctl) + + +(defvar *step* 0.05) +(defvar *terse* nil "If t, this will supress messages that get shown on changes to volume.") + +(defun call-sndioctl (args captive) + "Calls sndioctl with the required arguments." + (run-shell-command (format nil "sndioctl ~a" args) captive)) + +(defun make-step-cmd (direction) + "Helpful wrapper for generating command strings for incrementing/decrementing volume." + (cond + ((string= "+" direction) + (format nil "-q output.level=+~a" *step*)) + ((string= "-" direction) + (format nil "-q output.level=-~a" *step*)) + (t (error "Not a valid step direction!")))) + +(defun get-mute-state-string () + "Returns a nicely formatted string containing the current mute state." + (let ((state (aref (call-sndioctl "-n output.mute" t) 0))) + (cond + ((string= "0" state) + (format nil "Muted: No")) + ((string= "1" state) + (format nil "Muted: Yes")) + (t (error "Unknown output from sndioctl -n output.mute"))))) + +(defun get-volume-level-string () + "Returns a nicely formatted string containing the current volume level." + (let ((level + (with-input-from-string (vol-str (call-sndioctl "-n output.level" t)) + (read vol-str)))) + (format nil "Volume: ~2$%" (* 100.0 level)))) + +(defun sndioctl-status-message () + "Returns a string indicating currrent sndioctl state." + (format nil "~a ~a" (get-volume-level-string) (get-mute-state-string))) + +(defcommand volume-up () () + "Volume goes up" + (call-sndioctl (make-step-cmd "+") nil) + (if (not *terse*) + (message (sndioctl-status-message)))) + +(defcommand volume-down () () + "Volume goes down" + (call-sndioctl (make-step-cmd "-") nil) + (if (not *terse*) + (message (sndioctl-status-message)))) + +(defcommand toggle-mute () () + "Toggles mute" + (call-sndioctl "-q output.mute=!" nil) + (if (not *terse*) + (message (sndioctl-status-message)))) + +(defcommand set-mute () () + "Force sets mute to ON" + (call-sndioctl "-q output.mute=1" nil) + (if (not *terse*) + (message (sndioctl-status-message)))) + +(defcommand unset-mute () () + "Force sets mute to OFF" + (call-sndioctl "-q output.mute=0" nil) + (if (not *terse*) + (message (sndioctl-status-message))))