Atlas - testhaptic.c

Home / ext / SDL / test Lines: 1 | Size: 14429 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
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 SDL_HapticEffectID 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} 395
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.