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