src/haptic/windows/SDL_windowshaptic.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 21 May 2018 12:00:21 -0400
changeset 11994 8e094f91ddab
parent 11811 5d94cb6b24d3
child 12142 b2123abf97e0
permissions -rw-r--r--
thread: fixed compiler warnings on non-Linux systems that use pthread.

(static function rtkit_setpriority was unused, moved it in with rest of
__LINUX__ section.)
slouken@2713
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 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@8972
    23
#if SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT
slouken@2713
    24
icculus@6990
    25
#include "SDL_assert.h"
icculus@7481
    26
#include "SDL_thread.h"
icculus@7481
    27
#include "SDL_mutex.h"
icculus@7481
    28
#include "SDL_timer.h"
icculus@6990
    29
#include "SDL_hints.h"
slouken@2713
    30
#include "SDL_haptic.h"
slouken@2713
    31
#include "../SDL_syshaptic.h"
slouken@2713
    32
#include "SDL_joystick.h"
slouken@2713
    33
#include "../../joystick/SDL_sysjoystick.h"     /* For the real SDL_Joystick */
slouken@8972
    34
#include "../../joystick/windows/SDL_windowsjoystick_c.h"      /* For joystick hwdata */
slouken@8972
    35
#include "../../joystick/windows/SDL_xinputjoystick_c.h"      /* For xinput rumble */
slouken@2713
    36
slouken@8972
    37
#include "SDL_windowshaptic_c.h"
slouken@8972
    38
#include "SDL_dinputhaptic_c.h"
slouken@8972
    39
#include "SDL_xinputhaptic_c.h"
slouken@2713
    40
slouken@2713
    41
slouken@2713
    42
/*
slouken@2713
    43
 * Internal stuff.
slouken@2713
    44
 */
slouken@8972
    45
SDL_hapticlist_item *SDL_hapticlist = NULL;
icculus@8179
    46
static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
icculus@8179
    47
static int numhaptics = 0;
slouken@2713
    48
slouken@2713
    49
slouken@2713
    50
/*
slouken@2713
    51
 * Initializes the haptic subsystem.
slouken@2713
    52
 */
slouken@2713
    53
int
slouken@2713
    54
SDL_SYS_HapticInit(void)
slouken@2713
    55
{
slouken@8972
    56
    if (SDL_DINPUT_HapticInit() < 0) {
slouken@8972
    57
        return -1;
slouken@2713
    58
    }
slouken@8972
    59
    if (SDL_XINPUT_HapticInit() < 0) {
slouken@8972
    60
        return -1;
slouken@2713
    61
    }
icculus@8179
    62
    return numhaptics;
slouken@2713
    63
}
slouken@2713
    64
icculus@8179
    65
int
slouken@8972
    66
SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
icculus@8179
    67
{
icculus@8179
    68
    if (SDL_hapticlist_tail == NULL) {
icculus@8179
    69
        SDL_hapticlist = SDL_hapticlist_tail = item;
icculus@8179
    70
    } else {
icculus@8179
    71
        SDL_hapticlist_tail->next = item;
icculus@8179
    72
        SDL_hapticlist_tail = item;
icculus@8179
    73
    }
icculus@8179
    74
icculus@8179
    75
    /* Device has been added. */
icculus@8179
    76
    ++numhaptics;
icculus@8179
    77
icculus@8179
    78
    return numhaptics;
icculus@8179
    79
}
icculus@8179
    80
icculus@8179
    81
int
slouken@8972
    82
SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
icculus@8179
    83
{
slouken@8972
    84
    const int retval = item->haptic ? item->haptic->index : -1;
slouken@8972
    85
    if (prev != NULL) {
slouken@8972
    86
        prev->next = item->next;
slouken@8972
    87
    } else {
slouken@8972
    88
        SDL_assert(SDL_hapticlist == item);
slouken@8972
    89
        SDL_hapticlist = item->next;
icculus@8185
    90
    }
slouken@8972
    91
    if (item == SDL_hapticlist_tail) {
slouken@8972
    92
        SDL_hapticlist_tail = prev;
icculus@8179
    93
    }
slouken@8972
    94
    --numhaptics;
slouken@8972
    95
    /* !!! TODO: Send a haptic remove event? */
slouken@8972
    96
    SDL_free(item);
slouken@8972
    97
    return retval;
icculus@8179
    98
}
icculus@8179
    99
