src/haptic/SDL_haptic.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 26 May 2015 06:27:46 -0700
changeset 9619 b94b6d0bff0f
parent 8974 f813b8b10b55
child 9740 55e88e3bc7cc
permissions -rw-r--r--
Updated the copyright year to 2015
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2015 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 
    28 SDL_Haptic *SDL_haptics = NULL;
    29 
    30 
    31 /*
    32  * Initializes the Haptic devices.
    33  */
    34 int
    35 SDL_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  */
    51 static int
    52 ValidHaptic(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  */
    82 int
    83 SDL_NumHaptics(void)
    84 {
    85     return SDL_SYS_NumHaptics();
    86 }
    87 
    88 
    89 /*
    90  * Gets the name of a Haptic device by index.
    91  */
    92 const char *
    93 SDL_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  */
   107 SDL_Haptic *
   108 SDL_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  */
   168 int
   169 SDL_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  */
   199 int
   200 SDL_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  */
   213 int
   214 SDL_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  */
   225 SDL_Haptic *
   226 SDL_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  */
   244 int
   245 SDL_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  */
   268 SDL_Haptic *
   269 SDL_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  */
   333 void
   334 SDL_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  */
   388 void
   389 SDL_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  */
   399 int
   400 SDL_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  */
   413 int
   414 SDL_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  */
   427 unsigned int
   428 SDL_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  */
   441 int
   442 SDL_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  */
   454 int
   455 SDL_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  */
   469 int
   470 SDL_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  */
   506 static int
   507 ValidEffect(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  */
   519 int
   520 SDL_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  */
   547 int
   548 SDL_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  */
   566 int
   567 SDL_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  */
   584 void
   585 SDL_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  */
   602 int
   603 SDL_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  */
   619 int
   620 SDL_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  */
   664 int
   665 SDL_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  */
   689 int
   690 SDL_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  */
   706 int
   707 SDL_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  */
   723 int
   724 SDL_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  */
   736 int
   737 SDL_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  */
   750 int
   751 SDL_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  */
   791 int
   792 SDL_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  */
   834 int
   835 SDL_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