aboutsummaryrefslogtreecommitdiff
path: root/sndio.el
blob: ea5413e6db6edb19309107661d011aac93e60913 (plain)
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
;;; sndio.el --- Interact with sndio(8)  -*- lexical-binding: t; -*-

;; Copyright (C) 2020 Omar Polo

;; Author: Omar Polo <op@omarpolo.com>
;; Version: 1.0
;; Keywords: multimedia
;; URL: https://git.omarpolo.com/sndio.el

;;; Commentary:

;; This package provides the sndio major mode to interact with
;; OpenBSD' sndio(8).

;;; Code:

(eval-when-compile (require 'subr-x))

(defvar sndio-sndioctl-cmd "sndioctl"
  "Path to the sndioctl executable.")

(defvar sndio-step 0.02
  "Step for `sndio-increase' and `sndio-decrease'.")

(defvar sndio-mode-map
  (let ((m (make-sparse-keymap)))
    (define-key m (kbd "n") #'forward-line)
    (define-key m (kbd "p") #'previous-line)
    (define-key m (kbd "i") #'sndio-increase)
    (define-key m (kbd "d") #'sndio-decrease)
    (define-key m (kbd "m") #'sndio-mute)
    (define-key m (kbd "t") #'sndio-toggle)
    (define-key m (kbd "g") #'sndio-update)
    m)
  "Keymap for sndio.")

(define-derived-mode sndio-mode special-mode "sndio"
  "Major mode for sndio interaction."
  (buffer-disable-undo)
  (sndio-update))

(defun sndio-update ()
  "Update the current sndio buffer."
  (interactive)
  (with-current-buffer "*sndio*"
    (let ((inhibit-read-only t))
      (erase-buffer)
      (process-file sndio-sndioctl-cmd nil (current-buffer) nil))))

(defun sndio--run (&rest args)
  "Run `sndio-sndioctl-cmd' with ARGS yielding its output."
  (with-temp-buffer
    (when (zerop (apply #'process-file sndio-sndioctl-cmd nil t nil args))
      (buffer-string))))

(defun sndio--current-io ()
  "Yield the input/poutput at point as string."
  (when-let (end (save-excursion
                   (beginning-of-line)
                   (ignore-errors (search-forward "="))))
    (buffer-substring-no-properties (line-beginning-position)
                                    (1- end))))

(defun sndio--update-value (x)
  "Update the value for the input/output at point setting it to X."
  (save-excursion
    (beginning-of-line)
    (search-forward "=")
    (let ((inhibit-read-only t))
      (delete-region (point) (line-end-position))
      (insert (string-trim-right x)))))

(defun sndio-increase ()
  "Increase the volume for the input/output at point."
  (interactive)
  (when-let (x (sndio--current-io))
    (when-let (val (sndio--run "-n" (concat x "=+" (number-to-string sndio-step))))
      (sndio--update-value val))))

(defun sndio-decrease ()
  "Decrease the volume for the input/output at point."
  (interactive)
  (when-let (x (sndio--current-io))
    (when-let (val (sndio--run "-n" (concat x "=-" (number-to-string sndio-step))))
      (sndio--update-value val))))

(defun sndio-mute ()
  "Mute the input/output at point."
  (interactive)
  (when-let (x (sndio--current-io))
    (when-let (val (sndio--run "-n" (concat x "=0")))
      (sndio--update-value val))))

(defun sndio-toggle ()
  "Toggle input/output at point."
  (interactive)
  (when-let (x (sndio--current-io))
    (when-let (val (sndio--run "-n" (concat x "=!")))
      (sndio--update-value val))))

;;;###autoload
(defun sndio ()
  "Launch sndio."
  (interactive)
  (switch-to-buffer "*sndio*")
  (sndio-mode))

(provide 'sndio)
;;; sndio.el ends here