]> git.saurik.com Git - wxWidgets.git/blame - src/mac/corefoundation/hidjoystick.cpp
Removed duplicate xh_grid.cpp/h and rebaked files
[wxWidgets.git] / src / mac / corefoundation / hidjoystick.cpp
CommitLineData
4cb1d3da
RN
1/////////////////////////////////////////////////////////////////////////////
2// Name: joystick.cpp
3// Purpose: wxJoystick class
4// Author: Ryan Norton
5// Modified by:
6// Created: 2/13/2005
7// RCS-ID: $Id$
8// Copyright: (c) Ryan Norton
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
ce0d1032
SC
12//===========================================================================
13// DECLARATIONS
14//===========================================================================
15
16//---------------------------------------------------------------------------
17// Pre-compiled header stuff
18//---------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
4cb1d3da
RN
21#include "wx/wxprec.h"
22
ce0d1032
SC
23//---------------------------------------------------------------------------
24// Guard
25//---------------------------------------------------------------------------
4cb1d3da 26
ce0d1032
SC
27//we only support HID on OSX (DARWIN), since it requires DARWIN...
28#if wxUSE_JOYSTICK && defined(__DARWIN__)
4cb1d3da 29
ce0d1032
SC
30//---------------------------------------------------------------------------
31// Includes
32//---------------------------------------------------------------------------
33#include "wx/event.h" //joystick wxEvents
34#include "wx/log.h" //logging...
35#include "wx/joystick.h" //...
36#include "wx/thread.h" //wxThread for polling thread/ wxCriticalSection
37#include "wx/window.h" //for wxWindow to "capture" joystick
4cb1d3da 38
ce0d1032
SC
39//private headers
40#include "wx/mac/corefoundation/hid.h" //private mac hid stuff
4cb1d3da 41
ce0d1032 42//mac headers
4cb1d3da
RN
43#include <CoreServices/CoreServices.h>
44#include <mach/mach.h>
45#include <mach/mach_time.h>
46#include <unistd.h>
47
ce0d1032
SC
48//---------------------------------------------------------------------------
49// Definitions/Enumerations
50//---------------------------------------------------------------------------
51
52#define wxJS_MAX_AXES 10 /*max number of axes*/
53#define wxJS_MAX_BUTTONS 40 /*max number of buttons*/
54
55enum
56{
57 //These are positions within the cookie array
58 //in wxHIDJoystick that the cookies that store the axis' are
65442ab6 59 wxJS_AXIS_X = 40,
4cb1d3da
RN
60 wxJS_AXIS_Y,
61 wxJS_AXIS_Z,
62 wxJS_AXIS_RUDDER,
63 wxJS_AXIS_U,
64 wxJS_AXIS_V,
65
ce0d1032 66 //For the Get[XXX](Min/Max) functions
65442ab6
RN
67 wxJS_AXIS_MAX = 255, //32767,
68 wxJS_AXIS_MIN = 0, //-32767
4cb1d3da
RN
69};
70
ce0d1032
SC
71//---------------------------------------------------------------------------
72// wxHIDJoystick
73//---------------------------------------------------------------------------
4cb1d3da
RN
74class wxHIDJoystick : public wxHIDDevice
75{
76public:
77 bool Create(int nWhich);
78 virtual void BuildCookies(wxCFArray& Array);
65442ab6 79 void MakeCookies(wxCFArray& Array);
ce0d1032
SC
80 IOHIDElementCookie* GetCookies();
81 IOHIDQueueInterface** GetQueue();
65442ab6
RN
82
83 friend class wxJoystick;
4cb1d3da
RN
84};
85
ce0d1032
SC
86//---------------------------------------------------------------------------
87// wxJoystickThread
88//---------------------------------------------------------------------------
4cb1d3da
RN
89class wxJoystickThread : public wxThread
90{
91public:
92 wxJoystickThread(wxHIDJoystick* hid, int joystick);
93 void* Entry();
ce0d1032 94 static void HIDCallback(void* target, IOReturn res, void* context, void* sender);
65442ab6 95
4cb1d3da
RN
96private:
97 wxHIDJoystick* m_hid;
98 int m_joystick;
99 wxPoint m_lastposition;
ce0d1032 100 int m_axe[wxJS_MAX_AXES];
4cb1d3da
RN
101 int m_buttons;
102 wxWindow* m_catchwin;
103 int m_polling;
104
105 friend class wxJoystick;
106};
107
ce0d1032
SC
108//===========================================================================
109// IMPLEMENTATION
110//===========================================================================
4cb1d3da 111
ce0d1032
SC
112//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
113//
114// wxJoystick
115//
116//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4cb1d3da 117
ce0d1032 118IMPLEMENT_DYNAMIC_CLASS(wxJoystick, wxObject)
4cb1d3da 119
ce0d1032
SC
120//---------------------------------------------------------------------------
121// wxJoystick Constructor
122//
123// 1) Initializes member variables
124// 2) Attempts to create the native HID joystick implementation - if none
125// could be found (no joysticks, etc.) then it sets it to NULL
126//---------------------------------------------------------------------------
4cb1d3da
RN
127wxJoystick::wxJoystick(int joystick)
128 : m_joystick(joystick),
129 m_thread(NULL)
130{
131 m_hid = new wxHIDJoystick();
132
133 if (m_hid->Create(m_joystick))
134 {
135 m_thread = new wxJoystickThread(m_hid, m_joystick);
136 m_thread->Create();
137 m_thread->Run();
138 }
139 else
140 {
141 delete m_hid;
142 m_hid = NULL;
143 }
144}
145
ce0d1032
SC
146//---------------------------------------------------------------------------
147// wxJoystick Destructor
148//
149// Releases the capture of the thread, deletes it, and deletes
150// the native implementation.
151//---------------------------------------------------------------------------
4cb1d3da
RN
152wxJoystick::~wxJoystick()
153{
154 ReleaseCapture();
155 if (m_thread)
156 m_thread->Delete(); // It's detached so it will delete itself
157
158 if (m_hid)
159 delete m_hid;
160}
161
ce0d1032
SC
162//---------------------------------------------------------------------------
163// wxJoystick::Get[XXX]Position
164//
165// Returns the value of an axis that was polled from the thread. In the
166// case of GetPosition returns the X and Y values in a wxPoint
167//---------------------------------------------------------------------------
4cb1d3da
RN
168wxPoint wxJoystick::GetPosition() const
169{
170 wxPoint pos(wxDefaultPosition);
171 if (m_thread) pos = m_thread->m_lastposition;
172 return pos;
173}
4cb1d3da
RN
174int wxJoystick::GetZPosition() const
175{
176 if (m_thread)
177 return m_thread->m_axe[wxJS_AXIS_Z];
178 return 0;
179}
4cb1d3da
RN
180int wxJoystick::GetRudderPosition() const
181{
182 if (m_thread)
183 return m_thread->m_axe[wxJS_AXIS_RUDDER];
184 return 0;
185}
4cb1d3da
RN
186int wxJoystick::GetUPosition() const
187{
188 if (m_thread)
189 return m_thread->m_axe[wxJS_AXIS_U];
190 return 0;
191}
4cb1d3da
RN
192int wxJoystick::GetVPosition() const
193{
194 if (m_thread)
195 return m_thread->m_axe[wxJS_AXIS_V];
196 return 0;
197}
198
ce0d1032
SC
199//---------------------------------------------------------------------------
200// wxJoystick::GetButtonState
201//
202// Returns the state of the buttons in a bitmask as dictated by the
203// wx manual (the real work takes place in the thread, as always)
204//---------------------------------------------------------------------------
205int wxJoystick::GetButtonState() const
206{
207 if (m_thread)
208 return m_thread->m_buttons;
209 return 0;
210}
4cb1d3da 211
ce0d1032
SC
212//---------------------------------------------------------------------------
213// wxJoystick::IsOk
214//
215// Returns whether the joystick initialized successfully - in this case
216// if the native implementation doesn't exist (in constructor)
217//---------------------------------------------------------------------------
4cb1d3da 218bool wxJoystick::IsOk() const
ce0d1032
SC
219{
220 return m_hid != NULL;
221}
4cb1d3da 222
ce0d1032
SC
223//---------------------------------------------------------------------------
224// wxJoystick::Get[XXX](Id/Name)
225//
226// Simple accessors to the native HID implementation
227//---------------------------------------------------------------------------
4cb1d3da 228int wxJoystick::GetManufacturerId() const
65442ab6 229{ return m_hid->m_nManufacturerId; }
4cb1d3da 230int wxJoystick::GetProductId() const
65442ab6 231{ return m_hid->m_nProductId; }
4cb1d3da 232wxString wxJoystick::GetProductName() const
65442ab6 233{ return m_hid->m_szProductName; }
4cb1d3da 234
ce0d1032
SC
235//---------------------------------------------------------------------------
236// wxJoystick::GetNumberButtons
237// wxJoystick::GetNumberAxes
238//
239// Queries the joystick for an active number of buttons/axes.
240//
241// In the native HID implementation, the cookies:
242// 0-40 are the buttons of the joystick
243// 40-50 are the axes of the joystick
244//
245// These just query the native HID implementation as above.
246//---------------------------------------------------------------------------
4cb1d3da
RN
247int wxJoystick::GetNumberButtons() const
248{
249 int nCount = 0;
250
251 for(int nIndex = 0; nIndex < 40; ++nIndex)
252 {
253 if(m_hid->HasElement(nIndex))
254 ++nCount;
255 }
256
257 return nCount;
258}
4cb1d3da
RN
259int wxJoystick::GetNumberAxes() const
260{
261 int nCount = 0;
262
263 for(int nIndex = 40; nIndex < 50; ++nIndex)
264 {
265 if(m_hid->HasElement(nIndex))
266 ++nCount;
267 }
268
269 return nCount;
270}
271
ce0d1032
SC
272//---------------------------------------------------------------------------
273// wxJoystick::GetNumberJoysticks
4cb1d3da 274//
ce0d1032
SC
275// Gets the number of joysticks on the system. In HID that
276// is all devices with the kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad
277// identifiers.
278//---------------------------------------------------------------------------
279int wxJoystick::GetNumberJoysticks() const
280{
281 return
282 wxHIDDevice::GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick) +
283 wxHIDDevice::GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
284}
4cb1d3da 285
ce0d1032
SC
286//---------------------------------------------------------------------------
287// wxJoystick::SetCapture
288//
289// Stops sending events from the thread to the window set in
290// SetCapture and stops polling the joystick
291//---------------------------------------------------------------------------
292bool wxJoystick::SetCapture(wxWindow* win, int pollingFreq)
293{
294 if (m_thread)
295 {
296 m_thread->m_catchwin = win;
297 m_thread->m_polling = pollingFreq;
298 return true;
299 }
300 return false;
301}
4cb1d3da 302
ce0d1032
SC
303//---------------------------------------------------------------------------
304// wxJoystick::ReleaseCapture
305//
306// Stops sending events from the thread to the window set in
307// SetCapture and stops polling the joystick
308//---------------------------------------------------------------------------
309bool wxJoystick::ReleaseCapture()
310{
311 if (m_thread)
312 {
313 m_thread->m_catchwin = NULL;
314 m_thread->m_polling = 0;
315 return true;
316 }
317 return false;
318}
4cb1d3da 319
ce0d1032
SC
320//---------------------------------------------------------------------------
321// wxJoystick::Get[XXX]
322//
323// All values in hid range from 0 to 255, making these all kind of
324// superflous. These are mainly here due to the msw-centric api
325// that wxJoystick has... it should REALLY do its own scaling... oh well :)
326//---------------------------------------------------------------------------
327int wxJoystick::GetXMin() const
328{ return wxJS_AXIS_MIN; }
329int wxJoystick::GetYMin() const
330{ return wxJS_AXIS_MIN; }
331int wxJoystick::GetZMin() const
4cb1d3da 332{ return wxJS_AXIS_MIN; }
4cb1d3da
RN
333int wxJoystick::GetUMin() const
334{ return wxJS_AXIS_MIN; }
4cb1d3da
RN
335int wxJoystick::GetVMin() const
336{ return wxJS_AXIS_MIN; }
ce0d1032
SC
337int wxJoystick::GetRudderMin() const
338{ return wxJS_AXIS_MIN; }
4cb1d3da 339
ce0d1032
SC
340int wxJoystick::GetXMax() const
341{ return wxJS_AXIS_MAX; }
342int wxJoystick::GetYMax() const
343{ return wxJS_AXIS_MAX; }
344int wxJoystick::GetZMax() const
345{ return wxJS_AXIS_MAX; }
346int wxJoystick::GetUMax() const
347{ return wxJS_AXIS_MAX; }
4cb1d3da
RN
348int wxJoystick::GetVMax() const
349{ return wxJS_AXIS_MAX; }
ce0d1032
SC
350int wxJoystick::GetRudderMax() const
351{ return wxJS_AXIS_MAX; }
352
353//---------------------------------------------------------------------------
354// wxJoystick::Get[XXX]
355//
356// Min/Max values for buttons, axes, etc.. Polling in this case is just
357// what the linux port has.
358//---------------------------------------------------------------------------
359int wxJoystick::GetMaxButtons() const
360{ return wxJS_MAX_BUTTONS; }
361int wxJoystick::GetMaxAxes() const
362{ return wxJS_MAX_AXES; }
363int wxJoystick::GetPollingMin() const
364{ return 10; }
365int wxJoystick::GetPollingMax() const
366{ return 1000; }
4cb1d3da 367
ce0d1032
SC
368//---------------------------------------------------------------------------
369// wxJoystick::Has[XXX]
370//
371// Just queries the native hid implementation if the cookie was found
372// when enumerating the cookies of the joystick device
373//---------------------------------------------------------------------------
4cb1d3da
RN
374bool wxJoystick::HasRudder() const
375{ return m_hid->HasElement(wxJS_AXIS_RUDDER); }
4cb1d3da
RN
376bool wxJoystick::HasZ() const
377{ return m_hid->HasElement(wxJS_AXIS_Z); }
4cb1d3da
RN
378bool wxJoystick::HasU() const
379{ return m_hid->HasElement(wxJS_AXIS_U); }
4cb1d3da
RN
380bool wxJoystick::HasV() const
381{ return m_hid->HasElement(wxJS_AXIS_V); }
382
ce0d1032
SC
383//---------------------------------------------------------------------------
384// UNSUPPORTED
385//---------------------------------------------------------------------------
386int wxJoystick::GetPOVPosition() const
387{ return -1; }
388int wxJoystick::GetPOVCTSPosition() const
389{ return -1; }
390int wxJoystick::GetMovementThreshold() const
391{ return 0; }
392void wxJoystick::SetMovementThreshold(int threshold)
393{ }
4cb1d3da
RN
394bool wxJoystick::HasPOV() const
395{ return false; }
4cb1d3da
RN
396bool wxJoystick::HasPOV4Dir() const
397{ return false; }
4cb1d3da
RN
398bool wxJoystick::HasPOVCTS() const
399{ return false; }
400
ce0d1032
SC
401//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
402//
403// wxHIDJoystick
404//
405//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4cb1d3da 406
ce0d1032
SC
407//---------------------------------------------------------------------------
408// wxHIDJoystick::Create
409//
410// Creates the native HID device (joysticks are of either
411// kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad)
412//---------------------------------------------------------------------------
413bool wxHIDJoystick::Create(int nWhich)
4cb1d3da 414{
ce0d1032
SC
415 int nJoysticks = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
416
417 if (nWhich <= nJoysticks)
418 return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
419 else
420 nWhich -= nJoysticks;
421
422 int nGamePads = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
423
424 if (nWhich <= nGamePads)
425 return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
426 else
4cb1d3da
RN
427 return false;
428}
429
ce0d1032
SC
430//---------------------------------------------------------------------------
431// wxHIDJoystick::BuildCookies
432// wxHIDJoystick::MakeCookies
433//
434// Sets up the cookies for the HID device (called from Create) - as
435// mentioned 0-40 are the buttons and 40-50 are the axes.
436//
437// MakeCookies is just a recursive function for each array within
438// BuildCookies.
439//---------------------------------------------------------------------------
440void wxHIDJoystick::BuildCookies(wxCFArray& Array)
4cb1d3da 441{
ce0d1032
SC
442 Array = CFDictionaryGetValue((CFDictionaryRef)Array[0], CFSTR(kIOHIDElementKey));
443 InitCookies(50, true);
444
445 memset(m_pCookies, 0, sizeof(*m_pCookies) * 50);
446
447 //
448 // I wasted two hours of my life on this line :(
449 // accidently removed it during some source cleaning...
450 //
451 MakeCookies(Array);
452
453 //paranoid debugging stuff
454#if 0
455 for(int i = 0; i < 50; ++i)
456 wxPrintf(wxT("\nVAL #%i:[%i]"), i, m_pCookies[i]);
457#endif
458}//end buildcookies
459
460void wxHIDJoystick::MakeCookies(wxCFArray& Array)
461{
462 int i, nUsage, nPage;
463
464 for (i = 0; i < Array.Count(); ++i)
4cb1d3da 465 {
ce0d1032
SC
466 const void* ref = CFDictionaryGetValue((CFDictionaryRef)Array[i], CFSTR(kIOHIDElementKey));
467
468 if (ref != NULL)
469 {
470 wxCFArray newarray(ref);
471 MakeCookies(newarray);
4cb1d3da 472 }
ce0d1032
SC
473 else
474 {
475 CFNumberGetValue(
476 (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)),
477 kCFNumberLongType, &nUsage);
478
479 CFNumberGetValue(
480 (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsagePageKey)),
481 kCFNumberLongType, &nPage);
482
483#if 0
484 wxLogSysError(wxT("[%i][%i]"), nUsage, nPage);
485#endif
486 if (nPage == kHIDPage_Button && nUsage <= 40)
487 AddCookieInQueue(Array[i], nUsage-1 );
488 else if (nPage == kHIDPage_GenericDesktop)
489 {
490 switch(nUsage)
491 {
492 case kHIDUsage_GD_X:
493 AddCookieInQueue(Array[i], wxJS_AXIS_X);
494 break;
495 case kHIDUsage_GD_Y:
496 AddCookieInQueue(Array[i], wxJS_AXIS_Y);
497 break;
498 case kHIDUsage_GD_Z:
499 AddCookieInQueue(Array[i], wxJS_AXIS_Z);
500 break;
501 default:
502 break;
503 }
504 }
505 else if (nPage == kHIDPage_Simulation && nUsage == kHIDUsage_Sim_Rudder)
506 AddCookieInQueue(Array[i], wxJS_AXIS_RUDDER );
507 }
508 }
4cb1d3da 509}
ce0d1032
SC
510
511//---------------------------------------------------------------------------
512// wxHIDJoystick::Get[XXX]
513//
514// Simple accessors so that the HID callback and the thread procedure
515// can access members from wxHIDDevice (our parent here).
516//---------------------------------------------------------------------------
517IOHIDElementCookie* wxHIDJoystick::GetCookies()
518{ return m_pCookies; }
519IOHIDQueueInterface** wxHIDJoystick::GetQueue()
520{ return m_ppQueue; }
521
522//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
523//
524// wxJoystickThread
525//
526//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
527
528//---------------------------------------------------------------------------
529// wxJoystickThread Constructor
530//
531// Just initializes members
532//---------------------------------------------------------------------------
533wxJoystickThread::wxJoystickThread(wxHIDJoystick* hid, int joystick)
534 : m_hid(hid),
535 m_joystick(joystick),
536 m_lastposition(127,127),
537 m_buttons(0),
538 m_catchwin(NULL),
539 m_polling(0)
540{
541 memset(m_axe, 0, sizeof(int) * wxJS_MAX_AXES);
542}
543
544//---------------------------------------------------------------------------
545// wxJoystickThread::Entry
546//
547// Thread procedure
548//
549// Runs a CFRunLoop for polling. Basically, it sets the HID queue to
550// call wxJoystickThread::HIDCallback in the context of this thread
551// when something changes on the device. It polls as long as the user
552// wants, or a certain amount if the user wants to "block". Note that
553// we don't actually block here since this is in a secondary thread.
554//---------------------------------------------------------------------------
555void* wxJoystickThread::Entry()
556{
557 CFRunLoopSourceRef pRLSource = NULL;
558
559 if ((*m_hid->GetQueue())->createAsyncEventSource(
560 m_hid->GetQueue(), &pRLSource) != kIOReturnSuccess )
561 {
562 wxLogSysError(wxT("Couldn't create async event source"));
563 return NULL;
564 }
565
566 wxASSERT(pRLSource != NULL);
567
568 //attach runloop source to main run loop in thread
569 CFRunLoopRef pRL = CFRunLoopGetCurrent();
570 CFRunLoopAddSource(pRL, pRLSource, kCFRunLoopDefaultMode);
571 wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );
572
573
574 if( (*m_hid->GetQueue())->setEventCallout(m_hid->GetQueue(),
575 wxJoystickThread::HIDCallback, this, this) != kIOReturnSuccess )
576 {
577 wxLogSysError(wxT("Could not set event callout for queue"));
578 return NULL;
579 }
580
581 if( (*m_hid->GetQueue())->start(m_hid->GetQueue()) != kIOReturnSuccess )
582 {
583 wxLogSysError(wxT("Could not start queue"));
584 return NULL;
585 }
586
587 double dTime;
588
589 while(true)
590 {
591 if (TestDestroy())
592 break;
593
594 if (m_polling)
595 dTime = 0.0001 * m_polling;
596 else
597 dTime = 0.0001 * 10; // check at least every 10 msec in "blocking" case
598
599 //true just "handles and returns" - false forces it to stay the time
600 //amount
601#if 1
602 CFRunLoopRunInMode(kCFRunLoopDefaultMode, dTime, true);
603#else
604 IOReturn ret = NULL;
605 HIDCallback(this, ret, this, this);
606 Sleep(3000);
4cb1d3da 607#endif
ce0d1032
SC
608 }
609
610 wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );
611
612 CFRunLoopRemoveSource(pRL, pRLSource, kCFRunLoopDefaultMode);
613 CFRelease(pRLSource);
614
615 return NULL;
616}
617
618//---------------------------------------------------------------------------
619// wxJoystickThread::HIDCallback (static)
620//
621// Callback for the native HID device when it recieves input.
622//
623// This is where the REAL dirty work gets done.
624//
625// 1) Loops through each event the queue has recieved
626// 2) First, checks if the thread that is running the loop for
627// the polling has ended - if so it breaks out
628// 3) Next, it checks if there was an error getting this event from
629// the HID queue, if there was, it logs an error and returns
630// 4) Now it does the real dirty work by getting the button states
631// from cookies 0-40 and axes positions/states from cookies 40-50
632// in the native HID device by quering cookie values.
633// 5) Sends the event to the polling window (if any)
634// 6) Gets the next event and goes back to (1)
635//---------------------------------------------------------------------------
636/*static*/ void wxJoystickThread::HIDCallback(void* target, IOReturn res,
637 void* context, void* sender)
638{
639 IOHIDEventStruct hidevent;
640 AbsoluteTime bogustime = {0,0};
641 IOReturn ret;
642 wxJoystickThread* pThis = (wxJoystickThread*) context;
643 wxHIDJoystick* m_hid = pThis->m_hid;
4cb1d3da 644
ce0d1032
SC
645 //Get the "first" event from the queue
646 //bogustime tells it we don't care at what time to start
647 //where it gets the next from
648 ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
649 &hidevent, bogustime, 0);
650
651 while (ret != kIOReturnUnderrun)
652 {
653 if (pThis->TestDestroy())
654 break;
655
656 if(ret != kIOReturnSuccess)
657 {
658 wxLogSysError(wxString::Format(wxT("wxJoystick Error:[%i]"), ret));
659 return;
660 }
661
662 wxJoystickEvent wxevent;
663
664 //Find the cookie that changed
665 int nIndex = 0;
666 IOHIDElementCookie* pCookies = m_hid->GetCookies();
667 while(nIndex < 50)
668 {
669 if(hidevent.elementCookie == pCookies[nIndex])
670 break;
671
672 ++nIndex;
673 }
674
675 //debugging stuff
676#if 0
677 if(nIndex == 50)
678 {
679 wxLogSysError(wxString::Format(wxT("wxJoystick Out Of Bounds Error")));
680 break;
681 }
4cb1d3da 682#endif
ce0d1032
SC
683
684 //is the cookie a button?
685 if (nIndex < 40)
686 {
687 if (hidevent.value)
688 {
689 pThis->m_buttons |= (1 << nIndex);
690 wxevent.SetEventType(wxEVT_JOY_BUTTON_DOWN);
691 }
692 else
693 {
694 pThis->m_buttons &= ~(1 << nIndex);
695 wxevent.SetEventType(wxEVT_JOY_BUTTON_UP);
696 }
697
698 wxevent.SetButtonChange(nIndex+1);
699 }
700 else if (nIndex == wxJS_AXIS_X)
701 {
702 pThis->m_lastposition.x = hidevent.value;
703 wxevent.SetEventType(wxEVT_JOY_MOVE);
704 pThis->m_axe[0] = hidevent.value;
705 }
706 else if (nIndex == wxJS_AXIS_Y)
707 {
708 pThis->m_lastposition.y = hidevent.value;
709 wxevent.SetEventType(wxEVT_JOY_MOVE);
710 pThis->m_axe[1] = hidevent.value;
711 }
712 else if (nIndex == wxJS_AXIS_Z)
713 {
714 wxevent.SetEventType(wxEVT_JOY_ZMOVE);
715 pThis->m_axe[2] = hidevent.value;
716 }
717 else
718 wxevent.SetEventType(wxEVT_JOY_MOVE);
719
720 Nanoseconds timestamp = AbsoluteToNanoseconds(hidevent.timestamp);
721
722 wxULongLong llTime(timestamp.hi, timestamp.lo);
723
724 llTime /= 1000000;
725
726 wxevent.SetTimestamp(llTime.GetValue());
727 wxevent.SetJoystick(pThis->m_joystick);
728 wxevent.SetButtonState(pThis->m_buttons);
729 wxevent.SetPosition(pThis->m_lastposition);
730 wxevent.SetZPosition(pThis->m_axe[2]);
731 wxevent.SetEventObject(pThis->m_catchwin);
732
733 if (pThis->m_catchwin)
734 pThis->m_catchwin->AddPendingEvent(wxevent);
735
736 ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
737 &hidevent, bogustime, 0);
738 }
739}
740
741#endif // wxUSE_JOYSTICK && defined(__DARWIN__)
4cb1d3da 742