| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "SDL_internal.h"
- #ifdef SDL_HAPTIC_DINPUT
- #include "../SDL_syshaptic.h"
- #include "../../joystick/SDL_sysjoystick.h" // For the real SDL_Joystick
- #include "../../joystick/windows/SDL_windowsjoystick_c.h" // For joystick hwdata
- #include "../../joystick/windows/SDL_xinputjoystick_c.h" // For xinput rumble
- #include "SDL_windowshaptic_c.h"
- #include "SDL_dinputhaptic_c.h"
- // Set up for C function definitions, even when using C++
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*
- * Internal stuff.
- */
- SDL_hapticlist_item *SDL_hapticlist = NULL;
- static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
- static int numhaptics = 0;
- /*
- * Initializes the haptic subsystem.
- */
- bool SDL_SYS_HapticInit(void)
- {
- JoyStick_DeviceData *device;
- if (!SDL_DINPUT_HapticInit()) {
- return false;
- }
- /* The joystick subsystem will usually be initialized before haptics,
- * so the initial HapticMaybeAddDevice() calls from the joystick
- * subsystem will arrive too early to create haptic devices. We will
- * invoke those callbacks again here to pick up any joysticks that
- * were added prior to haptics initialization. */
- for (device = SYS_Joystick; device; device = device->pNext) {
- SDL_DINPUT_HapticMaybeAddDevice(&device->dxdevice);
- }
- return true;
- }
- bool SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
- {
- if (!SDL_hapticlist_tail) {
- SDL_hapticlist = SDL_hapticlist_tail = item;
- } else {
- SDL_hapticlist_tail->next = item;
- SDL_hapticlist_tail = item;
- }
- // Device has been added.
- ++numhaptics;
- return true;
- }
- bool SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
- {
- const bool result = item->haptic ? true : false;
- if (prev) {
- prev->next = item->next;
- } else {
- SDL_assert(SDL_hapticlist == item);
- SDL_hapticlist = item->next;
- }
- if (item == SDL_hapticlist_tail) {
- SDL_hapticlist_tail = prev;
- }
- --numhaptics;
- // !!! TODO: Send a haptic remove event?
- SDL_free(item);
- return result;
- }
- int SDL_SYS_NumHaptics(void)
- {
- return numhaptics;
- }
- static SDL_hapticlist_item *HapticByDevIndex(int device_index)
- {
- SDL_hapticlist_item *item = SDL_hapticlist;
- if ((device_index < 0) || (device_index >= numhaptics)) {
- return NULL;
- }
- while (device_index > 0) {
- SDL_assert(item != NULL);
- --device_index;
- item = item->next;
- }
- return item;
- }
- static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id)
- {
- SDL_hapticlist_item *item;
- for (item = SDL_hapticlist; item; item = item->next) {
- if (instance_id == item->instance_id) {
- return item;
- }
- }
- return NULL;
- }
- SDL_HapticID SDL_SYS_HapticInstanceID(int index)
- {
- SDL_hapticlist_item *item = HapticByDevIndex(index);
- if (item) {
- return item->instance_id;
- }
- return 0;
- }
- /*
- * Return the name of a haptic device, does not need to be opened.
- */
- const char *SDL_SYS_HapticName(int index)
- {
- SDL_hapticlist_item *item = HapticByDevIndex(index);
- return item->name;
- }
- /*
- * Opens a haptic device for usage.
- */
- bool SDL_SYS_HapticOpen(SDL_Haptic *haptic)
- {
- SDL_hapticlist_item *item = HapticByInstanceID(haptic->instance_id);
- return SDL_DINPUT_HapticOpen(haptic, item);
- }
- /*
- * Opens a haptic device from first mouse it finds for usage.
- */
- int SDL_SYS_HapticMouse(void)
- {
- #ifdef SDL_HAPTIC_DINPUT
- SDL_hapticlist_item *item;
- int index = 0;
- // Grab the first mouse haptic device we find.
- for (item = SDL_hapticlist; item; item = item->next) {
- if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER) {
- return index;
- }
- ++index;
- }
- #endif // SDL_HAPTIC_DINPUT
- return -1;
- }
- /*
- * Checks to see if a joystick has haptic features.
- */
- bool SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
- {
- if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
- return false;
- }
- if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
- return true;
- }
- return false;
- }
- /*
- * Checks to see if the haptic device and joystick are in reality the same.
- */
- bool SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
- {
- if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
- return false;
- }
- return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
- }
- /*
- * Opens a SDL_Haptic from a SDL_Joystick.
- */
- bool SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
- {
- SDL_assert(joystick->driver == &SDL_WINDOWS_JoystickDriver);
- return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
- }
- /*
- * Closes the haptic device.
- */
- void SDL_SYS_HapticClose(SDL_Haptic *haptic)
- {
- if (haptic->hwdata) {
- // Free effects.
- SDL_free(haptic->effects);
- haptic->effects = NULL;
- haptic->neffects = 0;
- // Clean up
- SDL_DINPUT_HapticClose(haptic);
- // Free
- SDL_free(haptic->hwdata);
- haptic->hwdata = NULL;
- }
- }
- /*
- * Clean up after system specific haptic stuff
- */
- void SDL_SYS_HapticQuit(void)
- {
- SDL_hapticlist_item *item;
- SDL_hapticlist_item *next = NULL;
- for (item = SDL_hapticlist; item; item = next) {
- /* Opened and not closed haptics are leaked, this is on purpose.
- * Close your haptic devices after usage. */
- // !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not.
- next = item->next;
- SDL_free(item->name);
- SDL_free(item);
- }
- SDL_DINPUT_HapticQuit();
- numhaptics = 0;
- SDL_hapticlist = NULL;
- SDL_hapticlist_tail = NULL;
- }
- /*
- * Creates a new haptic effect.
- */
- bool SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect,
- const SDL_HapticEffect *base)
- {
- bool result;
- // Alloc the effect.
- effect->hweffect = (struct haptic_hweffect *) SDL_calloc(1, sizeof(struct haptic_hweffect));
- if (!effect->hweffect) {
- return false;
- }
- result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
- if (!result) {
- SDL_free(effect->hweffect);
- effect->hweffect = NULL;
- }
- return result;
- }
- /*
- * Updates an effect.
- */
- bool SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data)
- {
- return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
- }
- /*
- * Runs an effect.
- */
- bool SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
- {
- return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
- }
- /*
- * Stops an effect.
- */
- bool SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
- {
- return SDL_DINPUT_HapticStopEffect(haptic, effect);
- }
- /*
- * Frees the effect.
- */
- void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
- {
- SDL_DINPUT_HapticDestroyEffect(haptic, effect);
- SDL_free(effect->hweffect);
- effect->hweffect = NULL;
- }
- /*
- * Gets the status of a haptic effect.
- */
- int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
- {
- return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
- }
- /*
- * Sets the gain.
- */
- bool SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
- {
- return SDL_DINPUT_HapticSetGain(haptic, gain);
- }
- /*
- * Sets the autocentering.
- */
- bool SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
- {
- return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
- }
- /*
- * Pauses the device.
- */
- bool SDL_SYS_HapticPause(SDL_Haptic *haptic)
- {
- return SDL_DINPUT_HapticPause(haptic);
- }
- /*
- * Pauses the device.
- */
- bool SDL_SYS_HapticResume(SDL_Haptic *haptic)
- {
- return SDL_DINPUT_HapticResume(haptic);
- }
- /*
- * Stops all the playing effects on the device.
- */
- bool SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
- {
- return SDL_DINPUT_HapticStopAll(haptic);
- }
- // Ends C function definitions when using C++
- #ifdef __cplusplus
- }
- #endif
- #endif // SDL_HAPTIC_DINPUT
|