My Logitech keyboard has several buttons at the top that I wanted to use to control mpd (man|arch). They were Prev, Play/Pause, Next, and Mute/Unmute.
I knew that my window manager i3 (man|arch) was able to bind key combinations to perform functions such as executing a program, switching the visible workspace, or moving a window. The format of the .i3/config file to launch a program on a certain key combination is:
With that known, we need to know how the system refers to those media keys. This is where xev (man|arch) is useful. Xev is a program that will print out data about mouse movements, key press events, and key release events. When the key is unbound you’ll get a KeyPress event like the below:
root 0x28e, subw 0x0, time 654012911, (-169,-224), root:(1755,327),
state 0x10, keycode 20 (keysym 0x2d, minus), same_screen YES,
XLookupString gives 1 bytes: (2d) “-“
XmbLookupString gives 1 bytes: (2d) “-“
XFilterEvent returns: False
Notice the section on the 2nd line, “(keysym 0x2d, minus)”, in this example, I had pressed the “-” key and found that the system refers to it as “minus”. I did this for each of the media keys and found their names to be:
Prev: XF86AudioPrev
Next: XF86AudioNext
Play/Pause: XF86AudioPlay
Mute/Unmute: XF86AudioMute
We can now fill in the key combination section of the .i3/config:
bindsym XF86AudioNext exec <command to execute>
bindsym XF86AudioPlay exec <command to execute>
bindsym XF86AudioMute exec <command to execute>
By reading the man page of mpc(man|arch), we know that it can perform the following functions given the corresponding command:
Prev: mpc prev
Next: mpc next
Play: mpc play
Pause: mpc pause
This makes two of the key bindings straight forward, but leaves us needing a toggle for Play/Pause, as we have one button that must send one of two commands depending on the current state of mpd. Here’s a bash script that will perform just such a toggle: https://github.com/rarmknecht/utilities/blob/master/mpc_toggle
With the mpc_toggle script copied to /usr/local/bin our .i3/config now looks like:
bindsym XF86AudioNext exec mpc next
bindsym XF86AudioPlay exec mpc_toggle
bindsym XF86AudioMute exec <command to execute>
Next up, Mute/Unmute. Because I’m using the ALSA sound drivers I can use the tool amixer (man|arch) to control the Master output. Again, here’s a bash script that allows for a toggle by reading the state of Master before setting it: https://github.com/rarmknecht/utilities/blob/master/my_mute
And that’s it once we drop the script in /usr/bin/local and update the i3 configuration file. We can now play/pause, mute/unmute, go back a song, or skip to the next from the keyboard.
Final .i3/config snippet:
bindsym XF86AudioNext exec mpc next
bindsym XF86AudioPlay exec mpc_toggle
bindsym XF86AudioMute exec my_mute
You know there is a mpc toggle command, right?
I do now. Thanks for the tip!
Thank you for your post, it was very helpful :)
I needed to assign volume up, volume down and mute multimedia keys to alsa and i3 turned out simple to setup:
bindsym XF86AudioLowerVolume exec amixer set Master 3– unmute
bindsym XF86AudioRaiseVolume exec amixer set Master 3+ unmute
bindsym XF86AudioMute exec amixer set Master toggle
Cheers!