How to configure hotkeys on multimedia keyboards in Linux

By

Patrick A. Read

June 2, 2005


Many PC keyboards these days have a plethora of "hotkeys" -- keys which usually have only one function associated with them; usually an icon on the key itself explains which function pressing that key performs.

For example, a button on the top or side of the keyboard with an envelope icon usually means "E-Mail" and a similarly-shaped button nearby with a speaker icon and an "X" across it means "Mute".

By default, these keyboards work usually without any drivers in Microsoft Windows. However, for Linux, they usually don't work automatically "out-of-the-box".

The keyboard I use is a Logitech Elite LE model with a matching mouse which I purchased at Wal-Mart. I'm curious as to whether this is a custom model manufactured solely for Wal-Mart (A lot of gadgets are exclusively made for sale at Wal-Mart in this fashion) since I can't find this EXACT model on Logitech's Web site. Here is a very similar model (hyperlink):

http://www.logitech.com/index.cfm/products/details/US/EN,CRID=2166,CONTENTID=5013

CAVEAT: I know this works with KDE. I do not know how to do this with Gnome, but surely the process is similar.

REQUIREMENTS:

  1. X Windows and K Desktop Environment version 3.x or newer. These keys only work inside a GUI anyway.
  2. Linux kernel 2.4 or 2.6.
  3. Web browser (to map the "WWW" key). I use Firefox, but Mozilla, Netscape, and Opera all work fine. You could even use Internet Explorer if you can Wine it. :-)
  4. X Multimedia System (XMMS) (to map the play/pause key). Other GNU/Linux media players might work fine, even command-line players like mpg321, but XMMS has command-line switches which enable play/pause from a shell prompt even though it is considered a GUI media player.
  5. Alsa-utils installed (to map volume and mute buttons, I needed some shell commands provided by the alsa-utils package). Most Linux distros include these anyway. For info, check out http://alsa-project.org/.

