How to test/handle SDL2 game controller inputs? - sdl

I am trying to figure out how to properly handle game controller inputs in an SDL2 program. I have written a program which is able to handle inputs from my game controller on my Mac, but not on my Linux machine. However, the game controller does work with other programs on the Linux machine. My program uses a library called Simple2D, which wraps SDL2 to provide an easier interface.
I'm trying to determine if the problem is with the controller input handling or some missing dependency/configuration on the Linux side. I have not found any examples of using SDL2 to handle game controller inputs to determine if the code is working correctly.
Here is the code that Simple2D uses for handling game controller inputs. Do you see anything that could cause my controller to not work on my Linux machine?
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;
Update: Thanks to #genpfault, I found out that the SDL codebase comes with a test script. I am working on compiling and running this. After downloading the source code, on my Mac, I was able to successfully compile and run the test script like this:
$ cd SDL2-2.0.4/test
$ gcc testgamecontroller.c `sdl2-config --cflags --libs`
$ ./a.out
However, when I tried the same thing on my Linux machine, it failed to compile:
$ 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
So then I tried to run ./configure && make instead:
$ ./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
I'm not sure why it is failing to compile and how to move past these errors.
Update: Thanks again to #genpfault, installing the latest version of SDL (2.0.4) from source, instead of using version 2.0.2 that was available as a package, fixed my compiling issues.
Now when I run the controller test script, on my Linux machine, I see this:
2016-06-29 12:59:05.588 a.out[64297:8754739] INFO: There are 0 game controller(s) attached (0 joystick(s))
However, when I run it on my Mac I see this:
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))
What could be different about the Linux environment? Again, the same controller works in other programs on this same Linux machine.
Update: I found that the device is detected:
$ 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
However, I'm not sure why SDL is not detecting it.

Related

undefined reference to `WinMain' in eclipse IDE with cygwin (setup-x86_64)

I am currently doing unit testing for a project of c/c++ in eclipse IDE (Version: Luna Service Release 2 (4.4.2)) and I have recently upgraded my cygwin to cygwin64 to make it compatible with c++17 standard and my g++ version is g++ (GCC) 10.2.0, But I am not able to build my testsuites in eclipse, I have set the environment path to "C:\cygwin64\bin", But still I am getting the below error. Could you please help me with the below error:
Console output after building my project :
make all
Building file:
C:/Accurev/AngioJet_Development_ver1/CS/AngioJet/Firmware/src/ClinicalFeatures/door.cpp
Invoking: Cygwin C++ Compiler
g++ -DUNIT_TESTING - "C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../../AngioJet/Firmware/build/PicoZed_FSBL_bsp/ps7_cortexa9_0/include" -I"C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../testsupport/" -I"C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../testsupport/Source" -I"C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../../AngioJet/Firmware/src/Platform/Zynq7000" - I"C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../../AngioJet/Firmware/src/HostInterface" -I"C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../../AngioJet/Firmware/soup/treck/6_0_1_56/include" -I"C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../../Einstein/src/Platform/Zynq7000" -I"C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../../Einstein/src/Common" -I"C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../../AngioJet/Firmware/src/Common" -I"C:/Accurev/AngioJet_Development_ver1/CS/ut/testsuites/Firmware/hell/../../../../AngioJet/Firmware/src/ClinicalFeatures" -O0 -g -fprofile-arcs -ftest-coverage -Wall -c -fmessage-length=0 -MMD -MP -MF"src/door.d" -MT"src/door.d" -o "src/door.o" "C:/Accurev/AngioJet_Development_ver1/CS/AngioJet/Firmware/src/ClinicalFeatures/door.cpp"
Finished building: C:/Accurev/AngioJet_Development_ver1/CS/AngioJet/Firmware/src/ClinicalFeatures/door.cpp
Building target: helll.exe
Invoking: Cygwin C++ Linker
g++ -fprofile-arcs -o "helll.exe" ./src/door.o -lgcov -lbfd
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: /usr/lib/gcc/x86_64-pc-cygwin/10/../../../../lib/libcygwin.a(libcmain.o): in function `main':
/usr/src/debug/cygwin-3.3.6-1/winsup/cygwin/lib/libcmain.c:37: undefined reference to `WinMain'
collect2: error: ld returned 1 exit status
make: *** [makefile:47: helll.exe] Error 1
07:05:17 Build Finished (took 4s.531ms)
`*
I have uninstalled and reinstalled the softwares. Also I have built a new project from scratch which is building fine but whenever i try to build my project it is not building.
While doing unit testing in eclipse we create the project as c++ project and import the source files mentioned below and the structure is as follow:
Source file - door.cpp, door.h
door.h:
#include "global.h"
namespace lDOOR { void close( BasicTypes::UInt8 mode ); }
door.cpp:
#include "door.h"
void lDOOR::close(void)
{
//Normal Mode
close(BscMsg::NORMAL);
}
and we do the unit testing for the above functions present in .cpp file in the file created by us door_testsuite.h which is as follows:
#include <cxxtest/TestSuite.h>
class door_TestSuite: public CxxTest::TestSuite {
public:
void setUp(){}
void teardown(){}
void testDoorLDoorClose()
{
BscMsg::UInt8 mode = 2;
lDOOR::close(mode);
TS_ASSERT_EQUALS();
}};
And when I test the above code in cygwin terminal it executes completely fine.
This means there is no WinMain function, which is the entry point to Windows windows programs. Yes, confusing. You can choose to either build a program as a console program or windows program. (There are a few other types that are irrelevant) In a console program, the entry point is main (As with the entire world of computing), but in a windows program, it is WinMain. This question has a good answer that goes into depth about it, but you either need to switch the type of program to console, or (If your program is creating and using windows) add a WinMain function.
Sorry if this is confusing, it is difficult to differentiate between Windows, the OS, and windows, the type of program. Also, my knowledge on this subject is all from VSCode, so may be completely or partially incorrect.
TLDR: Either add a WinMain function, or switch to building your program as a windows program.

