Retransmit OSC gamepad packets every 100 ms to recover from dropped events in GFE

This commit is contained in:
Cameron Gutman 2018-11-30 21:17:12 -08:00
parent 4930087c4d
commit 6993051529
3 changed files with 23 additions and 15 deletions

View File

@ -406,6 +406,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
(FrameLayout)streamView.getParent(), (FrameLayout)streamView.getParent(),
this); this);
virtualController.refreshLayout(); virtualController.refreshLayout();
virtualController.show();
} }
if (prefConfig.usbDriver) { if (prefConfig.usbDriver) {
@ -692,6 +693,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
SpinnerDialog.closeDialogs(this); SpinnerDialog.closeDialogs(this);
Dialog.closeDialogs(); Dialog.closeDialogs();
if (virtualController != null) {
virtualController.hide();
}
if (conn != null) { if (conn != null) {
int videoFormat = decoderRenderer.getActiveVideoFormat(); int videoFormat = decoderRenderer.getActiveVideoFormat();

View File

@ -339,15 +339,6 @@ public class AnalogStick extends VirtualControllerElement {
stick_state = STICK_STATE.NO_MOVEMENT; stick_state = STICK_STATE.NO_MOVEMENT;
notifyOnRevoke(); notifyOnRevoke();
// HACK: We can sometimes generate back-to-back controller events
// that cause GFE to drop newer data. Dropping zeroing events would
// be disastrous because we may not get a follow-up joystick event to
// correct the dropped zeroing packet. Delay 5 ms when raising the
// analog stick to ensure this doesn't happen.
try {
Thread.sleep(5);
} catch (InterruptedException e) {}
// not longer pressed reset analog stick // not longer pressed reset analog stick
notifyOnMovement(0, 0); notifyOnMovement(0, 0);
} }

View File

@ -17,6 +17,8 @@ import com.limelight.nvstream.NvConnection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class VirtualController { public class VirtualController {
public class ControllerInputContext { public class ControllerInputContext {
@ -42,6 +44,8 @@ public class VirtualController {
private FrameLayout frame_layout = null; private FrameLayout frame_layout = null;
private RelativeLayout relative_layout = null; private RelativeLayout relative_layout = null;
private Timer retransmitTimer;
ControllerMode currentMode = ControllerMode.Active; ControllerMode currentMode = ControllerMode.Active;
ControllerInputContext inputContext = new ControllerInputContext(); ControllerInputContext inputContext = new ControllerInputContext();
@ -88,11 +92,24 @@ public class VirtualController {
} }
public void hide() { public void hide() {
retransmitTimer.cancel();
relative_layout.setVisibility(View.INVISIBLE); relative_layout.setVisibility(View.INVISIBLE);
} }
public void show() { public void show() {
relative_layout.setVisibility(View.VISIBLE); relative_layout.setVisibility(View.VISIBLE);
// HACK: GFE sometimes discards gamepad packets when they are received
// very shortly after another. This can be critical if an axis zeroing packet
// is lost and causes an analog stick to get stuck. To avoid this, we send
// a gamepad input packet every 100 ms to ensure any loss can be recovered.
retransmitTimer = new Timer("OSC timer", true);
retransmitTimer.schedule(new TimerTask() {
@Override
public void run() {
sendControllerInputContext();
}
}, 100, 100);
} }
public void removeElements() { public void removeElements() {
@ -149,18 +166,13 @@ public class VirtualController {
return inputContext; return inputContext;
} }
public void sendControllerInputContext() { void sendControllerInputContext() {
sendControllerInputPacket();
}
private void sendControllerInputPacket() {
try { try {
_DBG("INPUT_MAP + " + inputContext.inputMap); _DBG("INPUT_MAP + " + inputContext.inputMap);
_DBG("LEFT_TRIGGER " + inputContext.leftTrigger); _DBG("LEFT_TRIGGER " + inputContext.leftTrigger);
_DBG("RIGHT_TRIGGER " + inputContext.rightTrigger); _DBG("RIGHT_TRIGGER " + inputContext.rightTrigger);
_DBG("LEFT STICK X: " + inputContext.leftStickX + " Y: " + inputContext.leftStickY); _DBG("LEFT STICK X: " + inputContext.leftStickX + " Y: " + inputContext.leftStickY);
_DBG("RIGHT STICK X: " + inputContext.rightStickX + " Y: " + inputContext.rightStickY); _DBG("RIGHT STICK X: " + inputContext.rightStickX + " Y: " + inputContext.rightStickY);
_DBG("RIGHT STICK X: " + inputContext.rightStickX + " Y: " + inputContext.rightStickY);
if (connection != null) { if (connection != null) {
connection.sendControllerInput( connection.sendControllerInput(