As I've said in introduction, our goal is to make all HTPC functions available through remote controller, without need for a mouse or similar "pointing" input device. Obviously, we need to make every function accessible through simple keyboard shortcuts and configure our remote to simulate those keypresses. Since most of remote controls don't have modifier keys (Control, Alt etc.) keyboard shortcuts must be single keys, but on the other hand we may use all the keycodes that X window system knows about instead of using only the ones that we are accustomed on our keyboards. Moreover, I decided not to stick with only one remote, but to support many different ones simultaneously: in my current setup "remotes" are my wireless keyboard, ATI Remote Wonder and my SonyEricsson W800i through its bluetooth HID profile - each one working with its own set of keys but all of them providing same functionality.
Two sets of keys
But before I start explaining configuration files that make all this possible, I first have to describe logical use of remote controls in my setup. Because I decided for modular approach in which one remote control with same set of keys must control all of the HTPC components (TV playback, video player etc.), I've divided remote keys to two groups:
- global keys that trigger always the same keypresses that are either generic ones (Enter, Escape and arrow keys in my case) or they simulate virtual keypresses that are caught by window manager itself and trigger some global actions, independent of which component is currently in foreground (actions for switching between components is obviously one of such global action)
- remappable keys that produce different keypresses depending on which component is currently in foreground - we remap those keys for every remote when switching between components to match keyboard shortcuts for application that works as component
Which keys on your remote(s) will be used as global and which ones as remappable keys is your decision which will depend on how many keys your remote has available. Enter, Escape and arrow keys should be one of those because they provide basic keyboard navigation, but some way of switching between different components should be also available (at least one key that popups list of available components through which you may navigate with arrow keys and confirm switch with Enter).
Determine keycodes
Before we start mapping keys on our remotes to specific global actions and/or remappable component-dependent keyboard shortcuts, we first must determine keycodes that every hardware key on our remote produces. Utility for this action is xev - start the program from the terminal, place mouse pointer above it and start pressing keys - in terminal window you will see few lines printed for every key press (actually, few lines will be printed for every key down and according key up events). Look for the information about keycode (usually on the third line, second number) - to help you, standard keycode for key Enter is 36. Also, in last line of xev output you'll see which "symbol" is associated with that key or to put it some simple, which key will your operating system see when you press that key. If that key is not associated with any symbol, "XLookupString gives 0 bytes:" will be printed in that last line.
Choose symbols
Now, determine which global "symbols" you want to use as global shortcuts. For Enter, Escape and arrow keys it is simple because you don't have choice: since that keys will be processed in applications, you must somehow generate that exact symbols. For keyboard no additional setup is required because every AT-compatible keyboard provides these keys, but for remotes you may have to play around a bit. If they do not provide that keys natively, you have to determine keys on remote that you want to use as Enter, Escape and arrow keys respectively, find their keycodes with xev and then map them to proper X window symbols. Map them at startup (read ahead for description how to do that) and you don't have to do any further configuration - just let that keys to do what they are supposed to do.
Symbols that I use for component switching are another story, because we have to execute proper scripts when these keys are pressed. Obviously, window manager of your choice must support customizable keyboard events that call external scripts, but most of them these days do. Because I wanted these keys not to interfere with usual work on standard keyboard I've choose Ctrl-F1 through Ctrl-F5 to do the job. Remote controls are a different story, because they do not have modifier Control key so we have to use only a single key. Again, not to interfere with usual work on standard keyboard I've choose function keys that do not exist on such keyboards: F21 through F25.
Associate symbols with scripts
Keyboard shortcut association in Openbox is done in file ~/.config/openbox/rc.xml so open that file in user tv's home folder and look for <keyboard> section. Openbox manual will give you the instructions on what kind of associations are available and in this tutorial's download section you can find my rc.xml file and just use that settings. One little trick that I used is that I didn't map keyboard shortcuts to direct scripts in tv's bin folder but instead I've associated them to symlinks in tv's input folder that point to actual scripts in bin. This way I can experiment with different key associations without restarting Openbox. For example, key shortcut Control+F1 calls script ~/input/keyboard/ctrl-f01 which is symlinked to script in folder bin that switch viewing mode to TV playback. Structure of input folder in my current setup looks like this (notice that every remote has its own folder for better readability):
input
|-- ati-remote
| |-- book -> ../../bin/switch-mode-gallery
| |-- channel-down -> ../../bin/decrease-gamma
| |-- channel-up -> ../../bin/increase-gamma
| |-- dvd -> ../../bin/switch-mode-cinema
| |-- hand -> ../../bin/switch-mode-ask
| |-- power -> ../../bin/toggle-monitor-on-off
| |-- tv -> ../../bin/switch-mode-tv
| |-- volume-down -> ../../bin/joker-jukebox-quiet-playlist
| |-- volume-up -> ../../bin/joker-jukebox-loud-playlist
| `-- web -> ../../bin/switch-mode-jukebox
|-- keyboard
| |-- ctrl-f01 -> ../../bin/switch-mode-tv
| |-- ctrl-f02 -> ../../bin/switch-mode-cinema
| |-- ctrl-f03 -> ../../bin/switch-mode-gallery
| |-- ctrl-f04 -> ../../bin/switch-mode-jukebox
| |-- ctrl-f05 -> ../../bin/switch-mode-phone
| |-- ctrl-f06 -> ../../bin/nop
| |-- ctrl-f07 -> ../../bin/nop
| |-- ctrl-f08 -> ../../bin/nop
| |-- ctrl-f09 -> ../../bin/switch-mode-status
| `-- ctrl-f10 -> ../../bin/toggle-monitor-on-off
`-- w800
|-- camera -> ../../bin/switch-mode-ask
|-- volume-down -> ../../bin/joker-jukebox-quiet-playlist
`-- volume-up -> ../../bin/joker-jukebox-loud-playlist
Association of keycodes with proper symbols is done with xmodmap utility. Just place your mappings in a text file containing one mapping per line in syntax:
keycode <keycode> = <symbol>
For example, line that would make key with hardware keycode 219 to produce a symbol F21 looks like this:
keycode 219 = F21
Now call xmodmap with this file as first parameter and you are done. Mappings for my global keys are placed in file ~/etc/xkb.conf in tv's home and you can find it in download section. If special keys F21-F25 that I've used here do not suite you for some reason, you may choose any other ones that X window system supports - you can find them in file /usr/include/X11/keysymdef.h (just remove the prefix XK_).
As you can see, configuration of keyboard shortcuts is made as configurable as it can be, but one important limitation remains: because your remotes do not have modifier keys (and you don't want them to have one), applications that you use on your HTPC must have configurable keyboard shortcuts that you can assign to only one key, because almost always default ones include some modifier key that you can not support. Skype for example will give you big headaches here, but as I've said in software guidance of this tutorial, Skype still do not have any real alternative, so we can just hope that this feature will emerge in Skype for Linux soon.
Bluetooth HID
If you have bluetooth adapter on your HTPC box and bluetooth capable cell phone with "Remote control" bluetooth profile, you can enable bluetooth HID daemon, pair your cell phone with your HTPC and start using it as any other remote control (although with significantly smaller number of keys, but still very functional). On Debian, install Bluez bluetooth package, enable both BLUETOOTH and HIDD in file /etc/default/bluetooth, tweak your /etc/bluetooth/hcid.conf file as necessary (both these files from my setup are available in download section) and hopefully everything will just work. Unfortunately, bluetooth on Linux is still very fast evolving area, not very standardized among different distributions and even among different versions of same distribution, so I can not give you detailed instructions here. Basically, its a try/fix/try again game for those with good nerves :)





