direcs  2012-09-30
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
joystick.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) Markus Knapp *
3  * www.direcs.de *
4  * *
5  * This file is part of direcs. *
6  * *
7  * direcs is free software: you can redistribute it and/or modify it *
8  * under the terms of the GNU General Public License as published *
9  * by the Free Software Foundation, version 3 of the License. *
10  * *
11  * direcs is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License *
17  * along with direcs. If not, see <http://www.gnu.org/licenses/>. *
18  * *
19  *************************************************************************/
20 
21 
22 #include "joystick.h"
23 
24 
26 {
27  stopped = false;
28 
29  #ifdef Q_OS_MAC // joystick support for Mac OS:
30  numJoysticks = 0;
31  #endif
32 }
33 
34 
36 {
37 }
38 
39 
41 {
42  stopped = true;
43 }
44 
45 
47 {
48  #ifdef Q_OS_MAC // joystick support for Mac OS:
49  int currentJoystick = 0;
50  int buttonOrAxis = 0;
51 
52 
53  //
54  // start "threading"...
55  //
56  while (!stopped)
57  {
58  // let the thread sleep some time for having more time for the other threads
59  msleep(THREADSLEEPTIME);
60 
61 
62  if (numJoysticks != 0)
63  {
64  for (currentJoystick=0; currentJoystick<numJoysticks; currentJoystick++)
65  {
66  //
67  // read joysticks state
68  //
69  joystick[currentJoystick].Read();
70 
71 
72  //
73  // Axes
74  //
75  for (buttonOrAxis=0; buttonOrAxis<JoyReaderMaxNumAxis; buttonOrAxis++)
76  {
77  if (joystick[currentJoystick].axis[buttonOrAxis].exist != 0)
78  {
79  // we convert, round and multiply with 32767 the original value here to have a nive int from range -32767 to +32767 for the GUI
80  emit joystickMoved(buttonOrAxis, (int) qRound(joystick[currentJoystick].axis[buttonOrAxis].GetCalibratedValue() * 32767) );
81  }
82  }
83 
84 
85  //
86  // Buttons
87  //
88  for (buttonOrAxis=0; buttonOrAxis<JoyReaderMaxNumButton; buttonOrAxis++)
89  {
90  if (joystick[currentJoystick].button[buttonOrAxis].exist != 0)
91  {
92  if (joystick[currentJoystick].button[buttonOrAxis].value == 1)
93  {
94  emit joystickButtonPressed(buttonOrAxis, true);
95  }
96  else
97  {
98  emit joystickButtonPressed(buttonOrAxis, false);
99  }
100  }
101  }
102 
103 
104  //
105  // POV (Hat Switch)
106  //
107  for (buttonOrAxis=0; buttonOrAxis<JoyReaderMaxNumHatSwitch; buttonOrAxis++)
108  {
109  if (joystick[currentJoystick].hatSwitch[buttonOrAxis].exist != 0)
110  {
111  // emits the value 0 to 8 to Gui::JoystickDialog
112  emit joystickPOVButtonPressed(joystick[currentJoystick].hatSwitch[buttonOrAxis].value);
113 
114 
115  // the following is a workaround for Mac only since we cannon identify the POV under Linux and therefor we would need a different Direcs::executeJoystickCommand
116  // so here we're emitting another signal for this Slot (which is for drive-by-joystick). And this is the POV button layout:
117  //
118  // 1
119  // 8 2
120  // 7 0 3
121  // 6 4
122  // 5
123  //
124  switch (joystick[currentJoystick].hatSwitch[buttonOrAxis].value)
125  {
126  case 0:
127  // no POV button pressed
128  emit joystickMoved(JOYSTICKAXISY5, 0);
129  break;
130  case 1:
131  // Y axis, UP, drive forward
132  emit joystickMoved(JOYSTICKAXISY5, -32767);
133  break;
134  case 3:
135  // x axis, RIGHT, drive right
136  emit joystickMoved(JOYSTICKAXISX4, 32767);
137  break;
138  case 5:
139  // Y axis, DOWN, drive backward
140  emit joystickMoved(JOYSTICKAXISY5, 32767);
141  break;
142  case 7:
143  // x axis, LEFT, drive left
144  emit joystickMoved(JOYSTICKAXISX4, -32767);
145  break;
146  }
147  }
148  }
149  }
150  } // numJoysticks
151  } // while
152  #endif
153 
154  #ifdef Q_OS_LINUX // joystick support for Linux:
155  axes = 2;
156  buttons = 2;
157  axisButtonNumber = 0;
158  axisButtonValue = 0;
159 
160  // check if joystick is accessible
161  if (isConnected() == false)
162  {
163  stopped = true;
164  return;
165  }
166 
167  ioctl(fd, JSIOCGVERSION, &version);
168  ioctl(fd, JSIOCGAXES, &axes);
169  ioctl(fd, JSIOCGBUTTONS, &buttons);
170  ioctl(fd, JSIOCGNAME(NAME_LENGTH), name);
171  ioctl(fd, JSIOCGAXMAP, axmap);
172  ioctl(fd, JSIOCGBTNMAP, btnmap);
173 
174 
175  //qDebug("Driver version is %d.%d.%d.\n", version >> 16, (version >> 8) & 0xff, version & 0xff);
176  //qDebug("Joystick (%s) has %d axes (", name, axes);
177  //qDebug("and %d buttons (", buttons);
178 
179 /*
180  * Old (0.x) interface.
181  */
182 /*
183  if ((argc == 2 && version < 0x010000) || !strcmp("--old", argv[1])) {
184 
185  struct JS_DATA_TYPE js;
186 
187  while (1) {
188 
189  if (read(fd, &js, JS_RETURN) != JS_RETURN) {
190  perror("\njstest: error reading");
191  exit(1);
192  }
193 
194  printf("Axes: X:%3d Y:%3d Buttons: A:%s B:%s\r",
195  js.x, js.y, (js.buttons & 1) ? "on " : "off", (js.buttons & 2) ? "on " : "off");
196 
197  fflush(stdout);
198 
199  usleep(10000);
200  }
201  }
202 */
203 
204 
205  //
206  // start "threading"...
207  //
208  while (!stopped)
209  {
210  // let the thread sleep some time
211  // for having more time for the other threads
212  msleep(THREADSLEEPTIME);
213 
214 
215  if (read(fd, &js, sizeof(struct js_event)) != sizeof(struct js_event))
216  {
217  emit message("Error reading joystick device!");
218  // no 'return' here, try further!
219  }
220  else
221  {
222 // switch(js.type & ~JS_EVENT_INIT)
223  switch(js.type)
224  {
225  case JS_EVENT_INIT:
226  emit message("Joystick initialised.");
227  break;
228  case JS_EVENT_BUTTON:
229  axisButtonNumber = js.number;
230  if (js.value == 0)
231  {
232  emit joystickButtonPressed(axisButtonNumber, false);
233  break;
234  }
235  if (js.value == 1)
236  {
237  emit joystickButtonPressed(axisButtonNumber, true);
238  break;
239  }
240  break;
241  case JS_EVENT_AXIS:
242  axisButtonNumber = js.number;
243  axisButtonValue = js.value;
244  emit joystickMoved(axisButtonNumber, axisButtonValue);
245  break;
246  }
247  }
248  }
249 #endif
250 
251  stopped = false;
252 }
253 
254 
256 {
257 #ifdef Q_OS_LINUX // joystick support for Linux:
258  if ((fd = open(joystickPort.toAscii(), O_RDONLY)) < 0)
259  {
260  emit message( QString(QString("No joystick found at %1").arg(joystickPort)).toAscii() );
261  stopped = true;
262  return false;
263  }
264 
265  // joystick is connected
266  return true;
267 
268 #endif
269 
270 #ifdef Q_OS_MAC // joystick support for Mac OS:
271  JoyReaderSetUpJoystick(numJoysticks, joystick, maxNumJoystick);
272  JoyReaderLoadJoystickCalibrationInfo(numJoysticks, joystick);
273 
274  if (numJoysticks != 0)
275  {
276  return true;
277  }
278 
279  return false;
280 #endif
281 
282  return false; // we return false. Noy joystick supported -> NO joystick "connected"!
283 }
284 
285 
286 void Joystick::setPort(QString port)
287 {
288  joystickPort = port;
289 }