icculus@8179
   100
int
philipp@10617
   101
SDL_SYS_NumHaptics(void)
icculus@8179
   102
{
icculus@8179
   103
    return numhaptics;
icculus@8179
   104
}
icculus@8179
   105
icculus@8179
   106
static SDL_hapticlist_item *
icculus@8179
   107
HapticByDevIndex(int device_index)
icculus@8179
   108
{
icculus@8179
   109
    SDL_hapticlist_item *item = SDL_hapticlist;
icculus@8179
   110
icculus@8179
   111
    if ((device_index < 0) || (device_index >= numhaptics)) {
icculus@8179
   112
        return NULL;
slouken@2713
   113
    }
slouken@2713
   114
icculus@8179
   115
    while (device_index > 0) {
icculus@8179
   116
        SDL_assert(item != NULL);
urkle@8183
   117
        --device_index;
icculus@8179
   118
        item = item->next;
slouken@2713
   119
    }
icculus@8179
   120
    return item;
slouken@2713
   121
}
slouken@2713
   122
slouken@2713
   123
/*
slouken@2713
   124
 * Return the name of a haptic device, does not need to be opened.
slouken@2713
   125
 */
slouken@2713
   126
const char *
slouken@2713
   127
SDL_SYS_HapticName(int index)
slouken@2713
   128
{
icculus@8179
   129
    SDL_hapticlist_item *item = HapticByDevIndex(index);
icculus@8179
   130
    return item->name;
slouken@2713
   131
}
slouken@2713
   132
slouken@2713
   133
/*
slouken@2713
   134
 * Opens a haptic device for usage.
slouken@2713
   135
 */
slouken@2713
   136
int
slouken@2713
   137
SDL_SYS_HapticOpen(SDL_Haptic * haptic)
slouken@2713
   138
{
icculus@8179
   139
    SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
slouken@8972
   140
    if (item->bXInputHaptic) {
slouken@8972
   141
        return SDL_XINPUT_HapticOpen(haptic, item);
slouken@8972
   142
    } else {
slouken@8972
   143
        return SDL_DINPUT_HapticOpen(haptic, item);
slouken@8972
   144
    }
slouken@2713
   145
}
slouken@2713
   146
slouken@2713
   147
slouken@2713
   148
/*
slouken@2713
   149
 * Opens a haptic device from first mouse it finds for usage.
slouken@2713
   150
 */
slouken@2713
   151
int
slouken@2713
   152
SDL_SYS_HapticMouse(void)
slouken@2713
   153
{
slouken@8972
   154
#if SDL_HAPTIC_DINPUT
icculus@8179
   155
    SDL_hapticlist_item *item;
urkle@8183
   156
    int index = 0;
slouken@2713
   157
slouken@2713
   158
    /* Grab the first mouse haptic device we find. */
icculus@8179
   159
    for (item = SDL_hapticlist; item != NULL; item = item->next) {
icculus@8179
   160
        if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER ) {
icculus@8179
   161
            return index;
slouken@2713
   162
        }
urkle@8183
   163
        ++index;
slouken@2713
   164
    }
slouken@8972
   165
#endif /* SDL_HAPTIC_DINPUT */
slouken@2713
   166
    return -1;
slouken@2713
   167
}
slouken@2713
   168
slouken@2713
   169
slouken@2713
   170
/*
slouken@2713
   171
 * Checks to see if a joystick has haptic features.
slouken@2713
   172
 */
slouken@2713
   173
int
slouken@2713
   174
SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
slouken@2713
   175
{
icculus@6990
   176
    const struct joystick_hwdata *hwdata = joystick->hwdata;
slouken@8972
   177
#if SDL_HAPTIC_XINPUT
slouken@8972
   178
    if (hwdata->bXInputHaptic) {
slouken@8972
   179
        return 1;
slouken@8972
   180
    }
slouken@8972
   181
#endif
slouken@8972
   182
#if SDL_HAPTIC_DINPUT
slouken@8972
   183
    if (hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
slouken@8972
   184
        return 1;
slouken@8972
   185
    }
slouken@8972
   186
#endif
slouken@8972
   187
    return 0;
slouken@2713
   188
}
slouken@2713
   189
slouken@2713
   190
/*
icculus@7708
   191
 * Checks to see if the haptic device and joystick are in reality the same.
slouken@2713
   192
 */
slouken@2713
   193
int
slouken@2713
   194
SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@2713
   195
{
icculus@7848
   196
    if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
icculus@7846
   197
        return 0;  /* one is XInput, one is not; not the same device. */
slouken@8972
   198
    } else if (joystick->hwdata->bXInputHaptic) {
slouken@8972
   199
        return SDL_XINPUT_JoystickSameHaptic(haptic, joystick);
slouken@8972
   200
    } else {
slouken@8972
   201
        return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
slouken@2713
   202
    }
slouken@2713
   203
}
slouken@2713
   204
slouken@2713
   205
/*
slouken@2713
   206
 * Opens a SDL_Haptic from a SDL_Joystick.
slouken@2713
   207
 */
slouken@2713
   208
int
slouken@2713
   209
SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@2713
   210
{
icculus@6990
   211
    if (joystick->hwdata->bXInputDevice) {
slouken@8972
   212
        return SDL_XINPUT_HapticOpenFromJoystick(haptic, joystick);
icculus@6990
   213
    } else {
slouken@8972
   214
        return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
slouken@5358
   215
    }
slouken@2713
   216
}
slouken@2713
   217
slouken@2713
   218
/*
slouken@2713
   219
 * Closes the haptic device.
slouken@2713
   220
 */
slouken@2713
   221
void
slouken@2713
   222
SDL_SYS_HapticClose(SDL_Haptic * haptic)
slouken@2713
   223
{
slouken@2713
   224
    if (haptic->hwdata) {
slouken@2713
   225
slouken@2713
   226
        /* Free effects. */
slouken@2713
   227
        SDL_free(haptic->effects);
slouken@2713
   228
        haptic->effects = NULL;
slouken@2713
   229
        haptic->neffects = 0;
slouken@2713
   230
slouken@2713
   231
        /* Clean up */
icculus@7481
   232
        if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   233
            SDL_XINPUT_HapticClose(haptic);
icculus@7481
   234
        } else {
slouken@8972
   235
            SDL_DINPUT_HapticClose(haptic);
slouken@2713
   236
        }
slouken@2713
   237
slouken@2713
   238
        /* Free */
slouken@2713
   239
        SDL_free(haptic->hwdata);
slouken@2713
   240
        haptic->hwdata = NULL;
slouken@2713
   241
    }
slouken@2713
   242
}
slouken@2713
   243
slouken@7191
   244
/*
slouken@2713
   245
 * Clean up after system specific haptic stuff
slouken@2713
   246
 */
slouken@2713
   247
void
slouken@2713
   248
SDL_SYS_HapticQuit(void)
slouken@2713
   249
{
icculus@8179
   250
    SDL_hapticlist_item *item;
icculus@8179
   251
    SDL_hapticlist_item *next = NULL;
icculus@8281
   252
    SDL_Haptic *hapticitem = NULL;
slouken@5090
   253
icculus@8281
   254
    extern SDL_Haptic *SDL_haptics;
icculus@8281
   255
    for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
icculus@8281
   256
        if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
icculus@8281
   257
            /* we _have_ to stop the thread before we free the XInput DLL! */
icculus@10003
   258
            SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1);
icculus@8281
   259
            SDL_WaitThread(hapticitem->hwdata->thread, NULL);
icculus@8281
   260
            hapticitem->hwdata->thread = NULL;
