cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_haptic.c (18608B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 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#include "SDL_syshaptic.h"
     24#include "SDL_haptic_c.h"
     25#include "../joystick/SDL_joystick_c.h" /* For SDL_PrivateJoystickValid */
     26#include "SDL_assert.h"
     27
     28SDL_Haptic *SDL_haptics = NULL;
     29
     30
     31/*
     32 * Initializes the Haptic devices.
     33 */
     34int
     35SDL_HapticInit(void)
     36{
     37    int status;
     38
     39    status = SDL_SYS_HapticInit();
     40    if (status >= 0) {
     41        status = 0;
     42    }
     43
     44    return status;
     45}
     46
     47
     48/*
     49 * Checks to see if the haptic device is valid
     50 */
     51static int
     52ValidHaptic(SDL_Haptic * haptic)
     53{
     54    int valid;
     55    SDL_Haptic *hapticlist;
     56
     57    valid = 0;
     58    if (haptic != NULL) {
     59        hapticlist = SDL_haptics;
     60        while ( hapticlist )
     61        {
     62            if (hapticlist == haptic) {
     63                valid = 1;
     64                break;
     65            }
     66            hapticlist = hapticlist->next;
     67        }
     68    }
     69
     70    /* Create the error here. */
     71    if (valid == 0) {
     72        SDL_SetError("Haptic: Invalid haptic device identifier");
     73    }
     74
     75    return valid;
     76}
     77
     78
     79/*
     80 * Returns the number of available devices.
     81 */
     82int
     83SDL_NumHaptics(void)
     84{
     85    return SDL_SYS_NumHaptics();
     86}
     87
     88
     89/*
     90 * Gets the name of a Haptic device by index.
     91 */
     92const char *
     93SDL_HapticName(int device_index)
     94{
     95    if ((device_index < 0) || (device_index >= SDL_NumHaptics())) {
     96        SDL_SetError("Haptic: There are %d haptic devices available",
     97                     SDL_NumHaptics());
     98        return NULL;
     99    }
    100    return SDL_SYS_HapticName(device_index);
    101}
    102
    103
    104/*
    105 * Opens a Haptic device.
    106 */
    107SDL_Haptic *
    108SDL_HapticOpen(int device_index)
    109{
    110    SDL_Haptic *haptic;
    111    SDL_Haptic *hapticlist;
    112
    113    if ((device_index < 0) || (device_index >= SDL_NumHaptics())) {
    114        SDL_SetError("Haptic: There are %d haptic devices available",
    115                     SDL_NumHaptics());
    116        return NULL;
    117    }
    118
    119    hapticlist = SDL_haptics;
    120    /* If the haptic is already open, return it
    121    * TODO: Should we create haptic instance IDs like the Joystick API?
    122    */
    123    while ( hapticlist )
    124    {
    125        if (device_index == hapticlist->index) {
    126            haptic = hapticlist;
    127            ++haptic->ref_count;
    128            return haptic;
    129        }
    130        hapticlist = hapticlist->next;
    131    }
    132
    133    /* Create the haptic device */
    134    haptic = (SDL_Haptic *) SDL_malloc((sizeof *haptic));
    135    if (haptic == NULL) {
    136        SDL_OutOfMemory();
    137        return NULL;
    138    }
    139
    140    /* Initialize the haptic device */
    141    SDL_memset(haptic, 0, (sizeof *haptic));
    142    haptic->rumble_id = -1;
    143    haptic->index = device_index;
    144    if (SDL_SYS_HapticOpen(haptic) < 0) {
    145        SDL_free(haptic);
    146        return NULL;
    147    }
    148
    149    /* Add haptic to list */
    150    ++haptic->ref_count;
    151    /* Link the haptic in the list */
    152    haptic->next = SDL_haptics;
    153    SDL_haptics = haptic;
    154
    155    /* Disable autocenter and set gain to max. */
    156    if (haptic->supported & SDL_HAPTIC_GAIN)
    157        SDL_HapticSetGain(haptic, 100);
    158    if (haptic->supported & SDL_HAPTIC_AUTOCENTER)
    159        SDL_HapticSetAutocenter(haptic, 0);
    160
    161    return haptic;
    162}
    163
    164
    165/*
    166 * Returns 1 if the device has been opened.
    167 */
    168int
    169SDL_HapticOpened(int device_index)
    170{
    171    int opened;
    172    SDL_Haptic *hapticlist;
    173
    174    /* Make sure it's valid. */
    175    if ((device_index < 0) || (device_index >= SDL_NumHaptics())) {
    176        SDL_SetError("Haptic: There are %d haptic devices available",
    177                     SDL_NumHaptics());
    178        return 0;
    179    }
    180
    181    opened = 0;
    182    hapticlist = SDL_haptics;
    183    /* TODO Should this use an instance ID? */
    184    while ( hapticlist )
    185    {
    186        if (hapticlist->index == (Uint8) device_index) {
    187            opened = 1;
    188            break;
    189        }
    190        hapticlist = hapticlist->next;
    191    }
    192    return opened;
    193}
    194
    195
    196/*
    197 * Returns the index to a haptic device.
    198 */
    199int
    200SDL_HapticIndex(SDL_Haptic * haptic)
    201{
    202    if (!ValidHaptic(haptic)) {
    203        return -1;
    204    }
    205
    206    return haptic->index;
    207}
    208
    209
    210/*
    211 * Returns SDL_TRUE if mouse is haptic, SDL_FALSE if it isn't.
    212 */
    213int
    214SDL_MouseIsHaptic(void)
    215{
    216    if (SDL_SYS_HapticMouse() < 0)
    217        return SDL_FALSE;
    218    return SDL_TRUE;
    219}
    220
    221
    222/*
    223 * Returns the haptic device if mouse is haptic or NULL elsewise.
    224 */
    225SDL_Haptic *
    226SDL_HapticOpenFromMouse(void)
    227{
    228    int device_index;
    229
    230    device_index = SDL_SYS_HapticMouse();
    231
    232    if (device_index < 0) {
    233        SDL_SetError("Haptic: Mouse isn't a haptic device.");
    234        return NULL;
    235    }
    236
    237    return SDL_HapticOpen(device_index);
    238}
    239
    240
    241/*
    242 * Returns SDL_TRUE if joystick has haptic features.
    243 */
    244int
    245SDL_JoystickIsHaptic(SDL_Joystick * joystick)
    246{
    247    int ret;
    248
    249    /* Must be a valid joystick */
    250    if (!SDL_PrivateJoystickValid(joystick)) {
    251        return -1;
    252    }
    253
    254    ret = SDL_SYS_JoystickIsHaptic(joystick);
    255
    256    if (ret > 0)
    257        return SDL_TRUE;
    258    else if (ret == 0)
    259        return SDL_FALSE;
    260    else
    261        return -1;
    262}
    263
    264
    265/*
    266 * Opens a haptic device from a joystick.
    267 */
    268SDL_Haptic *
    269SDL_HapticOpenFromJoystick(SDL_Joystick * joystick)
    270{
    271    SDL_Haptic *haptic;
    272    SDL_Haptic *hapticlist;
    273
    274    /* Make sure there is room. */
    275    if (SDL_NumHaptics() <= 0) {
    276        SDL_SetError("Haptic: There are %d haptic devices available",
    277                     SDL_NumHaptics());
    278        return NULL;
    279    }
    280
    281    /* Must be a valid joystick */
    282    if (!SDL_PrivateJoystickValid(joystick)) {
    283        SDL_SetError("Haptic: Joystick isn't valid.");
    284        return NULL;
    285    }
    286
    287    /* Joystick must be haptic */
    288    if (SDL_SYS_JoystickIsHaptic(joystick) <= 0) {
    289        SDL_SetError("Haptic: Joystick isn't a haptic device.");
    290        return NULL;
    291    }
    292
    293    hapticlist = SDL_haptics;
    294    /* Check to see if joystick's haptic is already open */
    295    while ( hapticlist )
    296    {
    297        if (SDL_SYS_JoystickSameHaptic(hapticlist, joystick)) {
    298            haptic = hapticlist;
    299            ++haptic->ref_count;
    300            return haptic;
    301        }
    302        hapticlist = hapticlist->next;
    303    }
    304
    305    /* Create the haptic device */
    306    haptic = (SDL_Haptic *) SDL_malloc((sizeof *haptic));
    307    if (haptic == NULL) {
    308        SDL_OutOfMemory();
    309        return NULL;
    310    }
    311
    312    /* Initialize the haptic device */
    313    SDL_memset(haptic, 0, sizeof(SDL_Haptic));
    314    haptic->rumble_id = -1;
    315    if (SDL_SYS_HapticOpenFromJoystick(haptic, joystick) < 0) {
    316        SDL_free(haptic);
    317        return NULL;
    318    }
    319
    320    /* Add haptic to list */
    321    ++haptic->ref_count;
    322    /* Link the haptic in the list */
    323    haptic->next = SDL_haptics;
    324    SDL_haptics = haptic;
    325
    326    return haptic;
    327}
    328
    329
    330/*
    331 * Closes a SDL_Haptic device.
    332 */
    333void
    334SDL_HapticClose(SDL_Haptic * haptic)
    335{
    336    int i;
    337    SDL_Haptic *hapticlist;
    338    SDL_Haptic *hapticlistprev;
    339
    340    /* Must be valid */
    341    if (!ValidHaptic(haptic)) {
    342        return;
    343    }
    344
    345    /* Check if it's still in use */
    346    if (--haptic->ref_count > 0) {
    347        return;
    348    }
    349
    350    /* Close it, properly removing effects if needed */
    351    for (i = 0; i < haptic->neffects; i++) {
    352        if (haptic->effects[i].hweffect != NULL) {
    353            SDL_HapticDestroyEffect(haptic, i);
    354        }
    355    }
    356    SDL_SYS_HapticClose(haptic);
    357
    358    /* Remove from the list */
    359    hapticlist = SDL_haptics;
    360    hapticlistprev = NULL;
    361    while ( hapticlist )
    362    {
    363        if (haptic == hapticlist)
    364        {
    365            if ( hapticlistprev )
    366            {
    367                /* unlink this entry */
    368                hapticlistprev->next = hapticlist->next;
    369            }
    370            else
    371            {
    372                SDL_haptics = haptic->next;
    373            }
    374
    375            break;
    376        }
    377        hapticlistprev = hapticlist;
    378        hapticlist = hapticlist->next;
    379    }
    380
    381    /* Free */
    382    SDL_free(haptic);
    383}
    384
    385/*
    386 * Cleans up after the subsystem.
    387 */
    388void
    389SDL_HapticQuit(void)
    390{
    391    SDL_SYS_HapticQuit();
    392    SDL_assert(SDL_haptics == NULL);
    393    SDL_haptics = NULL;
    394}
    395
    396/*
    397 * Returns the number of effects a haptic device has.
    398 */
    399int
    400SDL_HapticNumEffects(SDL_Haptic * haptic)
    401{
    402    if (!ValidHaptic(haptic)) {
    403        return -1;
    404    }
    405
    406    return haptic->neffects;
    407}
    408
    409
    410/*
    411 * Returns the number of effects a haptic device can play.
    412 */
    413int
    414SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic)
    415{
    416    if (!ValidHaptic(haptic)) {
    417        return -1;
    418    }
    419
    420    return haptic->nplaying;
    421}
    422
    423
    424/*
    425 * Returns supported effects by the device.
    426 */
    427unsigned int
    428SDL_HapticQuery(SDL_Haptic * haptic)
    429{
    430    if (!ValidHaptic(haptic)) {
    431        return 0; /* same as if no effects were supported */
    432    }
    433
    434    return haptic->supported;
    435}
    436
    437
    438/*
    439 * Returns the number of axis on the device.
    440 */
    441int
    442SDL_HapticNumAxes(SDL_Haptic * haptic)
    443{
    444    if (!ValidHaptic(haptic)) {
    445        return -1;
    446    }
    447
    448    return haptic->naxes;
    449}
    450
    451/*
    452 * Checks to see if the device can support the effect.
    453 */
    454int
    455SDL_HapticEffectSupported(SDL_Haptic * haptic, SDL_HapticEffect * effect)
    456{
    457    if (!ValidHaptic(haptic)) {
    458        return -1;
    459    }
    460
    461    if ((haptic->supported & effect->type) != 0)
    462        return SDL_TRUE;
    463    return SDL_FALSE;
    464}
    465
    466/*
    467 * Creates a new haptic effect.
    468 */
    469int
    470SDL_HapticNewEffect(SDL_Haptic * haptic, SDL_HapticEffect * effect)
    471{
    472    int i;
    473
    474    /* Check for device validity. */
    475    if (!ValidHaptic(haptic)) {
    476        return -1;
    477    }
    478
    479    /* Check to see if effect is supported */
    480    if (SDL_HapticEffectSupported(haptic, effect) == SDL_FALSE) {
    481        return SDL_SetError("Haptic: Effect not supported by haptic device.");
    482    }
    483
    484    /* See if there's a free slot */
    485    for (i = 0; i < haptic->neffects; i++) {
    486        if (haptic->effects[i].hweffect == NULL) {
    487
    488            /* Now let the backend create the real effect */
    489            if (SDL_SYS_HapticNewEffect(haptic, &haptic->effects[i], effect)
    490                != 0) {
    491                return -1;      /* Backend failed to create effect */
    492            }
    493
    494            SDL_memcpy(&haptic->effects[i].effect, effect,
    495                       sizeof(SDL_HapticEffect));
    496            return i;
    497        }
    498    }
    499
    500    return SDL_SetError("Haptic: Device has no free space left.");
    501}
    502
    503/*
    504 * Checks to see if an effect is valid.
    505 */
    506static int
    507ValidEffect(SDL_Haptic * haptic, int effect)
    508{
    509    if ((effect < 0) || (effect >= haptic->neffects)) {
    510        SDL_SetError("Haptic: Invalid effect identifier.");
    511        return 0;
    512    }
    513    return 1;
    514}
    515
    516/*
    517 * Updates an effect.
    518 */
    519int
    520SDL_HapticUpdateEffect(SDL_Haptic * haptic, int effect,
    521                       SDL_HapticEffect * data)
    522{
    523    if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
    524        return -1;
    525    }
    526
    527    /* Can't change type dynamically. */
    528    if (data->type != haptic->effects[effect].effect.type) {
    529        return SDL_SetError("Haptic: Updating effect type is illegal.");
    530    }
    531
    532    /* Updates the effect */
    533    if (SDL_SYS_HapticUpdateEffect(haptic, &haptic->effects[effect], data) <
    534        0) {
    535        return -1;
    536    }
    537
    538    SDL_memcpy(&haptic->effects[effect].effect, data,
    539               sizeof(SDL_HapticEffect));
    540    return 0;
    541}
    542
    543
    544/*
    545 * Runs the haptic effect on the device.
    546 */
    547int
    548SDL_HapticRunEffect(SDL_Haptic * haptic, int effect, Uint32 iterations)
    549{
    550    if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
    551        return -1;
    552    }
    553
    554    /* Run the effect */
    555    if (SDL_SYS_HapticRunEffect(haptic, &haptic->effects[effect], iterations)
    556        < 0) {
    557        return -1;
    558    }
    559
    560    return 0;
    561}
    562
    563/*
    564 * Stops the haptic effect on the device.
    565 */
    566int
    567SDL_HapticStopEffect(SDL_Haptic * haptic, int effect)
    568{
    569    if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
    570        return -1;
    571    }
    572
    573    /* Stop the effect */
    574    if (SDL_SYS_HapticStopEffect(haptic, &haptic->effects[effect]) < 0) {
    575        return -1;
    576    }
    577
    578    return 0;
    579}
    580
    581/*
    582 * Gets rid of a haptic effect.
    583 */
    584void
    585SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect)
    586{
    587    if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
    588        return;
    589    }
    590
    591    /* Not allocated */
    592    if (haptic->effects[effect].hweffect == NULL) {
    593        return;
    594    }
    595
    596    SDL_SYS_HapticDestroyEffect(haptic, &haptic->effects[effect]);
    597}
    598
    599/*
    600 * Gets the status of a haptic effect.
    601 */
    602int
    603SDL_HapticGetEffectStatus(SDL_Haptic * haptic, int effect)
    604{
    605    if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
    606        return -1;
    607    }
    608
    609    if ((haptic->supported & SDL_HAPTIC_STATUS) == 0) {
    610        return SDL_SetError("Haptic: Device does not support status queries.");
    611    }
    612
    613    return SDL_SYS_HapticGetEffectStatus(haptic, &haptic->effects[effect]);
    614}
    615
    616/*
    617 * Sets the global gain of the device.
    618 */
    619int
    620SDL_HapticSetGain(SDL_Haptic * haptic, int gain)
    621{
    622    const char *env;
    623    int real_gain, max_gain;
    624
    625    if (!ValidHaptic(haptic)) {
    626        return -1;
    627    }
    628
    629    if ((haptic->supported & SDL_HAPTIC_GAIN) == 0) {
    630        return SDL_SetError("Haptic: Device does not support setting gain.");
    631    }
    632
    633    if ((gain < 0) || (gain > 100)) {
    634        return SDL_SetError("Haptic: Gain must be between 0 and 100.");
    635    }
    636
    637    /* We use the envvar to get the maximum gain. */
    638    env = SDL_getenv("SDL_HAPTIC_GAIN_MAX");
    639    if (env != NULL) {
    640        max_gain = SDL_atoi(env);
    641
    642        /* Check for sanity. */
    643        if (max_gain < 0)
    644            max_gain = 0;
    645        else if (max_gain > 100)
    646            max_gain = 100;
    647
    648        /* We'll scale it linearly with SDL_HAPTIC_GAIN_MAX */
    649        real_gain = (gain * max_gain) / 100;
    650    } else {
    651        real_gain = gain;
    652    }
    653
    654    if (SDL_SYS_HapticSetGain(haptic, real_gain) < 0) {
    655        return -1;
    656    }
    657
    658    return 0;
    659}
    660
    661/*
    662 * Makes the device autocenter, 0 disables.
    663 */
    664int
    665SDL_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
    666{
    667    if (!ValidHaptic(haptic)) {
    668        return -1;
    669    }
    670
    671    if ((haptic->supported & SDL_HAPTIC_AUTOCENTER) == 0) {
    672        return SDL_SetError("Haptic: Device does not support setting autocenter.");
    673    }
    674
    675    if ((autocenter < 0) || (autocenter > 100)) {
    676        return SDL_SetError("Haptic: Autocenter must be between 0 and 100.");
    677    }
    678
    679    if (SDL_SYS_HapticSetAutocenter(haptic, autocenter) < 0) {
    680        return -1;
    681    }
    682
    683    return 0;
    684}
    685
    686/*
    687 * Pauses the haptic device.
    688 */
    689int
    690SDL_HapticPause(SDL_Haptic * haptic)
    691{
    692    if (!ValidHaptic(haptic)) {
    693        return -1;
    694    }
    695
    696    if ((haptic->supported & SDL_HAPTIC_PAUSE) == 0) {
    697        return SDL_SetError("Haptic: Device does not support setting pausing.");
    698    }
    699
    700    return SDL_SYS_HapticPause(haptic);
    701}
    702
    703/*
    704 * Unpauses the haptic device.
    705 */
    706int
    707SDL_HapticUnpause(SDL_Haptic * haptic)
    708{
    709    if (!ValidHaptic(haptic)) {
    710        return -1;
    711    }
    712
    713    if ((haptic->supported & SDL_HAPTIC_PAUSE) == 0) {
    714        return 0;               /* Not going to be paused, so we pretend it's unpaused. */
    715    }
    716
    717    return SDL_SYS_HapticUnpause(haptic);
    718}
    719
    720/*
    721 * Stops all the currently playing effects.
    722 */
    723int
    724SDL_HapticStopAll(SDL_Haptic * haptic)
    725{
    726    if (!ValidHaptic(haptic)) {
    727        return -1;
    728    }
    729
    730    return SDL_SYS_HapticStopAll(haptic);
    731}
    732
    733/*
    734 * Checks to see if rumble is supported.
    735 */
    736int
    737SDL_HapticRumbleSupported(SDL_Haptic * haptic)
    738{
    739    if (!ValidHaptic(haptic)) {
    740        return -1;
    741    }
    742
    743    /* Most things can use SINE, but XInput only has LEFTRIGHT. */
    744    return ((haptic->supported & (SDL_HAPTIC_SINE|SDL_HAPTIC_LEFTRIGHT)) != 0);
    745}
    746
    747/*
    748 * Initializes the haptic device for simple rumble playback.
    749 */
    750int
    751SDL_HapticRumbleInit(SDL_Haptic * haptic)
    752{
    753    SDL_HapticEffect *efx = &haptic->rumble_effect;
    754
    755    if (!ValidHaptic(haptic)) {
    756        return -1;
    757    }
    758
    759    /* Already allocated. */
    760    if (haptic->rumble_id >= 0) {
    761        return 0;
    762    }
    763
    764    SDL_zerop(efx);
    765    if (haptic->supported & SDL_HAPTIC_SINE) {
    766        efx->type = SDL_HAPTIC_SINE;
    767        efx->periodic.period = 1000;
    768        efx->periodic.magnitude = 0x4000;
    769        efx->periodic.length = 5000;
    770        efx->periodic.attack_length = 0;
    771        efx->periodic.fade_length = 0;
    772    } else if (haptic->supported & SDL_HAPTIC_LEFTRIGHT) {  /* XInput? */
    773        efx->type = SDL_HAPTIC_LEFTRIGHT;
    774        efx->leftright.length = 5000;
    775        efx->leftright.large_magnitude = 0x4000;
    776        efx->leftright.small_magnitude = 0x4000;
    777    } else {
    778        return SDL_SetError("Device doesn't support rumble");
    779    }
    780
    781    haptic->rumble_id = SDL_HapticNewEffect(haptic, &haptic->rumble_effect);
    782    if (haptic->rumble_id >= 0) {
    783        return 0;
    784    }
    785    return -1;
    786}
    787
    788/*
    789 * Runs simple rumble on a haptic device
    790 */
    791int
    792SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length)
    793{
    794    SDL_HapticEffect *efx;
    795    Sint16 magnitude;
    796
    797    if (!ValidHaptic(haptic)) {
    798        return -1;
    799    }
    800
    801    if (haptic->rumble_id < 0) {
    802        return SDL_SetError("Haptic: Rumble effect not initialized on haptic device");
    803    }
    804
    805    /* Clamp strength. */
    806    if (strength > 1.0f) {
    807        strength = 1.0f;
    808    } else if (strength < 0.0f) {
    809        strength = 0.0f;
    810    }
    811    magnitude = (Sint16)(32767.0f*strength);
    812
    813    efx = &haptic->rumble_effect;
    814    if (efx->type == SDL_HAPTIC_SINE) {
    815        efx->periodic.magnitude = magnitude;
    816        efx->periodic.length = length;
    817    } else if (efx->type == SDL_HAPTIC_LEFTRIGHT) {
    818        efx->leftright.small_magnitude = efx->leftright.large_magnitude = magnitude;
    819        efx->leftright.length = length;
    820    } else {
    821        SDL_assert(0 && "This should have been caught elsewhere");
    822    }
    823
    824    if (SDL_HapticUpdateEffect(haptic, haptic->rumble_id, &haptic->rumble_effect) < 0) {
    825        return -1;
    826    }
    827
    828    return SDL_HapticRunEffect(haptic, haptic->rumble_id, 1);
    829}
    830
    831/*
    832 * Stops the simple rumble on a haptic device.
    833 */
    834int
    835SDL_HapticRumbleStop(SDL_Haptic * haptic)
    836{
    837    if (!ValidHaptic(haptic)) {
    838        return -1;
    839    }
    840
    841    if (haptic->rumble_id < 0) {
    842        return SDL_SetError("Haptic: Rumble effect not initialized on haptic device");
    843    }
    844
    845    return SDL_HapticStopEffect(haptic, haptic->rumble_id);
    846}
    847