testgamecontroller.c (10905B)
1/* 2 Copyright (C) 1997-2014 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 game controller 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 512 28#define SCREEN_HEIGHT 317 29#endif 30 31static SDL_Texture * 32LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent) 33{ 34 SDL_Surface *temp = NULL; 35 SDL_Texture *texture = NULL; 36 37 temp = SDL_LoadBMP(file); 38 if (temp == NULL) { 39 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError()); 40 } else { 41 /* Set transparent pixel as the pixel at (0,0) */ 42 if (transparent) { 43 if (temp->format->BytesPerPixel == 1) { 44 SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *)temp->pixels); 45 } else { 46 SDL_assert(!temp->format->palette); 47 SDL_assert(temp->format->BitsPerPixel == 24); 48 SDL_SetColorKey(temp, SDL_TRUE, (*(Uint32 *)temp->pixels) & 0x00FFFFFF); 49 } 50 } 51 52 texture = SDL_CreateTextureFromSurface(renderer, temp); 53 if (!texture) { 54 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError()); 55 } 56 } 57 if (temp) { 58 SDL_FreeSurface(temp); 59 } 60 return texture; 61} 62 63SDL_bool 64WatchGameController(SDL_GameController * gamecontroller) 65{ 66 /* This is indexed by SDL_GameControllerButton. */ 67 static const struct { int x; int y; } button_positions[] = { 68 {387, 167}, /* A */ 69 {431, 132}, /* B */ 70 {342, 132}, /* X */ 71 {389, 101}, /* Y */ 72 {174, 132}, /* BACK */ 73 {233, 132}, /* GUIDE */ 74 {289, 132}, /* START */ 75 {75, 154}, /* LEFTSTICK */ 76 {305, 230}, /* RIGHTSTICK */ 77 {77, 40}, /* LEFTSHOULDER */ 78 {396, 36}, /* RIGHTSHOULDER */ 79 {154, 188}, /* DPAD_UP */ 80 {154, 249}, /* DPAD_DOWN */ 81 {116, 217}, /* DPAD_LEFT */ 82 {186, 217}, /* DPAD_RIGHT */ 83 }; 84 85 /* This is indexed by SDL_GameControllerAxis. */ 86 static const struct { int x; int y; double angle; } axis_positions[] = { 87 {75, 154, 0.0}, /* LEFTX */ 88 {75, 154, 90.0}, /* LEFTY */ 89 {305, 230, 0.0}, /* RIGHTX */ 90 {305, 230, 90.0}, /* RIGHTY */ 91 {91, 0, 90.0}, /* TRIGGERLEFT */ 92 {375, 0, 90.0}, /* TRIGGERRIGHT */ 93 }; 94 95 const char *name = SDL_GameControllerName(gamecontroller); 96 const char *basetitle = "Game Controller Test: "; 97 const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + 1; 98 char *title = (char *)SDL_malloc(titlelen); 99 SDL_Texture *background, *button, *axis; 100 SDL_Window *window = NULL; 101 SDL_Renderer *screen = NULL; 102 SDL_bool retval = SDL_FALSE; 103 SDL_bool done = SDL_FALSE; 104 SDL_Event event; 105 int i; 106 107 if (title) { 108 SDL_snprintf(title, titlelen, "%s%s", basetitle, name); 109 } 110 111 /* Create a window to display controller state */ 112 window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, 113 SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 114 SCREEN_HEIGHT, 0); 115 if (window == NULL) { 116 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); 117 return SDL_FALSE; 118 } 119 120 screen = SDL_CreateRenderer(window, -1, 0); 121 if (screen == NULL) { 122 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); 123 SDL_DestroyWindow(window); 124 return SDL_FALSE; 125 } 126 127 SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE); 128 SDL_RenderClear(screen); 129 SDL_RenderPresent(screen); 130 SDL_RaiseWindow(window); 131 132 /* scale for platforms that don't give you the window size you asked for. */ 133 SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT); 134 135 background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE); 136 button = LoadTexture(screen, "button.bmp", SDL_TRUE); 137 axis = LoadTexture(screen, "axis.bmp", SDL_TRUE); 138 139 if (!background || !button || !axis) { 140 SDL_DestroyRenderer(screen); 141 SDL_DestroyWindow(window); 142 return SDL_FALSE; 143 } 144 SDL_SetTextureColorMod(button, 10, 255, 21); 145 SDL_SetTextureColorMod(axis, 10, 255, 21); 146 147 /* !!! FIXME: */ 148 /*SDL_RenderSetLogicalSize(screen, background->w, background->h);*/ 149 150 /* Print info about the controller we are watching */ 151 SDL_Log("Watching controller %s\n", name ? name : "Unknown Controller"); 152 153 /* Loop, getting controller events! */ 154 while (!done) { 155 /* blank screen, set up for drawing this frame. */ 156 SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE); 157 SDL_RenderClear(screen); 158 SDL_RenderCopy(screen, background, NULL, NULL); 159 160 while (SDL_PollEvent(&event)) { 161 switch (event.type) { 162 case SDL_KEYDOWN: 163 if (event.key.keysym.sym != SDLK_ESCAPE) { 164 break; 165 } 166 /* Fall through to signal quit */ 167 case SDL_QUIT: 168 done = SDL_TRUE; 169 break; 170 default: 171 break; 172 } 173 } 174 175 /* Update visual controller state */ 176 for (i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) { 177 if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) { 178 const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 }; 179 SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, 0); 180 } 181 } 182 183 for (i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) { 184 const Sint16 deadzone = 8000; /* !!! FIXME: real deadzone */ 185 const Sint16 value = SDL_GameControllerGetAxis(gamecontroller, (SDL_GameControllerAxis)(i)); 186 if (value < -deadzone) { 187 const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 }; 188 const double angle = axis_positions[i].angle; 189 SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0); 190 } else if (value > deadzone) { 191 const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 }; 192 const double angle = axis_positions[i].angle + 180.0; 193 SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0); 194 } 195 } 196 197 SDL_RenderPresent(screen); 198 199 if (!SDL_GameControllerGetAttached(gamecontroller)) { 200 done = SDL_TRUE; 201 retval = SDL_TRUE; /* keep going, wait for reattach. */ 202 } 203 } 204 205 SDL_DestroyRenderer(screen); 206 SDL_DestroyWindow(window); 207 return retval; 208} 209 210int 211main(int argc, char *argv[]) 212{ 213 int i; 214 int nController = 0; 215 int retcode = 0; 216 char guid[64]; 217 SDL_GameController *gamecontroller; 218 219 /* Enable standard application logging */ 220 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 221 222 /* Initialize SDL (Note: video is required to start event loop) */ 223 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER ) < 0) { 224 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); 225 return 1; 226 } 227 228 SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt"); 229 230 /* Print information about the controller */ 231 for (i = 0; i < SDL_NumJoysticks(); ++i) { 232 const char *name; 233 const char *description; 234 235 SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), 236 guid, sizeof (guid)); 237 238 if ( SDL_IsGameController(i) ) 239 { 240 nController++; 241 name = SDL_GameControllerNameForIndex(i); 242 description = "Controller"; 243 } else { 244 name = SDL_JoystickNameForIndex(i); 245 description = "Joystick"; 246 } 247 SDL_Log("%s %d: %s (guid %s)\n", description, i, name ? name : "Unknown", guid); 248 } 249 SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n", nController, SDL_NumJoysticks()); 250 251 if (argv[1]) { 252 SDL_bool reportederror = SDL_FALSE; 253 SDL_bool keepGoing = SDL_TRUE; 254 SDL_Event event; 255 int device = atoi(argv[1]); 256 if (device >= SDL_NumJoysticks()) { 257 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%i is an invalid joystick index.\n", device); 258 retcode = 1; 259 } else { 260 SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(device), 261 guid, sizeof (guid)); 262 SDL_Log("Attempting to open device %i, guid %s\n", device, guid); 263 gamecontroller = SDL_GameControllerOpen(device); 264 while (keepGoing) { 265 if (gamecontroller == NULL) { 266 if (!reportederror) { 267 if (gamecontroller == NULL) { 268 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open gamecontroller %d: %s\n", device, SDL_GetError()); 269 retcode = 1; 270 } 271 keepGoing = SDL_FALSE; 272 reportederror = SDL_TRUE; 273 } 274 } else { 275 reportederror = SDL_FALSE; 276 keepGoing = WatchGameController(gamecontroller); 277 SDL_GameControllerClose(gamecontroller); 278 } 279 280 gamecontroller = NULL; 281 if (keepGoing) { 282 SDL_Log("Waiting for attach\n"); 283 } 284 while (keepGoing) { 285 SDL_WaitEvent(&event); 286 if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN) 287 || (event.type == SDL_MOUSEBUTTONDOWN)) { 288 keepGoing = SDL_FALSE; 289 } else if (event.type == SDL_CONTROLLERDEVICEADDED) { 290 gamecontroller = SDL_GameControllerOpen(event.cdevice.which); 291 break; 292 } 293 } 294 } 295 } 296 } 297 298 SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); 299 300 return retcode; 301} 302 303#else 304 305int 306main(int argc, char *argv[]) 307{ 308 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n"); 309 exit(1); 310} 311 312#endif