~ubuntu-dev/wxwidgets2.6/upstream-debian

« back to all changes in this revision

Viewing changes to src/mac/corefoundation/hidjoystick.cpp

  • Committer: Daniel T Chen
  • Date: 2006-06-26 10:15:11 UTC
  • Revision ID: crimsun@ubuntu.com-20060626101511-a4436cec4c6d9b35
ImportĀ DebianĀ 2.6.3.2.1

Show diffs side-by-side

added added

removed removed

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