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