MY HW/SW CONFIGURATION (Hey, it works great here):

  1. Homebuilt desktop PC with Pentium-4, Intel D865GBF motherboard with on-board Intel AC'97 (Linux likes these!), etc. Older/ slower hardware with sound card that functions in Linux should work fine.
  2. Slackware 10.1 with latest security updates.
  3. Linux kernel 2.6.11.11 downloaded from http://www.kernel.org/. I seem to have a obsession for downloading and using the absolutely latest kernel version available! :-) Again, any of the distros' kernels versions 2.4 or 2.6 should work fine.
  4. X11 and KDE defaults found on Slackware 10.1. X.org version is used here, but I'm certain that users of XFree86 would have no trouble. KDE version 3.3.2 used here; earlier versions of 3.x shouldn't give any trouble.
  5. All the ALSA stuff included with Slackware 10.1.
  6. XMMS version 1.2.10 compiled from source. I use all the MPEG-1 Layer 3 (MP3) stuff from mpg123 (but mpg321 would work equally well). I mention this since all my music collection is in MP3 format.
  7. NOTE: Redhat/Fedora users might not have MP3 support "right-out-of-the-box", but there exist many RPM's and package installers for MP3 and RH/Fedora online. Getting MP3's to play in RH/Fedora is beyond the scope of this document (but it ISN'T impossible). Check out the following hyperlink:

    http://tldp.org/HOWTO/Fedora-Multimedia-Installation-HOWTO/

  8. The Logitech Elite keyboard mentioned earlier. My particular model has the following buttons/icons: I was able to get each button mapped to its most closely related action with the following exceptions:
    1. The e-mail button presumably was designed for an e-mail client such as Outlook Express, Outlook, Eudora, or similar, but I set mine up for opening the Web browser to the Web mail account I use.
    2. The media button presumably was designed to open a player of some kind (Windows Media Player, Winamp, RealPlayer, etc.) but I instead used it to open the folder containing my music files.
    3. The Webcam button didn't map at all, but since I don't have a Webcam, this was not an issue for me. Apologies to all who use a Webcam and would like this button to work. :-(

PROCEDURE:

  1. Ensure that X is running (runlevel 5 in most distros; Slackware and a few others use runlevel 4 as the X runlevel). If X is not running, then type startx at the shell prompt.
  2. Create a bin directory inside your non-privileged user account home directory if not already there (Example: /home/patrick/bin).
  3. Ensure that the ${PATH} includes this directory. If not, then edit either the ~/.bash_profile or (as root) /etc/profile to include this directory in the ${PATH}.

    The easiest way to add ~/bin to the ${PATH} is to add the following line to the ~/.bash_profile script:

    PATH="${HOME}/bin:${PATH}"

  4. NOTE: I dwell on adding a ~/bin directory and adding it to the ${PATH} because the intent is that of a non-root user using these scripts and it's a good idea to have a local ~/bin directory in which to place your scripts. You could certainly place these scripts inside the system-wide /bin, /usr/bin, or /usr/local/bin directories just as easily.

  5. Use {vi|joe|emacs|jpico|gedit|kwrite|your_favorite_editor} to create three scripts inside the ~/bin directory you just created. The names of scripts are: louder, softer, and mute. Yes, each of them does pretty much exactly what its title suggests.

    louder

          #!/bin/bash
          ###########################################
          # Copyright (C) 2005 Patrick A. Read
          #
          # louder - this shell script increases
          # the volume of the Master playback control
          # in alsamixer.  Usage: louder [number]
          # where (optional) number is the number of 
          # "clicks" you wish to increase the volume.
          # Example:  louder 4 cranks up the volume
          # four steps.  If you do not specify a
          # number, then louder will raise the
          # volume one step.  NOTE:  Alsamixer uses
          # 32 steps (0-31) in its volume controls.
          ###########################################
          if [ "$1" != "" ]
          then
           VOLADJ=${1}+
          else
           VOLADJ="1+"
          fi
          amixer set Master ${VOLADJ}
          exit 0
          ###########################################
          # end of louder script
          ###########################################
    
    softer

          #!/bin/bash
          ###########################################
          # Copyright (C) 2005 Patrick A. Read
          #
          # softer - this shell script decreases
          # the volume of the Master playback control
          # in alsamixer.  Usage: softer [number]
          # where (optional) number is the number of
          # "clicks" you wish to decrease the volume.
          # Example:  softer 3 softens the volume
          # three steps.  If you do not specify a
          # number, then softer will lower the
          # volume one step.   NOTE: Alsamixer uses 
          # 32 steps (0-31) in its volume controls.
          ###########################################       
          if [ "$1" != "" ]
          then
           VOLADJ=${1}-
          else
           VOLADJ="1-"
          fi
          amixer set Master ${VOLADJ}
          exit 0
          ###########################################
          # end of softer script
          ###########################################
    
    mute

          
          #!/bin/bash
          ###########################################
          # Copyright (C) 2005 Patrick A. Read
          #
          # This script toggles muting the playback
          # of the Master volume device in alsamixer.
          # Usage: mute (no arguments) - the mute
          # state is TOGGLED by successively running
          # this script.  The volume level of the
          # Master control is saved to a temp file
          # (see script for details) so that when mute
          # is run again, the prior volume level is 
          # restored.  If this temp file does not exist 
          # when the user unmutes using this script, 
          # then I found a default value of 22 (on a
          # 0-31 scale) to be a comfortable level.
          # Feel free to vary this to your liking.
          ###########################################
          declare -r TEMPVOLFILE="/tmp/kde-${USER}/volume.tmp"
          declare -r CURRENTVOLUME=$(amixer get Master | grep \
           'Front Left:' | cut -d' ' -f6)
          declare -i NEWVOLUME
    
          if [ "${CURRENTVOLUME}" == "0" ]
          then
           if [ -f ${TEMPVOLFILE} ]
           then
            NEWVOLUME=$(cat ${TEMPVOLFILE})
           else
            NEWVOLUME=22
           fi
           amixer set Master ${NEWVOLUME}
          else
           echo ${CURRENTVOLUME} > ${TEMPVOLFILE}
           amixer set Master 0
          fi
          exit 0
          ###########################################
          # end of mute script
          ###########################################
    
  6. Open a shell prompt and make these scripts executable:

          patrick@pr01:~$ cd ~/bin
          patrick@pr01:~/bin$ chmod 755 ./softer ./louder ./mute
          

    At this point, you can test the scripts by running them with the optional numeric arguments for louder and softer. You will notice that alsamixer returns some console text with regards to the state of the Master control after each script is run.

    NOTE: For this example, we will set up the "Volume Up" key, but the procedure is similar for all hotkeys.

    NOTE: BE SURE TO USE A COMMAND SHELL WINDOW (CONSOLE) WITH A LARGE SCROLL BUFFER (like 500 lines or more).

  7. With the X server running, run xev (from within a command shell). A small window with a black square inside will open up. Also, you might notice a lot of scrolling text inside the command shell. These are normal.

    NOTE: xev is the command shell tool for monitoring X events, such as mouse clicks, mouse pointer movement, window movement/ resizing/opening/closing, and keyboard events.

  8. Press the hotkey you wish to map (Volume Up in this example). A bunch more text will scroll through the console.
  9. Close the xev GUI window using the mouse. BE SURE TO KEEP THE SHELL WINDOW OPEN! Once the xev window is closed, xev will return the command prompt to you.
  10. Scroll upwards in the console window and search for a block of text beginning with the text "KeyRelease event". Inside that block of text will be some parameters returned from xev. The one you're looking for is the number following "keycode" - you should see a 3 digit number (176 on my system for the "Volume Up" button). WRITE DOWN THIS NUMBER FOR THE GIVEN HOTKEY. For example, write down "Volume Up - 176" on a sheet of paper for later reference.

    NOTE: You may see and identical keycode parameter for a "KeyPress event" in addition to the KeyRelease event.

    NOTE: If you see a TWO digit number, you're probably looking at a keycode belonging to a more commonly-used key like a letter or number. BE ABSOLUTELY SURE THAT YOU ARE LOOKING AT THE KEYCODE ASSOCIATED WITH THE HOTKEY YOU'RE PRESSING.

  11. Repeat steps 6-9 for all remaining hotkeys. I found it best to do each key individually, but you could certainly find all keys' mappings in one xev session.

    NOTE: xev returns a KeyPress and KeyRelease event message each time a key is pressed on the keyboard. Additionally, xev returns mouse events (including moving the mouse pointer over different open windows). The sheer amount of text returned by xev inside the console window explains why a large screen buffer is needed and why I personally found it easier to do one key at a time.

    Listed below are the numerical values X shows for the hotkeys on my system (YOUR VALUES MAY VARY):

            Hotkey          keycode
            ======          =======
            Media . . . . . . . 237
            Play/Pause  . . . . 162
            Mute  . . . . . . . 160
            Up Volume . . . . . 176
            Down Volume . . . . 174
            E-Mail  . . . . . . 236
            WWW . . . . . . . . 178
            Calculator  . . . . 161
    
  12. Now that you have all your hotkeys mapped to a numerical keycode that X can understand, it's now time to re-map them to an extended F-key set. For instance, most users are accustomed to the idea of a modern PC keyboard having F1-F12 keys, but what some don't realize is that there are actually 24 F-keys, and F13-F24 are usually available for mapping events.

    Create one last script, call it keycodes.sh.

    NOTE: Your actual keycode values may differ from these here, and you can also choose ANY arbitrary F key from F13 to F24 for each hotkey. The idea here is that any hotkey needs to "pretend" to be an extended F-key for X and KDE to identify it.

    keycodes.sh

          #!/bin/bash
          ###########################################
          # keycodes.sh
          # FORMAT: keycode nnn=Fxx
          # where nnn is the three-digit keycode
          # and xx is any value from 13 to 24 unique
          # for each key.
          ###########################################
    
          xmodmap -e 'keycode 174=F21' # lower volume
          xmodmap -e 'keycode 176=F22' # raise volume
          xmodmap -e 'keycode 160=F23' # mute
          xmodmap -e 'keycode 161=F20' # calculator
          xmodmap -e 'keycode 162=F19' # play-pause
          xmodmap -e 'keycode 237=F18' # media
          xmodmap -e 'keycode 178=F17' # WWW
          xmodmap -e 'keycode 236=F16' # e-mail
    
          exit 0
          ###########################################
          # END OF keycodes.sh SCRIPT
          ###########################################
    
  13. Do NOT put this script in the ~/bin directory created earlier. Instead, put it in the ~/.kde/Autostart directory. Be sure to change the permissions to executable:

          patrick@pr01:~$ chmod 755 ~/.kde/Autostart/keycodes.sh
    
  14. Go ahead and execute the script. It will run automatically every time you log into KDE by virtue of it being in the ~/.kde/Autostart directory. Which it needs to do anyway in order to continue mapping these keys appropriately.

  15. Almost done! The only thing left to do is use KDE's KHotKeys configuration tool to map the keys to a shell command. Open upd KDE's Control Center (click on the K-Gear icon (or the Red Hat fedora or SUSE lizard head, etc.) and click ControlCenter.

    You could either search for "keys" under the "Search" tab or go straight there by expanding the "Regional & Accessibility" tree. Navigate to KHotKeys either way.

    You should see a window with two large panes, four command buttons on the bottom labeled "New Action", "New Group", "Delete Action", and "Global Settings". Click on "New Group". In the input field near the upper right side of the window, it'll say "New Action Group" - edit this and call it "hotkeys".

    Now, a group called "hotkeys" will appear in the left pane (there were two already there on my system, "Examples" and "Konqueror Gestures").

    NOTE: For this example, I will show mapping the "Raise Volume" button to the "louder" shell script we created earlier.

  16. Select the "hotkeys" action group in the left pane and click the "New Action" button at the bottom.

  17. Edit the Action Name field (upper right input field) and call it "Louder" (no quotes).
  18. In the "Action Type" drop-down selection list, select "Keyboard Shortcut -> Command/URL (Simple)" (2nd from top). After this, some of the tabs across the top will change.

  19. Click the "Keyboard Shortcut" tab (middle tab) on the top of the form. The tab form should show a key icon with the label "Select Keyboard Shortcut:". Click INSIDE this key icon.

  20. A new window will pop up prompting you for a key. Press the corresponding hotkey on your keyboard (Volume Up in this first example). The small window will close and the key icon inside the right pane will now show "F22" (or whichever F-key you mapped in the hotkeys.sh script above).

  21. Click the "Command/URL" tab (right-side tab). The window will now say "Command/URL to execute:" and an input field will appear. Inside the input field, type "~/bin/louder" (without quotes).

  22. Repeat steps 15-20 for each hotkey. I used the following commands for the corresponding hotkeys (YOUR VALUES WILL SURELY BE DIFFERENT):

            Hotkey              command
            ======              =======
            Media . . . . . . . konqueror /path/to/media/files
            Play/Pause  . . . . xmms -t
            Mute  . . . . . . . home/USER/bin/mute
            Up Volume . . . . . home/USER/bin/louder
            Down Volume . . . . home/USER/bin/softer
            E-Mail  . . . . . . /path/to/firefox http://www.gmail.com
            WWW . . . . . . . . /path/to/firefox
            Calculator  . . . . kcalc
    
    NOTE: UPDATED JUNE 5: I noticed that ~ (meaning /home/USER/) does NOT work since KDE doesn't interpret this as the user's part of the ${PATH}. Be sure to specify the entire path of script or program. Konqueror, XMMS, and KCalc are in the system default path which KDE already understands, thus the entire path is not needed (although it won't hurt to put it in).

    NOTE: xmms -t simply toggles play/pause XMMS from a command prompt.

    NOTE: mute, louder, and softer are the three scripts created earlier.

    NOTE: For the E-mail button, I chose opening the Web browser to a Web mail page (Google Mail in this example), but it could just as easily be used to open any e-mail client, such as Thunderbird, Netscape Mail, or Mozilla Mail. Or, you could Wine Outlook Express (Just kidding).

    NOTE: The Media button could be used to open a media player, but I chose to open the file browser (konqueror) to my music files directory instead.

  23. Click the "Apply" button near the lower right corner when you have finished mapping all the commands to the keys.

That's it! You now can use multimedia PC keyboards with hotkeys inside of Linux just like you could inside Microsoft Windows or Mac OS X.


back to ALE homepage
The plain ascii version of this article