icculus@8281
   261
        }
icculus@6990
   262
    }
icculus@6990
   263
icculus@8179
   264
    for (item = SDL_hapticlist; item; item = next) {
icculus@8179
   265
        /* Opened and not closed haptics are leaked, this is on purpose.
icculus@8179
   266
         * Close your haptic devices after usage. */
slouken@8972
   267
        /* !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not. */
icculus@8179
   268
        next = item->next;
icculus@8179
   269
        SDL_free(item->name);
icculus@8179
   270
        SDL_free(item);
slouken@5090
   271
    }
slouken@5090
   272
slouken@8972
   273
    SDL_XINPUT_HapticQuit();
slouken@8972
   274
    SDL_DINPUT_HapticQuit();
slouken@9740
   275
slouken@9740
   276
    numhaptics = 0;
slouken@9740
   277
    SDL_hapticlist = NULL;
slouken@9740
   278
    SDL_hapticlist_tail = NULL;
slouken@2713
   279
}
slouken@2713
   280
slouken@2713
   281
/*
slouken@2713
   282
 * Creates a new haptic effect.
slouken@2713
   283
 */
slouken@2713
   284
int
slouken@2713
   285
SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
slouken@2713
   286
                        SDL_HapticEffect * base)
slouken@2713
   287
{
slouken@8972
   288
    int result;
slouken@2713
   289
slouken@2713
   290
    /* Alloc the effect. */
slouken@2713
   291
    effect->hweffect = (struct haptic_hweffect *)
slouken@2713
   292
        SDL_malloc(sizeof(struct haptic_hweffect));
slouken@2713
   293
    if (effect->hweffect == NULL) {
slouken@2713
   294
        SDL_OutOfMemory();
slouken@8972
   295
        return -1;
slouken@2713
   296
    }
icculus@6990
   297
    SDL_zerop(effect->hweffect);
icculus@6990
   298
icculus@6990
   299
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   300
        result = SDL_XINPUT_HapticNewEffect(haptic, effect, base);
slouken@8972
   301
    } else {
slouken@8972
   302
        result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
icculus@6990
   303
    }
slouken@8972
   304
    if (result < 0) {
slouken@8972
   305
        SDL_free(effect->hweffect);
slouken@8972
   306
        effect->hweffect = NULL;
slouken@2713
   307
    }
slouken@8972
   308
    return result;
slouken@2713
   309
}
slouken@2713
   310
slouken@2713
   311
/*
slouken@2713
   312
 * Updates an effect.
slouken@2713
   313
 */
slouken@2713
   314
int
slouken@2713
   315
SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
slouken@2713
   316
                           struct haptic_effect *effect,
slouken@2713
   317
                           SDL_HapticEffect * data)
slouken@2713
   318
{
icculus@6990
   319
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   320
        return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data);
slouken@8972
   321
    } else {
slouken@8972
   322
        return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
icculus@6990
   323
    }
slouken@2713
   324
}
slouken@2713
   325
slouken@2713
   326
/*
slouken@2713
   327
 * Runs an effect.
slouken@2713
   328
 */
slouken@2713
   329
int
slouken@2713
   330
SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
slouken@2713
   331
                        Uint32 iterations)
slouken@2713
   332
{
icculus@6990
   333
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   334
        return SDL_XINPUT_HapticRunEffect(haptic, effect, iterations);
slouken@8972
   335
    } else {
slouken@8972
   336
        return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
icculus@6990
   337
    }
slouken@2713
   338
}
slouken@2713
   339
slouken@2713
   340
/*
slouken@2713
   341
 * Stops an effect.
slouken@2713
   342
 */
slouken@2713
   343
int
slouken@2713
   344
SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@2713
   345
{
icculus@6990
   346
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   347
        return SDL_XINPUT_HapticStopEffect(haptic, effect);
slouken@8972
   348
    } else {
slouken@8972
   349
        return SDL_DINPUT_HapticStopEffect(haptic, effect);
icculus@6990
   350
    }
