mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2025-07-22 12:13:35 +00:00
Add support for game controllers
This commit is contained in:
parent
37428c8c77
commit
f2ae32c45c
@ -11,6 +11,7 @@
|
|||||||
98A03B4D19F352EB00861ACA /* liblimelight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98A03B4A19F3514B00861ACA /* liblimelight-common.a */; };
|
98A03B4D19F352EB00861ACA /* liblimelight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98A03B4A19F3514B00861ACA /* liblimelight-common.a */; };
|
||||||
98A03B5019F3598400861ACA /* VideoDecoderRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 98A03B4F19F3598400861ACA /* VideoDecoderRenderer.m */; };
|
98A03B5019F3598400861ACA /* VideoDecoderRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 98A03B4F19F3598400861ACA /* VideoDecoderRenderer.m */; };
|
||||||
98A03B5119F35AAC00861ACA /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FBCC0E9819EF9703009729EB /* libcrypto.a */; };
|
98A03B5119F35AAC00861ACA /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FBCC0E9819EF9703009729EB /* libcrypto.a */; };
|
||||||
|
98B175B419F5DAFC00DA2AED /* ControllerSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 98B175B319F5DAFC00DA2AED /* ControllerSupport.m */; };
|
||||||
FB290CF219B2C406004C83CF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF119B2C406004C83CF /* Foundation.framework */; };
|
FB290CF219B2C406004C83CF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF119B2C406004C83CF /* Foundation.framework */; };
|
||||||
FB290CF419B2C406004C83CF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF319B2C406004C83CF /* CoreGraphics.framework */; };
|
FB290CF419B2C406004C83CF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF319B2C406004C83CF /* CoreGraphics.framework */; };
|
||||||
FB290CF619B2C406004C83CF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF519B2C406004C83CF /* UIKit.framework */; };
|
FB290CF619B2C406004C83CF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF519B2C406004C83CF /* UIKit.framework */; };
|
||||||
@ -85,6 +86,8 @@
|
|||||||
98A03B4519F3514B00861ACA /* limelight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "limelight-common.xcodeproj"; path = "limelight-common-c/limelight-common.xcodeproj"; sourceTree = "<group>"; };
|
98A03B4519F3514B00861ACA /* limelight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "limelight-common.xcodeproj"; path = "limelight-common-c/limelight-common.xcodeproj"; sourceTree = "<group>"; };
|
||||||
98A03B4E19F3598400861ACA /* VideoDecoderRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VideoDecoderRenderer.h; path = Limelight/VideoDecoderRenderer.h; sourceTree = SOURCE_ROOT; };
|
98A03B4E19F3598400861ACA /* VideoDecoderRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VideoDecoderRenderer.h; path = Limelight/VideoDecoderRenderer.h; sourceTree = SOURCE_ROOT; };
|
||||||
98A03B4F19F3598400861ACA /* VideoDecoderRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VideoDecoderRenderer.m; path = Limelight/VideoDecoderRenderer.m; sourceTree = SOURCE_ROOT; };
|
98A03B4F19F3598400861ACA /* VideoDecoderRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VideoDecoderRenderer.m; path = Limelight/VideoDecoderRenderer.m; sourceTree = SOURCE_ROOT; };
|
||||||
|
98B175B219F5DAFC00DA2AED /* ControllerSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControllerSupport.h; sourceTree = "<group>"; };
|
||||||
|
98B175B319F5DAFC00DA2AED /* ControllerSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ControllerSupport.m; sourceTree = "<group>"; };
|
||||||
FB290CEE19B2C406004C83CF /* Limelight.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Limelight.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
FB290CEE19B2C406004C83CF /* Limelight.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Limelight.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
FB290CF119B2C406004C83CF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
FB290CF119B2C406004C83CF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||||
FB290CF319B2C406004C83CF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
FB290CF319B2C406004C83CF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||||
@ -337,6 +340,8 @@
|
|||||||
FB8945EE19F5C3CD00339C8A /* Utils.m */,
|
FB8945EE19F5C3CD00339C8A /* Utils.m */,
|
||||||
FB8945F019F5C76C00339C8A /* StreamConfiguration.h */,
|
FB8945F019F5C76C00339C8A /* StreamConfiguration.h */,
|
||||||
FB8945F119F5C76C00339C8A /* StreamConfiguration.m */,
|
FB8945F119F5C76C00339C8A /* StreamConfiguration.m */,
|
||||||
|
98B175B219F5DAFC00DA2AED /* ControllerSupport.h */,
|
||||||
|
98B175B319F5DAFC00DA2AED /* ControllerSupport.m */,
|
||||||
);
|
);
|
||||||
path = Limelight;
|
path = Limelight;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -705,6 +710,7 @@
|
|||||||
FB290D0419B2C406004C83CF /* AppDelegate.m in Sources */,
|
FB290D0419B2C406004C83CF /* AppDelegate.m in Sources */,
|
||||||
FBAB29F619EDE0F800929691 /* Computer.m in Sources */,
|
FBAB29F619EDE0F800929691 /* Computer.m in Sources */,
|
||||||
FB290D3A19B2C6E3004C83CF /* StreamFrameViewController.m in Sources */,
|
FB290D3A19B2C6E3004C83CF /* StreamFrameViewController.m in Sources */,
|
||||||
|
98B175B419F5DAFC00DA2AED /* ControllerSupport.m in Sources */,
|
||||||
FB290D0019B2C406004C83CF /* main.m in Sources */,
|
FB290D0019B2C406004C83CF /* main.m in Sources */,
|
||||||
FB8945F219F5C76C00339C8A /* StreamConfiguration.m in Sources */,
|
FB8945F219F5C76C00339C8A /* StreamConfiguration.m in Sources */,
|
||||||
FB290D3919B2C6E3004C83CF /* MainFrameViewController.m in Sources */,
|
FB290D3919B2C6E3004C83CF /* MainFrameViewController.m in Sources */,
|
||||||
|
20
Limelight/ControllerSupport.h
Normal file
20
Limelight/ControllerSupport.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// ControllerSupport.h
|
||||||
|
// Limelight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 10/20/14.
|
||||||
|
// Copyright (c) 2014 Limelight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface ControllerSupport : NSObject
|
||||||
|
|
||||||
|
-(id) init;
|
||||||
|
|
||||||
|
-(void) cleanup;
|
||||||
|
|
||||||
|
@property (nonatomic, strong) id connectObserver;
|
||||||
|
@property (nonatomic, strong) id disconnectObserver;
|
||||||
|
|
||||||
|
@end
|
121
Limelight/ControllerSupport.m
Normal file
121
Limelight/ControllerSupport.m
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
//
|
||||||
|
// ControllerSupport.m
|
||||||
|
// Limelight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 10/20/14.
|
||||||
|
// Copyright (c) 2014 Limelight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ControllerSupport.h"
|
||||||
|
#include "Limelight.h"
|
||||||
|
|
||||||
|
@import GameController;
|
||||||
|
|
||||||
|
@implementation ControllerSupport
|
||||||
|
|
||||||
|
// UPDATE_BUTTON(flag, pressed)
|
||||||
|
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
||||||
|
(y) ? (buttonFlags | (x)) : (buttonFlags & ~(x)))
|
||||||
|
|
||||||
|
static NSLock *controllerStreamLock;
|
||||||
|
|
||||||
|
+(void) registerControllerCallbacks
|
||||||
|
{
|
||||||
|
for (int i = 0; i < [[GCController controllers] count]; i++) {
|
||||||
|
GCController *controller = [GCController controllers][i];
|
||||||
|
|
||||||
|
if (controller != NULL) {
|
||||||
|
NSLog(@"Controller connected!");
|
||||||
|
if (controller.extendedGamepad != NULL) {
|
||||||
|
controller.extendedGamepad.valueChangedHandler = ^(GCExtendedGamepad *gamepad, GCControllerElement *element) {
|
||||||
|
short buttonFlags;
|
||||||
|
short leftStickX, leftStickY;
|
||||||
|
short rightStickX, rightStickY;
|
||||||
|
char leftTrigger, rightTrigger;
|
||||||
|
|
||||||
|
UPDATE_BUTTON(A_FLAG, gamepad.buttonA.pressed);
|
||||||
|
UPDATE_BUTTON(B_FLAG, gamepad.buttonB.pressed);
|
||||||
|
UPDATE_BUTTON(X_FLAG, gamepad.buttonX.pressed);
|
||||||
|
UPDATE_BUTTON(Y_FLAG, gamepad.buttonY.pressed);
|
||||||
|
|
||||||
|
UPDATE_BUTTON(UP_FLAG, gamepad.dpad.up.pressed);
|
||||||
|
UPDATE_BUTTON(DOWN_FLAG, gamepad.dpad.down.pressed);
|
||||||
|
UPDATE_BUTTON(LEFT_FLAG, gamepad.dpad.left.pressed);
|
||||||
|
UPDATE_BUTTON(RIGHT_FLAG, gamepad.dpad.right.pressed);
|
||||||
|
|
||||||
|
UPDATE_BUTTON(LB_FLAG, gamepad.leftShoulder.pressed);
|
||||||
|
UPDATE_BUTTON(RB_FLAG, gamepad.rightShoulder.pressed);
|
||||||
|
|
||||||
|
leftStickX = gamepad.leftThumbstick.xAxis.value * 0x7FFE;
|
||||||
|
leftStickY = gamepad.leftThumbstick.yAxis.value * 0x7FFE;
|
||||||
|
|
||||||
|
rightStickX = gamepad.rightThumbstick.xAxis.value * 0x7FFE;
|
||||||
|
rightStickY = gamepad.rightThumbstick.yAxis.value * 0x7FFE;
|
||||||
|
|
||||||
|
leftTrigger = gamepad.leftTrigger.value * 0xFF;
|
||||||
|
rightTrigger = gamepad.rightTrigger.value * 0xFF;
|
||||||
|
|
||||||
|
// We call LiSendControllerEvent while holding a lock to prevent
|
||||||
|
// multiple simultaneous calls since this function isn't thread safe.
|
||||||
|
[controllerStreamLock lock];
|
||||||
|
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger,
|
||||||
|
leftStickX, leftStickY, rightStickX, rightStickY);
|
||||||
|
[controllerStreamLock unlock];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (controller.gamepad != NULL) {
|
||||||
|
controller.gamepad.valueChangedHandler = ^(GCGamepad *gamepad, GCControllerElement *element) {
|
||||||
|
short buttonFlags;
|
||||||
|
|
||||||
|
UPDATE_BUTTON(A_FLAG, gamepad.buttonA.pressed);
|
||||||
|
UPDATE_BUTTON(B_FLAG, gamepad.buttonB.pressed);
|
||||||
|
UPDATE_BUTTON(X_FLAG, gamepad.buttonX.pressed);
|
||||||
|
UPDATE_BUTTON(Y_FLAG, gamepad.buttonY.pressed);
|
||||||
|
|
||||||
|
UPDATE_BUTTON(UP_FLAG, gamepad.dpad.up.pressed);
|
||||||
|
UPDATE_BUTTON(DOWN_FLAG, gamepad.dpad.down.pressed);
|
||||||
|
UPDATE_BUTTON(LEFT_FLAG, gamepad.dpad.left.pressed);
|
||||||
|
UPDATE_BUTTON(RIGHT_FLAG, gamepad.dpad.right.pressed);
|
||||||
|
|
||||||
|
UPDATE_BUTTON(LB_FLAG, gamepad.leftShoulder.pressed);
|
||||||
|
UPDATE_BUTTON(RB_FLAG, gamepad.rightShoulder.pressed);
|
||||||
|
|
||||||
|
// We call LiSendControllerEvent while holding a lock to prevent
|
||||||
|
// multiple simultaneous calls since this function isn't thread safe.
|
||||||
|
[controllerStreamLock lock];
|
||||||
|
LiSendControllerEvent(buttonFlags, 0, 0, 0, 0, 0, 0);
|
||||||
|
[controllerStreamLock unlock];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
-(id) init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (controllerStreamLock == NULL) {
|
||||||
|
controllerStreamLock = [[NSLock alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.connectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
|
[ControllerSupport registerControllerCallbacks];
|
||||||
|
}];
|
||||||
|
self.disconnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
|
NSLog(@"Controller disconnected!");
|
||||||
|
}];
|
||||||
|
|
||||||
|
[ControllerSupport registerControllerCallbacks];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) cleanup
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self.connectObserver];
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self.disconnectObserver];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
@ -11,12 +11,15 @@
|
|||||||
#import "Connection.h"
|
#import "Connection.h"
|
||||||
#import "VideoDecoderRenderer.h"
|
#import "VideoDecoderRenderer.h"
|
||||||
#import "StreamManager.h"
|
#import "StreamManager.h"
|
||||||
|
#import "ControllerSupport.h"
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
@implementation StreamFrameViewController
|
@implementation StreamFrameViewController {
|
||||||
|
ControllerSupport *_controllerSupport;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewDidLoad
|
- (void)viewDidLoad
|
||||||
{
|
{
|
||||||
@ -24,6 +27,8 @@
|
|||||||
|
|
||||||
[UIApplication sharedApplication].idleTimerDisabled = YES;
|
[UIApplication sharedApplication].idleTimerDisabled = YES;
|
||||||
|
|
||||||
|
_controllerSupport = [[ControllerSupport alloc] init];
|
||||||
|
|
||||||
StreamManager* streamMan = [[StreamManager alloc] initWithHost:[MainFrameViewController getHost] renderView:self.view];
|
StreamManager* streamMan = [[StreamManager alloc] initWithHost:[MainFrameViewController getHost] renderView:self.view];
|
||||||
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
|
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
|
||||||
[opQueue addOperation:streamMan];
|
[opQueue addOperation:streamMan];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user