src/haptic/SDL_haptic.c
author Edgar Simo <bobbens@gmail.com>
Wed, 02 Jul 2008 08:24:35 +0000
branchgsoc2008_force_feedback
changeset 2489 96adc8025331
parent 2488 8e2bdbccf7ff
child 2490 be9b206d44af
permissions -rw-r--r--
Exposed some of the joystick stuff to the haptic subsystem.
Added SDL_JoystickIsHaptic().
     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    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    if (!SDL_PrivateJoystickValid(&joystick)) {
   161       return -1;
   162    }
   163    return -1;
   164 }
   165 
   166 
   167 /*
   168  * Checks to see if the haptic device is valid
   169  */
   170 static int
   171 ValidHaptic(SDL_Haptic ** haptic)
   172 {
   173    int valid;
   174 
   175    if (*haptic == NULL) {
   176       SDL_SetError("Haptic device hasn't been opened yet");
   177       valid = 0;
   178    } else {
   179       valid = 1;
   180    }
   181    return valid;
   182 }
   183 
   184 
   185 /*
   186  * Closes a SDL_Haptic device.
   187  */
   188 void
   189 SDL_HapticClose(SDL_Haptic * haptic)
   190 {
   191    int i;
   192 
   193    /* Must be valid */
   194    if (!ValidHaptic(&haptic)) {
   195       return;
   196    }
   197 
   198    /* Check if it's still in use */
   199    if (--haptic->ref_count < 0) {
   200       return;
   201    }
   202 
   203    /* Close it, properly removing effects if needed */
   204    for (i=0; i<haptic->neffects; i++) {
   205       if (haptic->effects[i].hweffect != NULL) {
   206          SDL_HapticDestroyEffect(haptic,i);
   207       }
   208    }
   209    SDL_SYS_HapticClose(haptic);
   210 
   211    /* Remove from the list */
   212    for (i = 0; SDL_haptics[i]; ++i) {
   213       if (haptic == SDL_haptics[i]) {
   214          SDL_memcpy(&SDL_haptics[i], &SDL_haptics[i + 1],
   215                (SDL_numhaptics - i) * sizeof(haptic));
   216          break;
   217       }
   218    }
   219 
   220    /* Free */
   221    SDL_free(haptic);
   222 }
   223 
   224 /*
   225  * Cleans up after the subsystem.
   226  */
   227 void
   228 SDL_HapticQuit(void)
   229 {
   230    SDL_numhaptics = 0;
   231 
   232    SDL_SYS_HapticQuit();
   233    if (SDL_haptics != NULL) {
   234       SDL_free(SDL_haptics);
   235       SDL_haptics = NULL;
   236    }
   237 }
   238 
   239 /*
   240  * Returns the number of effects a haptic device has.
   241  */
   242 int
   243 SDL_HapticNumEffects(SDL_Haptic * haptic)
   244 {
   245    if (!ValidHaptic(&haptic)) {
   246       return -1;
   247    }
   248 
   249    return haptic->neffects;
   250 }
   251 
   252 /*
   253  * Returns supported effects by the device.
   254  */
   255 unsigned int
   256 SDL_HapticQueryEffects(SDL_Haptic * haptic)
   257 {
   258    if (!ValidHaptic(&haptic)) {
   259       return -1;
   260    }
   261 
   262    return haptic->supported;
   263 }
   264 
   265 /*
   266  * Checks to see if the device can support the effect.
   267  */
   268 int
   269 SDL_HapticEffectSupported(SDL_Haptic * haptic, SDL_HapticEffect * effect)
   270 {
   271    if (!ValidHaptic(&haptic)) {
   272       return -1;
   273    }
   274 
   275    if ((haptic->supported & effect->type) != 0)
   276       return SDL_TRUE;
   277    return SDL_FALSE;
   278 }
   279 
   280 /*
   281  * Creates a new haptic effect.
   282  */
   283 int
   284 SDL_HapticNewEffect(SDL_Haptic * haptic, SDL_HapticEffect * effect)
   285 {
   286    int i;
   287 
   288    /* Check for device validity. */
   289    if (!ValidHaptic(&haptic)) {
   290       return -1;
   291    }
   292 
   293    /* Check to see if effect is supported */
   294    if (SDL_HapticEffectSupported(haptic,effect)==SDL_FALSE) {
   295       SDL_SetError("Haptic effect not supported by haptic device.");
   296       return -1;
   297    }
   298 
   299    /* See if there's a free slot */
   300    for (i=0; i<haptic->neffects; i++) {
   301       if (haptic->effects[i].hweffect == NULL) {
   302 
   303          /* Now let the backend create the real effect */
   304          if (SDL_SYS_HapticNewEffect(haptic,&haptic->effects[i],effect) != 0) {
   305             return -1; /* Backend failed to create effect */
   306          }
   307          return i;
   308       }
   309    }
   310 
   311    SDL_SetError("Haptic device has no free space left.");
   312    return -1;
   313 }
   314 
   315 /*
   316  * Checks to see if an effect is valid.
   317  */
   318 static int
   319 ValidEffect(SDL_Haptic * haptic, int effect)
   320 {
   321    if ((effect < 0) || (effect >= haptic->neffects)) {
   322       SDL_SetError("Invalid haptic effect identifier.");
   323       return 0;
   324    }
   325    return 1;
   326 }
   327 
   328 /*
   329  * Updates an effect.
   330  */
   331 int
   332 SDL_HapticUpdateEffect(SDL_Haptic * haptic, int effect, SDL_HapticEffect * data)
   333 {
   334    if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
   335       return -1;
   336    }
   337 
   338    /* Updates the effect */
   339    if (SDL_SYS_HapticUpdateEffect(haptic,&haptic->effects[effect],data) < 0) {
   340       return -1;
   341    }
   342 
   343    return 0;
   344 }
   345 
   346 
   347 /*
   348  * Runs the haptic effect on the device.
   349  */
   350 int
   351 SDL_HapticRunEffect(SDL_Haptic * haptic, int effect)
   352 {
   353    if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
   354       return -1;
   355    }
   356 
   357    /* Run the effect */
   358    if (SDL_SYS_HapticRunEffect(haptic,&haptic->effects[effect]) < 0) {
   359       return -1;
   360    }
   361 
   362    return 0;
   363 }
   364 
   365 /*
   366  * Stops the haptic effect on the device.
   367  */
   368 int
   369 SDL_HapticStopEffect(SDL_Haptic * haptic, int effect)
   370 {
   371    if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
   372       return -1;
   373    }
   374 
   375    /* Stop the effect */
   376    if (SDL_SYS_HapticStopEffect(haptic,&haptic->effects[effect]) < 0) {
   377       return -1;
   378    }
   379 
   380    return 0;
   381 }
   382 
   383 /*
   384  * Gets rid of a haptic effect.
   385  */
   386 void
   387 SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect)
   388 {
   389    if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
   390       return;
   391    }
   392 
   393    /* Not allocated */
   394    if (haptic->effects[effect].hweffect == NULL) {
   395       return;
   396    }
   397 
   398    SDL_SYS_HapticDestroyEffect(haptic, &haptic->effects[effect]);
   399 }
   400 
   401 /*
   402  * Sets the global gain of the device.
   403  */
   404 int
   405 SDL_HapticSetGain(SDL_Haptic * haptic, int gain )
   406 {
   407    if (!ValidHaptic(&haptic)) {
   408       return -1;
   409    }
   410 
   411    if ((haptic->supported & SDL_HAPTIC_GAIN) == 0) {
   412       SDL_SetError("Haptic device does not support setting gain.");
   413       return -1;
   414    }
   415 
   416    if ((gain < 0) || (gain > 100)) {
   417       SDL_SetError("Haptic gain must be between 0 and 100.");
   418       return -1;
   419    }
   420 
   421    if (SDL_SYS_HapticSetGain(haptic,gain) < 0) {
   422       return -1;
   423    }
   424 
   425    return 0;
   426 }
   427 
   428 /*
   429  * Makes the device autocenter, 0 disables.
   430  */
   431 int
   432 SDL_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter )
   433 {
   434    if (!ValidHaptic(&haptic)) {
   435       return -1;
   436    }
   437 
   438    if ((haptic->supported & SDL_HAPTIC_AUTOCENTER) == 0) {
   439       SDL_SetError("Haptic device does not support setting autocenter.");
   440       return -1;
   441    }
   442 
   443    if ((autocenter < 0) || (autocenter > 100)) {
   444       SDL_SetError("Haptic autocenter must be between 0 and 100.");
   445       return -1;
   446    }                                           
   447 
   448    if (SDL_SYS_HapticSetAutocenter(haptic,autocenter) < 0) {
   449       return -1;
   450    }
   451 
   452    return 0;
   453 }
   454 
   455