Как проверить / обработать входы игрового контроллера SDL2?
Я пытаюсь понять, как правильно обрабатывать входы игрового контроллера в программе SDL2. Я написал программу, которая может обрабатывать входные данные с моего игрового контроллера на моем Mac, но не на моей машине с Linux. Тем не менее, игровой контроллер работает с другими программами на компьютере с Linux. Моя программа использует библиотеку Simple2D, которая оборачивает SDL2 для обеспечения более легкого интерфейса.
Я пытаюсь определить, связана ли проблема с обработкой ввода контроллера или с отсутствующей зависимостью / конфигурацией на стороне Linux. Я не нашел примеров использования SDL2 для обработки входов игрового контроллера, чтобы определить, работает ли код правильно.
Вот код, который Simple2D использует для обработки входов игрового контроллера. Вы видите что-нибудь, что может заставить мой контроллер не работать на моей машине с Linux?
https://github.com/simple2d/simple2d/blob/master/src/simple2d.c#L642-L689
// Variables for controllers and joysticks
SDL_GameController *controller = NULL;
SDL_Joystick *joy = NULL;
// Enumerate joysticks
for (int i = 0; i < SDL_NumJoysticks(); ++i) {
// Check to see if joystick supports SDL's game controller interface
if (SDL_IsGameController(i)) {
controller = SDL_GameControllerOpen(i);
if (controller) {
sprintf(S2D_msg, "Found a valid controller, named: %s\n",
SDL_GameControllerName(controller));
S2D_Log(S2D_msg, S2D_INFO);
break; // Break after first available controller
} else {
sprintf(S2D_msg, "Could not open game controller %i: %s\n", i, SDL_GetError());
S2D_Log(S2D_msg, S2D_ERROR);
}
// Controller interface not supported, try to open as joystick
} else {
sprintf(S2D_msg, "Joystick %i is not supported by the game controller interface", i);
S2D_Log(S2D_msg, S2D_WARN);
joy = SDL_JoystickOpen(i);
// Joystick is valid
if (joy) {
sprintf(S2D_msg,
"Opened Joystick %i\n"
"Name: %s\n"
"Axes: %d\n"
"Buttons: %d\n"
"Balls: %d\n",
i, SDL_JoystickName(joy), SDL_JoystickNumAxes(joy),
SDL_JoystickNumButtons(joy), SDL_JoystickNumBalls(joy)
);
S2D_Log(S2D_msg, S2D_INFO);
// Joystick not valid
} else {
sprintf(S2D_msg, "Could not open Joystick %i", i);
S2D_Log(S2D_msg, S2D_ERROR);
}
break; // Break after first available joystick
}
}
https://github.com/simple2d/simple2d/blob/master/src/simple2d.c#L782-L806
SDL_Event e;
while (SDL_PollEvent(&e)) {
switch (e.type) {
case SDL_JOYAXISMOTION:
if (window->on_controller)
window->on_controller(true, e.jaxis.axis, e.jaxis.value, false, 0);
break;
case SDL_JOYBUTTONDOWN:
if (window->on_controller)
window->on_controller(false, 0, 0, true, e.jbutton.button);
break;
Обновление: благодаря @genpfault я обнаружил, что база кода SDL поставляется с тестовым скриптом. Я работаю над компиляцией и запуском этого. После загрузки исходного кода на моем Mac я смог успешно скомпилировать и запустить тестовый скрипт следующим образом:
$ cd SDL2-2.0.4/test
$ gcc testgamecontroller.c `sdl2-config --cflags --libs`
$ ./a.out
Однако, когда я попробовал то же самое на моем компьютере с Linux, он не смог скомпилировать:
$ gcc testgamecontroller.c `sdl2-config --cflags --libs`
In file included from /usr/include/SDL2/SDL.h:69:0,
from testgamecontroller.c:19:
testgamecontroller.c: In function 'main':
testgamecontroller.c:296:132: warning: comparison between pointer and integer
SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
^
/usr/include/SDL2/SDL_assert.h:143:19: note: in definition of macro 'SDL_enabled_assert'
while ( !(condition) ) { \
^
testgamecontroller.c:296:17: note: in expansion of macro 'SDL_assert'
SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
^
testgamecontroller.c:325:144: warning: comparison between pointer and integer
SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
^
/usr/include/SDL2/SDL_assert.h:143:19: note: in definition of macro 'SDL_enabled_assert'
while ( !(condition) ) { \
^
testgamecontroller.c:325:29: note: in expansion of macro 'SDL_assert'
SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
^
/tmp/ccipRq1s.o: In function `main':
testgamecontroller.c:(.text+0x8ea): undefined reference to `SDL_GameControllerFromInstanceID'
testgamecontroller.c:(.text+0xa0e): undefined reference to `SDL_GameControllerFromInstanceID'
collect2: error: ld returned 1 exit status
Итак, я попытался бежать ./configure && make
вместо:
$ ./configure
checking build system type... armv7l-unknown-linux-gnueabihf
checking host system type... armv7l-unknown-linux-gnueabihf
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for an ANSI C-conforming const... yes
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for SDL... yes
checking how to run the C preprocessor... gcc -E
checking for X... libraries , headers
checking for OpenGL support... yes
checking for OpenGL ES support... no
checking for OpenGL ES2 support... yes
checking for TTF_Init in -lSDL2_ttf... yes
configure: creating ./config.status
config.status: creating Makefile
$ make
gcc -o checkkeys checkkeys.c -g -O2 -D_REENTRANT -I/usr/include/SDL2 -DHAVE_OPENGLES2 -DHAVE_OPENGL -DHAVE_SDL_TTF -g -lSDL2_test -lSDL2
gcc -o loopwave loopwave.c -g -O2 -D_REENTRANT -I/usr/include/SDL2 -DHAVE_OPENGLES2 -DHAVE_OPENGL -DHAVE_SDL_TTF -g -lSDL2_test -lSDL2
gcc -o loopwavequeue loopwavequeue.c -g -O2 -D_REENTRANT -I/usr/include/SDL2 -DHAVE_OPENGLES2 -DHAVE_OPENGL -DHAVE_SDL_TTF -g -lSDL2_test -lSDL2
/tmp/ccdYXqs4.o: In function `loop':
/home/chip/stash/SDL2-2.0.4/test/loopwavequeue.c:63: undefined reference to `SDL_GetQueuedAudioSize'
/home/chip/stash/SDL2-2.0.4/test/loopwavequeue.c:66: undefined reference to `SDL_QueueAudio'
collect2: error: ld returned 1 exit status
Makefile:78: recipe for target 'loopwavequeue' failed
make: *** [loopwavequeue] Error 1
Я не уверен, почему он не компилируется и как пройти мимо этих ошибок.
Обновление: еще раз спасибо @genpfault, установив последнюю версию SDL (2.0.4) из исходного кода вместо использования версии 2.0.2, которая была доступна в виде пакета, исправлены мои проблемы с компиляцией.
Теперь, когда я запускаю тестовый скрипт контроллера на моей машине с Linux, я вижу это:
2016-06-29 12:59:05.588 a.out[64297:8754739] INFO: There are 0 game controller(s) attached (0 joystick(s))
Однако, когда я запускаю его на своем Mac, я вижу это:
2016-06-29 12:59:25.688 a.out[64303:8755040] INFO: Joystick 0: USB,2-axis 8-button gamepad (guid 83050000000000006020000000000000)
2016-06-29 12:59:25.690 a.out[64303:8755040] INFO: There are 0 game controller(s) attached (1 joystick(s))
Что может отличаться в среде Linux? Опять же, тот же контроллер работает в других программах на той же машине Linux.
Обновление: я обнаружил, что устройство обнаружено:
$ cat /proc/bus/input/devices
...
I: Bus=0003 Vendor=0583 Product=2060 Version=0110
N: Name="USB,2-axis 8-button gamepad "
P: Phys=usb-1c14400.usb-1/input0
S: Sysfs=/devices/platform/soc@01c00000/1c14400.usb/usb2/2-1/2-1:1.0/0003:0583:2060.0003/input/input5
U: Uniq=
H: Handlers=js0 event2
B: PROP=0
B: EV=1b
B: KEY=ff 0 0 0 0 0 0 0 0 0
B: ABS=3
B: MSC=10
Однако я не уверен, почему SDL не обнаруживает это.