test/testjoystick.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 03 Oct 2018 16:54:24 -0400
changeset 12284 fe9bafcd47ba
parent 12088 399cc39583cc
child 12503 806492103856
permissions -rw-r--r--
evdev: Don't initialize struct sigaction with "{ 0 }".

It causes warnings on some platforms, depending on the actual definition of
sigaction, and since this is static data, it'll be zero'd out anyhow.
slouken@5535
     1
/*
slouken@11811
     2
  Copyright (C) 1997-2018 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@0
    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@12088
    93
                /* First button triggers a 0.5 second full strength rumble */
slouken@12088
    94
                if (event.jbutton.button == 0) {
slouken@12088
    95
                    SDL_JoystickRumble(joystick, 0xFFFF, 0xFFFF, 500);
slouken@12088
    96
                }
slouken@1895
    97
                break;
slouken@1895
    98
            case SDL_JOYBUTTONUP:
aschiffler@7639
    99
                SDL_Log("Joystick %d button %d up\n",
slouken@1895
   100
                       event.jbutton.which, event.jbutton.button);
slouken@1895
   101
                break;
slouken@1895
   102
            case SDL_KEYDOWN:
slouken@7017
   103
                if ((event.key.keysym.sym != SDLK_ESCAPE) &&
slouken@7017
   104
                    (event.key.keysym.sym != SDLK_AC_BACK)) {
slouken@1895
   105
                    break;
slouken@1895
   106
                }
slouken@1895
   107
                /* Fall through to signal quit */
slouken@7017
   108
            case SDL_FINGERDOWN:
slouken@7017
   109
            case SDL_MOUSEBUTTONDOWN:
slouken@1895
   110
            case SDL_QUIT:
icculus@6730
   111
                done = SDL_TRUE;
slouken@1895
   112
                break;
slouken@1895
   113
            default:
slouken@1895
   114
                break;
slouken@1895
   115
            }
slouken@1895
   116
        }
slouken@6690
   117
        /* Update visual joystick state */
slouken@6690
   118
        SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
slouken@6690
   119
        for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) {
slouken@6690
   120
            if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) {
slouken@7017
   121
                DrawRect(screen, (i%20) * 34, SCREEN_HEIGHT - 68 + (i/20) * 34, 32, 32);
slouken@6690
   122
            }
slouken@6690
   123
        }
slouken@6586
   124
slouken@6690
   125
        SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE);
slouken@7017
   126
        for (i = 0; i < SDL_JoystickNumAxes(joystick); ++i) {
slouken@6690
   127
            /* Draw the X/Y axis */
slouken@6690
   128
            int x, y;
slouken@7017
   129
            x = (((int) SDL_JoystickGetAxis(joystick, i)) + 32768);
slouken@6690
   130
            x *= SCREEN_WIDTH;
slouken@6690
   131
            x /= 65535;
slouken@6690
   132
            if (x < 0) {
slouken@6690
   133
                x = 0;
slouken@6690
   134
            } else if (x > (SCREEN_WIDTH - 16)) {
slouken@6690
   135
                x = SCREEN_WIDTH - 16;
slouken@6690
   136
            }
slouken@7017
   137
            ++i;
slouken@7017
   138
            if (i < SDL_JoystickNumAxes(joystick)) {
slouken@7017
   139
                y = (((int) SDL_JoystickGetAxis(joystick, i)) + 32768);
slouken@7017
   140
            } else {
slouken@7017
   141
                y = 32768;
slouken@7017
   142
            }
slouken@6690
   143
            y *= SCREEN_HEIGHT;
slouken@6690
   144
            y /= 65535;
slouken@6690
   145
            if (y < 0) {
slouken@6690
   146
                y = 0;
slouken@6690
   147
            } else if (y > (SCREEN_HEIGHT - 16)) {
slouken@6690
   148
                y = SCREEN_HEIGHT - 16;
slouken@1895
   149
            }
slouken@2765
   150
slouken@6690
   151
            DrawRect(screen, x, y, 16, 16);
slouken@6690
   152
        }
icculus@6397
   153
slouken@6690
   154
        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE);
