src/haptic/win32/SDL_syshaptic.c
author Edgar Simo <bobbens@gmail.com>
Wed, 06 Aug 2008 09:52:51 +0000
branchgsoc2008_force_feedback
changeset 2623 6deba05725ac
parent 2621 83659de20bf2
child 2626 53dd30491c71
permissions -rw-r--r--
This should hopefully allow initailizing the joystick/haptic subsystems without calling SetVideoMode first.
bobbens@2551
     1
/*
bobbens@2551
     2
    SDL - Simple DirectMedia Layer
bobbens@2551
     3
    Copyright (C) 2008 Edgar Simo
bobbens@2551
     4
bobbens@2551
     5
    This library is free software; you can redistribute it and/or
bobbens@2551
     6
    modify it under the terms of the GNU Lesser General Public
bobbens@2551
     7
    License as published by the Free Software Foundation; either
bobbens@2551
     8
    version 2.1 of the License, or (at your option) any later version.
bobbens@2551
     9
bobbens@2551
    10
    This library is distributed in the hope that it will be useful,
bobbens@2551
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
bobbens@2551
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
bobbens@2551
    13
    Lesser General Public License for more details.
bobbens@2551
    14
bobbens@2551
    15
    You should have received a copy of the GNU Lesser General Public
bobbens@2551
    16
    License along with this library; if not, write to the Free Software
bobbens@2551
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
bobbens@2551
    18
bobbens@2551
    19
    Sam Lantinga
bobbens@2551
    20
    slouken@libsdl.org
bobbens@2551
    21
*/
bobbens@2551
    22
#include "SDL_config.h"
bobbens@2551
    23
bobbens@2551
    24
#ifdef SDL_HAPTIC_DINPUT
bobbens@2551
    25
bobbens@2551
    26
#include "SDL_haptic.h"
bobbens@2551
    27
#include "../SDL_syshaptic.h"
bobbens@2551
    28
#include "SDL_joystick.h"
bobbens@2551
    29
#include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
bobbens@2617
    30
#include "../../joystick/win32/SDL_dxjoystick_c.h" /* For joystick hwdata */
bobbens@2551
    31
bobbens@2551
    32
#define WIN32_LEAN_AND_MEAN
bobbens@2551
    33
#include <windows.h>
bobbens@2551
    34
bobbens@2570
    35
#define DIRECTINPUT_VERSION 0x0700 /* Need at least DirectX 7 for dwStartDelay */
bobbens@2551
    36
#include <dinput.h>
bobbens@2578
    37
#include <dxerr.h>
bobbens@2551
    38
#ifdef _MSC_VER
bobbens@2580
    39
#  pragma comment (lib, "dinput8.lib")
bobbens@2580
    40
#  pragma comment (lib, "dxguid.lib")
bobbens@2580
    41
#  pragma comment (lib, "dxerr.lib")
bobbens@2551
    42
#endif /* _MSC_VER */
bobbens@2551
    43
bobbens@2551
    44
    /* an ISO hack for VisualC++ */
bobbens@2551
    45
#ifdef _MSC_VER
bobbens@2551
    46
#define   snprintf   _snprintf
bobbens@2551
    47
#endif /* _MSC_VER */
bobbens@2551
    48
bobbens@2551
    49
bobbens@2551
    50
#define MAX_HAPTICS  32
bobbens@2551
    51
bobbens@2551
    52
bobbens@2551
    53
/*
bobbens@2551
    54
 * List of available haptic devices.
bobbens@2551
    55
 */
bobbens@2551
    56
static struct
bobbens@2551
    57
{
bobbens@2551
    58
   DIDEVICEINSTANCE instance;
bobbens@2551
    59
   SDL_Haptic *haptic;
bobbens@2612
    60
   DIDEVCAPS capabilities;
bobbens@2551
    61
} SDL_hapticlist[MAX_HAPTICS];
bobbens@2551
    62
bobbens@2551
    63
bobbens@2551
    64
/*
bobbens@2551
    65
 * Haptic system hardware data.
bobbens@2551
    66
 */
bobbens@2551
    67
struct haptic_hwdata
bobbens@2551
    68
{
bobbens@2551
    69
   LPDIRECTINPUTDEVICE2 device;
bobbens@2617
    70
   DWORD axes[3]; /* Axes to use. */
bobbens@2617
    71
   int is_joystick; /* Device is loaded as joystick. */
bobbens@2551
    72
};
bobbens@2551
    73
bobbens@2551
    74
bobbens@2551
    75
/*
bobbens@2551
    76
 * Haptic system effect data.
bobbens@2551
    77
 */
bobbens@2551
    78
struct haptic_hweffect
bobbens@2551
    79
{
bobbens@2551
    80
   DIEFFECT effect;
bobbens@2573
    81
   LPDIRECTINPUTEFFECT ref;
bobbens@2551
    82
};
bobbens@2551
    83
bobbens@2551
    84
bobbens@2551
    85
/*
bobbens@2551
    86
 * Internal stuff.
bobbens@2551
    87
 */
bobbens@2551
    88
static LPDIRECTINPUT dinput = NULL;
bobbens@2551
    89
bobbens@2551
    90
bobbens@2551
    91
/*
bobbens@2568
    92
 * External stuff.
bobbens@2568
    93
 */
bobbens@2580
    94
extern HWND SDL_HelperWindow;
bobbens@2568
    95
bobbens@2568
    96
bobbens@2568
    97
/*
bobbens@2551
    98
 * Prototypes.
bobbens@2551
    99
 */
bobbens@2619
   100
static void DI_SetError(const char *str, HRESULT err);
bobbens@2619
   101
static int DI_GUIDIsSame(const GUID * a, const GUID * b);
bobbens@2619
   102
static int SDL_SYS_HapticOpenFromInstance(SDL_Haptic * haptic, DIDEVICEINSTANCE instance);
bobbens@2619
   103
static int SDL_SYS_HapticOpenFromDevice2(SDL_Haptic * haptic, LPDIRECTINPUTDEVICE2 device2);
bobbens@2619
   104
static DWORD DIGetTriggerButton( Uint16 button );
bobbens@2619
   105
static int SDL_SYS_SetDirection( DIEFFECT * effect, SDL_HapticDirection *dir, int naxes );
bobbens@2619
   106
static int SDL_SYS_ToDIEFFECT( SDL_Haptic * haptic, DIEFFECT * dest, SDL_HapticEffect * src );
bobbens@2619
   107
static void SDL_SYS_HapticFreeDIEFFECT( DIEFFECT * effect, int type );
bobbens@2619
   108
static REFGUID SDL_SYS_HapticEffectType(SDL_HapticEffect * effect);
bobbens@2619
   109
/* Callbacks. */
bobbens@2551
   110
static BOOL CALLBACK EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext);
bobbens@2619
   111
static BOOL CALLBACK DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv);
bobbens@2551
   112
bobbens@2551
   113
bobbens@2551
   114
/* 
bobbens@2551
   115
 * Like SDL_SetError but for DX error codes.
bobbens@2551
   116
 */
bobbens@2551
   117
static void
bobbens@2551
   118
DI_SetError(const char *str, HRESULT err)
bobbens@2551
   119
{
bobbens@2551
   120
   SDL_SetError( "Haptic: %s - %s: %s", str,
bobbens@2578
   121
                 DXGetErrorString(err),
bobbens@2578
   122
                 DXGetErrorDescription(err));
bobbens@2551
   123
}
bobbens@2551
   124
bobbens@2551
   125
bobbens@2551
   126
/*
bobbens@2617
   127
 * Checks to see if two GUID are the same.
bobbens@2617
   128
 */
bobbens@2617
   129
static int
bobbens@2619
   130
DI_GUIDIsSame(const GUID * a, const GUID * b)
bobbens@2617
   131
{
bobbens@2617
   132
   if (((a)->Data1 == (b)->Data1) &&
bobbens@2617
   133
         ((a)->Data2 == (b)->Data2) &&
bobbens@2617
   134
         ((a)->Data3 == (b)->Data3) &&
bobbens@2617
   135
         (SDL_strcmp((a)->Data4, (b)->Data4)==0))
bobbens@2617
   136
      return 1;
bobbens@2617
   137
   return 0;
bobbens@2617
   138
}
bobbens@2617
   139
bobbens@2617
   140
bobbens@2617
   141
/*
bobbens@2551
   142
 * Initializes the haptic subsystem.
bobbens@2551
   143
 */
bobbens@2551
   144
int
bobbens@2551
   145
SDL_SYS_HapticInit(void)
bobbens@2551
   146
{
bobbens@2551
   147
   HRESULT ret;
bobbens@2623
   148
   HINSTANCE instance;
bobbens@2551
   149
bobbens@2551
   150
   if (dinput != NULL) { /* Already open. */
bobbens@2551
   151
      SDL_SetError("Haptic: SubSystem already open.");
bobbens@2551
   152
      return -1;
bobbens@2551
   153
   }
bobbens@2551
   154
bobbens@2551
   155
   /* Clear all the memory. */
bobbens@2551
   156
   SDL_memset(SDL_hapticlist, 0, sizeof(SDL_hapticlist));
bobbens@2551
   157
bobbens@2551
   158
   SDL_numhaptics = 0;
bobbens@2551
   159
bobbens@2551
   160
   ret = CoInitialize(NULL);
bobbens@2551
   161
   if (FAILED(ret)) {
bobbens@2551
   162
      DI_SetError("Coinitialize",ret);
bobbens@2551
   163
      return -1;
bobbens@2551
   164
   }
bobbens@2551
   165
bobbens@2551
   166
   ret = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
bobbens@2551
   167
                          &IID_IDirectInput, &dinput);
