Thursday, January 6, 2011

Introducing alsa-mixer

Besides being "that cabal test guy"... Actually, that was about it, until now. Having recently discovered that the complement of ALSA bindings on Hackage lacked an interface to the mixer API, I undertook, over the last week, to implement one. The results of this work are now available on Hackage in the form of alsa-mixer, which provides a high-level interface to the ALSA mixer API.


Why should I care? Or, what is it good for?


Let me tell you why I care. About a month ago, the multimedia buttons on my laptop began to malfunction. In fact, my poor computer simply could not boot with the buttons even attached to the soundcard. Being unable to determine why this would be the case, I did what anyone in my position would do: I opened the darn thing, and disconnected the buttons entirely. It had always been rather convenient for me that the volume buttons did their thing in hardware, so I never had need for any key bindings or what-have-you to make them work. No longer. This was no problem, I thought; running Xmonad, I can just find bindings for the ALSA mixer API on Hackage and hook them to a key binding and voila! My cunning plan was foiled, however, by the absence of such a binding.


Now you, too, can control your soundcard directly from Xmonad! Here's how:

  1. Put the following snippets in your ~/.xmonad/xmonad.hs file:

  2. > changeVolumeBy :: Integer -> IO ()
    > changeVolumeBy i = do
    > Just control <- getControlByName "default" "Master"
    > let Just playbackVolume = playback $ volume control
    > (min, max) <- getRange playbackVolume
    > Just vol <- getChannel FrontLeft $ value $ playbackVolume
    > when ((i > 0 && vol < max) || (i < 0 && vol > min))
    > $ setChannel FrontLeft (value $ playbackVolume) $ vol + i

    > toggleMute :: IO ()
    > toggleMute = do
    > Just control <- getControlByName "default" "Master"
    > let Just playbackSwitch = playback $ switch control
    > Just sw <- getChannel FrontLeft playbackSwitch
    > setChannel FrontLeft playbackSwitch $ not sw

  3. In the same file, import Sound.ALSA.Mixer.

  4. Bind your volume up key to liftIO (changeVolumeBy 1).

  5. Bind your volume down key to liftIO (changeVolumeBy (-1)).

  6. Bind your mute key to liftIO toggleMute.


And you're done! You can find out more about alsa-mixer at its Hackage page or by reading the API documentation.

1 comment:

  1. You can achieve the same with the command line interface to ALSA mixer. I have these bindings in my xmonad.hs:

    ...
    , ("<XF86AudioMute>", spawn "amixer -q set Master toggle")
    , ("<XF86AudioLowerVolume>", spawn "amixer -q set Master 5%- unmute")
    , ("<XF86AudioRaiseVolume>", spawn "amixer -q set Master 5%+ unmute")
    ...

    ReplyDelete