Merge branch 'master' of github.com:limelight-stream/limelight-ios

# By Cameron Gutman
# Via Cameron Gutman
* 'master' of github.com:limelight-stream/limelight-ios:
  Add support for game controllers
This commit is contained in:
Diego Waxemberg
2014-10-20 21:26:24 -04:00
4 changed files with 153 additions and 1 deletions

View 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

View 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

View File

@@ -11,12 +11,15 @@
#import "Connection.h"
#import "VideoDecoderRenderer.h"
#import "StreamManager.h"
#import "ControllerSupport.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@implementation StreamFrameViewController
@implementation StreamFrameViewController {
ControllerSupport *_controllerSupport;
}
- (void)viewDidLoad
{
@@ -24,6 +27,8 @@
[UIApplication sharedApplication].idleTimerDisabled = YES;
_controllerSupport = [[ControllerSupport alloc] init];
StreamManager* streamMan = [[StreamManager alloc] initWithConfig:[MainFrameViewController getStreamConfiguration] renderView:self.view];
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation:streamMan];