c++ pthread in eclipse cant compile, in terminal is ok

I'm trying to use pthread in eclipse (photon), end everytime i'm wave got error in compilation:
arm-linux-gnueabihf-g++ -pthread -o "FG002_PartB_1st_Edition_Ver0.1" ./I2C.o ./MCP23017.o ./MPU6050.o ./PCA9685.o -l-pthread
/usr/bin/arm-linux-gnueabihf-ld: cannot find -l-pthread
collect2: error: ld returned 1 exit status
Or another from make, but that I'll add tommorow, it depends on settings. Of course i'd tried to find answer in google, and i'd find, nad try a lot of them, but nothing helped. I thing code is ok (copied from internet example, to be sre, it is ok, a few of them, and the same result, co it must be ok).
As you see in code it is arm cross commpiller, but the same errors i have in normal compiller (in console too)
wowa#wowa-pc:~/eclipse-workspace/FG002_PartB_1st_Edition_Ver0.1$ g++ -pthread main.cpp
wowa#wowa-pc:~/eclipse-workspace/FG002_PartB_1st_Edition_Ver0.1$ ./a.outx: 0, y: 0
y increment finished
x increment finished
x: 100, y: 100

Unable to cross compile Linux openGL program with mingw32. Config.log error: undefined reference to `_glEnable'

I am attempting to cross-compile an OpenGL program using Mingw32 but have run into a road block. After invoking mingw32-configure; the compilation is interrupted by
configure: error: lacking proper OpenGL support
I checked the config.log file and found the following entries:
configure:21709: checking GL/gl.h usability
configure:21726: ccache i686-pc-mingw32-g++ -c -O2 -g -pipe -Wall -,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -mms-bitfields conftest.cpp >&5
configure:21732: $? = 0
configure:21746: result: yes
configure:21750: checking GL/gl.h presence
configure:21765: ccache i686-pc-mingw32-g++ -E conftest.cpp
configure:21771: $? = 0
configure:21785: result: yes
configure:21813: checking for GL/gl.h
configure:21820: result: yes
configure:21834: checking for glEnable in -lGL
configure:21869: ccache i686-pc-mingw32-g++ -o conftest.exe -O2 -g -pipe - Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -mms- bitfields conftest.cpp -lGL >&5
/tmp/ccjGmlvX.o: In function 'main':../rpmbuild/SOURCES/poker3d-1.1.36/conftest.cpp:34: undefined reference to `_glEnable'
collect2: ld returned 1 exit status
configure:21875: $? = 1
configure: failed program was:
| /* confdefs.h. */
I have added the llvm software rasterizer to my system after a suggestion on this website from another thread related to this problem and have also implemented a suggestion from the Mingw site to copy libopengl32.a to libGL.a. So far nothing has changed the errors that I get after each compile attempt.
Give me some advice on how to resolve this.
autotools/autoconf is abysmally bad for crosscompilation. The way the generated configure script works is, that for many tests it attempts to compile and execute short test snippet programs. Of course the whole "execute" part will miserably fail for cross compiled libraries, due to either lack in instruction set support (compiling for a different CPU) or targeting an entirely different OS.
At least in Linux one can work around this using the "misc binfmt" kernel support, which allows to register interpreters for non-native executable formats. For Windows targets you'd use Wine as an interpreter and for foreign CPUs you can use QEmu which not only can emulate whole machines, but focus CPU emulation on a single process/binary. And of course you can combine it.
However this is just a crutch and honestly you should probably ditch autoconf/autotools entirely and just write Makefiles. Today the *nix-ish systems are so similar that none of these compiled tests make a lot of sense at all.

AC_LANG_PROGRAM failed the linker stage because of order of linker option