slouken@6690
   155
        for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) {
slouken@6690
   156
            /* Derive the new position */
slouken@6690
   157
            int x = SCREEN_WIDTH/2;
slouken@6690
   158
            int y = SCREEN_HEIGHT/2;
slouken@6690
   159
            const Uint8 hat_pos = SDL_JoystickGetHat(joystick, i);
slouken@6690
   160
slouken@6690
   161
            if (hat_pos & SDL_HAT_UP) {
slouken@6690
   162
                y = 0;
slouken@6690
   163
            } else if (hat_pos & SDL_HAT_DOWN) {
slouken@6690
   164
                y = SCREEN_HEIGHT-8;
icculus@6397
   165
            }
icculus@6397
   166
slouken@6690
   167
            if (hat_pos & SDL_HAT_LEFT) {
slouken@6690
   168
                x = 0;
slouken@6690
   169
            } else if (hat_pos & SDL_HAT_RIGHT) {
slouken@6690
   170
                x = SCREEN_WIDTH-8;
icculus@6397
   171
            }
icculus@6397
   172
slouken@6690
   173
            DrawRect(screen, x, y, 8, 8);
slouken@1895
   174
        }
slouken@6690
   175
slouken@6690
   176
        SDL_RenderPresent(screen);
icculus@6730
   177
icculus@6730
   178
        if (SDL_JoystickGetAttached( joystick ) == 0) {
icculus@6730
   179
            done = SDL_TRUE;
icculus@6730
   180
            retval = SDL_TRUE;  /* keep going, wait for reattach. */
icculus@6730
   181
        }
philipp@9607
   182
philipp@9607
   183
#ifdef __EMSCRIPTEN__
philipp@9607
   184
    if (done) {
philipp@9607
   185
        emscripten_cancel_main_loop();
philipp@9607
   186
    }
philipp@9607
   187
#endif
icculus@9278
   188
}
icculus@9278
   189
icculus@9278
   190
static SDL_bool
icculus@9278
   191
WatchJoystick(SDL_Joystick * joystick)
icculus@9278
   192
{
icculus@9278
   193
    SDL_Window *window = NULL;
icculus@9278
   194
    const char *name = NULL;
philipp@9340
   195
philipp@9340
   196
    retval = SDL_FALSE;
philipp@9338
   197
    done = SDL_FALSE;
icculus@9278
   198
icculus@9278
   199
    /* Create a window to display joystick axis position */
icculus@9278
   200
    window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
icculus@9278
   201
                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
icculus@9278
   202
                              SCREEN_HEIGHT, 0);
icculus@9278
   203
    if (window == NULL) {
icculus@9278
   204
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
icculus@9278
   205
        return SDL_FALSE;
slouken@1895
   206
    }
slouken@6690
   207
icculus@9278
   208
    screen = SDL_CreateRenderer(window, -1, 0);
icculus@9278
   209
    if (screen == NULL) {
icculus@9278
   210
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
icculus@9278
   211
        SDL_DestroyWindow(window);
icculus@9278
   212
        return SDL_FALSE;
icculus@9278
   213
    }
icculus@9278
   214
icculus@9278
   215
    SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
icculus@9278
   216
    SDL_RenderClear(screen);
icculus@9278
   217
    SDL_RenderPresent(screen);
icculus@9278
   218
    SDL_RaiseWindow(window);
icculus@9278
   219
icculus@9278
   220
    /* Print info about the joystick we are watching */
icculus@9278
   221
    name = SDL_JoystickName(joystick);
icculus@9278
   222
    SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
icculus@9278
   223
           name ? name : "Unknown Joystick");
icculus@9278
   224
    SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
icculus@9278
   225
           SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
icculus@9278
   226
           SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
icculus@9278
   227
icculus@9278
   228
    /* Loop, getting joystick events! */
icculus@9278
   229
#ifdef __EMSCRIPTEN__
icculus@9278
   230
    emscripten_set_main_loop_arg(loop, joystick, 0, 1);
icculus@9278
   231
#else
icculus@9278
   232
    while (!done) {
icculus@9278
   233
        loop(joystick);
icculus@9278
   234
    }
