src/haptic/SDL_haptic.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 20 Feb 2011 10:54:44 -0800
changeset 5360 220d3af9121f
parent 4472 791b3256fb22
child 5362 074fc8730031
permissions -rw-r--r--
Simple rumble API for haptic

Edgar Simo 2011-02-20 10:27:52 PST

Adding patch that adds a simplified API for the haptic subsystem built ontop of
the "real one" for those who want simple rumble without jumping through hoops.

Adds 4 functions:

- extern DECLSPEC int SDLCALL SDL_HapticRumbleSupported(SDL_Haptic * haptic);
- extern DECLSPEC int SDLCALL SDL_HapticRumbleInit(SDL_Haptic * haptic);
- extern DECLSPEC int SDLCALL SDL_HapticRumblePlay(SDL_Haptic * haptic, float
strength, Uint32 length );
- extern DECLSPEC int SDLCALL SDL_HapticRumbleStop(SDL_Haptic * haptic);

Also provided is test/testrumble.c which does test this.

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