1 ;;; sndio.el --- Interact with sndio(8) -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2020, 2021 Free Software Foundation, Inc.
5 ;; Author: Omar Polo <op@omarpolo.com>
7 ;; Keywords: multimedia
8 ;; URL: https://git.omarpolo.com/sndio.el
9 ;; Package-Requires: ((emacs "25.1"))
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation, either version 3 of the License, or
14 ;; (at your option) any later version.
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
26 ;; This package provides the sndio major mode to interact with
38 (defcustom sndio-sndioctl-cmd "sndioctl"
39 "Path to the sndioctl executable."
42 (defcustom sndio-step 0.02
43 "Step for `sndio-increase' and `sndio-decrease'."
46 (defvar sndio--window nil
49 (defvar sndio-mode-map
50 (let ((m (make-sparse-keymap)))
51 (define-key m (kbd "n") #'forward-line)
52 (define-key m (kbd "p") #'previous-line)
53 (define-key m (kbd "i") #'sndio-increase)
54 (define-key m (kbd "d") #'sndio-decrease)
55 (define-key m (kbd "m") #'sndio-mute)
56 (define-key m (kbd "t") #'sndio-toggle)
57 (define-key m (kbd "g") #'sndio-update)
58 (define-key m (kbd "q") #'sndio-quit)
62 (define-derived-mode sndio-mode special-mode "sndio"
63 "Major mode for sndio interaction."
67 (defun sndio-update ()
68 "Update the current sndio buffer."
70 (unless (executable-find sndio-sndioctl-cmd)
71 (user-error "Can't find executable %s, is sndio installed?"
73 (when (derived-mode-p 'sndio-mode)
74 (let ((inhibit-read-only t))
76 (process-file sndio-sndioctl-cmd nil (current-buffer) nil)
77 (goto-char (point-min)))))
79 (defun sndio--run (&rest args)
80 "Run `sndio-sndioctl-cmd' with ARGS yielding its output."
82 (when (zerop (apply #'process-file sndio-sndioctl-cmd nil t nil args))
85 (defun sndio--current-io ()
86 "Yield the input/poutput at point as string."
87 (when-let (end (save-excursion
89 (ignore-errors (search-forward "="))))
90 (buffer-substring-no-properties (line-beginning-position)
93 (defun sndio--update-value (x)
94 "Update the value for the input/output at point setting it to X."
98 (let ((inhibit-read-only t))
99 (delete-region (point) (line-end-position))
100 (insert (string-trim-right x)))))
102 (defun sndio-increase ()
103 "Increase the volume for the input/output at point."
105 (when-let (x (sndio--current-io))
106 (when-let (val (sndio--run "-n" (concat x "=+" (number-to-string sndio-step))))
107 (sndio--update-value val))))
109 (defun sndio-decrease ()
110 "Decrease the volume for the input/output at point."
112 (when-let (x (sndio--current-io))
113 (when-let (val (sndio--run "-n" (concat x "=-" (number-to-string sndio-step))))
114 (sndio--update-value val))))
117 "Mute the input/output at point."
119 (when-let (x (sndio--current-io))
120 (when-let (val (sndio--run "-n" (concat x "=0")))
121 (sndio--update-value val))))
123 (defun sndio-toggle ()
124 "Toggle input/output at point."
126 (when-let (x (sndio--current-io))
127 (when-let (val (sndio--run "-n" (concat x "=!")))
128 (sndio--update-value val))))
132 Call `delete-window' when the sndio popup window is open or
133 `quit-window' otherwise."
135 (if (window-live-p sndio--window)
143 (switch-to-buffer "*sndio*")
147 (defun sndio-win-open ()
148 "Open an sndio window at the bottom of the frame for quick editing."
150 (unless (window-live-p sndio--window)
153 (let ((ignore-window-parameters t))
154 (split-window (frame-root-window)
158 (switch-to-buffer (get-buffer-create "*sndio-quick*")
160 (if (derived-mode-p 'sndio-mode)
164 (setq mode-line-format nil
165 header-line-format nil
167 (set-window-hscroll sndio--window 0)
168 (set-window-dedicated-p sndio--window t)
169 (select-window sndio--window 'norecord)
170 (let ((window-resize-pixelwise t)
172 (fit-window-to-buffer sndio--window nil nil 1))))
175 ;;; sndio.el ends here