SDL  2.0
SDL_dinputhaptic.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #include "SDL_error.h"
24 #include "SDL_haptic.h"
25 #include "../SDL_syshaptic.h"
26 
27 #if SDL_HAPTIC_DINPUT
28 
29 #include "SDL_stdinc.h"
30 #include "SDL_timer.h"
31 #include "SDL_windowshaptic_c.h"
32 #include "SDL_dinputhaptic_c.h"
33 #include "../../joystick/windows/SDL_windowsjoystick_c.h"
34 
35 /*
36  * External stuff.
37  */
38 extern HWND SDL_HelperWindow;
39 
40 
41 /*
42  * Internal stuff.
43  */
44 static SDL_bool coinitialized = SDL_FALSE;
45 static LPDIRECTINPUT8 dinput = NULL;
46 
47 
48 /*
49  * Like SDL_SetError but for DX error codes.
50  */
51 static int
52 DI_SetError(const char *str, HRESULT err)
53 {
54  /*
55  SDL_SetError("Haptic: %s - %s: %s", str,
56  DXGetErrorString8A(err), DXGetErrorDescription8A(err));
57  */
58  return SDL_SetError("Haptic error %s", str);
59 }
60 
61 /*
62  * Checks to see if two GUID are the same.
63  */
64 static int
65 DI_GUIDIsSame(const GUID * a, const GUID * b)
66 {
67  return (SDL_memcmp(a, b, sizeof (GUID)) == 0);
68 }
69 
70 /*
71  * Callback to find the haptic devices.
72  */
73 static BOOL CALLBACK
74 EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
75 {
76  (void) pContext;
77  SDL_DINPUT_MaybeAddDevice(pdidInstance);
78  return DIENUM_CONTINUE; /* continue enumerating */
79 }
80 
81 int
83 {
84  HRESULT ret;
85  HINSTANCE instance;
86 
87  if (dinput != NULL) { /* Already open. */
88  return SDL_SetError("Haptic: SubSystem already open.");
89  }
90 
91  ret = WIN_CoInitialize();
92  if (FAILED(ret)) {
93  return DI_SetError("Coinitialize", ret);
94  }
95 
96  coinitialized = SDL_TRUE;
97 
98  ret = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
99  &IID_IDirectInput8, (LPVOID)& dinput);
100  if (FAILED(ret)) {
102  return DI_SetError("CoCreateInstance", ret);
103  }
104 
105  /* Because we used CoCreateInstance, we need to Initialize it, first. */
106  instance = GetModuleHandle(NULL);
107  if (instance == NULL) {
109  return SDL_SetError("GetModuleHandle() failed with error code %lu.",
110  GetLastError());
111  }
112  ret = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
113  if (FAILED(ret)) {
115  return DI_SetError("Initializing DirectInput device", ret);
116  }
117 
118  /* Look for haptic devices. */
119  ret = IDirectInput8_EnumDevices(dinput,
120  0,
121  EnumHapticsCallback,
122  NULL,
123  DIEDFL_FORCEFEEDBACK |
124  DIEDFL_ATTACHEDONLY);
125  if (FAILED(ret)) {
127  return DI_SetError("Enumerating DirectInput devices", ret);
128  }
129  return 0;
130 }
131 
132 int
133 SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
134 {
135  HRESULT ret;
136  LPDIRECTINPUTDEVICE8 device;
137  const DWORD needflags = DIDC_ATTACHED | DIDC_FORCEFEEDBACK;
138  DIDEVCAPS capabilities;
139  SDL_hapticlist_item *item = NULL;
140 
141  if (dinput == NULL) {
142  return -1; /* not initialized. We'll pick these up on enumeration if we init later. */
143  }
144 
145  /* Make sure we don't already have it */
146  for (item = SDL_hapticlist; item; item = item->next) {
147  if ((!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0)) {
148  return -1; /* Already added */
149  }
150  }
151 
152  /* Open the device */
153  ret = IDirectInput8_CreateDevice(dinput, &pdidInstance->guidInstance, &device, NULL);
154  if (FAILED(ret)) {
155  /* DI_SetError("Creating DirectInput device",ret); */
156  return -1;
157  }
158 
159  /* Get capabilities. */
160  SDL_zero(capabilities);
161  capabilities.dwSize = sizeof(DIDEVCAPS);
162  ret = IDirectInputDevice8_GetCapabilities(device, &capabilities);
163  IDirectInputDevice8_Release(device);
164  if (FAILED(ret)) {
165  /* DI_SetError("Getting device capabilities",ret); */
166  return -1;
167  }
168 
169  if ((capabilities.dwFlags & needflags) != needflags) {
170  return -1; /* not a device we can use. */
171  }
172 
173  item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item));
174  if (item == NULL) {
175  return SDL_OutOfMemory();
176  }
177 
178  item->name = WIN_StringToUTF8(pdidInstance->tszProductName);
179  if (!item->name) {
180  SDL_free(item);
181  return -1;
182  }
183 
184  /* Copy the instance over, useful for creating devices. */
185  SDL_memcpy(&item->instance, pdidInstance, sizeof(DIDEVICEINSTANCE));
186  SDL_memcpy(&item->capabilities, &capabilities, sizeof(capabilities));
187 
188  return SDL_SYS_AddHapticDevice(item);
189 }
190 
191 int
193 {
194  SDL_hapticlist_item *item;
195  SDL_hapticlist_item *prev = NULL;
196 
197  if (dinput == NULL) {
198  return -1; /* not initialized, ignore this. */
199  }
200 
201  for (item = SDL_hapticlist; item != NULL; item = item->next) {
202  if (!item->bXInputHaptic && SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) {
203  /* found it, remove it. */
204  return SDL_SYS_RemoveHapticDevice(prev, item);
205  }
206  prev = item;
207  }
208  return -1;
209 }
210 
211 /*
212  * Callback to get supported axes.
213  */
214 static BOOL CALLBACK
215 DI_DeviceObjectCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
216 {
217  SDL_Haptic *haptic = (SDL_Haptic *) pvRef;
218 
219  if ((dev->dwType & DIDFT_AXIS) && (dev->dwFlags & DIDOI_FFACTUATOR)) {
220  const GUID *guid = &dev->guidType;
221  DWORD offset = 0;
222  if (DI_GUIDIsSame(guid, &GUID_XAxis)) {
223  offset = DIJOFS_X;
224  } else if (DI_GUIDIsSame(guid, &GUID_YAxis)) {
225  offset = DIJOFS_Y;
226  } else if (DI_GUIDIsSame(guid, &GUID_ZAxis)) {
227  offset = DIJOFS_Z;
228  } else if (DI_GUIDIsSame(guid, &GUID_RxAxis)) {
229  offset = DIJOFS_RX;
230  } else if (DI_GUIDIsSame(guid, &GUID_RyAxis)) {
231  offset = DIJOFS_RY;
232  } else if (DI_GUIDIsSame(guid, &GUID_RzAxis)) {
233  offset = DIJOFS_RZ;
234  } else {
235  return DIENUM_CONTINUE; /* can't use this, go on. */
236  }
237 
238  haptic->hwdata->axes[haptic->naxes] = offset;
239  haptic->naxes++;
240 
241  /* Currently using the artificial limit of 3 axes. */
242  if (haptic->naxes >= 3) {
243  return DIENUM_STOP;
244  }
245  }
246 
247  return DIENUM_CONTINUE;
248 }
249 
250 /*
251  * Callback to get all supported effects.
252  */
253 #define EFFECT_TEST(e,s) \
254 if (DI_GUIDIsSame(&pei->guid, &(e))) \
255  haptic->supported |= (s)
256 static BOOL CALLBACK
257 DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
258 {
259  /* Prepare the haptic device. */
260  SDL_Haptic *haptic = (SDL_Haptic *) pv;
261 
262  /* Get supported. */
263  EFFECT_TEST(GUID_Spring, SDL_HAPTIC_SPRING);
264  EFFECT_TEST(GUID_Damper, SDL_HAPTIC_DAMPER);
265  EFFECT_TEST(GUID_Inertia, SDL_HAPTIC_INERTIA);
266  EFFECT_TEST(GUID_Friction, SDL_HAPTIC_FRICTION);
267  EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
268  EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
269  EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
270  /* !!! FIXME: put this back when we have more bits in 2.1 */
271  /* EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE); */
272  EFFECT_TEST(GUID_Triangle, SDL_HAPTIC_TRIANGLE);
273  EFFECT_TEST(GUID_SawtoothUp, SDL_HAPTIC_SAWTOOTHUP);
274  EFFECT_TEST(GUID_SawtoothDown, SDL_HAPTIC_SAWTOOTHDOWN);
275  EFFECT_TEST(GUID_RampForce, SDL_HAPTIC_RAMP);
276 
277  /* Check for more. */
278  return DIENUM_CONTINUE;
279 }
280 
281 /*
282  * Opens the haptic device.
283  *
284  * Steps:
285  * - Set cooperative level.
286  * - Set data format.
287  * - Acquire exclusiveness.
288  * - Reset actuators.
289  * - Get supported features.
290  */
291 static int
292 SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic * haptic, LPDIRECTINPUTDEVICE8 device8, SDL_bool is_joystick)
293 {
294  HRESULT ret;
295  DIPROPDWORD dipdw;
296 
297  /* Allocate the hwdata */
298  haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata));
299  if (haptic->hwdata == NULL) {
300  return SDL_OutOfMemory();
301  }
302  SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
303 
304  /* We'll use the device8 from now on. */
305  haptic->hwdata->device = device8;
306  haptic->hwdata->is_joystick = is_joystick;
307 
308  /* !!! FIXME: opening a haptic device here first will make an attempt to
309  !!! FIXME: SDL_JoystickOpen() that same device fail later, since we
310  !!! FIXME: have it open in exclusive mode. But this will allow
311  !!! FIXME: SDL_JoystickOpen() followed by SDL_HapticOpenFromJoystick()
312  !!! FIXME: to work, and that's probably the common case. Still,
313  !!! FIXME: ideally, We need to unify the opening code. */
314 
315  if (!is_joystick) { /* if is_joystick, we already set this up elsewhere. */
316  /* Grab it exclusively to use force feedback stuff. */
317  ret = IDirectInputDevice8_SetCooperativeLevel(haptic->hwdata->device,
318  SDL_HelperWindow,
319  DISCL_EXCLUSIVE |
320  DISCL_BACKGROUND);
321  if (FAILED(ret)) {
322  DI_SetError("Setting cooperative level to exclusive", ret);
323  goto acquire_err;
324  }
325 
326  /* Set data format. */
327  ret = IDirectInputDevice8_SetDataFormat(haptic->hwdata->device,
328  &SDL_c_dfDIJoystick2);
329  if (FAILED(ret)) {
330  DI_SetError("Setting data format", ret);
331  goto acquire_err;
332  }
333 
334 
335  /* Acquire the device. */
336  ret = IDirectInputDevice8_Acquire(haptic->hwdata->device);
337  if (FAILED(ret)) {
338  DI_SetError("Acquiring DirectInput device", ret);
339  goto acquire_err;
340  }
341  }
342 
343  /* Get number of axes. */
344  ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
345  DI_DeviceObjectCallback,
346  haptic, DIDFT_AXIS);
347  if (FAILED(ret)) {
348  DI_SetError("Getting device axes", ret);
349  goto acquire_err;
350  }
351 
352  /* Reset all actuators - just in case. */
353  ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
354  DISFFC_RESET);
355  if (FAILED(ret)) {
356  DI_SetError("Resetting device", ret);
357  goto acquire_err;
358  }
359 
360  /* Enabling actuators. */
361  ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
362  DISFFC_SETACTUATORSON);
363  if (FAILED(ret)) {
364  DI_SetError("Enabling actuators", ret);
365  goto acquire_err;
366  }
367 
368  /* Get supported effects. */
369  ret = IDirectInputDevice8_EnumEffects(haptic->hwdata->device,
370  DI_EffectCallback, haptic,
371  DIEFT_ALL);
372  if (FAILED(ret)) {
373  DI_SetError("Enumerating supported effects", ret);
374  goto acquire_err;
375  }
376  if (haptic->supported == 0) { /* Error since device supports nothing. */
377  SDL_SetError("Haptic: Internal error on finding supported effects.");
378  goto acquire_err;
379  }
380 
381  /* Check autogain and autocenter. */
382  dipdw.diph.dwSize = sizeof(DIPROPDWORD);
383  dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
384  dipdw.diph.dwObj = 0;
385  dipdw.diph.dwHow = DIPH_DEVICE;
386  dipdw.dwData = 10000;
387  ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
388  DIPROP_FFGAIN, &dipdw.diph);
389  if (!FAILED(ret)) { /* Gain is supported. */
390  haptic->supported |= SDL_HAPTIC_GAIN;
391  }
392  dipdw.diph.dwObj = 0;
393  dipdw.diph.dwHow = DIPH_DEVICE;
394  dipdw.dwData = DIPROPAUTOCENTER_OFF;
395  ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
396  DIPROP_AUTOCENTER, &dipdw.diph);
397  if (!FAILED(ret)) { /* Autocenter is supported. */
398  haptic->supported |= SDL_HAPTIC_AUTOCENTER;
399  }
400 
401  /* Status is always supported. */
402  haptic->supported |= SDL_HAPTIC_STATUS | SDL_HAPTIC_PAUSE;
403 
404  /* Check maximum effects. */
405  haptic->neffects = 128; /* This is not actually supported as thus under windows,
406  there is no way to tell the number of EFFECTS that a
407  device can hold, so we'll just use a "random" number
408  instead and put warnings in SDL_haptic.h */
409  haptic->nplaying = 128; /* Even more impossible to get this then neffects. */
410 
411  /* Prepare effects memory. */
412  haptic->effects = (struct haptic_effect *)
413  SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
414  if (haptic->effects == NULL) {
415  SDL_OutOfMemory();
416  goto acquire_err;
417  }
418  /* Clear the memory */
419  SDL_memset(haptic->effects, 0,
420  sizeof(struct haptic_effect) * haptic->neffects);
421 
422  return 0;
423 
424  /* Error handling */
425  acquire_err:
426  IDirectInputDevice8_Unacquire(haptic->hwdata->device);
427  return -1;
428 }
429 
430 int
431 SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
432 {
433  HRESULT ret;
434  LPDIRECTINPUTDEVICE8 device;
435  LPDIRECTINPUTDEVICE8 device8;
436 
437  /* Open the device */
438  ret = IDirectInput8_CreateDevice(dinput, &item->instance.guidInstance,
439  &device, NULL);
440  if (FAILED(ret)) {
441  DI_SetError("Creating DirectInput device", ret);
442  return -1;
443  }
444 
445  /* Now get the IDirectInputDevice8 interface, instead. */
446  ret = IDirectInputDevice8_QueryInterface(device,
447  &IID_IDirectInputDevice8,
448  (LPVOID *)&device8);
449  /* Done with the temporary one now. */
450  IDirectInputDevice8_Release(device);
451  if (FAILED(ret)) {
452  DI_SetError("Querying DirectInput interface", ret);
453  return -1;
454  }
455 
456  if (SDL_DINPUT_HapticOpenFromDevice(haptic, device8, SDL_FALSE) < 0) {
457  IDirectInputDevice8_Release(device8);
458  return -1;
459  }
460  return 0;
461 }
462 
463 int
464 SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
465 {
466  HRESULT ret;
467  DIDEVICEINSTANCE hap_instance, joy_instance;
468 
469  hap_instance.dwSize = sizeof(DIDEVICEINSTANCE);
470  joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
471 
472  /* Get the device instances. */
473  ret = IDirectInputDevice8_GetDeviceInfo(haptic->hwdata->device,
474  &hap_instance);
475  if (FAILED(ret)) {
476  return 0;
477  }
478  ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice,
479  &joy_instance);
480  if (FAILED(ret)) {
481  return 0;
482  }
483 
484  return DI_GUIDIsSame(&hap_instance.guidInstance, &joy_instance.guidInstance);
485 }
486 
487 int
488 SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
489 {
490  SDL_hapticlist_item *item;
491  int index = 0;
492  HRESULT ret;
493  DIDEVICEINSTANCE joy_instance;
494 
495  joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
496  ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice, &joy_instance);
497  if (FAILED(ret)) {
498  return -1;
499  }
500 
501  /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
502  for (item = SDL_hapticlist; item != NULL; item = item->next) {
503  if (!item->bXInputHaptic && DI_GUIDIsSame(&item->instance.guidInstance, &joy_instance.guidInstance)) {
504  haptic->index = index;
505  return SDL_DINPUT_HapticOpenFromDevice(haptic, joystick->hwdata->InputDevice, SDL_TRUE);
506  }
507  ++index;
508  }
509 
510  SDL_SetError("Couldn't find joystick in haptic device list");
511  return -1;
512 }
513 
514 void
515 SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
516 {
517  IDirectInputDevice8_Unacquire(haptic->hwdata->device);
518 
519  /* Only release if isn't grabbed by a joystick. */
520  if (haptic->hwdata->is_joystick == 0) {
521  IDirectInputDevice8_Release(haptic->hwdata->device);
522  }
523 }
524 
525 void
527 {
528  if (dinput != NULL) {
529  IDirectInput8_Release(dinput);
530  dinput = NULL;
531  }
532 
533  if (coinitialized) {
535  coinitialized = SDL_FALSE;
536  }
537 }
538 
539 /*
540  * Converts an SDL trigger button to an DIEFFECT trigger button.
541  */
542 static DWORD
543 DIGetTriggerButton(Uint16 button)
544 {
545  DWORD dwTriggerButton;
546 
547  dwTriggerButton = DIEB_NOTRIGGER;
548 
549  if (button != 0) {
550  dwTriggerButton = DIJOFS_BUTTON(button - 1);
551  }
552 
553  return dwTriggerButton;
554 }
555 
556 
557 /*
558  * Sets the direction.
559  */
560 static int
561 SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir, int naxes)
562 {
563  LONG *rglDir;
564 
565  /* Handle no axes a part. */
566  if (naxes == 0) {
567  effect->dwFlags |= DIEFF_SPHERICAL; /* Set as default. */
568  effect->rglDirection = NULL;
569  return 0;
570  }
571 
572  /* Has axes. */
573  rglDir = SDL_malloc(sizeof(LONG) * naxes);
574  if (rglDir == NULL) {
575  return SDL_OutOfMemory();
576  }
577  SDL_memset(rglDir, 0, sizeof(LONG) * naxes);
578  effect->rglDirection = rglDir;
579 
580  switch (dir->type) {
581  case SDL_HAPTIC_POLAR:
582  effect->dwFlags |= DIEFF_POLAR;
583  rglDir[0] = dir->dir[0];
584  return 0;
586  effect->dwFlags |= DIEFF_CARTESIAN;
587  rglDir[0] = dir->dir[0];
588  if (naxes > 1)
589  rglDir[1] = dir->dir[1];
590  if (naxes > 2)
591  rglDir[2] = dir->dir[2];
592  return 0;
594  effect->dwFlags |= DIEFF_SPHERICAL;
595  rglDir[0] = dir->dir[0];
596  if (naxes > 1)
597  rglDir[1] = dir->dir[1];
598  if (naxes > 2)
599  rglDir[2] = dir->dir[2];
600  return 0;
601 
602  default:
603  return SDL_SetError("Haptic: Unknown direction type.");
604  }
605 }
606 
607 /* Clamps and converts. */
608 #define CCONVERT(x) (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
609 /* Just converts. */
610 #define CONVERT(x) (((x)*10000) / 0x7FFF)
611 /*
612  * Creates the DIEFFECT from a SDL_HapticEffect.
613  */
614 static int
615 SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
617 {
618  int i;
619  DICONSTANTFORCE *constant;
620  DIPERIODIC *periodic;
621  DICONDITION *condition; /* Actually an array of conditions - one per axis. */
622  DIRAMPFORCE *ramp;
623  DICUSTOMFORCE *custom;
624  DIENVELOPE *envelope;
625  SDL_HapticConstant *hap_constant;
626  SDL_HapticPeriodic *hap_periodic;
627  SDL_HapticCondition *hap_condition;
628  SDL_HapticRamp *hap_ramp;
629  SDL_HapticCustom *hap_custom;
630  DWORD *axes;
631 
632  /* Set global stuff. */
633  SDL_memset(dest, 0, sizeof(DIEFFECT));
634  dest->dwSize = sizeof(DIEFFECT); /* Set the structure size. */
635  dest->dwSamplePeriod = 0; /* Not used by us. */
636  dest->dwGain = 10000; /* Gain is set globally, not locally. */
637  dest->dwFlags = DIEFF_OBJECTOFFSETS; /* Seems obligatory. */
638 
639  /* Envelope. */
640  envelope = SDL_malloc(sizeof(DIENVELOPE));
641  if (envelope == NULL) {
642  return SDL_OutOfMemory();
643  }
644  SDL_memset(envelope, 0, sizeof(DIENVELOPE));
645  dest->lpEnvelope = envelope;
646  envelope->dwSize = sizeof(DIENVELOPE); /* Always should be this. */
647 
648  /* Axes. */
649  dest->cAxes = haptic->naxes;
650  if (dest->cAxes > 0) {
651  axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
652  if (axes == NULL) {
653  return SDL_OutOfMemory();
654  }
655  axes[0] = haptic->hwdata->axes[0]; /* Always at least one axis. */
656  if (dest->cAxes > 1) {
657  axes[1] = haptic->hwdata->axes[1];
658  }
659  if (dest->cAxes > 2) {
660  axes[2] = haptic->hwdata->axes[2];
661  }
662  dest->rgdwAxes = axes;
663  }
664 
665  /* The big type handling switch, even bigger than Linux's version. */
666  switch (src->type) {
667  case SDL_HAPTIC_CONSTANT:
668  hap_constant = &src->constant;
669  constant = SDL_malloc(sizeof(DICONSTANTFORCE));
670  if (constant == NULL) {
671  return SDL_OutOfMemory();
672  }
673  SDL_memset(constant, 0, sizeof(DICONSTANTFORCE));
674 
675  /* Specifics */
676  constant->lMagnitude = CONVERT(hap_constant->level);
677  dest->cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
678  dest->lpvTypeSpecificParams = constant;
679 
680  /* Generics */
681  dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */
682  dest->dwTriggerButton = DIGetTriggerButton(hap_constant->button);
683  dest->dwTriggerRepeatInterval = hap_constant->interval;
684  dest->dwStartDelay = hap_constant->delay * 1000; /* In microseconds. */
685 
686  /* Direction. */
687  if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes) < 0) {
688  return -1;
689  }
690 
691  /* Envelope */
692  if ((hap_constant->attack_length == 0)
693  && (hap_constant->fade_length == 0)) {
694  SDL_free(dest->lpEnvelope);
695  dest->lpEnvelope = NULL;
696  } else {
697  envelope->dwAttackLevel = CCONVERT(hap_constant->attack_level);
698  envelope->dwAttackTime = hap_constant->attack_length * 1000;
699  envelope->dwFadeLevel = CCONVERT(hap_constant->fade_level);
700  envelope->dwFadeTime = hap_constant->fade_length * 1000;
701  }
702 
703  break;
704 
705  case SDL_HAPTIC_SINE:
706  /* !!! FIXME: put this back when we have more bits in 2.1 */
707  /* case SDL_HAPTIC_SQUARE: */
708  case SDL_HAPTIC_TRIANGLE:
711  hap_periodic = &src->periodic;
712  periodic = SDL_malloc(sizeof(DIPERIODIC));
713  if (periodic == NULL) {
714  return SDL_OutOfMemory();
715  }
716  SDL_memset(periodic, 0, sizeof(DIPERIODIC));
717 
718  /* Specifics */
719  periodic->dwMagnitude = CONVERT(SDL_abs(hap_periodic->magnitude));
720  periodic->lOffset = CONVERT(hap_periodic->offset);
721  periodic->dwPhase =
722  (hap_periodic->phase + (hap_periodic->magnitude < 0 ? 18000 : 0)) % 36000;
723  periodic->dwPeriod = hap_periodic->period * 1000;
724  dest->cbTypeSpecificParams = sizeof(DIPERIODIC);
725  dest->lpvTypeSpecificParams = periodic;
726 
727  /* Generics */
728  dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */
729  dest->dwTriggerButton = DIGetTriggerButton(hap_periodic->button);
730  dest->dwTriggerRepeatInterval = hap_periodic->interval;
731  dest->dwStartDelay = hap_periodic->delay * 1000; /* In microseconds. */
732 
733  /* Direction. */
734  if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes)
735  < 0) {
736  return -1;
737  }
738 
739  /* Envelope */
740  if ((hap_periodic->attack_length == 0)
741  && (hap_periodic->fade_length == 0)) {
742  SDL_free(dest->lpEnvelope);
743  dest->lpEnvelope = NULL;
744  } else {
745  envelope->dwAttackLevel = CCONVERT(hap_periodic->attack_level);
746  envelope->dwAttackTime = hap_periodic->attack_length * 1000;
747  envelope->dwFadeLevel = CCONVERT(hap_periodic->fade_level);
748  envelope->dwFadeTime = hap_periodic->fade_length * 1000;
749  }
750 
751  break;
752 
753  case SDL_HAPTIC_SPRING:
754  case SDL_HAPTIC_DAMPER:
755  case SDL_HAPTIC_INERTIA:
756  case SDL_HAPTIC_FRICTION:
757  hap_condition = &src->condition;
758  condition = SDL_malloc(sizeof(DICONDITION) * dest->cAxes);
759  if (condition == NULL) {
760  return SDL_OutOfMemory();
761  }
762  SDL_memset(condition, 0, sizeof(DICONDITION));
763 
764  /* Specifics */
765  for (i = 0; i < (int) dest->cAxes; i++) {
766  condition[i].lOffset = CONVERT(hap_condition->center[i]);
767  condition[i].lPositiveCoefficient =
768  CONVERT(hap_condition->right_coeff[i]);
769  condition[i].lNegativeCoefficient =
770  CONVERT(hap_condition->left_coeff[i]);
771  condition[i].dwPositiveSaturation =
772  CCONVERT(hap_condition->right_sat[i] / 2);
773  condition[i].dwNegativeSaturation =
774  CCONVERT(hap_condition->left_sat[i] / 2);
775  condition[i].lDeadBand = CCONVERT(hap_condition->deadband[i] / 2);
776  }
777  dest->cbTypeSpecificParams = sizeof(DICONDITION) * dest->cAxes;
778  dest->lpvTypeSpecificParams = condition;
779 
780  /* Generics */
781  dest->dwDuration = hap_condition->length * 1000; /* In microseconds. */
782  dest->dwTriggerButton = DIGetTriggerButton(hap_condition->button);
783  dest->dwTriggerRepeatInterval = hap_condition->interval;
784  dest->dwStartDelay = hap_condition->delay * 1000; /* In microseconds. */
785 
786  /* Direction. */
787  if (SDL_SYS_SetDirection(dest, &hap_condition->direction, dest->cAxes)
788  < 0) {
789  return -1;
790  }
791 
792  /* Envelope - Not actually supported by most CONDITION implementations. */
793  SDL_free(dest->lpEnvelope);
794  dest->lpEnvelope = NULL;
795 
796  break;
797 
798  case SDL_HAPTIC_RAMP:
799  hap_ramp = &src->ramp;
800  ramp = SDL_malloc(sizeof(DIRAMPFORCE));
801  if (ramp == NULL) {
802  return SDL_OutOfMemory();
803  }
804  SDL_memset(ramp, 0, sizeof(DIRAMPFORCE));
805 
806  /* Specifics */
807  ramp->lStart = CONVERT(hap_ramp->start);
808  ramp->lEnd = CONVERT(hap_ramp->end);
809  dest->cbTypeSpecificParams = sizeof(DIRAMPFORCE);
810  dest->lpvTypeSpecificParams = ramp;
811 
812  /* Generics */
813  dest->dwDuration = hap_ramp->length * 1000; /* In microseconds. */
814  dest->dwTriggerButton = DIGetTriggerButton(hap_ramp->button);
815  dest->dwTriggerRepeatInterval = hap_ramp->interval;
816  dest->dwStartDelay = hap_ramp->delay * 1000; /* In microseconds. */
817 
818  /* Direction. */
819  if (SDL_SYS_SetDirection(dest, &hap_ramp->direction, dest->cAxes) < 0) {
820  return -1;
821  }
822 
823  /* Envelope */
824  if ((hap_ramp->attack_length == 0) && (hap_ramp->fade_length == 0)) {
825  SDL_free(dest->lpEnvelope);
826  dest->lpEnvelope = NULL;
827  } else {
828  envelope->dwAttackLevel = CCONVERT(hap_ramp->attack_level);
829  envelope->dwAttackTime = hap_ramp->attack_length * 1000;
830  envelope->dwFadeLevel = CCONVERT(hap_ramp->fade_level);
831  envelope->dwFadeTime = hap_ramp->fade_length * 1000;
832  }
833 
834  break;
835 
836  case SDL_HAPTIC_CUSTOM:
837  hap_custom = &src->custom;
838  custom = SDL_malloc(sizeof(DICUSTOMFORCE));
839  if (custom == NULL) {
840  return SDL_OutOfMemory();
841  }
842  SDL_memset(custom, 0, sizeof(DICUSTOMFORCE));
843 
844  /* Specifics */
845  custom->cChannels = hap_custom->channels;
846  custom->dwSamplePeriod = hap_custom->period * 1000;
847  custom->cSamples = hap_custom->samples;
848  custom->rglForceData =
849  SDL_malloc(sizeof(LONG) * custom->cSamples * custom->cChannels);
850  for (i = 0; i < hap_custom->samples * hap_custom->channels; i++) { /* Copy data. */
851  custom->rglForceData[i] = CCONVERT(hap_custom->data[i]);
852  }
853  dest->cbTypeSpecificParams = sizeof(DICUSTOMFORCE);
854  dest->lpvTypeSpecificParams = custom;
855 
856  /* Generics */
857  dest->dwDuration = hap_custom->length * 1000; /* In microseconds. */
858  dest->dwTriggerButton = DIGetTriggerButton(hap_custom->button);
859  dest->dwTriggerRepeatInterval = hap_custom->interval;
860  dest->dwStartDelay = hap_custom->delay * 1000; /* In microseconds. */
861 
862  /* Direction. */
863  if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) < 0) {
864  return -1;
865  }
866 
867  /* Envelope */
868  if ((hap_custom->attack_length == 0)
869  && (hap_custom->fade_length == 0)) {
870  SDL_free(dest->lpEnvelope);
871  dest->lpEnvelope = NULL;
872  } else {
873  envelope->dwAttackLevel = CCONVERT(hap_custom->attack_level);
874  envelope->dwAttackTime = hap_custom->attack_length * 1000;
875  envelope->dwFadeLevel = CCONVERT(hap_custom->fade_level);
876  envelope->dwFadeTime = hap_custom->fade_length * 1000;
877  }
878 
879  break;
880 
881  default:
882  return SDL_SetError("Haptic: Unknown effect type.");
883  }
884 
885  return 0;
886 }
887 
888 
889 /*
890  * Frees an DIEFFECT allocated by SDL_SYS_ToDIEFFECT.
891  */
892 static void
893 SDL_SYS_HapticFreeDIEFFECT(DIEFFECT * effect, int type)
894 {
895  DICUSTOMFORCE *custom;
896 
897  SDL_free(effect->lpEnvelope);
898  effect->lpEnvelope = NULL;
899  SDL_free(effect->rgdwAxes);
900  effect->rgdwAxes = NULL;
901  if (effect->lpvTypeSpecificParams != NULL) {
902  if (type == SDL_HAPTIC_CUSTOM) { /* Must free the custom data. */
903  custom = (DICUSTOMFORCE *) effect->lpvTypeSpecificParams;
904  SDL_free(custom->rglForceData);
905  custom->rglForceData = NULL;
906  }
907  SDL_free(effect->lpvTypeSpecificParams);
908  effect->lpvTypeSpecificParams = NULL;
909  }
910  SDL_free(effect->rglDirection);
911  effect->rglDirection = NULL;
912 }
913 
914 /*
915  * Gets the effect type from the generic SDL haptic effect wrapper.
916  */
917 static REFGUID
918 SDL_SYS_HapticEffectType(SDL_HapticEffect * effect)
919 {
920  switch (effect->type) {
921  case SDL_HAPTIC_CONSTANT:
922  return &GUID_ConstantForce;
923 
924  case SDL_HAPTIC_RAMP:
925  return &GUID_RampForce;
926 
927  /* !!! FIXME: put this back when we have more bits in 2.1 */
928  /* case SDL_HAPTIC_SQUARE:
929  return &GUID_Square; */
930 
931  case SDL_HAPTIC_SINE:
932  return &GUID_Sine;
933 
934  case SDL_HAPTIC_TRIANGLE:
935  return &GUID_Triangle;
936 
938  return &GUID_SawtoothUp;
939 
941  return &GUID_SawtoothDown;
942 
943  case SDL_HAPTIC_SPRING:
944  return &GUID_Spring;
945 
946  case SDL_HAPTIC_DAMPER:
947  return &GUID_Damper;
948 
949  case SDL_HAPTIC_INERTIA:
950  return &GUID_Inertia;
951 
952  case SDL_HAPTIC_FRICTION:
953  return &GUID_Friction;
954 
955  case SDL_HAPTIC_CUSTOM:
956  return &GUID_CustomForce;
957 
958  default:
959  return NULL;
960  }
961 }
962 int
963 SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
964 {
965  HRESULT ret;
966  REFGUID type = SDL_SYS_HapticEffectType(base);
967 
968  if (type == NULL) {
969  SDL_SetError("Haptic: Unknown effect type.");
970  return -1;
971  }
972 
973  /* Get the effect. */
974  if (SDL_SYS_ToDIEFFECT(haptic, &effect->hweffect->effect, base) < 0) {
975  goto err_effectdone;
976  }
977 
978  /* Create the actual effect. */
979  ret = IDirectInputDevice8_CreateEffect(haptic->hwdata->device, type,
980  &effect->hweffect->effect,
981  &effect->hweffect->ref, NULL);
982  if (FAILED(ret)) {
983  DI_SetError("Unable to create effect", ret);
984  goto err_effectdone;
985  }
986 
987  return 0;
988 
989 err_effectdone:
990  SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, base->type);
991  return -1;
992 }
993 
994 int
995 SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
996 {
997  HRESULT ret;
998  DWORD flags;
999  DIEFFECT temp;
1000 
1001  /* Get the effect. */
1002  SDL_memset(&temp, 0, sizeof(DIEFFECT));
1003  if (SDL_SYS_ToDIEFFECT(haptic, &temp, data) < 0) {
1004  goto err_update;
1005  }
1006 
1007  /* Set the flags. Might be worthwhile to diff temp with loaded effect and
1008  * only change those parameters. */
1009  flags = DIEP_DIRECTION |
1010  DIEP_DURATION |
1011  DIEP_ENVELOPE |
1012  DIEP_STARTDELAY |
1013  DIEP_TRIGGERBUTTON |
1014  DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS;
1015 
1016  /* Create the actual effect. */
1017  ret =
1018  IDirectInputEffect_SetParameters(effect->hweffect->ref, &temp, flags);
1019  if (FAILED(ret)) {
1020  DI_SetError("Unable to update effect", ret);
1021  goto err_update;
1022  }
1023 
1024  /* Copy it over. */
1025  SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, data->type);
1026  SDL_memcpy(&effect->hweffect->effect, &temp, sizeof(DIEFFECT));
1027 
1028  return 0;
1029 
1030 err_update:
1031  SDL_SYS_HapticFreeDIEFFECT(&temp, data->type);
1032  return -1;
1033 }
1034 
1035 int
1036 SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
1037 {
1038  HRESULT ret;
1039  DWORD iter;
1040 
1041  /* Check if it's infinite. */
1042  if (iterations == SDL_HAPTIC_INFINITY) {
1043  iter = INFINITE;
1044  } else {
1045  iter = iterations;
1046  }
1047 
1048  /* Run the effect. */
1049  ret = IDirectInputEffect_Start(effect->hweffect->ref, iter, 0);
1050  if (FAILED(ret)) {
1051  return DI_SetError("Running the effect", ret);
1052  }
1053  return 0;
1054 }
1055 
1056 int
1057 SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
1058 {
1059  HRESULT ret;
1060 
1061  ret = IDirectInputEffect_Stop(effect->hweffect->ref);
1062  if (FAILED(ret)) {
1063  return DI_SetError("Unable to stop effect", ret);
1064  }
1065  return 0;
1066 }
1067 
1068 void
1069 SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
1070 {
1071  HRESULT ret;
1072 
1073  ret = IDirectInputEffect_Unload(effect->hweffect->ref);
1074  if (FAILED(ret)) {
1075  DI_SetError("Removing effect from the device", ret);
1076  }
1077  SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, effect->effect.type);
1078 }
1079 
1080 int
1081 SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
1082 {
1083  HRESULT ret;
1084  DWORD status;
1085 
1086  ret = IDirectInputEffect_GetEffectStatus(effect->hweffect->ref, &status);
1087  if (FAILED(ret)) {
1088  return DI_SetError("Getting effect status", ret);
1089  }
1090 
1091  if (status == 0)
1092  return SDL_FALSE;
1093  return SDL_TRUE;
1094 }
1095 
1096 int
1097 SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
1098 {
1099  HRESULT ret;
1100  DIPROPDWORD dipdw;
1101 
1102  /* Create the weird structure thingy. */
1103  dipdw.diph.dwSize = sizeof(DIPROPDWORD);
1104  dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
1105  dipdw.diph.dwObj = 0;
1106  dipdw.diph.dwHow = DIPH_DEVICE;
1107  dipdw.dwData = gain * 100; /* 0 to 10,000 */
1108 
1109  /* Try to set the autocenter. */
1110  ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
1111  DIPROP_FFGAIN, &dipdw.diph);
1112  if (FAILED(ret)) {
1113  return DI_SetError("Setting gain", ret);
1114  }
1115  return 0;
1116 }
1117 
1118 int
1119 SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
1120 {
1121  HRESULT ret;
1122  DIPROPDWORD dipdw;
1123 
1124  /* Create the weird structure thingy. */
1125  dipdw.diph.dwSize = sizeof(DIPROPDWORD);
1126  dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
1127  dipdw.diph.dwObj = 0;
1128  dipdw.diph.dwHow = DIPH_DEVICE;
1129  dipdw.dwData = (autocenter == 0) ? DIPROPAUTOCENTER_OFF :
1130  DIPROPAUTOCENTER_ON;
1131 
1132  /* Try to set the autocenter. */
1133  ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
1134  DIPROP_AUTOCENTER, &dipdw.diph);
1135  if (FAILED(ret)) {
1136  return DI_SetError("Setting autocenter", ret);
1137  }
1138  return 0;
1139 }
1140 
1141 int
1142 SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
1143 {
1144  HRESULT ret;
1145 
1146  /* Pause the device. */
1147  ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
1148  DISFFC_PAUSE);
1149  if (FAILED(ret)) {
1150  return DI_SetError("Pausing the device", ret);
1151  }
1152  return 0;
1153 }
1154 
1155 int
1156 SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
1157 {
1158  HRESULT ret;
1159 
1160  /* Unpause the device. */
1161  ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
1162  DISFFC_CONTINUE);
1163  if (FAILED(ret)) {
1164  return DI_SetError("Pausing the device", ret);
1165  }
1166  return 0;
1167 }
1168 
1169 int
1170 SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
1171 {
1172  HRESULT ret;
1173 
1174  /* Try to stop the effects. */
1175  ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
1176  DISFFC_STOPALL);
1177  if (FAILED(ret)) {
1178  return DI_SetError("Stopping the device", ret);
1179  }
1180  return 0;
1181 }
1182 
1183 #else /* !SDL_HAPTIC_DINPUT */
1184 
1185 typedef struct DIDEVICEINSTANCE DIDEVICEINSTANCE;
1187 
1188 int
1190 {
1191  return 0;
1192 }
1193 
1194 int
1196 {
1197  return SDL_Unsupported();
1198 }
1199 
1200 int
1202 {
1203  return SDL_Unsupported();
1204 }
1205 
1206 int
1207 SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
1208 {
1209  return SDL_Unsupported();
1210 }
1211 
1212 int
1213 SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
1214 {
1215  return SDL_Unsupported();
1216 }
1217 
1218 int
1219 SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
1220 {
1221  return SDL_Unsupported();
1222 }
1223 
1224 void
1225 SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
1226 {
1227 }
1228 
1229 void
1231 {
1232 }
1233 
1234 int
1235 SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
1236 {
1237  return SDL_Unsupported();
1238 }
1239 
1240 int
1241 SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
1242 {
1243  return SDL_Unsupported();
1244 }
1245 
1246 int
1247 SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
1248 {
1249  return SDL_Unsupported();
1250 }
1251 
1252 int
1253 SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
1254 {
1255  return SDL_Unsupported();
1256 }
1257 
1258 void
1259 SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
1260 {
1261 }
1262 
1263 int
1264 SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
1265 {
1266  return SDL_Unsupported();
1267 }
1268 
1269 int
1270 SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
1271 {
1272  return SDL_Unsupported();
1273 }
1274 
1275 int
1276 SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
1277 {
1278  return SDL_Unsupported();
1279 }
1280 
1281 int
1282 SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
1283 {
1284  return SDL_Unsupported();
1285 }
1286 
1287 int
1288 SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
1289 {
1290  return SDL_Unsupported();
1291 }
1292 
1293 int
1294 SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
1295 {
1296  return SDL_Unsupported();
1297 }
1298 
1299 #endif /* SDL_HAPTIC_DINPUT */
1300 
1301 /* vi: set ts=4 sw=4 expandtab: */
Uint16 deadband[3]
Definition: SDL_haptic.h:609
#define SDL_abs
Structure that represents a haptic direction.
Definition: SDL_haptic.h:437
int SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance)
#define SDL_HAPTIC_SPHERICAL
Uses spherical coordinates for the direction.
Definition: SDL_haptic.h:324
void SDL_DINPUT_HapticQuit(void)
int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
SDL_Texture * button
int SDL_DINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
#define SDL_HAPTIC_AUTOCENTER
Device can set autocenter.
Definition: SDL_haptic.h:280
A structure containing a template for a Periodic effect.
Definition: SDL_haptic.h:536
#define SDL_HAPTIC_GAIN
Device can set global gain.
Definition: SDL_haptic.h:271
#define DIRECTINPUT_VERSION
Definition: SDL_directx.h:95
#define SDL_HAPTIC_CUSTOM
Custom effect is supported.
Definition: SDL_haptic.h:258
#define SDL_HAPTIC_TRIANGLE
Triangle wave effect supported.
Definition: SDL_haptic.h:184
SDL_HapticDirection direction
Definition: SDL_haptic.h:594
SDL_HapticCustom custom
Definition: SDL_haptic.h:794
#define SDL_HAPTIC_INERTIA
Inertia effect supported - uses axes acceleration.
Definition: SDL_haptic.h:241
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
Uint16 fade_level
Definition: SDL_haptic.h:648
SDL_HapticRamp ramp
Definition: SDL_haptic.h:792
int SDL_DINPUT_HapticSetGain(SDL_Haptic *haptic, int gain)
int SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance)
A structure containing a template for a Condition effect.
Definition: SDL_haptic.h:589
The SDL Haptic subsystem allows you to control haptic (force feedback) devices.
static int iterations
Definition: testsprite2.c:43
Sint16 left_coeff[3]
Definition: SDL_haptic.h:608
Uint16 right_sat[3]
Definition: SDL_haptic.h:605
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:159
Uint16 fade_length
Definition: SDL_haptic.h:712
int SDL_DINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
void SDL_DINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
Sint16 right_coeff[3]
Definition: SDL_haptic.h:607
#define SDL_HAPTIC_SINE
Sine wave effect supported.
Definition: SDL_haptic.h:161
int SDL_DINPUT_HapticInit(void)
int SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
A structure containing a template for a Constant effect.
Definition: SDL_haptic.h:455
int SDL_DINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item)
int SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
#define SDL_HAPTIC_INFINITY
Used to play a device an infinite number of times.
Definition: SDL_haptic.h:339
Uint16 interval
Definition: SDL_haptic.h:638
#define SDL_HAPTIC_CARTESIAN
Uses cartesian coordinates for the direction.
Definition: SDL_haptic.h:317
SDL_hapticlist_item * SDL_hapticlist
struct SDL_hapticlist_item * next
SDL_HapticCondition condition
Definition: SDL_haptic.h:791
#define FAILED(x)
Definition: SDL_directx.h:54
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1564
#define SDL_memcpy
void * SDL_calloc(size_t nmemb, size_t size)
The generic template for any haptic effect.
Definition: SDL_haptic.h:785
#define SDL_HAPTIC_CONSTANT
Constant effect supported.
Definition: SDL_haptic.h:152
int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
HRESULT WIN_CoInitialize(void)
void SDL_free(void *mem)
#define SDL_HAPTIC_POLAR
Uses polar coordinates for the direction.
Definition: SDL_haptic.h:310
#define SDL_memcmp
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:45
SDL_HapticConstant constant
Definition: SDL_haptic.h:789
#define SDL_zero(x)
Definition: SDL_stdinc.h:359
#define SDL_HAPTIC_PAUSE
Device can be paused.
Definition: SDL_haptic.h:297
void SDL_DINPUT_HapticClose(SDL_Haptic *haptic)
int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
SDL_HapticDirection direction
Definition: SDL_haptic.h:630
A structure containing a template for a Ramp effect.
Definition: SDL_haptic.h:626
GLuint index
Uint16 attack_length
Definition: SDL_haptic.h:645
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
Uint16 fade_length
Definition: SDL_haptic.h:647
int SDL_DINPUT_HapticUnpause(SDL_Haptic *haptic)
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
void WIN_CoUninitialize(void)
SDL_HapticEffect effect
Definition: SDL_syshaptic.h:32
GLintptr offset
static SDL_Haptic * haptic
Definition: testhaptic.c:25
void SDL_SYS_HapticQuit(void)
struct haptic_hweffect * hweffect
Definition: SDL_syshaptic.h:33
#define SDL_SetError
#define SDL_HAPTIC_STATUS
Device can be queried for effect status.
Definition: SDL_haptic.h:289
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
SDL_HapticDirection direction
Definition: SDL_haptic.h:542
int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
Uint16 attack_level
Definition: SDL_haptic.h:711
#define SDL_HAPTIC_RAMP
Ramp effect supported.
Definition: SDL_haptic.h:211
#define SDL_HAPTIC_SPRING
Spring effect supported - uses axes position.
Definition: SDL_haptic.h:221
int SDL_DINPUT_HapticPause(SDL_Haptic *haptic)
GLenum condition
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:151
A structure containing a template for the SDL_HAPTIC_CUSTOM effect.
Definition: SDL_haptic.h:689
GLbitfield flags
#define SDL_malloc
#define SDL_HAPTIC_SAWTOOTHUP
Sawtoothup wave effect supported.
Definition: SDL_haptic.h:193
int SDL_DINPUT_HapticStopAll(SDL_Haptic *haptic)
int SDL_DINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
GLboolean GLboolean GLboolean GLboolean a
SDL_HapticPeriodic periodic
Definition: SDL_haptic.h:790
Uint16 attack_level
Definition: SDL_haptic.h:646
Uint16 attack_length
Definition: SDL_haptic.h:710
GLenum src
GLboolean GLboolean GLboolean b
#define SDL_HAPTIC_FRICTION
Friction effect supported - uses axes movement.
Definition: SDL_haptic.h:251
#define SDL_Unsupported()
Definition: SDL_error.h:53
#define SDL_HAPTIC_SAWTOOTHDOWN
Sawtoothdown wave effect supported.
Definition: SDL_haptic.h:202
#define SDL_memset
int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
SDL_HapticDirection direction
Definition: SDL_haptic.h:459
SDL_HapticDirection direction
Definition: SDL_haptic.h:693
#define SDL_HAPTIC_DAMPER
Damper effect supported - uses axes velocity.
Definition: SDL_haptic.h:231
Uint16 left_sat[3]
Definition: SDL_haptic.h:606