/
testhaptic.c
322 lines (284 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/*
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely.
*/
/*
Copyright (c) 2008, Edgar Simo Serra
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* 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.
* 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.
THIS 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.
*/
/*
* includes
*/
#include <stdlib.h>
#include <string.h> /* strstr */
#include <ctype.h> /* isdigit */
#include "SDL.h"
#ifndef SDL_HAPTIC_DISABLED
#include "SDL_haptic.h"
static SDL_Haptic *haptic;
/*
* prototypes
*/
static void abort_execution(void);
static void HapticPrintSupported(SDL_Haptic * haptic);
/**
* @brief The entry point of this force feedback demo.
* @param[in] argc Number of arguments.
* @param[in] argv Array of argc arguments.
*/
int
main(int argc, char **argv)
{
int i;
char *name;
int index;
SDL_HapticEffect efx[5];
int id[5];
int nefx;
unsigned int supported;
64
65
66
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
67
68
69
70
71
name = NULL;
index = -1;
if (argc > 1) {
name = argv[1];
if ((strcmp(name, "--help") == 0) || (strcmp(name, "-h") == 0)) {
72
SDL_Log("USAGE: %s [device]\n"
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"If device is a two-digit number it'll use it as an index, otherwise\n"
"it'll use it as if it were part of the device's name.\n",
argv[0]);
return 0;
}
i = strlen(name);
if ((i < 3) && isdigit(name[0]) && ((i == 1) || isdigit(name[1]))) {
index = atoi(name);
name = NULL;
}
}
/* Initialize the force feedbackness */
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK |
SDL_INIT_HAPTIC);
89
SDL_Log("%d Haptic devices detected.\n", SDL_NumHaptics());
90
91
92
93
94
95
96
97
98
99
100
101
102
if (SDL_NumHaptics() > 0) {
/* We'll just use index or the first force feedback device found */
if (name == NULL) {
i = (index != -1) ? index : 0;
}
/* Try to find matching device */
else {
for (i = 0; i < SDL_NumHaptics(); i++) {
if (strstr(SDL_HapticName(i), name) != NULL)
break;
}
if (i >= SDL_NumHaptics()) {
103
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to find device matching '%s', aborting.\n",
104
105
106
107
108
109
110
name);
return 1;
}
}
haptic = SDL_HapticOpen(i);
if (haptic == NULL) {
111
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create the haptic device: %s\n",
112
113
114
SDL_GetError());
return 1;
}
115
SDL_Log("Device: %s\n", SDL_HapticName(i));
116
117
HapticPrintSupported(haptic);
} else {
118
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No Haptic devices found!\n");
119
120
121
122
123
124
125
126
127
128
129
return 1;
}
/* We only want force feedback errors. */
SDL_ClearError();
/* Create effects. */
memset(&efx, 0, sizeof(efx));
nefx = 0;
supported = SDL_HapticQuery(haptic);
130
SDL_Log("\nUploading effects\n");
131
132
/* First we'll try a SINE effect. */
if (supported & SDL_HAPTIC_SINE) {
133
SDL_Log(" effect %d: Sine Wave\n", nefx);
134
135
136
137
138
139
140
141
efx[nefx].type = SDL_HAPTIC_SINE;
efx[nefx].periodic.period = 1000;
efx[nefx].periodic.magnitude = 0x4000;
efx[nefx].periodic.length = 5000;
efx[nefx].periodic.attack_length = 1000;
efx[nefx].periodic.fade_length = 1000;
id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
if (id[nefx] < 0) {
142
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
143
144
145
146
147
148
abort_execution();
}
nefx++;
}
/* Now we'll try a SAWTOOTHUP */
if (supported & SDL_HAPTIC_SAWTOOTHUP) {
149
SDL_Log(" effect %d: Sawtooth Up\n", nefx);
150
151
152
153
154
155
156
157
efx[nefx].type = SDL_HAPTIC_SAWTOOTHUP;
efx[nefx].periodic.period = 500;
efx[nefx].periodic.magnitude = 0x5000;
efx[nefx].periodic.length = 5000;
efx[nefx].periodic.attack_length = 1000;
efx[nefx].periodic.fade_length = 1000;
id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
if (id[nefx] < 0) {
158
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
159
160
161
162
163
164
abort_execution();
}
nefx++;
}
/* Now the classical constant effect. */
if (supported & SDL_HAPTIC_CONSTANT) {
165
SDL_Log(" effect %d: Constant Force\n", nefx);
166
167
168
169
170
171
172
173
174
efx[nefx].type = SDL_HAPTIC_CONSTANT;
efx[nefx].constant.direction.type = SDL_HAPTIC_POLAR;
efx[nefx].constant.direction.dir[0] = 20000; /* Force comes from the south-west. */
efx[nefx].constant.length = 5000;
efx[nefx].constant.level = 0x6000;
efx[nefx].constant.attack_length = 1000;
efx[nefx].constant.fade_length = 1000;
id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
if (id[nefx] < 0) {
175
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
176
177
178
179
180
181
abort_execution();
}
nefx++;
}
/* The cute spring effect. */
if (supported & SDL_HAPTIC_SPRING) {
182
SDL_Log(" effect %d: Condition Spring\n", nefx);
183
184
185
186
187
188
189
190
191
192
193
efx[nefx].type = SDL_HAPTIC_SPRING;
efx[nefx].condition.length = 5000;
for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
efx[nefx].condition.right_sat[i] = 0x7FFF;
efx[nefx].condition.left_sat[i] = 0x7FFF;
efx[nefx].condition.right_coeff[i] = 0x2000;
efx[nefx].condition.left_coeff[i] = 0x2000;
efx[nefx].condition.center[i] = 0x1000; /* Displace the center for it to move. */
}
id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
if (id[nefx] < 0) {
194
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
195
196
197
198
199
200
abort_execution();
}
nefx++;
}
/* The pretty awesome inertia effect. */
if (supported & SDL_HAPTIC_INERTIA) {
201
SDL_Log(" effect %d: Condition Inertia\n", nefx);
202
203
204
205
206
207
208
209
210
211
efx[nefx].type = SDL_HAPTIC_SPRING;
efx[nefx].condition.length = 5000;
for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
efx[nefx].condition.right_sat[i] = 0x7FFF;
efx[nefx].condition.left_sat[i] = 0x7FFF;
efx[nefx].condition.right_coeff[i] = 0x2000;
efx[nefx].condition.left_coeff[i] = 0x2000;
}
id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
if (id[nefx] < 0) {
212
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
213
214
215
216
217
218
219
abort_execution();
}
nefx++;
}
/* Finally we'll try a left/right effect. */
if (supported & SDL_HAPTIC_LEFTRIGHT) {
220
SDL_Log(" effect %d: Left/Right\n", nefx);
221
222
223
224
225
226
efx[nefx].type = SDL_HAPTIC_LEFTRIGHT;
efx[nefx].leftright.length = 5000;
efx[nefx].leftright.large_magnitude = 0x3000;
efx[nefx].leftright.small_magnitude = 0xFFFF;
id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
if (id[nefx] < 0) {
227
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
228
229
230
231
232
233
abort_execution();
}
nefx++;
}
234
SDL_Log
235
236
("\nNow playing effects for 5 seconds each with 1 second delay between\n");
for (i = 0; i < nefx; i++) {
237
SDL_Log(" Playing effect %d\n", i);
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
SDL_HapticRunEffect(haptic, id[i], 1);
SDL_Delay(6000); /* Effects only have length 5000 */
}
/* Quit */
if (haptic != NULL)
SDL_HapticClose(haptic);
SDL_Quit();
return 0;
}
/*
* Cleans up a bit.
*/
static void
abort_execution(void)
{
257
SDL_Log("\nAborting program execution.\n");
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
SDL_HapticClose(haptic);
SDL_Quit();
exit(1);
}
/*
* Displays information about the haptic device.
*/
static void
HapticPrintSupported(SDL_Haptic * haptic)
{
unsigned int supported;
supported = SDL_HapticQuery(haptic);
275
SDL_Log(" Supported effects [%d effects, %d playing]:\n",
276
277
SDL_HapticNumEffects(haptic), SDL_HapticNumEffectsPlaying(haptic));
if (supported & SDL_HAPTIC_CONSTANT)
278
SDL_Log(" constant\n");
279
if (supported & SDL_HAPTIC_SINE)
280
SDL_Log(" sine\n");
281
/* !!! FIXME: put this back when we have more bits in 2.1 */
282
/* if (supported & SDL_HAPTIC_SQUARE)
283
SDL_Log(" square\n"); */
284
if (supported & SDL_HAPTIC_TRIANGLE)
285
SDL_Log(" triangle\n");
286
if (supported & SDL_HAPTIC_SAWTOOTHUP)
287
SDL_Log(" sawtoothup\n");
288
if (supported & SDL_HAPTIC_SAWTOOTHDOWN)
289
SDL_Log(" sawtoothdown\n");
290
if (supported & SDL_HAPTIC_RAMP)
291
SDL_Log(" ramp\n");
292
if (supported & SDL_HAPTIC_FRICTION)
293
SDL_Log(" friction\n");
294
if (supported & SDL_HAPTIC_SPRING)
295
SDL_Log(" spring\n");
296
if (supported & SDL_HAPTIC_DAMPER)
297
SDL_Log(" damper\n");
298
if (supported & SDL_HAPTIC_INERTIA)
299
SDL_Log(" inertia\n");
300
if (supported & SDL_HAPTIC_CUSTOM)
301
SDL_Log(" custom\n");
302
if (supported & SDL_HAPTIC_LEFTRIGHT)
303
304
SDL_Log(" left/right\n");
SDL_Log(" Supported capabilities:\n");
305
if (supported & SDL_HAPTIC_GAIN)
306
SDL_Log(" gain\n");
307
if (supported & SDL_HAPTIC_AUTOCENTER)
308
SDL_Log(" autocenter\n");
309
if (supported & SDL_HAPTIC_STATUS)
310
SDL_Log(" status\n");
311
312
313
314
315
316
317
}
#else
int
main(int argc, char *argv[])
{
318
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Haptic support.\n");
319
320
321
322
exit(1);
}
#endif