Add rumble support

This commit is contained in:
Cameron Gutman
2019-02-11 19:22:18 -08:00
parent 918e1248f2
commit 335b5aef1f
8 changed files with 79 additions and 2 deletions

View File

@@ -20,5 +20,7 @@
@property (nonatomic) short lastLeftStickY;
@property (nonatomic) short lastRightStickX;
@property (nonatomic) short lastRightStickY;
@property (nonatomic) unsigned short lowFreqMotor;
@property (nonatomic) unsigned short highFreqMotor;
@end

View File

@@ -42,6 +42,8 @@
-(void) updateFinished:(Controller*)controller;
-(void) rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor;
+(int) getConnectedGamepadMask:(StreamConfiguration*)streamConfig;
@property (nonatomic, strong) id connectObserver;

View File

@@ -19,10 +19,12 @@
#include "Limelight.h"
@import GameController;
@import AudioToolbox;
@implementation ControllerSupport {
NSLock *_controllerStreamLock;
NSMutableDictionary *_controllers;
NSTimer *_rumbleTimer;
OnScreenControls *_osc;
@@ -42,6 +44,38 @@
#define UPDATE_BUTTON_FLAG(controller, x, y) \
((y) ? [self setButtonFlag:controller flags:x] : [self clearButtonFlag:controller flags:x])
-(void) rumbleController: (Controller*)controller
{
// Only vibrate if the amplitude is large enough
if (controller.lowFreqMotor > 0x5000 || controller.highFreqMotor > 0x5000) {
// If the gamepad is nil (on-screen controls) or it's attached to the device,
// then vibrate the device itself
if (controller.gamepad == nil || [controller.gamepad isAttachedToDevice]) {
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
}
}
}
-(void) rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor
{
Controller* controller = [_controllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
if (controller == nil && controllerNumber == 0 && _oscEnabled) {
// No physical controller, but we have on-screen controls
controller = _player0osc;
}
if (controller == nil) {
// No connected controller for this player
return;
}
// Update the motor levels for the rumble timer to grab next iteration
controller.lowFreqMotor = lowFreqMotor;
controller.highFreqMotor = highFreqMotor;
// Rumble now to ensure short vibrations aren't missed
[self rumbleController:controller];
}
-(void) updateLeftStick:(Controller*)controller x:(short)x y:(short)y
{
@synchronized(controller) {
@@ -412,6 +446,23 @@
return mask;
}
-(void) rumbleTimer
{
for (int i = 0; i < 4; i++) {
Controller* controller = [_controllers objectForKey:[NSNumber numberWithInteger:i]];
if (controller == nil && i == 0 && _oscEnabled) {
// No physical controller, but we have on-screen controls
controller = _player0osc;
}
if (controller == nil) {
// No connected controller for this player
continue;
}
[self rumbleController:controller];
}
}
-(id) initWithConfig:(StreamConfiguration*)streamConfig
{
self = [super init];
@@ -433,6 +484,12 @@
Gamepad_detectDevices();
#endif
_rumbleTimer = [NSTimer scheduledTimerWithTimeInterval:0.20
target:self
selector:@selector(rumbleTimer)
userInfo:nil
repeats:YES];
Log(LOG_I, @"Number of supported controllers connected: %d", [ControllerSupport getGamepadCount]);
Log(LOG_I, @"Multi-controller: %d", _multiController);
@@ -492,6 +549,8 @@
-(void) cleanup
{
[_rumbleTimer invalidate];
_rumbleTimer = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self.connectObserver];
[[NSNotificationCenter defaultCenter] removeObserver:self.disconnectObserver];
[_controllers removeAllObjects];

View File

@@ -19,6 +19,7 @@
- (void) launchFailed:(NSString*)message;
- (void) displayMessage:(const char*)message;
- (void) displayTransientMessage:(const char*)message;
- (void) rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor;
@end

View File

@@ -243,6 +243,11 @@ void ClLogMessage(const char* format, ...)
va_end(va);
}
void ClRumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor)
{
[_callbacks rumble:controllerNumber lowFreqMotor:lowFreqMotor highFreqMotor:highFreqMotor];
}
-(void) terminate
{
// Interrupt any action blocking LiStartConnection(). This is
@@ -375,6 +380,7 @@ void ClLogMessage(const char* format, ...)
_clCallbacks.displayMessage = ClDisplayMessage;
_clCallbacks.displayTransientMessage = ClDisplayTransientMessage;
_clCallbacks.logMessage = ClLogMessage;
_clCallbacks.rumble = ClRumble;
return self;
}

View File

@@ -263,6 +263,12 @@
Log(LOG_I, @"Display transient message: %s", message);
}
- (void)rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor {
Log(LOG_I, @"Rumble on gamepad %d: %04x %04x", controllerNumber, lowFreqMotor, highFreqMotor);
[_controllerSupport rumble:controllerNumber lowFreqMotor:lowFreqMotor highFreqMotor:highFreqMotor];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];

View File

@@ -18,6 +18,7 @@
9865DC3E21332D660005B9B9 /* MainFrameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89462519F646E200339C8A /* MainFrameViewController.m */; };
9890CF6B203B7EE1006C4B06 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9890CF6A203B7EE1006C4B06 /* libxml2.tbd */; };
9897B6A1221260EF00966419 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 9897B6A0221260EF00966419 /* Controller.m */; };
9897B6A62212732C00966419 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 9897B6A0221260EF00966419 /* Controller.m */; };
98CFB82F1CAD481B0048EF74 /* libmoonlight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98AB2E841CAD46840089BB98 /* libmoonlight-common.a */; };
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */; };
98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */; };
@@ -1008,6 +1009,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9897B6A62212732C00966419 /* Controller.m in Sources */,
9865DC3E21332D660005B9B9 /* MainFrameViewController.m in Sources */,
9865DC36213287F30005B9B9 /* AppDelegate.m in Sources */,
FB1A6819213284FB00507771 /* UIComputerView.m in Sources */,
@@ -1022,7 +1024,6 @@
FB1A67E02132460A00507771 /* Logger.m in Sources */,
FB1A67D52132460400507771 /* ControllerSupport.m in Sources */,
FB1A67D82132460400507771 /* StreamView.m in Sources */,
9897B6A2221260EF00966419 /* Controller.m in Sources */,
FB1A67DA2132460400507771 /* OnScreenControls.m in Sources */,
FB1A67DC2132460400507771 /* KeyboardSupport.m in Sources */,
FB1A67CD213245F800507771 /* DataManager.m in Sources */,