testjoystick.c (10066B)
1 /* 2 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely. 11 */ 12 13 /* Simple program to test the SDL joystick routines */ 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include "SDL.h" 20 21 #ifdef __EMSCRIPTEN__ 22 #include <emscripten/emscripten.h> 23 #endif 24 25 #ifndef SDL_JOYSTICK_DISABLED 26 27 #ifdef __IPHONEOS__ 28 #define SCREEN_WIDTH 320 29 #define SCREEN_HEIGHT 480 30 #else 31 #define SCREEN_WIDTH 640 32 #define SCREEN_HEIGHT 480 33 #endif 34 35 static SDL_Window *window = NULL; 36 static SDL_Renderer *screen = NULL; 37 static SDL_Joystick *joystick = NULL; 38 static SDL_bool done = SDL_FALSE; 39 40 static void 41 PrintJoystick(SDL_Joystick *joystick) 42 { 43 const char *type; 44 char guid[64]; 45 46 SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick); 47 SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), guid, sizeof (guid)); 48 switch (SDL_JoystickGetType(joystick)) { 49 case SDL_JOYSTICK_TYPE_GAMECONTROLLER: 50 type = "Game Controller"; 51 break; 52 case SDL_JOYSTICK_TYPE_WHEEL: 53 type = "Wheel"; 54 break; 55 case SDL_JOYSTICK_TYPE_ARCADE_STICK: 56 type = "Arcade Stick"; 57 break; 58 case SDL_JOYSTICK_TYPE_FLIGHT_STICK: 59 type = "Flight Stick"; 60 break; 61 case SDL_JOYSTICK_TYPE_DANCE_PAD: 62 type = "Dance Pad"; 63 break; 64 case SDL_JOYSTICK_TYPE_GUITAR: 65 type = "Guitar"; 66 break; 67 case SDL_JOYSTICK_TYPE_DRUM_KIT: 68 type = "Drum Kit"; 69 break; 70 case SDL_JOYSTICK_TYPE_ARCADE_PAD: 71 type = "Arcade Pad"; 72 break; 73 case SDL_JOYSTICK_TYPE_THROTTLE: 74 type = "Throttle"; 75 break; 76 default: 77 type = "Unknown"; 78 break; 79 } 80 SDL_Log("Joystick\n"); 81 SDL_Log(" name: %s\n", SDL_JoystickName(joystick)); 82 SDL_Log(" type: %s\n", type); 83 SDL_Log(" axes: %d\n", SDL_JoystickNumAxes(joystick)); 84 SDL_Log(" balls: %d\n", SDL_JoystickNumBalls(joystick)); 85 SDL_Log(" hats: %d\n", SDL_JoystickNumHats(joystick)); 86 SDL_Log(" buttons: %d\n", SDL_JoystickNumButtons(joystick)); 87 SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick)); 88 SDL_Log(" guid: %s\n", guid); 89 SDL_Log(" VID/PID: 0x%.4x/0x%.4x\n", SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick)); 90 } 91 92 static void 93 DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h) 94 { 95 const SDL_Rect area = { x, y, w, h }; 96 SDL_RenderFillRect(r, &area); 97 } 98 99 void 100 loop(void *arg) 101 { 102 SDL_Event event; 103 int i; 104 105 /* blank screen, set up for drawing this frame. */ 106 SDL_SetRenderDrawColor(screen, 0x0, 0x0, 0x0, SDL_ALPHA_OPAQUE); 107 SDL_RenderClear(screen); 108 109 while (SDL_PollEvent(&event)) { 110 switch (event.type) { 111 112 case SDL_JOYDEVICEADDED: 113 SDL_Log("Joystick device %d added.\n", (int) event.jdevice.which); 114 if (!joystick) { 115 joystick = SDL_JoystickOpen(event.jdevice.which); 116 if (joystick) { 117 PrintJoystick(joystick); 118 } else { 119 SDL_Log("Couldn't open joystick: %s\n", SDL_GetError()); 120 } 121 } 122 break; 123 124 case SDL_JOYDEVICEREMOVED: 125 SDL_Log("Joystick device %d removed.\n", (int) event.jdevice.which); 126 if (event.jdevice.which == SDL_JoystickInstanceID(joystick)) { 127 SDL_JoystickClose(joystick); 128 joystick = SDL_JoystickOpen(0); 129 } 130 break; 131 132 case SDL_JOYAXISMOTION: 133 SDL_Log("Joystick %d axis %d value: %d\n", 134 event.jaxis.which, 135 event.jaxis.axis, event.jaxis.value); 136 break; 137 case SDL_JOYHATMOTION: 138 SDL_Log("Joystick %d hat %d value:", 139 event.jhat.which, event.jhat.hat); 140 if (event.jhat.value == SDL_HAT_CENTERED) 141 SDL_Log(" centered"); 142 if (event.jhat.value & SDL_HAT_UP) 143 SDL_Log(" up"); 144 if (event.jhat.value & SDL_HAT_RIGHT) 145 SDL_Log(" right"); 146 if (event.jhat.value & SDL_HAT_DOWN) 147 SDL_Log(" down"); 148 if (event.jhat.value & SDL_HAT_LEFT) 149 SDL_Log(" left"); 150 SDL_Log("\n"); 151 break; 152 case SDL_JOYBALLMOTION: 153 SDL_Log("Joystick %d ball %d delta: (%d,%d)\n", 154 event.jball.which, 155 event.jball.ball, event.jball.xrel, event.jball.yrel); 156 break; 157 case SDL_JOYBUTTONDOWN: 158 SDL_Log("Joystick %d button %d down\n", 159 event.jbutton.which, event.jbutton.button); 160 /* First button triggers a 0.5 second full strength rumble */ 161 if (event.jbutton.button == 0) { 162 SDL_JoystickRumble(joystick, 0xFFFF, 0xFFFF, 500); 163 } 164 break; 165 case SDL_JOYBUTTONUP: 166 SDL_Log("Joystick %d button %d up\n", 167 event.jbutton.which, event.jbutton.button); 168 break; 169 case SDL_KEYDOWN: 170 /* Press the L key to lag for 3 seconds, to see what happens 171 when SDL doesn't service the event loop quickly. */ 172 if (event.key.keysym.sym == SDLK_l) { 173 SDL_Log("Lagging for 3 seconds...\n"); 174 SDL_Delay(3000); 175 break; 176 } 177 178 if ((event.key.keysym.sym != SDLK_ESCAPE) && 179 (event.key.keysym.sym != SDLK_AC_BACK)) { 180 break; 181 } 182 /* Fall through to signal quit */ 183 case SDL_FINGERDOWN: 184 case SDL_MOUSEBUTTONDOWN: 185 case SDL_QUIT: 186 done = SDL_TRUE; 187 break; 188 default: 189 break; 190 } 191 } 192 193 if (joystick) { 194 195 /* Update visual joystick state */ 196 SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE); 197 for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) { 198 if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) { 199 DrawRect(screen, (i%20) * 34, SCREEN_HEIGHT - 68 + (i/20) * 34, 32, 32); 200 } 201 } 202 203 SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE); 204 for (i = 0; i < SDL_JoystickNumAxes(joystick); ++i) { 205 /* Draw the X/Y axis */ 206 int x, y; 207 x = (((int) SDL_JoystickGetAxis(joystick, i)) + 32768); 208 x *= SCREEN_WIDTH; 209 x /= 65535; 210 if (x < 0) { 211 x = 0; 212 } else if (x > (SCREEN_WIDTH - 16)) { 213 x = SCREEN_WIDTH - 16; 214 } 215 ++i; 216 if (i < SDL_JoystickNumAxes(joystick)) { 217 y = (((int) SDL_JoystickGetAxis(joystick, i)) + 32768); 218 } else { 219 y = 32768; 220 } 221 y *= SCREEN_HEIGHT; 222 y /= 65535; 223 if (y < 0) { 224 y = 0; 225 } else if (y > (SCREEN_HEIGHT - 16)) { 226 y = SCREEN_HEIGHT - 16; 227 } 228 229 DrawRect(screen, x, y, 16, 16); 230 } 231 232 SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE); 233 for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) { 234 /* Derive the new position */ 235 int x = SCREEN_WIDTH/2; 236 int y = SCREEN_HEIGHT/2; 237 const Uint8 hat_pos = SDL_JoystickGetHat(joystick, i); 238 239 if (hat_pos & SDL_HAT_UP) { 240 y = 0; 241 } else if (hat_pos & SDL_HAT_DOWN) { 242 y = SCREEN_HEIGHT-8; 243 } 244 245 if (hat_pos & SDL_HAT_LEFT) { 246 x = 0; 247 } else if (hat_pos & SDL_HAT_RIGHT) { 248 x = SCREEN_WIDTH-8; 249 } 250 251 DrawRect(screen, x, y, 8, 8); 252 } 253 } 254 255 SDL_RenderPresent(screen); 256 257 #ifdef __EMSCRIPTEN__ 258 if (done) { 259 emscripten_cancel_main_loop(); 260 } 261 #endif 262 } 263 264 int 265 main(int argc, char *argv[]) 266 { 267 SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); 268 269 /* Enable standard application logging */ 270 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 271 272 /* Initialize SDL (Note: video is required to start event loop) */ 273 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { 274 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); 275 exit(1); 276 } 277 278 /* Create a window to display joystick axis position */ 279 window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED, 280 SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 281 SCREEN_HEIGHT, 0); 282 if (window == NULL) { 283 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); 284 return SDL_FALSE; 285 } 286 287 screen = SDL_CreateRenderer(window, -1, 0); 288 if (screen == NULL) { 289 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); 290 SDL_DestroyWindow(window); 291 return SDL_FALSE; 292 } 293 294 SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE); 295 SDL_RenderClear(screen); 296 SDL_RenderPresent(screen); 297 298 /* Loop, getting joystick events! */ 299 #ifdef __EMSCRIPTEN__ 300 emscripten_set_main_loop_arg(loop, NULL, 0, 1); 301 #else 302 while (!done) { 303 loop(NULL); 304 } 305 #endif 306 307 SDL_DestroyRenderer(screen); 308 SDL_DestroyWindow(window); 309 310 SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK); 311 312 return 0; 313 } 314 315 #else 316 317 int 318 main(int argc, char *argv[]) 319 { 320 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n"); 321 return 1; 322 } 323 324 #endif 325 326 /* vi: set ts=4 sw=4 expandtab: */