bobbens@2551
   168
   if (FAILED(ret)) {
bobbens@2551
   169
      DI_SetError("CoCreateInstance",ret);
bobbens@2551
   170
      return -1;
bobbens@2551
   171
   }
bobbens@2551
   172
bobbens@2551
   173
   /* Because we used CoCreateInstance, we need to Initialize it, first. */
bobbens@2623
   174
   instance = GetModuleHandle(NULL);
bobbens@2623
   175
   if (instance == NULL) {
bobbens@2623
   176
      SDL_SetError("GetModuleHandle() failed with error code %d.", GetLastError());
bobbens@2623
   177
      return -1;
bobbens@2623
   178
   }
bobbens@2623
   179
   ret = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
bobbens@2551
   180
   if (FAILED(ret)) {
bobbens@2551
   181
      DI_SetError("Initializing DirectInput device",ret);
bobbens@2551
   182
      return -1;
bobbens@2551
   183
   }
bobbens@2551
   184
bobbens@2551
   185
   /* Look for haptic devices. */
bobbens@2551
   186
   ret = IDirectInput_EnumDevices( dinput,
bobbens@2607
   187
                                   0, /* Not sure if this is legal, but gets all devices. */
bobbens@2568
   188
                                   EnumHapticsCallback,
bobbens@2551
   189
                                   NULL, DIEDFL_FORCEFEEDBACK | DIEDFL_ATTACHEDONLY);
bobbens@2551
   190
   if (FAILED(ret)) {
bobbens@2551
   191
      DI_SetError("Enumerating DirectInput devices",ret);
bobbens@2551
   192
      return -1;
bobbens@2551
   193
   }
bobbens@2551
   194
bobbens@2551
   195
   return SDL_numhaptics;
bobbens@2551
   196
}
bobbens@2551
   197
bobbens@2551
   198
/*
bobbens@2551
   199
 * Callback to find the haptic devices.
bobbens@2551
   200
 */
bobbens@2551
   201
static BOOL CALLBACK
bobbens@2551
   202
EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
bobbens@2551
   203
{
bobbens@2612
   204
   HRESULT ret;
bobbens@2612
   205
   LPDIRECTINPUTDEVICE device;
bobbens@2612
   206
bobbens@2612
   207
   /* Copy the instance over, useful for creating devices. */
bobbens@2575
   208
   SDL_memcpy(&SDL_hapticlist[SDL_numhaptics].instance, pdidInstance,
bobbens@2551
   209
         sizeof(DIDEVICEINSTANCE));
bobbens@2612
   210
bobbens@2612
   211
   /* Open the device */
bobbens@2614
   212
   ret = IDirectInput_CreateDevice( dinput, &pdidInstance->guidInstance,
bobbens@2612
   213
                                    &device, NULL );
bobbens@2612
   214
   if (FAILED(ret)) {
bobbens@2612
   215
      /* DI_SetError("Creating DirectInput device",ret); */
bobbens@2612
   216
      return DIENUM_CONTINUE;
bobbens@2612
   217
   }
bobbens@2612
   218
bobbens@2612
   219
   /* Get capabilities. */
bobbens@2612
   220
   SDL_hapticlist[SDL_numhaptics].capabilities.dwSize = sizeof(DIDEVCAPS);
bobbens@2612
   221
   ret = IDirectInputDevice_GetCapabilities( device,
bobbens@2612
   222
                                             &SDL_hapticlist[SDL_numhaptics].capabilities );
bobbens@2612
   223
   if (FAILED(ret)) {
bobbens@2612
   224
      /* DI_SetError("Getting device capabilities",ret); */
bobbens@2612
   225
      IDirectInputDevice_Release(device);
bobbens@2612
   226
      return DIENUM_CONTINUE;
bobbens@2612
   227
   }
bobbens@2612
   228
bobbens@2612
   229
   /* Close up device and count it. */
bobbens@2612
   230
   IDirectInputDevice_Release(device);
bobbens@2551
   231
   SDL_numhaptics++;
bobbens@2551
   232
bobbens@2612
   233
   /* Watch out for hard limit. */
bobbens@2551
   234
   if (SDL_numhaptics >= MAX_HAPTICS)
bobbens@2551
   235
      return DIENUM_STOP;
bobbens@2551
   236
bobbens@2551
   237
   return DIENUM_CONTINUE;
bobbens@2551
   238
}
bobbens@2551
   239
bobbens@2551
   240
bobbens@2551
   241
/*
bobbens@2551
   242
 * Return the name of a haptic device, does not need to be opened.
bobbens@2551
   243
 */
bobbens@2551
   244
const char *
bobbens@2551
   245
SDL_SYS_HapticName(int index)
bobbens@2551
   246
{
bobbens@2551
   247
   return SDL_hapticlist[index].instance.tszProductName;
bobbens@2551
   248
}
bobbens@2551
   249
bobbens@2551
   250
bobbens@2551
   251
/*
bobbens@2551
   252
 * Callback to get all supported effects.
bobbens@2551
   253
 */
bobbens@2617
   254
#define EFFECT_TEST(e,s)               \
bobbens@2617
   255
if (DI_GUIDIsSame(&pei->guid, &(e)))   \
bobbens@2551
   256
   haptic->supported |= (s)
bobbens@2551
   257
static BOOL CALLBACK
bobbens@2571
   258
DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
bobbens@2551
   259
{
bobbens@2551
   260
   /* Prepare the haptic device. */
bobbens@2551
   261
   SDL_Haptic *haptic = (SDL_Haptic*) pv;
bobbens@2551
   262
bobbens@2551
   263
   /* Get supported. */
bobbens@2551
   264
   EFFECT_TEST(GUID_Spring,         SDL_HAPTIC_SPRING);
bobbens@2551
   265
   EFFECT_TEST(GUID_Damper,         SDL_HAPTIC_DAMPER);
bobbens@2551
   266
   EFFECT_TEST(GUID_Inertia,        SDL_HAPTIC_INERTIA);
bobbens@2551
   267
   EFFECT_TEST(GUID_Friction,       SDL_HAPTIC_FRICTION);
bobbens@2551
   268
   EFFECT_TEST(GUID_ConstantForce,  SDL_HAPTIC_CONSTANT);
bobbens@2551
   269
   EFFECT_TEST(GUID_CustomForce,    SDL_HAPTIC_CUSTOM);
bobbens@2551
   270
   EFFECT_TEST(GUID_Sine,           SDL_HAPTIC_SINE);
bobbens@2551
   271
   EFFECT_TEST(GUID_Square,         SDL_HAPTIC_SQUARE);
bobbens@2551
   272
   EFFECT_TEST(GUID_Triangle,       SDL_HAPTIC_TRIANGLE);
bobbens@2551
   273
   EFFECT_TEST(GUID_SawtoothUp,     SDL_HAPTIC_SAWTOOTHUP);
bobbens@2551
   274
   EFFECT_TEST(GUID_SawtoothDown,   SDL_HAPTIC_SAWTOOTHDOWN);
bobbens@2551
   275
   EFFECT_TEST(GUID_RampForce,      SDL_HAPTIC_RAMP);
bobbens@2551
   276
  
bobbens@2551
   277
   /* Check for more. */
bobbens@2551
   278
   return DIENUM_CONTINUE;
bobbens@2551
   279
}
bobbens@2551
   280
bobbens@2551
   281
bobbens@2551
   282
/*
bobbens@2601
   283
 * Callback to get supported axes.
bobbens@2601
   284
 */
bobbens@2601
   285
static BOOL CALLBACK
bobbens@2601
   286
DI_DeviceObjectCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
bobbens@2601
   287
{
bobbens@2602
   288
   SDL_Haptic *haptic = (SDL_Haptic *) pvRef;
bobbens@2601
   289
bobbens@2605
   290
   if ((dev->dwType & DIDFT_AXIS) && (dev->dwFlags & DIDOI_FFACTUATOR)) {
bobbens@2601
   291
bobbens@2606
   292
      haptic->hwdata->axes[haptic->naxes] = dev->dwOfs;
bobbens@2601
   293
      haptic->naxes++;
bobbens@2601
   294
bobbens@2601
   295
      /* Currently using the artificial limit of 3 axes. */
bobbens@2601
   296
      if (haptic->naxes >= 3) {
bobbens@2601
   297
         return DIENUM_STOP;
bobbens@2601
   298
      }
bobbens@2601
   299
   }
bobbens@2601
   300
bobbens@2601
   301
   return DIENUM_CONTINUE;
bobbens@2601
   302
}
bobbens@2601
   303
bobbens@2601
   304
bobbens@2601
   305
/*
bobbens@2551
   306
 * Opens the haptic device from the file descriptor.
bobbens@2551
   307
 *
bobbens@2551
   308
 *    Steps:
bobbens@2551
   309
 *       - Open temporary DirectInputDevice interface.
bobbens@2551
   310
 *       - Create DirectInputDevice2 interface.
bobbens@2551
   311
 *       - Release DirectInputDevice interface.
bobbens@2617
   312
 *       - Call SDL_SYS_HapticOpenFromDevice2
bobbens@2551
   313
 */
bobbens@2551
   314
static int
bobbens@2551
   315
