mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-10-20 23:36:53 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f09cbd609 | ||
|
|
b6ee0764ff | ||
|
|
f56b7ff79e | ||
|
|
645ea683ee | ||
|
|
67e22fca6b | ||
|
|
a726ba8ea7 | ||
|
|
23fcaa1bab | ||
|
|
ad684a6f6b | ||
|
|
d3438f4938 | ||
|
|
cafdc21bf2 | ||
|
|
ceb9bd3342 | ||
|
|
13b80eda8a | ||
|
|
6677949614 | ||
|
|
080dcd92d7 | ||
|
|
31b0bcf041 | ||
|
|
36664133f8 | ||
|
|
a3106bffca | ||
|
|
94a26fb831 |
No files matched your search
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.limelight"
|
package="com.limelight"
|
||||||
android:versionCode="34"
|
android:versionCode="35"
|
||||||
android:versionName="2.5.5" >
|
android:versionName="2.5.6" >
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="16"
|
android:minSdkVersion="16"
|
||||||
|
|||||||
Binary file not shown.
+218
-66
@@ -35,6 +35,7 @@ import android.view.SurfaceHolder;
|
|||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnGenericMotionListener;
|
import android.view.View.OnGenericMotionListener;
|
||||||
|
import android.view.View.OnSystemUiVisibilityChangeListener;
|
||||||
import android.view.View.OnTouchListener;
|
import android.view.View.OnTouchListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
@@ -43,7 +44,8 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
|
|
||||||
public class Game extends Activity implements SurfaceHolder.Callback,
|
public class Game extends Activity implements SurfaceHolder.Callback,
|
||||||
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener
|
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
|
||||||
|
OnSystemUiVisibilityChangeListener
|
||||||
{
|
{
|
||||||
private int lastMouseX = Integer.MIN_VALUE;
|
private int lastMouseX = Integer.MIN_VALUE;
|
||||||
private int lastMouseY = Integer.MIN_VALUE;
|
private int lastMouseY = Integer.MIN_VALUE;
|
||||||
@@ -69,6 +71,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
private boolean toastsDisabled;
|
private boolean toastsDisabled;
|
||||||
|
|
||||||
private EvdevWatcher evdevWatcher;
|
private EvdevWatcher evdevWatcher;
|
||||||
|
private int modifierFlags = 0;
|
||||||
|
private boolean grabbedInput = true;
|
||||||
|
private boolean grabComboDown = false;
|
||||||
|
private static final int MODIFIER_CTRL = 0x1;
|
||||||
|
private static final int MODIFIER_SHIFT = 0x2;
|
||||||
|
|
||||||
private ConfigurableDecoderRenderer decoderRenderer;
|
private ConfigurableDecoderRenderer decoderRenderer;
|
||||||
|
|
||||||
@@ -133,6 +140,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Listen for UI visibility events
|
||||||
|
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
|
||||||
|
|
||||||
// Change volume button behavior
|
// Change volume button behavior
|
||||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||||
|
|
||||||
@@ -270,11 +280,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private void hideSystemUi() {
|
private void hideSystemUi(int delay) {
|
||||||
Handler h = getWindow().getDecorView().getHandler();
|
Handler h = getWindow().getDecorView().getHandler();
|
||||||
if (h != null) {
|
if (h != null) {
|
||||||
h.removeCallbacks(hideSystemUi);
|
h.removeCallbacks(hideSystemUi);
|
||||||
h.postDelayed(hideSystemUi, 1000);
|
h.postDelayed(hideSystemUi, delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +296,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
Dialog.closeDialogs();
|
Dialog.closeDialogs();
|
||||||
|
|
||||||
displayedFailureDialog = true;
|
displayedFailureDialog = true;
|
||||||
conn.stop();
|
stopConnection();
|
||||||
|
|
||||||
int averageEndToEndLat = decoderRenderer.getAverageEndToEndLatency();
|
int averageEndToEndLat = decoderRenderer.getAverageEndToEndLatency();
|
||||||
int averageDecoderLat = decoderRenderer.getAverageDecoderLatency();
|
int averageDecoderLat = decoderRenderer.getAverageDecoderLatency();
|
||||||
@@ -304,10 +314,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
if (message != null) {
|
if (message != null) {
|
||||||
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evdevWatcher != null) {
|
|
||||||
evdevWatcher.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
@@ -319,6 +325,80 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
wifiLock.release();
|
wifiLock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Runnable toggleGrab = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
if (evdevWatcher != null) {
|
||||||
|
if (grabbedInput) {
|
||||||
|
evdevWatcher.ungrabAll();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
evdevWatcher.regrabAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grabbedInput = !grabbedInput;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns true if the key stroke was consumed
|
||||||
|
private boolean handleMagicKeyCombos(short translatedKey, boolean down) {
|
||||||
|
int modifierMask = 0;
|
||||||
|
|
||||||
|
// Mask off the high byte
|
||||||
|
translatedKey &= 0xff;
|
||||||
|
|
||||||
|
if (translatedKey == KeyboardTranslator.VK_CONTROL) {
|
||||||
|
modifierMask = MODIFIER_CTRL;
|
||||||
|
}
|
||||||
|
else if (translatedKey == KeyboardTranslator.VK_SHIFT) {
|
||||||
|
modifierMask = MODIFIER_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (down) {
|
||||||
|
this.modifierFlags |= modifierMask;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.modifierFlags &= ~modifierMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if Ctrl+Shift+Z is pressed
|
||||||
|
if (translatedKey == KeyboardTranslator.VK_Z &&
|
||||||
|
(modifierFlags & (MODIFIER_CTRL|MODIFIER_SHIFT)) == (MODIFIER_CTRL|MODIFIER_SHIFT))
|
||||||
|
{
|
||||||
|
if (down) {
|
||||||
|
// Now that we've pressed the magic combo
|
||||||
|
// we'll wait for one of the keys to come up
|
||||||
|
grabComboDown = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Toggle the grab if Z comes up
|
||||||
|
Handler h = getWindow().getDecorView().getHandler();
|
||||||
|
if (h != null) {
|
||||||
|
h.postDelayed(toggleGrab, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
grabComboDown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Toggle the grab if control or shift comes up
|
||||||
|
else if (grabComboDown) {
|
||||||
|
Handler h = getWindow().getDecorView().getHandler();
|
||||||
|
if (h != null) {
|
||||||
|
h.postDelayed(toggleGrab, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
grabComboDown = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not a special combo
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private static byte getModifierState(KeyEvent event) {
|
private static byte getModifierState(KeyEvent event) {
|
||||||
byte modifier = 0;
|
byte modifier = 0;
|
||||||
if (event.isShiftPressed()) {
|
if (event.isShiftPressed()) {
|
||||||
@@ -354,6 +434,21 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
return super.onKeyDown(keyCode, event);
|
return super.onKeyDown(keyCode, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let this method take duplicate key down events
|
||||||
|
if (handleMagicKeyCombos(translated, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eat repeat down events
|
||||||
|
if (event.getRepeatCount() > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass through keyboard input if we're not grabbing
|
||||||
|
if (!grabbedInput) {
|
||||||
|
return super.onKeyDown(keyCode, event);
|
||||||
|
}
|
||||||
|
|
||||||
keybTranslator.sendKeyDown(translated,
|
keybTranslator.sendKeyDown(translated,
|
||||||
getModifierState(event));
|
getModifierState(event));
|
||||||
}
|
}
|
||||||
@@ -363,16 +458,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||||
// Pressing a volume button drops the immersive flag so the UI shows up again and doesn't
|
|
||||||
// go away. I'm not sure if that's a bug or a feature, but we're working around it here
|
|
||||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
|
|
||||||
Handler h = getWindow().getDecorView().getHandler();
|
|
||||||
if (h != null) {
|
|
||||||
h.removeCallbacks(hideSystemUi);
|
|
||||||
h.postDelayed(hideSystemUi, 2000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InputDevice dev = event.getDevice();
|
InputDevice dev = event.getDevice();
|
||||||
if (dev == null) {
|
if (dev == null) {
|
||||||
return super.onKeyUp(keyCode, event);
|
return super.onKeyUp(keyCode, event);
|
||||||
@@ -392,6 +477,15 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
return super.onKeyUp(keyCode, event);
|
return super.onKeyUp(keyCode, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (handleMagicKeyCombos(translated, false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass through keyboard input if we're not grabbing
|
||||||
|
if (!grabbedInput) {
|
||||||
|
return super.onKeyUp(keyCode, event);
|
||||||
|
}
|
||||||
|
|
||||||
keybTranslator.sendKeyUp(translated,
|
keybTranslator.sendKeyUp(translated,
|
||||||
getModifierState(event));
|
getModifierState(event));
|
||||||
}
|
}
|
||||||
@@ -408,25 +502,35 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Returns true if the event was consumed
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
private boolean handleMotionEvent(MotionEvent event) {
|
||||||
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0)
|
// Pass through keyboard input if we're not grabbing
|
||||||
|
if (!grabbedInput) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
|
||||||
|
if (controllerHandler.handleMotionEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0)
|
||||||
{
|
{
|
||||||
// This case is for touch-based input devices
|
// This case is for touch-based input devices
|
||||||
if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN ||
|
if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN ||
|
||||||
event.getSource() == InputDevice.SOURCE_STYLUS)
|
event.getSource() == InputDevice.SOURCE_STYLUS)
|
||||||
{
|
{
|
||||||
int actionIndex = event.getActionIndex();
|
int actionIndex = event.getActionIndex();
|
||||||
|
|
||||||
int eventX = (int)event.getX(actionIndex);
|
int eventX = (int)event.getX(actionIndex);
|
||||||
int eventY = (int)event.getY(actionIndex);
|
int eventY = (int)event.getY(actionIndex);
|
||||||
|
|
||||||
TouchContext context = getTouchContext(actionIndex);
|
TouchContext context = getTouchContext(actionIndex);
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
return super.onTouchEvent(event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event.getActionMasked())
|
switch (event.getActionMasked())
|
||||||
{
|
{
|
||||||
case MotionEvent.ACTION_POINTER_DOWN:
|
case MotionEvent.ACTION_POINTER_DOWN:
|
||||||
@@ -449,7 +553,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return super.onTouchEvent(event);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// This case is for mice
|
// This case is for mice
|
||||||
@@ -457,6 +561,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
{
|
{
|
||||||
int changedButtons = event.getButtonState() ^ lastButtonState;
|
int changedButtons = event.getButtonState() ^ lastButtonState;
|
||||||
|
|
||||||
|
if (event.getActionMasked() == MotionEvent.ACTION_SCROLL) {
|
||||||
|
// Send the vertical scroll packet
|
||||||
|
byte vScrollClicks = (byte) event.getAxisValue(MotionEvent.AXIS_VSCROLL);
|
||||||
|
conn.sendMouseScroll(vScrollClicks);
|
||||||
|
}
|
||||||
|
|
||||||
if ((changedButtons & MotionEvent.BUTTON_PRIMARY) != 0) {
|
if ((changedButtons & MotionEvent.BUTTON_PRIMARY) != 0) {
|
||||||
if ((event.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0) {
|
if ((event.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0) {
|
||||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_LEFT);
|
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_LEFT);
|
||||||
@@ -465,7 +575,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((changedButtons & MotionEvent.BUTTON_SECONDARY) != 0) {
|
if ((changedButtons & MotionEvent.BUTTON_SECONDARY) != 0) {
|
||||||
if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
|
if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
|
||||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
||||||
@@ -474,7 +584,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((changedButtons & MotionEvent.BUTTON_TERTIARY) != 0) {
|
if ((changedButtons & MotionEvent.BUTTON_TERTIARY) != 0) {
|
||||||
if ((event.getButtonState() & MotionEvent.BUTTON_TERTIARY) != 0) {
|
if ((event.getButtonState() & MotionEvent.BUTTON_TERTIARY) != 0) {
|
||||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_MIDDLE);
|
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_MIDDLE);
|
||||||
@@ -483,47 +593,41 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_MIDDLE);
|
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_MIDDLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMousePosition((int)event.getX(), (int)event.getY());
|
updateMousePosition((int)event.getX(), (int)event.getY());
|
||||||
|
|
||||||
lastButtonState = event.getButtonState();
|
lastButtonState = event.getButtonState();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return super.onTouchEvent(event);
|
// Unknown source
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handled a known source
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unknown class
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
if (!handleMotionEvent(event)) {
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
return super.onTouchEvent(event);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onGenericMotionEvent(MotionEvent event) {
|
public boolean onGenericMotionEvent(MotionEvent event) {
|
||||||
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
|
if (!handleMotionEvent(event)) {
|
||||||
if (controllerHandler.handleMotionEvent(event)) {
|
return super.onGenericMotionEvent(event);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0)
|
|
||||||
{
|
|
||||||
switch (event.getActionMasked())
|
|
||||||
{
|
|
||||||
case MotionEvent.ACTION_HOVER_MOVE:
|
|
||||||
// Send a mouse move update (if neccessary)
|
|
||||||
updateMousePosition((int)event.getX(), (int)event.getY());
|
|
||||||
break;
|
|
||||||
case MotionEvent.ACTION_SCROLL:
|
|
||||||
// Send the vertical scroll packet
|
|
||||||
byte vScrollClicks = (byte) event.getAxisValue(MotionEvent.AXIS_VSCROLL);
|
|
||||||
conn.sendMouseScroll(vScrollClicks);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onGenericMotionEvent(event);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateMousePosition(int eventX, int eventY) {
|
private void updateMousePosition(int eventX, int eventY) {
|
||||||
@@ -551,15 +655,13 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onGenericMotion(View v, MotionEvent event) {
|
public boolean onGenericMotion(View v, MotionEvent event) {
|
||||||
// Send it to the activity's motion event handler
|
return handleMotionEvent(event);
|
||||||
return onGenericMotionEvent(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
// Send it to the activity's touch event handler
|
return handleMotionEvent(event);
|
||||||
return onTouchEvent(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -572,6 +674,19 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
@Override
|
@Override
|
||||||
public void stageComplete(Stage stage) {
|
public void stageComplete(Stage stage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void stopConnection() {
|
||||||
|
if (connecting || connected) {
|
||||||
|
connecting = connected = false;
|
||||||
|
conn.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the Evdev watcher to allow use of captured input devices
|
||||||
|
if (evdevWatcher != null) {
|
||||||
|
evdevWatcher.shutdown();
|
||||||
|
evdevWatcher = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stageFailed(Stage stage) {
|
public void stageFailed(Stage stage) {
|
||||||
@@ -582,9 +697,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
if (!displayedFailureDialog) {
|
if (!displayedFailureDialog) {
|
||||||
displayedFailureDialog = true;
|
displayedFailureDialog = true;
|
||||||
|
stopConnection();
|
||||||
Dialog.displayDialog(this, "Connection Error", "Starting "+stage.getName()+" failed", true);
|
Dialog.displayDialog(this, "Connection Error", "Starting "+stage.getName()+" failed", true);
|
||||||
conn.stop();
|
|
||||||
connecting = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,9 +707,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
if (!displayedFailureDialog) {
|
if (!displayedFailureDialog) {
|
||||||
displayedFailureDialog = true;
|
displayedFailureDialog = true;
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
||||||
|
stopConnection();
|
||||||
Dialog.displayDialog(this, "Connection Terminated", "The connection failed unexpectedly", true);
|
Dialog.displayDialog(this, "Connection Terminated", "The connection failed unexpectedly", true);
|
||||||
conn.stop();
|
|
||||||
connected = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,7 +723,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
connecting = false;
|
connecting = false;
|
||||||
connected = true;
|
connected = true;
|
||||||
|
|
||||||
hideSystemUi();
|
hideSystemUi(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -657,8 +771,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
@Override
|
@Override
|
||||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||||
if (connected) {
|
if (connected) {
|
||||||
conn.stop();
|
stopConnection();
|
||||||
connected = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,4 +812,43 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
public void mouseScroll(byte amount) {
|
public void mouseScroll(byte amount) {
|
||||||
conn.sendMouseScroll(amount);
|
conn.sendMouseScroll(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void keyboardEvent(boolean buttonDown, short keyCode) {
|
||||||
|
short keyMap = keybTranslator.translate(keyCode);
|
||||||
|
if (keyMap != 0) {
|
||||||
|
if (handleMagicKeyCombos(keyMap, buttonDown)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonDown) {
|
||||||
|
keybTranslator.sendKeyDown(keyMap, (byte) 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
keybTranslator.sendKeyUp(keyMap, (byte) 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSystemUiVisibilityChange(int visibility) {
|
||||||
|
// Don't do anything if we're not connected
|
||||||
|
if (!connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This flag is set for all devices
|
||||||
|
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
|
||||||
|
hideSystemUi(2000);
|
||||||
|
}
|
||||||
|
// This flag is only set on 4.4+
|
||||||
|
else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT &&
|
||||||
|
(visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
|
||||||
|
hideSystemUi(2000);
|
||||||
|
}
|
||||||
|
// This flag is only set before 4.4+
|
||||||
|
else if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT &&
|
||||||
|
(visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) {
|
||||||
|
hideSystemUi(2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import java.net.InetAddress;
|
|||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
import com.limelight.binding.PlatformBinding;
|
import com.limelight.binding.PlatformBinding;
|
||||||
|
import com.limelight.binding.crypto.AndroidCryptoProvider;
|
||||||
import com.limelight.computers.ComputerManagerListener;
|
import com.limelight.computers.ComputerManagerListener;
|
||||||
import com.limelight.computers.ComputerManagerService;
|
import com.limelight.computers.ComputerManagerService;
|
||||||
import com.limelight.nvstream.http.ComputerDetails;
|
import com.limelight.nvstream.http.ComputerDetails;
|
||||||
@@ -59,6 +60,9 @@ public class PcView extends Activity {
|
|||||||
|
|
||||||
// Start updates
|
// Start updates
|
||||||
startComputerUpdates();
|
startComputerUpdates();
|
||||||
|
|
||||||
|
// Force a keypair to be generated early to avoid discovery delays
|
||||||
|
new AndroidCryptoProvider(PcView.this).getClientCertificate();
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
|||||||
private RSAPrivateKey key;
|
private RSAPrivateKey key;
|
||||||
private byte[] pemCertBytes;
|
private byte[] pemCertBytes;
|
||||||
|
|
||||||
|
private static Object globalCryptoLock = new Object();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Install the Bouncy Castle provider
|
// Install the Bouncy Castle provider
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
@@ -208,7 +210,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
|||||||
public X509Certificate getClientCertificate() {
|
public X509Certificate getClientCertificate() {
|
||||||
// Use a lock here to ensure only one guy will be generating or loading
|
// Use a lock here to ensure only one guy will be generating or loading
|
||||||
// the certificate and key at a time
|
// the certificate and key at a time
|
||||||
synchronized (this) {
|
synchronized (globalCryptoLock) {
|
||||||
// Return a loaded cert if we have one
|
// Return a loaded cert if we have one
|
||||||
if (cert != null) {
|
if (cert != null) {
|
||||||
return cert;
|
return cert;
|
||||||
@@ -235,7 +237,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
|||||||
public RSAPrivateKey getClientPrivateKey() {
|
public RSAPrivateKey getClientPrivateKey() {
|
||||||
// Use a lock here to ensure only one guy will be generating or loading
|
// Use a lock here to ensure only one guy will be generating or loading
|
||||||
// the certificate and key at a time
|
// the certificate and key at a time
|
||||||
synchronized (this) {
|
synchronized (globalCryptoLock) {
|
||||||
// Return a loaded key if we have one
|
// Return a loaded key if we have one
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
return key;
|
return key;
|
||||||
@@ -260,7 +262,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getPemEncodedClientCertificate() {
|
public byte[] getPemEncodedClientCertificate() {
|
||||||
synchronized (this) {
|
synchronized (globalCryptoLock) {
|
||||||
// Call our helper function to do the cert loading/generation for us
|
// Call our helper function to do the cert loading/generation for us
|
||||||
getClientCertificate();
|
getClientCertificate();
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ public class ControllerHandler {
|
|||||||
|
|
||||||
public ControllerHandler(NvConnection conn) {
|
public ControllerHandler(NvConnection conn) {
|
||||||
this.conn = conn;
|
this.conn = conn;
|
||||||
|
|
||||||
|
// We want limelight-common to scale the axis values to match Xinput values
|
||||||
|
ControllerPacket.enableAxisScaling = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControllerMapping createMappingForDevice(InputDevice dev) {
|
private ControllerMapping createMappingForDevice(InputDevice dev) {
|
||||||
@@ -135,6 +138,15 @@ public class ControllerHandler {
|
|||||||
InputDevice.MotionRange lsYRange = dev.getMotionRange(mapping.leftStickYAxis);
|
InputDevice.MotionRange lsYRange = dev.getMotionRange(mapping.leftStickYAxis);
|
||||||
if (lsXRange != null && lsYRange != null) {
|
if (lsXRange != null && lsYRange != null) {
|
||||||
mapping.leftStickDeadzoneRadius = Math.max(lsXRange.getFlat(), lsYRange.getFlat());
|
mapping.leftStickDeadzoneRadius = Math.max(lsXRange.getFlat(), lsYRange.getFlat());
|
||||||
|
|
||||||
|
// If there isn't a (reasonable) deadzone at all, use 20%
|
||||||
|
if (mapping.leftStickDeadzoneRadius < 0.02f) {
|
||||||
|
mapping.leftStickDeadzoneRadius = 0.20f;
|
||||||
|
}
|
||||||
|
// Check that the deadzone is 12% at minimum
|
||||||
|
else if (mapping.leftStickDeadzoneRadius < 0.12f) {
|
||||||
|
mapping.leftStickDeadzoneRadius = 0.12f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +155,15 @@ public class ControllerHandler {
|
|||||||
InputDevice.MotionRange rsYRange = dev.getMotionRange(mapping.rightStickYAxis);
|
InputDevice.MotionRange rsYRange = dev.getMotionRange(mapping.rightStickYAxis);
|
||||||
if (rsXRange != null && rsYRange != null) {
|
if (rsXRange != null && rsYRange != null) {
|
||||||
mapping.rightStickDeadzoneRadius = Math.max(rsXRange.getFlat(), rsYRange.getFlat());
|
mapping.rightStickDeadzoneRadius = Math.max(rsXRange.getFlat(), rsYRange.getFlat());
|
||||||
|
|
||||||
|
// If there isn't a (reasonable) deadzone at all, use 20%
|
||||||
|
if (mapping.rightStickDeadzoneRadius < 0.02f) {
|
||||||
|
mapping.rightStickDeadzoneRadius = 0.20f;
|
||||||
|
}
|
||||||
|
// Check that the deadzone is 12% at minimum
|
||||||
|
else if (mapping.rightStickDeadzoneRadius < 0.12f) {
|
||||||
|
mapping.rightStickDeadzoneRadius = 0.12f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +263,7 @@ public class ControllerHandler {
|
|||||||
// Scale the input based on the distance from the deadzone
|
// Scale the input based on the distance from the deadzone
|
||||||
inputVector.getNormalized(normalizedInputVector);
|
inputVector.getNormalized(normalizedInputVector);
|
||||||
normalizedInputVector.scalarMultiply((inputVector.getMagnitude() - deadzoneRadius) / (1.0f - deadzoneRadius));
|
normalizedInputVector.scalarMultiply((inputVector.getMagnitude() - deadzoneRadius) / (1.0f - deadzoneRadius));
|
||||||
|
|
||||||
// Bound the X value to -1.0 to 1.0
|
// Bound the X value to -1.0 to 1.0
|
||||||
if (normalizedInputVector.getX() > 1.0f) {
|
if (normalizedInputVector.getX() > 1.0f) {
|
||||||
normalizedInputVector.setX(1.0f);
|
normalizedInputVector.setX(1.0f);
|
||||||
@@ -284,7 +305,7 @@ public class ControllerHandler {
|
|||||||
event.getAxisValue(mapping.rightStickYAxis), mapping.rightStickDeadzoneRadius);
|
event.getAxisValue(mapping.rightStickYAxis), mapping.rightStickDeadzoneRadius);
|
||||||
|
|
||||||
rightStickX = (short)(rightStickVector.getX() * 0x7FFE);
|
rightStickX = (short)(rightStickVector.getX() * 0x7FFE);
|
||||||
rightStickY = (short)(-rightStickVector.getY() * 0x7FFE);
|
rightStickY = (short)(-rightStickVector.getY() * 0x7FFE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle controllers with analog triggers
|
// Handle controllers with analog triggers
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.limelight.binding.input.evdev;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import com.limelight.LimeLog;
|
import com.limelight.LimeLog;
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ public class EvdevWatcher {
|
|||||||
private HashMap<String, EvdevHandler> handlers = new HashMap<String, EvdevHandler>();
|
private HashMap<String, EvdevHandler> handlers = new HashMap<String, EvdevHandler>();
|
||||||
private boolean shutdown = false;
|
private boolean shutdown = false;
|
||||||
private boolean init = false;
|
private boolean init = false;
|
||||||
|
private boolean ungrabbed = false;
|
||||||
private EvdevListener listener;
|
private EvdevListener listener;
|
||||||
private Thread startThread;
|
private Thread startThread;
|
||||||
|
|
||||||
@@ -42,7 +44,11 @@ public class EvdevWatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EvdevHandler handler = new EvdevHandler(PATH + "/" + fileName, listener);
|
EvdevHandler handler = new EvdevHandler(PATH + "/" + fileName, listener);
|
||||||
handler.start();
|
|
||||||
|
// If we're ungrabbed now, don't start the handler
|
||||||
|
if (!ungrabbed) {
|
||||||
|
handler.start();
|
||||||
|
}
|
||||||
|
|
||||||
handlers.put(fileName, handler);
|
handlers.put(fileName, handler);
|
||||||
}
|
}
|
||||||
@@ -78,6 +84,31 @@ public class EvdevWatcher {
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ungrabAll() {
|
||||||
|
synchronized (handlers) {
|
||||||
|
// Note that we're ungrabbed for now
|
||||||
|
ungrabbed = true;
|
||||||
|
|
||||||
|
// Stop all handlers
|
||||||
|
for (EvdevHandler handler : handlers.values()) {
|
||||||
|
handler.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void regrabAll() {
|
||||||
|
synchronized (handlers) {
|
||||||
|
// We're regrabbing everything now
|
||||||
|
ungrabbed = false;
|
||||||
|
|
||||||
|
for (Map.Entry<String, EvdevHandler> entry : handlers.entrySet()) {
|
||||||
|
// We need to recreate each entry since we can't reuse a stopped one
|
||||||
|
entry.setValue(new EvdevHandler(PATH + "/" + entry.getKey(), listener));
|
||||||
|
entry.getValue().start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
startThread = new Thread() {
|
startThread = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
@@ -119,10 +150,15 @@ public class EvdevWatcher {
|
|||||||
// Stop the observer
|
// Stop the observer
|
||||||
observer.stopWatching();
|
observer.stopWatching();
|
||||||
|
|
||||||
synchronized (handlers) {
|
synchronized (handlers) {
|
||||||
// Stop creating new handlers
|
// Stop creating new handlers
|
||||||
shutdown = true;
|
shutdown = true;
|
||||||
|
|
||||||
|
// If we've already ungrabbed, there's nothing else to do
|
||||||
|
if (ungrabbed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Stop all handlers
|
// Stop all handlers
|
||||||
for (EvdevHandler handler : handlers.values()) {
|
for (EvdevHandler handler : handlers.values()) {
|
||||||
handler.stop();
|
handler.stop();
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
|
|
||||||
private int cpuCount = Runtime.getRuntime().availableProcessors();
|
private int cpuCount = Runtime.getRuntime().availableProcessors();
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private int findOptimalPerformanceLevel() {
|
private int findOptimalPerformanceLevel() {
|
||||||
StringBuilder cpuInfo = new StringBuilder();
|
StringBuilder cpuInfo = new StringBuilder();
|
||||||
BufferedReader br = null;
|
BufferedReader br = null;
|
||||||
@@ -93,7 +94,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) {
|
public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) {
|
||||||
this.targetFps = redrawRate;
|
this.targetFps = redrawRate;
|
||||||
|
|
||||||
int perfLevel = findOptimalPerformanceLevel();
|
int perfLevel = LOW_PERF; //findOptimalPerformanceLevel();
|
||||||
int threadCount;
|
int threadCount;
|
||||||
|
|
||||||
int avcFlags = 0;
|
int avcFlags = 0;
|
||||||
|
|||||||
@@ -44,11 +44,20 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
private int numPpsIn;
|
private int numPpsIn;
|
||||||
private int numIframeIn;
|
private int numIframeIn;
|
||||||
|
|
||||||
|
public static final List<String> preferredDecoders;
|
||||||
|
|
||||||
public static final List<String> blacklistedDecoderPrefixes;
|
public static final List<String> blacklistedDecoderPrefixes;
|
||||||
public static final List<String> spsFixupBitstreamFixupDecoderPrefixes;
|
public static final List<String> spsFixupBitstreamFixupDecoderPrefixes;
|
||||||
public static final List<String> spsFixupNumRefFixupDecoderPrefixes;
|
public static final List<String> spsFixupNumRefFixupDecoderPrefixes;
|
||||||
public static final List<String> whitelistedAdaptiveResolutionPrefixes;
|
public static final List<String> whitelistedAdaptiveResolutionPrefixes;
|
||||||
|
|
||||||
|
static {
|
||||||
|
preferredDecoders = new LinkedList<String>();
|
||||||
|
|
||||||
|
// This is the most reliable of Samsung's decoders
|
||||||
|
preferredDecoders.add("OMX.SEC.AVC.Decoder");
|
||||||
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
blacklistedDecoderPrefixes = new LinkedList<String>();
|
blacklistedDecoderPrefixes = new LinkedList<String>();
|
||||||
|
|
||||||
@@ -158,6 +167,31 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static MediaCodecInfo findPreferredDecoder() {
|
||||||
|
// This is a different algorithm than the other findXXXDecoder functions,
|
||||||
|
// because we want to evaluate the decoders in our list's order
|
||||||
|
// rather than MediaCodecList's order
|
||||||
|
|
||||||
|
for (String preferredDecoder : preferredDecoders) {
|
||||||
|
for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
|
||||||
|
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
|
||||||
|
|
||||||
|
// Skip encoders
|
||||||
|
if (codecInfo.isEncoder()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for preferred decoders
|
||||||
|
if (preferredDecoder.equalsIgnoreCase(codecInfo.getName())) {
|
||||||
|
LimeLog.info("Preferred decoder choice is "+codecInfo.getName());
|
||||||
|
return codecInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static MediaCodecInfo findFirstDecoder() {
|
private static MediaCodecInfo findFirstDecoder() {
|
||||||
for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
|
for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
|
||||||
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
|
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
|
||||||
@@ -186,7 +220,13 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static MediaCodecInfo findProbableSafeDecoder() {
|
public static MediaCodecInfo findProbableSafeDecoder() {
|
||||||
// First look for decoders we know are safe
|
// First look for a preferred decoder by name
|
||||||
|
MediaCodecInfo info = findPreferredDecoder();
|
||||||
|
if (info != null) {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now look for decoders we know are safe
|
||||||
try {
|
try {
|
||||||
// If this function completes, it will determine if the decoder is safe
|
// If this function completes, it will determine if the decoder is safe
|
||||||
return findKnownSafeDecoder();
|
return findKnownSafeDecoder();
|
||||||
@@ -436,9 +476,9 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
LimeLog.info("Adding bitstream restrictions");
|
LimeLog.info("Adding bitstream restrictions");
|
||||||
|
|
||||||
sps.vuiParams.bitstreamRestriction = new VUIParameters.BitstreamRestriction();
|
sps.vuiParams.bitstreamRestriction = new VUIParameters.BitstreamRestriction();
|
||||||
sps.vuiParams.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag = false;
|
sps.vuiParams.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag = true;
|
||||||
sps.vuiParams.bitstreamRestriction.max_bytes_per_pic_denom = 0;
|
sps.vuiParams.bitstreamRestriction.max_bytes_per_pic_denom = 2;
|
||||||
sps.vuiParams.bitstreamRestriction.max_bits_per_mb_denom = 0;
|
sps.vuiParams.bitstreamRestriction.max_bits_per_mb_denom = 1;
|
||||||
sps.vuiParams.bitstreamRestriction.log2_max_mv_length_horizontal = 16;
|
sps.vuiParams.bitstreamRestriction.log2_max_mv_length_horizontal = 16;
|
||||||
sps.vuiParams.bitstreamRestriction.log2_max_mv_length_vertical = 16;
|
sps.vuiParams.bitstreamRestriction.log2_max_mv_length_vertical = 16;
|
||||||
sps.vuiParams.bitstreamRestriction.num_reorder_frames = 0;
|
sps.vuiParams.bitstreamRestriction.num_reorder_frames = 0;
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ public class ComputerManagerService extends Service {
|
|||||||
polledDetails = tryPollIp(details.remoteIp);
|
polledDetails = tryPollIp(details.remoteIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (polledDetails == null) {
|
if (polledDetails == null && !details.localIp.equals(details.remoteIp)) {
|
||||||
// Failed, so let's try the fallback
|
// Failed, so let's try the fallback
|
||||||
if (!localFirst) {
|
if (!localFirst) {
|
||||||
polledDetails = tryPollIp(details.localIp);
|
polledDetails = tryPollIp(details.localIp);
|
||||||
@@ -356,7 +356,8 @@ public class ComputerManagerService extends Service {
|
|||||||
polledDetails.reachability = !localFirst ? ComputerDetails.Reachability.LOCAL :
|
polledDetails.reachability = !localFirst ? ComputerDetails.Reachability.LOCAL :
|
||||||
ComputerDetails.Reachability.REMOTE;
|
ComputerDetails.Reachability.REMOTE;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else if (polledDetails != null) {
|
||||||
polledDetails.reachability = localFirst ? ComputerDetails.Reachability.LOCAL :
|
polledDetails.reachability = localFirst ? ComputerDetails.Reachability.LOCAL :
|
||||||
ComputerDetails.Reachability.REMOTE;
|
ComputerDetails.Reachability.REMOTE;
|
||||||
}
|
}
|
||||||
@@ -401,7 +402,12 @@ public class ComputerManagerService extends Service {
|
|||||||
public void run() {
|
public void run() {
|
||||||
boolean newPc = (details.name == null);
|
boolean newPc = (details.name == null);
|
||||||
|
|
||||||
if (stopped) {
|
// This is called from addComputerManually() where we don't
|
||||||
|
// want to block the initial poll if polling is disabled, so
|
||||||
|
// we explicitly let this through if we've never seen this
|
||||||
|
// PC before. This path won't be triggered normally when polling
|
||||||
|
// is disabled because the mDNS discovery is stopped.
|
||||||
|
if (stopped && !newPc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user