early-access version 1611
This commit is contained in:
456
externals/SDL/src/haptic/windows/SDL_windowshaptic.c
vendored
Executable file
456
externals/SDL/src/haptic/windows/SDL_windowshaptic.c
vendored
Executable file
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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"
|
||||
|
||||
#if SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#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" /* 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"
|
||||
#include "SDL_xinputhaptic_c.h"
|
||||
|
||||
|
||||
/*
|
||||
* Internal stuff.
|
||||
*/
|
||||
SDL_hapticlist_item *SDL_hapticlist = NULL;
|
||||
static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
|
||||
static int numhaptics = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Initializes the haptic subsystem.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticInit(void)
|
||||
{
|
||||
if (SDL_DINPUT_HapticInit() < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (SDL_XINPUT_HapticInit() < 0) {
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* Device has been added. */
|
||||
++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;
|
||||
/* !!! TODO: Send a haptic remove event? */
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Opens a haptic device from first mouse it finds for usage.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticMouse(void)
|
||||
{
|
||||
#if SDL_HAPTIC_DINPUT
|
||||
SDL_hapticlist_item *item;
|
||||
int index = 0;
|
||||
|
||||
/* Grab the first mouse haptic device we find. */
|
||||
for (item = SDL_hapticlist; item != NULL; 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks to see if the haptic device and joystick are in reality the same.
|
||||
*/
|
||||
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; /* one is XInput, one is not; not the same device. */
|
||||
} else if (joystick->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_JoystickSameHaptic(haptic, joystick);
|
||||
} else {
|
||||
return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens a SDL_Haptic from a SDL_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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
SDL_XINPUT_HapticClose(haptic);
|
||||
} else {
|
||||
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;
|
||||
SDL_Haptic *hapticitem = NULL;
|
||||
|
||||
extern SDL_Haptic *SDL_haptics;
|
||||
for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
|
||||
if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
|
||||
/* we _have_ to stop the thread before we free the XInput DLL! */
|
||||
SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1);
|
||||
SDL_WaitThread(hapticitem->hwdata->thread, NULL);
|
||||
hapticitem->hwdata->thread = 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_XINPUT_HapticQuit();
|
||||
SDL_DINPUT_HapticQuit();
|
||||
|
||||
numhaptics = 0;
|
||||
SDL_hapticlist = NULL;
|
||||
SDL_hapticlist_tail = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new haptic effect.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
|
||||
SDL_HapticEffect * base)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Alloc the effect. */
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates an effect.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs an effect.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stops an effect.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees the 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the status of a haptic effect.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the gain.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the autocentering.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pauses the device.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticPause(SDL_Haptic * haptic)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticPause(haptic);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticPause(haptic);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pauses the device.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticUnpause(haptic);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticUnpause(haptic);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stops all the playing effects on the device.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticStopAll(haptic);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticStopAll(haptic);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
Reference in New Issue
Block a user