src/haptic/SDL_haptic.c
author Edgar Simo <bobbens@gmail.com>
Wed, 02 Jul 2008 09:52:44 +0000
branchgsoc2008_force_feedback
changeset 2490 be9b206d44af
parent 2489 96adc8025331
child 2491 10bc7aaf5114
permissions -rw-r--r--
Some more error checking.
Implemented SDL_HapticOpenFromJoystick().
     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_haptic_c.h"
    25 #include "SDL_syshaptic.h"
    26 #include "../joystick/SDL_joystick_c.h" /* For SDL_PrivateJoystickValid */
    27 
    28 
    29 static Uint8 SDL_numhaptics = 0;
    30 SDL_Haptic **SDL_haptics = NULL;
    31 static SDL_Haptic *default_haptic = NULL;
    32 
    33 
    34 /*
    35  * Initializes the Haptic devices.
    36  */
    37 int
    38 SDL_HapticInit(void)
    39 {  
    40    int arraylen;
    41    int status;
    42 
    43    SDL_numhaptics = 0;
    44    status = SDL_SYS_HapticInit();
    45    if (status >= 0) {
    46       arraylen = (status + 1) * sizeof(*SDL_haptics);
    47       SDL_haptics = (SDL_Haptic **) SDL_malloc(arraylen);
    48       if (SDL_haptics == NULL) {
    49          SDL_numhaptics = 0;
    50       } else {
    51          SDL_memset(SDL_haptics, 0, arraylen);
    52          SDL_numhaptics = status;
    53       }
    54       status = 0;
    55    }
    56    default_haptic = NULL;
    57 
    58    return status;
    59 }
    60 
    61 
    62 /*
    63  * Returns the number of available devices.
    64  */
    65 int
    66 SDL_NumHaptics(void)
    67 {
    68    return SDL_numhaptics;
    69 }
    70 
    71 
    72 /*
    73  * Gets the name of a Haptic device by index.
    74  */
    75 const char *
    76 SDL_HapticName(int device_index)
    77 {
    78    if ((device_index < 0) || (device_index >= SDL_numhaptics)) {
    79       SDL_SetError("There are %d haptic devices available", SDL_numhaptics);
    80       return NULL;
    81    }
    82    return SDL_SYS_HapticName(device_index);
    83 }
    84 
    85 
    86 /*
    87  * Opens a Haptic device.
    88  */
    89 SDL_Haptic *
    90 SDL_HapticOpen(int device_index)
    91 {
    92    int i;
    93    SDL_Haptic *haptic;
    94 
    95    if ((device_index < 0) || (device_index >= SDL_numhaptics)) {
    96       SDL_SetError("There are %d haptic devices available", SDL_numhaptics);
    97       return NULL;
    98    }
    99 
   100    /* If the haptic is already open, return it */
   101    for (i=0; SDL_haptics[i]; i++) {             
   102       if (device_index == SDL_haptics[i]->index) {
   103          haptic = SDL_haptics[i];
   104          ++haptic->ref_count;
   105          return haptic;
   106       }
   107    }
   108 
   109    /* Create the haptic device */
   110    haptic = (SDL_Haptic *) SDL_malloc((sizeof *haptic));
   111    if (haptic == NULL) {
   112       SDL_OutOfMemory();
   113       return NULL;
   114    }
   115 
   116    /* Initialize the haptic device */
   117    SDL_memset(haptic, 0, (sizeof *haptic));
   118    haptic->index = device_index;
   119    if (SDL_SYS_HapticOpen(haptic) < 0) {
   120       SDL_free(haptic);
   121       return NULL;
   122    }
   123 
   124    /* Add haptic to list */
   125    ++haptic->ref_count;
   126    for (i=0; SDL_haptics[i]; i++)
   127       /* Skip to next haptic */ ;
   128    SDL_haptics[i] = haptic;
   129 
   130    return haptic;
   131 }
   132 
   133 
   134 /*
   135  * Returns SDL_TRUE if joystick has haptic features.
   136  */
   137 int
   138 SDL_JoystickIsHaptic(SDL_Joystick * joystick)
   139 {
   140    int ret;
   141 
   142    /* Must be a valid joystick */
   143    if (!SDL_PrivateJoystickValid(&joystick)) {
   144       return -1;
   145    }
   146 
   147    ret = SDL_SYS_JoystickIsHaptic(joystick);
   148 
   149    if (ret > 0) return SDL_TRUE;
   150    else if (ret == 0) return SDL_FALSE;
   151    else return -1;
   152 }
   153 
   154 
   155 /*
   156  * Opens a haptic device from a joystick.
   157  */
   158 SDL_Haptic *
   159 SDL_HapticOpenFromJoystick(SDL_Joystick * joystick)
   160 {
   161    int i;
   162    SDL_Haptic *haptic;
   163 
   164    /* Must be a valid joystick */
   165    if (!SDL_PrivateJoystickValid(&joystick)) {
   166       return NULL;
   167    }
   168 
   169    /* Joystick must be haptic */
   170    if (SDL_SYS_JoystickIsHaptic(joystick) <= 0) {
   171       return NULL;
   172    }
   173 
   174    /* Check to see if joystick's haptic is already open */
   175    for (i=0; SDL_haptics[i]; i++) {
   176       if (SDL_SYS_JoystickSameHaptic(&SDL_haptics[i],joystick)) {
   177          haptic = SDL_haptics[i];
   178          ++haptic->ref_count;
   179          return haptic;
   180       }
   181    }
   182 
   183    /* Create the haptic device */
   184    haptic = (SDL_Haptic *) SDL_malloc((sizeof *haptic));
   185    if (haptic == NULL) {
   186       SDL_OutOfMemory();
   187       return NULL;
   188    }
   189 
   190    /* Initialize the haptic device */
   191    SDL_memset(haptic, 0, (sizeof *haptic));
   192    if (SDL_SYS_HapticOpenFromJoystick(haptic,joystick) < 0) {
   193       SDL_free(haptic);
   194       return NULL;
   195    }
   196 
   197    /* Add haptic to list */
   198    ++haptic->ref_count;
   199    for (i=0; SDL_haptics[i]; i++)
   200       /* Skip to next haptic */ ;
   201    SDL_haptics[i] = haptic;
   202 
   203    return haptic;
   204 }
   205 
   206 
   207 /*
   208  * Checks to see if the haptic device is valid
   209  */
   210 static int
   211 ValidHaptic(SDL_Haptic ** haptic)
   212 {
   213    int valid;
   214 
   215    if (*haptic == NULL) {
   216       SDL_SetError("Haptic device hasn't been opened yet");
   217       valid = 0;
   218    } else {
   219       valid = 1;
   220    }
   221    return valid;
   222 }
   223 
   224 
   225 /*
   226  * Closes a SDL_Haptic device.
   227  */
   228 void
   229 SDL_HapticClose(SDL_Haptic * haptic)
   230 {
   231    int i;
   232 
   233    /* Must be valid */
   234    if (!ValidHaptic(&haptic)) {
   235       return;
   236    }
   237 
   238    /* Check if it's still in use */
   239    if (--haptic->ref_count < 0) {
   240       return;
   241    }
   242 
   243    /* Close it, properly removing effects if needed */
   244    for (i=0; i<haptic->neffects; i++) {
   245       if (haptic->effects[i].hweffect != NULL) {
   246          SDL_HapticDestroyEffect(haptic,i);
   247       }
   248    }
   249    SDL_SYS_HapticClose(haptic);
   250 
   251    /* Remove from the list */
   252    for (i = 0; SDL_haptics[i]; ++i) {
   253       if (haptic == SDL_haptics[i]) {
   254          SDL_memcpy(&SDL_haptics[i], &SDL_haptics[i + 1],
   255                (SDL_numhaptics - i) * sizeof(haptic));
   256          break;
   257       }
   258    }
   259 
   260    /* Free */
   261    SDL_free(haptic);
   262 }
   263 
   264 /*
   265  * Cleans up after the subsystem.
   266  */
   267 void
   268 SDL_HapticQuit(void)
   269 {
   270    SDL_numhaptics = 0;
   271 
   272    SDL_SYS_HapticQuit();
   273    if (SDL_haptics != NULL) {
   274       SDL_free(SDL_haptics);
   275       SDL_haptics = NULL;
   276    }
   277 }
   278 
   279 /*
   280  * Returns the number of effects a haptic device has.
   281  */
   282 int
   283 SDL_HapticNumEffects(SDL_Haptic * haptic)
   284 {
   285    if (!ValidHaptic(&haptic)) {
   286       return -1;
   287    }
   288 
   289    return haptic->neffects;
   290 }
   291 
   292 /*
   293  * Returns supported effects by the device.
   294  */
   295 unsigned int
   296 SDL_HapticQueryEffects(SDL_Haptic * haptic)
   297 {
   298    if (!ValidHaptic(&haptic)) {
   299       return -1;
   300    }
   301 
   302    return haptic->supported;
   303 }
   304 
   305 /*
   306  * Checks to see if the device can support the effect.
   307  */
   308 int
   309 SDL_HapticEffectSupported(SDL_Haptic * haptic, SDL_HapticEffect * effect)
   310 {
   311    if (!ValidHaptic(&haptic)) {
   312       return -1;
   313    }
   314 
   315    if ((haptic->supported & effect->type) != 0)
   316       return SDL_TRUE;
   317    return SDL_FALSE;
   318 }
   319 
   320 /*
   321  * Creates a new haptic effect.
   322  */
   323 int
   324 SDL_HapticNewEffect(SDL_Haptic * haptic, SDL_HapticEffect * effect)
   325 {
   326    int i;
   327 
   328    /* Check for device validity. */
   329    if (!ValidHaptic(&haptic)) {
   330       return -1;
   331    }
   332 
   333    /* Check to see if effect is supported */
   334    if (SDL_HapticEffectSupported(haptic,effect)==SDL_FALSE) {
   335       SDL_SetError("Haptic effect not supported by haptic device.");
   336       return -1;
   337    }
   338 
   339    /* See if there's a free slot */
   340    for (i=0; i<haptic->neffects; i++) {
   341       if (haptic->effects[i].hweffect == NULL) {
   342 
   343          /* Now let the backend create the real effect */
   344          if (SDL_SYS_HapticNewEffect(haptic,&haptic->effects[i],effect) != 0) {
   345             return -1; /* Backend failed to create effect */
   346          }
   347          return i;
   348       }
   349    }
   350 
   351    SDL_SetError("Haptic device has no free space left.");
   352    return -1;
   353 }
   354 
   355 /*
   356  * Checks to see if an effect is valid.
   357  */
   358 static int
   359 ValidEffect(SDL_Haptic * haptic, int effect)
   360 {
   361    if ((effect < 0) || (effect >= haptic->neffects)) {
   362       SDL_SetError("Invalid haptic effect identifier.");
   363       return 0;
   364    }
   365    return 1;
   366 }
   367 
   368 /*
   369  * Updates an effect.
   370  */
   371 int
   372 SDL_HapticUpdateEffect(SDL_Haptic * haptic, int effect, SDL_HapticEffect * data)
   373 {
   374    if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
   375       return -1;
   376    }
   377 
   378    /* Updates the effect */
   379    if (SDL_SYS_HapticUpdateEffect(haptic,&haptic->effects[effect],data) < 0) {
   380       return -1;
   381    }
   382 
   383    return 0;
   384 }
   385 
   386 
   387 /*
   388  * Runs the haptic effect on the device.
   389  */
   390 int
   391 SDL_HapticRunEffect(SDL_Haptic * haptic, int effect)
   392 {
   393    if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
   394       return -1;
   395    }
   396 
   397    /* Run the effect */
   398    if (SDL_SYS_HapticRunEffect(haptic,&haptic->effects[effect]) < 0) {
   399       return -1;
   400    }
   401 
   402    return 0;
   403 }
   404 
   405 /*
   406  * Stops the haptic effect on the device.
   407  */
   408 int
   409 SDL_HapticStopEffect(SDL_Haptic * haptic, int effect)
   410 {
   411    if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
   412       return -1;
   413    }
   414 
   415    /* Stop the effect */
   416    if (SDL_SYS_HapticStopEffect(haptic,&haptic->effects[effect]) < 0) {
   417       return -1;
   418    }
   419 
   420    return 0;
   421 }
   422 
   423 /*
   424  * Gets rid of a haptic effect.
   425  */
   426 void
   427 SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect)
   428 {
   429    if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
   430       return;
   431    }
   432 
   433    /* Not allocated */
   434    if (haptic->effects[effect].hweffect == NULL) {
   435       return;
   436    }
   437 
   438    SDL_SYS_HapticDestroyEffect(haptic, &haptic->effects[effect]);
   439 }
   440 
   441 /*
   442  * Sets the global gain of the device.
   443  */
   444 int
   445 SDL_HapticSetGain(SDL_Haptic * haptic, int gain )
   446 {
   447    if (!ValidHaptic(&haptic)) {
   448       return -1;
   449    }
   450 
   451    if ((haptic->supported & SDL_HAPTIC_GAIN) == 0) {
   452       SDL_SetError("Haptic device does not support setting gain.");
   453       return -1;
   454    }
   455 
   456    if ((gain < 0) || (gain > 100)) {
   457       SDL_SetError("Haptic gain must be between 0 and 100.");
   458       return -1;
   459    }
   460 
   461    if (SDL_SYS_HapticSetGain(haptic,gain) < 0) {
   462       return -1;
   463    }
   464 
   465    return 0;
   466 }
   467 
   468 /*
   469  * Makes the device autocenter, 0 disables.
   470  */
   471 int
   472 SDL_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter )
   473 {
   474    if (!ValidHaptic(&haptic)) {
   475       return -1;
   476    }
   477 
   478    if ((haptic->supported & SDL_HAPTIC_AUTOCENTER) == 0) {
   479       SDL_SetError("Haptic device does not support setting autocenter.");
   480       return -1;
   481    }
   482 
   483    if ((autocenter < 0) || (autocenter > 100)) {
   484       SDL_SetError("Haptic autocenter must be between 0 and 100.");
   485       return -1;
   486    }                                           
   487 
   488    if (SDL_SYS_HapticSetAutocenter(haptic,autocenter) < 0) {
   489       return -1;
   490    }
   491 
   492    return 0;
   493 }
   494 
   495