diff --git a/Cocoa/Document.m b/Cocoa/Document.m index 90a1dc8..ff47cd9 100644 --- a/Cocoa/Document.m +++ b/Cocoa/Document.m @@ -381,7 +381,7 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) self.view.mouseHidingEnabled = NO; GB_save_battery(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"sav"] UTF8String]); GB_save_cheats(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"cht"] UTF8String]); - [_view setRumble:false]; + [_view setRumble:0]; stopping = false; } diff --git a/Cocoa/GBView.m b/Cocoa/GBView.m index e733731..d342497 100644 --- a/Cocoa/GBView.m +++ b/Cocoa/GBView.m @@ -116,6 +116,7 @@ } [[NSNotificationCenter defaultCenter] removeObserver:self]; [lastController setRumbleAmplitude:0]; + [lastController _forceStopPWMThread]; [JOYController unregisterListener:self]; } - (instancetype)initWithCoder:(NSCoder *)coder @@ -302,6 +303,7 @@ if (![self.window isMainWindow]) return; if (controller != lastController) { [lastController setRumbleAmplitude:0]; + [lastController _forceStopPWMThread]; lastController = controller; } diff --git a/JoyKit/JOYController.h b/JoyKit/JOYController.h index 9ed7cf7..9363e36 100644 --- a/JoyKit/JOYController.h +++ b/JoyKit/JOYController.h @@ -35,6 +35,7 @@ static NSString const *JOYHatsEmulateButtonsKey = @"JOYHatsEmulateButtons"; - (NSArray *) hats; - (void)setRumbleAmplitude:(double)amp; - (void)setPlayerLEDs:(uint8_t)mask; +- (void)_forceStopPWMThread; // Hack @property (readonly, getter=isConnected) bool connected; @end diff --git a/JoyKit/JOYController.m b/JoyKit/JOYController.m index f9f0775..0268054 100644 --- a/JoyKit/JOYController.m +++ b/JoyKit/JOYController.m @@ -118,6 +118,7 @@ typedef struct __attribute__((packed)) { bool _physicallyConnected; bool _logicallyConnected; bool _rumblePWMThreadRunning; + volatile bool _forceStopPWMThread; } - (instancetype)initWithDevice:(IOHIDDeviceRef) device @@ -608,7 +609,7 @@ typedef struct __attribute__((packed)) { /* TODO: This does not handle correctly the case of having a multi-port controller where more than one controller uses rumble. */ unsigned rumbleCounter = 0; - while (self.connected) { + while (self.connected && !_forceStopPWMThread) { if ([_rumbleElement setValue:rumbleCounter < round(_rumblePWMRatio * PWM_RESOLUTION)]) { break; } @@ -619,6 +620,7 @@ typedef struct __attribute__((packed)) { } [_rumblePWMThreadLock lock]; _rumblePWMThreadRunning = false; + _forceStopPWMThread = false; [_rumblePWMThreadLock unlock]; } @@ -688,6 +690,15 @@ typedef struct __attribute__((packed)) { return _logicallyConnected && _physicallyConnected; } +- (void)_forceStopPWMThread +{ + [_rumblePWMThreadLock lock]; + if (_rumblePWMThreadRunning) { + _forceStopPWMThread = true; + } + [_rumblePWMThreadLock unlock]; +} + + (void)controllerAdded:(IOHIDDeviceRef) device { NSString *name = (__bridge NSString *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));