Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1338281 Posts in 61016 Topics- by 52496 Members - Latest Member: Fizzie

May 20, 2018, 09:56:19 am

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Simple cross-platform gamepad library
Pages: 1 2 [3] 4 5 6
Print
Author Topic: Simple cross-platform gamepad library  (Read 33467 times)
fractilegames
Level 1
*



View Profile WWW
« Reply #40 on: August 19, 2013, 12:28:20 pm »

This might be slightly off-topic, but would the raw input API allow using PS3 controller without needing to install any special drivers? The DualShock3 controller shows as a HID device, but does not work directly and there seems to be no good drivers for it..
Logged

ThemsAllTook
Global Moderator
Level 10
******



View Profile WWW
« Reply #41 on: August 19, 2013, 12:41:29 pm »

Good question... I haven't gotten the chance to dig into Raw Input just yet, but if the PS3 controller is recognized as HID, I should be able to at least get something from it. I kind of assumed it doesn't work at the moment just because it has a lot more axes than joyGetPosEx can report.

I need to do some research at some point and figure out exactly how everything relates between the hardware, drivers, USB HID, and the system APIs for reading device info/state, since I've pretty much only dealt with high-level system APIs for this library. My impression was that the driver talks directly to the hardware and establishes the HID interface that the higher-level system components talk to, but maybe I have this the wrong way around?
Logged

ThemsAllTook
Global Moderator
Level 10
******



View Profile WWW
« Reply #42 on: September 01, 2013, 02:43:57 pm »

Got an incremental update for you guys. First post updated with latest download. Changelog:

  • Gamepad callbacks now include context pointers
  • Axis move callback now reports previous axis value in addition to current one
  • Fixed a major bug (introduced in 1.2.0) that caused button up events never to be reported on Windows

I guess none of you got far enough with it for the Windows button up bug to be noticed, heh. No idea how I missed it earlier. The change to the axis move callback is small but important; I've found that providing the previous value to the callback allowed me to get rid of a bunch of extra objects created for the sole purpose of tracking the axis state and determining when it's passed a certain threshold. The context pointers to callbacks were at the request of another programmer, and seemed like a good idea.

Haven't had a chance to get to the rest of the stuff discussed here yet, but I'm slowly working on it in my downtime. More updates to come!
Logged

ar2rsawseen
Level 0
*

Me


View Profile WWW
« Reply #43 on: October 08, 2013, 10:31:00 pm »

Only registered here to say how awesome your Gamepad lib is. Lightway and sooooo easy to use.
Transfering to it from hidapi, which was ok, but provided only raw input without the option to get and parse descriptors.

Really looking up for updates and availability of the lib on Github, which would provide more visibility to project, option for others to contribute and easier way to track updates on the project for the rest of us.

Using it with QT now and its the best thing out there Wink
Logged
ar2rsawseen
Level 0
*

Me


View Profile WWW
« Reply #44 on: October 11, 2013, 02:19:18 am »

Been playing with it a lot. And also had some troubles, firstly, sometimes there are crashes on shutdown on Mac:

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.apple.CoreFoundation       0x00007fff8cc3404a CFArrayGetCount + 10
1   com.apple.framework.IOKit      0x00007fff91a87bfe IOHIDDeviceRegisterInputValueCallback + 135
2   libcontroller.1.0.0.dylib      0x00000001064bbab0 disposeDevice + 32
3   libcontroller.1.0.0.dylib      0x00000001064bbcbb Gamepad_shutdown + 123

Then there is a difference that inside Windows version you check for devices inside init, but on Mac that does not happen. That actually crashed my code, because I was not aware that callback for detected device may be invoked before Gamepad_detectDevices was called.

Another possible issue (or maybe it was intended that way), that nextDeviceID does not get reset on Gamepad_shutdown and deviceID keep increasing and not starting back from 0

Additionally I started putting together mappings and made it public so anyone could add what they have here: https://docs.google.com/spreadsheet/ccc?key=0Anv7XJg_o_UJdEwwcVpCZHpQOGppemY2RGwzQlhuWFE#gid=0

Also ordered Green Throttle, GameStick and will get PS3 controller to test. Also will get bluetooth adapter to test them on Windows

I would be willing to contribute as much as I could if there would be a public repository (wink, wink, github) Smiley

