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