icculus@9278
   235
#endif
icculus@9278
   236
slouken@6690
   237
    SDL_DestroyRenderer(screen);
philipp@9340
   238
    screen = NULL;
slouken@6690
   239
    SDL_DestroyWindow(window);
icculus@6730
   240
    return retval;
slouken@0
   241
}
slouken@0
   242
slouken@1895
   243
int
slouken@1895
   244
main(int argc, char *argv[])
slouken@0
   245
{
slouken@10867
   246
    const char *name, *type;
slouken@6690
   247
    int i;
slouken@1895
   248
    SDL_Joystick *joystick;
slouken@0
   249
slime73@9876
   250
    SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
slime73@9876
   251
aschiffler@7639
   252
    /* Enable standard application logging */
philipp@9922
   253
    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
aschiffler@7639
   254
slouken@1895
   255
    /* Initialize SDL (Note: video is required to start event loop) */
slouken@6690
   256
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
aschiffler@7639
   257
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
slouken@1895
   258
        exit(1);
slouken@1895
   259
    }
slouken@0
   260
slouken@1895
   261
    /* Print information about the joysticks */
aschiffler@7639
   262
    SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
slouken@1895
   263
    for (i = 0; i < SDL_NumJoysticks(); ++i) {
slouken@6690
   264
        name = SDL_JoystickNameForIndex(i);
aschiffler@7639
   265
        SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
icculus@2200
   266
        joystick = SDL_JoystickOpen(i);
icculus@2200
   267
        if (joystick == NULL) {
aschiffler@7639
   268
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
slouken@2201
   269
                    SDL_GetError());
icculus@2200
   270
        } else {
icculus@6747
   271
            char guid[64];
icculus@9916
   272
            SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
icculus@6747
   273
            SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
icculus@6747
   274
                                      guid, sizeof (guid));
slouken@10867
   275
            switch (SDL_JoystickGetType(joystick)) {
slouken@10867
   276
            case SDL_JOYSTICK_TYPE_GAMECONTROLLER:
slouken@10867
   277
                type = "Game Controller";
slouken@10867
   278
                break;
slouken@10867
   279
            case SDL_JOYSTICK_TYPE_WHEEL:
slouken@10867
   280
                type = "Wheel";
slouken@10867
   281
                break;
slouken@10867
   282
            case SDL_JOYSTICK_TYPE_ARCADE_STICK:
slouken@10867
   283
                type = "Arcade Stick";
slouken@10867
   284
                break;
slouken@10867
   285
            case SDL_JOYSTICK_TYPE_FLIGHT_STICK:
slouken@10867
   286
                type = "Flight Stick";
slouken@10867
   287
                break;
slouken@10867
   288
            case SDL_JOYSTICK_TYPE_DANCE_PAD:
slouken@10867
   289
                type = "Dance Pad";
slouken@10867
   290
                break;
slouken@10867
   291
            case SDL_JOYSTICK_TYPE_GUITAR:
slouken@10867
   292
                type = "Guitar";
slouken@10867
   293
                break;
slouken@10867
   294
            case SDL_JOYSTICK_TYPE_DRUM_KIT:
slouken@10867
   295
                type = "Drum Kit";
slouken@10867
   296
                break;
slouken@10867
   297
            case SDL_JOYSTICK_TYPE_ARCADE_PAD:
slouken@10867
   298
                type = "Arcade Pad";
slouken@10867
   299
                break;
slouken@10868
   300
            case SDL_JOYSTICK_TYPE_THROTTLE:
slouken@10868
   301
                type = "Throttle";
slouken@10868
   302
                break;
slouken@10867
   303
            default:
slouken@10867
   304
                type = "Unknown";
slouken@10867
   305
                break;
slouken@10867
   306
            }
slouken@10867
   307
            SDL_Log("       type: %s\n", type);
aschiffler@7639
   308
            SDL_Log("       axes: %d\n", SDL_JoystickNumAxes(joystick));
aschiffler@7639
   309
            SDL_Log("      balls: %d\n", SDL_JoystickNumBalls(joystick));
