SDL 2.0
testhaptic.c
Go to the documentation of this file.
1/*
2Copyright (c) 2008, Edgar Simo Serra
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of the Simple Directmedia Layer (SDL) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
11THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12*/
13
14/*
15 * includes
16 */
17#include <stdlib.h>
18#include <string.h> /* strstr */
19#include <ctype.h> /* isdigit */
20
21#include "SDL.h"
22
23#ifndef SDL_HAPTIC_DISABLED
24
25static SDL_Haptic *haptic;
26
27
28/*
29 * prototypes
30 */
31static void abort_execution(void);
32static void HapticPrintSupported(SDL_Haptic * haptic);
33
34
35/**
36 * @brief The entry point of this force feedback demo.
37 * @param[in] argc Number of arguments.
38 * @param[in] argv Array of argc arguments.
39 */
40int
41main(int argc, char **argv)
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. */
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());
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());
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());
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());
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());
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());
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());
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());
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());
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);
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}
296
297
298/*
299 * Cleans up a bit.
300 */
301static void
303{
304 SDL_Log("\nAborting program execution.\n");
305
307 SDL_Quit();
308
309 exit(1);
310}
311
312
313/*
314 * Displays information about the haptic device.
315 */
316static void
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}
359
360#else
361
362int
363main(int argc, char *argv[])
364{
365 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Haptic support.\n");
366 exit(1);
367}
368
369#endif
#define SDL_INIT_TIMER
Definition: SDL.h:77
#define SDL_INIT_JOYSTICK
Definition: SDL.h:80
#define SDL_INIT_HAPTIC
Definition: SDL.h:81
#define SDL_INIT_VIDEO
Definition: SDL.h:79
#define SDL_GetError
#define SDL_HapticNewEffect
#define SDL_HapticNumEffectsPlaying
#define SDL_LogSetPriority
#define SDL_ClearError
#define SDL_LogError
#define SDL_HapticName
#define SDL_HapticClose
#define SDL_Delay
#define SDL_Quit
#define SDL_HapticQuery
#define SDL_HapticNumEffects
#define SDL_Init
#define SDL_HapticRunEffect
#define SDL_Log
#define SDL_HapticOpen
#define SDL_NumHaptics
#define SDL_HapticNumAxes
#define SDL_HAPTIC_INERTIA
Inertia effect supported - uses axes acceleration.
Definition: SDL_haptic.h:252
#define SDL_HAPTIC_AUTOCENTER
Device can set autocenter.
Definition: SDL_haptic.h:291
#define SDL_HAPTIC_GAIN
Device can set global gain.
Definition: SDL_haptic.h:282
#define SDL_HAPTIC_SPRING
Spring effect supported - uses axes position.
Definition: SDL_haptic.h:232
#define SDL_HAPTIC_DAMPER
Damper effect supported - uses axes velocity.
Definition: SDL_haptic.h:242
#define SDL_HAPTIC_CUSTOM
Custom effect is supported.
Definition: SDL_haptic.h:269
#define SDL_HAPTIC_CONSTANT
Constant effect supported.
Definition: SDL_haptic.h:163
#define SDL_HAPTIC_FRICTION
Friction effect supported - uses axes movement.
Definition: SDL_haptic.h:262
#define SDL_HAPTIC_SINE
Sine wave effect supported.
Definition: SDL_haptic.h:172
#define SDL_HAPTIC_SAWTOOTHUP
Sawtoothup wave effect supported.
Definition: SDL_haptic.h:204
#define SDL_HAPTIC_STATUS
Device can be queried for effect status.
Definition: SDL_haptic.h:300
#define SDL_HAPTIC_POLAR
Uses polar coordinates for the direction.
Definition: SDL_haptic.h:323
#define SDL_HAPTIC_LEFTRIGHT
Left/Right effect supported.
Definition: SDL_haptic.h:183
#define SDL_HAPTIC_TRIANGLE
Triangle wave effect supported.
Definition: SDL_haptic.h:195
#define SDL_HAPTIC_RAMP
Ramp effect supported.
Definition: SDL_haptic.h:222
#define SDL_HAPTIC_CARTESIAN
Uses cartesian coordinates for the direction.
Definition: SDL_haptic.h:330
#define SDL_HAPTIC_SAWTOOTHDOWN
Sawtoothdown wave effect supported.
Definition: SDL_haptic.h:213
@ SDL_LOG_PRIORITY_INFO
Definition: SDL_log.h:106
@ SDL_LOG_CATEGORY_APPLICATION
Definition: SDL_log.h:66
#define memset
Definition: SDL_malloc.c:627
GLuint index
GLuint const GLchar * name
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 NULL
Definition: begin_code.h:167
Sint16 left_coeff[3]
Definition: SDL_haptic.h:621
Sint16 right_coeff[3]
Definition: SDL_haptic.h:620
Uint16 right_sat[3]
Definition: SDL_haptic.h:618
Uint16 left_sat[3]
Definition: SDL_haptic.h:619
Uint16 deadband[3]
Definition: SDL_haptic.h:622
SDL_HapticDirection direction
Definition: SDL_haptic.h:472
SDL_HapticDirection direction
Definition: SDL_haptic.h:643
Uint16 fade_length
Definition: SDL_haptic.h:660
Uint16 attack_length
Definition: SDL_haptic.h:658
int main(int argc, char **argv)
The entry point of this force feedback demo.
Definition: testhaptic.c:41
static void abort_execution(void)
Definition: testhaptic.c:302
static void HapticPrintSupported(SDL_Haptic *haptic)
Definition: testhaptic.c:317
static SDL_Haptic * haptic
Definition: testhaptic.c:25
The generic template for any haptic effect.
Definition: SDL_haptic.h:801
SDL_HapticRamp ramp
Definition: SDL_haptic.h:807
SDL_HapticLeftRight leftright
Definition: SDL_haptic.h:808
SDL_HapticPeriodic periodic
Definition: SDL_haptic.h:805
SDL_HapticCondition condition
Definition: SDL_haptic.h:806
SDL_HapticConstant constant
Definition: SDL_haptic.h:804