SDL_SYS_HapticOpenFromInstance(SDL_Haptic * haptic, DIDEVICEINSTANCE instance)
bobbens@2551
   316
{
bobbens@2551
   317
   HRESULT ret;
bobbens@2617
   318
   int ret2;
bobbens@2551
   319
   LPDIRECTINPUTDEVICE device;
bobbens@2551
   320
bobbens@2551
   321
   /* Allocate the hwdata */
bobbens@2551
   322
   haptic->hwdata = (struct haptic_hwdata *)
bobbens@2551
   323
         SDL_malloc(sizeof(*haptic->hwdata));
bobbens@2551
   324
   if (haptic->hwdata == NULL) {
bobbens@2551
   325
      SDL_OutOfMemory();
bobbens@2551
   326
      goto creat_err;
bobbens@2551
   327
   }
bobbens@2551
   328
   SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
bobbens@2551
   329
  
bobbens@2551
   330
   /* Open the device */
bobbens@2569
   331
   ret = IDirectInput_CreateDevice( dinput, &instance.guidInstance,
bobbens@2569
   332
                                    &device, NULL );
bobbens@2551
   333
   if (FAILED(ret)) {
bobbens@2551
   334
      DI_SetError("Creating DirectInput device",ret);
bobbens@2551
   335
      goto creat_err;
bobbens@2551
   336
   }
bobbens@2551
   337
bobbens@2551
   338
   /* Now get the IDirectInputDevice2 interface, instead. */
bobbens@2551
   339
   ret = IDirectInputDevice_QueryInterface( device,
bobbens@2551
   340
                                            &IID_IDirectInputDevice2,
bobbens@2568
   341
                                            (LPVOID *) &haptic->hwdata->device );
bobbens@2551
   342
   /* Done with the temporary one now. */
bobbens@2551
   343
   IDirectInputDevice_Release(device);
bobbens@2551
   344
   if (FAILED(ret)) {
bobbens@2551
   345
      DI_SetError("Querying DirectInput interface",ret);
bobbens@2551
   346
      goto creat_err;
bobbens@2551
   347
   }
bobbens@2551
   348
bobbens@2617
   349
   ret2 = SDL_SYS_HapticOpenFromDevice2( haptic, haptic->hwdata->device );
bobbens@2617
   350
   if (ret2 < 0) {
bobbens@2617
   351
      goto query_err;
bobbens@2617
   352
   }
bobbens@2617
   353
bobbens@2617
   354
   return 0;
bobbens@2617
   355
bobbens@2617
   356
query_err:
bobbens@2617
   357
   IDirectInputDevice2_Release(haptic->hwdata->device);   
bobbens@2617
   358
creat_err:
bobbens@2617
   359
   if (haptic->hwdata != NULL) {
bobbens@2617
   360
      SDL_free(haptic->hwdata);
bobbens@2617
   361
      haptic->hwdata = NULL;                                              
bobbens@2617
   362
   }
bobbens@2620
   363
   return -1;
bobbens@2617
   364
}
bobbens@2617
   365
bobbens@2617
   366
bobbens@2617
   367
/*
bobbens@2617
   368
 * Opens the haptic device from the file descriptor.
bobbens@2617
   369
 *
bobbens@2617
   370
 *    Steps:
bobbens@2617
   371
 *       - Set cooperative level.
bobbens@2617
   372
 *       - Set data format.
bobbens@2617
   373
 *       - Acquire exclusiveness.
bobbens@2617
   374
 *       - Reset actuators.
bobbens@2617
   375
 *       - Get supported featuers.
bobbens@2617
   376
 */
bobbens@2617
   377
static int
bobbens@2617
   378
SDL_SYS_HapticOpenFromDevice2(SDL_Haptic * haptic, LPDIRECTINPUTDEVICE2 device2)
bobbens@2617
   379
bobbens@2617
   380
{
bobbens@2617
   381
   HRESULT ret;
bobbens@2619
   382
   DIPROPDWORD dipdw;
bobbens@2617
   383
bobbens@2617
   384
   /* We'll use the device2 from now on. */
bobbens@2617
   385
   haptic->hwdata->device = device2;
bobbens@2617
   386
bobbens@2551
   387
   /* Grab it exclusively to use force feedback stuff. */
bobbens@2551
   388
   ret =IDirectInputDevice2_SetCooperativeLevel( haptic->hwdata->device,
bobbens@2580
   389
                                                 SDL_HelperWindow,
bobbens@2551
   390
                                                 DISCL_EXCLUSIVE | DISCL_BACKGROUND );
bobbens@2551
   391
   if (FAILED(ret)) {
bobbens@2551
   392
      DI_SetError("Setting cooperative level to exclusive",ret);
bobbens@2551
   393
      goto acquire_err;
bobbens@2551
   394
   }
bobbens@2551
   395
bobbens@2588
   396
   /* Set data format. */
bobbens@2588
   397
   ret = IDirectInputDevice2_SetDataFormat( haptic->hwdata->device,
bobbens@2588
   398
                                            &c_dfDIJoystick2 );
bobbens@2588
   399
   if (FAILED(ret)) {
bobbens@2588
   400
      DI_SetError("Setting data format",ret);
bobbens@2617
   401
      goto acquire_err;
bobbens@2588
   402
   }
bobbens@2588
   403
bobbens@2601
   404
   /* Get number of axes. */
bobbens@2601
   405
   ret = IDirectInputDevice2_EnumObjects( haptic->hwdata->device,
bobbens@2601
   406
                                          DI_DeviceObjectCallback,
bobbens@2601
   407
                                          haptic, DIDFT_AXIS );
bobbens@2601
   408
   if (FAILED(ret)) {
bobbens@2601
   409
      DI_SetError("Getting device axes",ret);
bobbens@2617
   410
      goto acquire_err;
bobbens@2601
   411
   }
bobbens@2601
   412
bobbens@2587
   413
   /* Acquire the device. */
bobbens@2587
   414
   ret = IDirectInputDevice2_Acquire(haptic->hwdata->device);
bobbens@2587
   415
   if (FAILED(ret)) {
bobbens@2587
   416
      DI_SetError("Acquiring DirectInput device",ret);
bobbens@2617
   417
      goto acquire_err;
bobbens@2587
   418
   }
bobbens@2587
   419
bobbens@2551
   420
   /* Reset all actuators - just in case. */
bobbens@2551
   421
   ret = IDirectInputDevice2_SendForceFeedbackCommand( haptic->hwdata->device,
bobbens@2551
   422
                                                       DISFFC_RESET );
bobbens@2551
   423
   if (FAILED(ret)) {
bobbens@2551
   424
      DI_SetError("Resetting device",ret);
bobbens@2551
   425
      goto acquire_err;
bobbens@2551
   426
   }
bobbens@2551
   427
bobbens@2551
   428
   /* Enabling actuators. */
bobbens@2551
   429
   ret = IDirectInputDevice2_SendForceFeedbackCommand( haptic->hwdata->device,
bobbens@2551
   430
                                                       DISFFC_SETACTUATORSON );
bobbens@2551
   431
   if (FAILED(ret)) {
bobbens@2551
   432
      DI_SetError("Enabling actuators",ret);
bobbens@2551
   433
      goto acquire_err;
bobbens@2551
   434
   }
bobbens@2551
   435
bobbens@2551
   436
   /* Get supported effects. */
bobbens@2568
   437
   ret = IDirectInputDevice2_EnumEffects( haptic->hwdata->device, 
bobbens@2568
   438
                                          DI_EffectCallback, haptic, DIEFT_ALL );
bobbens@2551
   439
   if (FAILED(ret)) {
bobbens@2551
   440
      DI_SetError("Enumerating supported effects",ret);
bobbens@2551
   441
      goto acquire_err;
bobbens@2551
   442
   }
bobbens@2551
   443
   if (haptic->supported == 0) { /* Error since device supports nothing. */
bobbens@2551
   444
      SDL_SetError("Haptic: Internal error on finding supported effects.");
bobbens@2551
   445
      goto acquire_err;
bobbens@2551
   446
   }
bobbens@2551
   447
bobbens@2551
   448
   /* Check autogain and autocenter. */
bobbens@2551
   449
   dipdw.diph.dwSize       = sizeof(DIPROPDWORD); 
bobbens@2551
   450
   dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
bobbens@2551
   451
   dipdw.diph.dwObj        = 0;
bobbens@2551
   452
   dipdw.diph.dwHow        = DIPH_DEVICE;
bobbens@2551
   453
   dipdw.dwData            = 10000;
bobbens@2551
   454
   ret = IDirectInputDevice2_SetProperty( haptic->hwdata->device,        
bobbens@2551
   455
                                          DIPROP_FFGAIN, &dipdw.diph );
bobbens@2606
   456
   if (!FAILED(ret)) { /* Gain is supported. */
bobbens@2551
   457
      haptic->supported |= SDL_HAPTIC_GAIN;
bobbens@2551
   458
   }
bobbens@2601
   459
   dipdw.diph.dwObj        = 0;
bobbens@2601
   460
   dipdw.diph.dwHow        = DIPH_DEVICE;
bobbens@2551
   461
   dipdw.dwData            = DIPROPAUTOCENTER_OFF;
bobbens@2551
   462
   ret = IDirectInputDevice2_SetProperty( haptic->hwdata->device,
bobbens@2551
   463
                                          DIPROP_AUTOCENTER, &dipdw.diph );
bobbens@2606
   464
   if (!FAILED(ret)) { /* Autocenter is supported. */
bobbens@2551
   465
      haptic->supported |= SDL_HAPTIC_AUTOCENTER;
bobbens@2551
   466
   }
bobbens@2551
   467
bobbens@2551
   468
   /* Check maximum effects. */
bobbens@2551
   469
   haptic->neffects = 128; /* TODO actually figure this out. */
bobbens@2551
   470
   haptic->nplaying = 128;
bobbens@2551
   471
bobbens@2551
   472
   /* Prepare effects memory. */
bobbens@2551
   473
   haptic->effects = (struct haptic_effect *)
bobbens@2551
   474
         SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
bobbens@2551
   475
   if (haptic->effects == NULL) {
bobbens@2551
   476
      SDL_OutOfMemory();
bobbens@2551
   477
      goto acquire_err;
bobbens@2551
   478
   }
bobbens@2551
   479
   /* Clear the memory */
bobbens@2551
   480
   SDL_memset(haptic->effects, 0,
bobbens@2551
   481
         sizeof(struct haptic_effect) * haptic->neffects);
bobbens@2551
   482
   
bobbens@2551
   483
   return 0;
bobbens@2551
   484
   
bobbens@2551
   485
   /* Error handling */
bobbens@2551
   486
acquire_err:
bobbens@2551
   487
   IDirectInputDevice2_Unacquire(haptic->hwdata->device);
bobbens@2551
   488
   return -1;
bobbens@2551
   489
bobbens@2551
   490
}
bobbens@2551
   491
