src/haptic/SDL_haptic.c
author David Ludwig <dludwig@pobox.com>
Wed, 25 Dec 2013 21:39:48 -0500
changeset 8563 c0e68f3b6bbb
parent 7719 31b5f9ff36ca
child 8093 b43765095a6f
permissions -rw-r--r--
WinRT: compiled the d3d11 renderer's shaders into SDL itself

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