From d55426afa0155be57c75f661299a11a927bc68ad Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Thu, 13 Jun 2024 22:46:02 +0300 Subject: [PATCH] Fix a bug where haptics randomly stop working --- iOS/GBHapticManager.m | 73 ++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/iOS/GBHapticManager.m b/iOS/GBHapticManager.m index b82abebff..300835123 100644 --- a/iOS/GBHapticManager.m +++ b/iOS/GBHapticManager.m @@ -12,6 +12,7 @@ #pragma clang diagnostic pop __weak GCController *_controller; double _rumble; + dispatch_queue_t _queue; } + (instancetype)sharedManager @@ -36,6 +37,7 @@ _engine.autoShutdownEnabled = true; } if (!_engine) return [[GBHapticManagerLegacy alloc] init]; + _queue = dispatch_queue_create("SameBoy Haptic Queue", NULL); return self; } @@ -57,20 +59,22 @@ - (void)doTapHaptic { - if (_rumble) return; + double intensity = [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBHapticsStrength"]; + if (_rumble > intensity) return; - CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:@[[self eventWithType:CHHapticEventTypeHapticTransient - sharpness:0.25 - intensity:[[NSUserDefaults standardUserDefaults] doubleForKey:@"GBHapticsStrength"] - duration:1.0]] - parameters:nil - error:nil]; - @try { - id player = [_engine createPlayerWithPattern:pattern error:nil]; - - [player startAtTime:0 error:nil]; - } - @catch (NSException *exception) {} + dispatch_async(_queue, ^{ + CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:@[[self eventWithType:CHHapticEventTypeHapticTransient + sharpness:0.25 + intensity:intensity + duration:1.0]] + parameters:nil + error:nil]; + @try { + id player = [_engine createPlayerWithPattern:pattern error:nil]; + [player startAtTime:0 error:nil]; + } + @catch (NSException *exception) {} + }); } - (void)setRumbleStrength:(double)rumble @@ -90,27 +94,32 @@ _rumble = 0; return; } + + // No change + if (rumble == _rumble) return; _rumble = rumble; - CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:@[[self eventWithType:CHHapticEventTypeHapticContinuous - sharpness:0.75 - intensity:rumble - duration:1.0]] - parameters:nil - error:nil]; - @try { - id newPlayer = [_externalEngine ?: _engine createPlayerWithPattern:pattern error:nil]; - - [newPlayer startAtTime:0 error:nil]; - [_rumblePlayer stopAtTime:0 error:nil]; - _rumblePlayer = newPlayer; - } - @catch (NSException *exception) { - if (_externalEngine) { - // Something might have happened with our controller? Delete and try again - _externalEngine = nil; - [self setRumbleStrength: rumble]; + + dispatch_async(_queue, ^{ + CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:@[[self eventWithType:CHHapticEventTypeHapticContinuous + sharpness:0.75 + intensity:rumble + duration:1.0]] + parameters:nil + error:nil]; + @try { + id newPlayer = [_externalEngine ?: _engine createPlayerWithPattern:pattern error:nil]; + [newPlayer startAtTime:0 error:nil]; + [_rumblePlayer stopAtTime:0 error:nil]; + _rumblePlayer = newPlayer; } - } + @catch (NSException *exception) { + if (_externalEngine) { + // Something might have happened with our controller? Delete and try again + _externalEngine = nil; + [self setRumbleStrength: rumble]; + } + } + }); } - (void)setController:(GCController *)controller