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