diff --git a/Limelight/Input/ControllerSupport.h b/Limelight/Input/ControllerSupport.h index d6432f8..94476ee 100644 --- a/Limelight/Input/ControllerSupport.h +++ b/Limelight/Input/ControllerSupport.h @@ -34,6 +34,8 @@ -(void) updateFinished:(Controller*)controller; -(Controller*) getOscController; ++(int) getConnectedGamepadMask; + @property (nonatomic, strong) id connectObserver; @property (nonatomic, strong) id disconnectObserver; diff --git a/Limelight/Input/ControllerSupport.m b/Limelight/Input/ControllerSupport.m index 186e601..12d9103 100644 --- a/Limelight/Input/ControllerSupport.m +++ b/Limelight/Input/ControllerSupport.m @@ -8,6 +8,7 @@ #import "ControllerSupport.h" #import "OnScreenControls.h" +#import "DataManager.h" #include "Limelight.h" // Swift @@ -21,6 +22,7 @@ NSMutableDictionary *_controllers; OnScreenControls *_osc; + bool _oscEnabled; // This controller object is shared between on-screen controls // and player 0 @@ -147,7 +149,7 @@ [_controllerStreamLock lock]; @synchronized(controller) { // Player 1 is always present for OSC - LiSendMultiControllerEvent(controller.playerIndex, _controllerNumbers | 1, controller.lastButtonFlags, controller.lastLeftTrigger, controller.lastRightTrigger, controller.lastLeftStickX, controller.lastLeftStickY, controller.lastRightStickX, controller.lastRightStickY); + LiSendMultiControllerEvent(controller.playerIndex, _controllerNumbers | (_oscEnabled ? 1 : 0), controller.lastButtonFlags, controller.lastLeftTrigger, controller.lastRightTrigger, controller.lastLeftStickX, controller.lastLeftStickY, controller.lastRightStickX, controller.lastRightStickY); } [_controllerStreamLock unlock]; } @@ -303,6 +305,25 @@ return _player0osc; } ++(int) getConnectedGamepadMask { + int mask = 0; + + for (int i = 0; i < [[GCController controllers] count]; i++) { + mask |= 1 << i; + } + + DataManager* dataMan = [[DataManager alloc] init]; + OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan getSettings].onscreenControls integerValue]; + + // Even if no gamepads are present, we will always count one + // if OSC is enabled. + if (level != OnScreenControlsLevelOff) { + mask |= 1; + } + + return mask; +} + -(id) init { self = [super init]; @@ -313,6 +334,9 @@ _player0osc = [[Controller alloc] init]; _player0osc.playerIndex = 0; + DataManager* dataMan = [[DataManager alloc] init]; + _oscEnabled = (OnScreenControlsLevel)[[dataMan getSettings].onscreenControls integerValue] != OnScreenControlsLevelOff; + Log(LOG_I, @"Number of controllers connected: %ld", (long)[[GCController controllers] count]); for (GCController* controller in [GCController controllers]) { [self assignController:controller]; @@ -337,10 +361,13 @@ GCController* controller = note.object; [self unregisterControllerCallbacks:controller]; - [_controllers removeObjectForKey:[NSNumber numberWithInteger:controller.playerIndex]]; _controllerNumbers &= ~(1 << controller.playerIndex); Log(LOG_I, @"Unassigning controller index: %ld", (long)controller.playerIndex); + // Inform the server of the updated active gamepads before removing this controller + [self updateFinished:[_controllers objectForKey:[NSNumber numberWithInteger:controller.playerIndex]]]; + [_controllers removeObjectForKey:[NSNumber numberWithInteger:controller.playerIndex]]; + // Re-evaluate the on-screen control mode [self updateAutoOnScreenControlMode]; }]; diff --git a/Limelight/Network/HttpManager.h b/Limelight/Network/HttpManager.h index 97caaaa..1a5f198 100644 --- a/Limelight/Network/HttpManager.h +++ b/Limelight/Network/HttpManager.h @@ -22,7 +22,7 @@ - (NSURLRequest*) newAppListRequest; - (NSURLRequest*) newServerInfoRequest; - (NSURLRequest*) newHttpServerInfoRequest; -- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid; +- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid gamepadMask:(int)gamepadMask; - (NSURLRequest*) newResumeRequestWithRiKey:(NSString*)riKey riKeyId:(int)riKeyId; - (NSURLRequest*) newQuitAppRequest; - (NSURLRequest*) newAppAssetRequestWithAppId:(NSString*)appId; diff --git a/Limelight/Network/HttpManager.m b/Limelight/Network/HttpManager.m index 181fac0..945bc6b 100644 --- a/Limelight/Network/HttpManager.m +++ b/Limelight/Network/HttpManager.m @@ -167,8 +167,8 @@ static const NSString* HTTPS_PORT = @"47984"; return [self createRequestFromString:urlString enableTimeout:TRUE]; } -- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid { - NSString* urlString = [NSString stringWithFormat:@"%@/launch?uniqueid=%@&appid=%@&mode=%dx%dx%d&additionalStates=1&sops=1&rikey=%@&rikeyid=%d", _baseHTTPSURL, _uniqueId, appId, width, height, refreshRate, rikey, rikeyid]; +- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid gamepadMask:(int)gamepadMask { + NSString* urlString = [NSString stringWithFormat:@"%@/launch?uniqueid=%@&appid=%@&mode=%dx%dx%d&additionalStates=1&sops=1&rikey=%@&rikeyid=%d&remoteControllersBitmap=%d&gcmap=%d", _baseHTTPSURL, _uniqueId, appId, width, height, refreshRate, rikey, rikeyid, gamepadMask, gamepadMask]; // This blocks while the app is launching return [self createRequestFromString:urlString enableTimeout:FALSE]; } diff --git a/Limelight/Stream/StreamConfiguration.h b/Limelight/Stream/StreamConfiguration.h index 7ce1ba4..3d9c611 100644 --- a/Limelight/Stream/StreamConfiguration.h +++ b/Limelight/Stream/StreamConfiguration.h @@ -20,5 +20,6 @@ @property int bitRate; @property int riKeyId; @property NSData* riKey; +@property int gamepadMask; @end diff --git a/Limelight/Stream/StreamConfiguration.m b/Limelight/Stream/StreamConfiguration.m index e463739..a9e4a44 100644 --- a/Limelight/Stream/StreamConfiguration.m +++ b/Limelight/Stream/StreamConfiguration.m @@ -9,5 +9,5 @@ #import "StreamConfiguration.h" @implementation StreamConfiguration -@synthesize host, appID, width, height, frameRate, bitRate, riKeyId, riKey; +@synthesize host, appID, width, height, frameRate, bitRate, riKeyId, riKey, gamepadMask; @end diff --git a/Limelight/Stream/StreamManager.m b/Limelight/Stream/StreamManager.m index f3d7d15..455e6ff 100644 --- a/Limelight/Stream/StreamManager.m +++ b/Limelight/Stream/StreamManager.m @@ -106,7 +106,8 @@ height:_config.height refreshRate:_config.frameRate rikey:[Utils bytesToHex:_config.riKey] - rikeyid:_config.riKeyId]]]; + rikeyid:_config.riKeyId + gamepadMask:_config.gamepadMask]]]; NSString *gameSession = [launchResp getStringTag:@"gamesession"]; if (launchResp == NULL || ![launchResp isStatusOk]) { [_callbacks launchFailed:@"Failed to launch app"]; diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index 12c89fd..a8aa7ee 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -408,6 +408,7 @@ static NSMutableSet* hostList; _streamConfig.bitRate = [streamSettings.bitrate intValue]; _streamConfig.height = [streamSettings.height intValue]; _streamConfig.width = [streamSettings.width intValue]; + _streamConfig.gamepadMask = [ControllerSupport getConnectedGamepadMask]; [_appManager stopRetrieving];