src/haptic/windows/SDL_windowshaptic.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 26 May 2015 06:27:46 -0700
changeset 9619 b94b6d0bff0f
parent 8972 dfc759d7486f
child 9740 55e88e3bc7cc
permissions -rw-r--r--
Updated the copyright year to 2015
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@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
icculus@8179
   101
SDL_SYS_NumHaptics()
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@8281
   258
            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@2713
   275
}
slouken@2713
   276
slouken@2713
   277
/*
slouken@2713
   278
 * Creates a new haptic effect.
slouken@2713
   279
 */
slouken@2713
   280
int
slouken@2713
   281
SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
slouken@2713
   282
                        SDL_HapticEffect * base)
slouken@2713
   283
{
slouken@8972
   284
    int result;
slouken@2713
   285
slouken@2713
   286
    /* Alloc the effect. */
slouken@2713
   287
    effect->hweffect = (struct haptic_hweffect *)
slouken@2713
   288
        SDL_malloc(sizeof(struct haptic_hweffect));
slouken@2713
   289
    if (effect->hweffect == NULL) {
slouken@2713
   290
        SDL_OutOfMemory();
slouken@8972
   291
        return -1;
slouken@2713
   292
    }
icculus@6990
   293
    SDL_zerop(effect->hweffect);
icculus@6990
   294
icculus@6990
   295
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   296
        result = SDL_XINPUT_HapticNewEffect(haptic, effect, base);
slouken@8972
   297
    } else {
slouken@8972
   298
        result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
icculus@6990
   299
    }
slouken@8972
   300
    if (result < 0) {
slouken@8972
   301
        SDL_free(effect->hweffect);
slouken@8972
   302
        effect->hweffect = NULL;
slouken@2713
   303
    }
slouken@8972
   304
    return result;
slouken@2713
   305
}
slouken@2713
   306
slouken@2713
   307
/*
slouken@2713
   308
 * Updates an effect.
slouken@2713
   309
 */
slouken@2713
   310
int
slouken@2713
   311
SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
slouken@2713
   312
                           struct haptic_effect *effect,
slouken@2713
   313
                           SDL_HapticEffect * data)
slouken@2713
   314
{
icculus@6990
   315
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   316
        return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data);
slouken@8972
   317
    } else {
slouken@8972
   318
        return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
icculus@6990
   319
    }
slouken@2713
   320
}
slouken@2713
   321
slouken@2713
   322
/*
slouken@2713
   323
 * Runs an effect.
slouken@2713
   324
 */
slouken@2713
   325
int
slouken@2713
   326
SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
slouken@2713
   327
                        Uint32 iterations)
slouken@2713
   328
{
icculus@6990
   329
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   330
        return SDL_XINPUT_HapticRunEffect(haptic, effect, iterations);
slouken@8972
   331
    } else {
slouken@8972
   332
        return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
icculus@6990
   333
    }
slouken@2713
   334
}
slouken@2713
   335
slouken@2713
   336
/*
slouken@2713
   337
 * Stops an effect.
slouken@2713
   338
 */
slouken@2713
   339
int
slouken@2713
   340
SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@2713
   341
{
icculus@6990
   342
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   343
        return SDL_XINPUT_HapticStopEffect(haptic, effect);
slouken@8972
   344
    } else {
slouken@8972
   345
        return SDL_DINPUT_HapticStopEffect(haptic, effect);
icculus@6990
   346
    }
slouken@2713
   347
}
slouken@2713
   348
slouken@2713
   349
/*
slouken@2713
   350
 * Frees the effect.
slouken@2713
   351
 */
slouken@2713
   352
void
slouken@2713
   353
SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@2713
   354
{
icculus@6990
   355
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   356
        SDL_XINPUT_HapticDestroyEffect(haptic, effect);
icculus@6990
   357
    } else {
slouken@8972
   358
        SDL_DINPUT_HapticDestroyEffect(haptic, effect);
slouken@2713
   359
    }
slouken@2713
   360
    SDL_free(effect->hweffect);
slouken@2713
   361
    effect->hweffect = NULL;
slouken@2713
   362
}
slouken@2713
   363
slouken@2713
   364
/*
slouken@2713
   365
 * Gets the status of a haptic effect.
slouken@2713
   366
 */
slouken@2713
   367
int
slouken@2713
   368
SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
slouken@2713
   369
                              struct haptic_effect *effect)
slouken@2713
   370
{
slouken@8972
   371
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   372
        return SDL_XINPUT_HapticGetEffectStatus(haptic, effect);
slouken@8972
   373
    } else {
slouken@8972
   374
        return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
slouken@2713
   375
    }
slouken@2713
   376
}
slouken@2713
   377
slouken@2713
   378
/*
slouken@2713
   379
 * Sets the gain.
slouken@2713
   380
 */
slouken@2713
   381
int
slouken@2713
   382
SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
slouken@2713
   383
{
slouken@8972
   384
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   385
        return SDL_XINPUT_HapticSetGain(haptic, gain);
slouken@8972
   386
    } else {
slouken@8972
   387
        return SDL_DINPUT_HapticSetGain(haptic, gain);
slouken@2713
   388
    }
slouken@2713
   389
}
slouken@2713
   390
slouken@2713
   391
/*
slouken@2713
   392
 * Sets the autocentering.
slouken@2713
   393
 */
slouken@2713
   394
int
slouken@2713
   395
SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
slouken@2713
   396
{
slouken@8972
   397
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   398
        return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
slouken@8972
   399
    } else {
slouken@8972
   400
        return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
slouken@2713
   401
    }
slouken@2713
   402
}
slouken@2713
   403
slouken@2713
   404
/*
slouken@2713
   405
 * Pauses the device.
slouken@2713
   406
 */
slouken@2713
   407
int
slouken@2713
   408
SDL_SYS_HapticPause(SDL_Haptic * haptic)
slouken@2713
   409
{
slouken@8972
   410
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   411
        return SDL_XINPUT_HapticPause(haptic);
slouken@8972
   412
    } else {
slouken@8972
   413
        return SDL_DINPUT_HapticPause(haptic);
slouken@2713
   414
    }
slouken@2713
   415
}
slouken@2713
   416
slouken@2713
   417
/*
slouken@2713
   418
 * Pauses the device.
slouken@2713
   419
 */
slouken@2713
   420
int
slouken@2713
   421
SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
slouken@2713
   422
{
slouken@8972
   423
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   424
        return SDL_XINPUT_HapticUnpause(haptic);
slouken@8972
   425
    } else {
slouken@8972
   426
        return SDL_DINPUT_HapticUnpause(haptic);
slouken@2713
   427
    }
slouken@2713
   428
}
slouken@2713
   429
slouken@2713
   430
/*
slouken@2713
   431
 * Stops all the playing effects on the device.
slouken@2713
   432
 */
slouken@2713
   433
int
bobbens@2715
   434
SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
slouken@2713
   435
{
icculus@6990
   436
    if (haptic->hwdata->bXInputHaptic) {
slouken@8972
   437
        return SDL_XINPUT_HapticStopAll(haptic);
slouken@8972
   438
    } else {
slouken@8972
   439
        return SDL_DINPUT_HapticStopAll(haptic);
icculus@6990
   440
    }
slouken@2713
   441
}
slouken@2713
   442
slouken@8972
   443
#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
slouken@2713
   444
slouken@7191
   445
/* vi: set ts=4 sw=4 expandtab: */