diff --git a/Limelight/Input/ControllerSupport.h b/Limelight/Input/ControllerSupport.h index fffd79f..cf7b38c 100644 --- a/Limelight/Input/ControllerSupport.h +++ b/Limelight/Input/ControllerSupport.h @@ -8,12 +8,27 @@ #import +@class OnScreenControls; + @interface ControllerSupport : NSObject -(id) init; - +-(void) initAutoOnScreenControlMode:(OnScreenControls*)osc; -(void) cleanup; +-(void) updateLeftStick:(short)x y:(short)y; +-(void) updateRightStick:(short)x y:(short)y; + +-(void) updateLeftTrigger:(char)left; +-(void) updateRightTrigger:(char)right; +-(void) updateTriggers:(char)left right:(char)right; + +-(void) updateButtonFlags:(int)flags; +-(void) setButtonFlag:(int)flags; +-(void) clearButtonFlag:(int)flags; + +-(void) updateFinished; + @property (nonatomic, strong) id connectObserver; @property (nonatomic, strong) id disconnectObserver; diff --git a/Limelight/Input/ControllerSupport.m b/Limelight/Input/ControllerSupport.m index cdf1f3d..337daab 100644 --- a/Limelight/Input/ControllerSupport.m +++ b/Limelight/Input/ControllerSupport.m @@ -7,19 +7,166 @@ // #import "ControllerSupport.h" +#import "OnScreenControls.h" #include "Limelight.h" @import GameController; -@implementation ControllerSupport +@implementation ControllerSupport { + NSLock *_controllerValueLock; + NSLock *_controllerStreamLock; + + OnScreenControls *_osc; + + int _lastButtonFlags; + char _lastLeftTrigger, _lastRightTrigger; + short _lastLeftStickX, _lastLeftStickY; + short _lastRightStickX, _lastRightStickY; + +#define EMULATING_SELECT 0x1 +#define EMULATING_SPECIAL 0x2 + int _emulatingButtonFlags; +} // UPDATE_BUTTON(flag, pressed) #define UPDATE_BUTTON(x, y) (buttonFlags = \ (y) ? (buttonFlags | (x)) : (buttonFlags & ~(x))) -static NSLock *controllerStreamLock; +-(void) updateLeftStick:(short)x y:(short)y +{ + [_controllerValueLock lock]; + _lastLeftStickX = x; + _lastLeftStickY = y; + [_controllerValueLock unlock]; +} -+(void) registerControllerCallbacks +-(void) updateRightStick:(short)x y:(short)y +{ + [_controllerValueLock lock]; + _lastRightStickX = x; + _lastRightStickY = y; + [_controllerValueLock unlock]; +} + +-(void) updateLeftTrigger:(char)left +{ + [_controllerValueLock lock]; + _lastLeftTrigger = left; + [_controllerValueLock unlock]; +} + +-(void) updateRightTrigger:(char)right +{ + [_controllerValueLock lock]; + _lastRightTrigger = right; + [_controllerValueLock unlock]; +} + +-(void) updateTriggers:(char)left right:(char)right +{ + [_controllerValueLock lock]; + _lastLeftTrigger = left; + _lastRightTrigger = right; + [_controllerValueLock unlock]; +} + +-(void) handleSpecialCombosReleased:(int)releasedButtons +{ + if (releasedButtons & PLAY_FLAG) { + if ((_emulatingButtonFlags & EMULATING_SELECT) && + (releasedButtons & LB_FLAG)) { + _lastButtonFlags &= ~BACK_FLAG; + _emulatingButtonFlags &= ~EMULATING_SELECT; + } + if ((_emulatingButtonFlags & EMULATING_SPECIAL) && + (releasedButtons & RB_FLAG)) { + _lastButtonFlags &= ~SPECIAL_FLAG; + _emulatingButtonFlags &= ~EMULATING_SPECIAL; + } + } +} + +-(void) handleSpecialCombosPressed +{ + // Special button combos for select and special + if (_lastButtonFlags & PLAY_FLAG) { + // If LB and start are down, trigger select + if (_lastButtonFlags & LB_FLAG) { + _lastButtonFlags |= BACK_FLAG; + _lastButtonFlags &= ~(PLAY_FLAG | LB_FLAG); + _emulatingButtonFlags |= EMULATING_SELECT; + } + // If RB and start are down, trigger special + else if (_lastButtonFlags & RB_FLAG) { + _lastButtonFlags |= SPECIAL_FLAG; + _lastButtonFlags &= ~(PLAY_FLAG | RB_FLAG); + _emulatingButtonFlags |= EMULATING_SPECIAL; + } + } +} + +-(void) updateButtonFlags:(int)flags +{ + [_controllerValueLock lock]; + int releasedButtons = (_lastButtonFlags ^ flags) & ~flags; + + _lastButtonFlags = flags; + + // This must be called before handleSpecialCombosPressed + // because we clear the original button flags there + [self handleSpecialCombosReleased: releasedButtons]; + + [self handleSpecialCombosPressed]; + + [_controllerValueLock unlock]; +} + +-(void) setButtonFlag:(int)flags +{ + [_controllerValueLock lock]; + _lastButtonFlags |= flags; + [self handleSpecialCombosPressed]; + [_controllerValueLock unlock]; +} + +-(void) clearButtonFlag:(int)flags +{ + [_controllerValueLock lock]; + _lastButtonFlags &= ~flags; + [self handleSpecialCombosReleased: flags]; + [_controllerValueLock unlock]; +} + +-(void) updateFinished +{ + [_controllerStreamLock lock]; + [_controllerValueLock lock]; + + LiSendControllerEvent(_lastButtonFlags, _lastLeftTrigger, _lastRightTrigger, _lastLeftStickX, _lastLeftStickY, _lastRightStickX, _lastRightStickY); + + [_controllerValueLock unlock]; + [_controllerStreamLock unlock]; +} + +-(void) unregisterControllerCallbacks +{ + for (int i = 0; i < [[GCController controllers] count]; i++) { + GCController *controller = [GCController controllers][i]; + + if (controller != NULL) { + controller.controllerPausedHandler = NULL; + + if (controller.extendedGamepad != NULL) { + controller.extendedGamepad.valueChangedHandler = NULL; + } + else if (controller.gamepad != NULL) { + controller.gamepad.valueChangedHandler = NULL; + } + } + } +} + +-(void) registerControllerCallbacks { for (int i = 0; i < [[GCController controllers] count]; i++) { GCController *controller = [GCController controllers][i]; @@ -27,16 +174,14 @@ static NSLock *controllerStreamLock; if (controller != NULL) { NSLog(@"Controller connected!"); controller.controllerPausedHandler = ^(GCController *controller) { - // We call LiSendControllerEvent while holding a lock to prevent - // multiple simultaneous calls since this function isn't thread safe. - [controllerStreamLock lock]; - LiSendControllerEvent(PLAY_FLAG, 0, 0, 0, 0, 0, 0); + [self setButtonFlag:PLAY_FLAG]; + [self updateFinished]; // Pause for 100 ms usleep(100 * 1000); - LiSendControllerEvent(0, 0, 0, 0, 0, 0, 0); - [controllerStreamLock unlock]; + [self clearButtonFlag:PLAY_FLAG]; + [self updateFinished]; }; if (controller.extendedGamepad != NULL) { @@ -68,12 +213,11 @@ static NSLock *controllerStreamLock; 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]; + [self updateButtonFlags:buttonFlags]; + [self updateLeftStick:leftStickX y:leftStickY]; + [self updateRightStick:rightStickX y:rightStickY]; + [self updateTriggers:leftTrigger right:rightTrigger]; + [self updateFinished]; }; } else if (controller.gamepad != NULL) { @@ -93,11 +237,8 @@ static NSLock *controllerStreamLock; 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]; + [self updateButtonFlags:buttonFlags]; + [self updateFinished]; }; } } @@ -105,22 +246,72 @@ static NSLock *controllerStreamLock; } +-(void) updateAutoOnScreenControlMode +{ + // Auto on-screen control support may not be enabled + if (_osc == NULL) { + return; + } + + OnScreenControlsLevel level = OnScreenControlsLevelFull; + + // We currently stop after the first controller we find. + // Maybe we'll want to change that logic later. + for (int i = 0; i < [[GCController controllers] count]; i++) { + GCController *controller = [GCController controllers][i]; + + if (controller != NULL) { + if (controller.extendedGamepad != NULL) { + level = OnScreenControlsLevelAutoGCExtendedGamepad; + break; + } + else if (controller.gamepad != NULL) { + level = OnScreenControlsLevelAutoGCGamepad; + break; + } + } + } + + [_osc setLevel:level]; +} + +-(void) initAutoOnScreenControlMode:(OnScreenControls*)osc +{ + _osc = osc; + + [self updateAutoOnScreenControlMode]; +} + -(id) init { self = [super init]; - if (controllerStreamLock == NULL) { - controllerStreamLock = [[NSLock alloc] init]; - } + _controllerStreamLock = [[NSLock alloc] init]; + _controllerValueLock = [[NSLock alloc] init]; self.connectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - [ControllerSupport registerControllerCallbacks]; + // Register callbacks on the new controller + [self registerControllerCallbacks]; + + // Re-evaluate the on-screen control mode + [self updateAutoOnScreenControlMode]; }]; self.disconnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { NSLog(@"Controller disconnected!"); + + // Reset all controller state to be safe + [self updateButtonFlags:0]; + [self updateLeftStick:0 y:0]; + [self updateRightStick:0 y:0]; + [self updateTriggers:0 right:0]; + [self updateFinished]; + + // Re-evaluate the on-screen control mode + [self updateAutoOnScreenControlMode]; }]; - [ControllerSupport registerControllerCallbacks]; + // Register for controller callbacks on any existing controllers + [self registerControllerCallbacks]; return self; } @@ -129,6 +320,8 @@ static NSLock *controllerStreamLock; { [[NSNotificationCenter defaultCenter] removeObserver:self.connectObserver]; [[NSNotificationCenter defaultCenter] removeObserver:self.disconnectObserver]; + + [self unregisterControllerCallbacks]; } @end diff --git a/Limelight/Input/OnScreenControls.h b/Limelight/Input/OnScreenControls.h index 1e01f61..84abbc9 100644 --- a/Limelight/Input/OnScreenControls.h +++ b/Limelight/Input/OnScreenControls.h @@ -8,15 +8,22 @@ #import +@class ControllerSupport; + @interface OnScreenControls : NSObject typedef NS_ENUM(NSInteger, OnScreenControlsLevel) { OnScreenControlsLevelOff, + OnScreenControlsLevelAuto, OnScreenControlsLevelSimple, - OnScreenControlsLevelFull + OnScreenControlsLevelFull, + + // Internal levels selected by ControllerSupport + OnScreenControlsLevelAutoGCGamepad, + OnScreenControlsLevelAutoGCExtendedGamepad, }; -- (id) initWithView:(UIView*)view; +- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport; - (BOOL) handleTouchDownEvent:(NSSet*)touches; - (BOOL) handleTouchUpEvent:(NSSet*)touches; - (BOOL) handleTouchMovedEvent:(NSSet*)touches; diff --git a/Limelight/Input/OnScreenControls.m b/Limelight/Input/OnScreenControls.m index 40f8f28..a641595 100644 --- a/Limelight/Input/OnScreenControls.m +++ b/Limelight/Input/OnScreenControls.m @@ -7,6 +7,7 @@ // #import "OnScreenControls.h" +#import "ControllerSupport.h" #include "Limelight.h" #define UPDATE_BUTTON(x, y) (buttonFlags = \ @@ -31,11 +32,6 @@ CALayer* _r2Button; CALayer* _l1Button; CALayer* _l2Button; - - short buttonFlags; - short leftStickX, leftStickY; - short rightStickX, rightStickY; - char leftTrigger, rightTrigger; UITouch* _aTouch; UITouch* _bTouch; @@ -56,6 +52,8 @@ UIView* _view; OnScreenControlsLevel _level; + + ControllerSupport *_controllerSupport; } static const float BUTTON_SIZE = 50; @@ -99,33 +97,10 @@ static float L1_Y; static float L2_X; static float L2_Y; -- (id) initWithView:(UIView*)view { +- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport { self = [self init]; _view = view; - - D_PAD_CENTER_X = _view.frame.size.width * .15; - D_PAD_CENTER_Y = _view.frame.size.height * .55; - BUTTON_CENTER_X = _view.frame.size.width * .85; - BUTTON_CENTER_Y = _view.frame.size.height * .55; - - LS_CENTER_X = _view.frame.size.width * .35; - LS_CENTER_Y = _view.frame.size.height * .75; - RS_CENTER_X = _view.frame.size.width * .65; - RS_CENTER_Y = _view.frame.size.height * .75; - - START_X = _view.frame.size.width * .55; - START_Y = _view.frame.size.height * .1; - SELECT_X = _view.frame.size.width * .45; - SELECT_Y = _view.frame.size.height * .1; - - L1_X = _view.frame.size.width * .15; - L1_Y = _view.frame.size.height * .25; - L2_X = _view.frame.size.width * .15; - L2_Y = _view.frame.size.height * .1; - R1_X = _view.frame.size.width * .85; - R1_Y = _view.frame.size.height * .25; - R2_X = _view.frame.size.width * .85; - R2_Y = _view.frame.size.height * .1; + _controllerSupport = controllerSupport; _aButton = [CALayer layer]; _bButton = [CALayer layer]; @@ -163,8 +138,32 @@ static float L2_Y; [self hideStartSelect]; [self hideSticks]; break; + case OnScreenControlsLevelAutoGCGamepad: + // GCGamepad is missing triggers, both analog sticks, + // and the select button + [self setupGamepadControls]; + + [self hideButtons]; + [self hideBumpers]; + [self drawTriggers]; + [self drawStartSelect]; + [self drawSticks]; + // TODO: Draw L3 and R3 buttons + break; + case OnScreenControlsLevelAutoGCExtendedGamepad: + // GCExtendedGamepad is missing R3, L3, and select + [self setupExtendedGamepadControls]; + + [self hideButtons]; + [self hideBumpers]; + [self hideTriggers]; + [self drawStartSelect]; + [self hideSticks]; + // TODO: Draw L3 and R3 buttons + break; case OnScreenControlsLevelSimple: [self setupSimpleControls]; + [self drawTriggers]; [self drawStartSelect]; [self hideButtons]; @@ -172,25 +171,81 @@ static float L2_Y; [self hideSticks]; break; case OnScreenControlsLevelFull: + [self setupComplexControls]; + [self drawButtons]; [self drawStartSelect]; [self drawBumpers]; [self drawTriggers]; [self drawSticks]; break; + default: + NSLog(@"Unknown on-screen controls level: %d", (int)_level); + break; } } +// For GCExtendedGamepad controls we move start, select, L3, and R3 to the button +- (void) setupExtendedGamepadControls { + // Start with the default complex layout + [self setupComplexControls]; + + START_Y = _view.frame.size.height * .9; + SELECT_Y = _view.frame.size.height * .9; + + // TODO: Position L3 and R3 at the bottom of the screen +} + +// For GCGamepad controls we move triggers, start, and select +// to sit right above the analog sticks +- (void) setupGamepadControls { + // Start with the default complex layout + [self setupComplexControls]; + + // TODO +} + // For simple controls we move the triggers and buttons to the bottom - (void) setupSimpleControls { + // Start with the default complex layout + [self setupComplexControls]; + START_Y = _view.frame.size.height * .9; SELECT_Y = _view.frame.size.height * .9; + L1_Y = _view.frame.size.height * .75; L2_Y = _view.frame.size.height * .9; R1_Y = _view.frame.size.height * .75; R2_Y = _view.frame.size.height * .9; } +- (void) setupComplexControls +{ + D_PAD_CENTER_X = _view.frame.size.width * .15; + D_PAD_CENTER_Y = _view.frame.size.height * .55; + BUTTON_CENTER_X = _view.frame.size.width * .85; + BUTTON_CENTER_Y = _view.frame.size.height * .55; + + LS_CENTER_X = _view.frame.size.width * .35; + LS_CENTER_Y = _view.frame.size.height * .75; + RS_CENTER_X = _view.frame.size.width * .65; + RS_CENTER_Y = _view.frame.size.height * .75; + + START_X = _view.frame.size.width * .55; + START_Y = _view.frame.size.height * .1; + SELECT_X = _view.frame.size.width * .45; + SELECT_Y = _view.frame.size.height * .1; + + L1_X = _view.frame.size.width * .15; + L1_Y = _view.frame.size.height * .25; + L2_X = _view.frame.size.width * .15; + L2_Y = _view.frame.size.height * .1; + R1_X = _view.frame.size.width * .85; + R1_Y = _view.frame.size.height * .25; + R2_X = _view.frame.size.width * .85; + R2_Y = _view.frame.size.height * .1; +} + - (void) drawButtons { // create A button _aButton.contents = (id) [UIImage imageNamed:@"AButton"].CGImage; @@ -325,7 +380,7 @@ static float L2_Y; } - (BOOL) handleTouchMovedEvent:touches { - BOOL shouldSendPacket = false; + BOOL updated = false; BOOL buttonTouch = false; float rsMaxX = RS_CENTER_X + STICK_OUTER_SIZE / 2; float rsMaxY = RS_CENTER_Y + STICK_OUTER_SIZE / 2; @@ -354,10 +409,9 @@ static float L2_Y; if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0; if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0; - leftStickX = 0x7FFE * xStickVal; - leftStickY = 0x7FFE * -yStickVal; + [_controllerSupport updateLeftStick:0x7FFE * xStickVal y:0x7FFE * -yStickVal]; - shouldSendPacket = true; + updated = true; } else if (touch == _rsTouch) { if (xLoc > rsMaxX) xLoc = rsMaxX; if (xLoc < rsMinX) xLoc = rsMinX; @@ -372,10 +426,9 @@ static float L2_Y; if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0; if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0; - rightStickX = 0x7FFE * xStickVal; - rightStickY = 0x7FFE * -yStickVal; + [_controllerSupport updateRightStick:0x7FFE * xStickVal y:0x7FFE * -yStickVal]; - shouldSendPacket = true; + updated = true; } else if (touch == _aTouch) { buttonTouch = true; } else if (touch == _bTouch) { @@ -406,167 +459,163 @@ static float L2_Y; buttonTouch = true; } } - if (shouldSendPacket) { - LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger, - leftStickX, leftStickY, rightStickX, rightStickY); + if (updated) { + [_controllerSupport updateFinished]; } - return shouldSendPacket || buttonTouch; + return updated || buttonTouch; } - (BOOL)handleTouchDownEvent:touches { - BOOL shouldSendPacket = false; + BOOL updated = false; + BOOL stickTouch = false; for (UITouch* touch in touches) { CGPoint touchLocation = [touch locationInView:_view]; if ([_aButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(A_FLAG, 1); + [_controllerSupport setButtonFlag:A_FLAG]; _aTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_bButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(B_FLAG, 1); + [_controllerSupport setButtonFlag:B_FLAG]; _bTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_xButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(X_FLAG, 1); + [_controllerSupport setButtonFlag:X_FLAG]; _xTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_yButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(Y_FLAG, 1); + [_controllerSupport setButtonFlag:Y_FLAG]; _yTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_upButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(UP_FLAG, 1); + [_controllerSupport setButtonFlag:UP_FLAG]; _upTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_downButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(DOWN_FLAG, 1); + [_controllerSupport setButtonFlag:DOWN_FLAG]; _downTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_leftButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(LEFT_FLAG, 1); + [_controllerSupport setButtonFlag:LEFT_FLAG]; _leftTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_rightButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(RIGHT_FLAG, 1); + [_controllerSupport setButtonFlag:RIGHT_FLAG]; _rightTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_startButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(PLAY_FLAG, 1); + [_controllerSupport setButtonFlag:PLAY_FLAG]; _startTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_selectButton.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(BACK_FLAG, 1); + [_controllerSupport setButtonFlag:BACK_FLAG]; _selectTouch = touch; - shouldSendPacket = true; + updated = true; } else if ([_l1Button.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(LB_FLAG, 1); + [_controllerSupport setButtonFlag:LB_FLAG]; _l1Touch = touch; - shouldSendPacket = true; + updated = true; } else if ([_r1Button.presentationLayer hitTest:touchLocation]) { - UPDATE_BUTTON(RB_FLAG, 1); + [_controllerSupport setButtonFlag:RB_FLAG]; _r1Touch = touch; - shouldSendPacket = true; + updated = true; } else if ([_l2Button.presentationLayer hitTest:touchLocation]) { - leftTrigger = 1 * 0xFF; + [_controllerSupport updateLeftTrigger:0xFF]; _l2Touch = touch; - shouldSendPacket = true; + updated = true; } else if ([_r2Button.presentationLayer hitTest:touchLocation]) { - rightTrigger = 1 * 0xFF; + [_controllerSupport updateRightTrigger:0xFF]; _r2Touch = touch; - shouldSendPacket = true; + updated = true; } else if ([_leftStick.presentationLayer hitTest:touchLocation]) { _lsTouch = touch; - shouldSendPacket = true; + stickTouch = true; } else if ([_rightStick.presentationLayer hitTest:touchLocation]) { _rsTouch = touch; - shouldSendPacket = true; + stickTouch = true; } } - if (shouldSendPacket) { - LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger, - leftStickX, leftStickY, rightStickX, rightStickY); + if (updated) { + [_controllerSupport updateFinished]; } - return shouldSendPacket; + return updated || stickTouch; } - (BOOL)handleTouchUpEvent:touches { - BOOL shouldSendPacket = false; + BOOL updated = false; for (UITouch* touch in touches) { if (touch == _aTouch) { - UPDATE_BUTTON(A_FLAG, 0); + [_controllerSupport clearButtonFlag:A_FLAG]; _aTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _bTouch) { - UPDATE_BUTTON(B_FLAG, 0); + [_controllerSupport clearButtonFlag:B_FLAG]; _bTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _xTouch) { - UPDATE_BUTTON(X_FLAG, 0); + [_controllerSupport clearButtonFlag:X_FLAG]; _xTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _yTouch) { - UPDATE_BUTTON(Y_FLAG, 0); + [_controllerSupport clearButtonFlag:Y_FLAG]; _yTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _upTouch) { - UPDATE_BUTTON(UP_FLAG, 0); + [_controllerSupport clearButtonFlag:UP_FLAG]; _upTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _downTouch) { - UPDATE_BUTTON(DOWN_FLAG, 0); + [_controllerSupport clearButtonFlag:DOWN_FLAG]; _downTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _leftTouch) { - UPDATE_BUTTON(LEFT_FLAG, 0); + [_controllerSupport clearButtonFlag:LEFT_FLAG]; _leftTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _rightTouch) { - UPDATE_BUTTON(RIGHT_FLAG, 0); + [_controllerSupport clearButtonFlag:RIGHT_FLAG]; _rightTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _startTouch) { - UPDATE_BUTTON(PLAY_FLAG, 0); + [_controllerSupport clearButtonFlag:PLAY_FLAG]; _startTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _selectTouch) { - UPDATE_BUTTON(BACK_FLAG, 0); + [_controllerSupport clearButtonFlag:BACK_FLAG]; _selectTouch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _l1Touch) { - UPDATE_BUTTON(LB_FLAG, 0); + [_controllerSupport clearButtonFlag:LB_FLAG]; _l1Touch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _r1Touch) { - UPDATE_BUTTON(RB_FLAG, 0); + [_controllerSupport clearButtonFlag:RB_FLAG]; _r1Touch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _l2Touch) { - leftTrigger = 0 * 0xFF; + [_controllerSupport updateLeftTrigger:0]; _l2Touch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _r2Touch) { - rightTrigger = 0 * 0xFF; + [_controllerSupport updateRightTrigger:0]; _r2Touch = nil; - shouldSendPacket = true; + updated = true; } else if (touch == _lsTouch) { _leftStick.frame = CGRectMake(LS_CENTER_X - STICK_INNER_SIZE / 2, LS_CENTER_Y - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE); - leftStickX = 0 * 0x7FFE; - leftStickY = 0 * 0x7FFE; - shouldSendPacket = true; + [_controllerSupport updateLeftStick:0 y:0]; + updated = true; _lsTouch = nil; } else if (touch == _rsTouch) { _rightStick.frame = CGRectMake(RS_CENTER_X - STICK_INNER_SIZE / 2, RS_CENTER_Y - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE); - rightStickX = 0 * 0x7FFE; - rightStickY = 0 * 0x7FFE; + [_controllerSupport updateRightStick:0 y:0]; _rsTouch = nil; - shouldSendPacket = true; + updated = true; } } - if (shouldSendPacket) { - LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger, - leftStickX, leftStickY, rightStickX, rightStickY); + if (updated) { + [_controllerSupport updateFinished]; } - return shouldSendPacket; + return updated; } @end diff --git a/Limelight/Input/StreamView.h b/Limelight/Input/StreamView.h index a7aa4e5..ef4b009 100644 --- a/Limelight/Input/StreamView.h +++ b/Limelight/Input/StreamView.h @@ -7,9 +7,10 @@ // #import +#import "ControllerSupport.h" @interface StreamView : UIView -- (void) setupOnScreenControls; +- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport; @end diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index af1a5fb..1d4c6b0 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -10,6 +10,7 @@ #include #import "OnScreenControls.h" #import "DataManager.h" +#import "ControllerSupport.h" @implementation StreamView { CGPoint touchLocation; @@ -17,12 +18,19 @@ OnScreenControls* onScreenControls; } -- (void) setupOnScreenControls { - onScreenControls = [[OnScreenControls alloc] initWithView:self]; +- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport { + onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport]; DataManager* dataMan = [[DataManager alloc] init]; OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan retrieveSettings].onscreenControls integerValue]; - NSLog(@"Setting on-screen controls level: %d", (int)level); - [onScreenControls setLevel:level]; + + if (level == OnScreenControlsLevelAuto) { + [controllerSupport initAutoOnScreenControlMode:onScreenControls]; + } + else { + NSLog(@"Setting manual on-screen controls level: %d", (int)level); + [onScreenControls setLevel:level]; + } + } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { diff --git a/Limelight/ViewControllers/StreamFrameViewController.m b/Limelight/ViewControllers/StreamFrameViewController.m index 92b63d9..7a7f91c 100644 --- a/Limelight/ViewControllers/StreamFrameViewController.m +++ b/Limelight/ViewControllers/StreamFrameViewController.m @@ -64,7 +64,7 @@ [self.stageLabel setText:@"Waiting for first frame..."]; [self.stageLabel sizeToFit]; }); - [(StreamView*)self.view setupOnScreenControls]; + [(StreamView*)self.view setupOnScreenControls: _controllerSupport]; } - (void)connectionTerminated:(long)errorCode { diff --git a/iPad.storyboard b/iPad.storyboard index 8fa528b..d67f042 100644 --- a/iPad.storyboard +++ b/iPad.storyboard @@ -126,11 +126,12 @@ - + + diff --git a/iPhone.storyboard b/iPhone.storyboard index b54cbdb..c20efc6 100644 --- a/iPhone.storyboard +++ b/iPhone.storyboard @@ -146,11 +146,12 @@ - + +