SDL  2.0
testhaptic.c File Reference
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "SDL.h"
+ Include dependency graph for testhaptic.c:

Go to the source code of this file.

Functions

static void abort_execution (void)
 
static void HapticPrintSupported (SDL_Haptic *haptic)
 
int main (int argc, char **argv)
 The entry point of this force feedback demo. More...
 

Variables

static SDL_Haptic * haptic
 

Function Documentation

◆ abort_execution()

static void abort_execution ( void  )
static

Definition at line 302 of file testhaptic.c.

References haptic, SDL_HapticClose, SDL_Log, and SDL_Quit.

Referenced by main().

303 {
304  SDL_Log("\nAborting program execution.\n");
305 
307  SDL_Quit();
308 
309  exit(1);
310 }
#define SDL_HapticClose
#define SDL_Log
#define SDL_Quit
static SDL_Haptic * haptic
Definition: testhaptic.c:25

◆ HapticPrintSupported()

static void HapticPrintSupported ( SDL_Haptic *  haptic)
static

Definition at line 317 of file testhaptic.c.

References main(), SDL_HAPTIC_AUTOCENTER, SDL_HAPTIC_CONSTANT, SDL_HAPTIC_CUSTOM, SDL_HAPTIC_DAMPER, SDL_HAPTIC_FRICTION, SDL_HAPTIC_GAIN, SDL_HAPTIC_INERTIA, SDL_HAPTIC_LEFTRIGHT, SDL_HAPTIC_RAMP, SDL_HAPTIC_SAWTOOTHDOWN, SDL_HAPTIC_SAWTOOTHUP, SDL_HAPTIC_SINE, SDL_HAPTIC_SPRING, SDL_HAPTIC_STATUS, SDL_HAPTIC_TRIANGLE, SDL_HapticNumEffects, SDL_HapticNumEffectsPlaying, SDL_HapticQuery, SDL_Log, SDL_LOG_CATEGORY_APPLICATION, and SDL_LogError.

Referenced by main().

