]> git.saurik.com Git - wxWidgets.git/blob - src/unix/joystick.cpp
fix wxExecute() return code checks and removed not working code to open URLs in new...
[wxWidgets.git] / src / unix / joystick.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: joystick.cpp
3 // Purpose: wxJoystick class
4 // Author: Ported to Linux by Guilhem Lavaux
5 // Modified by:
6 // Created: 05/23/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Guilhem Lavaux
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // for compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #include "wx/defs.h"
16
17 #if wxUSE_JOYSTICK
18
19 #include "wx/joystick.h"
20
21 #include <linux/joystick.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <sys/ioctl.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28
29 #include "wx/event.h"
30 #include "wx/window.h"
31
32 enum {
33 wxJS_AXIS_X = 0,
34 wxJS_AXIS_Y,
35 wxJS_AXIS_Z,
36 wxJS_AXIS_RUDDER,
37 wxJS_AXIS_U,
38 wxJS_AXIS_V,
39
40 wxJS_AXIS_MAX = 32767,
41 wxJS_AXIS_MIN = -32767
42 };
43
44
45 IMPLEMENT_DYNAMIC_CLASS(wxJoystick, wxObject)
46
47
48 ////////////////////////////////////////////////////////////////////////////
49 // Background thread for reading the joystick device
50 ////////////////////////////////////////////////////////////////////////////
51
52 class wxJoystickThread : public wxThread
53 {
54 public:
55 wxJoystickThread(int device, int joystick);
56 void* Entry();
57
58 private:
59 int m_device;
60 int m_joystick;
61 wxPoint m_lastposition;
62 int m_axe[15];
63 int m_buttons;
64 wxWindow* m_catchwin;
65 int m_polling;
66
67 friend class wxJoystick;
68 };
69
70
71 wxJoystickThread::wxJoystickThread(int device, int joystick)
72 : m_device(device),
73 m_joystick(joystick),
74 m_lastposition(wxDefaultPosition),
75 m_buttons(0),
76 m_catchwin(NULL),
77 m_polling(0)
78 {
79 for (int i=0; i<15; i++)
80 m_axe[i] = 0;
81 }
82
83
84 void* wxJoystickThread::Entry()
85 {
86 struct js_event j_evt;
87 fd_set read_fds;
88 struct timeval time_out = {0, 0};
89
90 FD_ZERO(&read_fds);
91 while (true)
92 {
93 if (TestDestroy())
94 break;
95
96 // We use select when either polling or 'blocking' as even in the
97 // blocking case we need to check TestDestroy periodically
98 if (m_polling)
99 time_out.tv_usec = m_polling * 1000;
100 else
101 time_out.tv_usec = 10 * 1000; // check at least every 10 msec in blocking case
102
103 FD_SET(m_device, &read_fds);
104 select(m_device+1, &read_fds, NULL, NULL, &time_out);
105 if (FD_ISSET(m_device, &read_fds))
106 {
107 memset(&j_evt, 0, sizeof(j_evt));
108 read(m_device, &j_evt, sizeof(j_evt));
109
110 //printf("time: %d\t value: %d\t type: %d\t number: %d\n",
111 // j_evt.time, j_evt.value, j_evt.type, j_evt.number);
112
113 wxJoystickEvent jwx_event;
114
115 if (j_evt.type & JS_EVENT_AXIS)
116 {
117 m_axe[j_evt.number] = j_evt.value;
118
119 switch (j_evt.number)
120 {
121 case wxJS_AXIS_X:
122 m_lastposition.x = j_evt.value;
123 jwx_event.SetEventType(wxEVT_JOY_MOVE);
124 break;
125 case wxJS_AXIS_Y:
126 m_lastposition.y = j_evt.value;
127 jwx_event.SetEventType(wxEVT_JOY_MOVE);
128 break;
129 case wxJS_AXIS_Z:
130 jwx_event.SetEventType(wxEVT_JOY_ZMOVE);
131 break;
132 default:
133 jwx_event.SetEventType(wxEVT_JOY_MOVE);
134 // TODO: There should be a way to indicate that the event
135 // is for some other axes.
136 break;
137 }
138 }
139
140 if (j_evt.type & JS_EVENT_BUTTON)
141 {
142 if (j_evt.value)
143 {
144 m_buttons |= (1 << j_evt.number);
145 jwx_event.SetEventType(wxEVT_JOY_BUTTON_DOWN);
146 }
147 else
148 {
149 m_buttons &= ~(1 << j_evt.number);
150 jwx_event.SetEventType(wxEVT_JOY_BUTTON_UP);
151 }
152
153 jwx_event.SetButtonChange(j_evt.number);
154
155 jwx_event.SetTimestamp(j_evt.time);
156 jwx_event.SetJoystick(m_joystick);
157 jwx_event.SetButtonState(m_buttons);
158 jwx_event.SetPosition(m_lastposition);
159 jwx_event.SetZPosition(m_axe[3]);
160 jwx_event.SetEventObject(m_catchwin);
161
162 if (m_catchwin)
163 m_catchwin->AddPendingEvent(jwx_event);
164 }
165 }
166 }
167
168 close(m_device);
169 return NULL;
170 }
171
172
173 ////////////////////////////////////////////////////////////////////////////
174
175 wxJoystick::wxJoystick(int joystick)
176 : m_device(-1),
177 m_joystick(joystick),
178 m_thread(NULL)
179 {
180 wxString dev_name;
181
182 // old /dev structure
183 dev_name.Printf( wxT("/dev/js%d"), joystick);
184 m_device = open(dev_name.fn_str(), O_RDONLY);
185
186 // new /dev structure with "input" subdirectory
187 if (m_device == -1)
188 {
189 dev_name.Printf( wxT("/dev/input/js%d"), joystick);
190 m_device = open(dev_name.fn_str(), O_RDONLY);
191 }
192
193 if (m_device != -1)
194 {
195 m_thread = new wxJoystickThread(m_device, m_joystick);
196 m_thread->Create();
197 m_thread->Run();
198 }
199 }
200
201
202 wxJoystick::~wxJoystick()
203 {
204 ReleaseCapture();
205 if (m_thread)
206 m_thread->Delete(); // It's detached so it will delete itself
207 m_device = -1;
208 }
209
210
211 ////////////////////////////////////////////////////////////////////////////
212 // State
213 ////////////////////////////////////////////////////////////////////////////
214
215 wxPoint wxJoystick::GetPosition() const
216 {
217 wxPoint pos(wxDefaultPosition);
218 if (m_thread) pos = m_thread->m_lastposition;
219 return pos;
220 }
221
222 int wxJoystick::GetZPosition() const
223 {
224 if (m_thread)
225 return m_thread->m_axe[wxJS_AXIS_Z];
226 return 0;
227 }
228
229 int wxJoystick::GetButtonState() const
230 {
231 if (m_thread)
232 return m_thread->m_buttons;
233 return 0;
234 }
235
236 int wxJoystick::GetPOVPosition() const
237 {
238 return -1;
239 }
240
241 int wxJoystick::GetPOVCTSPosition() const
242 {
243 return -1;
244 }
245
246 int wxJoystick::GetRudderPosition() const
247 {
248 if (m_thread)
249 return m_thread->m_axe[wxJS_AXIS_RUDDER];
250 return 0;
251 }
252
253 int wxJoystick::GetUPosition() const
254 {
255 if (m_thread)
256 return m_thread->m_axe[wxJS_AXIS_U];
257 return 0;
258 }
259
260 int wxJoystick::GetVPosition() const
261 {
262 if (m_thread)
263 return m_thread->m_axe[wxJS_AXIS_V];
264 return 0;
265 }
266
267 int wxJoystick::GetMovementThreshold() const
268 {
269 return 0;
270 }
271
272 void wxJoystick::SetMovementThreshold(int threshold)
273 {
274 }
275
276 ////////////////////////////////////////////////////////////////////////////
277 // Capabilities
278 ////////////////////////////////////////////////////////////////////////////
279
280 bool wxJoystick::IsOk() const
281 {
282 return (m_device != -1);
283 }
284
285 int wxJoystick::GetNumberJoysticks() const
286 {
287 wxString dev_name;
288 int fd, j;
289
290 for (j=0; j<4; j++) {
291 dev_name.Printf(wxT("/dev/js%d"), j);
292 fd = open(dev_name.fn_str(), O_RDONLY);
293 if (fd == -1)
294 break;
295 close(fd);
296 }
297
298 if (j == 0) {
299 for (j=0; j<4; j++) {
300 dev_name.Printf(wxT("/dev/input/js%d"), j);
301 fd = open(dev_name.fn_str(), O_RDONLY);
302 if (fd == -1)
303 return j;
304 close(fd);
305 }
306 }
307
308 return j;
309 }
310
311 int wxJoystick::GetManufacturerId() const
312 {
313 return 0;
314 }
315
316 int wxJoystick::GetProductId() const
317 {
318 return 0;
319 }
320
321 wxString wxJoystick::GetProductName() const
322 {
323 char name[128];
324
325 if (ioctl(m_device, JSIOCGNAME(sizeof(name)), name) < 0)
326 strcpy(name, "Unknown");
327 return wxString(name, wxConvLibc);
328 }
329
330 int wxJoystick::GetXMin() const
331 {
332 return wxJS_AXIS_MIN;
333 }
334
335 int wxJoystick::GetYMin() const
336 {
337 return wxJS_AXIS_MIN;
338 }
339
340 int wxJoystick::GetZMin() const
341 {
342 return wxJS_AXIS_MIN;
343 }
344
345 int wxJoystick::GetXMax() const
346 {
347 return wxJS_AXIS_MAX;
348 }
349
350 int wxJoystick::GetYMax() const
351 {
352 return wxJS_AXIS_MAX;
353 }
354
355 int wxJoystick::GetZMax() const
356 {
357 return wxJS_AXIS_MAX;
358 }
359
360 int wxJoystick::GetNumberButtons() const
361 {
362 char nb=0;
363
364 if (m_device != -1)
365 ioctl(m_device, JSIOCGBUTTONS, &nb);
366
367 return nb;
368 }
369
370 int wxJoystick::GetNumberAxes() const
371 {
372 char nb=0;
373
374 if (m_device != -1)
375 ioctl(m_device, JSIOCGAXES, &nb);
376
377 return nb;
378 }
379
380 int wxJoystick::GetMaxButtons() const
381 {
382 return 15; // internal
383 }
384
385 int wxJoystick::GetMaxAxes() const
386 {
387 return 15; // internal
388 }
389
390 int wxJoystick::GetPollingMin() const
391 {
392 return 10;
393 }
394
395 int wxJoystick::GetPollingMax() const
396 {
397 return 1000;
398 }
399
400 int wxJoystick::GetRudderMin() const
401 {
402 return wxJS_AXIS_MIN;
403 }
404
405 int wxJoystick::GetRudderMax() const
406 {
407 return wxJS_AXIS_MAX;
408 }
409
410 int wxJoystick::GetUMin() const
411 {
412 return wxJS_AXIS_MIN;
413 }
414
415 int wxJoystick::GetUMax() const
416 {
417 return wxJS_AXIS_MAX;
418 }
419
420 int wxJoystick::GetVMin() const
421 {
422 return wxJS_AXIS_MIN;
423 }
424
425 int wxJoystick::GetVMax() const
426 {
427 return wxJS_AXIS_MAX;
428 }
429
430 bool wxJoystick::HasRudder() const
431 {
432 return GetNumberAxes() >= wxJS_AXIS_RUDDER;
433 }
434
435 bool wxJoystick::HasZ() const
436 {
437 return GetNumberAxes() >= wxJS_AXIS_Z;
438 }
439
440 bool wxJoystick::HasU() const
441 {
442 return GetNumberAxes() >= wxJS_AXIS_U;
443 }
444
445 bool wxJoystick::HasV() const
446 {
447 return GetNumberAxes() >= wxJS_AXIS_V;
448 }
449
450 bool wxJoystick::HasPOV() const
451 {
452 return false;
453 }
454
455 bool wxJoystick::HasPOV4Dir() const
456 {
457 return false;
458 }
459
460 bool wxJoystick::HasPOVCTS() const
461 {
462 return false;
463 }
464
465 ////////////////////////////////////////////////////////////////////////////
466 // Operations
467 ////////////////////////////////////////////////////////////////////////////
468
469 bool wxJoystick::SetCapture(wxWindow* win, int pollingFreq)
470 {
471 if (m_thread)
472 {
473 m_thread->m_catchwin = win;
474 m_thread->m_polling = pollingFreq;
475 return true;
476 }
477 return false;
478 }
479
480 bool wxJoystick::ReleaseCapture()
481 {
482 if (m_thread)
483 {
484 m_thread->m_catchwin = NULL;
485 m_thread->m_polling = 0;
486 return true;
487 }
488 return false;
489 }
490 #endif // wxUSE_JOYSTICK
491