1 /* 2 Copyright (C) 1997-2014 Sam Lantinga <slouken (at) 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 #ifndef SDL_JOYSTICK_DISABLED 22 23 #ifdef __IPHONEOS__ 24 #define SCREEN_WIDTH 320 25 #define SCREEN_HEIGHT 480 26 #else 27 #define SCREEN_WIDTH 640 28 #define SCREEN_HEIGHT 480 29 #endif 30 31 32 static void 33 DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h) 34 { 35 const SDL_Rect area = { x, y, w, h }; 36 SDL_RenderFillRect(r, &area); 37 } 38 39 static SDL_bool 40 WatchJoystick(SDL_Joystick * joystick) 41 { 42 SDL_Window *window = NULL; 43 SDL_Renderer *screen = NULL; 44 const char *name = NULL; 45 SDL_bool retval = SDL_FALSE; 46 SDL_bool done = SDL_FALSE; 47 SDL_Event event; 48 int i; 49 50 /* Create a window to display joystick axis position */ 51 window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED, 52 SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 53 SCREEN_HEIGHT, 0); 54 if (window == NULL) { 55 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); 56 return SDL_FALSE; 57 } 58 59 screen = SDL_CreateRenderer(window, -1, 0); 60 if (screen == NULL) { 61 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); 62 SDL_DestroyWindow(window); 63 return SDL_FALSE; 64 } 65 66 SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE); 67 SDL_RenderClear(screen); 68 SDL_RenderPresent(screen); 69 SDL_RaiseWindow(window); 70 71 /* Print info about the joystick we are watching */ 72 name = SDL_JoystickName(joystick); 73 SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick), 74 name ? name : "Unknown Joystick"); 75 SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n", 76 SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick), 77 SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick)); 78 79 /* Loop, getting joystick events! */ 80 while (!done) { 81 /* blank screen, set up for drawing this frame. */ 82 SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE); 83 SDL_RenderClear(screen); 84 85 while (SDL_PollEvent(&event)) { 86 switch (event.type) { 87 case SDL_JOYAXISMOTION: 88 SDL_Log("Joystick %d axis %d value: %d\n", 89 event.jaxis.which, 90 event.jaxis.axis, event.jaxis.value); 91 break; 92 case SDL_JOYHATMOTION: 93 SDL_Log("Joystick %d hat %d value:", 94 event.jhat.which, event.jhat.hat); 95 if (event.jhat.value == SDL_HAT_CENTERED) 96 SDL_Log(" centered"); 97 if (event.jhat.value & SDL_HAT_UP) 98 SDL_Log(" up"); 99 if (event.jhat.value & SDL_HAT_RIGHT) 100 SDL_Log(" right"); 101 if (event.jhat.value & SDL_HAT_DOWN) 102 SDL_Log(" down"); 103 if (event.jhat.value & SDL_HAT_LEFT) 104 SDL_Log(" left"); 105 SDL_Log("\n"); 106 break; 107 case SDL_JOYBALLMOTION: 108 SDL_Log("Joystick %d ball %d delta: (%d,%d)\n", 109 event.jball.which, 110 event.jball.ball, event.jball.xrel, event.jball.yrel); 111 break; 112 case SDL_JOYBUTTONDOWN: 113 SDL_Log("Joystick %d button %d down\n", 114 event.jbutton.which, event.jbutton.button); 115 break; 116 case SDL_JOYBUTTONUP: 117 SDL_Log("Joystick %d button %d up\n", 118 event.jbutton.which, event.jbutton.button); 119 break; 120 case SDL_KEYDOWN: 121 if ((event.key.keysym.sym != SDLK_ESCAPE) && 122 (event.key.keysym.sym != SDLK_AC_BACK)) { 123 break; 124 } 125 /* Fall through to signal quit */ 126 case SDL_FINGERDOWN: 127 case SDL_MOUSEBUTTONDOWN: 128 case SDL_QUIT: 129 done = SDL_TRUE; 130 break; 131 default: 132 break; 133 } 134 } 135 /* Update visual joystick state */ 136 SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE); 137 for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) { 138 if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) { 139 DrawRect(screen, (i%20) * 34, SCREEN_HEIGHT - 68 + (i/20) * 34, 32, 32); 140 } 141 } 142 143 SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE); 144 for (i = 0; i < SDL_JoystickNumAxes(joystick); ++i) { 145 /* Draw the X/Y axis */ 146 int x, y; 147 x = (((int) SDL_JoystickGetAxis(joystick, i)) + 32768); 148 x *= SCREEN_WIDTH; 149 x /= 65535; 150 if (x < 0) { 151 x = 0; 152 } else if (x > (SCREEN_WIDTH - 16)) { 153 x = SCREEN_WIDTH - 16; 154 } 155 ++i; 156 if (i < SDL_JoystickNumAxes(joystick)) { 157 y = (((int) SDL_JoystickGetAxis(joystick, i)) + 32768); 158 } else { 159 y = 32768; 160 } 161 y *= SCREEN_HEIGHT; 162 y /= 65535; 163 if (y < 0) { 164 y = 0; 165 } else if (y > (SCREEN_HEIGHT - 16)) { 166 y = SCREEN_HEIGHT - 16; 167 } 168 169 DrawRect(screen, x, y, 16, 16); 170 } 171 172 SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE); 173 for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) { 174 /* Derive the new position */ 175 int x = SCREEN_WIDTH/2; 176 int y = SCREEN_HEIGHT/2; 177 const Uint8 hat_pos = SDL_JoystickGetHat(joystick, i); 178 179 if (hat_pos & SDL_HAT_UP) { 180 y = 0; 181 } else if (hat_pos & SDL_HAT_DOWN) { 182 y = SCREEN_HEIGHT-8; 183 } 184 185 if (hat_pos & SDL_HAT_LEFT) { 186 x = 0; 187 } else if (hat_pos & SDL_HAT_RIGHT) { 188 x = SCREEN_WIDTH-8; 189 } 190 191 DrawRect(screen, x, y, 8, 8); 192 } 193 194 SDL_RenderPresent(screen); 195 196 if (SDL_JoystickGetAttached( joystick ) == 0) { 197 done = SDL_TRUE; 198 retval = SDL_TRUE; /* keep going, wait for reattach. */ 199 } 200 } 201 202 SDL_DestroyRenderer(screen); 203 SDL_DestroyWindow(window); 204 return retval; 205 } 206 207 int 208 main(int argc, char *argv[]) 209 { 210 const char *name; 211 int i; 212 SDL_Joystick *joystick; 213 214 /* Enable standard application logging */ 215 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 216 217 /* Initialize SDL (Note: video is required to start event loop) */ 218 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { 219 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); 220 exit(1); 221 } 222 223 /* Print information about the joysticks */ 224 SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks()); 225 for (i = 0; i < SDL_NumJoysticks(); ++i) { 226 name = SDL_JoystickNameForIndex(i); 227 SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick"); 228 joystick = SDL_JoystickOpen(i); 229 if (joystick == NULL) { 230 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i, 231 SDL_GetError()); 232 } else { 233 char guid[64]; 234 SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), 235 guid, sizeof (guid)); 236 SDL_Log(" axes: %d\n", SDL_JoystickNumAxes(joystick)); 237 SDL_Log(" balls: %d\n", SDL_JoystickNumBalls(joystick)); 238 SDL_Log(" hats: %d\n", SDL_JoystickNumHats(joystick)); 239 SDL_Log(" buttons: %d\n", SDL_JoystickNumButtons(joystick)); 240 SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick)); 241 SDL_Log(" guid: %s\n", guid); 242 SDL_JoystickClose(joystick); 243 } 244 } 245 246 #ifdef ANDROID 247 if (SDL_NumJoysticks() > 0) { 248 #else 249 if (argv[1]) { 250 #endif 251 SDL_bool reportederror = SDL_FALSE; 252 SDL_bool keepGoing = SDL_TRUE; 253 SDL_Event event; 254 int device; 255 #ifdef ANDROID 256 device = 0; 257 #else 258 device = atoi(argv[1]); 259 #endif 260 joystick = SDL_JoystickOpen(device); 261 262 while ( keepGoing ) { 263 if (joystick == NULL) { 264 if ( !reportederror ) { 265 SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError()); 266 keepGoing = SDL_FALSE; 267 reportederror = SDL_TRUE; 268 } 269 } else { 270 reportederror = SDL_FALSE; 271 keepGoing = WatchJoystick(joystick); 272 SDL_JoystickClose(joystick); 273 } 274 275 joystick = NULL; 276 if (keepGoing) { 277 SDL_Log("Waiting for attach\n"); 278 } 279 while (keepGoing) { 280 SDL_WaitEvent(&event); 281 if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN) 282 || (event.type == SDL_MOUSEBUTTONDOWN)) { 283 keepGoing = SDL_FALSE; 284 } else if (event.type == SDL_JOYDEVICEADDED) { 285 joystick = SDL_JoystickOpen(device); 286 break; 287 } 288 } 289 } 290 } 291 SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK); 292 293 return 0; 294 } 295 296 #else 297 298 int 299 main(int argc, char *argv[]) 300 { 301 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n"); 302 exit(1); 303 } 304 305 #endif 306