test/testgamecontroller.c
author Edward Rudd <urkle@outoforder.cc>
Wed, 03 Dec 2014 12:47:39 -0500
changeset 9262 b3df9db209b0
parent 9102 a22458d5eed9
child 9278 8900afb78a19
permissions -rw-r--r--
ugh.. stray character
     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 
    31 static SDL_Texture *
    32 LoadTexture(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 
    63 SDL_bool
    64 WatchGameController(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 
   210 int
   211 main(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 
   305 int
   306 main(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