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