#include "../../SDL_internal.h"
#if SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT
#include "SDL_thread.h"
#include "SDL_mutex.h"
#include "SDL_timer.h"
#include "SDL_hints.h"
#include "SDL_haptic.h"
#include "../SDL_syshaptic.h"
#include "SDL_joystick.h"
#include "../../joystick/SDL_sysjoystick.h"
#include "../../joystick/windows/SDL_windowsjoystick_c.h"
#include "../../joystick/windows/SDL_xinputjoystick_c.h"
#include "SDL_windowshaptic_c.h"
#include "SDL_dinputhaptic_c.h"
#include "SDL_xinputhaptic_c.h"
#ifdef __cplusplus
extern "C" {
#endif
SDL_hapticlist_item *SDL_hapticlist = NULL;
static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
static int numhaptics = 0;
int
SDL_SYS_HapticInit(void)
{
JoyStick_DeviceData* device;
if (SDL_DINPUT_HapticInit() < 0) {
return -1;
}
if (SDL_XINPUT_HapticInit() < 0) {
return -1;
}
for (device = SYS_Joystick; device; device = device->pNext) {
if (device->bXInputDevice) {
SDL_XINPUT_HapticMaybeAddDevice(device->XInputUserId);
} else {
SDL_DINPUT_HapticMaybeAddDevice(&device->dxdevice);
}
}
return numhaptics;
}
int
SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
{
if (SDL_hapticlist_tail == NULL) {
SDL_hapticlist = SDL_hapticlist_tail = item;
} else {
SDL_hapticlist_tail->next = item;
SDL_hapticlist_tail = item;
}
++numhaptics;
return numhaptics;
}
int
SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
{
const int retval = item->haptic ? item->haptic->index : -1;
if (prev != NULL) {
prev->next = item->next;
} else {
SDL_assert(SDL_hapticlist == item);
SDL_hapticlist = item->next;
}
if (item == SDL_hapticlist_tail) {
SDL_hapticlist_tail = prev;
}
--numhaptics;
SDL_free(item);
return retval;
}
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;
}
const char *
SDL_SYS_HapticName(int index)
{
SDL_hapticlist_item *item = HapticByDevIndex(index);
return item->name;
}
int
SDL_SYS_HapticOpen(SDL_Haptic * haptic)
{
SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
if (item->bXInputHaptic) {
return SDL_XINPUT_HapticOpen(haptic, item);
} else {
return SDL_DINPUT_HapticOpen(haptic, item);
}
}
int
SDL_SYS_HapticMouse(void)
{
#if SDL_HAPTIC_DINPUT
SDL_hapticlist_item *item;
int index = 0;
for (item = SDL_hapticlist; item != NULL; item = item->next) {
if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER) {
return index;
}
++index;
}
#endif
return -1;
}
int
SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
{
if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
return 0;
}
#if SDL_HAPTIC_XINPUT
if (joystick->hwdata->bXInputHaptic) {
return 1;
}
#endif
#if SDL_HAPTIC_DINPUT
if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
return 1;
}
#endif
return 0;
}
int
SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
{
if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
return 0;
}
if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
return 0;
} else if (joystick->hwdata->bXInputHaptic) {
return SDL_XINPUT_JoystickSameHaptic(haptic, joystick);
} else {
return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
}
}
int
SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
{
SDL_assert(joystick->driver == &SDL_WINDOWS_JoystickDriver);
if (joystick->hwdata->bXInputDevice) {
return SDL_XINPUT_HapticOpenFromJoystick(haptic, joystick);
} else {
return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
}
}
void
SDL_SYS_HapticClose(SDL_Haptic * haptic)
{
if (haptic->hwdata) {
SDL_free(haptic->effects);
haptic->effects = NULL;
haptic->neffects = 0;
if (haptic->hwdata->bXInputHaptic) {
SDL_XINPUT_HapticClose(haptic);
} else {
SDL_DINPUT_HapticClose(haptic);
}
SDL_free(haptic->hwdata);
haptic->hwdata = NULL;
}
}
void
SDL_SYS_HapticQuit(void)
{
SDL_hapticlist_item *item;
SDL_hapticlist_item *next = NULL;
SDL_Haptic *hapticitem = NULL;
extern SDL_Haptic *SDL_haptics;
for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1);
SDL_WaitThread(hapticitem->hwdata->thread, NULL);
hapticitem->hwdata->thread = NULL;
}
}
for (item = SDL_hapticlist; item; item = next) {
next = item->next;
SDL_free(item->name);
SDL_free(item);
}
SDL_XINPUT_HapticQuit();
SDL_DINPUT_HapticQuit();
numhaptics = 0;
SDL_hapticlist = NULL;
SDL_hapticlist_tail = NULL;
}
int
SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
SDL_HapticEffect * base)
{
int result;
effect->hweffect = (struct haptic_hweffect *)
SDL_malloc(sizeof(struct haptic_hweffect));
if (effect->hweffect == NULL) {
SDL_OutOfMemory();
return -1;
}
SDL_zerop(effect->hweffect);
if (haptic->hwdata->bXInputHaptic) {
result = SDL_XINPUT_HapticNewEffect(haptic, effect, base);
} else {
result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
}
if (result < 0) {
SDL_free(effect->hweffect);
effect->hweffect = NULL;
}
return result;
}
int
SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
struct haptic_effect *effect,
SDL_HapticEffect * data)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data);
} else {
return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
}
}
int
SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
Uint32 iterations)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticRunEffect(haptic, effect, iterations);
} else {
return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
}
}
int
SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticStopEffect(haptic, effect);
} else {
return SDL_DINPUT_HapticStopEffect(haptic, effect);
}
}
void
SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
{
if (haptic->hwdata->bXInputHaptic) {
SDL_XINPUT_HapticDestroyEffect(haptic, effect);
} else {
SDL_DINPUT_HapticDestroyEffect(haptic, effect);
}
SDL_free(effect->hweffect);
effect->hweffect = NULL;
}
int
SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
struct haptic_effect *effect)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticGetEffectStatus(haptic, effect);
} else {
return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
}
}
int
SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticSetGain(haptic, gain);
} else {
return SDL_DINPUT_HapticSetGain(haptic, gain);
}
}
int
SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
} else {
return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
}
}
int
SDL_SYS_HapticPause(SDL_Haptic * haptic)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticPause(haptic);
} else {
return SDL_DINPUT_HapticPause(haptic);
}
}
int
SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticUnpause(haptic);
} else {
return SDL_DINPUT_HapticUnpause(haptic);
}
}
int
SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticStopAll(haptic);
} else {
return SDL_DINPUT_HapticStopAll(haptic);
}
}
#ifdef __cplusplus
}
#endif
#endif