summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-3.2.20/test/testhaptic.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/testhaptic.c')
-rw-r--r--src/contrib/SDL-3.2.20/test/testhaptic.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/test/testhaptic.c b/src/contrib/SDL-3.2.20/test/testhaptic.c
new file mode 100644
index 0000000..a31d278
--- /dev/null
+++ b/src/contrib/SDL-3.2.20/test/testhaptic.c
@@ -0,0 +1,394 @@
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#include <SDL3/SDL.h>
15#include <SDL3/SDL_main.h>
16#include <SDL3/SDL_test.h>
17
18#include <stdlib.h>
19
20static SDL_Haptic *haptic;
21static SDLTest_CommonState *state;
22
23/*
24 * prototypes
25 */
26static void abort_execution(void);
27static void HapticPrintSupported(SDL_Haptic *);
28
29/**
30 * The entry point of this force feedback demo.
31 * \param[in] argc Number of arguments.
32 * \param[in] argv Array of argc arguments.
33 */
34int main(int argc, char **argv)
35{
36 int i;
37 char *name = NULL;
38 int index = -1;
39 SDL_HapticEffect efx[9];
40 int id[9];
41 int nefx;
42 unsigned int supported;
43 SDL_HapticID *haptics;
44 int num_haptics;
45
46 /* Initialize test framework */
47 state = SDLTest_CommonCreateState(argv, 0);
48 if (!state) {
49 return 1;
50 }
51
52 /* Parse commandline */
53 for (i = 1; i < argc;) {
54 int consumed;
55
56 consumed = SDLTest_CommonArg(state, i);
57 if (!consumed) {
58 if (!name && index < 0) {
59 size_t len;
60 name = argv[i];
61 len = SDL_strlen(name);
62 if (len < 3 && SDL_isdigit(name[0]) && (len == 1 || SDL_isdigit(name[1]))) {
63 index = SDL_atoi(name);
64 name = NULL;
65 }
66 consumed = 1;
67 }
68 }
69 if (consumed <= 0) {
70 static const char *options[] = { "[device]", NULL };
71 SDLTest_CommonLogUsage(state, argv[0], options);
72 SDL_Log("%s", "");
73 SDL_Log("If device is a two-digit number it'll use it as an index, otherwise");
74 SDL_Log("it'll use it as if it were part of the device's name.");
75 return 1;
76 }
77
78 i += consumed;
79 }
80
81 /* Initialize the force feedbackness */
82 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC);
83 haptics = SDL_GetHaptics(&num_haptics);
84 SDL_Log("%d Haptic devices detected.", num_haptics);
85 for (i = 0; i < num_haptics; ++i) {
86 SDL_Log(" %s", SDL_GetHapticNameForID(haptics[i]));
87 }
88 if (num_haptics == 0) {
89 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No Haptic devices found!");
90 SDL_free(haptics);
91 return 1;
92 }
93
94 /* We'll just use index or the first force feedback device found */
95 if (!name) {
96 i = (index != -1) ? index : 0;
97
98 if (i >= num_haptics) {
99 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Index out of range, aborting.");
100 SDL_free(haptics);
101 return 1;
102 }
103 }
104 /* Try to find matching device */
105 else {
106 for (i = 0; i < num_haptics; i++) {
107 if (SDL_strstr(SDL_GetHapticNameForID(haptics[i]), name) != NULL) {
108 break;
109 }
110 }
111
112 if (i >= num_haptics) {
113 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to find device matching '%s', aborting.", name);
114 SDL_free(haptics);
115 return 1;
116 }
117 }
118
119 haptic = SDL_OpenHaptic(haptics[i]);
120 if (!haptic) {
121 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create the haptic device: %s", SDL_GetError());
122 SDL_free(haptics);
123 return 1;
124 }
125 SDL_Log("Device: %s", SDL_GetHapticName(haptic));
126 HapticPrintSupported(haptic);
127 SDL_free(haptics);
128
129 /* We only want force feedback errors. */
130 SDL_ClearError();
131
132 /* Create effects. */
133 SDL_memset(efx, 0, sizeof(efx));
134 nefx = 0;
135 supported = SDL_GetHapticFeatures(haptic);
136
137 SDL_Log("%s", "");
138 SDL_Log("Uploading effects");
139 /* First we'll try a SINE effect. */
140 if (supported & SDL_HAPTIC_SINE) {
141 SDL_Log(" effect %d: Sine Wave", nefx);
142 efx[nefx].type = SDL_HAPTIC_SINE;
143 efx[nefx].periodic.period = 1000;
144 efx[nefx].periodic.magnitude = -0x2000; /* Negative magnitude and ... */
145 efx[nefx].periodic.phase = 18000; /* ... 180 degrees phase shift => cancel eachother */
146 efx[nefx].periodic.length = 5000;
147 efx[nefx].periodic.attack_length = 1000;
148 efx[nefx].periodic.fade_length = 1000;
149 id[nefx] = SDL_CreateHapticEffect(haptic, &efx[nefx]);
150 if (id[nefx] < 0) {
151 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s", SDL_GetError());
152 abort_execution();
153 }
154 nefx++;
155 }
156 /* Now we'll try a SAWTOOTHUP */
157 if (supported & SDL_HAPTIC_SAWTOOTHUP) {
158 SDL_Log(" effect %d: Sawtooth Up", nefx);
159 efx[nefx].type = SDL_HAPTIC_SAWTOOTHUP;
160 efx[nefx].periodic.period = 500;
161 efx[nefx].periodic.magnitude = 0x5000;
162 efx[nefx].periodic.length = 5000;
163 efx[nefx].periodic.attack_length = 1000;
164 efx[nefx].periodic.fade_length = 1000;
165 id[nefx] = SDL_CreateHapticEffect(haptic, &efx[nefx]);
166 if (id[nefx] < 0) {
167 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s", SDL_GetError());
168 abort_execution();
169 }
170 nefx++;
171 }
172
173 /* Now the classical constant effect. */
174 if (supported & SDL_HAPTIC_CONSTANT) {
175 SDL_Log(" effect %d: Constant Force", nefx);
176 efx[nefx].type = SDL_HAPTIC_CONSTANT;
177 efx[nefx].constant.direction.type = SDL_HAPTIC_POLAR;
178 efx[nefx].constant.direction.dir[0] = 20000; /* Force comes from the south-west. */
179 efx[nefx].constant.length = 5000;
180 efx[nefx].constant.level = 0x6000;
181 efx[nefx].constant.attack_length = 1000;
182 efx[nefx].constant.fade_length = 1000;
183 id[nefx] = SDL_CreateHapticEffect(haptic, &efx[nefx]);
184 if (id[nefx] < 0) {
185 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s", SDL_GetError());
186 abort_execution();
187 }
188 nefx++;
189 }
190
191 /* The cute spring effect. */
192 if (supported & SDL_HAPTIC_SPRING) {
193 SDL_Log(" effect %d: Condition Spring", nefx);
194 efx[nefx].type = SDL_HAPTIC_SPRING;
195 efx[nefx].condition.length = 5000;
196 for (i = 0; i < SDL_GetNumHapticAxes(haptic); i++) {
197 efx[nefx].condition.right_sat[i] = 0xFFFF;
198 efx[nefx].condition.left_sat[i] = 0xFFFF;
199 efx[nefx].condition.right_coeff[i] = 0x2000;
200 efx[nefx].condition.left_coeff[i] = 0x2000;
201 efx[nefx].condition.center[i] = 0x1000; /* Displace the center for it to move. */
202 }
203 id[nefx] = SDL_CreateHapticEffect(haptic, &efx[nefx]);
204 if (id[nefx] < 0) {
205 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s", SDL_GetError());
206 abort_execution();
207 }
208 nefx++;
209 }
210 /* The interesting damper effect. */
211 if (supported & SDL_HAPTIC_DAMPER) {
212 SDL_Log(" effect %d: Condition Damper", nefx);
213 efx[nefx].type = SDL_HAPTIC_DAMPER;
214 efx[nefx].condition.length = 5000;
215 for (i = 0; i < SDL_GetNumHapticAxes(haptic); i++) {
216 efx[nefx].condition.right_sat[i] = 0xFFFF;
217 efx[nefx].condition.left_sat[i] = 0xFFFF;
218 efx[nefx].condition.right_coeff[i] = 0x2000;
219 efx[nefx].condition.left_coeff[i] = 0x2000;
220 }
221 id[nefx] = SDL_CreateHapticEffect(haptic, &efx[nefx]);
222 if (id[nefx] < 0) {
223 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s", SDL_GetError());
224 abort_execution();
225 }
226 nefx++;
227 }
228 /* The pretty awesome inertia effect. */
229 if (supported & SDL_HAPTIC_INERTIA) {
230 SDL_Log(" effect %d: Condition Inertia", nefx);
231 efx[nefx].type = SDL_HAPTIC_INERTIA;
232 efx[nefx].condition.length = 5000;
233 for (i = 0; i < SDL_GetNumHapticAxes(haptic); i++) {
234 efx[nefx].condition.right_sat[i] = 0xFFFF;
235 efx[nefx].condition.left_sat[i] = 0xFFFF;
236 efx[nefx].condition.right_coeff[i] = 0x2000;
237 efx[nefx].condition.left_coeff[i] = 0x2000;
238 efx[nefx].condition.deadband[i] = 0x1000; /* 1/16th of axis-range around the center is 'dead'. */
239 }
240 id[nefx] = SDL_CreateHapticEffect(haptic, &efx[nefx]);
241 if (id[nefx] < 0) {
242 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s", SDL_GetError());
243 abort_execution();
244 }
245 nefx++;
246 }
247 /* The hot friction effect. */
248 if (supported & SDL_HAPTIC_FRICTION) {
249 SDL_Log(" effect %d: Condition Friction", nefx);
250 efx[nefx].type = SDL_HAPTIC_FRICTION;
251 efx[nefx].condition.length = 5000;
252 for (i = 0; i < SDL_GetNumHapticAxes(haptic); i++) {
253 efx[nefx].condition.right_sat[i] = 0xFFFF;
254 efx[nefx].condition.left_sat[i] = 0xFFFF;
255 efx[nefx].condition.right_coeff[i] = 0x2000;
256 efx[nefx].condition.left_coeff[i] = 0x2000;
257 }
258 id[nefx] = SDL_CreateHapticEffect(haptic, &efx[nefx]);
259 if (id[nefx] < 0) {
260 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s", SDL_GetError());
261 abort_execution();
262 }
263 nefx++;
264 }
265
266 /* Now we'll try a ramp effect */
267 if (supported & SDL_HAPTIC_RAMP) {
268 SDL_Log(" effect %d: Ramp", nefx);
269 efx[nefx].type = SDL_HAPTIC_RAMP;
270 efx[nefx].ramp.direction.type = SDL_HAPTIC_CARTESIAN;
271 efx[nefx].ramp.direction.dir[0] = 1; /* Force comes from */
272 efx[nefx].ramp.direction.dir[1] = -1; /* the north-east. */
273 efx[nefx].ramp.length = 5000;
274 efx[nefx].ramp.start = 0x4000;
275 efx[nefx].ramp.end = -0x4000;
276 efx[nefx].ramp.attack_length = 1000;
277 efx[nefx].ramp.fade_length = 1000;
278 id[nefx] = SDL_CreateHapticEffect(haptic, &efx[nefx]);
279 if (id[nefx] < 0) {
280 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s", SDL_GetError());
281 abort_execution();
282 }
283 nefx++;
284 }
285
286 /* Finally we'll try a left/right effect. */
287 if (supported & SDL_HAPTIC_LEFTRIGHT) {
288 SDL_Log(" effect %d: Left/Right", nefx);
289 efx[nefx].type = SDL_HAPTIC_LEFTRIGHT;
290 efx[nefx].leftright.length = 5000;
291 efx[nefx].leftright.large_magnitude = 0x3000;
292 efx[nefx].leftright.small_magnitude = 0xFFFF;
293 id[nefx] = SDL_CreateHapticEffect(haptic, &efx[nefx]);
294 if (id[nefx] < 0) {
295 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s", SDL_GetError());
296 abort_execution();
297 }
298 nefx++;
299 }
300
301 SDL_Log("%s", "");
302 SDL_Log("Now playing effects for 5 seconds each with 1 second delay between");
303 for (i = 0; i < nefx; i++) {
304 SDL_Log(" Playing effect %d", i);
305 SDL_RunHapticEffect(haptic, id[i], 1);
306 SDL_Delay(6000); /* Effects only have length 5000 */
307 }
308
309 /* Quit */
310 if (haptic) {
311 SDL_CloseHaptic(haptic);
312 }
313 SDL_Quit();
314 SDLTest_CommonDestroyState(state);
315
316 return 0;
317}
318
319/**
320 * Cleans up a bit.
321 */
322static void
323abort_execution(void)
324{
325 SDL_Log("%s", "");
326 SDL_Log("Aborting program execution.");
327
328 SDL_CloseHaptic(haptic);
329 SDL_Quit();
330 SDLTest_CommonDestroyState(state);
331
332 exit(1);
333}
334
335/**
336 * Displays information about the haptic device.
337 */
338static void
339HapticPrintSupported(SDL_Haptic *ptr)
340{
341 unsigned int supported;
342
343 supported = SDL_GetHapticFeatures(ptr);
344 SDL_Log(" Supported effects [%d effects, %d playing]:",
345 SDL_GetMaxHapticEffects(ptr), SDL_GetMaxHapticEffectsPlaying(ptr));
346 if (supported & SDL_HAPTIC_CONSTANT) {
347 SDL_Log(" constant");
348 }
349 if (supported & SDL_HAPTIC_SINE) {
350 SDL_Log(" sine");
351 }
352 if (supported & SDL_HAPTIC_SQUARE)
353 SDL_Log(" square");
354 if (supported & SDL_HAPTIC_TRIANGLE) {
355 SDL_Log(" triangle");
356 }
357 if (supported & SDL_HAPTIC_SAWTOOTHUP) {
358 SDL_Log(" sawtoothup");
359 }
360 if (supported & SDL_HAPTIC_SAWTOOTHDOWN) {
361 SDL_Log(" sawtoothdown");
362 }
363 if (supported & SDL_HAPTIC_RAMP) {
364 SDL_Log(" ramp");
365 }
366 if (supported & SDL_HAPTIC_FRICTION) {
367 SDL_Log(" friction");
368 }
369 if (supported & SDL_HAPTIC_SPRING) {
370 SDL_Log(" spring");
371 }
372 if (supported & SDL_HAPTIC_DAMPER) {
373 SDL_Log(" damper");
374 }
375 if (supported & SDL_HAPTIC_INERTIA) {
376 SDL_Log(" inertia");
377 }
378 if (supported & SDL_HAPTIC_CUSTOM) {
379 SDL_Log(" custom");
380 }
381 if (supported & SDL_HAPTIC_LEFTRIGHT) {
382 SDL_Log(" left/right");
383 }
384 SDL_Log(" Supported capabilities:");
385 if (supported & SDL_HAPTIC_GAIN) {
386 SDL_Log(" gain");
387 }
388 if (supported & SDL_HAPTIC_AUTOCENTER) {
389 SDL_Log(" autocenter");
390 }
391 if (supported & SDL_HAPTIC_STATUS) {
392 SDL_Log(" status");
393 }
394}