what I think is missing (but don't know if its possible), retrieving a unique ID as serial number to identify device across sessions. As in, I play my game and controller lost connection, it reconnects and gets different id, and if there are multiple players, each has its own id, then I cant continue playing current game session, because my id was changed and is not in the current game.

Any ideas on that?
Logged
ThemsAllTook
Global Moderator
Level 10
******



View Profile WWW
« Reply #45 on: October 11, 2013, 12:46:49 pm »

Been playing with it a lot. And also had some troubles, firstly, sometimes there are crashes on shutdown on Mac:

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.apple.CoreFoundation       0x00007fff8cc3404a CFArrayGetCount + 10
1   com.apple.framework.IOKit      0x00007fff91a87bfe IOHIDDeviceRegisterInputValueCallback + 135
2   libcontroller.1.0.0.dylib      0x00000001064bbab0 disposeDevice + 32
3   libcontroller.1.0.0.dylib      0x00000001064bbcbb Gamepad_shutdown + 123

Yikes. I'll look into that, thanks!

Then there is a difference that inside Windows version you check for devices inside init, but on Mac that does not happen. That actually crashed my code, because I was not aware that callback for detected device may be invoked before Gamepad_detectDevices was called.

Whoops, that's definitely a bug. I'll fix it so that the callback won't be invoked too early on Windows.

Another possible issue (or maybe it was intended that way), that nextDeviceID does not get reset on Gamepad_shutdown and deviceID keep increasing and not starting back from 0

what I think is missing (but don't know if its possible), retrieving a unique ID as serial number to identify device across sessions. As in, I play my game and controller lost connection, it reconnects and gets different id, and if there are multiple players, each has its own id, then I cant continue playing current game session, because my id was changed and is not in the current game.

Any ideas on that?

Hmm, interesting. I hadn't thought about the use case of calling Gamepad_shutdown() and then subsequently reinitializing it. Still, I think nextDeviceID doesn't necessarily need to be reset. The idea behind the deviceID field was to identify the order in which controllers were attached/detected, and to allow you to distinguish between two identical controllers that are connected at the same time. Maybe it needs a better name...

For identifying hardware, you'll want to use the vendorID and productID fields. They'll always be consistent between sessions and will uniquely identify each type of controller that can be used. If you have (for example) two identical Xbox controllers, they'll report the same vendorID and productID, but different deviceIDs so you can tell which one is generating an event at runtime. If you unplug one and plug it back in during the same session, it'll get a new deviceID every time.

Additionally I started putting together mappings and made it public so anyone could add what they have here: https://docs.google.com/spreadsheet/ccc?key=0Anv7XJg_o_UJdEwwcVpCZHpQOGppemY2RGwzQlhuWFE#gid=0

Awesome! I was hoping to put together a database like this someday, but hadn't really gotten started yet. Looks like you beat me to it!

Thanks for the great feedback. I'll try to post an update here soon that fixes the issues that have been reported. I'll also look into getting it onto github soon so that issues can be tracked in one place...
Logged

Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #46 on: October 11, 2013, 08:46:38 pm »

Just for fun, and to get some practice with Ada 2012, I went ahead and wrote up an Ada interface for this.

You can download it here if you want it.

I just made a more Ada-like layer over your C code while largely preserving its behavior.  The one thing I couldn't reproduce was the void* contexts to the callback functions, since Ada's insanely strong type system makes that sort of thing very hard to do in a way that makes any sense.

I'll admit that I haven't tested it at all, but it compiles fine, and for Ada that usually means that it works.
Logged



What would John Carmack do?
ar2rsawseen
Level 0
*

Me


View Profile WWW
« Reply #47 on: October 13, 2013, 10:41:24 am »

Just want to clarify about unique identification. Although your chosen way is quite popular and is for example, what is used on android systems also, I don't think its suitable for multi controller games. Of course I might be missing something, and there is a way to achieve what I mean, so please correct me if so Smiley

Let's say game supports up to two controllers. Controller with deviceID 1 selects character number 1 to play, controller with deviceID 2 selects character number 2 to play with. When they do it, I match that input from 1 goes to character 1 and input from 2 goes to character 2.
Then while playing, deviceID 1 gets disconnected, so I pause the game and wait for it to reconnect. But I can not know when it gets back, because there will never be the controller with deviceID 1. So I need to assume that next connected device will simple take the place of deviceID 1. Which I think is wrong. It would be the same, if reconnected controller simply took the first free deviceID (which actually at least would be easier to support with multi controller games than incremental ids)

Same goes for single player games. If there are multiple controller connected, I would want to provide only the controller which started the game (pressed start button for example) to play, so others controllers won't interfere/help during playing time, but if it gets disconnected, then its lost.

So is there any solution for that? Maybe I'm missing something.

Now I don't say that you need to change your current system, no, for most cases it is quite ok, but if there is an option to additionally include unique identification (like serial number of controller) to the Gamepad_device struct, I would be very grateful if you did so Smiley
Logged
ThemsAllTook
Global Moderator
Level 10
******



View Profile WWW
« Reply #48 on: October 13, 2013, 01:05:16 pm »

Ah, I see what you're going for. As far as I know, controllers don't report a serial number or anything like that, so identifying them uniquely unfortunately isn't possible. I might be able to find a way to tell which USB port they're plugged into, so if a controller is replugged into the same port it would get the same port ID... I'll definitely check on that. The solution I'd suggest would be to keep your own mapping from deviceID to controller number, and updating it when a controller disconnects or reconnects. I'll think about adding a convenience API to do this for you if I can come up with a good way to do it.
Logged

ar2rsawseen
Level 0
*

Me


View Profile WWW
« Reply #49 on: October 21, 2013, 03:05:06 am »

Quick question, is the http://sacredsoftware.net/svn/misc/StemLibProjects/gamepad/tags/1.3.0 is really the correct version source that is used in the test here (http://alexdiener.info/code/gamepad_1.3.0.zip)?

I just got my USB bluetooth, and all controller descriptions on Windows 7 32bit are reported simply as single letter M, while in your test app from here (http://alexdiener.info/code/gamepad_1.3.0.zip) it shows the correct name of controllers.

The code I'm using to get the controller works great on the Mac version, only Windows version reports M letter
Code:
struct Gamepad_device * device = Gamepad_deviceAtIndex(playerId);
char descriptionString[256];
printf("%s (0x%X 0x%X %u)", device->description, device->vendorID, device->productID, device->deviceID);
Logged
5IGVATR
Level 0
**


☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭


View Profile
« Reply #50 on: October 24, 2013, 11:37:35 pm »

aer you sure you want to asign callbacks to everything? in my experience callbacks can become messy and troublesome in heavilly threaded situations. have you taken many precautions to make the lib thread safe? i havent looked at the soucre yet but is it easy to dig directly into the back end side of things or haev you hidden everything nicely so people dont fuck something up?
Logged
ThemsAllTook
Global Moderator
Level 10
******



View Profile WWW
« Reply #51 on: October 25, 2013, 12:06:10 am »

Quick question, is the http://sacredsoftware.net/svn/misc/StemLibProjects/gamepad/tags/1.3.0 is really the correct version source that is used in the test here (http://alexdiener.info/code/gamepad_1.3.0.zip)?

Yep, should be the exact same one.

I just got my USB bluetooth, and all controller descriptions on Windows 7 32bit are reported simply as single letter M, while in your test app from here (http://alexdiener.info/code/gamepad_1.3.0.zip) it shows the correct name of controllers.

Weird! No idea what could cause that, I'll have to dig into it... The code to get the description string on Windows was borrowed from SDL_joystick, and I can't claim to entirely understand it. Bunch of registry nonsense. Maybe with some luck I'll be able to get the description a different way once I get the library switched over to Raw Input or DirectInput.

aer you sure you want to asign callbacks to everything? in my experience callbacks can become messy and troublesome in heavilly threaded situations. have you taken many precautions to make the lib thread safe? i havent looked at the soucre yet but is it easy to dig directly into the back end side of things or haev you hidden everything nicely so people dont fuck something up?

In the current implementation, the library doesn't go particularly out of its way to be thread safe. I've written some basic thread safety notes in the header file so that you'll know what to expect if you're using it in a multithreaded situation. You're likely to run into trouble if you try to call gamepad functions from multiple threads at the same time, but there probably aren't a lot of situations where you'd need to do that - for the most part, you can just set up your callbacks once, call detectDevices() and processEvents() periodically (ideally from the same thread every time), and not worry about much else. Your callbacks will execute from the thread that called detectDevices() or processEvents(), other than the device remove callback, which can be called at any time from an unspecified thread.
Logged

5IGVATR
Level 0
**


☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭☭


View Profile
« Reply #52 on: October 25, 2013, 02:07:19 pm »

aight

does this have any compatibiltiy with sdl and/or wxwidgeste? do yuo gotta wsource forge thing for this? thered' probs be lots of interest in somehting like this
Logged
ThemsAllTook
Global Moderator
Level 10
******



View Profile WWW
« Reply #53 on: October 25, 2013, 03:13:40 pm »

Should work fine with SDL, wxWidgets, or any other API as far as I know. In theory it shouldn't even get in the way of SDL_joystick or anything like that, but I haven't tried it myself...let me know if you find any conflicts!

This isn't on SourceForge or anything like that at the moment, but a lot of people in this thread have been suggesting github. I'll get it up at some point, but I haven't gotten to it yet. Will post here (and edit first post) once that's done.
Logged

DrTwox
Level 0
*


View Profile
« Reply #54 on: November 04, 2013, 09:38:46 pm »

Awesome little library! Thank you for sharing it. Smiley

A few of issues to report:

Gamepad_linux.c: PATH_MAX is used but not defined in any of the included headers. <linux/limits.h>, not <limits.h>, has the definition.
Gamepad_linux.c, line 293: The format string for sscanf should be "event%d%u" instead of "event%d%n".

Gamepad_linux.c: Valgrind reports that memory allocated in Gamepad_detectDevices is not freed on exit:

$ cat test.c
#include "gamepad/Gamepad.h"
int main( int argc, char* argv[] )
{
    Gamepad_init();
    Gamepad_shutdown();
}

$ valgrind --leak-check=full ./test
==14040== Memcheck, a memory error detector
==14040== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==14040== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==14040== Command: ./test
==14040==
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040== Warning: invalid file descriptor -1 in syscall close()
==14040==
==14040== HEAP SUMMARY:
==14040==     in use at exit: 4,004 bytes in 6 blocks
==14040==   total heap usage: 14 allocs, 8 frees, 38,762 bytes allocated
==14040==
==14040== 4,004 (56 direct, 3,948 indirect) bytes in 1 blocks are definitely lost in loss record 6 of 6
==14040==    at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14040==    by 0x401ABD: Gamepad_detectDevices (in /home/drtwox/dev/src/gamepad-1.3.0/source/gamepad/test)
==14040==    by 0x400FF5: Gamepad_init (in /home/drtwox/dev/src/gamepad-1.3.0/source/gamepad/test)
==14040==    by 0x400EC0: main (in /home/drtwox/dev/src/gamepad-1.3.0/source/gamepad/test)
==14040==
==14040== LEAK SUMMARY:
==14040==    definitely lost: 56 bytes in 1 blocks
==14040==    indirectly lost: 3,948 bytes in 5 blocks
==14040==      possibly lost: 0 bytes in 0 blocks
==14040==    still reachable: 0 bytes in 0 blocks
==14040==         suppressed: 0 bytes in 0 blocks
==14040==
==14040== For counts of detected and suppressed errors, rerun with: -v
==14040== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
Logged
ThemsAllTook
Global Moderator
Level 10
******



View Profile WWW
« Reply #55 on: November 04, 2013, 09:49:51 pm »

Thanks for the reports!

Gamepad_linux.c: PATH_MAX is used but not defined in any of the included headers. <linux/limits.h>, not <limits.h>, has the definition.

Interesting, the headers I'm using must be different for some reason. I'll change it to <linux/limits.h> if that's more portable.

Gamepad_linux.c, line 293: The format string for sscanf should be "event%d%u" instead of "event%d%n".

%n should be correct in this case, since I need to know how many characters were read. Maybe you mean "event%u%n"? If so, you're right, that makes more sense than %d%n.

Gamepad_linux.c: Valgrind reports that memory allocated in Gamepad_detectDevices is not freed on exit:

Good catch, something is definitely fishy about the way Gamepad_shutdown() frees memory. Will fix!
Logged

DrTwox
Level 0
*


View Profile
« Reply #56 on: November 04, 2013, 10:04:33 pm »

Quote from: ThemsAllTook
%n should be correct in this case, since I need to know how many characters were read. Maybe you mean "event%u%n"? If so, you're right, that makes more sense than %d%n.

It's been a long time since I used C, so all this could be wrong!

gcc (4.8.1) tells me: Gamepad_linux.c:293:4: error: format ‘%n’ expects argument of type ‘int *’, but argument 4 has type ‘unsigned int *’ [-Werror=format=]

Looking closer at the lines in question:

Code:
unsigned int charsConsumed;
int num
...
sscanf(entity->d_name, "event%d%n", &num, &charsConsumed)

charsConsumed is unsigned int, so the correct format specifier should be %u, shouldn't it?
Logged
ThemsAllTook
Global Moderator
Level 10
******



View Profile WWW
« Reply #57 on: November 04, 2013, 10:08:32 pm »

Ah, I gotcha - charsConsumed needs to be signed. %n doesn't actually read anything from the string, and instead writes the number of characters read so far by sscanf to its argument. Easy enough fix, not sure why I wasn't seeing the warning myself...
Logged

DrTwox
Level 0
*


View Profile
« Reply #58 on: November 04, 2013, 10:29:04 pm »

Ah, I gotcha - charsConsumed needs to be signed. %n doesn't actually read anything from the string, and instead writes the number of characters read so far by sscanf to its argument. Easy enough fix, not sure why I wasn't seeing the warning myself...

That would explain why the library stopped working for me after applying my naive "fix"! D'oh!  Embarrassed

I can also report that the library compiles and works with Visual Studio 2013, except Gamepad_windows.c calls snprintf, which Microsoft don't provide. A drop-in implementation from http://www.ijs.si/software/snprintf/ gets it going though.
Logged
Prinsessa
Level 10
*****


Ava Skoog


View Profile WWW
« Reply #59 on: November 07, 2013, 04:15:33 am »

This is great. I might not need it, since SDL2 probably provides it well, but if not, I'm definitely looking into this. This is a great thing to be able to readily plug into whatever system one otherwise uses, in case it lacks the support or at least sucks at it.
Logged

Pages: 1 2 [3] 4 5 6
Print
Jump to:  

Theme orange-lt created by panic