From: Ryan Norton Date: Mon, 14 Feb 2005 20:12:11 +0000 (+0000) Subject: Finalize wxJoystick on mac. Note change. Pretty up joystick sample a bit. Don... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/65442ab650425a5f6a1d5d685e8df582401a9be7 Finalize wxJoystick on mac. Note change. Pretty up joystick sample a bit. Don't logsyserror when wxSound can't find a file - its annoying. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@32045 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/changes.txt b/docs/changes.txt index 01a2089d0b..6977466302 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -101,6 +101,7 @@ wxMac: - Vertical sliders oriented consistent with MSW/GTK (0 at top) (Kevin Hock) - wxDynamicLibrary::GetDllExt() now returns ".bundle", not ".dylib" - wxDynamicLibrary::GetSymbol() now prepends underscore to the symbol name +- wxJoystick now works on OSX wxMSW: diff --git a/include/wx/mac/corefoundation/hid.h b/include/wx/mac/corefoundation/hid.h index 52e661eb63..3789e81ff3 100644 --- a/include/wx/mac/corefoundation/hid.h +++ b/include/wx/mac/corefoundation/hid.h @@ -24,7 +24,7 @@ #endif #include "wx/defs.h" - +#include "wx/string.h" // --------------------------------------------------------------------------- // definitions @@ -91,7 +91,9 @@ protected: IOHIDQueueInterface** m_ppQueue; //queue (if we want one) IOHIDElementCookie* m_pCookies; //cookies - const char* m_szName; //(product) name + wxString m_szProductName; //product name + int m_nProductId; //product id + int m_nManufacturerId; //manufacturer id mach_port_t m_pPort; }; diff --git a/samples/joytest/joytest.cpp b/samples/joytest/joytest.cpp index bb31b257a3..403ea91a8e 100644 --- a/samples/joytest/joytest.cpp +++ b/samples/joytest/joytest.cpp @@ -39,6 +39,7 @@ long ypos = -1; int winNumber = 1; +int nButtons = 0; // Initialise this in OnInit, not statically bool MyApp::OnInit() { @@ -85,7 +86,7 @@ bool MyApp::OnInit() #if wxUSE_STATUSBAR frame->CreateStatusBar(); - frame->SetStatusText(wxT("Ready...")); + frame->SetStatusText(wxString::Format(wxT("Device [%s] (PID:[%i] MID:[%i]) Ready... # of joysticks:[%i]"), stick.GetProductName().c_str(), stick.GetProductId(), stick.GetManufacturerId(), stick.GetNumberJoysticks())); #endif // wxUSE_STATUSBAR frame->CenterOnScreen(); @@ -105,6 +106,7 @@ MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size): wxScrolledWindow(parent, wxID_ANY, pos, size, wxSUNKEN_BORDER) { m_stick = new wxJoystick(wxJOYSTICK1); + nButtons = m_stick->GetNumberButtons(); m_stick->SetCapture(this, 10); } @@ -153,10 +155,18 @@ void MyCanvas::OnJoystickEvent(wxJoystickEvent& event) #if wxUSE_STATUSBAR wxString buf; if (event.ButtonDown()) - buf.Printf(_T("Joystick (%d, %d) Fire!"), pt.x, pt.y); + buf.Printf(_T("Joystick (%d, %d) #%i Fire!"), pt.x, pt.y, event.GetButtonChange()); else - buf.Printf(_T("Joystick (%d, %d)"), pt.x, pt.y); + buf.Printf(_T("Joystick (%d, %d) "), pt.x, pt.y); +/* + for(int i = 0; i < nButtons; ++i) + { + buf += wxString(wxT("[")) + + ((event.GetButtonState() & (1 << i)) ? wxT("Y") : wxT("N")) + wxString(wxT("]")); + } +*/ + frame->SetStatusText(buf); #endif // wxUSE_STATUSBAR diff --git a/src/mac/carbon/sound.cpp b/src/mac/carbon/sound.cpp index 93e36c103c..6533416d1f 100644 --- a/src/mac/carbon/sound.cpp +++ b/src/mac/carbon/sound.cpp @@ -422,8 +422,10 @@ bool wxSound::DoPlay(unsigned flags) const int nError; if ((nError = NativePathNameToFSSpec ((char*) m_sndname.c_str(), &sfFile, 0)) != noErr) { +/* wxLogSysError(wxString::Format(wxT("File:%s does not exist\nError:%i"), m_sndname.c_str(), nError)); +*/ return false; } #endif diff --git a/src/mac/corefoundation/hid.cpp b/src/mac/corefoundation/hid.cpp index 735895bbf5..75eec3cbc1 100644 --- a/src/mac/corefoundation/hid.cpp +++ b/src/mac/corefoundation/hid.cpp @@ -34,6 +34,7 @@ #include "wx/mac/corefoundation/hid.h" #include "wx/string.h" #include "wx/log.h" +#include "wx/mac/corefoundation/cfstring.h" // --------------------------------------------------------------------------- @@ -118,7 +119,7 @@ bool wxHIDDevice::Create (int nClass, int nType, int nDev) //Now get the maching services io_iterator_t pIterator; wxIOCHECK(IOServiceGetMatchingServices(m_pPort, pDictionary, &pIterator), "No Matching HID Services"); - wxASSERT(pIterator != 0); + wxASSERT_MSG(pIterator != 0, wxT("No devices found!")); //Now we iterate through them io_object_t pObject; @@ -133,11 +134,36 @@ bool wxHIDDevice::Create (int nClass, int nType, int nDev) //Just for sanity :) wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey))) == CFStringGetTypeID()); +/* + kIOHIDTransportKey; + kIOHIDVendorIDKey; + kIOHIDProductIDKey; + kIOHIDVersionNumberKey; + kIOHIDManufacturerKey; + kIOHIDSerialNumberKey; + if !kIOHIDLocationIDKey + kUSBDevicePropertyLocationID + kIOHIDPrimaryUsageKey +kIOHIDPrimaryUsagePageKey +idProduct +idVendor +USB Product Name +*/ //Get [product] name - m_szName = CFStringGetCStringPtr ( - (CFStringRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)), - CFStringGetSystemEncoding() - ); + m_szProductName = wxMacCFStringHolder( (CFStringRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)), false ).AsString(); + + CFNumberGetValue( + (CFNumberRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductIDKey)), + kCFNumberIntType, + &m_nProductId + ); + + + CFNumberGetValue( + (CFNumberRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDVendorIDKey)), + kCFNumberIntType, + &m_nManufacturerId + ); //Create the interface (good grief - long function names!) SInt32 nScore; @@ -164,8 +190,6 @@ bool wxHIDDevice::Create (int nClass, int nType, int nDev) // wxCFArray CookieArray = CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDElementKey)); BuildCookies(CookieArray); - if (m_ppQueue != NULL) - wxVERIFY((*m_ppQueue)->start(m_ppQueue) == S_OK); //cleanup CFRelease(pDictionary); @@ -215,7 +239,9 @@ int wxHIDDevice::GetCount (int nClass, int nType) //Now get the maching services io_iterator_t pIterator; wxIOCHECK(IOServiceGetMatchingServices(m_pPort, pDictionary, &pIterator), "No Matching HID Services"); - wxASSERT(pIterator != 0); + + if(pIterator == NULL) + return 0; //Now we iterate through them io_object_t pObject; diff --git a/src/mac/corefoundation/hidjoystick.cpp b/src/mac/corefoundation/hidjoystick.cpp index eacceb0507..780c1b5ca6 100644 --- a/src/mac/corefoundation/hidjoystick.cpp +++ b/src/mac/corefoundation/hidjoystick.cpp @@ -33,15 +33,15 @@ #include enum { - wxJS_AXIS_X = 41, + wxJS_AXIS_X = 40, wxJS_AXIS_Y, wxJS_AXIS_Z, wxJS_AXIS_RUDDER, wxJS_AXIS_U, wxJS_AXIS_V, - wxJS_AXIS_MAX = 32767, - wxJS_AXIS_MIN = -32767 + wxJS_AXIS_MAX = 255, //32767, + wxJS_AXIS_MIN = 0, //-32767 }; class wxHIDJoystick : public wxHIDDevice @@ -49,9 +49,11 @@ class wxHIDJoystick : public wxHIDDevice public: bool Create(int nWhich); virtual void BuildCookies(wxCFArray& Array); + void MakeCookies(wxCFArray& Array); IOHIDElementCookie* GetCookies() {return m_pCookies;} - IOHIDQueueInterface** GetQueue() {return m_ppQueue;} + + friend class wxJoystick; }; @@ -76,43 +78,63 @@ void wxHIDJoystick::BuildCookies(wxCFArray& Array) { Array = CFDictionaryGetValue((CFDictionaryRef)Array[0], CFSTR(kIOHIDElementKey)); InitCookies(50, true); + + memset(m_pCookies, 0, sizeof(*m_pCookies) * 50); + MakeCookies(Array); + +// for(int i = 0; i < 50; ++i) +// wxPrintf(wxT("\nVAL #%i:[%i]"), i, m_pCookies[i]); +}//end buildcookies + +void wxHIDJoystick::MakeCookies(wxCFArray& Array) +{ int i, nUsage, nPage; for (i = 0; i < Array.Count(); ++i) { - CFNumberGetValue( + const void* ref = CFDictionaryGetValue((CFDictionaryRef)Array[i], CFSTR(kIOHIDElementKey)); + +// wxPrintf(wxT("ELM\n")); + if (ref != NULL) + { + wxCFArray newarray(ref); + MakeCookies(newarray); + } + else + { + CFNumberGetValue( (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)), kCFNumberLongType, &nUsage); - CFNumberGetValue( + CFNumberGetValue( (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsagePageKey)), kCFNumberLongType, &nPage); - if (nPage == kHIDPage_Button && nUsage <= 40) - AddCookieInQueue(Array[i], nUsage ); - else if (nPage == kHIDPage_GenericDesktop) - { - switch(nUsage) + if (nPage == kHIDPage_Button && nUsage <= 40) + AddCookieInQueue(Array[i], nUsage-1 ); + else if (nPage == kHIDPage_GenericDesktop) { - case kHIDUsage_GD_X: - AddCookieInQueue(Array[i], wxJS_AXIS_X); - break; - case kHIDUsage_GD_Y: - AddCookieInQueue(Array[i], wxJS_AXIS_Y); - break; - case kHIDUsage_GD_Z: - AddCookieInQueue(Array[i], wxJS_AXIS_Z); - break; - default: - break; + switch(nUsage) + { + case kHIDUsage_GD_X: + AddCookieInQueue(Array[i], wxJS_AXIS_X); + break; + case kHIDUsage_GD_Y: + AddCookieInQueue(Array[i], wxJS_AXIS_Y); + break; + case kHIDUsage_GD_Z: + AddCookieInQueue(Array[i], wxJS_AXIS_Z); + break; + default: + break; + } } + else if (nPage == kHIDPage_Simulation && nUsage == kHIDUsage_Sim_Rudder) + AddCookieInQueue(Array[i], wxJS_AXIS_RUDDER ); } - else if (nPage == kHIDPage_Simulation && nUsage == kHIDUsage_Sim_Rudder) - AddCookieInQueue(Array[i], wxJS_AXIS_RUDDER ); } -}//end buildcookies - +} @@ -129,6 +151,107 @@ public: wxJoystickThread(wxHIDJoystick* hid, int joystick); void* Entry(); + static void 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; + +// wxMutexGuiEnter(); + ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(), + &hidevent, bogustime, 0); + // wxMutexGuiLeave(); + while ( ret != kIOReturnUnderrun ) + { + if (pThis->TestDestroy()) + break; + +// wxPrintf(wxT("ENTER\n")); + if(ret != kIOReturnSuccess) + { + wxLogSysError(wxString::Format(wxT("wxJoystick Error:[%i]"), ret)); + return; + } + + wxJoystickEvent wxevent; + + int nIndex = 0; + IOHIDElementCookie* pCookies = m_hid->GetCookies(); + while(nIndex < 50) + { + if(hidevent.elementCookie == pCookies[nIndex]) + break; + + ++nIndex; + } + if(nIndex == 50) + { + wxLogSysError(wxString::Format(wxT("wxJoystick Out Of Bounds Error"))); + break; + } + + 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); + +// wxPrintf(wxT("SEND\n")); + + if (pThis->m_catchwin) + pThis->m_catchwin->AddPendingEvent(wxevent); + + // wxMutexGuiEnter(); + ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(), + &hidevent, bogustime, 0); + // wxMutexGuiLeave(); + } + } + private: wxHIDJoystick* m_hid; int m_joystick; @@ -145,7 +268,7 @@ private: wxJoystickThread::wxJoystickThread(wxHIDJoystick* hid, int joystick) : m_hid(hid), m_joystick(joystick), - m_lastposition(wxDefaultPosition), + m_lastposition(127,127), m_buttons(0), m_catchwin(NULL), m_polling(0) @@ -170,12 +293,10 @@ void* wxJoystickThread::Entry() CFRunLoopRef pRL = CFRunLoopGetCurrent(); CFRunLoopAddSource(pRL, pRLSource, kCFRunLoopDefaultMode); -// wxJSVERIFY( (*m_hid->GetQueue())->start(m_hid->GetQueue()) == kIOReturnSuccess ); + wxJSVERIFY( (*m_hid->GetQueue())->start(m_hid->GetQueue()) == kIOReturnSuccess ); + wxJSVERIFY( (*m_hid->GetQueue())->setEventCallout(m_hid->GetQueue(), &wxJoystickThread::HIDCallback, this, this) == kIOReturnSuccess ); double dTime; - IOHIDEventStruct hidevent; - AbsoluteTime bogustime = {0,0}; - IOReturn ret; while(true) { @@ -187,78 +308,13 @@ void* wxJoystickThread::Entry() else dTime = 0.0001 * 10; // check at least every 10 msec in blocking case - CFRunLoopRunInMode(kCFRunLoopDefaultMode, dTime, m_polling); - - while ( (ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(), - &hidevent, bogustime, 0)) != kIOReturnUnderrun ) - { - if (TestDestroy()) - break; - - wxJSASSERT(ret == kIOReturnSuccess); - wxJoystickEvent wxevent; - - int nIndex = 0; - IOHIDElementCookie* pCookies = m_hid->GetCookies(); - while(nIndex < 50) - { - if(hidevent.elementCookie == pCookies[nIndex]) - break; - } - wxASSERT(nIndex != 50); - - if (nIndex < 40) - { - if (hidevent.value) - { - m_buttons |= (1 << nIndex); - wxevent.SetEventType(wxEVT_JOY_BUTTON_DOWN); - } - else - { - m_buttons &= ~(1 << nIndex); - wxevent.SetEventType(wxEVT_JOY_BUTTON_UP); - } - - wxevent.SetButtonChange(nIndex); - } - else if (nIndex == wxJS_AXIS_X) - { - m_lastposition.x = hidevent.value; - wxevent.SetEventType(wxEVT_JOY_MOVE); - m_axe[nIndex - 39] = hidevent.value; - } - else if (nIndex == wxJS_AXIS_Y) - { - m_lastposition.y = hidevent.value; - wxevent.SetEventType(wxEVT_JOY_MOVE); - m_axe[nIndex - 39] = hidevent.value; - } - else if (nIndex == wxJS_AXIS_Z) - { - wxevent.SetEventType(wxEVT_JOY_ZMOVE); - m_axe[nIndex - 39] = 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(m_joystick); - wxevent.SetButtonState(m_buttons); - wxevent.SetPosition(m_lastposition); - wxevent.SetZPosition(m_axe[3]); - wxevent.SetEventObject(m_catchwin); - - if (m_catchwin) - m_catchwin->AddPendingEvent(wxevent); - } + CFRunLoopRunInMode(kCFRunLoopDefaultMode, dTime, true); } + + wxJSASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) ); + CFRunLoopRemoveSource(pRL, pRLSource, kCFRunLoopDefaultMode); + CFRelease(pRLSource); + return NULL; } @@ -366,13 +422,13 @@ int wxJoystick::GetNumberJoysticks() const wxHIDDevice::GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad); } int wxJoystick::GetManufacturerId() const -{ return 0; } +{ return m_hid->m_nManufacturerId; } int wxJoystick::GetProductId() const -{ return 0; } +{ return m_hid->m_nProductId; } wxString wxJoystick::GetProductName() const -{ return wxT("unknown"); } +{ return m_hid->m_szProductName; } int wxJoystick::GetXMin() const { return wxJS_AXIS_MIN; }