aschiffler@7639
   310
            SDL_Log("       hats: %d\n", SDL_JoystickNumHats(joystick));
aschiffler@7639
   311
            SDL_Log("    buttons: %d\n", SDL_JoystickNumButtons(joystick));
aschiffler@7639
   312
            SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
aschiffler@7639
   313
            SDL_Log("       guid: %s\n", guid);
slouken@10597
   314
            SDL_Log("    VID/PID: 0x%.4x/0x%.4x\n", SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick));
icculus@2200
   315
            SDL_JoystickClose(joystick);
icculus@2200
   316
        }
slouken@1895
   317
    }
slouken@0
   318
slime73@9876
   319
#if defined(__ANDROID__) || defined(__IPHONEOS__)
slouken@7017
   320
    if (SDL_NumJoysticks() > 0) {
slouken@7017
   321
#else
slouken@6690
   322
    if (argv[1]) {
slouken@7017
   323
#endif
icculus@6731
   324
        SDL_bool reportederror = SDL_FALSE;
icculus@6730
   325
        SDL_bool keepGoing = SDL_TRUE;
icculus@6731
   326
        SDL_Event event;
philipp@8078
   327
        int device;
slime73@9876
   328
#if defined(__ANDROID__) || defined(__IPHONEOS__)
philipp@8078
   329
        device = 0;
slouken@7017
   330
#else
philipp@8078
   331
        device = atoi(argv[1]);
slouken@7017
   332
#endif
philipp@8078
   333
        joystick = SDL_JoystickOpen(device);
icculus@9916
   334
        if (joystick != NULL) {
icculus@9916
   335
            SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
icculus@9916
   336
        }
philipp@8078
   337
icculus@6731
   338
        while ( keepGoing ) {
icculus@6731
   339
            if (joystick == NULL) {
icculus@6731
   340
                if ( !reportederror ) {
philipp@8078
   341
                    SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
icculus@6732
   342
                    keepGoing = SDL_FALSE;
icculus@6731
   343
                    reportederror = SDL_TRUE;
icculus@6731
   344
                }
icculus@6731
   345
            } else {
icculus@6731
   346
                reportederror = SDL_FALSE;
icculus@6731
   347
                keepGoing = WatchJoystick(joystick);
icculus@6731
   348
                SDL_JoystickClose(joystick);
icculus@6731
   349
            }
icculus@6731
   350
slouken@6736
   351
            joystick = NULL;
icculus@6730
   352
            if (keepGoing) {
aschiffler@7639
   353
                SDL_Log("Waiting for attach\n");
slouken@6736
   354
            }
slouken@6736
   355
            while (keepGoing) {
slouken@6736
   356
                SDL_WaitEvent(&event);
slouken@7017
   357
                if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
slouken@7017
   358
                    || (event.type == SDL_MOUSEBUTTONDOWN)) {
slouken@6736
   359
                    keepGoing = SDL_FALSE;
slouken@6736
   360
                } else if (event.type == SDL_JOYDEVICEADDED) {
philipp@10707
   361
                    device = event.jdevice.which;
philipp@8078
   362
                    joystick = SDL_JoystickOpen(device);
icculus@9916
   363
                    if (joystick != NULL) {
icculus@9916
   364
                        SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
icculus@9916
   365
                    }
slouken@6736
   366
                    break;
icculus@6731
   367
                }
icculus@6730
   368
            }
icculus@6731
   369
        }
icculus@6731
   370
    }
slouken@6690
   371
    SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
slouken@0
   372
philipp@8073
   373
    return 0;
slouken@0
   374
}
aschiffler@6771
   375
aschiffler@6771
   376
#else
aschiffler@6771
   377
aschiffler@6771
   378
int
aschiffler@6771
   379
main(int argc, char *argv[])
aschiffler@6771
   380
{
aschiffler@7639
   381
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n");
aschiffler@6771
   382
    exit(1);
aschiffler@6771
   383
}
aschiffler@6771
   384
aschiffler@6771
   385
#endif
slouken@10597
   386
slouken@10597
   387
/* vi: set ts=4 sw=4 expandtab: */