Angel 3.2
A 2D Game Prototyping Engine
Controller.cpp
1 
2 // Copyright (C) 2008-2013, Shane Liesegang
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of the copyright holder nor the names of any
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
29 
30 #include "stdafx.h"
31 #include "../Input/Controller.h"
32 
33 #include "../Input/InputManager.h"
34 #include "../Util/MathUtil.h"
35 
36 
37 
38  // Here are the definitions from XInput.h
39 #ifndef XINPUT_GAMEPAD_DPAD_UP
40  #define XINPUT_GAMEPAD_DPAD_UP 0x00000001
41  #define XINPUT_GAMEPAD_DPAD_DOWN 0x00000002
42  #define XINPUT_GAMEPAD_DPAD_LEFT 0x00000004
43  #define XINPUT_GAMEPAD_DPAD_RIGHT 0x00000008
44  #define XINPUT_GAMEPAD_START 0x00000010
45  #define XINPUT_GAMEPAD_BACK 0x00000020
46  #define XINPUT_GAMEPAD_LEFT_THUMB 0x00000040
47  #define XINPUT_GAMEPAD_RIGHT_THUMB 0x00000080
48  #define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
49  #define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
50  #define XINPUT_GAMEPAD_A 0x1000
51  #define XINPUT_GAMEPAD_B 0x2000
52  #define XINPUT_GAMEPAD_X 0x4000
53  #define XINPUT_GAMEPAD_Y 0x8000
54  #define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
55  #define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
56  #define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
57 #endif
58 
59 
60 /*
61  // The definitions sussed out from the Apple HID Utilities
62  Generic Desktop X - Left X - 0x1b
63  Generic Dekstop Y - Left Y - 0x1c
64  Generic Desktop Rx - Right X - 0x1d
65  Generic Desktop Ry - Right Y - 0x1e
66  Button #0x000C - Dpad Up - 0x0a
67  Button #0x000D - Dpad Down - 0x0b
68  Button #0x000E - Dpad Left - 0x0c
69  Button #0x000F - Dpad Right - 0x0d
70  Button #0x0009 - Start - 0x0e
71  Button #0x000A - Back - 0x0f
72  Button #0x0007 - L3 - 0x10
73  Button #0x0008 - R3 - 0x11
74  Button #0x0005 - Left Bumper - 0x12
75  Button #0x0006 - Right Bumper - 0x13
76  Button #0x000B - Xbox Button - 0x14
77  Button #0x0001 - A Button - 0x15
78  Button #0x0002 - B Button - 0x16
79  Button #0x0003 - X Button - 0x17
80  Button #0x0004 - Y Button - 0x18
81  Generic Desktop Z - Left Trigger - 0x19
82  Generic Desktop Rz - Right Trigger - 0x1a
83 */
84 
85 
86 ControllerManager* ControllerManager::s_ControllerManager = NULL;
87 
89 {
90  if (s_ControllerManager == NULL)
91  {
92  s_ControllerManager = new ControllerManager();
93  }
94  return *s_ControllerManager;
95 }
96 
97 ControllerManager::ControllerManager()
98 {
99  _controllers[0] = new Controller();
100  _controllers[0]->_controllerID = 0;
101 
102  _controllers[1] = new Controller();
103  _controllers[1]->_controllerID = 1;
104 }
105 
107 {
108  #if defined(__APPLE__)
109  HIDReleaseAllDeviceQueues();
110  HIDReleaseDeviceList();
111  #endif
112 }
113 
115 {
116  _controllers[0]->Setup();
117  _controllers[1]->Setup();
118 }
119 
121 {
122  _controllers[0]->UpdateState();
123  _controllers[1]->UpdateState();
124 }
125 
126 Controller* Controller::s_Controller = NULL;
127 
128 Controller::Controller()
129 {
130  _connected = false;
131  _currentLeftVibration = 0;
132  _currentRightVibration = 0;
133 
134  #if defined(__APPLE__)
135  _device = NULL;
136  #endif
137 }
138 
140 {
141  #if defined(WIN32)
142  ZeroMemory( &_currentControllerRawState, sizeof(XINPUT_STATE));
143 
144  _dwResult = XInputGetState(_controllerID, &_currentControllerRawState);
145 
146  if (_dwResult == ERROR_SUCCESS)
147  {
148  sysLog.Printf("Controller %d connected!", _controllerID+1);
149  _connected = true;
150  }
151  else
152  {
153  sysLog.Printf("Controller %d not present...", _controllerID+1);
154  ZeroMemory( &_currentControllerRawState, sizeof(XINPUT_STATE));
155  _currentControllerInput.LeftThumbstickX =
156  _currentControllerInput.LeftThumbstickY =
157  _currentControllerInput.RightThumbstickX =
158  _currentControllerInput.RightThumbstickY =
159  _currentControllerInput.LeftTriggerValue =
160  _currentControllerInput.RightTriggerValue =
161  _currentControllerInput.Buttons = 0;
162  _connected = false;
163  }
164 
165  #elif defined(__APPLE__)
166  unsigned long usagePage = 0;
167  unsigned long usage = 0;
168  if (!HIDHaveDeviceList())
169  {
170  HIDBuildDeviceList(usagePage, usage);
171  }
172 
173  _device = HIDGetFirstDevice();
174  while (_device != NULL)
175  {
176  //is this device already taken by another controller?
177  bool breakIt = false;
178  for (int i=0; i < MAX_CONTROLLERS; i++)
179  {
180  Controller* check = &theControllerManager.GetController(i);
181  if ((check != this) && (check->_device == _device))
182  {
183  _device = HIDGetNextDevice(_device);
184  if (_device == NULL)
185  {
186  breakIt = true;
187  }
188  }
189  }
190  if (breakIt)
191  {
192  break;
193  }
194 
195  std::string manufacturer = _device->manufacturer;
196  std::string product = _device->product;
197  if (manufacturer.length() > 0)
198  manufacturer = manufacturer.substr(1, manufacturer.length()-1).c_str(); //trimming off the initial copyright symbol so matching won't be dumb
199  if (
200  ((manufacturer == "Microsoft Corporation") && (product == "Controller"))
201  || ((manufacturer == "icrosoft") && (product == "Wireless 360 Controller"))
202  )
203  {
204  sysLog.Printf("Controller %d connected!", _controllerID+1);
205  _connected = true;
206  break;
207  }
208 
209  _device = HIDGetNextDevice(_device);
210  }
211  if (_device == NULL)
212  {
213  sysLog.Printf("Controller %d not present...", _controllerID+1);
214  _connected = false;
215  }
216  else
217  {
218  pRecElement current_element = HIDGetFirstDeviceElement(_device, kHIDElementTypeIO);
219  while (current_element != NULL)
220  {
221  _elements[(unsigned int)current_element->cookie] = current_element;
222  current_element = HIDGetNextDeviceElement(current_element, kHIDElementTypeIO);
223  }
224  }
225  #elif defined(__linux__)
226  char* devicePath;
227  if (_controllerID == 0)
228  devicePath = LINUX_CONTROLLER_1_PATH;
229  else
230  devicePath = LINUX_CONTROLLER_2_PATH;
231 
232  _deviceFD = open(devicePath, O_RDONLY | O_NONBLOCK);
233  if (_deviceFD < 0)
234  {
235  sysLog.Printf("Controller %d not present...", _controllerID+1);
236  _connected = false;
237  }
238  else
239  {
240  sysLog.Printf("Controller %d connected!", _controllerID+1);
241  _connected = true;
242  }
243 
244  // Discover the force feedback device.
245  bool foundFirstController = false;
246  _ffFD = -1;
247  for (int i = 0; i < MAX_LINUX_EVENT_INTERFACES; i++)
248  {
249  std::stringstream ss;
250  ss << i;
251  String eventDev = LINUX_EVENT_INTERFACE + ss.str();
252  int fd = open(eventDev.c_str(), O_RDWR);
253  if (fd >= 0)
254  {
255  char name[256] = "Unknown";
256  ioctl(fd, EVIOCGNAME(sizeof(name)), name);
257  if (strcmp(name, "Microsoft X-Box 360 pad") == 0)
258  {
259  if (_controllerID == 0)
260  {
261  _ffFD = fd;
262  break;
263  }
264  else
265  {
266  if (foundFirstController)
267  {
268  _ffFD = fd;
269  break;
270  }
271  else
272  {
273  foundFirstController = true;
274  close(fd);
275  }
276  }
277  }
278  else
279  {
280  close(fd);
281  }
282  }
283  }
284  if (_ffFD < 0)
285  {
286  sysLog.Printf("Error opening Force Feedback device for controller %d!", _controllerID+1);
287  }
288  else
289  {
290  _ffEffect.type = FF_RUMBLE;
291  _ffEffect.id = -1;
292  _ffEffect.u.rumble.strong_magnitude = 0;
293  _ffEffect.u.rumble.weak_magnitude = 0;
294  _ffEffect.replay.length = 0x7fff;
295  _ffEffect.replay.delay = 0;
296  _ffPlay.type = EV_FF;
297  _ffPlay.value = 1;
298  }
299  #endif
300 }
301 
303 {
304  if(!_connected)
305  {
306  return;
307  }
308  #if defined(WIN32)
309  _dwResult = XInputGetState(_controllerID, &_currentControllerRawState);
310 
311  // We either don't have a controller or the Input has failed. Keep clearing the input
312  // data so we don't get garbage input.
313  if (_dwResult != ERROR_SUCCESS)
314  {
315  if (_connected)
316  {
317  sysLog.Printf("Uh oh, we lost controller %d...", _controllerID+1);
318  }
319 
320  _connected = false;
321  ZeroMemory( &_currentControllerRawState, sizeof(XINPUT_STATE));
322  _currentControllerInput.LeftThumbstickX =
323  _currentControllerInput.LeftThumbstickY =
324  _currentControllerInput.RightThumbstickX =
325  _currentControllerInput.RightThumbstickY =
326  _currentControllerInput.LeftTriggerValue =
327  _currentControllerInput.RightTriggerValue =
328  _currentControllerInput.Buttons = 0;
329  return;
330  }
331 
332  _connected = true;
333 
334  _currentControllerInput.Buttons = _currentControllerRawState.Gamepad.wButtons;
335  //TODO: dpad
336  _currentControllerInput.LeftTriggerValue = (int)_currentControllerRawState.Gamepad.bLeftTrigger;
337  _currentControllerInput.RightTriggerValue = (int)_currentControllerRawState.Gamepad.bRightTrigger;
338  _currentControllerInput.LeftThumbstickX = _currentControllerRawState.Gamepad.sThumbLX;
339  _currentControllerInput.LeftThumbstickY = _currentControllerRawState.Gamepad.sThumbLY;
340  _currentControllerInput.RightThumbstickX = _currentControllerRawState.Gamepad.sThumbRX;
341  _currentControllerInput.RightThumbstickY = _currentControllerRawState.Gamepad.sThumbRY;
342 
343  #elif defined(__APPLE__)
344  _currentControllerInput.LeftThumbstickX = _getValueForCookie(0x1b);
345  _currentControllerInput.LeftThumbstickY = -_getValueForCookie(0x1c);
346  _currentControllerInput.RightThumbstickX = _getValueForCookie(0x1d);
347  _currentControllerInput.RightThumbstickY = -_getValueForCookie(0x1e);
348  _currentControllerInput.LeftTriggerValue = _getValueForCookie(0x19);
349  _currentControllerInput.RightTriggerValue = _getValueForCookie(0x1a);
350 
351  _currentControllerInput.Buttons = 0;
352  if (_getValueForCookie(0x0a))
353  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_DPAD_UP;
354  if (_getValueForCookie(0x0b))
355  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_DPAD_DOWN;
356  if (_getValueForCookie(0x0c))
357  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_DPAD_LEFT;
358  if (_getValueForCookie(0x0d))
359  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_DPAD_RIGHT;
360  if (_getValueForCookie(0x0e))
361  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_START;
362  if (_getValueForCookie(0x0f))
363  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_BACK;
364  if (_getValueForCookie(0x10))
365  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_LEFT_THUMB;
366  if (_getValueForCookie(0x11))
367  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_RIGHT_THUMB;
368  if (_getValueForCookie(0x12))
369  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_LEFT_SHOULDER;
370  if (_getValueForCookie(0x13))
371  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_RIGHT_SHOULDER;
372  if (_getValueForCookie(0x15))
373  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_A;
374  if (_getValueForCookie(0x16))
375  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_B;
376  if (_getValueForCookie(0x17))
377  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_X;
378  if (_getValueForCookie(0x18))
379  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_Y;
380 
381  #elif defined(__linux__)
382  struct js_event js;
383  while (read(_deviceFD, &js, sizeof(struct js_event)) == sizeof(struct js_event))
384  {
385  switch (js.type)
386  {
387  case JS_EVENT_BUTTON:
388  unsigned int currButton;
389  switch (js.number)
390  {
391  case 0:
392  currButton = XINPUT_GAMEPAD_A;
393  break;
394  case 1:
395  currButton = XINPUT_GAMEPAD_B;
396  break;
397  case 2:
398  currButton = XINPUT_GAMEPAD_X;
399  break;
400  case 3:
401  currButton = XINPUT_GAMEPAD_Y;
402  break;
403  case 4:
404  currButton = XINPUT_GAMEPAD_LEFT_SHOULDER;
405  break;
406  case 5:
407  currButton = XINPUT_GAMEPAD_RIGHT_SHOULDER;
408  break;
409  case 6:
410  currButton = XINPUT_GAMEPAD_START;
411  break;
412  case 7:
413  // Big 'X' button - not used.
414  continue;
415  case 8:
416  currButton = XINPUT_GAMEPAD_LEFT_THUMB;
417  break;
418  case 9:
419  currButton = XINPUT_GAMEPAD_RIGHT_THUMB;
420  break;
421  case 10:
422  currButton = XINPUT_GAMEPAD_BACK;
423  break;
424  default:
425  sysLog.Printf("Error! Unknown button press event received!\n");
426  continue;
427  }
428  if (js.value) // button pressed
429  _currentControllerInput.Buttons |= currButton;
430  else // button released
431  _currentControllerInput.Buttons &= ~currButton;
432  break;
433  case JS_EVENT_AXIS:
434  switch (js.number)
435  {
436  case 0:
437  _currentControllerInput.LeftThumbstickX = js.value;
438  break;
439  case 1:
440  _currentControllerInput.LeftThumbstickY = -js.value;
441  break;
442  case 2:
443  _currentControllerInput.LeftTriggerValue = js.value;
444  break;
445  case 3:
446  _currentControllerInput.RightThumbstickX = js.value;
447  break;
448  case 4:
449  _currentControllerInput.RightThumbstickY = -js.value;
450  break;
451  case 5:
452  _currentControllerInput.RightTriggerValue = js.value;
453  break;
454  case 6:
455  if (js.value == 0)
456  _currentControllerInput.Buttons &= ~(XINPUT_GAMEPAD_DPAD_LEFT & XINPUT_GAMEPAD_DPAD_RIGHT);
457  else if (js.value < 0)
458  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_DPAD_LEFT;
459  else
460  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_DPAD_RIGHT;
461  break;
462  case 7:
463  if (js.value == 0)
464  _currentControllerInput.Buttons &= ~(XINPUT_GAMEPAD_DPAD_UP & XINPUT_GAMEPAD_DPAD_DOWN);
465  else if (js.value < 0)
466  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_DPAD_UP;
467  else
468  _currentControllerInput.Buttons |= XINPUT_GAMEPAD_DPAD_DOWN;
469  break;
470  default:
471  sysLog.Printf("Error! Unknown axis event received!\n");
472  break;
473  }
474  break;
475  default:
476  break;
477  }
478  }
479  #endif
480 
481  //Using the built-in deadzone -- comment out if you don't like it
482  if (_currentControllerInput.LeftThumbstickX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
483  _currentControllerInput.LeftThumbstickX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
484  _currentControllerInput.LeftThumbstickY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
485  _currentControllerInput.LeftThumbstickY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
486  {
487  _currentControllerInput.LeftThumbstickX = 0;
488  _currentControllerInput.LeftThumbstickY = 0;
489  }
490  if (_currentControllerInput.RightThumbstickX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
491  _currentControllerInput.RightThumbstickX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
492  _currentControllerInput.RightThumbstickY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
493  _currentControllerInput.RightThumbstickY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
494  {
495  _currentControllerInput.RightThumbstickX = 0;
496  _currentControllerInput.RightThumbstickY = 0;
497  }
498 
499  theInput.HandleControl( *this );
500 }
501 
503 {
504  return _currentControllerInput;
505 }
506 
508 {
509  Vector2 forReturn;
510  forReturn.X = float(_currentControllerInput.LeftThumbstickX) / 32768.0f;
511  forReturn.Y = float(_currentControllerInput.LeftThumbstickY) / 32768.0f;
512  return forReturn;
513 }
514 
516 {
517  Vector2 forReturn;
518  forReturn.X = float(_currentControllerInput.RightThumbstickX) / 32768.0f;
519  forReturn.Y = float(_currentControllerInput.RightThumbstickY) / 32768.0f;
520  return forReturn;
521 }
522 
524 {
525  Vec2i forReturn;
526  forReturn.X = _currentControllerInput.LeftThumbstickX;
527  forReturn.Y = _currentControllerInput.LeftThumbstickY;
528  return forReturn;
529 }
531 {
532  Vec2i forReturn;
533  forReturn.X = _currentControllerInput.RightThumbstickX;
534  forReturn.Y = _currentControllerInput.RightThumbstickY;
535  return forReturn;
536 }
537 
539 {
540  return _currentControllerInput.RightTriggerValue;
541 }
542 
544 {
545  return _currentControllerInput.LeftTriggerValue;
546 }
547 
548 const bool Controller::IsButtonDown(int buttonMask)
549 {
550  return ((_currentControllerInput.Buttons & buttonMask) != 0);
551 }
552 
554 {
555  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_A)
556  {
557  return true;
558  }
559  else
560  {
561  return false;
562  }
563 }
564 
566 {
567  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_B)
568  {
569  return true;
570  }
571  else
572  {
573  return false;
574  }
575 }
576 
578 {
579  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_X)
580  {
581  return true;
582  }
583  else
584  {
585  return false;
586  }
587 }
588 
590 {
591  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_Y)
592  {
593  return true;
594  }
595  else
596  {
597  return false;
598  }
599 }
600 
602 {
603  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_LEFT_THUMB)
604  {
605  return true;
606  }
607  else
608  {
609  return false;
610  }
611 }
612 
614 {
615  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_RIGHT_THUMB)
616  {
617  return true;
618  }
619  else
620  {
621  return false;
622  }
623 }
624 
626 {
627  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_START)
628  {
629  return true;
630  }
631  else
632  {
633  return false;
634  }
635 }
636 
638 {
639  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_BACK)
640  {
641  return true;
642  }
643  else
644  {
645  return false;
646  }
647 }
648 
650 {
651  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_LEFT_SHOULDER)
652  {
653  return true;
654  }
655  else
656  {
657  return false;
658  }
659 }
660 
662 {
663  if(_currentControllerInput.Buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
664  {
665  return true;
666  }
667  else
668  {
669  return false;
670  }
671 }
672 
674 {
675  if (_currentControllerInput.LeftTriggerValue > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
676  {
677  return true;
678  }
679  else
680  {
681  return false;
682  }
683 }
684 
686 {
687  if (_currentControllerInput.RightTriggerValue > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
688  {
689  return true;
690  }
691  else
692  {
693  return false;
694  }
695 }
696 
697 
698 const unsigned int Controller::GetLeftVibration()
699 {
700  return _currentLeftVibration;
701 }
702 
703 const unsigned int Controller::GetRightVibration()
704 {
705  return _currentRightVibration;
706 }
707 
708 void Controller::SetLeftVibrationRaw(unsigned int newVibration)
709 {
710 #if defined(WIN32)
711  XINPUT_VIBRATION vibration;
712  ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION));
713  vibration.wLeftMotorSpeed = _currentLeftVibration = newVibration;
714  vibration.wRightMotorSpeed = _currentRightVibration;
715  XInputSetState(0, &vibration);
716 #elif defined(__APPLE__)
717  newVibration = 0;
718 #elif defined(__linux__)
719  _ffEffect.u.rumble.strong_magnitude = _currentLeftVibration = newVibration;
720  _ffEffect.u.rumble.weak_magnitude = _currentRightVibration;
721  if (ioctl(_ffFD, EVIOCSFF, &_ffEffect) == -1)
722  {
723  sysLog.Printf("Error writing force feedback effect!");
724  return;
725  }
726  _ffPlay.code = _ffEffect.id;
727  if (write(_ffFD, &_ffPlay, sizeof(_ffPlay)) == -1)
728  {
729  sysLog.Printf("Error playing force feedback effect!");
730  }
731 #endif
732 }
733 
734 void Controller::SetRightVibrationRaw(unsigned int newVibration)
735 {
736 #if defined(WIN32)
737  XINPUT_VIBRATION vibration;
738  ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION));
739  vibration.wLeftMotorSpeed = _currentLeftVibration;
740  vibration.wRightMotorSpeed = _currentRightVibration = newVibration;
741  XInputSetState(0, &vibration);
742 #elif defined(__APPLE__)
743  newVibration = 0;
744 #elif defined(__linux__)
745  _ffEffect.u.rumble.strong_magnitude = _currentLeftVibration;
746  _ffEffect.u.rumble.weak_magnitude = _currentRightVibration = newVibration;
747  if (ioctl(_ffFD, EVIOCSFF, &_ffEffect) == -1)
748  {
749  sysLog.Printf("Error writing force feedback effect!");
750  return;
751  }
752  _ffPlay.code = _ffEffect.id;
753  if (write(_ffFD, &_ffPlay, sizeof(_ffPlay)) == -1)
754  {
755  sysLog.Printf("Error playing force feedback effect!");
756  }
757 #endif
758 }
759 
760 void Controller::SetLeftVibration(unsigned int newVibration)
761 {
762  newVibration = MathUtil::Clamp(newVibration, 0, 255);
763  if (newVibration == 255)
764  {
765  SetLeftVibrationRaw(65535);
766  }
767  else
768  {
769  SetLeftVibrationRaw(newVibration << 8);
770  }
771 }
772 
773 void Controller::SetRightVibration(unsigned int newVibration)
774 {
775  newVibration = MathUtil::Clamp(newVibration, 0, 255);
776  if (newVibration == 255)
777  {
778  SetRightVibrationRaw(65535);
779  }
780  else
781  {
782  SetRightVibrationRaw(newVibration << 8);
783  }
784 }