bobbens@2551
   492
bobbens@2551
   493
/*
bobbens@2551
   494
 * Opens a haptic device for usage.
bobbens@2551
   495
 */
bobbens@2551
   496
int
bobbens@2551
   497
SDL_SYS_HapticOpen(SDL_Haptic * haptic)
bobbens@2551
   498
{
bobbens@2551
   499
   return SDL_SYS_HapticOpenFromInstance( haptic,
bobbens@2551
   500
         SDL_hapticlist[haptic->index].instance );
bobbens@2551
   501
}
bobbens@2551
   502
bobbens@2551
   503
bobbens@2551
   504
/*
bobbens@2551
   505
 * Opens a haptic device from first mouse it finds for usage.
bobbens@2551
   506
 */
bobbens@2551
   507
int
bobbens@2551
   508
SDL_SYS_HapticMouse(void)
bobbens@2551
   509
{
bobbens@2612
   510
   int i;
bobbens@2612
   511
bobbens@2615
   512
   /* Grab the first mouse haptic device we find. */
bobbens@2612
   513
   for (i=0; i<SDL_numhaptics; i++) {
bobbens@2615
   514
      if (SDL_hapticlist[i].capabilities.dwDevType == DIDEVTYPE_MOUSE ) {
bobbens@2615
   515
         return i;
bobbens@2615
   516
      }
bobbens@2612
   517
   }
bobbens@2615
   518
bobbens@2551
   519
   return -1;
bobbens@2551
   520
}
bobbens@2551
   521
bobbens@2551
   522
bobbens@2551
   523
/*
bobbens@2551
   524
 * Checks to see if a joystick has haptic features.
bobbens@2551
   525
 */
bobbens@2551
   526
int
bobbens@2551
   527
SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
bobbens@2551
   528
{
bobbens@2617
   529
   if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
bobbens@2617
   530
      return SDL_TRUE;
bobbens@2617
   531
   }
bobbens@2617
   532
bobbens@2551
   533
   return SDL_FALSE;
bobbens@2551
   534
}
bobbens@2551
   535
bobbens@2551
   536
bobbens@2551
   537
/*
bobbens@2551
   538
 * Checks to see if the haptic device and joystick and in reality the same.
bobbens@2551
   539
 */
bobbens@2551
   540
int
bobbens@2551
   541
SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
bobbens@2551
   542
{
bobbens@2617
   543
   HRESULT ret;
bobbens@2617
   544
   DIDEVICEINSTANCE hap_instance, joy_instance;
bobbens@2617
   545
bobbens@2617
   546
   /* Get the device instances. */
bobbens@2617
   547
   ret = IDirectInputDevice2_GetDeviceInfo( haptic->hwdata->device,
bobbens@2617
   548
                                            &hap_instance );
bobbens@2617
   549
   if (FAILED(ret)) {
bobbens@2617
   550
      return 0;
bobbens@2617
   551
   }
bobbens@2617
   552
   ret = IDirectInputDevice2_GetDeviceInfo( joystick->hwdata->InputDevice,
bobbens@2617
   553
                                            &joy_instance );
bobbens@2617
   554
   if (FAILED(ret)) {
bobbens@2617
   555
      return 0;
bobbens@2617
   556
   }
bobbens@2617
   557
bobbens@2617
   558
   if (DI_GUIDIsSame(&hap_instance.guidInstance, &joy_instance.guidInstance))
bobbens@2617
   559
      return 1;
bobbens@2617
   560
bobbens@2551
   561
   return 0;
bobbens@2551
   562
}
bobbens@2551
   563
bobbens@2551
   564
bobbens@2551
   565
/*
bobbens@2551
   566
 * Opens a SDL_Haptic from a SDL_Joystick.
bobbens@2551
   567
 */
bobbens@2551
   568
int
bobbens@2551
   569
SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
bobbens@2551
   570
{
bobbens@2617
   571
   int ret;
bobbens@2617
   572
bobbens@2621
   573
   /* Allocate the hwdata */
bobbens@2621
   574
   haptic->hwdata = (struct haptic_hwdata *)
bobbens@2621
   575
         SDL_malloc(sizeof(*haptic->hwdata));
bobbens@2621
   576
   if (haptic->hwdata == NULL) {
bobbens@2621
   577
      SDL_OutOfMemory();
bobbens@2621
   578
      return -1;
bobbens@2621
   579
   }
bobbens@2621
   580
   SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
bobbens@2621
   581
bobbens@2621
   582
   /* Now open the device. */
bobbens@2617
   583
   ret = SDL_SYS_HapticOpenFromDevice2( haptic, joystick->hwdata->InputDevice );  
bobbens@2617
   584
   if (ret < 0) {
bobbens@2617
   585
      return -1;
bobbens@2617
   586
   }
bobbens@2617
   587
bobbens@2617
   588
   /* It's using the joystick device. */
bobbens@2617
   589
   haptic->hwdata->is_joystick = 1;
bobbens@2617
   590
bobbens@2617
   591
   return 0;
bobbens@2551
   592
}
bobbens@2551
   593
bobbens@2551
   594
bobbens@2551
   595
/*
bobbens@2551
   596
 * Closes the haptic device.
bobbens@2551
   597
 */
bobbens@2551
   598
void
bobbens@2551
   599
SDL_SYS_HapticClose(SDL_Haptic * haptic)
bobbens@2551
   600
{
bobbens@2551
   601
   if (haptic->hwdata) {
bobbens@2551
   602
bobbens@2561
   603
      /* Free effects. */
bobbens@2551
   604
      SDL_free(haptic->effects);
bobbens@2561
   605
      haptic->effects = NULL;
bobbens@2551
   606
      haptic->neffects = 0;
bobbens@2551
   607
bobbens@2551
   608
      /* Clean up */
bobbens@2551
   609
      IDirectInputDevice2_Unacquire(haptic->hwdata->device);
bobbens@2617
   610
      /* Only release if isn't grabbed by a joystick. */
bobbens@2617
   611
      if (haptic->hwdata->is_joystick == 0) {
bobbens@2617
   612
         IDirectInputDevice2_Release(haptic->hwdata->device);   
bobbens@2617
   613
      }
bobbens@2551
   614
bobbens@2551
   615
      /* Free */
bobbens@2551
   616
      SDL_free(haptic->hwdata);
bobbens@2551
   617
      haptic->hwdata = NULL;
bobbens@2551
   618
   }
bobbens@2551
   619
}
bobbens@2551
   620
bobbens@2551
   621
bobbens@2551
   622
/* 
bobbens@2551
   623
 * Clean up after system specific haptic stuff
bobbens@2551
   624
 */
bobbens@2551
   625
void
bobbens@2551
   626
SDL_SYS_HapticQuit(void)
bobbens@2551
   627
{
bobbens@2551
   628
   IDirectInput_Release(dinput);
bobbens@2551
   629
   dinput = NULL;
bobbens@2551
   630
}
bobbens@2551
   631
bobbens@2551
   632
bobbens@2551
   633
/*
bobbens@2566
   634
 * Converts an SDL trigger button to an DIEFFECT trigger button.
bobbens@2566
   635
 */
bobbens@2566
   636
static DWORD
bobbens@2566
   637
DIGetTriggerButton( Uint16 button )
bobbens@2566
   638
{
bobbens@2566
   639
   DWORD dwTriggerButton;
bobbens@2566
   640
   
bobbens@2566
   641
   dwTriggerButton = DIEB_NOTRIGGER;
bobbens@2566
   642
   
bobbens@2566
   643
   if (button != 0) {
bobbens@2566
   644
      dwTriggerButton = DIJOFS_BUTTON(button - 1);
bobbens@2566
   645
   }                                                                      
bobbens@2566
   646
                                                                          
bobbens@2566
   647
   return dwTriggerButton;
bobbens@2566
   648
}
bobbens@2566
   649
bobbens@2566
   650
bobbens@2566
   651
/*
bobbens@2551
   652
 * Sets the direction.
bobbens@2551
   653
 */
bobbens@2551
   654
static int
bobbens@2566
   655
