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