📄 hidjoystick.cpp
字号:
}bool wxJoystick::HasU() const{ return m_hid->HasElement(wxJS_AXIS_U);}bool wxJoystick::HasV() const{ return m_hid->HasElement(wxJS_AXIS_V);}//---------------------------------------------------------------------------// UNSUPPORTED//---------------------------------------------------------------------------int wxJoystick::GetPOVPosition() const{ return -1;}int wxJoystick::GetPOVCTSPosition() const{ return -1;}int wxJoystick::GetMovementThreshold() const{ return 0;}void wxJoystick::SetMovementThreshold(int threshold){}bool wxJoystick::HasPOV() const{ return false;}bool wxJoystick::HasPOV4Dir() const{ return false;}bool wxJoystick::HasPOVCTS() const{ return false;}//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//// wxHIDJoystick////+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//---------------------------------------------------------------------------// wxHIDJoystick ctor//// Initializes the min/max members//---------------------------------------------------------------------------wxHIDJoystick::wxHIDJoystick() : m_nXMax(0), m_nYMax(0), m_nZMax(0), m_nRudderMax(0), m_nUMax(0), m_nVMax(0), m_nXMin(0), m_nYMin(0), m_nZMin(0), m_nRudderMin(0), m_nUMin(0), m_nVMin(0){}//---------------------------------------------------------------------------// wxHIDJoystick dtor//// Nothing...//---------------------------------------------------------------------------wxHIDJoystick::~wxHIDJoystick(){}//---------------------------------------------------------------------------// wxHIDJoystick::Create//// Creates the native HID device (joysticks are of either// kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad)//---------------------------------------------------------------------------bool wxHIDJoystick::Create(int nWhich){ int nJoysticks = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick); if (nWhich <= nJoysticks) return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, nWhich); else nWhich -= nJoysticks; int nGamePads = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad); if (nWhich <= nGamePads) return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, nWhich); else return false;}//---------------------------------------------------------------------------// wxHIDJoystick::BuildCookies// wxHIDJoystick::MakeCookies//// Sets up the cookies for the HID device (called from Create) - as// mentioned 0-40 are the buttons and 40-50 are the axes.//// MakeCookies is just a recursive function for each array within// BuildCookies.//---------------------------------------------------------------------------void wxHIDJoystick::BuildCookies(CFArrayRef Array){ InitCookies(50, true); // // I wasted two hours of my life on this line :( // accidently removed it during some source cleaning... // MakeCookies(Array); //paranoid debugging stuff#if 0 for(int i = 0; i < 50; ++i) wxPrintf(wxT("\nVAL #%i:[%i]"), i, m_pCookies[i]);#endif}//end buildcookiesvoid wxHIDJoystick::MakeCookies(CFArrayRef Array){ int i, nUsage, nPage; for (i = 0; i < CFArrayGetCount(Array); ++i) { const void* ref = CFDictionaryGetValue( (CFDictionaryRef)CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementKey) ); if (ref != NULL) { MakeCookies((CFArrayRef) ref); } else { CFNumberGetValue( (CFNumberRef) CFDictionaryGetValue( (CFDictionaryRef) CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementUsageKey) ), kCFNumberIntType, &nUsage ); CFNumberGetValue( (CFNumberRef) CFDictionaryGetValue( (CFDictionaryRef) CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementUsagePageKey) ), kCFNumberIntType, &nPage );#if 0 wxLogSysError(wxT("[%i][%i]"), nUsage, nPage);#endif if (nPage == kHIDPage_Button && nUsage <= 40) AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), nUsage-1 ); else if (nPage == kHIDPage_GenericDesktop) { //axis... switch(nUsage) { case kHIDUsage_GD_X: AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_X); wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementMaxKey), &m_nXMax); wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementMinKey), &m_nXMin); break; case kHIDUsage_GD_Y: AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_Y); wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementMaxKey), &m_nYMax); wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementMinKey), &m_nYMin); break; case kHIDUsage_GD_Z: AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_Z); wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementMaxKey), &m_nZMax); wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementMinKey), &m_nZMin); break; default: break; } } else if (nPage == kHIDPage_Simulation && nUsage == kHIDUsage_Sim_Rudder) { //rudder... AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_RUDDER ); wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementMaxKey), &m_nRudderMax); wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i), CFSTR(kIOHIDElementMinKey), &m_nRudderMin); } } }}//---------------------------------------------------------------------------// wxHIDJoystick::Get[XXX]//// Simple accessors so that the HID callback and the thread procedure// can access members from wxHIDDevice (our parent here).//---------------------------------------------------------------------------IOHIDElementCookie* wxHIDJoystick::GetCookies(){ return m_pCookies; }IOHIDQueueInterface** wxHIDJoystick::GetQueue(){ return m_ppQueue; }//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//// wxJoystickThread////+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//---------------------------------------------------------------------------// wxJoystickThread Constructor//// Just initializes members//---------------------------------------------------------------------------wxJoystickThread::wxJoystickThread(wxHIDJoystick* hid, int joystick) : m_hid(hid), m_joystick(joystick), m_lastposition(127,127), m_buttons(0), m_catchwin(NULL), m_polling(0){ memset(m_axe, 0, sizeof(int) * wxJS_MAX_AXES);}//---------------------------------------------------------------------------// wxJoystickThread::Entry//// Thread procedure//// Runs a CFRunLoop for polling. Basically, it sets the HID queue to// call wxJoystickThread::HIDCallback in the context of this thread// when something changes on the device. It polls as long as the user// wants, or a certain amount if the user wants to "block". Note that// we don't actually block here since this is in a secondary thread.//---------------------------------------------------------------------------void* wxJoystickThread::Entry(){ CFRunLoopSourceRef pRLSource = NULL; if ((*m_hid->GetQueue())->createAsyncEventSource( m_hid->GetQueue(), &pRLSource) != kIOReturnSuccess ) { wxLogSysError(wxT("Couldn't create async event source")); return NULL; } wxASSERT(pRLSource != NULL); //attach runloop source to main run loop in thread CFRunLoopRef pRL = CFRunLoopGetCurrent(); CFRunLoopAddSource(pRL, pRLSource, kCFRunLoopDefaultMode); wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) ); if( (*m_hid->GetQueue())->setEventCallout(m_hid->GetQueue(), wxJoystickThread::HIDCallback, this, this) != kIOReturnSuccess ) { wxLogSysError(wxT("Could not set event callout for queue")); return NULL; } if( (*m_hid->GetQueue())->start(m_hid->GetQueue()) != kIOReturnSuccess ) { wxLogSysError(wxT("Could not start queue")); return NULL; } double dTime; while(true) { if (TestDestroy()) break; if (m_polling) dTime = 0.0001 * m_polling; else dTime = 0.0001 * 10; // check at least every 10 msec in "blocking" case //true just "handles and returns" - false forces it to stay the time //amount#if 1 CFRunLoopRunInMode(kCFRunLoopDefaultMode, dTime, true);#else IOReturn ret = NULL; HIDCallback(this, ret, this, this); Sleep(3000);#endif } wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) ); CFRunLoopRemoveSource(pRL, pRLSource, kCFRunLoopDefaultMode); CFRelease(pRLSource); return NULL;}//---------------------------------------------------------------------------// wxJoystickThread::HIDCallback (static)//// Callback for the native HID device when it recieves input.//// This is where the REAL dirty work gets done.//// 1) Loops through each event the queue has recieved// 2) First, checks if the thread that is running the loop for// the polling has ended - if so it breaks out// 3) Next, it checks if there was an error getting this event from// the HID queue, if there was, it logs an error and returns// 4) Now it does the real dirty work by getting the button states// from cookies 0-40 and axes positions/states from cookies 40-50// in the native HID device by quering cookie values.// 5) Sends the event to the polling window (if any)// 6) Gets the next event and goes back to (1)//---------------------------------------------------------------------------/*static*/ void wxJoystickThread::HIDCallback(void* target, IOReturn res, void* context, void* sender){ IOHIDEventStruct hidevent; AbsoluteTime bogustime = {0,0}; IOReturn ret; wxJoystickThread* pThis = (wxJoystickThread*) context; wxHIDJoystick* m_hid = pThis->m_hid; //Get the "first" event from the queue //bogustime tells it we don't care at what time to start //where it gets the next from ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(), &hidevent, bogustime, 0); while (ret != kIOReturnUnderrun) { if (pThis->TestDestroy()) break; if(ret != kIOReturnSuccess) { wxLogSysError(wxString::Format(wxT("wxJoystick Error:[%i]"), ret)); return; } wxJoystickEvent wxevent; //Find the cookie that changed int nIndex = 0; IOHIDElementCookie* pCookies = m_hid->GetCookies(); while(nIndex < 50) { if(hidevent.elementCookie == pCookies[nIndex]) break; ++nIndex; } //debugging stuff#if 0 if(nIndex == 50) { wxLogSysError(wxString::Format(wxT("wxJoystick Out Of Bounds Error"))); break; }#endif //is the cookie a button? if (nIndex < 40) { if (hidevent.value) { pThis->m_buttons |= (1 << nIndex); wxevent.SetEventType(wxEVT_JOY_BUTTON_DOWN); } else { pThis->m_buttons &= ~(1 << nIndex); wxevent.SetEventType(wxEVT_JOY_BUTTON_UP); } wxevent.SetButtonChange(nIndex+1); } else if (nIndex == wxJS_AXIS_X) { pThis->m_lastposition.x = hidevent.value; wxevent.SetEventType(wxEVT_JOY_MOVE); pThis->m_axe[0] = hidevent.value; } else if (nIndex == wxJS_AXIS_Y) { pThis->m_lastposition.y = hidevent.value; wxevent.SetEventType(wxEVT_JOY_MOVE); pThis->m_axe[1] = hidevent.value; } else if (nIndex == wxJS_AXIS_Z) { wxevent.SetEventType(wxEVT_JOY_ZMOVE); pThis->m_axe[2] = hidevent.value; } else wxevent.SetEventType(wxEVT_JOY_MOVE); Nanoseconds timestamp = AbsoluteToNanoseconds(hidevent.timestamp); wxULongLong llTime(timestamp.hi, timestamp.lo); llTime /= 1000000; wxevent.SetTimestamp(llTime.GetValue()); wxevent.SetJoystick(pThis->m_joystick); wxevent.SetButtonState(pThis->m_buttons); wxevent.SetPosition(pThis->m_lastposition); wxevent.SetZPosition(pThis->m_axe[2]); wxevent.SetEventObject(pThis->m_catchwin); if (pThis->m_catchwin) pThis->m_catchwin->AddPendingEvent(wxevent); ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(), &hidevent, bogustime, 0); }}#endif // wxUSE_JOYSTICK && defined(__DARWIN__)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -