src/haptic/SDL_haptic.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 22 Jun 2015 23:36:06 -0700
changeset 9776 952ff8a5076f
parent 9740 55e88e3bc7cc
child 9998 f67cf37e9cd4
permissions -rw-r--r--
Fixed bug 3030 - SDL_RecreateWindow fails to restore title, icon, etc.

Adam M.

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