[mythtv] [PATCH] Add joysticks as an input device to MythtTV
Jeremy White
jwhite at codeweavers.com
Tue Sep 28 08:23:24 EDT 2004
If regular spammers don't give up, and simply escalate
their attacks, I figure that approach should work for
me as well <grin>.
Attached patch resolves all of my issues
to my satisfaction, save one; before applying,
please review the event number assignment in
jsmenuevent.h (there is an obvious FIXME at the top).
Changelog:
Provide a facility to allow joystick devices to
be used as input to MythTV.
-------------- next part --------------
Index: settings.pro
===================================================================
RCS file: /var/lib/mythcvs/mythtv/settings.pro,v
retrieving revision 1.68
diff -u -r1.68 settings.pro
--- settings.pro 13 Sep 2004 06:09:22 -0000 1.68
+++ settings.pro 28 Sep 2004 12:18:25 -0000
@@ -73,6 +73,9 @@
# 'linux/dvb/frontend.h', not the directory with frontend.h
#INCLUDEPATH += /usr/src/linuxtv-dvb-1.0.1/include
+# Joystick menu support
+CONFIG += using_joystick_menu
+
# Native lirc support
#CONFIG += using_lirc
#LIRC_LIBS = -llirc_client
? libs/libmyth/jsmenu.cpp
? libs/libmyth/jsmenu.h
? libs/libmyth/jsmenuevent.cpp
? libs/libmyth/jsmenuevent.h
Index: libs/libmyth/libmyth.pro
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/libmyth.pro,v
retrieving revision 1.52
diff -u -r1.52 libmyth.pro
--- libs/libmyth/libmyth.pro 7 Sep 2004 21:20:19 -0000 1.52
+++ libs/libmyth/libmyth.pro 28 Sep 2004 12:18:26 -0000
@@ -75,6 +75,12 @@
LIBS += $$ALSA_LIBS
}
+using_joystick_menu {
+ DEFINES += USE_JOYSTICK_MENU
+ HEADERS += jsmenu.h jsmenuevent.h
+ SOURCES += jsmenu.cpp jsmenuevent.cpp
+}
+
using_lirc {
DEFINES += USE_LIRC
HEADERS += lirc.h lircevent.h
Index: libs/libmyth/mythdialogs.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/mythdialogs.cpp,v
retrieving revision 1.86
diff -u -r1.86 mythdialogs.cpp
--- libs/libmyth/mythdialogs.cpp 10 Sep 2004 05:56:56 -0000 1.86
+++ libs/libmyth/mythdialogs.cpp 28 Sep 2004 12:18:29 -0000
@@ -28,6 +28,11 @@
#include "lircevent.h"
#endif
+#ifdef USE_JOYSTICK_MENU
+#include "jsmenu.h"
+#include "jsmenuevent.h"
+#endif
+
#include "uitypes.h"
#include "uilistbtntype.h"
#include "xmlparse.h"
@@ -50,6 +55,19 @@
}
#endif
+#ifdef USE_JOYSTICK_MENU
+static void *SpawnJoystickMenu(void *param)
+{
+ MythMainWindow *main_window = (MythMainWindow *)param;
+ QString config_file = QDir::homeDirPath() + "/.mythtv/joystickmenurc";
+ JoystickMenuClient *js = new JoystickMenuClient(main_window);
+ if (!js->Init(config_file))
+ js->Process();
+
+ return NULL;
+}
+#endif
+
class KeyContext
{
public:
@@ -102,7 +120,13 @@
vector<QWidget *> widgetList;
+#ifdef USE_JOYSTICK_MENU
+ bool ignore_joystick_keys;
+#endif
+
+#ifdef USE_LIRC
bool ignore_lirc_keys;
+#endif
bool exitingtomain;
@@ -151,7 +175,6 @@
d = new MythMainWindowPrivate;
Init();
- d->ignore_lirc_keys = false;
d->exitingtomain = false;
d->exitmenucallback = false;
d->exitmenumediadevicecallback = false;
@@ -159,6 +182,7 @@
d->escapekey = Key_Escape;
#ifdef USE_LIRC
+ d->ignore_lirc_keys = false;
pthread_t lirc_tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
@@ -167,6 +191,16 @@
pthread_create(&lirc_tid, &attr, SpawnLirc, this);
#endif
+#ifdef USE_JOYSTICK_MENU
+ d->ignore_joystick_keys = false;
+ pthread_t js_tid;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ pthread_create(&js_tid, &attr, SpawnJoystickMenu, this);
+#endif
+
d->keyContexts.setAutoDelete(true);
RegisterKey("Global", "UP", "Up Arrow", "Up");
@@ -686,6 +720,48 @@
d->ignore_lirc_keys = lme->eventsMuted();
}
#endif
+#ifdef USE_JOYSTICK_MENU
+ else if (ce->type() == kJoystickKeycodeEventType && !d->ignore_joystick_keys)
+ {
+ JoystickKeycodeEvent *jke = (JoystickKeycodeEvent *)ce;
+ int keycode = jke->getKeycode();
+
+ if (keycode)
+ {
+ gContext->ResetScreensaver();
+
+ int mod = keycode & MODIFIER_MASK;
+ int k = keycode & ~MODIFIER_MASK; /* trim off the mod */
+ int ascii = 0;
+ QString text;
+
+ if (k & UNICODE_ACCEL)
+ {
+ QChar c(k & ~UNICODE_ACCEL);
+ ascii = c.latin1();
+ text = QString(c);
+ }
+
+ QKeyEvent key(jke->isKeyDown() ? QEvent::KeyPress :
+ QEvent::KeyRelease, k, ascii, mod, text);
+
+ QObject *key_target = getTarget(key);
+
+ QApplication::sendEvent(key_target, &key);
+ }
+ else
+ {
+ cerr << "JoystickMenuClient warning: attempt to convert '"
+ << jke->getJoystickMenuText() << "' to a key sequence failed. Fix"
+ " your key mappings.\n";
+ }
+ }
+ else if (ce->type() == kJoystickMuteEventType)
+ {
+ JoystickMenuMuteEvent *jme = (JoystickMenuMuteEvent *)ce;
+ d->ignore_joystick_keys = jme->eventsMuted();
+ }
+#endif
else if (ce->type() == ScreenSaverEvent::kScreenSaverEventType)
{
ScreenSaverEvent *sse = (ScreenSaverEvent *)ce;
Index: libs/libmyth/util.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/util.cpp,v
retrieving revision 1.36
diff -u -r1.36 util.cpp
--- libs/libmyth/util.cpp 7 Aug 2004 13:08:33 -0000 1.36
+++ libs/libmyth/util.cpp 28 Sep 2004 12:18:30 -0000
@@ -24,6 +24,10 @@
#include "lircevent.h"
#endif
+#ifdef USE_JOYSTICK_MENU
+#include "jsmenuevent.h"
+#endif
+
#define SOCKET_BUF_SIZE 128000
bool connectSocket(QSocketDevice *socket, const QString &host, int port)
@@ -615,7 +619,14 @@
{
#ifdef USE_LIRC
LircEventLock lirc_lock(!(flags & MYTH_SYSTEM_DONT_BLOCK_LIRC));
-#else
+#endif
+
+#ifdef USE_JOYSTICK_MENU
+ JoystickMenuEventLock joystick_lock(!(flags & MYTH_SYSTEM_DONT_BLOCK_JOYSTICK_MENU));
+#endif
+
+ /* Kill warning, I presume */
+#if ! defined(USE_LIRC) && ! defined(USE_JOYSTICK_MENU)
(void)flags;
#endif
Index: libs/libmyth/util.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/util.h,v
retrieving revision 1.15
diff -u -r1.15 util.h
--- libs/libmyth/util.h 8 Jul 2004 23:26:21 -0000 1.15
+++ libs/libmyth/util.h 28 Sep 2004 12:18:30 -0000
@@ -39,6 +39,7 @@
QRgb blendColors(QRgb source, QRgb add, int alpha);
#define MYTH_SYSTEM_DONT_BLOCK_LIRC (1)
+#define MYTH_SYSTEM_DONT_BLOCK_JOYSTICK_MENU (2)
int myth_system(const QString &command, int flags = 0);
QString cutDownString(QString text, QFont *testFont, int maxwidth);
--- /dev/null 2004-06-09 21:35:19.000000000 -0500
+++ libs/libmyth/jsmenu.cpp 2004-09-28 07:18:19.000000000 -0500
@@ -0,0 +1,362 @@
+/*----------------------------------------------------------------------------
+** jsmenu.cpp
+**
+** Description:
+** Set of functions to generate key events based on
+** input from a Joystick.
+**
+** Original Copyright 2004 by Jeremy White <jwhite at whitesen.org>
+**
+** License:
+** This program is free software; you can redistribute it
+** and/or modify it under the terms of the GNU General
+** Public License as published bythe Free Software Foundation;
+** either version 2, or (at your option)
+** any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+**--------------------------------------------------------------------------*/
+
+#include <qapplication.h>
+#include <qevent.h>
+#include <qkeysequence.h>
+#include <cstdio>
+#include <cerrno>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "mythcontext.h"
+
+#include <iostream>
+using namespace std;
+
+#include <linux/joystick.h>
+
+#include "jsmenu.h"
+#include "jsmenuevent.h"
+
+#if (QT_VERSION < 0x030100)
+#error Native LIRC support requires Qt 3.1 or greater.
+#endif
+
+
+
+/*----------------------------------------------------------------------------
+** JoystickMenuClient Constructor
+**--------------------------------------------------------------------------*/
+JoystickMenuClient::JoystickMenuClient(QObject *main_window)
+{
+ mainWindow = main_window;
+
+ fd = -1;
+ axes = NULL;
+ buttons = NULL;
+
+}
+
+/*----------------------------------------------------------------------------
+** JoystickMenuClient Destructor
+**--------------------------------------------------------------------------*/
+JoystickMenuClient::~JoystickMenuClient()
+{
+ if (fd != -1)
+ {
+ close(fd);
+ fd = -1;
+ }
+
+ if (axes)
+ {
+ free(axes);
+ buttons = NULL;
+ }
+
+ if (buttons)
+ {
+ free(buttons);
+ buttons = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------------
+** Init
+**--------------------------------------------------------------------------*/
+int JoystickMenuClient::Init(QString &config_file)
+{
+ int rc;
+
+ /*------------------------------------------------------------------------
+ ** Read the config file
+ **----------------------------------------------------------------------*/
+ rc = ReadConfig(config_file);
+ if (rc)
+ {
+ cerr << config_file << " not found; menu keys from joystick disabled.\n";
+ return(rc);
+ }
+
+ /*------------------------------------------------------------------------
+ ** Open the joystick device, retrieve basic info
+ **----------------------------------------------------------------------*/
+ fd = open((const char *) devicename, O_RDONLY);
+ if (fd == -1)
+ {
+ cerr << "Could not initialize " << devicename << "\n";
+ perror("open");
+ }
+
+ rc = ioctl(fd, JSIOCGAXES, &axes_count);
+ if (rc == -1)
+ {
+ perror("ioctl JSIOCGAXES");
+ return(rc);
+ }
+
+ ioctl(fd, JSIOCGBUTTONS, &button_count);
+ if (rc == -1)
+ {
+ perror("ioctl JSIOCGBUTTONS");
+ return(rc);
+ }
+
+ /*------------------------------------------------------------------------
+ ** Allocate the arrays in which we track button and axis status
+ **----------------------------------------------------------------------*/
+ buttons = new int[button_count];
+ memset(buttons, '\0', sizeof(*buttons * button_count));
+
+ axes = new int[axes_count];
+ memset(axes, '\0', sizeof(*axes * axes_count));
+
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+** ReadConfig
+** Read from a flat file config file, with a format of:
+** # Starts a comment
+** devicename devname - Name of physical joystick device
+** button num keystring - Represents a button
+** chord cnum bnum keystring - A chorded button sequence; hold down cnum
+** and press bnum to generate a key
+** axis num from to keystring - Represents an axis range to trigger a key
+** move that axis into the range and the
+** keystring is sent
+**--------------------------------------------------------------------------*/
+int JoystickMenuClient::ReadConfig(QString config_file)
+{
+ FILE *fp;
+
+ fp = fopen((const char *) config_file, "r");
+ if (!fp)
+ return(-1);
+
+ QTextIStream istream(fp);
+ for (int line = 1; ! istream.atEnd(); line++)
+ {
+ QString rawline = istream.readLine();
+ QString simple_line = rawline.simplifyWhiteSpace();
+ if (simple_line.isEmpty() || simple_line.startsWith("#"))
+ continue;
+
+ QStringList tokens = QStringList::split(" ", simple_line);
+ if (tokens.count() < 1)
+ continue;
+
+ if (tokens[0].startsWith("devicename", FALSE) && tokens.count() == 2)
+ devicename = tokens[1];
+ else if (tokens[0].startsWith("button", FALSE) && tokens.count() == 3)
+ map.AddButton(tokens[1].toInt(), tokens[2]);
+ else if (tokens[0].startsWith("axis", FALSE) && tokens.count() == 5)
+ map.AddAxis(tokens[1].toInt(), tokens[2].toInt(), tokens[3].toInt(), tokens[4]);
+ else if (tokens[0].startsWith("chord", FALSE) && tokens.count() == 4)
+ map.AddButton(tokens[2].toInt(), tokens[3], tokens[1].toInt());
+ else
+ cerr << config_file << "(" << line << "): unrecognized or malformed line: '" << rawline << "'\n";
+
+ }
+
+ fclose(fp);
+ return(0);
+}
+
+
+/*----------------------------------------------------------------------------
+** Process
+** This function is intended to run as the mainline of a thread which
+** looks for Joystick input and translates it into key stroke events
+** for MythTv.
+**--------------------------------------------------------------------------*/
+void JoystickMenuClient::Process(void)
+{
+ int rc;
+
+ fd_set readfds;
+ struct js_event js;
+
+ while (1)
+ {
+
+ /*--------------------------------------------------------------------
+ ** Wait for activity from the joy stick (we wait a configurable
+ ** poll time)
+ **------------------------------------------------------------------*/
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ rc = select(fd + 1, &readfds, NULL, NULL, NULL);
+ if (rc == -1)
+ {
+ /*----------------------------------------------------------------
+ ** TODO: In theory, we could recover from file errors
+ ** (what happens when we unplug a joystick?)
+ **--------------------------------------------------------------*/
+ perror("select");
+ return;
+ }
+
+ if (rc == 1)
+ {
+ /*----------------------------------------------------------------
+ ** Read a joystick event
+ **--------------------------------------------------------------*/
+ rc = read(fd, &js, sizeof(js));
+ if (rc != sizeof(js))
+ {
+ perror("error reading js");
+ return;
+ }
+
+ /*----------------------------------------------------------------
+ ** Events sent with the JS_EVENT_INIT flag are always sent
+ ** right after you open the joy stick; they are useful
+ ** for learning the initial state of buttons and axes
+ **--------------------------------------------------------------*/
+ if (js.type & JS_EVENT_INIT)
+ {
+ if (js.type & JS_EVENT_BUTTON && js.number < button_count)
+ buttons[js.number] = js.value;
+
+ if (js.type & JS_EVENT_AXIS && js.number < axes_count)
+ axes[js.number] = js.value;
+ }
+ else
+ {
+ /*------------------------------------------------------------
+ ** Record new button states and look for triggers
+ ** that would make us send a key.
+ ** Things are a little tricky here; for buttons, we
+ ** only act on button up events, not button down
+ ** (this lets us implement the chord function).
+ ** For axes, we only register a change if the
+ ** Joystick moves into the specified range
+ ** (that way, we only get one event per joystick
+ ** motion).
+ **----------------------------------------------------------*/
+ if (js.type & JS_EVENT_BUTTON && js.number < button_count)
+ {
+ if (js.value == 0 && buttons[js.number] == 1)
+ ButtonUp(js.number);
+
+ buttons[js.number] = js.value;
+ }
+
+ if (js.type & JS_EVENT_AXIS && js.number < button_count)
+ {
+ AxisChange(js.number, js.value);
+ axes[js.number] = js.value;
+ }
+
+ }
+
+ }
+
+ }
+
+}
+
+/*----------------------------------------------------------------------------
+** EmitKey
+** Send an event to the main UI loop with the appropriate keycode
+** (looking up the string using QT)
+**--------------------------------------------------------------------------*/
+void JoystickMenuClient::EmitKey(QString code)
+{
+ QKeySequence a(code);
+
+ int keycode = 0;
+
+ // Send a dummy keycode if we couldn't convert the key sequence.
+ // This is done so the main code can output a warning for bad
+ // mappings.
+ if (!a.count())
+ QApplication::postEvent(mainWindow, new JoystickKeycodeEvent(code,
+ keycode, true));
+
+ for (unsigned int i = 0; i < a.count(); i++)
+ {
+ keycode = a[i];
+
+ QApplication::postEvent(mainWindow, new JoystickKeycodeEvent(code,
+ keycode, true));
+ QApplication::postEvent(mainWindow, new JoystickKeycodeEvent(code,
+ keycode, false));
+
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+** ButtonUp
+** Handle a button up event; this is mildly complicated by
+** the support for 'chords'; holding down a button and pushing down
+** another can create one type of event.
+**--------------------------------------------------------------------------*/
+void JoystickMenuClient::ButtonUp(int button)
+{
+ vector<button_map_type>::iterator bmap;
+
+ /*------------------------------------------------------------------------
+ ** Process chords first
+ **----------------------------------------------------------------------*/
+ for (bmap = map.button_map.begin(); bmap < map.button_map.end(); bmap++)
+ if (button == bmap->button && bmap->chord != -1 && buttons[bmap->chord] == 1)
+ {
+ EmitKey(bmap->keystring);
+ buttons[bmap->chord] = 0;
+ return;
+ }
+
+ /*------------------------------------------------------------------------
+ ** Process everything else
+ **----------------------------------------------------------------------*/
+ for (bmap = map.button_map.begin(); bmap < map.button_map.end(); bmap++)
+ if (button == bmap->button && bmap->chord == -1)
+ EmitKey(bmap->keystring);
+}
+
+/*----------------------------------------------------------------------------
+** AxisChange
+** Handle a registerd change in a joystick axis
+**--------------------------------------------------------------------------*/
+void JoystickMenuClient::AxisChange(int axis, int value)
+{
+ vector<axis_map_type>::iterator amap;
+ for (amap = map.axis_map.begin(); amap < map.axis_map.end(); amap++)
+ if (axis == amap->axis)
+ {
+ /* If we're currently outside the range, and the move is
+ ** into the range, then we trigger */
+ if (axes[axis] < amap->from || axes[axis] > amap->to)
+ if (value >= amap->from && value <= amap->to)
+ EmitKey(amap->keystring);
+ }
+}
+
--- /dev/null 2004-06-09 21:35:19.000000000 -0500
+++ libs/libmyth/jsmenu.h 2004-09-27 23:15:33.000000000 -0500
@@ -0,0 +1,103 @@
+/*----------------------------------------------------------------------------
+** jsmenu.h
+** GPL license; Original copyright 2004 Jeremy White <jwhite at whitesen.org>
+**--------------------------------------------------------------------------*/
+
+#ifndef JSMENU_H_
+#define JSMENU_H_
+
+#include <qobject.h>
+#include <qsocket.h>
+#include <qstring.h>
+
+#include "mythdialogs.h"
+
+/*----------------------------------------------------------------------------
+** JoystickMap related information
+** We build a map of how joystick buttons and axes (axes are for sticks
+** and thumb controllers) are mapped into keystrokes.
+** For buttons, it's mostly very simple: joystick button number
+** corresponds to a key sequence that is sent to MythTV.
+** We complicate it a little by allowing for 'chords', which
+** means that if you hold down the 'chord' button while pressing
+** the other button, we use the alternate mapping
+** For axes, it's not very complicated. For each axis (ie up/down or
+** left/right), we define a range; the first time the joystick moves
+** into that range, we send the assigned keystring.
+**--------------------------------------------------------------------------*/
+struct button_map_type
+{
+ int button;
+ QString keystring;
+ int chord;
+};
+
+typedef struct
+{
+ int axis;
+ int from;
+ int to;
+ QString keystring;
+} axis_map_type;
+
+class JoystickMap
+{
+ public:
+ void AddButton(int in_button, QString in_keystr, int in_chord = -1)
+ {
+ button_map_type new_button = { in_button, in_keystr, in_chord };
+ button_map.push_back(new_button);
+ }
+
+ void AddAxis(int in_axis, int in_from, int in_to, QString in_keystr)
+ {
+ axis_map_type new_axis = { in_axis, in_from, in_to, in_keystr};
+ axis_map.push_back(new_axis);
+ }
+
+
+ vector<button_map_type> button_map;
+ vector<axis_map_type> axis_map;
+};
+
+/*----------------------------------------------------------------------------
+** JoystickMenuClient
+** Main object for injecting key strokes based on joystick movements
+**--------------------------------------------------------------------------*/
+class JoystickMenuClient : public QObject
+{
+ Q_OBJECT
+ public:
+ JoystickMenuClient(QObject *main_window);
+ ~JoystickMenuClient();
+ int Init(QString &config_file);
+
+ void Process(void);
+
+ void ButtonUp(int button);
+ void AxisChange(int axis, int value);
+ void JoystickMenuClient::EmitKey(QString code);
+ int ReadConfig(QString config_file);
+
+ private:
+ QObject *mainWindow;
+
+ QString devicename;
+
+ int fd;
+
+ JoystickMap map;
+
+ /*------------------------------------------------------------------------
+ ** These two arrays and their related counts track the status of the
+ ** joystick buttons and axes, as we do depend slightly on state
+ **----------------------------------------------------------------------*/
+ unsigned char button_count;
+ unsigned char axes_count;
+
+ int *buttons;
+ int *axes;
+
+};
+
+#endif
--- /dev/null 2004-06-09 21:35:19.000000000 -0500
+++ libs/libmyth/jsmenuevent.cpp 2004-09-26 20:08:58.000000000 -0500
@@ -0,0 +1,45 @@
+/*----------------------------------------------------------------------------
+** jsmenuevent.cpp
+** GPL license; Original copyright 2004 Jeremy White <jwhite at whitesen.org>
+** although this is largely a derivative of lircevent.cpp
+**--------------------------------------------------------------------------*/
+#include <qapplication.h>
+#include <qstring.h>
+#include "mythcontext.h"
+
+#include "jsmenuevent.h"
+
+JoystickMenuEventLock::JoystickMenuEventLock(bool lock_events)
+ : events_locked(false)
+{
+ if (lock_events)
+ lock();
+}
+
+JoystickMenuEventLock::~JoystickMenuEventLock()
+{
+ if (events_locked)
+ unlock();
+}
+
+void JoystickMenuEventLock::lock()
+{
+ MythMainWindow *mw = gContext->GetMainWindow();
+ if (mw)
+ {
+ events_locked = true;
+ QApplication::postEvent((QObject *)mw,
+ new JoystickMenuMuteEvent(events_locked));
+ }
+}
+
+void JoystickMenuEventLock::unlock()
+{
+ MythMainWindow *mw = gContext->GetMainWindow();
+ if (mw)
+ {
+ events_locked = false;
+ QApplication::postEvent((QObject *)mw,
+ new JoystickMenuMuteEvent(events_locked));
+ }
+}
--- /dev/null 2004-06-09 21:35:19.000000000 -0500
+++ libs/libmyth/jsmenuevent.h 2004-09-26 20:08:48.000000000 -0500
@@ -0,0 +1,69 @@
+/*----------------------------------------------------------------------------
+** jsmenuevent.h
+** GPL license; Original copyright 2004 Jeremy White <jwhite at whitesen.org>
+** although this is largely a derivative of lircevent.h
+**--------------------------------------------------------------------------*/
+#ifndef JSMENUEVENT_H_
+#define JSMENUEVENT_H_
+
+/* FIXME: Learn how to assign a real event type */
+const int kJoystickKeycodeEventType = 24425; /*LA LA WHERE THE HECK IS THIS FROM */
+const int kJoystickMuteEventType = 24426;
+
+class JoystickKeycodeEvent : public QCustomEvent
+{
+ public:
+ JoystickKeycodeEvent(const QString &jsmenuevent_text, int key_code, bool key_down) :
+ QCustomEvent(kJoystickKeycodeEventType), jsmenueventtext(jsmenuevent_text),
+ keycode(key_code), keydown(key_down) {}
+
+ QString getJoystickMenuText()
+ {
+ return jsmenueventtext;
+ }
+
+ int getKeycode()
+ {
+ return keycode;
+ }
+
+ bool isKeyDown()
+ {
+ return keydown;
+ }
+
+ private:
+ QString jsmenueventtext;
+ int keycode;
+ bool keydown;
+};
+
+class JoystickMenuMuteEvent : public QCustomEvent
+{
+ public:
+ JoystickMenuMuteEvent(bool mute_events) : QCustomEvent(kJoystickMuteEventType),
+ mute_jsmenu_events(mute_events) {}
+
+ bool eventsMuted()
+ {
+ return mute_jsmenu_events;
+ }
+
+ private:
+ bool mute_jsmenu_events;
+};
+
+class JoystickMenuEventLock
+{
+ public:
+ JoystickMenuEventLock(bool lock_events = true);
+ ~JoystickMenuEventLock();
+ void lock();
+ void unlock();
+
+ private:
+ bool events_locked;
+};
+
+#endif
+
--- /dev/null 2004-06-09 21:35:19.000000000 -0500
+++ configfiles/joystickmenurc.example 2004-09-27 23:46:56.000000000 -0500
@@ -0,0 +1,30 @@
+#
+# Joystick menu config file
+# Place in ~/.mythtv/
+#
+# Format:
+# devicename <devname> Specify name of joystick device to use
+# (e.g. /dev/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 from-to
+# send keystring
+
+devicename /dev/js0
+
+button 0 Enter
+button 1 Escape
+chord 2 5 Escape
+
+axis 0 -32767 -15000 Left
+axis 0 15000 32767 Right
+axis 1 -32767 -15000 Up
+axis 1 15000 32767 Down
+
+axis 5 -32767 -15000 Left
+axis 5 15000 32767 Right
+axis 6 -32767 -15000 Up
+axis 6 15000 32767 Down
+
+
More information about the mythtv-dev
mailing list