I am trying to test a C++ library and have to do a little more than the AC_SEARCH_LIBS or AC_CHECK_LIB. However, my linker is picky about the order of the options (g++ version 5.4.0).
My configure.ac contains the following code:
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <api/BamReader.h>], [BamTools::BamReader dummy])],
[TEST_LIBS=="$TEST_LIBS -lbamtools"] [HAVE_BAMTOOLS=1],
[AC_MSG_WARN([libbamtools is not installed])])
I know that the Bamtools are install on my system. This will generate an negative result:
checking api/BamReader.h usability... yes
checking api/BamReader.h presence... no
configure: WARNING: api/BamReader.h: accepted by the compiler, rejected by the preprocessor!
configure: WARNING: api/BamReader.h: proceeding with the compiler's result
checking for api/BamReader.h... yes
configure: WARNING: libbamtools is not installed <-- this line
After some investigation, it appears to be the order of the linker option.
The conftest.cpp file looks like the following:
#include <api/BamReader.h>
int main () {
BamTools::BamReader dummy;
return 0;
}
The autoconf macro is calling
g++ -o conftest -g -O2 -I/usr/local/include/bamtools -L/usr/local/lib/bamtools -lbamtools conftest.cpp/tmp/ccZiV1J9.o: In function `main':
/home/kzhou/coding/tmp/conftest.cpp:24: undefined reference to `BamTools::BamReader::BamReader()'
/home/kzhou/coding/tmp/conftest.cpp:24: undefined reference to `BamTools::BamReader::~BamReader()'
collect2: error: ld returned 1 exit status
If yo switch the order by putting the -lbamtools to the end, then the linker is happy:
g++ -o conftest -g -O2 -I/usr/local/include/bamtools -L/usr/local/lib/bamtools conftest.cpp -lbamtools
I wonder the AC_LANG_PROGRAM needs to be updated? Please comment. So far I have not found a good solution for this problem.
Please reference:
https://nerdland.net/2009/07/detecting-c-libraries-with-autotools/
This looks like you are passing the library in the wrong variable; if you were passing the library in LIBS it would be in the right position because autoconf does the right thing.
Now, the code you pasted has a syntax error too (using == which is a comparison instead of = which is an assignment), and a logical one since TEST_LIBS was a variable used by the specific post you reference. So that is not what is setting -lbamtools in any of the orders.
save_LIBS=$LIBS
LIBS="$LIBS -lbamtools"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <api/BamReader.h>], [BamTools::BamReader dummy])],
[save_LIBS="$LIBS"; HAVE_BAMTOOLS=1],
[AC_MSG_WARN([libbamtools is not installed])])
LIBS=$save_LIBS
this should do what you're looking for, although it's still a bit more complicated than it could be. You could use AC_CHECK_TYPE to just check if BamTools::BamReader is defined.

Dealing with "C compiler cannot create executables" in Cygwin

Whatever I try to compile in Cygwin I get the following output:
checking for mingw32 environment... no
checking for EMX OS/2 environment... no
checking how to run the C preprocessor... gcc -E
checking for gcc... gcc
checking whether the C compiler (gcc ) works... no
configure: error: installation or configuration problem: C compiler cannot creat
e executables.
The last few lines of the logfile look like this:
configure:2810: checking for EMX OS/2 environment
configure:2822: gcc -c conftest.c 1>&5
configure: In function `main':
configure:2818: error: `__EMX__' undeclared (first use in this function)
configure:2818: error: (Each undeclared identifier is reported only once
configure:2818: error: for each function it appears in.)
configure: failed program was:
#line 2815 "configure"
#include "confdefs.h"
int main() {
return __EMX__;
; return 0; }
configure:2838: checking how to run the C preprocessor
configure:2859: gcc -E conftest.c >/dev/null 2>conftest.out
configure:2943: checking for gcc
configure:3056: checking whether the C compiler (gcc ) works
configure:3072: gcc -o conftest conftest.c -llib 1>&5
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/ld: cannot find
-llib
collect2: ld returned 1 exit status
configure: failed program was:
#line 3067 "configure"
#include "confdefs.h"
main(){return(0);}
This is a fresh Cygwin install with G++ and a bunch of other devtools added. Any idea what I need to do to get this thing working?
Update 0: Nick, your link to http://www.geektimes.com/linux/troubleshooting/c-cant-create-executables.html was tried already - unfortunately this instructions are for redhat and do not seem to apply to cygwin.
Your Configure is wrong.
Usually autoreconf -f helps. If not you need to check the failing rule and fix it.
The '-llib' seems a bit unusual to me, but I'm far from an expert. Just out of curiosity is autoconf installed? I had some problems similar to this until I installed autoconf. It seems like the configure script is incorrectly generating a '-llib' value but it's hard to say why based on just the snippets posted.
When I've had this problem, it has been a link error caused by Cygwin looking for "library.o" instead of "library.obj" or "library.so" instead of "library.dll".