zenilib: zenilib/jni/external/sdl/src/haptic/windows/SDL_syshaptic.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_syshaptic.c
Go to the documentation of this file.
1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 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_config.h"
22
23 #ifdef SDL_HAPTIC_DINPUT
24
25 #include "SDL_assert.h"
26 #include "SDL_thread.h"
27 #include "SDL_mutex.h"
28 #include "SDL_timer.h"
29 #include "SDL_hints.h"
30 #include "SDL_haptic.h"
31 #include "../SDL_syshaptic.h"
32 #include "SDL_joystick.h"
33 #include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
34 #include "../../joystick/windows/SDL_dxjoystick_c.h" /* For joystick hwdata */
35
36 #define MAX_HAPTICS 32
37
38 /*
39 * List of available haptic devices.
40 */
41 static struct
42 {
43 DIDEVICEINSTANCE instance;
44 char *name;
45 SDL_Haptic *haptic;
46 DIDEVCAPS capabilities;
47 Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
48 Uint8 userid; /* XInput userid index for this joystick */
49 } SDL_hapticlist[MAX_HAPTICS];
50
51
52 /*
53 * Haptic system hardware data.
54 */
55 struct haptic_hwdata
56 {
57 LPDIRECTINPUTDEVICE8 device;
58 DWORD axes[3]; /* Axes to use. */
59 SDL_bool is_joystick; /* Device is loaded as joystick. */
60 Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
61 Uint8 userid; /* XInput userid index for this joystick */
62 SDL_Thread *thread;
63 SDL_mutex *mutex;
64 volatile Uint32 stopTicks;
65 volatile int stopThread;
66 };
67
68
69 /*
70 * Haptic system effect data.
71 */
72 struct haptic_hweffect
73 {
74 DIEFFECT effect;
75 LPDIRECTINPUTEFFECT ref;
76 XINPUT_VIBRATION vibration;
77 };
78
79
80 /*
81 * Internal stuff.
82 */
83 static SDL_bool coinitialized = SDL_FALSE;
84 static LPDIRECTINPUT8 dinput = NULL;
85 static SDL_bool loaded_xinput = SDL_FALSE;
86
87
88 /*
89 * External stuff.
90 */
91 extern HWND SDL_HelperWindow;
92
93
94 /*
95 * Prototypes.
96 */
97 static int DI_SetError(const char *str, HRESULT err);
98 static int DI_GUIDIsSame(const GUID * a, const GUID * b);
99 static int SDL_SYS_HapticOpenFromInstance(SDL_Haptic * haptic,
100 DIDEVICEINSTANCE instance);
101 static int SDL_SYS_HapticOpenFromDevice8(SDL_Haptic * haptic,
102 LPDIRECTINPUTDEVICE8 device8,
103 SDL_bool is_joystick);
104 static int SDL_SYS_HapticOpenFromXInput(SDL_Haptic * haptic, Uint8 userid);
105 static DWORD DIGetTriggerButton(Uint16 button);
106 static int SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir,
107 int naxes);
108 static int SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
109 SDL_HapticEffect * src);
110 static void SDL_SYS_HapticFreeDIEFFECT(DIEFFECT * effect, int type);
111 static REFGUID SDL_SYS_HapticEffectType(SDL_HapticEffect * effect);
112 static int SDLCALL SDL_RunXInputHaptic(void *arg);
113
114 /* Callbacks. */
115 static BOOL CALLBACK EnumHapticsCallback(const DIDEVICEINSTANCE *
116 pdidInstance, VOID * pContext);
117 static BOOL CALLBACK DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv);
118
119
120 /*
121 * Like SDL_SetError but for DX error codes.
122 */
123 static int
124 DI_SetError(const char *str, HRESULT err)
125 {
126 /*
127 SDL_SetError("Haptic: %s - %s: %s", str,
128 DXGetErrorString8A(err), DXGetErrorDescription8A(err));
129 */
130 return SDL_SetError("Haptic error %s", str);
131 }
132
133
134 /*
135 * Checks to see if two GUID are the same.
136 */
137 static int
138 DI_GUIDIsSame(const GUID * a, const GUID * b)
139 {
140 return (SDL_memcmp(a, b, sizeof (GUID)) == 0);
141 }
142
143
144 /*
145 * Initializes the haptic subsystem.
146 */
147 int
148 SDL_SYS_HapticInit(void)
149 {
150 const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
151 HRESULT ret;
152 HINSTANCE instance;
153
154 if (dinput != NULL) { /* Already open. */
155 return SDL_SetError("Haptic: SubSystem already open.");
156 }
157
158 /* Clear all the memory. */
159 SDL_memset(SDL_hapticlist, 0, sizeof(SDL_hapticlist));
160
161 SDL_numhaptics = 0;
162
163 ret = WIN_CoInitialize();
164 if (FAILED(ret)) {
165 return DI_SetError("Coinitialize", ret);
166 }
167
168 coinitialized = SDL_TRUE;
169
170 ret = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
171 &IID_IDirectInput8, (LPVOID) & dinput);
172 if (FAILED(ret)) {
173 SDL_SYS_HapticQuit();
174 return DI_SetError("CoCreateInstance", ret);
175 }
176
177 /* Because we used CoCreateInstance, we need to Initialize it, first. */
178 instance = GetModuleHandle(NULL);
179 if (instance == NULL) {
180 SDL_SYS_HapticQuit();
181 return SDL_SetError("GetModuleHandle() failed with error code %d.",
182 GetLastError());
183 }
184 ret = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
185 if (FAILED(ret)) {
186 SDL_SYS_HapticQuit();
187 return DI_SetError("Initializing DirectInput device", ret);
188 }
189
190 /* Look for haptic devices. */
191 ret = IDirectInput8_EnumDevices(dinput,
192 0,
193 EnumHapticsCallback,
194 NULL,
195 DIEDFL_FORCEFEEDBACK |
196 DIEDFL_ATTACHEDONLY);
197 if (FAILED(ret)) {
198 SDL_SYS_HapticQuit();
199 return DI_SetError("Enumerating DirectInput devices", ret);
200 }
201
202 if (!env || SDL_atoi(env)) {
203 loaded_xinput = (WIN_LoadXInputDLL() == 0);
204 }
205
206 if (loaded_xinput) {
207 DWORD i;
208 const SDL_bool bIs14OrLater = (SDL_XInputVersion >= ((1<<16)|4));
209
210 for (i = 0; (i < SDL_XINPUT_MAX_DEVICES) && (SDL_numhaptics < MAX_HAPTICS); i++) {
211 XINPUT_CAPABILITIES caps;
212 if (XINPUTGETCAPABILITIES(i, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) {
213 if ((!bIs14OrLater) || (caps.Flags & XINPUT_CAPS_FFB_SUPPORTED)) {
214 /* !!! FIXME: I'm not bothering to query for a real name right now. */
215 char buf[64];
216 SDL_snprintf(buf, sizeof (buf), "XInput Controller #%u", i+1);
217 SDL_hapticlist[SDL_numhaptics].name = SDL_strdup(buf);
218 SDL_hapticlist[SDL_numhaptics].bXInputHaptic = 1;
219 SDL_hapticlist[SDL_numhaptics].userid = (Uint8) i;
220 SDL_numhaptics++;
221 }
222 }
223 }
224 }
225
226 return SDL_numhaptics;
227 }
228
229 /*
230 * Callback to find the haptic devices.
231 */
232 static BOOL CALLBACK
233 EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
234 {
235 HRESULT ret;
236 LPDIRECTINPUTDEVICE8 device;
237
238 /* Copy the instance over, useful for creating devices. */
239 SDL_memcpy(&SDL_hapticlist[SDL_numhaptics].instance, pdidInstance,
240 sizeof(DIDEVICEINSTANCE));
241
242 /* Open the device */
243 ret = IDirectInput8_CreateDevice(dinput, &pdidInstance->guidInstance,
244 &device, NULL);
245 if (FAILED(ret)) {
246 /* DI_SetError("Creating DirectInput device",ret); */
247 return DIENUM_CONTINUE;
248 }
249
250 /* Get capabilities. */
251 SDL_hapticlist[SDL_numhaptics].capabilities.dwSize = sizeof(DIDEVCAPS);
252 ret = IDirectInputDevice8_GetCapabilities(device,
253 &SDL_hapticlist[SDL_numhaptics].
254 capabilities);
255 if (FAILED(ret)) {
256 /* DI_SetError("Getting device capabilities",ret); */
257 IDirectInputDevice8_Release(device);
258 return DIENUM_CONTINUE;
259 }
260
261 /* Copy the name */
262 SDL_hapticlist[SDL_numhaptics].name = WIN_StringToUTF8(SDL_hapticlist[SDL_numhaptics].instance.tszProductName);
263
264 /* Close up device and count it. */
265 IDirectInputDevice8_Release(device);
266 SDL_numhaptics++;
267
268 /* Watch out for hard limit. */
269 if (SDL_numhaptics >= MAX_HAPTICS)
270 return DIENUM_STOP;
271
272 return DIENUM_CONTINUE;
273 }
274
275
276 /*
277 * Return the name of a haptic device, does not need to be opened.
278 */
279 const char *
280 SDL_SYS_HapticName(int index)
281 {
282 return SDL_hapticlist[index].name;
283 }
284
285
286 /*
287 * Callback to get all supported effects.
288 */
289 #define EFFECT_TEST(e,s) \
290 if (DI_GUIDIsSame(&pei->guid, &(e))) \
291 haptic->supported |= (s)
292 static BOOL CALLBACK
293 DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
294 {
295 /* Prepare the haptic device. */
296 SDL_Haptic *haptic = (SDL_Haptic *) pv;
297
298 /* Get supported. */
299 EFFECT_TEST(GUID_Spring, SDL_HAPTIC_SPRING);
300 EFFECT_TEST(GUID_Damper, SDL_HAPTIC_DAMPER);
301 EFFECT_TEST(GUID_Inertia, SDL_HAPTIC_INERTIA);
302 EFFECT_TEST(GUID_Friction, SDL_HAPTIC_FRICTION);
303 EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
304 EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
305 EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
306 /* !!! FIXME: put this back when we have more bits in 2.1 */
307 /* EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE); */
308 EFFECT_TEST(GUID_Triangle, SDL_HAPTIC_TRIANGLE);
309 EFFECT_TEST(GUID_SawtoothUp, SDL_HAPTIC_SAWTOOTHUP);
310 EFFECT_TEST(GUID_SawtoothDown, SDL_HAPTIC_SAWTOOTHDOWN);
311 EFFECT_TEST(GUID_RampForce, SDL_HAPTIC_RAMP);
312
313 /* Check for more. */
314 return DIENUM_CONTINUE;
315 }
316
317
318 /*
319 * Callback to get supported axes.
320 */
321 static BOOL CALLBACK
322 DI_DeviceObjectCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
323 {
324 SDL_Haptic *haptic = (SDL_Haptic *) pvRef;
325
326 if ((dev->dwType & DIDFT_AXIS) && (dev->dwFlags & DIDOI_FFACTUATOR)) {
327
328 haptic->hwdata->axes[haptic->naxes] = dev->dwOfs;
329 haptic->naxes++;
330
331 /* Currently using the artificial limit of 3 axes. */
332 if (haptic->naxes >= 3) {
333 return DIENUM_STOP;
334 }
335 }
336
337 return DIENUM_CONTINUE;
338 }
339
340
341 /*
342 * Opens the haptic device from the file descriptor.
343 *
344 * Steps:
345 * - Open temporary DirectInputDevice interface.
346 * - Create DirectInputDevice8 interface.
347 * - Release DirectInputDevice interface.
348 * - Call SDL_SYS_HapticOpenFromDevice8
349 */
350 static int
351 SDL_SYS_HapticOpenFromInstance(SDL_Haptic * haptic, DIDEVICEINSTANCE instance)
352 {
353 HRESULT ret;
354 int ret2;
355 LPDIRECTINPUTDEVICE8 device;
356 LPDIRECTINPUTDEVICE8 device8;
357
358 /* Open the device */
359 ret = IDirectInput8_CreateDevice(dinput, &instance.guidInstance,
360 &device, NULL);
361 if (FAILED(ret)) {
362 DI_SetError("Creating DirectInput device", ret);
363 return -1;
364 }
365
366 /* Now get the IDirectInputDevice8 interface, instead. */
367 ret = IDirectInputDevice8_QueryInterface(device,
368 &IID_IDirectInputDevice8,
369 (LPVOID *) &device8);
370 /* Done with the temporary one now. */
371 IDirectInputDevice8_Release(device);
372 if (FAILED(ret)) {
373 DI_SetError("Querying DirectInput interface", ret);
374 return -1;
375 }
376
377 ret2 = SDL_SYS_HapticOpenFromDevice8(haptic, device8, SDL_FALSE);
378 if (ret2 < 0) {
379 IDirectInputDevice8_Release(device8);
380 return -1;
381 }
382
383 return 0;
384 }
385
386 static int
387 SDL_SYS_HapticOpenFromXInput(SDL_Haptic * haptic, Uint8 userid)
388 {
389 char threadName[32];
390 XINPUT_VIBRATION vibration = { 0, 0 }; /* stop any current vibration */
391 XINPUTSETSTATE(userid, &vibration);
392
393 haptic->supported = SDL_HAPTIC_LEFTRIGHT;
394
395 haptic->neffects = 1;
396 haptic->nplaying = 1;
397
398 /* Prepare effects memory. */
399 haptic->effects = (struct haptic_effect *)
400 SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
401 if (haptic->effects == NULL) {
402 return SDL_OutOfMemory();
403 }
404 /* Clear the memory */
405 SDL_memset(haptic->effects, 0,
406 sizeof(struct haptic_effect) * haptic->neffects);
407
408 haptic->hwdata = (struct haptic_hwdata *) SDL_malloc(sizeof(*haptic->hwdata));
409 if (haptic->hwdata == NULL) {
410 SDL_free(haptic->effects);
411 haptic->effects = NULL;
412 return SDL_OutOfMemory();
413 }
414 SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
415
416 haptic->hwdata->bXInputHaptic = 1;
417 haptic->hwdata->userid = userid;
418
419 haptic->hwdata->mutex = SDL_CreateMutex();
420 if (haptic->hwdata->mutex == NULL) {
421 SDL_free(haptic->effects);
422 SDL_free(haptic->hwdata);
423 haptic->effects = NULL;
424 return SDL_SetError("Couldn't create XInput haptic mutex");
425 }
426
427 SDL_snprintf(threadName, sizeof (threadName), "SDLXInputDev%d", (int) userid);
428
429 #if defined(__WIN32__) && !defined(HAVE_LIBC) /* !!! FIXME: this is nasty. */
430 #undef SDL_CreateThread
431 haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
432 #else
433 haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata);
434 #endif
435 if (haptic->hwdata->thread == NULL) {
436 SDL_DestroyMutex(haptic->hwdata->mutex);
437 SDL_free(haptic->effects);
438 SDL_free(haptic->hwdata);
439 haptic->effects = NULL;
440 return SDL_SetError("Couldn't create XInput haptic thread");
441 }
442
443 return 0;
444 }
445
446 /*
447 * Opens the haptic device from the file descriptor.
448 *
449 * Steps:
450 * - Set cooperative level.
451 * - Set data format.
452 * - Acquire exclusiveness.
453 * - Reset actuators.
454 * - Get supported features.
455 */
456 static int
457 SDL_SYS_HapticOpenFromDevice8(SDL_Haptic * haptic,
458 LPDIRECTINPUTDEVICE8 device8, SDL_bool is_joystick)
459 {
460 HRESULT ret;
461 DIPROPDWORD dipdw;
462
463 /* Allocate the hwdata */
464 haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata));
465 if (haptic->hwdata == NULL) {
466 return SDL_OutOfMemory();
467 }
468 SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
469
470 /* We'll use the device8 from now on. */
471 haptic->hwdata->device = device8;
472 haptic->hwdata->is_joystick = is_joystick;
473
474 /* Grab it exclusively to use force feedback stuff. */
475 ret = IDirectInputDevice8_SetCooperativeLevel(haptic->hwdata->device,
476 SDL_HelperWindow,
477 DISCL_EXCLUSIVE |
478 DISCL_BACKGROUND);
479 if (FAILED(ret)) {
480 DI_SetError("Setting cooperative level to exclusive", ret);
481 goto acquire_err;
482 }
483
484 /* Set data format. */
485 ret = IDirectInputDevice8_SetDataFormat(haptic->hwdata->device,
486 &c_dfDIJoystick2);
487 if (FAILED(ret)) {
488 DI_SetError("Setting data format", ret);
489 goto acquire_err;
490 }
491
492 /* Get number of axes. */
493 ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
494 DI_DeviceObjectCallback,
495 haptic, DIDFT_AXIS);
496 if (FAILED(ret)) {
497 DI_SetError("Getting device axes", ret);
498 goto acquire_err;
499 }
500
501 /* Acquire the device. */
502 ret = IDirectInputDevice8_Acquire(haptic->hwdata->device);
503 if (FAILED(ret)) {
504 DI_SetError("Acquiring DirectInput device", ret);
505 goto acquire_err;
506 }
507
508 /* Reset all actuators - just in case. */
509 ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
510 DISFFC_RESET);
511 if (FAILED(ret)) {
512 DI_SetError("Resetting device", ret);
513 goto acquire_err;
514 }
515
516 /* Enabling actuators. */
517 ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
518 DISFFC_SETACTUATORSON);
519 if (FAILED(ret)) {
520 DI_SetError("Enabling actuators", ret);
521 goto acquire_err;
522 }
523
524 /* Get supported effects. */
525 ret = IDirectInputDevice8_EnumEffects(haptic->hwdata->device,
526 DI_EffectCallback, haptic,
527 DIEFT_ALL);
528 if (FAILED(ret)) {
529 DI_SetError("Enumerating supported effects", ret);
530 goto acquire_err;
531 }
532 if (haptic->supported == 0) { /* Error since device supports nothing. */
533 SDL_SetError("Haptic: Internal error on finding supported effects.");
534 goto acquire_err;
535 }
536
537 /* Check autogain and autocenter. */
538 dipdw.diph.dwSize = sizeof(DIPROPDWORD);
539 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
540 dipdw.diph.dwObj = 0;
541 dipdw.diph.dwHow = DIPH_DEVICE;
542 dipdw.dwData = 10000;
543 ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
544 DIPROP_FFGAIN, &dipdw.diph);
545 if (!FAILED(ret)) { /* Gain is supported. */
546 haptic->supported |= SDL_HAPTIC_GAIN;
547 }
548 dipdw.diph.dwObj = 0;
549 dipdw.diph.dwHow = DIPH_DEVICE;
550 dipdw.dwData = DIPROPAUTOCENTER_OFF;
551 ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
552 DIPROP_AUTOCENTER, &dipdw.diph);
553 if (!FAILED(ret)) { /* Autocenter is supported. */
554 haptic->supported |= SDL_HAPTIC_AUTOCENTER;
555 }
556
557 /* Status is always supported. */
558 haptic->supported |= SDL_HAPTIC_STATUS | SDL_HAPTIC_PAUSE;
559
560 /* Check maximum effects. */
561 haptic->neffects = 128; /* This is not actually supported as thus under windows,
562 there is no way to tell the number of EFFECTS that a
563 device can hold, so we'll just use a "random" number
564 instead and put warnings in SDL_haptic.h */
565 haptic->nplaying = 128; /* Even more impossible to get this then neffects. */
566
567 /* Prepare effects memory. */
568 haptic->effects = (struct haptic_effect *)
569 SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
570 if (haptic->effects == NULL) {
571 SDL_OutOfMemory();
572 goto acquire_err;
573 }
574 /* Clear the memory */
575 SDL_memset(haptic->effects, 0,
576 sizeof(struct haptic_effect) * haptic->neffects);
577
578 return 0;
579
580 /* Error handling */
581 acquire_err:
582 IDirectInputDevice8_Unacquire(haptic->hwdata->device);
583 return -1;
584
585 }
586
587
588 /*
589 * Opens a haptic device for usage.
590 */
591 int
592 SDL_SYS_HapticOpen(SDL_Haptic * haptic)
593 {
594 if (SDL_hapticlist[haptic->index].bXInputHaptic) {
595 return SDL_SYS_HapticOpenFromXInput(haptic, SDL_hapticlist[haptic->index].userid);
596 }
597
598 return SDL_SYS_HapticOpenFromInstance(haptic, SDL_hapticlist[haptic->index].instance);
599 }
600
601
602 /*
603 * Opens a haptic device from first mouse it finds for usage.
604 */
605 int
606 SDL_SYS_HapticMouse(void)
607 {
608 int i;
609
610 /* Grab the first mouse haptic device we find. */
611 for (i = 0; i < SDL_numhaptics; i++) {
612 if (SDL_hapticlist[i].capabilities.dwDevType == DI8DEVCLASS_POINTER ) {
613 return i;
614 }
615 }
616
617 return -1;
618 }
619
620
621 /*
622 * Checks to see if a joystick has haptic features.
623 */
624 int
625 SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
626 {
627 const struct joystick_hwdata *hwdata = joystick->hwdata;
628 return ( (hwdata->bXInputHaptic) ||
629 ((hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) != 0) );
630 }
631
632
633 /*
634 * Checks to see if the haptic device and joystick are in reality the same.
635 */
636 int
637 SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
638 {
639 if ((joystick->hwdata->bXInputHaptic == haptic->hwdata->bXInputHaptic)) {
640 return haptic->hwdata->userid == joystick->hwdata->userid;
641 } else {
642 HRESULT ret;
643 DIDEVICEINSTANCE hap_instance, joy_instance;
644
645 hap_instance.dwSize = sizeof(DIDEVICEINSTANCE);
646 joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
647
648 /* Get the device instances. */
649 ret = IDirectInputDevice8_GetDeviceInfo(haptic->hwdata->device,
650 &hap_instance);
651 if (FAILED(ret)) {
652 return 0;
653 }
654 ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice,
655 &joy_instance);
656 if (FAILED(ret)) {
657 return 0;
658 }
659
660 if (DI_GUIDIsSame(&hap_instance.guidInstance, &joy_instance.guidInstance))
661 return 1;
662 }
663
664 return 0;
665 }
666
667
668 /*
669 * Opens a SDL_Haptic from a SDL_Joystick.
670 */
671 int
672 SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
673 {
674 int i;
675 HRESULT idret;
676 DIDEVICEINSTANCE joy_instance;
677 joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
678
679 /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
680 if (joystick->hwdata->bXInputDevice) {
681 const Uint8 userid = joystick->hwdata->userid;
682 for (i=0; i<SDL_numhaptics; i++) {
683 if ((SDL_hapticlist[i].bXInputHaptic) && (SDL_hapticlist[i].userid == userid)) {
684 SDL_assert(joystick->hwdata->bXInputHaptic);
685 haptic->index = i;
686 return SDL_SYS_HapticOpenFromXInput(haptic, SDL_hapticlist[haptic->index].userid);
687 }
688 }
689 } else {
690 for (i=0; i<SDL_numhaptics; i++) {
691 idret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice, &joy_instance);
692 if (FAILED(idret)) {
693 return -1;
694 }
695 if (DI_GUIDIsSame(&SDL_hapticlist[i].instance.guidInstance,
696 &joy_instance.guidInstance)) {
697 haptic->index = i;
698 return SDL_SYS_HapticOpenFromDevice8(haptic, joystick->hwdata->InputDevice, SDL_TRUE);
699 }
700 }
701 }
702 /* No match to our haptic list */
703 return -1;
704 }
705
706
707 /*
708 * Closes the haptic device.
709 */
710 void
711 SDL_SYS_HapticClose(SDL_Haptic * haptic)
712 {
713 if (haptic->hwdata) {
714
715 /* Free effects. */
716 SDL_free(haptic->effects);
717 haptic->effects = NULL;
718 haptic->neffects = 0;
719
720 /* Clean up */
721 if (haptic->hwdata->bXInputHaptic) {
722 haptic->hwdata->stopThread = 1;
723 SDL_WaitThread(haptic->hwdata->thread, NULL);
724 SDL_DestroyMutex(haptic->hwdata->mutex);
725 } else {
726 IDirectInputDevice8_Unacquire(haptic->hwdata->device);
727 /* Only release if isn't grabbed by a joystick. */
728 if (haptic->hwdata->is_joystick == 0) {
729 IDirectInputDevice8_Release(haptic->hwdata->device);
730 }
731 }
732
733 /* Free */
734 SDL_free(haptic->hwdata);
735 haptic->hwdata = NULL;
736 }
737 }
738
739
740 /*
741 * Clean up after system specific haptic stuff
742 */
743 void
744 SDL_SYS_HapticQuit(void)
745 {
746 int i;
747
748 if (loaded_xinput) {
749 WIN_UnloadXInputDLL();
750 loaded_xinput = SDL_FALSE;
751 }
752
753 for (i = 0; i < SDL_arraysize(SDL_hapticlist); ++i) {
754 SDL_free(SDL_hapticlist[i].name);
755 SDL_hapticlist[i].name = NULL;
756 }
757
758 if (dinput != NULL) {
759 IDirectInput8_Release(dinput);
760 dinput = NULL;
761 }
762
763 if (coinitialized) {
764 WIN_CoUninitialize();
765 coinitialized = SDL_FALSE;
766 }
767 }
768
769
770 /*
771 * Converts an SDL trigger button to an DIEFFECT trigger button.
772 */
773 static DWORD
774 DIGetTriggerButton(Uint16 button)
775 {
776 DWORD dwTriggerButton;
777
778 dwTriggerButton = DIEB_NOTRIGGER;
779
780 if (button != 0) {
781 dwTriggerButton = DIJOFS_BUTTON(button - 1);
782 }
783
784 return dwTriggerButton;
785 }
786
787
788 /*
789 * Sets the direction.
790 */
791 static int
792 SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir, int naxes)
793 {
794 LONG *rglDir;
795
796 /* Handle no axes a part. */
797 if (naxes == 0) {
798 effect->dwFlags |= DIEFF_SPHERICAL; /* Set as default. */
799 effect->rglDirection = NULL;
800 return 0;
801 }
802
803 /* Has axes. */
804 rglDir = SDL_malloc(sizeof(LONG) * naxes);
805 if (rglDir == NULL) {
806 return SDL_OutOfMemory();
807 }
808 SDL_memset(rglDir, 0, sizeof(LONG) * naxes);
809 effect->rglDirection = rglDir;
810
811 switch (dir->type) {
812 case SDL_HAPTIC_POLAR:
813 effect->dwFlags |= DIEFF_POLAR;
814 rglDir[0] = dir->dir[0];
815 return 0;
816 case SDL_HAPTIC_CARTESIAN:
817 effect->dwFlags |= DIEFF_CARTESIAN;
818 rglDir[0] = dir->dir[0];
819 if (naxes > 1)
820 rglDir[1] = dir->dir[1];
821 if (naxes > 2)
822 rglDir[2] = dir->dir[2];
823 return 0;
824 case SDL_HAPTIC_SPHERICAL:
825 effect->dwFlags |= DIEFF_SPHERICAL;
826 rglDir[0] = dir->dir[0];
827 if (naxes > 1)
828 rglDir[1] = dir->dir[1];
829 if (naxes > 2)
830 rglDir[2] = dir->dir[2];
831 return 0;
832
833 default:
834 return SDL_SetError("Haptic: Unknown direction type.");
835 }
836 }
837
838 #define CONVERT(x) (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
839 /*
840 * Creates the DIEFFECT from a SDL_HapticEffect.
841 */
842 static int
843 SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
844 SDL_HapticEffect * src)
845 {
846 int i;
847 DICONSTANTFORCE *constant;
848 DIPERIODIC *periodic;
849 DICONDITION *condition; /* Actually an array of conditions - one per axis. */
850 DIRAMPFORCE *ramp;
851 DICUSTOMFORCE *custom;
852 DIENVELOPE *envelope;
853 SDL_HapticConstant *hap_constant;
854 SDL_HapticPeriodic *hap_periodic;
855 SDL_HapticCondition *hap_condition;
856 SDL_HapticRamp *hap_ramp;
857 SDL_HapticCustom *hap_custom;
858 DWORD *axes;
859
860 /* Set global stuff. */
861 SDL_memset(dest, 0, sizeof(DIEFFECT));
862 dest->dwSize = sizeof(DIEFFECT); /* Set the structure size. */
863 dest->dwSamplePeriod = 0; /* Not used by us. */
864 dest->dwGain = 10000; /* Gain is set globally, not locally. */
865 dest->dwFlags = DIEFF_OBJECTOFFSETS; /* Seems obligatory. */
866
867 /* Envelope. */
868 envelope = SDL_malloc(sizeof(DIENVELOPE));
869 if (envelope == NULL) {
870 return SDL_OutOfMemory();
871 }
872 SDL_memset(envelope, 0, sizeof(DIENVELOPE));
873 dest->lpEnvelope = envelope;
874 envelope->dwSize = sizeof(DIENVELOPE); /* Always should be this. */
875
876 /* Axes. */
877 dest->cAxes = haptic->naxes;
878 if (dest->cAxes > 0) {
879 axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
880 if (axes == NULL) {
881 return SDL_OutOfMemory();
882 }
883 axes[0] = haptic->hwdata->axes[0]; /* Always at least one axis. */
884 if (dest->cAxes > 1) {
885 axes[1] = haptic->hwdata->axes[1];
886 }
887 if (dest->cAxes > 2) {
888 axes[2] = haptic->hwdata->axes[2];
889 }
890 dest->rgdwAxes = axes;
891 }
892
893
894 /* The big type handling switch, even bigger then Linux's version. */
895 switch (src->type) {
896 case SDL_HAPTIC_CONSTANT:
897 hap_constant = &src->constant;
898 constant = SDL_malloc(sizeof(DICONSTANTFORCE));
899 if (constant == NULL) {
900 return SDL_OutOfMemory();
901 }
902 SDL_memset(constant, 0, sizeof(DICONSTANTFORCE));
903
904 /* Specifics */
905 constant->lMagnitude = CONVERT(hap_constant->level);
906 dest->cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
907 dest->lpvTypeSpecificParams = constant;
908
909 /* Generics */
910 dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */
911 dest->dwTriggerButton = DIGetTriggerButton(hap_constant->button);
912 dest->dwTriggerRepeatInterval = hap_constant->interval;
913 dest->dwStartDelay = hap_constant->delay * 1000; /* In microseconds. */
914
915 /* Direction. */
916 if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes)
917 < 0) {
918 return -1;
919 }
920
921 /* Envelope */
922 if ((hap_constant->attack_length == 0)
923 && (hap_constant->fade_length == 0)) {
924 SDL_free(dest->lpEnvelope);
925 dest->lpEnvelope = NULL;
926 } else {
927 envelope->dwAttackLevel = CONVERT(hap_constant->attack_level);
928 envelope->dwAttackTime = hap_constant->attack_length * 1000;
929 envelope->dwFadeLevel = CONVERT(hap_constant->fade_level);
930 envelope->dwFadeTime = hap_constant->fade_length * 1000;
931 }
932
933 break;
934
935 case SDL_HAPTIC_SINE:
936 /* !!! FIXME: put this back when we have more bits in 2.1 */
937 /* case SDL_HAPTIC_SQUARE: */
938 case SDL_HAPTIC_TRIANGLE:
939 case SDL_HAPTIC_SAWTOOTHUP:
940 case SDL_HAPTIC_SAWTOOTHDOWN:
941 hap_periodic = &src->periodic;
942 periodic = SDL_malloc(sizeof(DIPERIODIC));
943 if (periodic == NULL) {
944 return SDL_OutOfMemory();
945 }
946 SDL_memset(periodic, 0, sizeof(DIPERIODIC));
947
948 /* Specifics */
949 periodic->dwMagnitude = CONVERT(hap_periodic->magnitude);
950 periodic->lOffset = CONVERT(hap_periodic->offset);
951 periodic->dwPhase = hap_periodic->phase;
952 periodic->dwPeriod = hap_periodic->period * 1000;
953 dest->cbTypeSpecificParams = sizeof(DIPERIODIC);
954 dest->lpvTypeSpecificParams = periodic;
955
956 /* Generics */
957 dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */
958 dest->dwTriggerButton = DIGetTriggerButton(hap_periodic->button);
959 dest->dwTriggerRepeatInterval = hap_periodic->interval;
960 dest->dwStartDelay = hap_periodic->delay * 1000; /* In microseconds. */
961
962 /* Direction. */
963 if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes)
964 < 0) {
965 return -1;
966 }
967
968 /* Envelope */
969 if ((hap_periodic->attack_length == 0)
970 && (hap_periodic->fade_length == 0)) {
971 SDL_free(dest->lpEnvelope);
972 dest->lpEnvelope = NULL;
973 } else {
974 envelope->dwAttackLevel = CONVERT(hap_periodic->attack_level);
975 envelope->dwAttackTime = hap_periodic->attack_length * 1000;
976 envelope->dwFadeLevel = CONVERT(hap_periodic->fade_level);
977 envelope->dwFadeTime = hap_periodic->fade_length * 1000;
978 }
979
980 break;
981
982 case SDL_HAPTIC_SPRING:
983 case SDL_HAPTIC_DAMPER:
984 case SDL_HAPTIC_INERTIA:
985 case SDL_HAPTIC_FRICTION:
986 hap_condition = &src->condition;
987 condition = SDL_malloc(sizeof(DICONDITION) * dest->cAxes);
988 if (condition == NULL) {
989 return SDL_OutOfMemory();
990 }
991 SDL_memset(condition, 0, sizeof(DICONDITION));
992
993 /* Specifics */
994 for (i = 0; i < (int) dest->cAxes; i++) {
995 condition[i].lOffset = CONVERT(hap_condition->center[i]);
996 condition[i].lPositiveCoefficient =
997 CONVERT(hap_condition->right_coeff[i]);
998 condition[i].lNegativeCoefficient =
999 CONVERT(hap_condition->left_coeff[i]);
1000 condition[i].dwPositiveSaturation =
1001 CONVERT(hap_condition->right_sat[i]);
1002 condition[i].dwNegativeSaturation =
1003 CONVERT(hap_condition->left_sat[i]);
1004 condition[i].lDeadBand = CONVERT(hap_condition->deadband[i]);
1005 }
1006 dest->cbTypeSpecificParams = sizeof(DICONDITION) * dest->cAxes;
1007 dest->lpvTypeSpecificParams = condition;
1008
1009 /* Generics */
1010 dest->dwDuration = hap_condition->length * 1000; /* In microseconds. */
1011 dest->dwTriggerButton = DIGetTriggerButton(hap_condition->button);
1012 dest->dwTriggerRepeatInterval = hap_condition->interval;
1013 dest->dwStartDelay = hap_condition->delay * 1000; /* In microseconds. */
1014
1015 /* Direction. */
1016 if (SDL_SYS_SetDirection(dest, &hap_condition->direction, dest->cAxes)
1017 < 0) {
1018 return -1;
1019 }
1020
1021 /* Envelope - Not actually supported by most CONDITION implementations. */
1022 SDL_free(dest->lpEnvelope);
1023 dest->lpEnvelope = NULL;
1024
1025 break;
1026
1027 case SDL_HAPTIC_RAMP:
1028 hap_ramp = &src->ramp;
1029 ramp = SDL_malloc(sizeof(DIRAMPFORCE));
1030 if (ramp == NULL) {
1031 return SDL_OutOfMemory();
1032 }
1033 SDL_memset(ramp, 0, sizeof(DIRAMPFORCE));
1034
1035 /* Specifics */
1036 ramp->lStart = CONVERT(hap_ramp->start);
1037 ramp->lEnd = CONVERT(hap_ramp->end);
1038 dest->cbTypeSpecificParams = sizeof(DIRAMPFORCE);
1039 dest->lpvTypeSpecificParams = ramp;
1040
1041 /* Generics */
1042 dest->dwDuration = hap_ramp->length * 1000; /* In microseconds. */
1043 dest->dwTriggerButton = DIGetTriggerButton(hap_ramp->button);
1044 dest->dwTriggerRepeatInterval = hap_ramp->interval;
1045 dest->dwStartDelay = hap_ramp->delay * 1000; /* In microseconds. */
1046
1047 /* Direction. */
1048 if (SDL_SYS_SetDirection(dest, &hap_ramp->direction, dest->cAxes) < 0) {
1049 return -1;
1050 }
1051
1052 /* Envelope */
1053 if ((hap_ramp->attack_length == 0) && (hap_ramp->fade_length == 0)) {
1054 SDL_free(dest->lpEnvelope);
1055 dest->lpEnvelope = NULL;
1056 } else {
1057 envelope->dwAttackLevel = CONVERT(hap_ramp->attack_level);
1058 envelope->dwAttackTime = hap_ramp->attack_length * 1000;
1059 envelope->dwFadeLevel = CONVERT(hap_ramp->fade_level);
1060 envelope->dwFadeTime = hap_ramp->fade_length * 1000;
1061 }
1062
1063 break;
1064
1065 case SDL_HAPTIC_CUSTOM:
1066 hap_custom = &src->custom;
1067 custom = SDL_malloc(sizeof(DICUSTOMFORCE));
1068 if (custom == NULL) {
1069 return SDL_OutOfMemory();
1070 }
1071 SDL_memset(custom, 0, sizeof(DICUSTOMFORCE));
1072
1073 /* Specifics */
1074 custom->cChannels = hap_custom->channels;
1075 custom->dwSamplePeriod = hap_custom->period * 1000;
1076 custom->cSamples = hap_custom->samples;
1077 custom->rglForceData =
1078 SDL_malloc(sizeof(LONG) * custom->cSamples * custom->cChannels);
1079 for (i = 0; i < hap_custom->samples * hap_custom->channels; i++) { /* Copy data. */
1080 custom->rglForceData[i] = CONVERT(hap_custom->data[i]);
1081 }
1082 dest->cbTypeSpecificParams = sizeof(DICUSTOMFORCE);
1083 dest->lpvTypeSpecificParams = custom;
1084
1085 /* Generics */
1086 dest->dwDuration = hap_custom->length * 1000; /* In microseconds. */
1087 dest->dwTriggerButton = DIGetTriggerButton(hap_custom->button);
1088 dest->dwTriggerRepeatInterval = hap_custom->interval;
1089 dest->dwStartDelay = hap_custom->delay * 1000; /* In microseconds. */
1090
1091 /* Direction. */
1092 if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) <
1093 0) {
1094 return -1;
1095 }
1096
1097 /* Envelope */
1098 if ((hap_custom->attack_length == 0)
1099 && (hap_custom->fade_length == 0)) {
1100 SDL_free(dest->lpEnvelope);
1101 dest->lpEnvelope = NULL;
1102 } else {
1103 envelope->dwAttackLevel = CONVERT(hap_custom->attack_level);
1104 envelope->dwAttackTime = hap_custom->attack_length * 1000;
1105 envelope->dwFadeLevel = CONVERT(hap_custom->fade_level);
1106 envelope->dwFadeTime = hap_custom->fade_length * 1000;
1107 }
1108
1109 break;
1110
1111
1112 default:
1113 return SDL_SetError("Haptic: Unknown effect type.");
1114 }
1115
1116 return 0;
1117 }
1118
1119
1120 /*
1121 * Frees an DIEFFECT allocated by SDL_SYS_ToDIEFFECT.
1122 */
1123 static void
1124 SDL_SYS_HapticFreeDIEFFECT(DIEFFECT * effect, int type)
1125 {
1126 DICUSTOMFORCE *custom;
1127
1128 SDL_free(effect->lpEnvelope);
1129 effect->lpEnvelope = NULL;
1130 SDL_free(effect->rgdwAxes);
1131 effect->rgdwAxes = NULL;
1132 if (effect->lpvTypeSpecificParams != NULL) {
1133 if (type == SDL_HAPTIC_CUSTOM) { /* Must free the custom data. */
1134 custom = (DICUSTOMFORCE *) effect->lpvTypeSpecificParams;
1135 SDL_free(custom->rglForceData);
1136 custom->rglForceData = NULL;
1137 }
1138 SDL_free(effect->lpvTypeSpecificParams);
1139 effect->lpvTypeSpecificParams = NULL;
1140 }
1141 SDL_free(effect->rglDirection);
1142 effect->rglDirection = NULL;
1143 }
1144
1145
1146 /*
1147 * Gets the effect type from the generic SDL haptic effect wrapper.
1148 */
1149 static REFGUID
1150 SDL_SYS_HapticEffectType(SDL_HapticEffect * effect)
1151 {
1152 switch (effect->type) {
1153 case SDL_HAPTIC_CONSTANT:
1154 return &GUID_ConstantForce;
1155
1156 case SDL_HAPTIC_RAMP:
1157 return &GUID_RampForce;
1158
1159 /* !!! FIXME: put this back when we have more bits in 2.1 */
1160 /* case SDL_HAPTIC_SQUARE:
1161 return &GUID_Square; */
1162
1163 case SDL_HAPTIC_SINE:
1164 return &GUID_Sine;
1165
1166 case SDL_HAPTIC_TRIANGLE:
1167 return &GUID_Triangle;
1168
1169 case SDL_HAPTIC_SAWTOOTHUP:
1170 return &GUID_SawtoothUp;
1171
1172 case SDL_HAPTIC_SAWTOOTHDOWN:
1173 return &GUID_SawtoothDown;
1174
1175 case SDL_HAPTIC_SPRING:
1176 return &GUID_Spring;
1177
1178 case SDL_HAPTIC_DAMPER:
1179 return &GUID_Damper;
1180
1181 case SDL_HAPTIC_INERTIA:
1182 return &GUID_Inertia;
1183
1184 case SDL_HAPTIC_FRICTION:
1185 return &GUID_Friction;
1186
1187 case SDL_HAPTIC_CUSTOM:
1188 case SDL_HAPTIC_LEFTRIGHT:
1189 return &GUID_CustomForce;
1190
1191 default:
1192 SDL_SetError("Haptic: Unknown effect type.");
1193 return NULL;
1194 }
1195 }
1196
1197
1198 /*
1199 * Creates a new haptic effect.
1200 */
1201 int
1202 SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
1203 SDL_HapticEffect * base)
1204 {
1205 HRESULT ret;
1206 REFGUID type = SDL_SYS_HapticEffectType(base);
1207
1208 if ((type == NULL) && (!haptic->hwdata->bXInputHaptic)) {
1209 goto err_hweffect;
1210 }
1211
1212 /* Alloc the effect. */
1213 effect->hweffect = (struct haptic_hweffect *)
1214 SDL_malloc(sizeof(struct haptic_hweffect));
1215 if (effect->hweffect == NULL) {
1216 SDL_OutOfMemory();
1217 goto err_hweffect;
1218 }
1219
1220 SDL_zerop(effect->hweffect);
1221
1222 if (haptic->hwdata->bXInputHaptic) {
1223 SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
1224 return SDL_SYS_HapticUpdateEffect(haptic, effect, base);
1225 }
1226
1227 /* Get the effect. */
1228 if (SDL_SYS_ToDIEFFECT(haptic, &effect->hweffect->effect, base) < 0) {
1229 goto err_effectdone;
1230 }
1231
1232 /* Create the actual effect. */
1233 ret = IDirectInputDevice8_CreateEffect(haptic->hwdata->device, type,
1234 &effect->hweffect->effect,
1235 &effect->hweffect->ref, NULL);
1236 if (FAILED(ret)) {
1237 DI_SetError("Unable to create effect", ret);
1238 goto err_effectdone;
1239 }
1240
1241 return 0;
1242
1243 err_effectdone:
1244 SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, base->type);
1245 err_hweffect:
1246 SDL_free(effect->hweffect);
1247 effect->hweffect = NULL;
1248 return -1;
1249 }
1250
1251
1252 /*
1253 * Updates an effect.
1254 */
1255 int
1256 SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
1257 struct haptic_effect *effect,
1258 SDL_HapticEffect * data)
1259 {
1260 HRESULT ret;
1261 DWORD flags;
1262 DIEFFECT temp;
1263
1264 if (haptic->hwdata->bXInputHaptic) {
1265 XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
1266 SDL_assert(data->type == SDL_HAPTIC_LEFTRIGHT);
1267 vib->wLeftMotorSpeed = data->leftright.large_magnitude;
1268 vib->wRightMotorSpeed = data->leftright.small_magnitude;
1269 SDL_LockMutex(haptic->hwdata->mutex);
1270 if (haptic->hwdata->stopTicks) { /* running right now? Update it. */
1271 XINPUTSETSTATE(haptic->hwdata->userid, vib);
1272 }
1273 SDL_UnlockMutex(haptic->hwdata->mutex);
1274 return 0;
1275 }
1276
1277 /* Get the effect. */
1278 SDL_memset(&temp, 0, sizeof(DIEFFECT));
1279 if (SDL_SYS_ToDIEFFECT(haptic, &temp, data) < 0) {
1280 goto err_update;
1281 }
1282
1283 /* Set the flags. Might be worthwhile to diff temp with loaded effect and
1284 * only change those parameters. */
1285 flags = DIEP_DIRECTION |
1286 DIEP_DURATION |
1287 DIEP_ENVELOPE |
1288 DIEP_STARTDELAY |
1289 DIEP_TRIGGERBUTTON |
1290 DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS;
1291
1292 /* Create the actual effect. */
1293 ret =
1294 IDirectInputEffect_SetParameters(effect->hweffect->ref, &temp, flags);
1295 if (FAILED(ret)) {
1296 DI_SetError("Unable to update effect", ret);
1297 goto err_update;
1298 }
1299
1300 /* Copy it over. */
1301 SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, data->type);
1302 SDL_memcpy(&effect->hweffect->effect, &temp, sizeof(DIEFFECT));
1303
1304 return 0;
1305
1306 err_update:
1307 SDL_SYS_HapticFreeDIEFFECT(&temp, data->type);
1308 return -1;
1309 }
1310
1311
1312 /*
1313 * Runs an effect.
1314 */
1315 int
1316 SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
1317 Uint32 iterations)
1318 {
1319 HRESULT ret;
1320 DWORD iter;
1321
1322 if (haptic->hwdata->bXInputHaptic) {
1323 XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
1324 SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
1325 SDL_LockMutex(haptic->hwdata->mutex);
1326 if(effect->effect.leftright.length == SDL_HAPTIC_INFINITY || iterations == SDL_HAPTIC_INFINITY)
1327 haptic->hwdata->stopTicks = SDL_HAPTIC_INFINITY;
1328 else
1329 haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations);
1330 SDL_UnlockMutex(haptic->hwdata->mutex);
1331 return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;
1332 }
1333
1334 /* Check if it's infinite. */
1335 if (iterations == SDL_HAPTIC_INFINITY) {
1336 iter = INFINITE;
1337 } else
1338 iter = iterations;
1339
1340 /* Run the effect. */
1341 ret = IDirectInputEffect_Start(effect->hweffect->ref, iter, 0);
1342 if (FAILED(ret)) {
1343 return DI_SetError("Running the effect", ret);
1344 }
1345
1346 return 0;
1347 }
1348
1349
1350 /*
1351 * Stops an effect.
1352 */
1353 int
1354 SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
1355 {
1356 HRESULT ret;
1357
1358 if (haptic->hwdata->bXInputHaptic) {
1359 XINPUT_VIBRATION vibration = { 0, 0 };
1360 SDL_LockMutex(haptic->hwdata->mutex);
1361 haptic->hwdata->stopTicks = 0;
1362 SDL_UnlockMutex(haptic->hwdata->mutex);
1363 return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
1364 }
1365
1366 ret = IDirectInputEffect_Stop(effect->hweffect->ref);
1367 if (FAILED(ret)) {
1368 return DI_SetError("Unable to stop effect", ret);
1369 }
1370
1371 return 0;
1372 }
1373
1374
1375 /*
1376 * Frees the effect.
1377 */
1378 void
1379 SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
1380 {
1381 HRESULT ret;
1382
1383 if (haptic->hwdata->bXInputHaptic) {
1384 SDL_SYS_HapticStopEffect(haptic, effect);
1385 } else {
1386 ret = IDirectInputEffect_Unload(effect->hweffect->ref);
1387 if (FAILED(ret)) {
1388 DI_SetError("Removing effect from the device", ret);
1389 }
1390 SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect,
1391 effect->effect.type);
1392 }
1393 SDL_free(effect->hweffect);
1394 effect->hweffect = NULL;
1395 }
1396
1397
1398 /*
1399 * Gets the status of a haptic effect.
1400 */
1401 int
1402 SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
1403 struct haptic_effect *effect)
1404 {
1405 HRESULT ret;
1406 DWORD status;
1407
1408 ret = IDirectInputEffect_GetEffectStatus(effect->hweffect->ref, &status);
1409 if (FAILED(ret)) {
1410 return DI_SetError("Getting effect status", ret);
1411 }
1412
1413 if (status == 0)
1414 return SDL_FALSE;
1415 return SDL_TRUE;
1416 }
1417
1418
1419 /*
1420 * Sets the gain.
1421 */
1422 int
1423 SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
1424 {
1425 HRESULT ret;
1426 DIPROPDWORD dipdw;
1427
1428 /* Create the weird structure thingy. */
1429 dipdw.diph.dwSize = sizeof(DIPROPDWORD);
1430 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
1431 dipdw.diph.dwObj = 0;
1432 dipdw.diph.dwHow = DIPH_DEVICE;
1433 dipdw.dwData = gain * 100; /* 0 to 10,000 */
1434
1435 /* Try to set the autocenter. */
1436 ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
1437 DIPROP_FFGAIN, &dipdw.diph);
1438 if (FAILED(ret)) {
1439 return DI_SetError("Setting gain", ret);
1440 }
1441
1442 return 0;
1443 }
1444
1445
1446 /*
1447 * Sets the autocentering.
1448 */
1449 int
1450 SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
1451 {
1452 HRESULT ret;
1453 DIPROPDWORD dipdw;
1454
1455 /* Create the weird structure thingy. */
1456 dipdw.diph.dwSize = sizeof(DIPROPDWORD);
1457 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
1458 dipdw.diph.dwObj = 0;
1459 dipdw.diph.dwHow = DIPH_DEVICE;
1460 dipdw.dwData = (autocenter == 0) ? DIPROPAUTOCENTER_OFF :
1461 DIPROPAUTOCENTER_ON;
1462
1463 /* Try to set the autocenter. */
1464 ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
1465 DIPROP_AUTOCENTER, &dipdw.diph);
1466 if (FAILED(ret)) {
1467 return DI_SetError("Setting autocenter", ret);
1468 }
1469
1470 return 0;
1471 }
1472
1473
1474 /*
1475 * Pauses the device.
1476 */
1477 int
1478 SDL_SYS_HapticPause(SDL_Haptic * haptic)
1479 {
1480 HRESULT ret;
1481
1482 /* Pause the device. */
1483 ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
1484 DISFFC_PAUSE);
1485 if (FAILED(ret)) {
1486 return DI_SetError("Pausing the device", ret);
1487 }
1488
1489 return 0;
1490 }
1491
1492
1493 /*
1494 * Pauses the device.
1495 */
1496 int
1497 SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
1498 {
1499 HRESULT ret;
1500
1501 /* Unpause the device. */
1502 ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
1503 DISFFC_CONTINUE);
1504 if (FAILED(ret)) {
1505 return DI_SetError("Pausing the device", ret);
1506 }
1507
1508 return 0;
1509 }
1510
1511
1512 /*
1513 * Stops all the playing effects on the device.
1514 */
1515 int
1516 SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
1517 {
1518 HRESULT ret;
1519
1520 if (haptic->hwdata->bXInputHaptic) {
1521 XINPUT_VIBRATION vibration = { 0, 0 };
1522 SDL_LockMutex(haptic->hwdata->mutex);
1523 haptic->hwdata->stopTicks = 0;
1524 SDL_UnlockMutex(haptic->hwdata->mutex);
1525 return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
1526 }
1527
1528 /* Try to stop the effects. */
1529 ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
1530 DISFFC_STOPALL);
1531 if (FAILED(ret)) {
1532 return DI_SetError("Stopping the device", ret);
1533 }
1534
1535 return 0;
1536 }
1537
1538
1539 /* !!! FIXME: this is a hack, remove this later. */
1540 /* Since XInput doesn't offer a way to vibrate for X time, we hook into
1541 * SDL_PumpEvents() to check if it's time to stop vibrating with some
1542 * frequency.
1543 * In practice, this works for 99% of use cases. But in an ideal world,
1544 * we do this in a separate thread so that:
1545 * - we aren't bound to when the app chooses to pump the event queue.
1546 * - we aren't adding more polling to the event queue
1547 * - we can emulate all the haptic effects correctly (start on a delay,
1548 * mix multiple effects, etc).
1549 *
1550 * Mostly, this is here to get rumbling to work, and all the other features
1551 * are absent in the XInput path for now. :(
1552 */
1553 static int SDLCALL
1554 SDL_RunXInputHaptic(void *arg)
1555 {
1556 struct haptic_hwdata *hwdata = (struct haptic_hwdata *) arg;
1557
1558 while (!hwdata->stopThread) {
1559 SDL_Delay(50);
1560 SDL_LockMutex(hwdata->mutex);
1561 /* If we're currently running and need to stop... */
1562 if ((hwdata->stopTicks) && (hwdata->stopTicks < SDL_GetTicks())) {
1563 XINPUT_VIBRATION vibration = { 0, 0 };
1564 hwdata->stopTicks = 0;
1565 XINPUTSETSTATE(hwdata->userid, &vibration);
1566 }
1567 SDL_UnlockMutex(hwdata->mutex);
1568 }
1569
1570 return 0;
1571 }
1572
1573 #endif /* SDL_HAPTIC_DINPUT */
1574
1575 /* vi: set ts=4 sw=4 expandtab: */
SDL_SYS_HapticOpenFromJoystick
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
_SDL_Haptic::hwdata
struct haptic_hwdata * hwdata
Definition: SDL_syshaptic.h:52
SDL_HapticPeriodic::period
Uint16 period
Definition: SDL_haptic.h:555
SDL_HapticCondition::deadband
Uint16 deadband[3]
Definition: SDL_haptic.h:611
DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION
Definition: directx.h:74
SDL_HapticDirection
Structure that represents a haptic direction.
Definition: SDL_haptic.h:439
condition
GLenum condition
Definition: gl2ext.h:1403
SDL_HapticCondition::delay
Uint16 delay
Definition: SDL_haptic.h:600
SDL_HapticConstant::interval
Uint16 interval
Definition: SDL_haptic.h:469
_SDL_Haptic::effects
struct haptic_effect * effects
Definition: SDL_syshaptic.h:46
SDL_HAPTIC_SPHERICAL
#define SDL_HAPTIC_SPHERICAL
Uses spherical coordinates for the direction.
Definition: SDL_haptic.h:329
SDL_HapticConstant::fade_level
Uint16 fade_level
Definition: SDL_haptic.h:478
SDL_joystick.h
joystick_hwdata::InputDevice
LPDIRECTINPUTDEVICE8 InputDevice
Definition: SDL_dxjoystick_c.h:133
type
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
SDL_HAPTIC_AUTOCENTER
#define SDL_HAPTIC_AUTOCENTER
Device can set autocenter.
Definition: SDL_haptic.h:285
_SDL_Haptic::index
Uint8 index
Definition: SDL_syshaptic.h:44
SDL_HapticPeriodic
A structure containing a template for a Periodic effect.
Definition: SDL_haptic.h:538
NULL
#define NULL
Definition: ftobjs.h:61
SDL_snprintf
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
SDL_HAPTIC_GAIN
#define SDL_HAPTIC_GAIN
Device can set global gain.
Definition: SDL_haptic.h:276
HRESULT
typedef HRESULT(WINAPI *LPD3DXIMTSIGNALCALLBACK)(CONST D3DXVECTOR2 *uv
SDL_HAPTIC_CUSTOM
#define SDL_HAPTIC_CUSTOM
Custom effect is supported.
Definition: SDL_haptic.h:263
SDL_LockMutex
DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:73
SDL_HAPTIC_TRIANGLE
#define SDL_HAPTIC_TRIANGLE
Triangle wave effect supported.
Definition: SDL_haptic.h:189
SDL_HapticCondition::direction
SDL_HapticDirection direction
Definition: SDL_haptic.h:596
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:116
SDL_SYS_HapticOpen
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
SDL_HapticPeriodic::length
Uint32 length
Definition: SDL_haptic.h:547
SDL_HapticEffect::custom
SDL_HapticCustom custom
Definition: SDL_haptic.h:796
SDL_SYS_HapticMouse
int SDL_SYS_HapticMouse(void)
SDL_SYS_JoystickSameHaptic
int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
_SDL_Haptic
Definition: SDL_syshaptic.h:42
SDL_HapticRamp::end
Sint16 end
Definition: SDL_haptic.h:644
SDL_HapticCondition::button
Uint16 button
Definition: SDL_haptic.h:603
SDL_TRUE
Definition: SDL_stdinc.h:119
SDL_HAPTIC_INERTIA
#define SDL_HAPTIC_INERTIA
Inertia effect supported - uses axes acceleration.
Definition: SDL_haptic.h:246
SDL_CreateMutex
DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void)
Definition: SDL_sysmutex.c:38
_SDL_Haptic::naxes
int naxes
Definition: SDL_syshaptic.h:50
SDL_free
DECLSPEC void SDLCALL SDL_free(void *mem)
SDL_HapticRamp::fade_level
Uint16 fade_level
Definition: SDL_haptic.h:650
SDL_HapticEffect::ramp
SDL_HapticRamp ramp
Definition: SDL_haptic.h:794
joystick_hwdata::userid
Uint8 userid
Definition: SDL_dxjoystick_c.h:145
SDL_HapticCondition::interval
Uint16 interval
Definition: SDL_haptic.h:604
SDL_SYS_HapticStopEffect
int SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
SDL_SYS_HapticName
const char * SDL_SYS_HapticName(int index)
SDL_HapticCondition
A structure containing a template for a Condition effect.
Definition: SDL_haptic.h:591
name
EGLImageKHR EGLint * name
Definition: eglext.h:284
SDL_memcmp
DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len)
Definition: SDL_string.c:370
SDL_HapticPeriodic::fade_level
Uint16 fade_level
Definition: SDL_haptic.h:564
SDL_haptic.h
The SDL Haptic subsystem allows you to control haptic (force feedback) devices.
SDL_SYS_HapticUnpause
int SDL_SYS_HapticUnpause(SDL_Haptic *haptic)
SDL_HapticConstant::attack_length
Uint16 attack_length
Definition: SDL_haptic.h:475
SDL_HapticCondition::left_coeff
Sint16 left_coeff[3]
Definition: SDL_haptic.h:610
SDL_HapticLeftRight::small_magnitude
Uint16 small_magnitude
Definition: SDL_haptic.h:675
SDL_HapticCondition::right_sat
Uint16 right_sat[3]
Definition: SDL_haptic.h:607
SDL_HapticPeriodic::button
Uint16 button
Definition: SDL_haptic.h:551
XINPUT_CAPS_FFB_SUPPORTED
#define XINPUT_CAPS_FFB_SUPPORTED
Definition: SDL_dxjoystick_c.h:54
SDLCALL
#define SDLCALL
Definition: begin_code.h:72
SDL_HapticCustom::fade_length
Uint16 fade_length
Definition: SDL_haptic.h:714
SDL_HapticCondition::right_coeff
Sint16 right_coeff[3]
Definition: SDL_haptic.h:609
SDL_HapticDirection::type
Uint8 type
Definition: SDL_haptic.h:441
SDL_HAPTIC_SINE
#define SDL_HAPTIC_SINE
Sine wave effect supported.
Definition: SDL_haptic.h:166
SDL_FALSE
Definition: SDL_stdinc.h:118
SDL_HapticPeriodic::attack_level
Uint16 attack_level
Definition: SDL_haptic.h:562
XINPUTGETCAPABILITIES
#define XINPUTGETCAPABILITIES
Definition: SDL_dxjoystick_c.h:107
XINPUTSETSTATE
#define XINPUTSETSTATE
Definition: SDL_dxjoystick_c.h:106
SDL_XINPUT_MAX_DEVICES
#define SDL_XINPUT_MAX_DEVICES
Definition: SDL_dxjoystick_c.h:109
SDL_SYS_HapticGetEffectStatus
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
SDL_config.h
SDL_UnlockMutex
DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:160
_SDL_Joystick::hwdata
struct joystick_hwdata * hwdata
Definition: SDL_sysjoystick.h:49
ret
ret
Definition: glew_str_glx.c:2
SDL_HapticCustom::data
Uint16 * data
Definition: SDL_haptic.h:709
SDL_HapticRamp::length
Uint32 length
Definition: SDL_haptic.h:635
SDL_HapticConstant
A structure containing a template for a Constant effect.
Definition: SDL_haptic.h:457
SDL_numhaptics
Uint8 SDL_numhaptics
Definition: SDL_haptic.c:28
joystick_hwdata
Definition: SDL_sysjoystick_c.h:58
joystick_hwdata::Capabilities
DIDEVCAPS Capabilities
Definition: SDL_dxjoystick_c.h:134
_SDL_Haptic::neffects
int neffects
Definition: SDL_syshaptic.h:47
SDL_HINT_XINPUT_ENABLED
#define SDL_HINT_XINPUT_ENABLED
A variable that lets you disable the detection and use of Xinput gamepad devices. ...
Definition: SDL_hints.h:215
SDL_HAPTIC_INFINITY
#define SDL_HAPTIC_INFINITY
Used to play a device an infinite number of times.
Definition: SDL_haptic.h:344
SDL_HapticRamp::interval
Uint16 interval
Definition: SDL_haptic.h:640
joystick_hwdata::axes
long axes
Definition: SDL_sysjoystick_c.h:69
SDL_HAPTIC_CARTESIAN
#define SDL_HAPTIC_CARTESIAN
Uses cartesian coordinates for the direction.
Definition: SDL_haptic.h:322
Uint32
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
SDL_HapticPeriodic::fade_length
Uint16 fade_length
Definition: SDL_haptic.h:563
_SDL_Haptic::supported
unsigned int supported
Definition: SDL_syshaptic.h:49
SDL_WaitThread
DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread *thread, int *status)
Definition: SDL_thread.c:399
SDL_HapticEffect::condition
SDL_HapticCondition condition
Definition: SDL_haptic.h:793
SDL_GetTicks
DECLSPEC Uint32 SDLCALL SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
Definition: SDL_systimer.c:44
SDL_HapticConstant::level
Sint16 level
Definition: SDL_haptic.h:472
SDL_HapticEffect
The generic template for any haptic effect.
Definition: SDL_haptic.h:787
SDL_HapticConstant::delay
Uint16 delay
Definition: SDL_haptic.h:465
SDL_HAPTIC_CONSTANT
#define SDL_HAPTIC_CONSTANT
Constant effect supported.
Definition: SDL_haptic.h:157
SDL_SYS_HapticSetAutocenter
int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
SDL_HapticConstant::attack_level
Uint16 attack_level
Definition: SDL_haptic.h:476
int
int
Definition: SDL_systhread.c:37
SDL_HapticCondition::length
Uint32 length
Definition: SDL_haptic.h:599
SDL_HapticPeriodic::offset
Sint16 offset
Definition: SDL_haptic.h:557
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
WIN_UnloadXInputDLL
void WIN_UnloadXInputDLL(void)
WIN_CoInitialize
HRESULT WIN_CoInitialize(void)
SDL_strdup
DECLSPEC char *SDLCALL SDL_strdup(const char *str)
Definition: SDL_string.c:511
SDL_HapticCustom::button
Uint16 button
Definition: SDL_haptic.h:702
haptic_effect
Definition: SDL_syshaptic.h:33
SDL_HAPTIC_POLAR
#define SDL_HAPTIC_POLAR
Uses polar coordinates for the direction.
Definition: SDL_haptic.h:315
SDL_HapticCustom::period
Uint16 period
Definition: SDL_haptic.h:707
SDL_Delay
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
Wait a specified number of milliseconds before returning.
Definition: SDL_systimer.c:70
pContext
static void * pContext
Definition: dsound.c:51
SDL_memset
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
SDL_HapticCustom::fade_level
Uint16 fade_level
Definition: SDL_haptic.h:715
joystick_hwdata::bXInputDevice
Uint8 bXInputDevice
Definition: SDL_dxjoystick_c.h:143
SDL_hints.h
WIN_StringToUTF8
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:41
SDL_HapticEffect::constant
SDL_HapticConstant constant
Definition: SDL_haptic.h:791
SDL_SetError
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
SDL_HAPTIC_PAUSE
#define SDL_HAPTIC_PAUSE
Device can be paused.
Definition: SDL_haptic.h:302
SDL_malloc
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
index
GLuint index
Definition: glew.h:1800
SDL_SYS_HapticUpdateEffect
int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
SDL_HapticDirection::dir
Sint32 dir[3]
Definition: SDL_haptic.h:442
SDL_HapticCustom::length
Uint32 length
Definition: SDL_haptic.h:698
SDL_SYS_JoystickIsHaptic
int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
SDL_HapticConstant::length
Uint32 length
Definition: SDL_haptic.h:464
SDL_HapticRamp::direction
SDL_HapticDirection direction
Definition: SDL_haptic.h:632
SDL_GetHint
DECLSPEC const char *SDLCALL SDL_GetHint(const char *name)
Get a hint.
Definition: SDL_hints.c:104
SDL_HapticConstant::button
Uint16 button
Definition: SDL_haptic.h:468
SDL_HapticEffect::type
Uint16 type
Definition: SDL_haptic.h:790
SDL_HapticRamp
A structure containing a template for a Ramp effect.
Definition: SDL_haptic.h:628
env
jmp_buf env
Definition: jumphack.c:12
SDL_CreateThread
DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data)
SDL_SYS_HapticDestroyEffect
void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
SDL_HapticRamp::attack_length
Uint16 attack_length
Definition: SDL_haptic.h:647
LPVOID
typedef LPVOID(WINAPI *PFNWGLCREATEIMAGEBUFFERI3DPROC)(HDC hDC
SDL_XInputVersion
DWORD SDL_XInputVersion
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:159
thread
static SDL_Thread * thread
Definition: SDL_sysjoystick.c:41
SDL_HapticRamp::fade_length
Uint16 fade_length
Definition: SDL_haptic.h:649
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
joystick_hwdata::bXInputHaptic
Uint8 bXInputHaptic
Definition: SDL_dxjoystick_c.h:144
SDL_HapticRamp::delay
Uint16 delay
Definition: SDL_haptic.h:636
WIN_CoUninitialize
void WIN_CoUninitialize(void)
haptic_effect::effect
SDL_HapticEffect effect
Definition: SDL_syshaptic.h:35
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
SDL_mutex
struct SDL_mutex SDL_mutex
Definition: SDL_mutex.h:59
SDL_HapticCustom::delay
Uint16 delay
Definition: SDL_haptic.h:699
SDL_SYS_HapticInit
int SDL_SYS_HapticInit(void)
SDL_SYS_HapticQuit
void SDL_SYS_HapticQuit(void)
haptic_effect::hweffect
struct haptic_hweffect * hweffect
Definition: SDL_syshaptic.h:36
WIN_LoadXInputDLL
int WIN_LoadXInputDLL(void)
SDL_HAPTIC_STATUS
#define SDL_HAPTIC_STATUS
Device can be queried for effect status.
Definition: SDL_haptic.h:294
SDL_SYS_HapticClose
void SDL_SYS_HapticClose(SDL_Haptic *haptic)
SDL_SYS_HapticPause
int SDL_SYS_HapticPause(SDL_Haptic *haptic)
SDL_memcpy
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
Definition: SDL_string.c:293
SDL_HapticPeriodic::direction
SDL_HapticDirection direction
Definition: SDL_haptic.h:544
SDL_HapticEffect::leftright
SDL_HapticLeftRight leftright
Definition: SDL_haptic.h:795
buf
GLenum GLuint GLsizei const GLchar * buf
Definition: glew.h:2539
flags
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
SDL_HapticPeriodic::magnitude
Sint16 magnitude
Definition: SDL_haptic.h:556
SDL_HapticCustom::attack_level
Uint16 attack_level
Definition: SDL_haptic.h:713
SDL_HapticCustom::samples
Uint16 samples
Definition: SDL_haptic.h:708
SDL_HAPTIC_RAMP
#define SDL_HAPTIC_RAMP
Ramp effect supported.
Definition: SDL_haptic.h:216
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
SDL_HAPTIC_SPRING
#define SDL_HAPTIC_SPRING
Spring effect supported - uses axes position.
Definition: SDL_haptic.h:226
_SDL_Haptic::nplaying
int nplaying
Definition: SDL_syshaptic.h:48
SDL_atoi
DECLSPEC int SDLCALL SDL_atoi(const char *str)
Definition: SDL_string.c:774
DWORD
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
SDL_HapticPeriodic::attack_length
Uint16 attack_length
Definition: SDL_haptic.h:561
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:255
SDL_HapticRamp::start
Sint16 start
Definition: SDL_haptic.h:643
_SDL_Joystick
Definition: SDL_sysjoystick.h:29
SDL_HapticPeriodic::delay
Uint16 delay
Definition: SDL_haptic.h:548
b
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
SDL_HapticPeriodic::interval
Uint16 interval
Definition: SDL_haptic.h:552
SDL_HapticCustom
A structure containing a template for the SDL_HAPTIC_CUSTOM effect.
Definition: SDL_haptic.h:691
SDL_Thread
Definition: SDL_thread_c.h:48
SDL_SYS_HapticStopAll
int SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
SDL_HapticCondition::center
Sint16 center[3]
Definition: SDL_haptic.h:612
Uint16
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:137
ref
GLclampf ref
Definition: gl2ext.h:1455
SDL_HAPTIC_SAWTOOTHUP
#define SDL_HAPTIC_SAWTOOTHUP
Sawtoothup wave effect supported.
Definition: SDL_haptic.h:198
str
#define str(s)
SDL_DestroyMutex
DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:61
SDL_SYS_HapticSetGain
int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
src
GLenum src
Definition: glew.h:2396
i
int i
Definition: pngrutil.c:1377
SDL_HapticLeftRight::large_magnitude
Uint16 large_magnitude
Definition: SDL_haptic.h:674
SDL_timer.h
SDL_HAPTIC_LEFTRIGHT
#define SDL_HAPTIC_LEFTRIGHT
Left/Right effect supported.
Definition: SDL_haptic.h:177
SDL_SYS_HapticRunEffect
int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
SDL_HapticEffect::periodic
SDL_HapticPeriodic periodic
Definition: SDL_haptic.h:792
SDL_HapticRamp::attack_level
Uint16 attack_level
Definition: SDL_haptic.h:648
SDL_HapticCustom::attack_length
Uint16 attack_length
Definition: SDL_haptic.h:712
SDL_HapticLeftRight::length
Uint32 length
Definition: SDL_haptic.h:671
SDL_HapticRamp::button
Uint16 button
Definition: SDL_haptic.h:639
SDL_HAPTIC_FRICTION
#define SDL_HAPTIC_FRICTION
Friction effect supported - uses axes movement.
Definition: SDL_haptic.h:256
VOID
typedef VOID(WINAPI *PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC)(HGLRC dstCtx
SDL_HAPTIC_SAWTOOTHDOWN
#define SDL_HAPTIC_SAWTOOTHDOWN
Sawtoothdown wave effect supported.
Definition: SDL_haptic.h:207
SDL_HapticPeriodic::phase
Uint16 phase
Definition: SDL_haptic.h:558
SDL_assert.h
SDL_HapticConstant::fade_length
Uint16 fade_length
Definition: SDL_haptic.h:477
SDL_HapticConstant::direction
SDL_HapticDirection direction
Definition: SDL_haptic.h:461
SDL_HapticCustom::direction
SDL_HapticDirection direction
Definition: SDL_haptic.h:695
SDL_HapticCustom::channels
Uint8 channels
Definition: SDL_haptic.h:706
SDL_SYS_HapticNewEffect
int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
SDL_HAPTIC_DAMPER
#define SDL_HAPTIC_DAMPER
Damper effect supported - uses axes velocity.
Definition: SDL_haptic.h:236
SDL_HapticCustom::interval
Uint16 interval
Definition: SDL_haptic.h:703
SDL_HapticCondition::left_sat
Uint16 left_sat[3]
Definition: SDL_haptic.h:608
BOOL
typedef BOOL(WINAPI *PFNWGLSETSTEREOEMITTERSTATE3DLPROC)(HDC hDC