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