test/testjoystick.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 Dec 2017 16:08:09 -0800
changeset 11730 ac6c607e065c
parent 10868 a06c32b64184
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Enable building the Metal renderer by default, and weak link the Metal framework so the SDL library is safe to use on older Macs
Also generate iOS versions of the Metal shaders
     1 /*
     2   Copyright (C) 1997-2017 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 SDL_Renderer *screen = NULL;
    36 SDL_bool retval = SDL_FALSE;
    37 SDL_bool done = SDL_FALSE;
    38 
    39 static void
    40 DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h)
    41 {
    42     const SDL_Rect area = { x, y, w, h };
    43     SDL_RenderFillRect(r, &area);
    44 }
    45 
    46 void
    47 loop(void *arg)
    48 {
    49     SDL_Event event;
    50     int i;
    51     SDL_Joystick *joystick = (SDL_Joystick *)arg;
    52 
    53         /* blank screen, set up for drawing this frame. */
    54     SDL_SetRenderDrawColor(screen, 0x0, 0x0, 0x0, SDL_ALPHA_OPAQUE);
    55         SDL_RenderClear(screen);
    56 
    57         while (SDL_PollEvent(&event)) {
    58             switch (event.type) {
    59 
    60             case SDL_JOYDEVICEREMOVED:
    61                 SDL_Log("Joystick device %d removed.\n", (int) event.jdevice.which);
    62                 SDL_Log("Our instance ID is %d\n", (int) SDL_JoystickInstanceID(joystick));
    63                 break;
    64 
    65             case SDL_JOYAXISMOTION:
    66                 SDL_Log("Joystick %d axis %d value: %d\n",
    67                        event.jaxis.which,
    68                        event.jaxis.axis, event.jaxis.value);
    69                 break;
    70             case SDL_JOYHATMOTION:
    71                 SDL_Log("Joystick %d hat %d value:",
    72                        event.jhat.which, event.jhat.hat);
    73                 if (event.jhat.value == SDL_HAT_CENTERED)
    74                     SDL_Log(" centered");
    75                 if (event.jhat.value & SDL_HAT_UP)
    76                     SDL_Log(" up");
    77                 if (event.jhat.value & SDL_HAT_RIGHT)
    78                     SDL_Log(" right");
    79                 if (event.jhat.value & SDL_HAT_DOWN)
    80                     SDL_Log(" down");
    81                 if (event.jhat.value & SDL_HAT_LEFT)
    82                     SDL_Log(" left");
    83                 SDL_Log("\n");
    84                 break;
    85             case SDL_JOYBALLMOTION:
    86                 SDL_Log("Joystick %d ball %d delta: (%d,%d)\n",
    87                        event.jball.which,
    88                        event.jball.ball, event.jball.xrel, event.jball.yrel);
    89                 break;
    90             case SDL_JOYBUTTONDOWN:
    91                 SDL_Log("Joystick %d button %d down\n",
    92                        event.jbutton.which, event.jbutton.button);
    93                 break;
    94             case SDL_JOYBUTTONUP:
    95                 SDL_Log("Joystick %d button %d up\n",
    96                        event.jbutton.which, event.jbutton.button);
    97                 break;
    98             case SDL_KEYDOWN:
    99                 if ((event.key.keysym.sym != SDLK_ESCAPE) &&
   100                     (event.key.keysym.sym != SDLK_AC_BACK)) {
   101                     break;
   102                 }
   103                 /* Fall through to signal quit */
   104             case SDL_FINGERDOWN:
   105             case SDL_MOUSEBUTTONDOWN:
   106             case SDL_QUIT:
   107                 done = SDL_TRUE;
   108                 break;
   109             default:
   110                 break;
   111             }
   112         }
   113         /* Update visual joystick state */
   114         SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
   115         for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) {
   116             if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) {
   117                 DrawRect(screen, (i%20) * 34, SCREEN_HEIGHT - 68 + (i/20) * 34, 32, 32);
   118             }
   119         }
   120 
   121         SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   122         for (i = 0; i < SDL_JoystickNumAxes(joystick); ++i) {
   123             /* Draw the X/Y axis */
   124             int x, y;
   125             x = (((int) SDL_JoystickGetAxis(joystick, i)) + 32768);
   126             x *= SCREEN_WIDTH;
   127             x /= 65535;
   128             if (x < 0) {
   129                 x = 0;
   130             } else if (x > (SCREEN_WIDTH - 16)) {
   131                 x = SCREEN_WIDTH - 16;
   132             }
   133             ++i;
   134             if (i < SDL_JoystickNumAxes(joystick)) {
   135                 y = (((int) SDL_JoystickGetAxis(joystick, i)) + 32768);
   136             } else {
   137                 y = 32768;
   138             }
   139             y *= SCREEN_HEIGHT;
   140             y /= 65535;
   141             if (y < 0) {
   142                 y = 0;
   143             } else if (y > (SCREEN_HEIGHT - 16)) {
   144                 y = SCREEN_HEIGHT - 16;
   145             }
   146 
   147             DrawRect(screen, x, y, 16, 16);
   148         }
   149 
   150         SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE);
   151         for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) {
   152             /* Derive the new position */
   153             int x = SCREEN_WIDTH/2;
   154             int y = SCREEN_HEIGHT/2;
   155             const Uint8 hat_pos = SDL_JoystickGetHat(joystick, i);
   156 
   157             if (hat_pos & SDL_HAT_UP) {
   158                 y = 0;
   159             } else if (hat_pos & SDL_HAT_DOWN) {
   160                 y = SCREEN_HEIGHT-8;
   161             }
   162 
   163             if (hat_pos & SDL_HAT_LEFT) {
   164                 x = 0;
   165             } else if (hat_pos & SDL_HAT_RIGHT) {
   166                 x = SCREEN_WIDTH-8;
   167             }
   168 
   169             DrawRect(screen, x, y, 8, 8);
   170         }
   171 
   172         SDL_RenderPresent(screen);
   173 
   174         if (SDL_JoystickGetAttached( joystick ) == 0) {
   175             done = SDL_TRUE;
   176             retval = SDL_TRUE;  /* keep going, wait for reattach. */
   177         }
   178 
   179 #ifdef __EMSCRIPTEN__
   180     if (done) {
   181         emscripten_cancel_main_loop();
   182     }
   183 #endif
   184 }
   185 
   186 static SDL_bool
   187 WatchJoystick(SDL_Joystick * joystick)
   188 {
   189     SDL_Window *window = NULL;
   190     const char *name = NULL;
   191 
   192     retval = SDL_FALSE;
   193     done = SDL_FALSE;
   194 
   195     /* Create a window to display joystick axis position */
   196     window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
   197                               SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
   198                               SCREEN_HEIGHT, 0);
   199     if (window == NULL) {
   200         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
   201         return SDL_FALSE;
   202     }
   203 
   204     screen = SDL_CreateRenderer(window, -1, 0);
   205     if (screen == NULL) {
   206         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
   207         SDL_DestroyWindow(window);
   208         return SDL_FALSE;
   209     }
   210 
   211     SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   212     SDL_RenderClear(screen);
   213     SDL_RenderPresent(screen);
   214     SDL_RaiseWindow(window);
   215 
   216     /* Print info about the joystick we are watching */
   217     name = SDL_JoystickName(joystick);
   218     SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
   219            name ? name : "Unknown Joystick");
   220     SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
   221            SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
   222            SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
   223 
   224     /* Loop, getting joystick events! */
   225 #ifdef __EMSCRIPTEN__
   226     emscripten_set_main_loop_arg(loop, joystick, 0, 1);
   227 #else
   228     while (!done) {
   229         loop(joystick);
   230     }
   231 #endif
   232 
   233     SDL_DestroyRenderer(screen);
   234     screen = NULL;
   235     SDL_DestroyWindow(window);
   236     return retval;
   237 }
   238 
   239 int
   240 main(int argc, char *argv[])
   241 {
   242     const char *name, *type;
   243     int i;
   244     SDL_Joystick *joystick;
   245 
   246     SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
   247 
   248     /* Enable standard application logging */
   249     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   250 
   251     /* Initialize SDL (Note: video is required to start event loop) */
   252     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
   253         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
   254         exit(1);
   255     }
   256 
   257     /* Print information about the joysticks */
   258     SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
   259     for (i = 0; i < SDL_NumJoysticks(); ++i) {
   260         name = SDL_JoystickNameForIndex(i);
   261         SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
   262         joystick = SDL_JoystickOpen(i);
   263         if (joystick == NULL) {
   264             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
   265                     SDL_GetError());
   266         } else {
   267             char guid[64];
   268             SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
   269             SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
   270                                       guid, sizeof (guid));
   271             switch (SDL_JoystickGetType(joystick)) {
   272             case SDL_JOYSTICK_TYPE_GAMECONTROLLER:
   273                 type = "Game Controller";
   274                 break;
   275             case SDL_JOYSTICK_TYPE_WHEEL:
   276                 type = "Wheel";
   277                 break;
   278             case SDL_JOYSTICK_TYPE_ARCADE_STICK:
   279                 type = "Arcade Stick";
   280                 break;
   281             case SDL_JOYSTICK_TYPE_FLIGHT_STICK:
   282                 type = "Flight Stick";
   283                 break;
   284             case SDL_JOYSTICK_TYPE_DANCE_PAD:
   285                 type = "Dance Pad";
   286                 break;
   287             case SDL_JOYSTICK_TYPE_GUITAR:
   288                 type = "Guitar";
   289                 break;
   290             case SDL_JOYSTICK_TYPE_DRUM_KIT:
   291                 type = "Drum Kit";
   292                 break;
   293             case SDL_JOYSTICK_TYPE_ARCADE_PAD:
   294                 type = "Arcade Pad";
   295                 break;
   296             case SDL_JOYSTICK_TYPE_THROTTLE:
   297                 type = "Throttle";
   298                 break;
   299             default:
   300                 type = "Unknown";
   301                 break;
   302             }
   303             SDL_Log("       type: %s\n", type);
   304             SDL_Log("       axes: %d\n", SDL_JoystickNumAxes(joystick));
   305             SDL_Log("      balls: %d\n", SDL_JoystickNumBalls(joystick));
   306             SDL_Log("       hats: %d\n", SDL_JoystickNumHats(joystick));
   307             SDL_Log("    buttons: %d\n", SDL_JoystickNumButtons(joystick));
   308             SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
   309             SDL_Log("       guid: %s\n", guid);
   310             SDL_Log("    VID/PID: 0x%.4x/0x%.4x\n", SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick));
   311             SDL_JoystickClose(joystick);
   312         }
   313     }
   314 
   315 #if defined(__ANDROID__) || defined(__IPHONEOS__)
   316     if (SDL_NumJoysticks() > 0) {
   317 #else
   318     if (argv[1]) {
   319 #endif
   320         SDL_bool reportederror = SDL_FALSE;
   321         SDL_bool keepGoing = SDL_TRUE;
   322         SDL_Event event;
   323         int device;
   324 #if defined(__ANDROID__) || defined(__IPHONEOS__)
   325         device = 0;
   326 #else
   327         device = atoi(argv[1]);
   328 #endif
   329         joystick = SDL_JoystickOpen(device);
   330         if (joystick != NULL) {
   331             SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
   332         }
   333 
   334         while ( keepGoing ) {
   335             if (joystick == NULL) {
   336                 if ( !reportederror ) {
   337                     SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
   338                     keepGoing = SDL_FALSE;
   339                     reportederror = SDL_TRUE;
   340                 }
   341             } else {
   342                 reportederror = SDL_FALSE;
   343                 keepGoing = WatchJoystick(joystick);
   344                 SDL_JoystickClose(joystick);
   345             }
   346 
   347             joystick = NULL;
   348             if (keepGoing) {
   349                 SDL_Log("Waiting for attach\n");
   350             }
   351             while (keepGoing) {
   352                 SDL_WaitEvent(&event);
   353                 if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
   354                     || (event.type == SDL_MOUSEBUTTONDOWN)) {
   355                     keepGoing = SDL_FALSE;
   356                 } else if (event.type == SDL_JOYDEVICEADDED) {
   357                     device = event.jdevice.which;
   358                     joystick = SDL_JoystickOpen(device);
   359                     if (joystick != NULL) {
   360                         SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
   361                     }
   362                     break;
   363                 }
   364             }
   365         }
   366     }
   367     SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
   368 
   369     return 0;
   370 }
   371 
   372 #else
   373 
   374 int
   375 main(int argc, char *argv[])
   376 {
   377     SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n");
   378     exit(1);
   379 }
   380 
   381 #endif
   382 
   383 /* vi: set ts=4 sw=4 expandtab: */