SDL_SYS_SetDirection( DIEFFECT * effect, SDL_HapticDirection *dir, int naxes )
bobbens@2551
   656
{
bobbens@2551
   657
   LONG *rglDir;
bobbens@2551
   658
bobbens@2551
   659
   /* Handle no axes a part. */
bobbens@2551
   660
   if (naxes == 0) {
bobbens@2599
   661
      effect->dwFlags |= DIEFF_SPHERICAL; /* Set as default. */
bobbens@2551
   662
      effect->rglDirection = NULL;
bobbens@2551
   663
      return 0;
bobbens@2551
   664
   }
bobbens@2551
   665
bobbens@2551
   666
   /* Has axes. */
bobbens@2551
   667
   rglDir = SDL_malloc( sizeof(LONG) * naxes );
bobbens@2551
   668
   if (rglDir == NULL) {
bobbens@2551
   669
      SDL_OutOfMemory();
bobbens@2551
   670
      return -1;
bobbens@2551
   671
   }
bobbens@2551
   672
   SDL_memset( rglDir, 0, sizeof(LONG) * naxes );
bobbens@2551
   673
   effect->rglDirection = rglDir;
bobbens@2551
   674
bobbens@2551
   675
   switch (dir->type) {
bobbens@2551
   676
      case SDL_HAPTIC_POLAR:
bobbens@2566
   677
         effect->dwFlags |= DIEFF_POLAR;
bobbens@2551
   678
         rglDir[0] = dir->dir[0];
bobbens@2551
   679
         return 0;
bobbens@2551
   680
      case SDL_HAPTIC_CARTESIAN:
bobbens@2566
   681
         effect->dwFlags |= DIEFF_CARTESIAN;
bobbens@2551
   682
         rglDir[0] = dir->dir[0];
bobbens@2604
   683
         if (naxes > 1)
bobbens@2604
   684
            rglDir[1] = dir->dir[1];
bobbens@2604
   685
         if (naxes > 2)
bobbens@2604
   686
            rglDir[2] = dir->dir[2];
bobbens@2551
   687
         return 0;
bobbens@2551
   688
      case SDL_HAPTIC_SPHERICAL:
bobbens@2566
   689
         effect->dwFlags |= DIEFF_SPHERICAL;
bobbens@2551
   690
         rglDir[0] = dir->dir[0];
bobbens@2604
   691
         if (naxes > 1)
bobbens@2604
   692
            rglDir[1] = dir->dir[1];
bobbens@2604
   693
         if (naxes > 2)
bobbens@2604
   694
            rglDir[2] = dir->dir[2];
bobbens@2551
   695
         return 0;
bobbens@2551
   696
bobbens@2551
   697
      default:
bobbens@2551
   698
         SDL_SetError("Haptic: Unknown direction type.");
bobbens@2551
   699
         return -1;
bobbens@2551
   700
   }
bobbens@2551
   701
}
bobbens@2551
   702
bobbens@2609
   703
#define CONVERT(x)   (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
bobbens@2551
   704
/*
bobbens@2566
   705
 * Creates the DIEFFECT from a SDL_HapticEffect.
bobbens@2551
   706
 */
bobbens@2551
   707
static int
bobbens@2566
   708
SDL_SYS_ToDIEFFECT( SDL_Haptic * haptic, DIEFFECT * dest, SDL_HapticEffect * src )
bobbens@2551
   709
{
bobbens@2551
   710
   int i;
bobbens@2566
   711
   DICONSTANTFORCE *constant;
bobbens@2566
   712
   DIPERIODIC *periodic;
bobbens@2566
   713
   DICONDITION *condition; /* Actually an array of conditions - one per axis. */
bobbens@2566
   714
   DIRAMPFORCE *ramp;
bobbens@2566
   715
   DICUSTOMFORCE *custom;
bobbens@2566
   716
   DIENVELOPE *envelope;
bobbens@2551
   717
   SDL_HapticConstant *hap_constant;
bobbens@2551
   718
   SDL_HapticPeriodic *hap_periodic;
bobbens@2551
   719
   SDL_HapticCondition *hap_condition;
bobbens@2551
   720
   SDL_HapticRamp *hap_ramp;
bobbens@2551
   721
   SDL_HapticCustom *hap_custom;
bobbens@2551
   722
   DWORD *axes;
bobbens@2551
   723
bobbens@2551
   724
   /* Set global stuff. */
bobbens@2566
   725
   SDL_memset(dest, 0, sizeof(DIEFFECT));
bobbens@2566
   726
   dest->dwSize = sizeof(DIEFFECT); /* Set the structure size. */
bobbens@2551
   727
   dest->dwSamplePeriod = 0; /* Not used by us. */
bobbens@2551
   728
   dest->dwGain = 10000; /* Gain is set globally, not locally. */
bobbens@2600
   729
   dest->dwFlags = DIEFF_OBJECTOFFSETS; /* Seems obligatory. */
bobbens@2551
   730
bobbens@2551
   731
   /* Envelope. */
bobbens@2566
   732
   envelope = SDL_malloc( sizeof(DIENVELOPE) );
bobbens@2551
   733
   if (envelope == NULL) {
bobbens@2551
   734
      SDL_OutOfMemory();
bobbens@2551
   735
      return -1;
bobbens@2551
   736
   }
bobbens@2566
   737
   SDL_memset(envelope, 0, sizeof(DIENVELOPE));
bobbens@2551
   738
   dest->lpEnvelope = envelope;
bobbens@2566
   739
   envelope->dwSize = sizeof(DIENVELOPE); /* Always should be this. */
bobbens@2551
   740
bobbens@2551
   741
   /* Axes. */
bobbens@2551
   742
   dest->cAxes = haptic->naxes;
bobbens@2551
   743
   if (dest->cAxes > 0) {
bobbens@2551
   744
      axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
bobbens@2551
   745
      if (axes == NULL) {
bobbens@2551
   746
         SDL_OutOfMemory();
bobbens@2551
   747
         return -1;
bobbens@2551
   748
      }
bobbens@2606
   749
      axes[0] = haptic->hwdata->axes[0]; /* Always at least one axis. */
bobbens@2551
   750
      if (dest->cAxes > 1) {
bobbens@2606
   751
         axes[1] = haptic->hwdata->axes[1];
bobbens@2551
   752
      }
bobbens@2551
   753
      if (dest->cAxes > 2) {
bobbens@2606
   754
         axes[2] = haptic->hwdata->axes[2];
bobbens@2551
   755
      }
bobbens@2551
   756
      dest->rgdwAxes = axes;
bobbens@2551
   757
   }
bobbens@2551
   758
bobbens@2551
   759
bobbens@2551
   760
   /* The big type handling switch, even bigger then linux's version. */
bobbens@2551
   761
   switch (src->type) {
bobbens@2551
   762
      case SDL_HAPTIC_CONSTANT:
bobbens@2551
   763
         hap_constant = &src->constant;
bobbens@2566
   764
         constant = SDL_malloc( sizeof(DICONSTANTFORCE) );
bobbens@2551
   765
         if (constant == NULL) {
bobbens@2551
   766
            SDL_OutOfMemory();
bobbens@2551
   767
            return -1;
bobbens@2551
   768
         }
bobbens@2566
   769
         SDL_memset(constant, 0, sizeof(DICONSTANTFORCE));
bobbens@2551
   770
bobbens@2551
   771
         /* Specifics */
bobbens@2551
   772
         constant->lMagnitude = CONVERT(hap_constant->level);
bobbens@2566
   773
         dest->cbTypeSpecificParams = sizeof(DICONSTANTFORCE); 
bobbens@2551
   774
         dest->lpvTypeSpecificParams = constant;
bobbens@2551
   775
bobbens@2551
   776
         /* Generics */
bobbens@2551
   777
         dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */
bobbens@2566
   778
         dest->dwTriggerButton = DIGetTriggerButton(hap_constant->button);
bobbens@2551
   779
         dest->dwTriggerRepeatInterval = hap_constant->interval;
bobbens@2551
   780
         dest->dwStartDelay = hap_constant->delay * 1000; /* In microseconds. */
bobbens@2551
   781
bobbens@2551
   782
         /* Direction. */
bobbens@2551
   783
         if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes) < 0) {
bobbens@2551
   784
            return -1;
bobbens@2551
   785
         }
bobbens@2551
   786
         
bobbens@2551
   787
         /* Envelope */
bobbens@2566
   788
         if ((hap_constant->attack_length==0) && (hap_constant->fade_length==0)) {
bobbens@2566
   789
            SDL_free(dest->lpEnvelope);
bobbens@2566
   790
            dest->lpEnvelope = NULL;
bobbens@2566
   791
         }
bobbens@2566
   792
         else {
bobbens@2566
   793
            envelope->dwAttackLevel = CONVERT(hap_constant->attack_level);
bobbens@2566
   794
            envelope->dwAttackTime = hap_constant->attack_length * 1000;
bobbens@2566
   795
            envelope->dwFadeLevel = CONVERT(hap_constant->fade_level);
bobbens@2566
   796
            envelope->dwFadeTime = hap_constant->fade_length * 1000;
bobbens@2566
   797
         }
bobbens@2551
   798
bobbens@2551
   799
         break;
bobbens@2551
   800
bobbens@2551
   801
      case SDL_HAPTIC_SINE:
bobbens@2551
   802
      case SDL_HAPTIC_SQUARE:
bobbens@2551
   803
      case SDL_HAPTIC_TRIANGLE:
bobbens@2551
   804
      case SDL_HAPTIC_SAWTOOTHUP:
bobbens@2551
   805
      case SDL_HAPTIC_SAWTOOTHDOWN:
bobbens@2551
   806
         hap_periodic = &src->periodic;
bobbens@2566
   807
         periodic = SDL_malloc(sizeof(DIPERIODIC));
bobbens@2551
   808
         if (periodic == NULL) {
bobbens@2551
   809
            SDL_OutOfMemory();
bobbens@2551
   810
            return -1;
bobbens@2551
   811
         }
bobbens@2566
   812
         SDL_memset(periodic, 0, sizeof(DIPERIODIC));
bobbens@2551
   813
bobbens@2551
   814
         /* Specifics */
bobbens@2551
   815
         periodic->dwMagnitude = CONVERT(hap_periodic->magnitude);
