Hammerspoon / hammerspoon

Staggeringly powerful macOS desktop automation with Lua
http://www.hammerspoon.org
MIT License
11.72k stars 579 forks source link

hs.gamepad - Support for Gamepad Devices #2372

Open latenitefilms opened 4 years ago

latenitefilms commented 4 years ago

Originally discussed in #1109, I'm now interested in trying to tackle adding Xbox Wireless Controller support to Hammerspoon using Apple's Game Controller Framework.

I've just ordered a Xbox Wireless Controller, so will attempt to make it work once it arrives.

cmsj commented 4 years ago

Sounds cool. One request - can we keep it generic and not call it hs.xbox or something, since it ought to work with other compatible controllers? (I should have a spare PS4 controller somewhere I can test with).

latenitefilms commented 4 years ago

@cmsj - Yes, absolutely - how do you feel about hs.gamecontroller?

Digging into this a bit more before my Xbox Wireless Controller arrives, it seems Apple's Game Controller Framework might not be the best way to go anyway, as it only really supports to the Xbox Wireless Controller in Catalina - whereas most of the people in our industry, are still on Mojave for the foreseeable future (i.e. until something like Final Cut Pro forces us to update).

I think probably the best way to go is to basically build our own extension from scratch using the same methods you've used in the Stream Deck plugin. That way we can manually add new controllers as people request them. Thoughts on this? @asmagill ?

It's also really hard to find out what devices Apple's Game Controller Framework actually supports - there doesn't seem to be any list or documentation on Apple's site.

For example, Apple says they only added Xbox Wireless Controller and DualShock4 support to the Game Controller Framework in Catalina, but others report that the Xbox One controller works on Mojave - so I have no idea what's going on until I get an actual controller in my hands (hopefully tomorrow).

One controller I know I want to support from the get-go is the Logitech F310, as another CommandPost user has requested support.

My plan at this stage is to basically try communicate with the hardware directly using Apple's IOKit framework. This is probably a good starting point?


Related video:

Supporting New Game Controllers With iOS 13, macOS Catalina, and tvOS 13, the Game Controller framework adds support for several well-known console game controllers. Get briefed about the newly-added controllers and understand how their inputs are delivered. Learn recommended best practices for handling optional buttons, and understand the right approach for support on macOS.

Related to Game Controller Framework:

Other related projects:

Related articles:

latenitefilms commented 4 years ago

For anyone playing at home, my fancy new Xbox Wireless Controller arrived.

As expected, connected via Bluetooth, or via the USB cable does nothing on Mojave (i.e. it won't appear in the HTML5 Gamepad Tester). Boo!

Side Note: here's an interesting back story on Apple's Game Controller history.

However, if you install the TattieBogle Xbox 360 Driver, the controller is now available in the HTML5 Gamepad Tester, which is great.

You can now use the free Enjoyable app to assign keyboard shortcuts to the buttons - which is awesome!

Unfortunately the TattieBogle Xbox 360 Driver doesn't allow devices to work with Apple's Game Controller Framework:

It is important to note that this driver does not work, and can never work, with Apple's "Game Controller Framework." This GCController framework corresponds to physical gamepads that have been offically reviewed by Apple and accepted into the mFi program. Due to the fact that we are not Microsoft, we cannot get their gamepad certified to be a GCController. This is an unfortunate oversight on Apple's part. If you would like to discuss this, please do so at this location.

I haven't tested this first hand yet - but I assume it's correct.

Interestingly, it looks like CCController got around this problem, at least initially, by:

using gamepad snapshots it's easy to trick GameController.framework into supporting them

However:

It seems there is a fatal bug in [GCControllerSnapshot snapshotData] that prevents them from being used on OS X 10.11. Until Apple fixes it, this library can only be used on 10.9 or 10.10.

Sadly the project hasn't been updated for 4 years, so I assume that's still the case. I've posted an issue here asking the question.

I've also tried running the code but it errors out on:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x68) IOHIDElementSetProperty(element, CFSTR(kIOHIDElementCalibrationMinKey), (__bridge CFTypeRef)@(dmin));

2020-05-23 11:17:51.765035+1000 ControllerTest[22774:977975] Warning. Oops, didn't find exactly one axis? (lldb)

The easiest option for Hammerspoon would probably just to add an extension for the official Apple Game Controller Framework, and just add a note that the Sony DualShock 4 and Bluetooth-based Xbox controllers are only supported in Catalina and above.

However, as I don't really want to update my main system to Catalina any time soon, I'd still love to find a solution for Mojave users.

The TattieBogle Xbox 360 Driver seems to work fine as a driver - and it's especially cool that it even works in HTML5 - so this seems like a decent workaround.

Basically what I think we need to do is support both the official Apple Game Controller Framework (which supports various MFi devices depending on what version of macOS you're running) as well as controllers originated from IOKit HID (which seem to be commonly referred to as "gamepad" controllers).

Ouzel, game engine mainly targeted for development of 2D games, seems to be doing exactly that in C++. I know very little about C++, but the code seems relatively simple.

This example code on Stack Overflow also looks fairly straight forward. It also looks like it might be from Sam McCall who worked on Enjoyable - which code also looks fairly straight forward.

Long story short... next step for me is to have a proper look at the Enjoyable source code, as it doesn't look crazy complex - and it's currently doing what I want it to.

I've forked Enjoyable here for anyone who's interested.

In the end, it might be easier to create two extensions, hs.gamepad (for IOKit) and hs.gamecontroller (for the Apple Game Controller Framework) - but we'll see how we go.

latenitefilms commented 4 years ago

I also just re-discovered hs._asm.iokit - very handy for doing some digging in IOKit.

latenitefilms commented 4 years ago

Note to self:

Alternative for HID API to implement Game controller for MacOS application?

latenitefilms commented 4 years ago

I've decided, at least initially, to just focus on Gamepad support (via IOKit).

If/when I eventually move to Catalina, I'll look into Apple's Game Controller Framework in more detail.

My basic plan is to base this new extension off hs.streamdeck, and take inspiration from Enjoyable for the controller logic.

I've started throwing together an extension here for anyone who wants to follow along.

@cmsj - Now that I have a newborn and a toddler, I'm not sure how much free time I'll have over the coming weeks to work on this - so if you get bored/inspired, feel free to play around yourself.

gingerbeardman commented 1 year ago

I just tested a couple of gamepads on my Mac:

They both report their button presses in a standard HID Input Report.

This particular Playstation adapter is odd because it reports two controllers so in WebHID Explorer the states alternate as it has no way to see the report of a single, specific report id.

Anyway, I think gamepads are yet other case for watching and reacting to HID Input Report #3392

andreyvit commented 11 months ago

Hey, has anyone made any progress on this? I want to use a multi-button USB joystick to control HS. I've built a binary of hs._asm.iokit but figuring out how to interface with a joystick is beyond the time I can invest right now. :(

latenitefilms commented 11 months ago

What device do you have exactly? Does it work natively in macOS using the Game Controller Framework, or is it a classic "gamepad" device that works with Enjoyable?

I'm still interested in this issue, but haven't worked on it in a long while.

andreyvit commented 11 months ago

@latenitefilms In my case, it's just a giant joystick with like 15 buttons. It works with classic joystick-supporting apps, presumably including Enjoyable. Not sure if Game Controller Framework is gonna cover it, haven't watched those WWDC vids.