Friday, March 16, 2012

Volume Control

So, I've finally started using StumpWM on my desktop (still on Ubuntu though) and I need to address some more practical matters. One of these is changing sound volume.

There's a handy tool called amixer that ships with Ubuntu and Debian (and probably other distros). It can be used to change many parameters of the mixer. Here we simply use it like amixer sset Master 5%+ which simply raises the master volume by 5 percent. That line also prints out the current volume (among other things) which we will use in order to show the user the current volume. I've added this snippet to my .stumpwmrc file:
;; setup volume control key bindings
(defcommand volume-up () ()
  "Increases master volume by 5 percent."
  (let ((result (run-shell-command "amixer sset Master 5%+" t)))
    (cl-ppcre:register-groups-bind (pct) ("\\[(\\d+)%\\]" result)
      (message "~a%" pct))))
(define-key *top-map* (kbd "XF86AudioRaiseVolume") "volume-up")

(defcommand volume-down () ()
  "Increases master volume by 5 percent."
  (let ((result (run-shell-command "amixer sset Master 5%-" t)))
    (cl-ppcre:register-groups-bind (pct) ("\\[(\\d+)%\\]" result)
      (message "~a%" pct))))
(define-key *top-map* (kbd "XF86AudioLowerVolume") "volume-down")

(defcommand volume-mute-toggle () ()
  "Mutes/Unmutes the master volume."
  (let ((result (run-shell-command "amixer sset Master toggle" t)))
    (cl-ppcre:register-groups-bind (state) ("\\[(on|off)\\]" result)
      (if (equalp state "off")
          (message "muted.")
          (message "unmuted.")))))
(define-key *top-map* (kbd "XF86AudioMute") "volume-mute-toggle")
This defines three commands (volume-up, volume-down and volume-mute-toggle) and binds them to the multimedia volume control keys. This works fine on my computer. If the multimedia keys are not available for you, this page suggests adding these lines:
(define-keysym #x1008ff11 "XF86AudioLowerVolume")
(define-keysym #x1008ff12 "XF86AudioMute")
(define-keysym #x1008ff13 "XF86AudioRaiseVolume")
UPDATE: I just noticed that the code for mute does not work on my Desktop (with Ubuntu Precise) though it's perfectly fine on my laptop (which runs Debian Squeeze). After some poking around, I found out that apparently when pulseaudio is present, amixer cannot unmute sound. I looked around for a pulseaudio equivalent and found pactl. But unlike amixer, pactl does not print out the current state of things after running a command and it also (as far as I know) does not provide a toggle command. What I did was to run pactl list first. This command prints out a lot of information from which we can find out if sound is muted or not. In the following snippet, I'm using a very simplistic regular expression to extract this information. It might not work correctly on a different setup
(defcommand volume-mute-toggle () ()
  "Mutes/Unmutes the master volume."
  (cl-ppcre:register-groups-bind (state)
      ("Mute: (yes|no)" (run-shell-command "pactl list" t))
    (cond ((equalp state "yes")
           (run-shell-command "pactl set-sink-mute 0 0")
           (message "unmuted."))
          (t
           (run-shell-command "pactl set-sink-mute 0 1")
           (message "muted.")))))

No comments:

Post a Comment

Better Console Font (in Arch)

In order to use Terminus as my console (tty) font, I simply installed the package terminus-font with pacman (includes both console and X11 ...