00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <qapplication.h>
00025 #include <qevent.h>
00026 #include <qkeysequence.h>
00027 #include <cstdio>
00028 #include <cerrno>
00029 #include <sys/wait.h>
00030 #include <sys/types.h>
00031 #include <unistd.h>
00032 #include <fcntl.h>
00033
00034 #include "mythcontext.h"
00035
00036 #include <iostream>
00037 using namespace std;
00038
00039 #include <linux/joystick.h>
00040
00041 #include "jsmenu.h"
00042 #include "jsmenuevent.h"
00043
00044 #if (QT_VERSION < 0x030100)
00045 #error Native LIRC support requires Qt 3.1 or greater.
00046 #endif
00047
00048 #define LOC QString("JoystickMenuClient: ")
00049 #define LOC_ERROR QString("JoystickMenuClient Error: ")
00050
00051
00052
00053
00054 JoystickMenuClient::JoystickMenuClient(QObject *main_window)
00055 {
00056 mainWindow = main_window;
00057
00058 fd = -1;
00059 axes = NULL;
00060 buttons = NULL;
00061
00062 }
00063
00064
00065
00066
00067 JoystickMenuClient::~JoystickMenuClient()
00068 {
00069 if (fd != -1)
00070 {
00071 close(fd);
00072 fd = -1;
00073 }
00074
00075 if (axes)
00076 {
00077 delete [] axes;
00078 axes = NULL;
00079 }
00080
00081 if (buttons)
00082 {
00083 delete [] buttons;
00084 buttons = NULL;
00085 }
00086 }
00087
00088
00089
00090
00091 int JoystickMenuClient::Init(QString &config_file)
00092 {
00093 int rc;
00094
00095
00096
00097
00098 rc = ReadConfig(config_file);
00099 if (rc)
00100 {
00101 VERBOSE(VB_GENERAL, LOC_ERROR + QString("Joystick disabled - Failed to read %1")
00102 .arg(config_file));
00103 return(rc);
00104 }
00105
00106
00107
00108
00109 fd = open((const char *) devicename, O_RDONLY);
00110 if (fd == -1)
00111 {
00112 VERBOSE(VB_IMPORTANT, LOC_ERROR + QString("Joystick disabled - Failed to open device %1")
00113 .arg(devicename));
00114 return -1;
00115 }
00116
00117 rc = ioctl(fd, JSIOCGAXES, &axes_count);
00118 if (rc == -1)
00119 {
00120 VERBOSE(VB_IMPORTANT, LOC_ERROR + "Joystick disabled - ioctl JSIOCGAXES failed");
00121 return(rc);
00122 }
00123
00124 ioctl(fd, JSIOCGBUTTONS, &button_count);
00125 if (rc == -1)
00126 {
00127 VERBOSE(VB_IMPORTANT, LOC_ERROR + "Joystick disabled - ioctl JSIOCGBUTTONS failed");
00128 return(rc);
00129 }
00130
00131
00132
00133
00134 buttons = new int[button_count];
00135 memset(buttons, '\0', sizeof(*buttons * button_count));
00136
00137 axes = new int[axes_count];
00138 memset(axes, '\0', sizeof(*axes * axes_count));
00139
00140 VERBOSE(VB_GENERAL, LOC + QString("Initialization of %1 succeeded using config file %2")
00141 .arg(devicename)
00142 .arg(config_file));
00143 return 0;
00144 }
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 int JoystickMenuClient::ReadConfig(QString config_file)
00159 {
00160 FILE *fp;
00161
00162 fp = fopen((const char *) config_file, "r");
00163 if (!fp)
00164 return(-1);
00165
00166 QTextIStream istream(fp);
00167 for (int line = 1; ! istream.atEnd(); line++)
00168 {
00169 QString rawline = istream.readLine();
00170 QString simple_line = rawline.simplifyWhiteSpace();
00171 if (simple_line.isEmpty() || simple_line.startsWith("#"))
00172 continue;
00173
00174 QStringList tokens = QStringList::split(" ", simple_line);
00175 if (tokens.count() < 1)
00176 continue;
00177
00178 QString firstTok = tokens[0].lower();
00179
00180 if (firstTok.startsWith("devicename") && tokens.count() == 2)
00181 devicename = tokens[1];
00182 else if (firstTok.startsWith("button") && tokens.count() == 3)
00183 map.AddButton(tokens[1].toInt(), tokens[2]);
00184 else if (firstTok.startsWith("axis") && tokens.count() == 5)
00185 map.AddAxis(tokens[1].toInt(), tokens[2].toInt(), tokens[3].toInt(), tokens[4]);
00186 else if (firstTok.startsWith("chord") && tokens.count() == 4)
00187 map.AddButton(tokens[2].toInt(), tokens[3], tokens[1].toInt());
00188 else
00189 VERBOSE(VB_IMPORTANT, LOC_ERROR + QString("ReadConfig(%1) unrecognized or "
00190 "malformed line \"%2\" ")
00191 .arg(line)
00192 .arg(rawline));
00193
00194 }
00195
00196 fclose(fp);
00197 return(0);
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207 void JoystickMenuClient::Process(void)
00208 {
00209 int rc;
00210
00211 fd_set readfds;
00212 struct js_event js;
00213
00214 while (1)
00215 {
00216
00217
00218
00219
00220
00221 FD_ZERO(&readfds);
00222 FD_SET(fd, &readfds);
00223
00224 rc = select(fd + 1, &readfds, NULL, NULL, NULL);
00225 if (rc == -1)
00226 {
00227
00228
00229
00230
00231 perror("select");
00232 return;
00233 }
00234
00235 if (rc == 1)
00236 {
00237
00238
00239
00240 rc = read(fd, &js, sizeof(js));
00241 if (rc != sizeof(js))
00242 {
00243 perror("error reading js");
00244 return;
00245 }
00246
00247
00248
00249
00250
00251
00252 if (js.type & JS_EVENT_INIT)
00253 {
00254 if (js.type & JS_EVENT_BUTTON && js.number < button_count)
00255 buttons[js.number] = js.value;
00256
00257 if (js.type & JS_EVENT_AXIS && js.number < axes_count)
00258 axes[js.number] = js.value;
00259 }
00260 else
00261 {
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 if (js.type & JS_EVENT_BUTTON && js.number < button_count)
00274 {
00275 if (js.value == 0 && buttons[js.number] == 1)
00276 ButtonUp(js.number);
00277
00278 buttons[js.number] = js.value;
00279 }
00280
00281 if (js.type & JS_EVENT_AXIS && js.number < button_count)
00282 {
00283 AxisChange(js.number, js.value);
00284 axes[js.number] = js.value;
00285 }
00286
00287 }
00288
00289 }
00290
00291 }
00292
00293 }
00294
00295
00296
00297
00298
00299
00300 void JoystickMenuClient::EmitKey(QString code)
00301 {
00302 QKeySequence a(code);
00303
00304 int keycode = 0;
00305
00306
00307
00308
00309 if (!a.count())
00310 QApplication::postEvent(mainWindow, new JoystickKeycodeEvent(code,
00311 keycode, true));
00312
00313 for (unsigned int i = 0; i < a.count(); i++)
00314 {
00315 keycode = a[i];
00316
00317 QApplication::postEvent(mainWindow, new JoystickKeycodeEvent(code,
00318 keycode, true));
00319 QApplication::postEvent(mainWindow, new JoystickKeycodeEvent(code,
00320 keycode, false));
00321
00322 }
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332 void JoystickMenuClient::ButtonUp(int button)
00333 {
00334 vector<button_map_type>::iterator bmap;
00335
00336
00337
00338
00339 for (bmap = map.button_map.begin(); bmap < map.button_map.end(); bmap++)
00340 if (button == bmap->button && bmap->chord != -1 && buttons[bmap->chord] == 1)
00341 {
00342 EmitKey(bmap->keystring);
00343 buttons[bmap->chord] = 0;
00344 return;
00345 }
00346
00347
00348
00349
00350 for (bmap = map.button_map.begin(); bmap < map.button_map.end(); bmap++)
00351 if (button == bmap->button && bmap->chord == -1)
00352 EmitKey(bmap->keystring);
00353 }
00354
00355
00356
00357
00358
00359 void JoystickMenuClient::AxisChange(int axis, int value)
00360 {
00361 vector<axis_map_type>::iterator amap;
00362 for (amap = map.axis_map.begin(); amap < map.axis_map.end(); amap++)
00363 if (axis == amap->axis)
00364 {
00365
00366
00367 if (axes[axis] < amap->from || axes[axis] > amap->to)
00368 if (value >= amap->from && value <= amap->to)
00369 EmitKey(amap->keystring);
00370 }
00371 }
00372