00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "cxutils/joystick.h"
00041 #include <assert.h>
00042 #include <string.h>
00043 #include <math.h>
00044 #include <iostream>
00045 #include <iomanip>
00046
00047 #if defined (WIN32)
00048 #include <windows.h>
00049 #include <mmsystem.h>
00050 #else
00051 #include <sys/types.h>
00052 #include <fcntl.h>
00053 #include <string.h>
00054 #include <unistd.h>
00055 #include <linux/joystick.h>
00056 #include <stdio.h>
00057 #include <sys/ioctl.h>
00058 #endif
00059
00060 #include <map>
00061
00062 const short int JOYSTICK_X_AXIS = 0;
00063 const short int JOYSTICK_Y_AXIS = 1;
00064 const short int JOYSTICK_Z_AXIS = 2;
00065 const short int JOYSTICK_R_AXIS = 3;
00066 const short int JOYSTICK_U_AXIS = 4;
00067 const short int JOYSTICK_V_AXIS = 5;
00068 const short int JOYSTICK_POV_AXIS = 6;
00069 const short int JOYSTICK_POV_X_AXIS = 7;
00070 const short int JOYSTICK_POV_Y_AXIS = 8;
00071
00072
00073 using namespace std;
00074
00075 namespace CxUtils
00076 {
00084 class JoystickInterface
00085 {
00086 public:
00087 JoystickInterface()
00088 {
00089 #ifdef WIN32
00090 #else
00091 mJoyFD = 0;
00092 mJSCalibratorFlag = false;
00093 #endif
00094 }
00095 ~JoystickInterface()
00096 {
00097 #ifdef WIN32
00098 #else
00099 mJoyFD = 0;
00100 #endif
00101 }
00102 #ifdef WIN32
00103 JOYINFOEX mJoyInfoEx;
00104 #else
00105 int mJoyFD;
00106 struct js_event mJoystickEvent;
00107 bool mJSCalibratorFlag;
00108 std::map<int, int> mAxisMinimum;
00109 std::map<int, int> mAxisMaximum;
00110 std::map<int, int> mAxisCenter;
00111 #endif
00112 };
00113 }
00114
00115 using namespace CxUtils;
00116
00117
00123 Joystick::Joystick()
00124 {
00125 mpAxis = new int[9];
00126 assert(mpAxis);
00127 memset(mpAxis, 0, sizeof(int)*9);
00128 mButtons = 0;
00129 mID = 0;
00130 mUpdateFrequency = 25;
00131 mpJoyInterface = new JoystickInterface();
00132 mJoystickConnected = false;
00133 }
00134
00135
00141 Joystick::~Joystick()
00142 {
00143 Shutdown();
00144 if(mpAxis)
00145 {
00146 delete[] mpAxis;
00147 mpAxis = NULL;
00148 }
00149 if(mpJoyInterface)
00150 {
00151 delete ((JoystickInterface *)(mpJoyInterface));
00152 }
00153 }
00154
00155
00170 int Joystick::Initialize(const unsigned int num,
00171 const unsigned int freq,
00172 const std::string& calibrationFile)
00173 {
00174
00175 Shutdown();
00176
00177 JoystickInterface* joyInfo = (JoystickInterface*)(mpJoyInterface);
00178
00179
00180 if(num == AnyJoystick)
00181 {
00182 for(unsigned int i = 0; i <= 10; i++)
00183 {
00184 if(Initialize(i, freq, calibrationFile))
00185 {
00186 return 1;
00187 }
00188 }
00189 return 0;
00190 }
00191
00192
00193 if(freq == 0 || freq > 50)
00194 {
00195 return 0;
00196 }
00197
00198 #ifdef WIN32
00199
00200 joyInfo->mJoyInfoEx.dwSize = sizeof(JOYINFOEX);
00201 joyInfo->mJoyInfoEx.dwFlags = JOY_RETURNALL;
00202
00203 if(joyGetPosEx(num, &joyInfo->mJoyInfoEx) != JOYERR_NOERROR)
00204 {
00205 return 0;
00206 }
00207 mID = num;
00208
00209 #else
00210 char port[256];
00211
00212 sprintf(port, "/dev/js%d", num);
00213 joyInfo->mJoyFD = open(port, O_RDONLY);
00214 if(joyInfo->mJoyFD > 0)
00215 {
00216 mID = num;
00217 }
00218 else
00219 {
00220 sprintf(port, "/dev/input/js%d", num);
00221 joyInfo->mJoyFD = open(port, O_RDONLY);
00222 if(joyInfo->mJoyFD > 0)
00223 {
00224 mID = num;
00225 }
00226 }
00227
00228
00229 if(joyInfo->mJoyFD <= 0)
00230 {
00231 return 0;
00232 }
00233
00235 if(joyInfo->mJoyFD > 0 && calibrationFile.empty() == false)
00236 {
00237 char name[128];
00238 if (ioctl(joyInfo->mJoyFD, JSIOCGNAME(sizeof(name)), name) < 0)
00239 strncpy(name, "Unknown", sizeof(name));
00240
00241 FILE *instream = fopen(calibrationFile.c_str(),"r");
00242 if(instream)
00243 {
00244 char numButtons = 0;
00245
00246 ioctl(joyInfo->mJoyFD, JSIOCGBUTTONS, &numButtons);
00247
00248
00249 int numAxes = 0;
00250 ioctl(joyInfo->mJoyFD, JSIOCGAXES, &numAxes);;
00251
00252
00253 joyInfo->mJSCalibratorFlag = true;
00254
00255 char tmpline[1024];
00256 int axis=-1;
00258 while(fgets(tmpline,1024,instream)!=NULL)
00259 {
00260
00261 if(strstr(tmpline,"BeginAxis"))
00262 {
00263 axis++;
00264 }
00265 if(axis >= 0 && axis < numAxes)
00266 {
00267 if(strstr(tmpline," Minimum"))
00268 {
00269 joyInfo->mAxisMinimum[axis] = atoi(strstr(tmpline,"=") + 2);
00270
00271 }
00272 else if(strstr(tmpline," Center"))
00273 {
00274 joyInfo->mAxisCenter[axis] = atoi(strstr(tmpline,"=") + 2);
00275
00276 }
00277 else if(strstr(tmpline," Maximum"))
00278 {
00279 joyInfo->mAxisMaximum[axis] = atoi(strstr(tmpline,"=") + 2);
00280
00281 }
00282 }
00283 }
00284 fclose(instream);
00285 }
00286 else
00287 {
00288 joyInfo->mJSCalibratorFlag = false;
00289 joyInfo->mAxisMinimum.clear();
00290 joyInfo->mAxisMaximum.clear();
00291 joyInfo->mAxisCenter.clear();
00292 }
00293 }
00294
00295 if(mCallbackThread.CreateThread(&Joystick::CallbackThreadFunction, this) == 0)
00296 {
00297 Shutdown();
00298 return 0;
00299 }
00300
00301 #endif
00302
00303
00304 if(mJoystickThread.CreateThread(&Joystick::JoystickThreadFunction, this) == 1)
00305 {
00306 mJoystickConnected = true;
00307 return 1;
00308 }
00309
00310
00311 Shutdown();
00312
00313 return 0;
00314 }
00315
00316
00324 int Joystick::Shutdown()
00325 {
00326
00327 JoystickInterface* joyInfo = (JoystickInterface*)(mpJoyInterface);
00328
00329 #ifndef WIN32
00330 if(joyInfo->mJoyFD != 0)
00331 {
00332 close(joyInfo->mJoyFD);
00333 }
00334 mCallbackThread.StopThread();
00335 #endif
00336 mJoystickThread.StopThread();
00337
00338 mUpdateFrequency = 15;
00339 memset(mpAxis, 0, sizeof(int)*7);
00340 mButtons = 0;
00341 mID = 0;
00342 #ifdef WIN32
00343 #else
00344 joyInfo->mJoyFD = 0;
00345 #endif
00346 mJoystickConnected = false;
00347 return 1;
00348 }
00349
00350
00360 int Joystick::GetAxis(const short int axis) const
00361 {
00362 if(!IsConnected())
00363 return 0;
00364
00365 int result = 0;
00366 if(axis >= 0 && axis < 9)
00367 {
00368 mJoystickMutex.Lock();
00369 result = mpAxis[axis];
00370 mJoystickMutex.Unlock();
00371 }
00372
00373 return result;
00374 }
00375
00376
00386 int Joystick::GetPOV() const
00387 {
00388 int result = 0;
00389
00390 mJoystickMutex.Lock();
00391
00392 #ifdef WIN32
00393 result = mpAxis[JOYSTICK_POV_AXIS];
00394 if(result != PovOff)
00395 result /= 100;
00396 #else
00397 result = mpAxis[JOYSTICK_POV_AXIS];
00398 #endif
00399 mJoystickMutex.Unlock();
00400 return result;
00401 }
00402
00410 int Joystick::GetButtonNumber() const
00411 {
00412 int result = 0, buttons = 0;
00413
00414
00415 mJoystickMutex.Lock();
00416 buttons = mButtons;
00417 mJoystickMutex.Unlock();
00418
00419 int bnumber = 1;
00420 for(int i = 0; i < 32; i++)
00421 {
00422 if( (buttons&bnumber) > 0)
00423 {
00424 result = i + 1;
00425 break;
00426 }
00427
00428 bnumber <<= 1;
00429 }
00430
00431 return result;
00432 }
00433
00434
00446 int Joystick::RegisterCallback(JoystickCallback* cb)
00447 {
00448 if(!cb)
00449 return 0;
00450
00451 mJoyCallbackMutex.Lock();
00452
00453 Callback::Data cbData;
00454
00455 cbData.mpJoyCallback = cb;
00456 cbData.mpJoyFunc = NULL;
00457 cbData.mpJoyFuncArgs = NULL;
00458
00459 mCallbacks.push_back(cbData);
00460
00461 mJoyCallbackMutex.Unlock();
00462
00463 return 1;
00464 }
00465
00466
00480 int Joystick::RegisterCallback(void (*func)(const Joystick& jstick, void* args), void* args)
00481 {
00482 if(!func)
00483 return 0;
00484
00485 mJoyCallbackMutex.Lock();
00486
00487 Callback::Data cbData;
00488
00489 cbData.mpJoyCallback = NULL;
00490 cbData.mpJoyFunc = func;
00491 cbData.mpJoyFuncArgs = args;
00492
00493 mCallbacks.push_back(cbData);
00494
00495 mJoyCallbackMutex.Unlock();
00496
00497 return 1;
00498 }
00499
00500
00514 int Joystick::RegisterCallback(void (*func)(const unsigned int buttonNumber, const Joystick::Event type, void* args),
00515 void* args)
00516 {
00517 if(!func)
00518 return 0;
00519
00520 mJoyCallbackMutex.Lock();
00521
00522 Callback::Data cbData;
00523
00524 cbData.mpJoyCallback = NULL;
00525 cbData.mpJoyButtonFunc = func;
00526 cbData.mpJoyFuncArgs = args;
00527
00528 mCallbacks.push_back(cbData);
00529
00530 mJoyCallbackMutex.Unlock();
00531
00532 return 1;
00533 }
00534
00535
00541 void Joystick::ClearCallbacks()
00542 {
00543 mJoyCallbackMutex.Lock();
00544 mCallbacks.clear();
00545 mJoyCallbackMutex.Unlock();
00546 }
00547
00553 void Joystick::PrintJoystickInfo() const
00554 {
00555 cout << "ID: " << mID << " - ";
00556 for(int i = 0; i < 6; i++)
00557 {
00558 cout << Joystick::GetLetterFromAxis(i) << ":" << setw(4) << (int)GetAxisPercentage(i) << " ";
00559 }
00560 cout << "POV-X: " << GetAxisPercentage(PovX) << " ";
00561 cout << "POV-Y: " << GetAxisPercentage(PovY) << " ";
00562 cout << "B: " << GetButtonNumber() << endl;
00563 }
00564
00565
00576 bool Joystick::IsButtonPressed(const unsigned int num) const
00577 {
00578 bool result = false;
00579
00580 mJoystickMutex.Lock();
00581
00582 if(num == 0 && mButtons != 0)
00583 {
00584 result = true;
00585 }
00586 else
00587 {
00588 int x = 1;
00589 x <<= (num - 1);
00590 if( (x&mButtons) != 0 )
00591 {
00592 result = true;
00593 }
00594 }
00595 mJoystickMutex.Unlock();
00596
00597 return result;
00598 }
00599
00600
00606 bool Joystick::IsConnected() const
00607 {
00608 return mJoystickConnected;
00609 }
00610
00611
00622 double Joystick::GetAxisPercentage(const short int axis, const short int deadzone) const
00623 {
00624 int val = GetAxis(axis);
00625 double dead = ( abs(deadzone)*MaxAxisValue )/100.0;
00626 double perc = 0.0;
00627 if(dead > MaxAxisValue)
00628 dead = MaxAxisValue;
00629
00630 if(axis == POV || axis == PovX || axis == PovY)
00631 {
00632 return (double)val;
00633 }
00634
00635 perc = (abs(val) <= dead) ? 0.0 : ((abs(val) - dead)*100.0)/(MaxAxisValue - dead);
00636
00637 if(val < 0)
00638 perc *= -1.0;
00639
00640 if(perc > 100.0)
00641 perc = 100.0;
00642 else if(perc < -100.0)
00643 perc = -100.0;
00644
00645 return perc;
00646 }
00647
00648
00655 void Joystick::JoystickThreadFunction(void *args)
00656 {
00657 Joystick* joystick = (Joystick*)(args);
00658
00659 JoystickInterface* joyInfo = (JoystickInterface*)(joystick->mpJoyInterface);
00660
00661 std::vector<int> buttonsDown;
00662 std::vector<int> buttonsUp;
00663
00664 while(joystick &&
00665 joystick->mJoystickThread.QuitThreadFlag() == false)
00666 {
00667 buttonsDown.clear();
00668 buttonsUp.clear();
00669
00670 #if defined(WIN32)
00671
00672 unsigned int delay;
00673 delay = (unsigned int)(1000.0/(joystick->mUpdateFrequency + .000000000000000001));
00674 if(delay < 1)
00675 {
00676 delay = 1;
00677 }
00678 SleepMs(delay);
00679
00680 int prevButtons;
00681 joystick->mJoystickMutex.Lock();
00682
00683 prevButtons = joystick->mButtons;
00684
00685
00686 joyGetPosEx(joystick->mID, &joyInfo->mJoyInfoEx);
00687
00688
00689
00690
00691 joystick->mButtons = joyInfo->mJoyInfoEx.dwButtons;
00692
00693
00694 joystick->mpAxis[JOYSTICK_X_AXIS] = joyInfo->mJoyInfoEx.dwXpos - 32767;
00695 joystick->mpAxis[JOYSTICK_Y_AXIS] = joyInfo->mJoyInfoEx.dwYpos - 32767;
00696 joystick->mpAxis[JOYSTICK_Z_AXIS] = joyInfo->mJoyInfoEx.dwRpos - 32767;
00697 joystick->mpAxis[JOYSTICK_R_AXIS] = joyInfo->mJoyInfoEx.dwZpos - 32767;
00698 joystick->mpAxis[JOYSTICK_U_AXIS] = joyInfo->mJoyInfoEx.dwUpos - 32767;
00699 joystick->mpAxis[JOYSTICK_V_AXIS] = joyInfo->mJoyInfoEx.dwVpos - 32767;
00700 joystick->mpAxis[JOYSTICK_POV_AXIS] = joyInfo->mJoyInfoEx.dwPOV;
00701 if(joyInfo->mJoyInfoEx.dwPOV == PovOff)
00702 {
00703 joystick->mpAxis[PovX] = 0;
00704 joystick->mpAxis[PovY] = 0;
00705 }
00706 if(joyInfo->mJoyInfoEx.dwPOV == 0)
00707 {
00708 joystick->mpAxis[PovY] = 100;
00709 }
00710 if(joyInfo->mJoyInfoEx.dwPOV == 18000)
00711 {
00712 joystick->mpAxis[PovY] = -100;
00713 }
00714 if(joyInfo->mJoyInfoEx.dwPOV == 9000)
00715 {
00716 joystick->mpAxis[PovX] = 100;
00717 }
00718 if(joyInfo->mJoyInfoEx.dwPOV == 27000)
00719 {
00720 joystick->mpAxis[PovX] = -100;
00721 }
00722 if(joyInfo->mJoyInfoEx.dwPOV == 4500)
00723 {
00724 joystick->mpAxis[PovX] = 100;
00725 joystick->mpAxis[PovY] = 100;
00726 }
00727 if(joyInfo->mJoyInfoEx.dwPOV == 13500)
00728 {
00729 joystick->mpAxis[PovX] = 100;
00730 joystick->mpAxis[PovY] = -100;
00731 }
00732 if(joyInfo->mJoyInfoEx.dwPOV == 22500)
00733 {
00734 joystick->mpAxis[PovX] = -100;
00735 joystick->mpAxis[PovY] = -100;
00736 }
00737 if(joyInfo->mJoyInfoEx.dwPOV == 31500)
00738 {
00739 joystick->mpAxis[PovX] = -100;
00740 joystick->mpAxis[PovY] = 100;
00741 }
00742
00743
00744 for(unsigned int i = 0; i < MaxButtons; i++)
00745 {
00746 int mask = 1 << i;
00747
00748 if( (prevButtons&mask) == 0 && (joystick->mButtons&mask) > 0)
00749 {
00750 buttonsDown.push_back(i + 1);
00751 }
00752
00753 if( (prevButtons&mask) > 0 && (joystick->mButtons&mask) == 0)
00754 {
00755 buttonsUp.push_back(i + 1);
00756 }
00757 }
00758
00759 joystick->mJoystickMutex.Unlock();
00760
00761 #else
00762
00763
00764 if(read (joyInfo->mJoyFD, &joyInfo->mJoystickEvent, sizeof(struct js_event)) != -1)
00765 {
00766
00767
00768 if(joyInfo->mJoystickEvent.type == JS_EVENT_BUTTON)
00769 {
00770 joystick->mJoystickMutex.Lock();
00771
00772
00773 if(joyInfo->mJoystickEvent.value == 0)
00774 {
00775
00776
00777 joystick->mButtons &= ~(1 << joyInfo->mJoystickEvent.number);
00778 buttonsUp.push_back(joyInfo->mJoystickEvent.number + 1);
00779 }
00780 else
00781 {
00782
00783 joystick->mButtons |= 1 << joyInfo->mJoystickEvent.number;
00784 buttonsDown.push_back(joyInfo->mJoystickEvent.number + 1);
00785 }
00786
00787 joystick->mJoystickMutex.Unlock();
00788 }
00789 else if(joyInfo->mJoystickEvent.type == JS_EVENT_AXIS)
00790 {
00791 short int value;
00792 int axis = 0;
00793 value = joyInfo->mJoystickEvent.value;
00794 axis = joyInfo->mJoystickEvent.number;
00795 joystick->mJoystickMutex.Lock();
00796
00797 switch(axis)
00798 {
00799 case 0:
00800 case 1:
00801 case 2:
00802 case 3:
00803 if(joyInfo->mJSCalibratorFlag)
00804 {
00805 if(value < joyInfo->mAxisCenter[axis])
00806 {
00807 joystick->mpAxis[axis]=(short int)((MaxAxisValue*(double)(value - joyInfo->mAxisCenter[axis])/(double)(joyInfo->mAxisCenter[axis]-joyInfo->mAxisMinimum[axis])));
00808 }
00809 else
00810 {
00811 joystick->mpAxis[axis]=(short int)((MaxAxisValue*(double)(value - joyInfo->mAxisCenter[axis])/(double)(joyInfo->mAxisMaximum[axis]-joyInfo->mAxisCenter[axis])));
00812 }
00813 }
00814 else
00815 {
00816 joystick->mpAxis[axis] = value;
00817 }
00818 if(axis == 3)
00819 {
00820 if(value == 255)
00821 {
00822 joystick->mpAxis[axis] = 0;
00823 }
00824 joystick->mpAxis[axis] *= -1;
00825 joystick->mpAxis[axis] = (int)((joystick->mpAxis[axis] - MaxAxisValue/2.0)*MaxAxisValue/ (MaxAxisValue/2.0));
00826 }
00827 break;
00828 case 4:
00829 joystick->mpAxis[JOYSTICK_POV_X_AXIS] = value;
00830 break;
00831 case 5:
00832 joystick->mpAxis[JOYSTICK_POV_Y_AXIS] = value;
00833 break;
00834 case 6:
00835 joystick->mpAxis[JOYSTICK_U_AXIS] = value;
00836 break;
00837 case 7:
00838 joystick->mpAxis[JOYSTICK_V_AXIS] = value;
00839 default:
00840 break;
00841 }
00842
00843 double angle = atan2(-(double)joystick->mpAxis[JOYSTICK_POV_Y_AXIS] , (double)joystick->mpAxis[JOYSTICK_POV_X_AXIS]);
00844 angle = CX_RAD2DEG(angle);
00845 if(joystick->mpAxis[JOYSTICK_POV_X_AXIS] == 0 &&
00846 joystick->mpAxis[JOYSTICK_POV_Y_AXIS] == 0)
00847 {
00848 angle = PovOff;
00849 }
00850 joystick->mpAxis[JOYSTICK_POV_AXIS] = angle;
00851
00852 joystick->mJoystickMutex.Unlock();
00853 }
00854 }
00855
00856 #endif
00857
00858 #ifdef WIN32
00859
00860
00861 joystick->mJoyCallbackMutex.Lock();
00862 Callback::Data::List::iterator cb;
00863 for(cb = joystick->mCallbacks.begin();
00864 cb != joystick->mCallbacks.end();
00865 cb++)
00866 {
00867 if(cb->mpJoyCallback)
00868 {
00869 cb->mpJoyCallback->ProcessJoystickEvent(*joystick);
00870 for(unsigned int i = 0; i < (unsigned int)buttonsDown.size(); i++)
00871 {
00872 cb->mpJoyCallback->ProcessButtonEvent(buttonsDown[i], Joystick::ButtonDown);
00873 }
00874 for(unsigned int i = 0; i < (unsigned int)buttonsUp.size(); i++)
00875 {
00876 cb->mpJoyCallback->ProcessButtonEvent(buttonsUp[i], Joystick::ButtonUp);
00877 }
00878 }
00879 else if(cb->mpJoyFunc)
00880 {
00881 cb->mpJoyFunc(*joystick, cb->mpJoyFuncArgs);
00882 }
00883 else if(cb->mpJoyButtonFunc)
00884 {
00885 for(unsigned int i = 0; i < (unsigned int)buttonsDown.size(); i++)
00886 {
00887 cb->mpJoyButtonFunc(buttonsDown[i], Joystick::ButtonDown, cb->mpJoyFuncArgs);
00888 }
00889 for(unsigned int i = 0; i < (unsigned int)buttonsUp.size(); i++)
00890 {
00891 cb->mpJoyButtonFunc(buttonsUp[i], Joystick::ButtonUp, cb->mpJoyFuncArgs);
00892 }
00893 }
00894 }
00895 joystick->mJoyCallbackMutex.Unlock();
00896 #endif
00897 }
00898 }
00899
00900
00912 short int Joystick::GetAxisFromLetter(const char ch)
00913 {
00914 short int result = 0;
00915 switch(tolower(ch))
00916 {
00917 case 'x':
00918 result = JOYSTICK_X_AXIS;
00919 break;
00920 case 'y':
00921 result = JOYSTICK_Y_AXIS;
00922 break;
00923 case 'z':
00924 result = JOYSTICK_Z_AXIS;
00925 break;
00926 case 'r':
00927 result = JOYSTICK_R_AXIS;
00928 break;
00929 case 'u':
00930 result = JOYSTICK_U_AXIS;
00931 break;
00932 case 'v':
00933 result = JOYSTICK_V_AXIS;
00934 break;
00935 default:
00936 result = 0;
00937 break;
00938 };
00939
00940 return result;
00941 }
00942
00952 char Joystick::GetLetterFromAxis(const short int axis)
00953 {
00954 char result = 0;
00955 switch(axis)
00956 {
00957 case JOYSTICK_X_AXIS:
00958 result = 'X';
00959 break;
00960 case JOYSTICK_Y_AXIS:
00961 result = 'Y';
00962 break;
00963 case JOYSTICK_Z_AXIS:
00964 result = 'Z';
00965 break;
00966 case JOYSTICK_R_AXIS:
00967 result = 'R';
00968 break;
00969 case JOYSTICK_U_AXIS:
00970 result = 'U';
00971 break;
00972 case JOYSTICK_V_AXIS:
00973 result = 'V';
00974 break;
00975 default:
00976 result = 0;
00977 break;
00978 };
00979
00980 return result;
00981 }
00982
00983
00984 #ifndef WIN32
00985
00993 void Joystick::CallbackThreadFunction(void* args)
00994 {
00995 Joystick* joystick = (Joystick*)args;
00996 std::vector<int> buttonsDown;
00997 std::vector<int> buttonsUp;
00998 int prevButtons = 0;
00999 while(joystick && joystick->mCallbackThread.QuitThreadFlag() == false)
01000 {
01001 int curButtons;
01002
01003 joystick->mJoystickMutex.Lock();
01004 curButtons = joystick->mButtons;
01005 joystick->mJoystickMutex.Unlock();
01006
01007 buttonsDown.clear();
01008 buttonsUp.clear();
01009
01010
01011 for(unsigned int i = 0; i < MaxButtons; i++)
01012 {
01013 int mask = 1 << i;
01014
01015 if( (prevButtons&mask) == 0 && (curButtons&mask) > 0)
01016 {
01017 buttonsDown.push_back(i + 1);
01018 }
01019
01020 if( (prevButtons&mask) > 0 && (curButtons&mask) == 0)
01021 {
01022 buttonsUp.push_back(i + 1);
01023 }
01024 }
01025
01026 prevButtons = curButtons;
01027
01028 joystick->mJoyCallbackMutex.Lock();
01029 Callback::Data::List::iterator cb;
01030 for(cb = joystick->mCallbacks.begin();
01031 cb != joystick->mCallbacks.end();
01032 cb++)
01033 {
01034 if(cb->mpJoyCallback)
01035 {
01036 cb->mpJoyCallback->ProcessJoystickEvent(*joystick);
01037 for(unsigned int i = 0; i < (unsigned int)buttonsDown.size(); i++)
01038 {
01039 cb->mpJoyCallback->ProcessButtonEvent(buttonsDown[i], Joystick::ButtonDown);
01040 }
01041 for(unsigned int i = 0; i < (unsigned int)buttonsUp.size(); i++)
01042 {
01043 cb->mpJoyCallback->ProcessButtonEvent(buttonsUp[i], Joystick::ButtonUp);
01044 }
01045 }
01046 else if(cb->mpJoyFunc)
01047 {
01048 cb->mpJoyFunc(*joystick, cb->mpJoyFuncArgs);
01049 }
01050 else if(cb->mpJoyButtonFunc)
01051 {
01052 for(unsigned int i = 0; i < (unsigned int)buttonsDown.size(); i++)
01053 {
01054 cb->mpJoyButtonFunc(buttonsDown[i], Joystick::ButtonDown, cb->mpJoyFuncArgs);
01055 }
01056 for(unsigned int i = 0; i < (unsigned int)buttonsUp.size(); i++)
01057 {
01058 cb->mpJoyButtonFunc(buttonsUp[i], Joystick::ButtonUp, cb->mpJoyFuncArgs);
01059 }
01060 }
01061 }
01062 joystick->mJoyCallbackMutex.Unlock();
01063
01064 unsigned int delay;
01065 delay = (unsigned int)(1000.0/(joystick->mUpdateFrequency + .000000000000000001));
01066 if(delay < 1)
01067 {
01068 delay = 1;
01069 }
01070 SleepMs(delay);
01071 }
01072 }
01073
01074 #endif
01075
01076
01077