SDL  2.0
SDL_windowshaptic.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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 #if SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT
24 
25 #include "SDL_thread.h"
26 #include "SDL_mutex.h"
27 #include "SDL_timer.h"
28 #include "SDL_hints.h"
29 #include "SDL_haptic.h"
30 #include "../SDL_syshaptic.h"
31 #include "SDL_joystick.h"
32 #include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
33 #include "../../joystick/windows/SDL_windowsjoystick_c.h" /* For joystick hwdata */
34 #include "../../joystick/windows/SDL_xinputjoystick_c.h" /* For xinput rumble */
35 
36 #include "SDL_windowshaptic_c.h"
37 #include "SDL_dinputhaptic_c.h"
38 #include "SDL_xinputhaptic_c.h"
39 
40 
41 /*
42  * Internal stuff.
43  */
45 static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
46 static int numhaptics = 0;
47 
48 
49 /*
50  * Initializes the haptic subsystem.
51  */
52 int
54 {
55  if (SDL_DINPUT_HapticInit() < 0) {
56  return -1;
57  }
58  if (SDL_XINPUT_HapticInit() < 0) {
59  return -1;
60  }
61  return numhaptics;
62 }
63 
64 int
66 {
67  if (SDL_hapticlist_tail == NULL) {
68  SDL_hapticlist = SDL_hapticlist_tail = item;
69  } else {
70  SDL_hapticlist_tail->next = item;
71  SDL_hapticlist_tail = item;
72  }
73 
74  /* Device has been added. */
75  ++numhaptics;
76 
77  return numhaptics;
78 }
79 
80 int
82 {
83  const int retval = item->haptic ? item->haptic->index : -1;
84  if (prev != NULL) {
85  prev->next = item->next;
86  } else {
87  SDL_assert(SDL_hapticlist == item);
88  SDL_hapticlist = item->next;
89  }
90  if (item == SDL_hapticlist_tail) {
91  SDL_hapticlist_tail = prev;
92  }
93  --numhaptics;
94  /* !!! TODO: Send a haptic remove event? */
95  SDL_free(item);
96  return retval;
97 }
98 
99 int
100 SDL_SYS_NumHaptics(void)
101 {
102  return numhaptics;
103 }
104 
105 static SDL_hapticlist_item *
106 HapticByDevIndex(int device_index)
107 {
109 
110  if ((device_index < 0) || (device_index >= numhaptics)) {
111  return NULL;
112  }
113 
114  while (device_index > 0) {
115  SDL_assert(item != NULL);
116  --device_index;
117  item = item->next;
118  }
119  return item;
120 }
121 
122 /*
123  * Return the name of a haptic device, does not need to be opened.
124  */
125 const char *
127 {
128  SDL_hapticlist_item *item = HapticByDevIndex(index);
129  return item->name;
130 }
131 
132 /*
133  * Opens a haptic device for usage.
134  */
135 int
136 SDL_SYS_HapticOpen(SDL_Haptic * haptic)
137 {
138  SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
139  if (item->bXInputHaptic) {
140  return SDL_XINPUT_HapticOpen(haptic, item);
141  } else {
142  return SDL_DINPUT_HapticOpen(haptic, item);
143  }
144 }
145 
146 
147 /*
148  * Opens a haptic device from first mouse it finds for usage.
149  */
150 int
152 {
153 #if SDL_HAPTIC_DINPUT
154  SDL_hapticlist_item *item;
155  int index = 0;
156 
157  /* Grab the first mouse haptic device we find. */
158  for (item = SDL_hapticlist; item != NULL; item = item->next) {
159  if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER) {
160  return index;
161  }
162  ++index;
163  }
164 #endif /* SDL_HAPTIC_DINPUT */
165  return -1;
166 }
167 
168 
169 /*
170  * Checks to see if a joystick has haptic features.
171  */
172 int
173 SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
174 {
175  if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
176  return 0;
177  }
178 #if SDL_HAPTIC_XINPUT
179  if (joystick->hwdata->bXInputHaptic) {
180  return 1;
181  }
182 #endif
183 #if SDL_HAPTIC_DINPUT
184  if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
185  return 1;
186  }
187 #endif
188  return 0;
189 }
190 
191 /*
192  * Checks to see if the haptic device and joystick are in reality the same.
193  */
194 int
195 SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
196 {
197  if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
198  return 0;
199  }
200  if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
201  return 0; /* one is XInput, one is not; not the same device. */
202  } else if (joystick->hwdata->bXInputHaptic) {
204  } else {
206  }
207 }
208 
209 /*
210  * Opens a SDL_Haptic from a SDL_Joystick.
211  */
212 int
213 SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
214 {
216 
217  if (joystick->hwdata->bXInputDevice) {
219  } else {
221  }
222 }
223 
224 /*
225  * Closes the haptic device.
226  */
227 void
228 SDL_SYS_HapticClose(SDL_Haptic * haptic)
229 {
230  if (haptic->hwdata) {
231 
232  /* Free effects. */
233  SDL_free(haptic->effects);
234  haptic->effects = NULL;
235  haptic->neffects = 0;
236 
237  /* Clean up */
238  if (haptic->hwdata->bXInputHaptic) {
240  } else {
242  }
243 
244  /* Free */
245  SDL_free(haptic->hwdata);
246  haptic->hwdata = NULL;
247  }
248 }
249 
250 /*
251  * Clean up after system specific haptic stuff
252  */
253 void
254 SDL_SYS_HapticQuit(void)
255 {
256  SDL_hapticlist_item *item;
257  SDL_hapticlist_item *next = NULL;
258  SDL_Haptic *hapticitem = NULL;
259 
260  extern SDL_Haptic *SDL_haptics;
261  for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
262  if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
263  /* we _have_ to stop the thread before we free the XInput DLL! */
264  SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1);
265  SDL_WaitThread(hapticitem->hwdata->thread, NULL);
266  hapticitem->hwdata->thread = NULL;
267  }
268  }
269 
270  for (item = SDL_hapticlist; item; item = next) {
271  /* Opened and not closed haptics are leaked, this is on purpose.
272  * Close your haptic devices after usage. */
273  /* !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not. */
274  next = item->next;
275  SDL_free(item->name);
276  SDL_free(item);
277  }
278 
281 
282  numhaptics = 0;
284  SDL_hapticlist_tail = NULL;
285 }
286 
287 /*
288  * Creates a new haptic effect.
289  */
290 int
291 SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
293 {
294  int result;
295 
296  /* Alloc the effect. */
297  effect->hweffect = (struct haptic_hweffect *)
298  SDL_malloc(sizeof(struct haptic_hweffect));
299  if (effect->hweffect == NULL) {
300  SDL_OutOfMemory();
301  return -1;
302  }
303  SDL_zerop(effect->hweffect);
304 
305  if (haptic->hwdata->bXInputHaptic) {
307  } else {
309  }
310  if (result < 0) {
311  SDL_free(effect->hweffect);
312  effect->hweffect = NULL;
313  }
314  return result;
315 }
316 
317 /*
318  * Updates an effect.
319  */
320 int
322  struct haptic_effect *effect,
324 {
325  if (haptic->hwdata->bXInputHaptic) {
326  return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data);
327  } else {
328  return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
329  }
330 }
331 
332 /*
333  * Runs an effect.
334  */
335 int
336 SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
338 {
339  if (haptic->hwdata->bXInputHaptic) {
341  } else {
343  }
344 }
345 
346 /*
347  * Stops an effect.
348  */
349 int
350 SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
351 {
352  if (haptic->hwdata->bXInputHaptic) {
353  return SDL_XINPUT_HapticStopEffect(haptic, effect);
354  } else {
355  return SDL_DINPUT_HapticStopEffect(haptic, effect);
356  }
357 }
358 
359 /*
360  * Frees the effect.
361  */
362 void
363 SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
364 {
365  if (haptic->hwdata->bXInputHaptic) {
367  } else {
369  }
370  SDL_free(effect->hweffect);
371  effect->hweffect = NULL;
372 }
373 
374 /*
375  * Gets the status of a haptic effect.
376  */
377 int
379  struct haptic_effect *effect)
380 {
381  if (haptic->hwdata->bXInputHaptic) {
383  } else {
385  }
386 }
387 
388 /*
389  * Sets the gain.
390  */
391 int
392 SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
393 {
394  if (haptic->hwdata->bXInputHaptic) {
395  return SDL_XINPUT_HapticSetGain(haptic, gain);
396  } else {
397  return SDL_DINPUT_HapticSetGain(haptic, gain);
398  }
399 }
400 
401 /*
402  * Sets the autocentering.
403  */
404 int
405 SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
406 {
407  if (haptic->hwdata->bXInputHaptic) {
408  return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
409  } else {
410  return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
411  }
412 }
413 
414 /*
415  * Pauses the device.
416  */
417 int
418 SDL_SYS_HapticPause(SDL_Haptic * haptic)
419 {
420  if (haptic->hwdata->bXInputHaptic) {
422  } else {
424  }
425 }
426 
427 /*
428  * Pauses the device.
429  */
430 int
431 SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
432 {
433  if (haptic->hwdata->bXInputHaptic) {
435  } else {
437  }
438 }
439 
440 /*
441  * Stops all the playing effects on the device.
442  */
443 int
444 SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
445 {
446  if (haptic->hwdata->bXInputHaptic) {
448  } else {
450  }
451 }
452 
453 #endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
454 
455 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:171
void SDL_DINPUT_HapticQuit(void)
int SDL_DINPUT_HapticSetGain(SDL_Haptic *haptic, int gain)
int SDL_DINPUT_HapticStopAll(SDL_Haptic *haptic)
int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
int SDL_DINPUT_HapticPause(SDL_Haptic *haptic)
int SDL_DINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item)
int SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
void SDL_DINPUT_HapticClose(SDL_Haptic *haptic)
void SDL_DINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_DINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_DINPUT_HapticUnpause(SDL_Haptic *haptic)
int SDL_DINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
int SDL_DINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
int SDL_DINPUT_HapticInit(void)
#define SDL_AtomicSet
#define SDL_malloc
#define SDL_free
#define SDL_WaitThread
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
static SDL_Haptic * SDL_haptics
Definition: SDL_haptic.c:31
The SDL haptic subsystem allows you to control haptic (force feedback) devices.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLuint64EXT * result
GLuint index
#define SDL_zerop(x)
Definition: SDL_stdinc.h:427
uint32_t Uint32
Definition: SDL_stdinc.h:209
void SDL_SYS_HapticClose(SDL_Haptic *haptic)
int SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_SYS_HapticPause(SDL_Haptic *haptic)
int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
const char * SDL_SYS_HapticName(int index)
void SDL_SYS_HapticQuit(void)
int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_SYS_HapticMouse(void)
int SDL_SYS_HapticUnpause(SDL_Haptic *haptic)
int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
int SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
int SDL_SYS_NumHaptics(void)
void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_SYS_HapticInit(void)
int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
SDL_JoystickDriver SDL_WINDOWS_JoystickDriver
int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
SDL_hapticlist_item * SDL_hapticlist
int SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
int SDL_XINPUT_HapticPause(SDL_Haptic *haptic)
int SDL_XINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_XINPUT_HapticSetGain(SDL_Haptic *haptic, int gain)
int SDL_XINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
void SDL_XINPUT_HapticQuit(void)
int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
void SDL_XINPUT_HapticClose(SDL_Haptic *haptic)
int SDL_XINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item)
int SDL_XINPUT_HapticInit(void)
int SDL_XINPUT_HapticStopAll(SDL_Haptic *haptic)
int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_XINPUT_HapticUnpause(SDL_Haptic *haptic)
#define NULL
Definition: begin_code.h:163
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst base
struct SDL_hapticlist_item * next
struct haptic_hweffect * hweffect
Definition: SDL_syshaptic.h:33
SDL_bool retval
static SDL_Haptic * haptic
Definition: testhaptic.c:25
static SDL_Joystick * joystick
Definition: testjoystick.c:37
static int iterations
Definition: testsprite2.c:45
The generic template for any haptic effect.
Definition: SDL_haptic.h:810