slouken@2713
   351
}
slouken@2713
   352
slouken@2713
   353
/*
slouken@2713
   354
 * Frees the effect.
slouken@2713
   355
 */
slouken@2713
   356
void
slouken@2713
   357
SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@2713
   358
{
icculus@6990
   359
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   360
        SDL_XINPUT_HapticDestroyEffect(haptic, effect);
icculus@6990
   361
    } else {
slouken@8972
   362
        SDL_DINPUT_HapticDestroyEffect(haptic, effect);
slouken@2713
   363
    }
slouken@2713
   364
    SDL_free(effect->hweffect);
slouken@2713
   365
    effect->hweffect = NULL;
slouken@2713
   366
}
slouken@2713
   367
slouken@2713
   368
/*
slouken@2713
   369
 * Gets the status of a haptic effect.
slouken@2713
   370
 */
slouken@2713
   371
int
slouken@2713
   372
SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
slouken@2713
   373
                              struct haptic_effect *effect)
slouken@2713
   374
{
slouken@8972
   375
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   376
        return SDL_XINPUT_HapticGetEffectStatus(haptic, effect);
slouken@8972
   377
    } else {
slouken@8972
   378
        return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
slouken@2713
   379
    }
slouken@2713
   380
}
slouken@2713
   381
slouken@2713
   382
/*
slouken@2713
   383
 * Sets the gain.
slouken@2713
   384
 */
slouken@2713
   385
int
slouken@2713
   386
SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
slouken@2713
   387
{
slouken@8972
   388
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   389
        return SDL_XINPUT_HapticSetGain(haptic, gain);
slouken@8972
   390
    } else {
slouken@8972
   391
        return SDL_DINPUT_HapticSetGain(haptic, gain);
slouken@2713
   392
    }
slouken@2713
   393
}
slouken@2713
   394
slouken@2713
   395
/*
slouken@2713
   396
 * Sets the autocentering.
slouken@2713
   397
 */
slouken@2713
   398
int
slouken@2713
   399
SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
slouken@2713
   400
{
slouken@8972
   401
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   402
        return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
slouken@8972
   403
    } else {
slouken@8972
   404
        return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
slouken@2713
   405
    }
slouken@2713
   406
}
slouken@2713
   407
slouken@2713
   408
/*
slouken@2713
   409
 * Pauses the device.
slouken@2713
   410
 */
slouken@2713
   411
int
slouken@2713
   412
SDL_SYS_HapticPause(SDL_Haptic * haptic)
slouken@2713
   413
{
slouken@8972
   414
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   415
        return SDL_XINPUT_HapticPause(haptic);
slouken@8972
   416
    } else {
slouken@8972
   417
        return SDL_DINPUT_HapticPause(haptic);
slouken@2713
   418
    }
slouken@2713
   419
}
slouken@2713
   420
slouken@2713
   421
/*
slouken@2713
   422
 * Pauses the device.
slouken@2713
   423
 */
slouken@2713
   424
int
slouken@2713
   425
SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
slouken@2713
   426
{
slouken@8972
   427
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   428
        return SDL_XINPUT_HapticUnpause(haptic);
slouken@8972
   429
    } else {
slouken@8972
   430
        return SDL_DINPUT_HapticUnpause(haptic);
slouken@2713
   431
    }
slouken@2713
   432
}
slouken@2713
   433
slouken@2713
   434
/*
slouken@2713
   435
 * Stops all the playing effects on the device.
slouken@2713
   436
 */
slouken@2713
   437
int
bobbens@2715
   438
SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
slouken@2713
   439
{
icculus@6990
   440
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   441
        return SDL_XINPUT_HapticStopAll(haptic);
slouken@8972
   442
    } else {
slouken@8972
   443
        return SDL_DINPUT_HapticStopAll(haptic);
icculus@6990
   444
    }
slouken@2713
   445
}
slouken@2713
   446
slouken@8972
   447
#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
slouken@2713
   448
slouken@7191
   449
/* vi: set ts=4 sw=4 expandtab: */