1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/joystick.cpp
3 // Purpose:     wxJoystick class
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     04/01/98
7 // Copyright:   (c) Julian Smart
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13 
14 #ifdef __BORLANDC__
15     #pragma hdrstop
16 #endif
17 
18 #if wxUSE_JOYSTICK
19 
20 #include "wx/joystick.h"
21 
22 #ifndef WX_PRECOMP
23     #include "wx/string.h"
24     #include "wx/window.h"
25 #endif
26 
27 #include "wx/msw/private.h"
28 
29 #if !defined(__GNUWIN32_OLD__) || defined(__CYGWIN10__)
30     #include <mmsystem.h>
31 #endif
32 
33 // Why doesn't BC++ have joyGetPosEx?
34 #if !defined(__WIN32__) || defined(__BORLANDC__)
35 #define NO_JOYGETPOSEX
36 #endif
37 
38 #include "wx/msw/registry.h"
39 
40 #include <regstr.h>
41 
IMPLEMENT_DYNAMIC_CLASS(wxJoystick,wxObject)42 IMPLEMENT_DYNAMIC_CLASS(wxJoystick, wxObject)
43 
44 // Attributes
45 ////////////////////////////////////////////////////////////////////////////
46 
47 /**
48     johan@linkdata.se 2002-08-20:
49     Now returns only valid, functioning
50     joysticks, counting from the first
51     available and upwards.
52 */
53 wxJoystick::wxJoystick(int joystick)
54 {
55     JOYINFO joyInfo;
56     int i, maxsticks;
57 
58     maxsticks = joyGetNumDevs();
59     for( i=0; i<maxsticks; i++ )
60     {
61         if( joyGetPos(i, & joyInfo) == JOYERR_NOERROR )
62         {
63             if( !joystick )
64             {
65                 /* Found the one we want, store actual OS id and return */
66                 m_joystick = i;
67                 return;
68             }
69             joystick --;
70         }
71     }
72 
73     /* No such joystick, return ID 0 */
74     m_joystick = 0;
75     return;
76 }
77 
GetPosition() const78 wxPoint wxJoystick::GetPosition() const
79 {
80     JOYINFO joyInfo;
81     MMRESULT res = joyGetPos(m_joystick, & joyInfo);
82     if (res == JOYERR_NOERROR )
83         return wxPoint(joyInfo.wXpos, joyInfo.wYpos);
84     else
85         return wxPoint(0,0);
86 }
87 
GetPosition(unsigned axis) const88 int wxJoystick::GetPosition(unsigned axis) const
89 {
90     switch (axis) {
91     case 0:
92         return GetPosition().x;
93     case 1:
94         return GetPosition().y;
95     case 2:
96         return GetZPosition();
97     case 3:
98         return GetRudderPosition();
99     case 4:
100         return GetUPosition();
101     case 5:
102         return GetVPosition();
103     default:
104         return 0;
105     }
106 }
107 
GetZPosition() const108 int wxJoystick::GetZPosition() const
109 {
110     JOYINFO joyInfo;
111     MMRESULT res = joyGetPos(m_joystick, & joyInfo);
112     if (res == JOYERR_NOERROR )
113         return joyInfo.wZpos;
114     else
115         return 0;
116 }
117 
118 /**
119     johan@linkdata.se 2002-08-20:
120     Return a bitmap with all button states in it,
121     like the GTK version does and Win32 does.
122 */
GetButtonState() const123 int wxJoystick::GetButtonState() const
124 {
125     JOYINFO joyInfo;
126     MMRESULT res = joyGetPos(m_joystick, & joyInfo);
127     if (res == JOYERR_NOERROR )
128     {
129         return joyInfo.wButtons;
130 #if 0
131         int buttons = 0;
132 
133         if (joyInfo.wButtons & JOY_BUTTON1)
134             buttons |= wxJOY_BUTTON1;
135         if (joyInfo.wButtons & JOY_BUTTON2)
136             buttons |= wxJOY_BUTTON2;
137         if (joyInfo.wButtons & JOY_BUTTON3)
138             buttons |= wxJOY_BUTTON3;
139         if (joyInfo.wButtons & JOY_BUTTON4)
140             buttons |= wxJOY_BUTTON4;
141 
142         return buttons;
143 #endif
144     }
145     else
146         return 0;
147 }
148 
GetButtonState(unsigned id) const149 bool wxJoystick::GetButtonState(unsigned id) const
150 {
151     if (id > sizeof(int) * 8)
152         return false;
153 
154     return (GetButtonState() & (1 << id)) != 0;
155 }
156 
157 /**
158     JLI 2002-08-20:
159     Returns -1 to signify error.
160 */
GetPOVPosition() const161 int wxJoystick::GetPOVPosition() const
162 {
163 #ifndef NO_JOYGETPOSEX
164     JOYINFOEX joyInfo;
165     joyInfo.dwFlags = JOY_RETURNPOV;
166     joyInfo.dwSize = sizeof(joyInfo);
167     MMRESULT res = joyGetPosEx(m_joystick, & joyInfo);
168     if (res == JOYERR_NOERROR )
169     {
170         return joyInfo.dwPOV;
171     }
172     else
173         return -1;
174 #else
175     return -1;
176 #endif
177 }
178 
179 /**
180     johan@linkdata.se 2002-08-20:
181     Returns -1 to signify error.
182 */
GetPOVCTSPosition() const183 int wxJoystick::GetPOVCTSPosition() const
184 {
185 #ifndef NO_JOYGETPOSEX
186     JOYINFOEX joyInfo;
187     joyInfo.dwFlags = JOY_RETURNPOVCTS;
188     joyInfo.dwSize = sizeof(joyInfo);
189     MMRESULT res = joyGetPosEx(m_joystick, & joyInfo);
190     if (res == JOYERR_NOERROR )
191     {
192         return joyInfo.dwPOV;
193     }
194     else
195         return -1;
196 #else
197     return -1;
198 #endif
199 }
200 
GetRudderPosition() const201 int wxJoystick::GetRudderPosition() const
202 {
203 #ifndef NO_JOYGETPOSEX
204     JOYINFOEX joyInfo;
205     joyInfo.dwFlags = JOY_RETURNR;
206     joyInfo.dwSize = sizeof(joyInfo);
207     MMRESULT res = joyGetPosEx(m_joystick, & joyInfo);
208     if (res == JOYERR_NOERROR )
209     {
210         return joyInfo.dwRpos;
211     }
212     else
213         return 0;
214 #else
215     return 0;
216 #endif
217 }
218 
GetUPosition() const219 int wxJoystick::GetUPosition() const
220 {
221 #ifndef NO_JOYGETPOSEX
222     JOYINFOEX joyInfo;
223     joyInfo.dwFlags = JOY_RETURNU;
224     joyInfo.dwSize = sizeof(joyInfo);
225     MMRESULT res = joyGetPosEx(m_joystick, & joyInfo);
226     if (res == JOYERR_NOERROR )
227     {
228         return joyInfo.dwUpos;
229     }
230     else
231         return 0;
232 #else
233     return 0;
234 #endif
235 }
236 
GetVPosition() const237 int wxJoystick::GetVPosition() const
238 {
239 #ifndef NO_JOYGETPOSEX
240     JOYINFOEX joyInfo;
241     joyInfo.dwFlags = JOY_RETURNV;
242     joyInfo.dwSize = sizeof(joyInfo);
243     MMRESULT res = joyGetPosEx(m_joystick, & joyInfo);
244     if (res == JOYERR_NOERROR )
245     {
246         return joyInfo.dwVpos;
247     }
248     else
249         return 0;
250 #else
251     return 0;
252 #endif
253 }
254 
GetMovementThreshold() const255 int wxJoystick::GetMovementThreshold() const
256 {
257     UINT thresh = 0;
258     MMRESULT res = joyGetThreshold(m_joystick, & thresh);
259     if (res == JOYERR_NOERROR )
260     {
261         return thresh;
262     }
263     else
264         return 0;
265 }
266 
SetMovementThreshold(int threshold)267 void wxJoystick::SetMovementThreshold(int threshold)
268 {
269     UINT thresh = threshold;
270     joySetThreshold(m_joystick, thresh);
271 }
272 
273 // Capabilities
274 ////////////////////////////////////////////////////////////////////////////
275 
276 /**
277     johan@linkdata.se 2002-08-20:
278     Now returns the number of connected, functioning
279     joysticks, as intended.
280 */
GetNumberJoysticks()281 int wxJoystick::GetNumberJoysticks()
282 {
283     JOYINFO joyInfo;
284     int i, maxsticks, actualsticks;
285     maxsticks = joyGetNumDevs();
286     actualsticks = 0;
287     for( i=0; i<maxsticks; i++ )
288     {
289         if( joyGetPos( i, & joyInfo ) == JOYERR_NOERROR )
290         {
291             actualsticks ++;
292         }
293     }
294     return actualsticks;
295 }
296 
297 /**
298     johan@linkdata.se 2002-08-20:
299     The old code returned true if there were any
300     joystick capable drivers loaded (=always).
301 */
IsOk() const302 bool wxJoystick::IsOk() const
303 {
304     JOYINFO joyInfo;
305     return (joyGetPos(m_joystick, & joyInfo) == JOYERR_NOERROR);
306 }
307 
GetManufacturerId() const308 int wxJoystick::GetManufacturerId() const
309 {
310     JOYCAPS joyCaps;
311     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
312         return 0;
313     else
314         return joyCaps.wMid;
315 }
316 
GetProductId() const317 int wxJoystick::GetProductId() const
318 {
319     JOYCAPS joyCaps;
320     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
321         return 0;
322     else
323         return joyCaps.wPid;
324 }
325 
GetProductName() const326 wxString wxJoystick::GetProductName() const
327 {
328     wxString str;
329 #ifndef __WINE__
330     JOYCAPS joyCaps;
331     if (joyGetDevCaps(m_joystick, &joyCaps, sizeof(joyCaps)) != JOYERR_NOERROR)
332         return wxEmptyString;
333 
334     wxRegKey key1(wxString::Format(wxT("HKEY_LOCAL_MACHINE\\%s\\%s\\%s"),
335                    REGSTR_PATH_JOYCONFIG, joyCaps.szRegKey, REGSTR_KEY_JOYCURR));
336 
337     key1.QueryValue(wxString::Format(wxT("Joystick%d%s"),
338                                      m_joystick + 1, REGSTR_VAL_JOYOEMNAME),
339                     str);
340 
341     wxRegKey key2(wxString::Format(wxT("HKEY_LOCAL_MACHINE\\%s\\%s"),
342                                         REGSTR_PATH_JOYOEM, str.c_str()));
343     key2.QueryValue(REGSTR_VAL_JOYOEMNAME, str);
344 #endif
345     return str;
346 }
347 
GetXMin() const348 int wxJoystick::GetXMin() const
349 {
350     JOYCAPS joyCaps;
351     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
352         return 0;
353     else
354         return joyCaps.wXmin;
355 }
356 
GetYMin() const357 int wxJoystick::GetYMin() const
358 {
359     JOYCAPS joyCaps;
360     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
361         return 0;
362     else
363         return joyCaps.wYmin;
364 }
365 
GetZMin() const366 int wxJoystick::GetZMin() const
367 {
368     JOYCAPS joyCaps;
369     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
370         return 0;
371     else
372         return joyCaps.wZmin;
373 }
374 
GetXMax() const375 int wxJoystick::GetXMax() const
376 {
377     JOYCAPS joyCaps;
378     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
379         return 0;
380     else
381         return joyCaps.wXmax;
382 }
383 
GetYMax() const384 int wxJoystick::GetYMax() const
385 {
386     JOYCAPS joyCaps;
387     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
388         return 0;
389     else
390         return joyCaps.wYmax;
391 }
392 
GetZMax() const393 int wxJoystick::GetZMax() const
394 {
395     JOYCAPS joyCaps;
396     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
397         return 0;
398     else
399         return joyCaps.wZmax;
400 }
401 
GetNumberButtons() const402 int wxJoystick::GetNumberButtons() const
403 {
404     JOYCAPS joyCaps;
405     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
406         return 0;
407     else
408         return joyCaps.wNumButtons;
409 }
410 
GetNumberAxes() const411 int wxJoystick::GetNumberAxes() const
412 {
413 #if defined(__WIN32__)
414     JOYCAPS joyCaps;
415     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
416         return 0;
417     else
418         return joyCaps.wNumAxes;
419 #else
420     return 0;
421 #endif
422 }
423 
GetMaxButtons() const424 int wxJoystick::GetMaxButtons() const
425 {
426 #if defined(__WIN32__)
427     JOYCAPS joyCaps;
428     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
429         return 0;
430     else
431         return joyCaps.wMaxButtons;
432 #else
433     return 0;
434 #endif
435 }
436 
GetMaxAxes() const437 int wxJoystick::GetMaxAxes() const
438 {
439 #if defined(__WIN32__)
440     JOYCAPS joyCaps;
441     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
442         return 0;
443     else
444         return joyCaps.wMaxAxes;
445 #else
446     return 0;
447 #endif
448 }
449 
GetPollingMin() const450 int wxJoystick::GetPollingMin() const
451 {
452     JOYCAPS joyCaps;
453     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
454         return 0;
455     else
456         return joyCaps.wPeriodMin;
457 }
458 
GetPollingMax() const459 int wxJoystick::GetPollingMax() const
460 {
461     JOYCAPS joyCaps;
462     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
463         return 0;
464     else
465         return joyCaps.wPeriodMax;
466 }
467 
GetRudderMin() const468 int wxJoystick::GetRudderMin() const
469 {
470 #if defined(__WIN32__)
471     JOYCAPS joyCaps;
472     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
473         return 0;
474     else
475         return joyCaps.wRmin;
476 #else
477     return 0;
478 #endif
479 }
480 
GetRudderMax() const481 int wxJoystick::GetRudderMax() const
482 {
483 #if defined(__WIN32__)
484     JOYCAPS joyCaps;
485     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
486         return 0;
487     else
488         return joyCaps.wRmax;
489 #else
490     return 0;
491 #endif
492 }
493 
GetUMin() const494 int wxJoystick::GetUMin() const
495 {
496 #if defined(__WIN32__)
497     JOYCAPS joyCaps;
498     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
499         return 0;
500     else
501         return joyCaps.wUmin;
502 #else
503     return 0;
504 #endif
505 }
506 
GetUMax() const507 int wxJoystick::GetUMax() const
508 {
509 #if defined(__WIN32__)
510     JOYCAPS joyCaps;
511     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
512         return 0;
513     else
514         return joyCaps.wUmax;
515 #else
516     return 0;
517 #endif
518 }
519 
GetVMin() const520 int wxJoystick::GetVMin() const
521 {
522 #if defined(__WIN32__)
523     JOYCAPS joyCaps;
524     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
525         return 0;
526     else
527         return joyCaps.wVmin;
528 #else
529     return 0;
530 #endif
531 }
532 
GetVMax() const533 int wxJoystick::GetVMax() const
534 {
535 #if defined(__WIN32__)
536     JOYCAPS joyCaps;
537     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
538         return 0;
539     else
540         return joyCaps.wVmax;
541 #else
542     return 0;
543 #endif
544 }
545 
546 
HasRudder() const547 bool wxJoystick::HasRudder() const
548 {
549 #if defined(__WIN32__)
550     JOYCAPS joyCaps;
551     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
552         return false;
553     else
554         return ((joyCaps.wCaps & JOYCAPS_HASR) == JOYCAPS_HASR);
555 #else
556     return false;
557 #endif
558 }
559 
HasZ() const560 bool wxJoystick::HasZ() const
561 {
562 #if defined(__WIN32__)
563     JOYCAPS joyCaps;
564     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
565         return false;
566     else
567         return ((joyCaps.wCaps & JOYCAPS_HASZ) == JOYCAPS_HASZ);
568 #else
569     return false;
570 #endif
571 }
572 
HasU() const573 bool wxJoystick::HasU() const
574 {
575 #if defined(__WIN32__)
576     JOYCAPS joyCaps;
577     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
578         return false;
579     else
580         return ((joyCaps.wCaps & JOYCAPS_HASU) == JOYCAPS_HASU);
581 #else
582     return false;
583 #endif
584 }
585 
HasV() const586 bool wxJoystick::HasV() const
587 {
588 #if defined(__WIN32__)
589     JOYCAPS joyCaps;
590     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
591         return false;
592     else
593         return ((joyCaps.wCaps & JOYCAPS_HASV) == JOYCAPS_HASV);
594 #else
595     return false;
596 #endif
597 }
598 
HasPOV() const599 bool wxJoystick::HasPOV() const
600 {
601 #if defined(__WIN32__)
602     JOYCAPS joyCaps;
603     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
604         return false;
605     else
606         return ((joyCaps.wCaps & JOYCAPS_HASPOV) == JOYCAPS_HASPOV);
607 #else
608     return false;
609 #endif
610 }
611 
HasPOV4Dir() const612 bool wxJoystick::HasPOV4Dir() const
613 {
614 #if defined(__WIN32__)
615     JOYCAPS joyCaps;
616     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
617         return false;
618     else
619         return ((joyCaps.wCaps & JOYCAPS_POV4DIR) == JOYCAPS_POV4DIR);
620 #else
621     return false;
622 #endif
623 }
624 
HasPOVCTS() const625 bool wxJoystick::HasPOVCTS() const
626 {
627 #if defined(__WIN32__)
628     JOYCAPS joyCaps;
629     if (joyGetDevCaps(m_joystick, & joyCaps, sizeof(JOYCAPS)) != JOYERR_NOERROR)
630         return false;
631     else
632         return ((joyCaps.wCaps & JOYCAPS_POVCTS) == JOYCAPS_POVCTS);
633 #else
634     return false;
635 #endif
636 }
637 
638 // Operations
639 ////////////////////////////////////////////////////////////////////////////
640 
SetCapture(wxWindow * win,int pollingFreq)641 bool wxJoystick::SetCapture(wxWindow* win, int pollingFreq)
642 {
643 #ifdef __WXMSW__
644     BOOL changed = (pollingFreq == 0);
645     MMRESULT res = joySetCapture((HWND) win->GetHWND(), m_joystick, pollingFreq, changed);
646     return (res == JOYERR_NOERROR);
647 #else
648     wxUnusedVar(win);
649     wxUnusedVar(pollingFreq);
650     return false;
651 #endif
652 }
653 
ReleaseCapture()654 bool wxJoystick::ReleaseCapture()
655 {
656     MMRESULT res = joyReleaseCapture(m_joystick);
657     return (res == JOYERR_NOERROR);
658 }
659 
660 #endif // wxUSE_JOYSTICK
661