test/testjoystick.c
author Kai Krakow <kai@kaishome.de>
Tue, 21 Jul 2020 23:38:42 +0200
changeset 13984 369fea168258
parent 13939 2173f488608f
permissions -rw-r--r--
Linux: Add hint for disabling deadzones
     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: */