Howto: Mythtv SNES Joystick Control

Update: Why oh why can’t Blogger preview my post in the *actual* stylesheet of my blog? I seem to remember WordPress doing this… if so, I must switch. ASAP.

I’m back down in Madison, and in the midst of unpacking all my junk after moving down here from home. One thing that Nate & I set up right away is my HTPC, an Ubuntu-based MythTV box. Unfortunately, I noticed over winter break that my homemade serial-port IR receiver has given up the ghost, so I can no longer control MythTV from my universal remote. I’ve ordered the parts for a USB IR receiver, but as I mentioned earlier, my soldering iron has also given up the ghost…

So, what to do in the interim? Well, there is a keyboard attached to the Myth box, but it doesn’t reach the couch. Enter the SNES controller and MythTV joystick control. Here’s how I got it to work:

Goal

  • Control MythTV from an SNES controller (or any other gamepad)

Required Software / Hardware

  • MythTV (I believe any version since 0.17 will work)
  • SNES controller connected via parallel port adapter and the gamecon driver (see Documentation/input/joystick-parport.txt in the Linux source tree)
  • jstest (Optional, available on Ubuntu in the “joystick” package)

Determining joystick layout

The first step in writing a MythTV joystick configuration is to determine the exact layout of your joystick, as Linux sees it. Specifically, we need to know what axes (and axis values) and buttons correspond to the controls on the joystick.

If you’re using an SNES controller with the gamecon driver, I’ve done the legwork, and you can skip to the next section below, using my example configuration. (Obviously you should test it and make sure it works.)

To determine the layout of your own joystick, you can use the optional jstest program mentioned above. You can install it on Ubuntu from the joystick package (you will need the universe repository enabled):

$ sudo apt-get install joystick

Run jstest and record the axis numbers and values, as well as button numbers, that correspond to all the controls you wish to use on your joystick. jstest requires a parameter of the joystick device to open. For example, I run jstest like this for my first SNES controller:

$ jstest /dev/input/js0

jstest produces output for my SNES controller like this:

Driver version is 2.1.0.

Joystick (SNES pad) has 2 axes (X, Y)

and 8 buttons (BtnX, BtnY, BtnTL, BtnTR, BtnTR2, BtnSelect, BtnThumbL, BtnThumbR).

Testing ... (interrupt to exit)

Axes: 0: 0 1: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off

This tells me that the joystick as seen by Linux has two axes and 7 buttons. Pressing them in sequence changes the output, such as this output when I hold the directional pad to the left and press the “A” button:

Testing ... (interrupt to exit)

Axes: 0:-32767 1: 0 Buttons: 0:on 1:off 2:off 3:off 4:off 5:off 6:off 7:off

This tells you that the D-pad “left” direction corresponds to value -32767 on Axis 0, and that the “A” button corresponds to button 0.

Compiling a full list for your joystick would give you a mapping like this one for the SNES controllers & gamecon driver:

SNES Button Linux joystick mapping
D-Pad Up Axis 1: -32767
D-Pad Right Axis 0: 32767
D-Pad Down Axis 1: 32767
D-Pad Left Axis 0: -32767
A Button 0
B Button 1
X Button 2
Y Button 3
L Button 4
R Button 5
Select Button 6
Start Button 7

Writing the MythTV JoystickmenurcConfiguration File

Now that you have the logical layout of your joystick in hand, it’s time to configure MythTV itself. This is done by means of the joystickmenurc configuration file, located at ~/.mythtv/joystickmenurc for the user that mythfrontend is launched under. This file will instruct MythTV as to which joystick device it should open, and then provides a mapping from the joystick layout to the keyboard strokes for MythTV.

joystickmenurc Format

As described in the formatting section of the Joystick Control page on the MythTV Wiki, the format for the joystickmenurc is as follows:

devicename <devname>
Specify the name of the joystick device to use, (e.g. /dev/input/js0)
button <num> <keystring>
Send keystring when button num is released
chord <cnum> <bnum> <keystring>
If button cnum is down, and button bnum is released, send keystring
axis <num> <from> <to> <keystring>
If axis num goes into the range of fromto send keystring

Example joystickmenurc for SNES controller

I think the formatting is best explained by an example. Below is the actual ~/.mythtv/joystickmenurc file I use on my system, with commenting explaining exactly what is intended and how it works. If you use an SNES controller attached via the gamecon driver to /dev/input/js0, this configuration should work for you as-is. Simply drop it in your ~/.mythtv directory and relaunch mythfrontend. For everyone else, feel free to use this as a template, or see the Joystick Control page on the MythTV Wiki for an example of an Xbox configuration file.

# ~/.mythtv/joystickmenurc
# Joystick menu config file
#
# Created 1/21/2007 by Colin McCambridge
# based on instructions at http://www.mythtv.org/wiki/index.php/Joystick_Control
#
# This joystick menu configuration controls MythTV with an SNES
# gamepad connected via parallel port and the gamecon driver.
#
# Controls:
#  SNES Pad            Keypresses       Joystick Device
#  --------            ----------       ---------------
#  UP/DOWN axis        Up, Down         Axis 1: U -32767 D 32767
#  LEFT/RIGHT axis     Left, Right      Axis 0: L -32767 R 32767
#  B                   Enter            Button 1
#  Y                   Esc              Button 3
#  A                   P  (Play/Pause)  Button 0
#  X                   S  (Guide)       Button 2
#  Start               M  (Menu)        Button 7
#  Select              I  (Info)        Button 6
#  Left Top            Page Up (REW)    Button 4
#  Right Top           Page Down (FF)   Button 5
#

###########################################################
#
#    SNES Gamepad Device
#
###########################################################

devicename /dev/input/js0

###########################################################
#
#    D-Pad
#
###########################################################

#Up
        axis    1       -32767  -1      Up
#Down
        axis    1       1       32767   Down
#Left
        axis    0       -32767  -1      Left
#Right
        axis    0       1       32767   Right

###########################################################
#
#    Buttons
#
###########################################################

#A ==> Play/Pause
        button  0       P
#B ==> Enter
        button  1       Enter
#X ==> Guide (S)
        button  2       S
#Y ==> Exit (Esc)
        button  3       Escape

#Start ==> Menu (M)
        button  7       M
#Select ==> Info (I)
        button  6       I

#Left Top ==> Rewind (PgUp)
        button  4       PgUp
#Right Top ==> F.Fwd (PgDown)
        button  5       PgDown

Final Notes

For making your own joystickmenurc file, you may find the MythTV Default Keybindings, or the more abbreviated Remote Control Buttons list handy references as to the control operations you can define.

For an exact list of valid key names to use (e.g. “Escape”) refer to the Qt documentation for the Qt.Key enum. This document lists key names in the form: “Qt::Key_Escape“, use only the name following the underscore.

Note: there is an undocumented discrepancy regarding the keys Page Up and Page Down. While the Qt.Key enum lists them as PageUp and PageDown, they can actually only be specified as either "PgUp" and "PgDown", or "Page Up" and "Page Down" respectively. See messages 3 and 4 of this email thread for reference, or view the relevant Qt source file (especially the keyname[] array at line 89, and method decodeString at line 388): qkeysequence.cpp