318 {
319  unsigned int supported;
320 
321  supported = SDL_HapticQuery(haptic);
322  SDL_Log(" Supported effects [%d effects, %d playing]:\n",
324  if (supported & SDL_HAPTIC_CONSTANT)
325  SDL_Log(" constant\n");
326  if (supported & SDL_HAPTIC_SINE)
327  SDL_Log(" sine\n");
328  /* !!! FIXME: put this back when we have more bits in 2.1 */
329  /* if (supported & SDL_HAPTIC_SQUARE)
330  SDL_Log(" square\n"); */
331  if (supported & SDL_HAPTIC_TRIANGLE)
332  SDL_Log(" triangle\n");
333  if (supported & SDL_HAPTIC_SAWTOOTHUP)
334  SDL_Log(" sawtoothup\n");
335  if (supported & SDL_HAPTIC_SAWTOOTHDOWN)
336  SDL_Log(" sawtoothdown\n");
337  if (supported & SDL_HAPTIC_RAMP)
338  SDL_Log(" ramp\n");
339  if (supported & SDL_HAPTIC_FRICTION)
340  SDL_Log(" friction\n");
341  if (supported & SDL_HAPTIC_SPRING)
342  SDL_Log(" spring\n");
343  if (supported & SDL_HAPTIC_DAMPER)
344  SDL_Log(" damper\n");
345  if (supported & SDL_HAPTIC_INERTIA)
346  SDL_Log(" inertia\n");
347  if (supported & SDL_HAPTIC_CUSTOM)
348  SDL_Log(" custom\n");
349  if (supported & SDL_HAPTIC_LEFTRIGHT)
350  SDL_Log(" left/right\n");
351  SDL_Log(" Supported capabilities:\n");
352  if (supported & SDL_HAPTIC_GAIN)
353  SDL_Log(" gain\n");
354  if (supported & SDL_HAPTIC_AUTOCENTER)
355  SDL_Log(" autocenter\n");
356  if (supported & SDL_HAPTIC_STATUS)
357  SDL_Log(" status\n");
358 }
#define SDL_HAPTIC_AUTOCENTER
Device can set autocenter.
Definition: SDL_haptic.h:280
#define SDL_HAPTIC_GAIN
Device can set global gain.
Definition: SDL_haptic.h:271
#define SDL_HAPTIC_CUSTOM
Custom effect is supported.
Definition: SDL_haptic.h:258
#define SDL_HAPTIC_TRIANGLE
Triangle wave effect supported.
Definition: SDL_haptic.h:184
#define SDL_HAPTIC_INERTIA
Inertia effect supported - uses axes acceleration.
Definition: SDL_haptic.h:241
#define SDL_HAPTIC_SINE
Sine wave effect supported.
Definition: SDL_haptic.h:161
#define SDL_Log
#define SDL_HAPTIC_CONSTANT
Constant effect supported.
Definition: SDL_haptic.h:152
static SDL_Haptic * haptic
Definition: testhaptic.c:25
#define SDL_HAPTIC_STATUS
Device can be queried for effect status.
Definition: SDL_haptic.h:289
#define SDL_HapticNumEffectsPlaying
#define SDL_HAPTIC_RAMP
Ramp effect supported.
Definition: SDL_haptic.h:211
#define SDL_HAPTIC_SPRING
Spring effect supported - uses axes position.
Definition: SDL_haptic.h:221
#define SDL_HAPTIC_SAWTOOTHUP
Sawtoothup wave effect supported.
Definition: SDL_haptic.h:193
#define SDL_HapticNumEffects
#define SDL_HAPTIC_LEFTRIGHT
Left/Right effect supported.
Definition: SDL_haptic.h:172
#define SDL_HAPTIC_FRICTION
Friction effect supported - uses axes movement.
Definition: SDL_haptic.h:251
#define SDL_HAPTIC_SAWTOOTHDOWN
Sawtoothdown wave effect supported.
Definition: SDL_haptic.h:202
#define SDL_HapticQuery
#define SDL_HAPTIC_DAMPER
Damper effect supported - uses axes velocity.
Definition: SDL_haptic.h:231

◆ main()

int main ( int  argc,
char **  argv 
)

The entry point of this force feedback demo.

Parameters
[in]argcNumber of arguments.
[in]argvArray of argc arguments.

Definition at line 41 of file testhaptic.c.

References abort_execution(), SDL_HapticConstant::attack_length, SDL_HapticPeriodic::attack_length, SDL_HapticRamp::attack_length, SDL_HapticCondition::center, SDL_HapticEffect::condition, SDL_HapticEffect::constant, SDL_HapticCondition::deadband, SDL_HapticDirection::dir, SDL_HapticConstant::direction, SDL_HapticRamp::direction, SDL_HapticRamp::end, SDL_HapticConstant::fade_length, SDL_HapticPeriodic::fade_length, SDL_HapticRamp::fade_length, haptic, HapticPrintSupported(), i, SDL_HapticLeftRight::large_magnitude, SDL_HapticCondition::left_coeff, SDL_HapticCondition::left_sat, SDL_HapticEffect::leftright, SDL_HapticConstant::length, SDL_HapticPeriodic::length, SDL_HapticCondition::length, SDL_HapticRamp::length, SDL_HapticLeftRight::length, SDL_HapticConstant::level, SDL_HapticPeriodic::magnitude, memset, NULL, SDL_HapticPeriodic::period, SDL_HapticEffect::periodic, SDL_HapticPeriodic::phase, SDL_HapticEffect::ramp, SDL_HapticCondition::right_coeff, SDL_HapticCondition::right_sat, SDL_ClearError, SDL_Delay, SDL_GetError, SDL_HAPTIC_CARTESIAN, SDL_HAPTIC_CONSTANT, SDL_HAPTIC_DAMPER, SDL_HAPTIC_FRICTION, SDL_HAPTIC_INERTIA, SDL_HAPTIC_LEFTRIGHT, SDL_HAPTIC_POLAR, SDL_HAPTIC_RAMP, SDL_HAPTIC_SAWTOOTHUP, SDL_HAPTIC_SINE, SDL_HAPTIC_SPRING, SDL_HapticClose, SDL_HapticName, SDL_HapticNewEffect, SDL_HapticNumAxes, SDL_HapticOpen, SDL_HapticQuery, SDL_HapticRunEffect, SDL_Init, SDL_INIT_HAPTIC, SDL_INIT_JOYSTICK, SDL_INIT_TIMER, SDL_INIT_VIDEO, SDL_Log, SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, SDL_LogError, SDL_LogSetPriority, SDL_NumHaptics, SDL_Quit, SDL_HapticLeftRight::small_magnitude, SDL_HapticRamp::start, SDL_HapticDirection::type, and SDL_HapticEffect::type.

Referenced by HapticPrintSupported().

42 {
43  int i;
44  char *name;
45  int index;
46  SDL_HapticEffect efx[9];
47  int id[9];
48  int nefx;
49  unsigned int supported;
50 
51  /* Enable standard application logging */
53 
54  name = NULL;
55  index = -1;
56  if (argc > 1) {
57  name = argv[1];
58  if ((strcmp(name, "--help") == 0) || (strcmp(name, "-h") == 0)) {
59  SDL_Log("USAGE: %s [device]\n"
60  "If device is a two-digit number it'll use it as an index, otherwise\n"
61  "it'll use it as if it were part of the device's name.\n",
62  argv[0]);
63  return 0;
64  }
65 
66  i = strlen(name);
67  if ((i < 3) && isdigit(name[0]) && ((i == 1) || isdigit(name[1]))) {
68  index = atoi(name);
69  name = NULL;
70  }
71  }
72 
73  /* Initialize the force feedbackness */
76  SDL_Log("%d Haptic devices detected.\n", SDL_NumHaptics());
77  if (SDL_NumHaptics() > 0) {
78  /* We'll just use index or the first force feedback device found */
79  if (name == NULL) {
80  i = (index != -1) ? index : 0;
81  }
82  /* Try to find matching device */
83  else {
84  for (i = 0; i < SDL_NumHaptics(); i++) {
85  if (strstr(SDL_HapticName(i), name) != NULL)
86  break;
87  }
88 
89  if (i >= SDL_NumHaptics()) {
90  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to find device matching '%s', aborting.\n",
91  name);
92  return 1;
93  }
94  }
95 
97  if (haptic == NULL) {
98  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create the haptic device: %s\n",
99  SDL_GetError());
100  return 1;
101  }
102  SDL_Log("Device: %s\n", SDL_HapticName(i));
104  } else {
105  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No Haptic devices found!\n");
106  return 1;
107  }
108 
109  /* We only want force feedback errors. */
110  SDL_ClearError();
111 
112  /* Create effects. */
113  memset(&efx, 0, sizeof(efx));
114  nefx = 0;
115  supported = SDL_HapticQuery(haptic);
116 
117  SDL_Log("\nUploading effects\n");
118  /* First we'll try a SINE effect. */
119  if (supported & SDL_HAPTIC_SINE) {
120  SDL_Log(" effect %d: Sine Wave\n", nefx);
121  efx[nefx].type = SDL_HAPTIC_SINE;
122  efx[nefx].periodic.period = 1000;
123  efx[nefx].periodic.magnitude = -0x2000; /* Negative magnitude and ... */
124  efx[nefx].periodic.phase = 18000; /* ... 180 degrees phase shift => cancel eachother */
125  efx[nefx].periodic.length = 5000;
126  efx[nefx].periodic.attack_length = 1000;
127  efx[nefx].periodic.fade_length = 1000;
128  id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
129  if (id[nefx] < 0) {
130  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
131  abort_execution();
132  }
133  nefx++;
134  }
135  /* Now we'll try a SAWTOOTHUP */
136  if (supported & SDL_HAPTIC_SAWTOOTHUP) {
137  SDL_Log(" effect %d: Sawtooth Up\n", nefx);
138  efx[nefx].type = SDL_HAPTIC_SAWTOOTHUP;
139  efx[nefx].periodic.period = 500;
140  efx[nefx].periodic.magnitude = 0x5000;
141  efx[nefx].periodic.length = 5000;
142  efx[nefx].periodic.attack_length = 1000;
143  efx[nefx].periodic.fade_length = 1000;
144  id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
145  if (id[nefx] < 0) {
146  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
147  abort_execution();
148  }
149  nefx++;
150  }
151 
152  /* Now the classical constant effect. */
153  if (supported & SDL_HAPTIC_CONSTANT) {
154  SDL_Log(" effect %d: Constant Force\n", nefx);
155  efx[nefx].type = SDL_HAPTIC_CONSTANT;
157  efx[nefx].constant.direction.dir[0] = 20000; /* Force comes from the south-west. */
158  efx[nefx].constant.length = 5000;
159  efx[nefx].constant.level = 0x6000;
160  efx[nefx].constant.attack_length = 1000;
161  efx[nefx].constant.fade_length = 1000;
162  id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
163  if (id[nefx] < 0) {
164  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
165  abort_execution();
166  }
167  nefx++;
168  }
169 
170  /* The cute spring effect. */
171  if (supported & SDL_HAPTIC_SPRING) {
172  SDL_Log(" effect %d: Condition Spring\n", nefx);
173  efx[nefx].type = SDL_HAPTIC_SPRING;
174  efx[nefx].condition.length = 5000;
175  for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
176  efx[nefx].condition.right_sat[i] = 0xFFFF;
177  efx[nefx].condition.left_sat[i] = 0xFFFF;
178  efx[nefx].condition.right_coeff[i] = 0x2000;
179  efx[nefx].condition.left_coeff[i] = 0x2000;
180  efx[nefx].condition.center[i] = 0x1000; /* Displace the center for it to move. */
181  }
182  id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
183  if (id[nefx] < 0) {
184  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
185  abort_execution();
186  }
187  nefx++;
188  }
189  /* The interesting damper effect. */
190  if (supported & SDL_HAPTIC_DAMPER) {
191  SDL_Log(" effect %d: Condition Damper\n", nefx);
192  efx[nefx].type = SDL_HAPTIC_DAMPER;
193  efx[nefx].condition.length = 5000;
194  for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
195  efx[nefx].condition.right_sat[i] = 0xFFFF;
196  efx[nefx].condition.left_sat[i] = 0xFFFF;
197  efx[nefx].condition.right_coeff[i] = 0x2000;
198  efx[nefx].condition.left_coeff[i] = 0x2000;
199  }
200  id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
201  if (id[nefx] < 0) {
202  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
203  abort_execution();
204  }
205  nefx++;
206  }
207  /* The pretty awesome inertia effect. */
208  if (supported & SDL_HAPTIC_INERTIA) {
209  SDL_Log(" effect %d: Condition Inertia\n", nefx);
210  efx[nefx].type = SDL_HAPTIC_INERTIA;
211  efx[nefx].condition.length = 5000;
212  for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
213  efx[nefx].condition.right_sat[i] = 0xFFFF;
214  efx[nefx].condition.left_sat[i] = 0xFFFF;
215  efx[nefx].condition.right_coeff[i] = 0x2000;
216  efx[nefx].condition.left_coeff[i] = 0x2000;
217  efx[nefx].condition.deadband[i] = 0x1000; /* 1/16th of axis-range around the center is 'dead'. */
218  }
219  id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
220  if (id[nefx] < 0) {
221  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
222  abort_execution();
223  }
224  nefx++;
225  }
226  /* The hot friction effect. */
227  if (supported & SDL_HAPTIC_FRICTION) {
228  SDL_Log(" effect %d: Condition Friction\n", nefx);
229  efx[nefx].type = SDL_HAPTIC_FRICTION;
230  efx[nefx].condition.length = 5000;
231  for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
232  efx[nefx].condition.right_sat[i] = 0xFFFF;
233  efx[nefx].condition.left_sat[i] = 0xFFFF;
234  efx[nefx].condition.right_coeff[i] = 0x2000;
235  efx[nefx].condition.left_coeff[i] = 0x2000;
236  }
237  id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
238  if (id[nefx] < 0) {
239  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
240  abort_execution();
241  }
242  nefx++;
243  }
244 
245  /* Now we'll try a ramp effect */
246  if (supported & SDL_HAPTIC_RAMP) {
247  SDL_Log(" effect %d: Ramp\n", nefx);
248  efx[nefx].type = SDL_HAPTIC_RAMP;
250  efx[nefx].ramp.direction.dir[0] = 1; /* Force comes from */
251  efx[nefx].ramp.direction.dir[1] = -1; /* the north-east. */
252  efx[nefx].ramp.length = 5000;
253  efx[nefx].ramp.start = 0x4000;
254  efx[nefx].ramp.end = -0x4000;
255  efx[nefx].ramp.attack_length = 1000;
256  efx[nefx].ramp.fade_length = 1000;
257  id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
258  if (id[nefx] < 0) {
259  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
260  abort_execution();
261  }
262  nefx++;
263  }
264 
265  /* Finally we'll try a left/right effect. */
266  if (supported & SDL_HAPTIC_LEFTRIGHT) {
267  SDL_Log(" effect %d: Left/Right\n", nefx);
268  efx[nefx].type = SDL_HAPTIC_LEFTRIGHT;
269  efx[nefx].leftright.length = 5000;
270  efx[nefx].leftright.large_magnitude = 0x3000;
271  efx[nefx].leftright.small_magnitude = 0xFFFF;
272  id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
273  if (id[nefx] < 0) {
274  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
275  abort_execution();
276  }
277  nefx++;
278  }
279 
280 
281  SDL_Log
282  ("\nNow playing effects for 5 seconds each with 1 second delay between\n");
283  for (i = 0; i < nefx; i++) {
284  SDL_Log(" Playing effect %d\n", i);
285  SDL_HapticRunEffect(haptic, id[i], 1);
286  SDL_Delay(6000); /* Effects only have length 5000 */
287  }
288 
289  /* Quit */
290  if (haptic != NULL)
292  SDL_Quit();
293 
294  return 0;
295 }
Uint16 deadband[3]
Definition: SDL_haptic.h:611
#define SDL_ClearError
#define SDL_GetError
#define SDL_HapticNewEffect
#define SDL_INIT_JOYSTICK
Definition: SDL.h:79
static void HapticPrintSupported(SDL_Haptic *haptic)
Definition: testhaptic.c:317
#define SDL_HAPTIC_INERTIA
Inertia effect supported - uses axes acceleration.
Definition: SDL_haptic.h:241
SDL_HapticRamp ramp
Definition: SDL_haptic.h:796
#define SDL_HapticOpen
#define memset
Definition: SDL_malloc.c:619
Sint16 left_coeff[3]
Definition: SDL_haptic.h:610
Uint16 right_sat[3]
Definition: SDL_haptic.h:607
Sint16 right_coeff[3]
Definition: SDL_haptic.h:609
#define SDL_HAPTIC_SINE
Sine wave effect supported.
Definition: SDL_haptic.h:161
#define SDL_HapticClose
#define SDL_HapticRunEffect
GLuint const GLchar * name
#define SDL_LogError
#define SDL_HAPTIC_CARTESIAN
Uses cartesian coordinates for the direction.
Definition: SDL_haptic.h:319
SDL_HapticCondition condition
Definition: SDL_haptic.h:795
#define SDL_Log
The generic template for any haptic effect.
Definition: SDL_haptic.h:789
#define SDL_HAPTIC_CONSTANT
Constant effect supported.
Definition: SDL_haptic.h:152
#define SDL_HapticName
#define SDL_Quit
#define SDL_HAPTIC_POLAR
Uses polar coordinates for the direction.
Definition: SDL_haptic.h:312
SDL_HapticConstant constant
Definition: SDL_haptic.h:793
static void abort_execution(void)
Definition: testhaptic.c:302
SDL_HapticDirection direction
Definition: SDL_haptic.h:632
#define SDL_HapticNumAxes
GLuint index
#define SDL_Delay
Uint16 attack_length
Definition: SDL_haptic.h:647
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define SDL_LogSetPriority
Uint16 fade_length
Definition: SDL_haptic.h:649
#define NULL
Definition: begin_code.h:164
static SDL_Haptic * haptic
Definition: testhaptic.c:25
#define SDL_INIT_TIMER
Definition: SDL.h:76
SDL_HapticLeftRight leftright
Definition: SDL_haptic.h:797
#define SDL_HAPTIC_RAMP
Ramp effect supported.
Definition: SDL_haptic.h:211
#define SDL_HAPTIC_SPRING
Spring effect supported - uses axes position.
Definition: SDL_haptic.h:221
#define SDL_NumHaptics
#define SDL_Init
#define SDL_HAPTIC_SAWTOOTHUP
Sawtoothup wave effect supported.
Definition: SDL_haptic.h:193
#define SDL_INIT_HAPTIC
Definition: SDL.h:80
#define SDL_HAPTIC_LEFTRIGHT
Left/Right effect supported.
Definition: SDL_haptic.h:172
SDL_HapticPeriodic periodic
Definition: SDL_haptic.h:794
#define SDL_HAPTIC_FRICTION
Friction effect supported - uses axes movement.
Definition: SDL_haptic.h:251
#define SDL_HapticQuery
#define SDL_INIT_VIDEO
Definition: SDL.h:78
SDL_HapticDirection direction
Definition: SDL_haptic.h:461
#define SDL_HAPTIC_DAMPER
Damper effect supported - uses axes velocity.
Definition: SDL_haptic.h:231
Uint16 left_sat[3]
Definition: SDL_haptic.h:608

Variable Documentation

◆ haptic

SDL_Haptic* haptic
static

Definition at line 25 of file testhaptic.c.

Referenced by abort_execution(), main(), SDL_HapticOpen(), and SDL_HapticOpenFromJoystick().