bobbens@2551
   816
         periodic->lOffset = CONVERT(hap_periodic->offset);
bobbens@2551
   817
         periodic->dwPhase = hap_periodic->phase;
bobbens@2551
   818
         periodic->dwPeriod = hap_periodic->period * 1000;
bobbens@2566
   819
         dest->cbTypeSpecificParams = sizeof(DIPERIODIC);
bobbens@2551
   820
         dest->lpvTypeSpecificParams = periodic;
bobbens@2551
   821
bobbens@2551
   822
         /* Generics */
bobbens@2551
   823
         dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */
bobbens@2566
   824
         dest->dwTriggerButton = DIGetTriggerButton(hap_periodic->button);
bobbens@2551
   825
         dest->dwTriggerRepeatInterval = hap_periodic->interval;
bobbens@2551
   826
         dest->dwStartDelay = hap_periodic->delay * 1000; /* In microseconds. */
bobbens@2551
   827
         
bobbens@2551
   828
         /* Direction. */
bobbens@2551
   829
         if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes) < 0) {
bobbens@2551
   830
            return -1;
bobbens@2551
   831
         }
bobbens@2551
   832
         
bobbens@2551
   833
         /* Envelope */
bobbens@2566
   834
         if ((hap_periodic->attack_length==0) && (hap_periodic->fade_length==0)) {
bobbens@2566
   835
            SDL_free(dest->lpEnvelope);
bobbens@2566
   836
            dest->lpEnvelope = NULL;
bobbens@2566
   837
         }
bobbens@2566
   838
         else {
bobbens@2566
   839
            envelope->dwAttackLevel = CONVERT(hap_periodic->attack_level);
bobbens@2566
   840
            envelope->dwAttackTime = hap_periodic->attack_length * 1000;
bobbens@2566
   841
            envelope->dwFadeLevel = CONVERT(hap_periodic->fade_level);
bobbens@2566
   842
            envelope->dwFadeTime = hap_periodic->fade_length * 1000;
bobbens@2566
   843
         }
bobbens@2551
   844
bobbens@2551
   845
         break;
bobbens@2551
   846
bobbens@2551
   847
      case SDL_HAPTIC_SPRING:
bobbens@2551
   848
      case SDL_HAPTIC_DAMPER:
bobbens@2551
   849
      case SDL_HAPTIC_INERTIA:
bobbens@2551
   850
      case SDL_HAPTIC_FRICTION:
bobbens@2551
   851
         hap_condition = &src->condition;
bobbens@2566
   852
         condition = SDL_malloc(sizeof(DICONDITION) * dest->cAxes);
bobbens@2551
   853
         if (condition == NULL) {
bobbens@2551
   854
            SDL_OutOfMemory();
bobbens@2551
   855
            return -1;
bobbens@2551
   856
         }
bobbens@2566
   857
         SDL_memset(condition, 0, sizeof(DICONDITION));
bobbens@2551
   858
bobbens@2551
   859
         /* Specifics */
bobbens@2572
   860
         for (i=0; i<(int)dest->cAxes; i++) {
bobbens@2551
   861
            condition[i].lOffset = CONVERT(hap_condition->center[i]);
bobbens@2551
   862
            condition[i].lPositiveCoefficient = CONVERT(hap_condition->right_coeff[i]);
bobbens@2551
   863
            condition[i].lNegativeCoefficient = CONVERT(hap_condition->left_coeff[i]);
bobbens@2551
   864
            condition[i].dwPositiveSaturation = CONVERT(hap_condition->right_sat[i]);
bobbens@2551
   865
            condition[i].dwNegativeSaturation = CONVERT(hap_condition->left_sat[i]);
bobbens@2551
   866
            condition[i].lDeadBand = CONVERT(hap_condition->deadband[i]);
bobbens@2551
   867
         }
bobbens@2566
   868
         dest->cbTypeSpecificParams = sizeof(DICONDITION) * dest->cAxes;
bobbens@2551
   869
         dest->lpvTypeSpecificParams = condition;
bobbens@2551
   870
bobbens@2551
   871
         /* Generics */
bobbens@2551
   872
         dest->dwDuration = hap_condition->length * 1000; /* In microseconds. */
bobbens@2566
   873
         dest->dwTriggerButton = DIGetTriggerButton(hap_condition->button);
bobbens@2551
   874
         dest->dwTriggerRepeatInterval = hap_condition->interval;
bobbens@2551
   875
         dest->dwStartDelay = hap_condition->delay * 1000; /* In microseconds. */
bobbens@2551
   876
bobbens@2551
   877
         /* Direction. */
bobbens@2551
   878
         if (SDL_SYS_SetDirection(dest, &hap_condition->direction, dest->cAxes) < 0) {
bobbens@2551
   879
            return -1;                
bobbens@2551
   880
         }                            
bobbens@2551
   881
                                      
bobbens@2551
   882
         /* Envelope */
bobbens@2551
   883
/* TODO Check is envelope actually used.
bobbens@2551
   884
         envelope->dwAttackLevel = CONVERT(hap_condition->attack_level);
bobbens@2551
   885
         envelope->dwAttackTime = hap_condition->attack_length * 1000;
bobbens@2551
   886
         envelope->dwFadeLevel = CONVERT(hap_condition->fade_level);
bobbens@2551
   887
         envelope->dwFadeTime = hap_condition->fade_length * 1000;
bobbens@2551
   888
*/
bobbens@2551
   889
bobbens@2551
   890
         break;
bobbens@2551
   891
bobbens@2551
   892
      case SDL_HAPTIC_RAMP:
bobbens@2551
   893
         hap_ramp = &src->ramp;
bobbens@2566
   894
         ramp = SDL_malloc(sizeof(DIRAMPFORCE));
bobbens@2551
   895
         if (ramp == NULL) {
bobbens@2551
   896
            SDL_OutOfMemory();
bobbens@2551
   897
            return -1;
bobbens@2551
   898
         }
bobbens@2566
   899
         SDL_memset(ramp, 0, sizeof(DIRAMPFORCE));
bobbens@2551
   900
bobbens@2551
   901
         /* Specifics */
bobbens@2551
   902
         ramp->lStart = CONVERT(hap_ramp->start);
bobbens@2551
   903
         ramp->lEnd = CONVERT(hap_ramp->end);
bobbens@2566
   904
         dest->cbTypeSpecificParams = sizeof(DIRAMPFORCE);
bobbens@2551
   905
         dest->lpvTypeSpecificParams = ramp;
bobbens@2551
   906
bobbens@2551
   907
         /* Generics */
bobbens@2551
   908
         dest->dwDuration = hap_ramp->length * 1000; /* In microseconds. */
bobbens@2566
   909
         dest->dwTriggerButton = DIGetTriggerButton(hap_ramp->button);
bobbens@2551
   910
         dest->dwTriggerRepeatInterval = hap_ramp->interval;
bobbens@2551
   911
         dest->dwStartDelay = hap_ramp->delay * 1000; /* In microseconds. */
bobbens@2551
   912
bobbens@2551
   913
         /* Direction. */
bobbens@2551
   914
         if (SDL_SYS_SetDirection(dest, &hap_ramp->direction, dest->cAxes) < 0) {
bobbens@2551
   915
            return -1;
bobbens@2551
   916
         }
bobbens@2551
   917
bobbens@2551
   918
         /* Envelope */
bobbens@2566
   919
         if ((hap_ramp->attack_length==0) && (hap_ramp->fade_length==0)) {
bobbens@2566
   920
            SDL_free(dest->lpEnvelope);
bobbens@2566
   921
            dest->lpEnvelope = NULL;
bobbens@2566
   922
         }
bobbens@2566
   923
         else {
bobbens@2566
   924
            envelope->dwAttackLevel = CONVERT(hap_ramp->attack_level);
bobbens@2566
   925
            envelope->dwAttackTime = hap_ramp->attack_length * 1000;
bobbens@2566
   926
            envelope->dwFadeLevel = CONVERT(hap_ramp->fade_level);
bobbens@2566
   927
            envelope->dwFadeTime = hap_ramp->fade_length * 1000;
bobbens@2566
   928
         }
bobbens@2551
   929
bobbens@2551
   930
         break;
bobbens@2551
   931
bobbens@2551
   932
      case SDL_HAPTIC_CUSTOM:
bobbens@2551
   933
         hap_custom = &src->custom;
bobbens@2566
   934
         custom = SDL_malloc(sizeof(DICUSTOMFORCE));
bobbens@2551
   935
         if (custom == NULL) {
bobbens@2551
   936
            SDL_OutOfMemory();
bobbens@2551
   937
            return -1;
bobbens@2551
   938
         }
bobbens@2566
   939
         SDL_memset(custom, 0, sizeof(DICUSTOMFORCE));
bobbens@2551
   940
bobbens@2551
   941
         /* Specifics */
bobbens@2551
   942
         custom->cChannels = hap_custom->channels;
bobbens@2551
   943
         custom->dwSamplePeriod = hap_custom->period * 1000;
bobbens@2551
   944
         custom->cSamples = hap_custom->samples;
bobbens@2551
   945
         custom->rglForceData = SDL_malloc(sizeof(LONG)*custom->cSamples*custom->cChannels);
bobbens@2551
   946
         for (i=0; i<hap_custom->samples*hap_custom->channels; i++) { /* Copy data. */
bobbens@2551
   947
            custom->rglForceData[i] = CONVERT(hap_custom->data[i]);
bobbens@2551
   948
         }
bobbens@2566
   949
         dest->cbTypeSpecificParams = sizeof(DICUSTOMFORCE);
bobbens@2551
   950
         dest->lpvTypeSpecificParams = custom;
