robreuss / VirtualGameController

Software-based game controllers for iOS, tvOS, OS X and watchOS in Swift 4.2.
MIT License
462 stars 44 forks source link

dpad.valueChangedHandler not called after reconnect #33

Closed Megatron1000 closed 5 years ago

Megatron1000 commented 6 years ago

I'm getting nothing back on my dpad.valueChangedHandler after my controller gets reconnected.

I'm using the library with an Apple TV app and I'm testing it with the built in iOS 11 iPhone's Apple TV Remote App. Everytime the Apple TV Remote app is closed it loses its connection, as expected, but every subsequent connect fails to work. It successfully connects but nothing comes through on the dpad.valueChangedHandler. Restarting the app is the only thing that solves the issue.

I'm using the 0.0.19 release.

The logs look like this.

[VGC] Setting up as a CENTRAL [VGC] IncludesPeerToPeer is set to: true [VGC] Initializing Central Publisher [VGC] Publishing NetService service to listen for Peripherals on Apple TV [VGC] Service bonjour domain is local, type is _geekquiz_central._tcp., name is Apple TV [VGC] NetService will be published [VGC] Central is now published on: local._geekquiz_central._tcp.Apple TV [VGC] Initializing new Controller [VGC] Adding hardware controller Remote [VGC] Profile type set to: MicroGamepad [VGC] <<< ERROR[VGC] Device info set on controller [VGC] Confirming controller doesn't already exist among 0 controllers [VGC] Appending controller Remote to vControllers (1 controllers with new controller) [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] Got hardware didDisconnect notification: name = GCControllerDidDisconnectNotification, object = Optional(<GCController 0x1c02b2120 vendorName='Remote' deviceHash=0x137e5b6c0>), userInfo = nil [VGC] Comparing UUID 0x137e5b6c0 to 0x137e5b6c0 [VGC] Removing controller from controllers array: <GCController 0x1c02b2120 vendorName='Remote' deviceHash=0x137e5b6c0> [VGC] Initializing new Controller [VGC] Adding hardware controller Remote [VGC] Profile type set to: MicroGamepad [VGC] <<< ERROR[VGC] Device info set on controller [VGC] Confirming controller doesn't already exist among 0 controllers [VGC] Appending controller Remote to vControllers (1 controllers with new controller) [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] Got hardware didDisconnect notification: name = GCControllerDidDisconnectNotification, object = Optional(<GCController 0x1c42befc0 vendorName='Remote' deviceHash=0x137d6b6a0>), userInfo = nil [VGC] Comparing UUID 0x137d6b6a0 to 0x137d6b6a0 [VGC] Removing controller from controllers array: <GCController 0x1c42befc0 vendorName='Remote' deviceHash=0x137d6b6a0> [VGC] Initializing new Controller [VGC] Adding hardware controller Remote [VGC] Profile type set to: MicroGamepad [VGC] <<< ERROR[VGC] Device info set on controller [VGC] Confirming controller doesn't already exist among 0 controllers [VGC] Appending controller Remote to vControllers (1 controllers with new controller) [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] Got hardware didDisconnect notification: name = GCControllerDidDisconnectNotification, object = Optional(<GCController 0x1c42b7520 vendorName='Remote' deviceHash=0x137d6c190>), userInfo = nil [VGC] Comparing UUID 0x137d6c190 to 0x137d6c190 [VGC] Re[VGC] Initializing new Controller [VGC] Adding hardware controller Remote [VGC] Profile type set to: MicroGamepad [VGC] <<< ERROR[VGC] Device info set on controller [VGC] Confirming controller doesn't already exist among 0 controllers [VGC] Appending controller Remote to vControllers (1 controllers with new controller) [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] nil stream SmallData error caught [VGC] Got hardware didDisconnect notification: name = GCControllerDidDisconnectNotification, object = Optional(<GCController 0x1c02ae5e0 vendorName='Remote' deviceHash=0x137e733e0>), userInfo = nil [VGC] Comparing UUID 0x137e733e0 to 0x137e733e0 [VGC] Re

robreuss commented 6 years ago

Am I correct that the iOS-based Apple TV Remote app simply overlays it's input on the Apple TV hardware remote, so they are represented as a single controller to the Apple TV? And if you use additional iOS-based Apple TV Remote app instances, they all channel through to the same controller? I wonder why Apple did it that way.

Regardless, I got setup and was unable to reproduce the issue. I have a dpad handler setup like so:

        newController.microGamepad?.dpad.xAxis.valueChangedHandler = { (dpad, value) in
            print("HANDLER: DPAD xAxis: \(value)")
        }

Note that the profile needs to be "microGamepad".

I confirm that dpad input is working (it works both from the hardware remote and the iOS Apple TV software remote).

I close the iOS Apple TV Remote app on my iPhone.

Hardware remote still works.

I re-launch the iOS Apple TV Remote app on my iPhone. dpad input works.

Let me know if my steps to reproduce were incorrect.

Megatron1000 commented 6 years ago

Right now I don't actually know where my Apple TV hardware remote is. I'm going to look for it and see if having that connected makes a difference. That little thing's been lost for so long that the battery is dead so the only thing connected to the Apple TV is the app on the phone.

The microgamepad is the profile I'm using and I've logged it out as being non-nil on the reconnect.

robreuss commented 6 years ago

I reviewed some of Apple's documentation on the iOS Remote app and it implies you can have multiple instances running as separate controllers, but I only get one that combines the hardware controller and all iOS-based controllers. Note that if you build a custom controller using VGC, that should provide you with better stability (though I understand the benefit of using Apple's software-based controller).

Megatron1000 commented 6 years ago

So I've tried it and, indeed, having the hardware remote connected seems to prevent this problem happening. It must be something that only happens when there aren't any controllers connected at all.

I've tried to take the physical remote out of range but I wasn't able to get the disconnect call back to fire. Perhaps you don't get that with these remotes. I'd imagine that in order to save on battery they don't keep a continuous connection to the Apple TV.

To clarify my use case. I'm building an app that works both with the hardware remote as the controller and my own app, that uses VirtualGameController, as a software controller. I was just using Apple's Remote App as I can never find my hardware controller, not as a substitute for my own iPhone app.

robreuss commented 6 years ago

Understood. That's the use case I anticipated.