Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Limelight/Database/DataManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
width:(NSInteger)width
audioConfig:(NSInteger)audioConfig
onscreenControls:(NSInteger)onscreenControls
motionMode:(NSInteger)motionMode
optimizeGames:(BOOL)optimizeGames
multiController:(BOOL)multiController
swapABXYButtons:(BOOL)swapABXYButtons
Expand Down
2 changes: 2 additions & 0 deletions Limelight/Database/DataManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ - (void) saveSettingsWithBitrate:(NSInteger)bitrate
width:(NSInteger)width
audioConfig:(NSInteger)audioConfig
onscreenControls:(NSInteger)onscreenControls
motionMode:(NSInteger)motionMode
optimizeGames:(BOOL)optimizeGames
multiController:(BOOL)multiController
swapABXYButtons:(BOOL)swapABXYButtons
Expand All @@ -77,6 +78,7 @@ - (void) saveSettingsWithBitrate:(NSInteger)bitrate
settingsToSave.width = [NSNumber numberWithInteger:width];
settingsToSave.audioConfig = [NSNumber numberWithInteger:audioConfig];
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
settingsToSave.motionMode = [NSNumber numberWithInteger:motionMode];
settingsToSave.optimizeGames = optimizeGames;
settingsToSave.multiController = multiController;
settingsToSave.swapABXYButtons = swapABXYButtons;
Expand Down
1 change: 1 addition & 0 deletions Limelight/Database/TemporarySettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
@property (nonatomic, retain) NSNumber * width;
@property (nonatomic, retain) NSNumber * audioConfig;
@property (nonatomic, retain) NSNumber * onscreenControls;
@property (nonatomic, retain) NSNumber * motionMode;
@property (nonatomic, retain) NSString * uniqueId;
@property (nonatomic) enum {
CODEC_PREF_AUTO,
Expand Down
1 change: 1 addition & 0 deletions Limelight/Database/TemporarySettings.m
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ - (id) initFromSettings:(Settings*)settings {
self.multiController = settings.multiController;
self.swapABXYButtons = settings.swapABXYButtons;
self.onscreenControls = settings.onscreenControls;
self.motionMode = settings.motionMode;
self.btMouseSupport = settings.btMouseSupport;
self.absoluteTouchMode = settings.absoluteTouchMode;
self.statsOverlay = settings.statsOverlay;
Expand Down
9 changes: 9 additions & 0 deletions Limelight/Input/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

@import GameController;
@import CoreHaptics;
#if !TARGET_OS_TV
@import CoreMotion;
#endif

@interface Controller : NSObject

Expand Down Expand Up @@ -43,6 +46,12 @@ typedef struct {
@property (nonatomic) NSTimer* _Nullable gyroTimer;
@property (nonatomic) GCRotationRate lastGyroSample;

#if !TARGET_OS_TV
@property (nonatomic) CMMotionManager * _Nullable motionManager;
@property (nonatomic) CMAcceleration lastDeviceAccelSample;
@property (nonatomic) CMRotationRate lastDeviceGyroSample;
#endif

@property (nonatomic) NSTimer* _Nullable batteryTimer;
@property (nonatomic) GCDeviceBatteryState lastBatteryState;
@property (nonatomic) float lastBatteryLevel;
Expand Down
118 changes: 110 additions & 8 deletions Limelight/Input/ControllerSupport.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#include "Limelight.h"

@import GameController;
#if !TARGET_OS_TV
@import CoreMotion;
#endif
@import AudioToolbox;

static const double MOUSE_SPEED_DIVISOR = 1.25;
Expand Down Expand Up @@ -46,6 +49,7 @@ @implementation ControllerSupport {
char _controllerNumbers;
bool _multiController;
bool _swapABXYButtons;
int _motionMode;
}

// UPDATE_BUTTON_FLAG(controller, flag, pressed)
Expand Down Expand Up @@ -88,15 +92,108 @@ - (void) setMotionEventState:(uint16_t)controllerNumber motionType:(uint8_t)moti
{
if (@available(iOS 14.0, tvOS 14.0, *)) {
Controller* controller = [_controllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
if (controller == nil) {
// No connected controller for this player
return;
}

if (controller.gamepad.motion == nil) {
// No motion supported for this controller
return;
}
#if !TARGET_OS_TV //tvOS has no device motion
NSInteger motionMode = _motionMode; //motionMode 0 = auto | 1 = always device | 2 = always controller
if(motionMode !=2 && controllerNumber < 2){
if(controller == nil || controller.gamepad.motion == nil || motionMode == 1){
//Player has no controller *or* no motion for controller 1 *or* wants to override controller 1 motion with device motion
//using device motion
if (controller == nil) {
// No connected controller for this player, use the _oscController instead
controller = _oscController;
}
if(!controller.motionManager) {
controller.motionManager = [[CMMotionManager alloc] init];
}

switch (motionType) {
case LI_MOTION_TYPE_ACCEL:
[controller.accelTimer invalidate];
controller.accelTimer = nil;

// Reset the last motion sample
CMAcceleration emptyDeviceAccelSample = {};
controller.lastDeviceAccelSample = emptyDeviceAccelSample;

{dispatch_sync(dispatch_get_main_queue(), ^{
controller.accelTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / reportRateHz repeats:YES block:^(NSTimer *timer) {
// Don't send duplicate samples
CMAcceleration lastDeviceAccelSample = controller.lastDeviceAccelSample;
CMAcceleration deviceAccelSample = controller.motionManager.deviceMotion.userAcceleration;
//userAcceleration does not contain gravity, add gravity to x, y and z values:
deviceAccelSample.x += controller.motionManager.deviceMotion.gravity.x;
deviceAccelSample.y += controller.motionManager.deviceMotion.gravity.y;
deviceAccelSample.z += controller.motionManager.deviceMotion.gravity.z;

if (memcmp(&deviceAccelSample, &lastDeviceAccelSample, sizeof(deviceAccelSample)) == 0) {
return;
}
controller.lastDeviceAccelSample = deviceAccelSample;

// Convert g to m/s^2
if(UIApplication.sharedApplication.windows.firstObject.windowScene.interfaceOrientation == 4){ //check for landscape left or landscape right
LiSendControllerMotionEvent((uint8_t)controllerNumber,
LI_MOTION_TYPE_ACCEL,
deviceAccelSample.y * -9.80665f,
deviceAccelSample.z * -9.80665f,
deviceAccelSample.x * -9.80665f);
}
else{
LiSendControllerMotionEvent((uint8_t)controllerNumber,
LI_MOTION_TYPE_ACCEL,
deviceAccelSample.y * +9.80665f,
deviceAccelSample.z * -9.80665f,
deviceAccelSample.x * +9.80665f);
}
}];
});}
break;
case LI_MOTION_TYPE_GYRO:
[controller.gyroTimer invalidate];
controller.gyroTimer = nil;

// Reset the last motion sample
CMRotationRate emptyDeviceGyroSample = {};
controller.lastDeviceGyroSample = emptyDeviceGyroSample;

[controller.motionManager startDeviceMotionUpdates];

dispatch_sync(dispatch_get_main_queue(), ^{
controller.gyroTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / reportRateHz repeats:YES block:^(NSTimer *timer) {

// Don't send duplicate samples
CMRotationRate lastDeviceGyroSample = controller.lastDeviceGyroSample;
CMRotationRate deviceGyroSample = controller.motionManager.deviceMotion.rotationRate;
if (memcmp(&deviceGyroSample, &lastDeviceGyroSample, sizeof(deviceGyroSample)) == 0) {
return;
}
controller.lastDeviceGyroSample = deviceGyroSample;

// Convert rad/s to deg/s
if(UIApplication.sharedApplication.windows.firstObject.windowScene.interfaceOrientation == 4){//check for landscape left or landscape right
LiSendControllerMotionEvent((uint8_t)controllerNumber,
LI_MOTION_TYPE_GYRO,
deviceGyroSample.y * 57.2957795f,
deviceGyroSample.z * 57.2957795f,
deviceGyroSample.x * 57.2957795f);
}
else{
LiSendControllerMotionEvent((uint8_t)controllerNumber,
LI_MOTION_TYPE_GYRO,
deviceGyroSample.y * -57.2957795f,
deviceGyroSample.z * 57.2957795f,
deviceGyroSample.x * -57.2957795f);
}

}];
});
break;
}
return;
}
}
#endif

switch (motionType) {
case LI_MOTION_TYPE_ACCEL:
Expand Down Expand Up @@ -1082,6 +1179,7 @@ -(id) initWithConfig:(StreamConfiguration*)streamConfig delegate:(id<ControllerS
_controllerNumbers = 0;
_multiController = streamConfig.multiController;
_swapABXYButtons = streamConfig.swapABXYButtons;
_motionMode = streamConfig.motionMode;
_delegate = delegate;

_oscController = [[Controller alloc] init];
Expand Down Expand Up @@ -1256,6 +1354,10 @@ -(void) cleanup
}
[_controllers removeAllObjects];

#if !TARGET_OS_TV
[self cleanupControllerMotion:_oscController];
[_oscController.motionManager stopDeviceMotionUpdates];
#endif
for (GCController* controller in [GCController controllers]) {
if ([ControllerSupport isSupportedGamepad:controller]) {
[self unregisterControllerCallbacks:controller];
Expand Down
3 changes: 3 additions & 0 deletions Limelight/Input/OnScreenControls.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#import "ControllerSupport.h"
#import "Controller.h"
#include "Limelight.h"
#if !TARGET_OS_TV
#import <CoreMotion/CoreMotion.h>
#endif

#define UPDATE_BUTTON(x, y) (buttonFlags = \
(y) ? (buttonFlags | (x)) : (buttonFlags & ~(x)))
Expand Down
2 changes: 2 additions & 0 deletions Limelight/Limelight-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
</array>
<key>NSLocalNetworkUsageDescription</key>
<string>Moonlight uses the local network to connect to your gaming PC for streaming.</string>
<key>NSMotionUsageDescription</key>
<string>Moonlight uses the device Gyro and Acceleration data to emulate motion controls when streaming.</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22225" systemVersion="23A344" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23602" systemVersion="24C5089c" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
<entity name="App" representedClassName="App" syncable="YES" codeGenerationType="class">
<attribute name="hdrSupported" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="hidden" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
Expand Down Expand Up @@ -29,6 +29,7 @@
<attribute name="enableHdr" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="framerate" attributeType="Integer 32" defaultValueString="60" usesScalarValueType="NO" syncable="YES"/>
<attribute name="height" attributeType="Integer 32" defaultValueString="720" usesScalarValueType="NO" syncable="YES"/>
<attribute name="motionMode" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
<attribute name="multiController" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" syncable="YES"/>
<attribute name="onscreenControls" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="NO" syncable="YES"/>
<attribute name="optimizeGames" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" syncable="YES"/>
Expand Down
1 change: 1 addition & 0 deletions Limelight/Stream/StreamConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@property BOOL optimizeGameSettings;
@property BOOL playAudioOnPC;
@property BOOL swapABXYButtons;
@property int motionMode;
@property int audioConfiguration;
@property int supportedVideoFormats;
@property BOOL multiController;
Expand Down
2 changes: 1 addition & 1 deletion Limelight/Stream/StreamConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
#import "StreamConfiguration.h"

@implementation StreamConfiguration
@synthesize host, httpsPort, appID, width, height, frameRate, bitRate, riKeyId, riKey, gamepadMask, appName, optimizeGameSettings, playAudioOnPC, swapABXYButtons, audioConfiguration, supportedVideoFormats, multiController, serverCert, rtspSessionUrl, serverCodecModeSupport;
@synthesize host, httpsPort, appID, width, height, frameRate, bitRate, riKeyId, riKey, gamepadMask, appName, optimizeGameSettings, playAudioOnPC, swapABXYButtons, motionMode, audioConfiguration, supportedVideoFormats, multiController, serverCert, rtspSessionUrl, serverCodecModeSupport;
@end
1 change: 1 addition & 0 deletions Limelight/ViewControllers/MainFrameViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ - (void) prepareToStreamApp:(TemporaryApp *)app {
_streamConfig.playAudioOnPC = streamSettings.playAudioOnPC;
_streamConfig.useFramePacing = streamSettings.useFramePacing;
_streamConfig.swapABXYButtons = streamSettings.swapABXYButtons;
_streamConfig.motionMode = [streamSettings.motionMode intValue];

// multiController must be set before calling getConnectedGamepadMask
_streamConfig.multiController = streamSettings.multiController;
Expand Down
1 change: 1 addition & 0 deletions Limelight/ViewControllers/SettingsViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
@property (strong, nonatomic) IBOutlet UIView *resolutionDisplayView;
@property (strong, nonatomic) IBOutlet UISegmentedControl *touchModeSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *onscreenControlSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *motionModeSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *optimizeSettingsSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *multiControllerSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *swapABXYButtonsSelector;
Expand Down
4 changes: 4 additions & 0 deletions Limelight/ViewControllers/SettingsViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ - (void)viewDidLoad {
[self.framerateSelector addTarget:self action:@selector(updateBitrate) forControlEvents:UIControlEventValueChanged];
[self.onscreenControlSelector setSelectedSegmentIndex:onscreenControls];
[self.onscreenControlSelector setEnabled:!currentSettings.absoluteTouchMode];
NSInteger motionMode = [currentSettings.motionMode integerValue];
[self.motionModeSelector setSelectedSegmentIndex:motionMode];
[self.bitrateSlider setMinimumValue:0];
[self.bitrateSlider setMaximumValue:(sizeof(bitrateTable) / sizeof(*bitrateTable)) - 1];
[self.bitrateSlider setValue:[self getSliderValueForBitrate:_bitrate] animated:YES];
Expand Down Expand Up @@ -528,6 +530,7 @@ - (void) saveSettings {
NSInteger height = [self getChosenStreamHeight];
NSInteger width = [self getChosenStreamWidth];
NSInteger onscreenControls = [self.onscreenControlSelector selectedSegmentIndex];
NSInteger motionMode = [self.motionModeSelector selectedSegmentIndex];
BOOL optimizeGames = [self.optimizeSettingsSelector selectedSegmentIndex] == 1;
BOOL multiController = [self.multiControllerSelector selectedSegmentIndex] == 1;
BOOL swapABXYButtons = [self.swapABXYButtonsSelector selectedSegmentIndex] == 1;
Expand All @@ -544,6 +547,7 @@ - (void) saveSettings {
width:width
audioConfig:2 // Stereo
onscreenControls:onscreenControls
motionMode:motionMode
optimizeGames:optimizeGames
multiController:multiController
swapABXYButtons:swapABXYButtons
Expand Down
Loading