bobbens@2551
   951
bobbens@2551
   952
         /* Generics */
bobbens@2551
   953
         dest->dwDuration = hap_custom->length * 1000; /* In microseconds. */
bobbens@2566
   954
         dest->dwTriggerButton = DIGetTriggerButton(hap_custom->button);
bobbens@2551
   955
         dest->dwTriggerRepeatInterval = hap_custom->interval;
bobbens@2551
   956
         dest->dwStartDelay = hap_custom->delay * 1000; /* In microseconds. */
bobbens@2551
   957
bobbens@2551
   958
         /* Direction. */
bobbens@2551
   959
         if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) < 0) {
bobbens@2551
   960
            return -1;
bobbens@2551
   961
         }
bobbens@2551
   962
         
bobbens@2551
   963
         /* Envelope */
bobbens@2566
   964
         if ((hap_custom->attack_length==0) && (hap_custom->fade_length==0)) {
bobbens@2566
   965
            SDL_free(dest->lpEnvelope);
bobbens@2566
   966
            dest->lpEnvelope = NULL;
bobbens@2566
   967
         }
bobbens@2566
   968
         else {
bobbens@2566
   969
            envelope->dwAttackLevel = CONVERT(hap_custom->attack_level);
bobbens@2566
   970
            envelope->dwAttackTime = hap_custom->attack_length * 1000;
bobbens@2566
   971
            envelope->dwFadeLevel = CONVERT(hap_custom->fade_level);
bobbens@2566
   972
            envelope->dwFadeTime = hap_custom->fade_length * 1000;
bobbens@2566
   973
         }
bobbens@2551
   974
bobbens@2551
   975
         break;
bobbens@2551
   976
bobbens@2551
   977
bobbens@2551
   978
      default:
bobbens@2551
   979
         SDL_SetError("Haptic: Unknown effect type.");
bobbens@2551
   980
         return -1;
bobbens@2551
   981
   }
bobbens@2551
   982
bobbens@2551
   983
   return 0;
bobbens@2551
   984
}
bobbens@2551
   985
bobbens@2551
   986
bobbens@2551
   987
/*
bobbens@2566
   988
 * Frees an DIEFFECT allocated by SDL_SYS_ToDIEFFECT.
bobbens@2551
   989
 */
bobbens@2551
   990
static void
bobbens@2566
   991
SDL_SYS_HapticFreeDIEFFECT( DIEFFECT * effect, int type )
bobbens@2551
   992
{
bobbens@2566
   993
   DICUSTOMFORCE *custom;
bobbens@2551
   994
bobbens@2551
   995
   if (effect->lpEnvelope != NULL) {
bobbens@2551
   996
      SDL_free(effect->lpEnvelope);
bobbens@2551
   997
      effect->lpEnvelope = NULL;
bobbens@2551
   998
   }
bobbens@2551
   999
   if (effect->rgdwAxes != NULL) {
bobbens@2551
  1000
      SDL_free(effect->rgdwAxes);
bobbens@2551
  1001
      effect->rgdwAxes = NULL;
bobbens@2551
  1002
   }
bobbens@2551
  1003
   if (effect->lpvTypeSpecificParams != NULL) {
bobbens@2551
  1004
      if (type == SDL_HAPTIC_CUSTOM) { /* Must free the custom data. */
bobbens@2566
  1005
         custom = (DICUSTOMFORCE*) effect->lpvTypeSpecificParams;
bobbens@2551
  1006
         SDL_free(custom->rglForceData);
bobbens@2551
  1007
         custom->rglForceData = NULL;
bobbens@2551
  1008
      }
bobbens@2551
  1009
      SDL_free(effect->lpvTypeSpecificParams);
bobbens@2551
  1010
      effect->lpvTypeSpecificParams = NULL;
bobbens@2551
  1011
   }
bobbens@2551
  1012
   if (effect->rglDirection != NULL) {
bobbens@2551
  1013
      SDL_free(effect->rglDirection);
bobbens@2551
  1014
      effect->rglDirection = NULL;
bobbens@2551
  1015
   }
bobbens@2551
  1016
}
bobbens@2551
  1017
bobbens@2551
  1018
bobbens@2551
  1019
/*
bobbens@2551
  1020
 * Gets the effect type from the generic SDL haptic effect wrapper.
bobbens@2551
  1021
 */
bobbens@2598
  1022
static REFGUID
bobbens@2598
  1023
SDL_SYS_HapticEffectType(SDL_HapticEffect * effect)
bobbens@2551
  1024
{
bobbens@2598
  1025
   switch (effect->type) {
bobbens@2551
  1026
      case SDL_HAPTIC_CONSTANT:
bobbens@2572
  1027
         return &GUID_ConstantForce;
bobbens@2551
  1028
bobbens@2551
  1029
      case SDL_HAPTIC_RAMP:
bobbens@2572
  1030
         return &GUID_RampForce;
bobbens@2551
  1031
bobbens@2551
  1032
      case SDL_HAPTIC_SQUARE:
bobbens@2572
  1033
         return &GUID_Square;
bobbens@2551
  1034
bobbens@2551
  1035
      case SDL_HAPTIC_SINE:
bobbens@2572
  1036
         return &GUID_Sine;
bobbens@2551
  1037
bobbens@2551
  1038
      case SDL_HAPTIC_TRIANGLE:
bobbens@2572
  1039
         return &GUID_Triangle;
bobbens@2551
  1040
bobbens@2551
  1041
      case SDL_HAPTIC_SAWTOOTHUP:
bobbens@2572
  1042
         return &GUID_SawtoothUp;
bobbens@2551
  1043
bobbens@2551
  1044
      case SDL_HAPTIC_SAWTOOTHDOWN:
bobbens@2572
  1045
         return &GUID_SawtoothDown;
bobbens@2551
  1046
bobbens@2551
  1047
      case SDL_HAPTIC_SPRING:
bobbens@2572
  1048
         return &GUID_Spring;
bobbens@2551
  1049
bobbens@2551
  1050
      case SDL_HAPTIC_DAMPER:
bobbens@2572
  1051
         return &GUID_Damper;
bobbens@2551
  1052
bobbens@2551
  1053
      case SDL_HAPTIC_INERTIA:
bobbens@2572
  1054
         return &GUID_Inertia;
bobbens@2551
  1055
bobbens@2551
  1056
      case SDL_HAPTIC_FRICTION:
bobbens@2572
  1057
         return &GUID_Friction;
bobbens@2551
  1058
bobbens@2551
  1059
      case SDL_HAPTIC_CUSTOM:
bobbens@2572
  1060
         return &GUID_CustomForce;
bobbens@2551
  1061
bobbens@2551
  1062
      default:
bobbens@2551
  1063
         SDL_SetError("Haptic: Unknown effect type.");
bobbens@2551
  1064
         return NULL;
bobbens@2551
  1065
   }
bobbens@2551
  1066
}
bobbens@2551
  1067
bobbens@2551
  1068
bobbens@2551
  1069
/*
bobbens@2551
  1070
 * Creates a new haptic effect.
bobbens@2551
  1071
 */
bobbens@2551
  1072
int
bobbens@2551
  1073
SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect * effect,
bobbens@2551
  1074
      SDL_HapticEffect * base)
bobbens@2551
  1075
{
bobbens@2551
  1076
   HRESULT ret;
bobbens@2574
  1077
bobbens@2574
  1078
   /* Get the type. */
bobbens@2598
  1079
   REFGUID type = SDL_SYS_HapticEffectType(base);
bobbens@2574
  1080
   if (type == NULL) {
bobbens@2574
  1081
      goto err_hweffect;
bobbens@2574
  1082
   }
bobbens@2551
  1083
bobbens@2551
  1084
   /* Alloc the effect. */
bobbens@2551
  1085
   effect->hweffect = (struct haptic_hweffect *)
bobbens@2551
  1086
         SDL_malloc(sizeof(struct haptic_hweffect));
bobbens@2551
  1087
   if (effect->hweffect == NULL) {
bobbens@2551
  1088
      SDL_OutOfMemory();
bobbens@2551
  1089
      goto err_hweffect;
bobbens@2551
  1090
   }
bobbens@2551
  1091
bobbens@2551
  1092
   /* Get the effect. */
bobbens@2566
  1093
   if (SDL_SYS_ToDIEFFECT(haptic, &effect->hweffect->effect, base) < 0) {
bobbens@2551
  1094
      goto err_effectdone;
bobbens@2551
  1095
   }
bobbens@2551
  1096
bobbens@2551
  1097
   /* Create the actual effect. */
bobbens@2566
  1098
   ret = IDirectInputDevice2_CreateEffect(haptic->hwdata->device, type,
bobbens@2566
  1099
         &effect->hweffect->effect, &effect->hweffect->ref, NULL);
bobbens@2566
  1100
   if (FAILED(ret)) {
bobbens@2566
  1101
      DI_SetError("Unable to create effect",ret);
bobbens@2551
  1102
      goto err_effectdone;
bobbens@2551
  1103
   }
bobbens@2551
  1104
bobbens@2551
  1105
   return 0;
bobbens@2551
  1106
bobbens@2551
  1107
err_effectdone:
bobbens@2566
  1108
   SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, base->type);
bobbens@2551
  1109
err_hweffect:
bobbens@2551
  1110
   if (effect->hweffect != NULL) {
bobbens@2551
  1111
      SDL_free(effect->hweffect);
bobbens@2551
  1112
      effect->hweffect = NULL;
bobbens@2551
  1113
   }
bobbens@2551
  1114
   return -1;
bobbens@2551
  1115
}
bobbens@2551
  1116
bobbens@2551
  1117
