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