sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_windowshaptic.c (11112B)


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