bobbens@2551
  1118
/*
bobbens@2551
  1119
 * Updates an effect.
bobbens@2551
  1120
 */
bobbens@2551
  1121
int
bobbens@2551
  1122
SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
bobbens@2551
  1123
      struct haptic_effect * effect, SDL_HapticEffect * data)
bobbens@2551
  1124
{
bobbens@2551
  1125
   HRESULT ret;
bobbens@2566
  1126
   DWORD flags;
bobbens@2566
  1127
   DIEFFECT temp;
bobbens@2551
  1128
bobbens@2551
  1129
   /* Get the effect. */
bobbens@2566
  1130
   SDL_memset(&temp, 0, sizeof(DIEFFECT));
bobbens@2566
  1131
   if (SDL_SYS_ToDIEFFECT(haptic, &temp, data) < 0) {
bobbens@2551
  1132
      goto err_update;
bobbens@2551
  1133
   }
bobbens@2551
  1134
bobbens@2551
  1135
   /* Set the flags.  Might be worthwhile to diff temp with loaded effect and
bobbens@2551
  1136
    *  only change those parameters. */
bobbens@2566
  1137
   flags = DIEP_DIRECTION | 
bobbens@2566
  1138
           DIEP_DURATION |
bobbens@2566
  1139
           DIEP_ENVELOPE |
bobbens@2566
  1140
           DIEP_STARTDELAY |
bobbens@2566
  1141
           DIEP_TRIGGERBUTTON |
bobbens@2566
  1142
           DIEP_TRIGGERREPEATINTERVAL |
bobbens@2566
  1143
           DIEP_TYPESPECIFICPARAMS;
bobbens@2551
  1144
bobbens@2551
  1145
   /* Create the actual effect. */
bobbens@2574
  1146
   ret = IDirectInputEffect_SetParameters(effect->hweffect->ref, &temp, flags);
bobbens@2573
  1147
   if (FAILED(ret)) {
bobbens@2573
  1148
      DI_SetError("Unable to update effect",ret);
bobbens@2551
  1149
      goto err_update;
bobbens@2551
  1150
   }
bobbens@2551
  1151
bobbens@2551
  1152
   /* Copy it over. */
bobbens@2566
  1153
   SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, data->type);
bobbens@2566
  1154
   SDL_memcpy(&effect->hweffect->effect, &temp, sizeof(DIEFFECT));
bobbens@2551
  1155
bobbens@2551
  1156
   return 0;
bobbens@2551
  1157
bobbens@2551
  1158
err_update:
bobbens@2566
  1159
   SDL_SYS_HapticFreeDIEFFECT(&temp, data->type);
bobbens@2551
  1160
   return -1;
bobbens@2551
  1161
}
bobbens@2551
  1162
bobbens@2551
  1163
bobbens@2551
  1164
/*
bobbens@2551
  1165
 * Runs an effect.
bobbens@2551
  1166
 */
bobbens@2551
  1167
int
bobbens@2551
  1168
SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect * effect,
bobbens@2551
  1169
                        Uint32 iterations)
bobbens@2551
  1170
{
bobbens@2551
  1171
   HRESULT ret;
bobbens@2566
  1172
   DWORD iter;
bobbens@2551
  1173
bobbens@2551
  1174
   /* Check if it's infinite. */
bobbens@2551
  1175
   if (iterations == SDL_HAPTIC_INFINITY) {
bobbens@2566
  1176
      iter = INFINITE;
bobbens@2551
  1177
   }
bobbens@2551
  1178
   else
bobbens@2551
  1179
      iter = iterations;
bobbens@2551
  1180
bobbens@2551
  1181
   /* Run the effect. */
bobbens@2566
  1182
   ret = IDirectInputEffect_Start( effect->hweffect->ref, iter, 0 );
bobbens@2566
  1183
   if (FAILED(ret)) {
bobbens@2566
  1184
      DI_SetError("Running the effect",ret);
bobbens@2551
  1185
      return -1;
bobbens@2551
  1186
   }
bobbens@2551
  1187
bobbens@2551
  1188
   return 0;
bobbens@2551
  1189
}
bobbens@2551
  1190
bobbens@2551
  1191
bobbens@2551
  1192
/*
bobbens@2551
  1193
 * Stops an effect.
bobbens@2551
  1194
 */
bobbens@2551
  1195
int
bobbens@2551
  1196
SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect * effect)
bobbens@2551
  1197
{
bobbens@2551
  1198
   HRESULT ret;
bobbens@2551
  1199
bobbens@2566
  1200
   ret = IDirectInputEffect_Stop(effect->hweffect->ref);
bobbens@2566
  1201
   if (FAILED(ret)) {
bobbens@2566
  1202
      DI_SetError("Unable to stop effect",ret);
bobbens@2551
  1203
      return -1;
bobbens@2551
  1204
   }
bobbens@2551
  1205
bobbens@2551
  1206
   return 0;
bobbens@2551
  1207
}
bobbens@2551
  1208
bobbens@2551
  1209
bobbens@2551
  1210
/*
bobbens@2551
  1211
 * Frees the effect.
bobbens@2551
  1212
 */
bobbens@2551
  1213
void
bobbens@2551
  1214
SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect * effect)
bobbens@2551
  1215
{
bobbens@2551
  1216
   HRESULT ret;
bobbens@2551
  1217
bobbens@2566
  1218
   ret = IDirectInputEffect_Unload(effect->hweffect->ref);
bobbens@2566
  1219
   if (FAILED(ret)) {
bobbens@2566
  1220
      DI_SetError("Removing effect from the device",ret);
bobbens@2551
  1221
   }
bobbens@2566
  1222
   SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, effect->effect.type);   
bobbens@2551
  1223
   SDL_free(effect->hweffect);
bobbens@2551
  1224
   effect->hweffect = NULL;
bobbens@2551
  1225
}
bobbens@2551
  1226
bobbens@2551
  1227
bobbens@2551
  1228
/*
bobbens@2551
  1229
 * Gets the status of a haptic effect.
bobbens@2551
  1230
 */
bobbens@2551
  1231
int
bobbens@2551
  1232
SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect * effect)
bobbens@2551
  1233
{
bobbens@2566
  1234
   SDL_SetError("Haptic: Status not supported.");
bobbens@2566
  1235
   return -1;
bobbens@2551
  1236
}
bobbens@2551
  1237
bobbens@2551
  1238
bobbens@2551
  1239
/*
bobbens@2551
  1240
 * Sets the gain.
bobbens@2551
  1241
 */
bobbens@2551
  1242
int
bobbens@2551
  1243
SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
bobbens@2551
  1244
{
bobbens@2551
  1245
   HRESULT ret;
bobbens@2551
  1246
   DIPROPDWORD dipdw;
bobbens@2551
  1247
bobbens@2551
  1248
   /* Create the weird structure thingy. */
bobbens@2551
  1249
   dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
bobbens@2551
  1250
   dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
bobbens@2551
  1251
   dipdw.diph.dwObj        = 0;
bobbens@2551
  1252
   dipdw.diph.dwHow        = DIPH_DEVICE;
bobbens@2551
  1253
   dipdw.dwData            = gain * 100; /* 0 to 10,000 */
bobbens@2551
  1254
bobbens@2551
  1255
   /* Try to set the autocenter. */
bobbens@2551
  1256
   ret = IDirectInputDevice2_SetProperty( haptic->hwdata->device,
bobbens@2551
  1257
                                          DIPROP_FFGAIN, &dipdw.diph );
bobbens@2551
  1258
   if (FAILED(ret)) {
bobbens@2551
  1259
      DI_SetError("Setting gain",ret);
bobbens@2551
  1260
      return -1;
bobbens@2551
  1261
   }
bobbens@2551
  1262
  
bobbens@2551
  1263
   return 0;
bobbens@2551
  1264
}
bobbens@2551
  1265
bobbens@2551
  1266
bobbens@2551
  1267
/*
bobbens@2551
  1268
 * Sets the autocentering.
bobbens@2551
  1269
 */
bobbens@2551
  1270
int
bobbens@2551
  1271
SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
bobbens@2551
  1272
{
bobbens@2551
  1273
   HRESULT ret;
bobbens@2551
  1274
   DIPROPDWORD dipdw;
bobbens@2551
  1275
bobbens@2551
  1276
   /* Create the weird structure thingy. */
bobbens@2551
  1277
   dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
bobbens@2551
  1278
   dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
bobbens@2551
  1279
   dipdw.diph.dwObj        = 0;
bobbens@2551
  1280
   dipdw.diph.dwHow        = DIPH_DEVICE;
bobbens@2551
  1281
   dipdw.dwData            = (autocenter == 0) ? DIPROPAUTOCENTER_OFF : 
bobbens@2551
  1282
                                                 DIPROPAUTOCENTER_ON;
bobbens@2551
  1283
bobbens@2551
  1284
   /* Try to set the autocenter. */
bobbens@2551
  1285
   ret = IDirectInputDevice2_SetProperty( haptic->hwdata->device,
bobbens@2551
  1286
                                          DIPROP_AUTOCENTER, &dipdw.diph );
bobbens@2551
  1287
   if (FAILED(ret)) {
bobbens@2551
  1288
      DI_SetError("Setting autocenter",ret);
bobbens@2551
  1289
      return -1;
bobbens@2551
  1290
   }
bobbens@2551
  1291
  
bobbens@2551
  1292
   return 0;
bobbens@2551
  1293
bobbens@2551
  1294
}
bobbens@2551
  1295
bobbens@2551
  1296
bobbens@2551
  1297
#endif /* SDL_HAPTIC_DINPUT */