Compare commits

...

35 Commits

Author SHA1 Message Date
Cameron Gutman deb78e1c64 Version 7.4 2019-06-05 23:02:06 -07:00
Cameron Gutman 9aec6b1d31 Target API 29 2019-06-05 22:59:39 -07:00
Cameron Gutman 97702b8861 Fix mouse capture after returning focus to the window on Android Q 2019-06-05 22:43:16 -07:00
Cameron Gutman 832e7197c5 Delay a bit before reporting USB devices to allow the old InputDevice to go away 2019-06-05 22:26:06 -07:00
Cameron Gutman 26b992726c Use transparent status bar and navigation bar on Android Q 2019-06-05 21:50:03 -07:00
Cameron Gutman 1cb3588841 Use low latency WifiLock on Android Q 2019-06-05 21:09:55 -07:00
Cameron Gutman b461d546d6 Use new MediaCodecInfo helper to blacklist software codecs 2019-06-05 21:05:33 -07:00
Cameron Gutman b7810d6eb6 Use the newly public InputDevice.isExternal() function on Android Q 2019-06-05 20:23:22 -07:00
Cameron Gutman 6fb3a8e57d Build with the Android Q SDK 2019-06-05 20:21:19 -07:00
Cameron Gutman b521c784bc Version 7.3.1 2019-05-27 01:48:00 -07:00
twboyii 8e1641af5f Add untranslated string in zh-rTW (#701) 2019-05-27 01:47:10 -07:00
Cameron Gutman c0aac01d33 Update AGP to 3.4.1 2019-05-27 01:43:38 -07:00
Cameron Gutman 4f8b0adcbb Fix video on GFE 3.19 2019-05-27 01:42:39 -07:00
Cameron Gutman 393a4c9c8a Fix pointer capture on Android Q Beta 3 2019-05-16 21:27:01 -07:00
Cameron Gutman 99b53f9a6a Version 7.3 2019-05-07 20:53:12 -07:00
Cameron Gutman 8da563b280 Bound queued audio data to prevent excessive latency 2019-05-07 20:39:45 -07:00
Cameron Gutman d5b950e5cf Version 7.2.1 2019-05-01 20:14:21 -07:00
Cameron Gutman c46b9acf6b Update common to fix receive time 2019-04-30 23:19:19 -07:00
Cameron Gutman d8e322bac9 Sync PC offline icon with Moonlight Qt 2019-04-30 22:27:22 -07:00
Cameron Gutman 44871626cf Version 7.2 2019-04-27 22:11:02 -07:00
Cameron Gutman f661522b5d Update moonlight-common with additional perf improvements 2019-04-27 22:00:27 -07:00
Cameron Gutman a454b0ab78 Update moonlight-common with perf improvements 2019-04-26 18:37:27 -07:00
Cameron Gutman 75bf84d0d9 Update Gradle for AS 3.4 2019-04-26 18:34:16 -07:00
Cameron Gutman c248994ed4 Version 7.1 2019-04-07 14:09:58 -07:00
Cameron Gutman a7a34ec629 Update vibration weights to match Moonlight Qt 2019-04-06 01:02:03 -07:00
Cameron Gutman 8d469c5d0a Add on-screen connection warnings 2019-04-06 00:56:45 -07:00
Cameron Gutman e6979d50b5 Update AGP to 3.3.2 2019-04-06 00:48:40 -07:00
Cameron Gutman 6e25b135a3 Update ProGuard rules to avoid slf4j warnings 2019-03-20 18:57:40 -07:00
Cameron Gutman 04e093a2c2 Update moonlight-common 2019-03-20 18:51:08 -07:00
bubuleur 813f2edd95 Update French Language (#676) 2019-03-02 20:01:21 -08:00
Cameron Gutman 337d753a33 Reduce gamepad deadzone to 7% 2019-03-02 17:23:01 -08:00
Cameron Gutman 1137c74f76 Pass AudioAttributes on L+ when vibrating 2019-03-02 17:20:39 -08:00
Cameron Gutman 0c1451f757 Improve scaling of lock icon by increasing dimensions 2019-02-18 20:46:34 -08:00
Cameron Gutman 5ab9ea48fd Version 7.0.1 2019-02-17 18:20:40 -08:00
Cameron Gutman ffcb623040 Fix crash when a rumble effect only uses the high-frequency motor 2019-02-17 18:18:00 -08:00
18 changed files with 245 additions and 77 deletions
+5 -5
View File
@@ -1,15 +1,15 @@
apply plugin: 'com.android.application'
android {
buildToolsVersion '28.0.3'
compileSdkVersion 28
buildToolsVersion '29.0.0'
compileSdkVersion 29
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
targetSdkVersion 29
versionName "7.0"
versionCode = 187
versionName "7.4"
versionCode = 195
}
flavorDimensions "root"
+1
View File
@@ -25,3 +25,4 @@
# jMDNS
-dontwarn javax.jmdns.impl.DNSCache
-dontwarn org.slf4j.**
+70 -11
View File
@@ -66,6 +66,7 @@ import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.widget.Toast;
import java.io.ByteArrayInputStream;
@@ -111,13 +112,15 @@ public class Game extends Activity implements SurfaceHolder.Callback,
private boolean grabbedInput = true;
private boolean grabComboDown = false;
private StreamView streamView;
private TextView notificationOverlayView;
private ShortcutHelper shortcutHelper;
private MediaCodecDecoderRenderer decoderRenderer;
private boolean reportedCrash;
private WifiManager.WifiLock wifiLock;
private WifiManager.WifiLock highPerfWifiLock;
private WifiManager.WifiLock lowLatencyWifiLock;
private boolean connectedToUsbDriverService = false;
private ServiceConnection usbDriverServiceConnection = new ServiceConnection() {
@@ -202,6 +205,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
streamView.setOnTouchListener(this);
streamView.setInputCallbacks(this);
notificationOverlayView = findViewById(R.id.notificationOverlay);
inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -224,9 +229,15 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// Make sure Wi-Fi is fully powered up
WifiManager wifiMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "Limelight");
wifiLock.setReferenceCounted(false);
wifiLock.acquire();
highPerfWifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "Moonlight High Perf Lock");
highPerfWifiLock.setReferenceCounted(false);
highPerfWifiLock.acquire();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
lowLatencyWifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "Moonlight Low Latency Lock");
lowLatencyWifiLock.setReferenceCounted(false);
lowLatencyWifiLock.acquire();
}
String host = Game.this.getIntent().getStringExtra(EXTRA_HOST);
String appName = Game.this.getIntent().getStringExtra(EXTRA_APP_NAME);
@@ -506,8 +517,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// Capture is lost when focus is lost, so it must be requested again
// when focus is regained.
if (inputCaptureProvider.isCapturingEnabled() && hasFocus) {
// Recapture the pointer if focus was regained
streamView.requestPointerCapture();
// Recapture the pointer if focus was regained. On Android Q,
// we have to delay a bit before requesting capture because otherwise
// we'll hit the "requestPointerCapture called for a window that has no focus"
// error and it will not actually capture the cursor.
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
streamView.requestPointerCapture();
}
}, 500);
}
}
}
@@ -698,7 +718,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
inputManager.unregisterInputDeviceListener(controllerHandler);
}
wifiLock.release();
if (lowLatencyWifiLock != null) {
lowLatencyWifiLock.release();
}
if (highPerfWifiLock != null) {
highPerfWifiLock.release();
}
if (connectedToUsbDriverService) {
// Unbind from the discovery service
@@ -1339,6 +1364,32 @@ public class Game extends Activity implements SurfaceHolder.Callback,
});
}
@Override
public void connectionStatusUpdate(final int connectionStatus) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (prefConfig.disableWarnings) {
return;
}
if (connectionStatus == MoonBridge.CONN_STATUS_POOR) {
if (prefConfig.bitrate > 5000) {
notificationOverlayView.setText(getResources().getString(R.string.slow_connection_msg));
}
else {
notificationOverlayView.setText(getResources().getString(R.string.poor_connection_msg));
}
notificationOverlayView.setVisibility(View.VISIBLE);
}
else if (connectionStatus == MoonBridge.CONN_STATUS_OKAY) {
notificationOverlayView.setVisibility(View.GONE);
}
}
});
}
@Override
public void connectionStarted() {
runOnUiThread(new Runnable() {
@@ -1352,10 +1403,18 @@ public class Game extends Activity implements SurfaceHolder.Callback,
connected = true;
connecting = false;
// Hide the mouse cursor now. Doing it before
// dismissing the spinner seems to be undone
// when the spinner gets displayed.
inputCaptureProvider.enableCapture();
// Hide the mouse cursor now after a short delay.
// Doing it before dismissing the spinner seems to be undone
// when the spinner gets displayed. On Android Q, even now
// is too early to capture. We will delay a second to allow
// the spinner to dismiss before capturing.
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
inputCaptureProvider.enableCapture();
}
}, 500);
// Keep the display on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
@@ -168,8 +168,17 @@ public class AndroidAudioRenderer implements AudioRenderer {
}
@Override
public void playDecodedAudio(byte[] audioData) {
track.write(audioData, 0, audioData.length);
public void playDecodedAudio(short[] audioData) {
// Only queue up to 40 ms of pending audio data in addition to what AudioTrack is buffering for us.
if (MoonBridge.getPendingAudioFrames() < 8) {
// This will block until the write is completed. That can cause a backlog
// of pending audio data, so we do the above check to be able to bound
// latency at 40 ms in that situation.
track.write(audioData, 0, audioData.length);
}
else {
LimeLog.info("Too many pending audio frames: " + MoonBridge.getPendingAudioFrames());
}
}
@Override
@@ -68,9 +68,9 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
this.prefConfig = prefConfig;
this.deviceVibrator = (Vibrator) activityContext.getSystemService(Context.VIBRATOR_SERVICE);
// HACK: For now we're hardcoding a 10% deadzone. Some deadzone
// HACK: For now we're hardcoding a 7% deadzone. Some deadzone
// is required for controller batching support to work.
int deadzonePercentage = 10;
int deadzonePercentage = 7;
int[] ids = InputDevice.getDeviceIds();
for (int id : ids) {
@@ -335,17 +335,23 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
}
private static boolean isExternal(InputDevice dev) {
try {
// Landroid/view/InputDevice;->isExternal()Z is on the light graylist in Android P
return (Boolean)dev.getClass().getMethod("isExternal").invoke(dev);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassCastException e) {
e.printStackTrace();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Landroid/view/InputDevice;->isExternal()Z is officially public on Android Q
return dev.isExternal();
}
else {
try {
// Landroid/view/InputDevice;->isExternal()Z is on the light graylist in Android P
return (Boolean)dev.getClass().getMethod("isExternal").invoke(dev);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassCastException e) {
e.printStackTrace();
}
}
// Answer true if we don't know
@@ -1072,19 +1078,22 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
}
private void rumbleVibrator(Vibrator vibrator, short lowFreqMotor, short highFreqMotor) {
if (lowFreqMotor == 0 && highFreqMotor == 0) {
// This case is easy - just cancel and get out
// Since we can only use a single amplitude value, compute the desired amplitude
// by taking 80% of the big motor and 33% of the small motor, then capping to 255.
// NB: This value is now 0-255 as required by VibrationEffect.
short lowFreqMotorMSB = (short)((lowFreqMotor >> 8) & 0xFF);
short highFreqMotorMSB = (short)((highFreqMotor >> 8) & 0xFF);
int simulatedAmplitude = Math.min(255, (int)((lowFreqMotorMSB * 0.80) + (highFreqMotorMSB * 0.33)));
if (simulatedAmplitude == 0) {
// This case is easy - just cancel the current effect and get out.
// NB: We cannot simply check lowFreqMotor == highFreqMotor == 0
// because our simulatedAmplitude could be 0 even though our inputs
// are not (ex: lowFreqMotor == 0 && highFreqMotor == 1).
vibrator.cancel();
return;
}
// Since we can only use a single amplitude value, compute the desired amplitude
// by taking 75% of the big motor and 25% of the small motor.
// NB: This value is now 0-255 as required by VibrationEffect.
short lowFreqMotorMSB = (short)((lowFreqMotor >> 8) & 0xFF);
short highFreqMotorMSB = (short)((lowFreqMotor >> 8) & 0xFF);
int simulatedAmplitude = (int)((lowFreqMotorMSB * 0.75) + (highFreqMotorMSB * 0.25));
// Attempt to use amplitude-based control if we're on Oreo and the device
// supports amplitude-based vibration control.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -1103,7 +1112,15 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
long pwmPeriod = 20;
long onTime = (long)((simulatedAmplitude / 255.0) * pwmPeriod);
long offTime = pwmPeriod - onTime;
vibrator.vibrate(new long[]{0, onTime, offTime}, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.build();
vibrator.vibrate(new long[]{0, onTime, offTime}, 0, audioAttributes);
}
else {
vibrator.vibrate(new long[]{0, onTime, offTime}, 0);
}
}
public void handleRumble(short controllerNumber, short lowFreqMotor, short highFreqMotor) {
@@ -30,6 +30,18 @@ public abstract class AbstractXboxController extends AbstractController {
private Thread createInputThread() {
return new Thread() {
public void run() {
try {
// Delay for a moment before reporting the new gamepad and
// accepting new input. This allows time for the old InputDevice
// to go away before we reclaim its spot. If the old device is still
// around when we call notifyDeviceAdded(), we won't be able to claim
// the controller number used by the original InputDevice.
Thread.sleep(1000);
} catch (InterruptedException e) {}
// Report that we're added _before_ reporting input
notifyDeviceAdded();
while (!isInterrupted() && !stopped) {
byte[] buffer = new byte[64];
@@ -114,9 +126,6 @@ public abstract class AbstractXboxController extends AbstractController {
return false;
}
// Report that we're added _before_ starting the input thread
notifyDeviceAdded();
// Start listening for controller input
inputThread = createInputThread();
inputThread.start();
@@ -474,6 +474,24 @@ public class MediaCodecHelper {
return null;
}
private static boolean isCodecBlacklisted(MediaCodecInfo codecInfo) {
// Use the new isSoftwareOnly() function on Android Q
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (codecInfo.isSoftwareOnly()) {
LimeLog.info("Skipping software-only decoder: "+codecInfo.getName());
return true;
}
}
// Check for explicitly blacklisted decoders
if (isDecoderInList(blacklistedDecoderPrefixes, codecInfo.getName())) {
LimeLog.info("Skipping blacklisted decoder: "+codecInfo.getName());
return true;
}
return false;
}
public static MediaCodecInfo findFirstDecoder(String mimeType) {
for (MediaCodecInfo codecInfo : getMediaCodecList()) {
@@ -482,15 +500,14 @@ public class MediaCodecHelper {
continue;
}
// Check for explicitly blacklisted decoders
if (isDecoderInList(blacklistedDecoderPrefixes, codecInfo.getName())) {
LimeLog.info("Skipping blacklisted decoder: "+codecInfo.getName());
continue;
}
// Find a decoder that supports the specified video format
for (String mime : codecInfo.getSupportedTypes()) {
if (mime.equalsIgnoreCase(mimeType)) {
// Skip blacklisted codecs
if (isCodecBlacklisted(codecInfo)) {
continue;
}
LimeLog.info("First decoder choice is "+codecInfo.getName());
return codecInfo;
}
@@ -530,17 +547,16 @@ public class MediaCodecHelper {
continue;
}
// Check for explicitly blacklisted decoders
if (isDecoderInList(blacklistedDecoderPrefixes, codecInfo.getName())) {
LimeLog.info("Skipping blacklisted decoder: "+codecInfo.getName());
continue;
}
// Find a decoder that supports the requested video format
for (String mime : codecInfo.getSupportedTypes()) {
if (mime.equalsIgnoreCase(mimeType)) {
LimeLog.info("Examining decoder capabilities of "+codecInfo.getName());
// Skip blacklisted codecs
if (isCodecBlacklisted(codecInfo)) {
//continue;
}
CodecCapabilities caps = codecInfo.getCapabilitiesForType(mime);
if (requiredProfile != -1) {
+8 -4
View File
@@ -1,5 +1,9 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="128dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"
android:fillColor="#FFFFFF"/>
</vector>
+4 -8
View File
@@ -1,9 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="128dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M23.64,7c-0.45,-0.34 -4.93,-4 -11.64,-4 -1.5,0 -2.89,0.19 -4.15,0.48L18.18,13.8 23.64,7zM17.04,15.22L3.27,1.44 2,2.72l2.05,2.06C1.91,5.76 0.59,6.82 0.36,7l11.63,14.49 0.01,0.01 0.01,-0.01 3.9,-4.86 3.32,3.32 1.27,-1.27 -3.46,-3.46z"
android:fillColor="#FFFFFF"/>
<vector android:height="128dp" android:width="128dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>
</vector>
+12
View File
@@ -10,4 +10,16 @@
android:layout_height="match_parent"
android:layout_gravity="center" />
<TextView
android:id="@+id/notificationOverlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_gravity="right"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="right"
android:background="#80000000"
android:visibility="gone" />
</merge>
+5
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Shortcut strings -->
<string name="scut_deleted_pc">PC supprimé</string>
<string name="scut_not_paired">PC non appairé</string>
@@ -133,6 +134,8 @@
<string name="category_input_settings">Paramètres d\'entrée</string>
<string name="title_checkbox_multi_controller">Prise en charge de plusieurs contrôleurs</string>
<string name="summary_checkbox_multi_controller">Lorsqu\'elle n\'est pas cochée, tous les contrôleurs sont regroupés</string>
<string name="title_checkbox_vibrate_fallback">Emuler le support vibration</string>
<string name="summary_checkbox_vibrate_fallback">Vibre votre appareil pour émuler une vibration si votre manette ne le prend pas en charge</string>
<string name="title_seekbar_deadzone">Régler la zone morte du stick analogique</string>
<string name="suffix_seekbar_deadzone">%</string>
<string name="title_checkbox_xb1_driver">Pilote de contrôleur Xbox 360/One</string>
@@ -147,6 +150,8 @@
<string name="category_on_screen_controls_settings">Paramètres des contrôles à l\'écran</string>
<string name="title_checkbox_show_onscreen_controls">Afficher les commandes à l\'écran</string>
<string name="summary_checkbox_show_onscreen_controls">Afficher la superposition du contrôleur virtuel sur l\'écran tactile</string>
<string name="title_checkbox_vibrate_osc">Activer les vibrations</string>
<string name="summary_checkbox_vibrate_osc">Vibre votre appareil pour émuler les vibrations des commandes à l\'écran</string>
<string name="title_only_l3r3">Montre seulement L3 et R3</string>
<string name="summary_only_l3r3">Cacher tout sauf L3 et R3</string>
<string name="title_reset_osc">Effacer la disposition des commandes à l\'écran sauvegardée</string>
+6
View File
@@ -0,0 +1,6 @@
<resources>
<style name="AppBaseTheme" parent="android:Theme.Material">
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
+32 -5
View File
@@ -97,27 +97,51 @@
<string name="category_basic_settings"> 基本設置 </string>
<string name="title_resolution_list"> 選擇目標解析度和幀數 </string>
<string name="summary_resolution_list"> 過高的設定會引起串流卡頓甚至軟體閃退 </string>
<string name="title_seekbar_bitrate"> 選擇目標視頻碼率 </string>
<string name="title_fps_list">影像幀數</string>
<string name="summary_fps_list">增加以提供更流暢的影像串流. 減少以在較低的配備上獲得較好的效能.</string>
<string name="title_seekbar_bitrate"> 選擇目標影像碼率 </string>
<string name="summary_seekbar_bitrate"> 低碼率減少卡頓,高碼率提高畫質 </string>
<string name="suffix_seekbar_bitrate">Kbps</string>
<string name="title_unlock_fps">解鎖所有可使用的幀率</string>
<string name="summary_unlock_fps">串流於90或120幀下可以減少高級配備的延遲, 但可能導致無法支持的配備出現延遲或崩潰</string>
<string name="title_checkbox_stretch_video"> 將畫面拉伸至全屏 </string>
<string name="title_checkbox_disable_warnings"> 禁用錯誤提示 </string>
<string name="summary_checkbox_disable_warnings"> 串流過程中禁用連接錯誤提示 </string>
<string name="title_checkbox_enable_pip">啟用子母畫面</string>
<string name="summary_checkbox_enable_pip">當多工處理時, 允許觀看串流畫面(無法控制)</string>
<string name="category_audio_settings"> 音頻設置 </string>
<string name="title_checkbox_51_surround"> 啟用 5.1 環繞音效 </string>
<string name="summary_checkbox_51_surround"> 如果你的聲音聽起來有問題請禁用。\n\n需要GeForce Experience 2.7 或更高版本 </string>
<string name="category_input_settings">輸入設定</string>
<string name="title_checkbox_multi_controller"> 啟用多手柄支持 </string>
<string name="summary_checkbox_multi_controller"> 如果禁用,所有手柄將會認作一個手柄 </string>
<string name="title_seekbar_deadzone"> 調整搖桿死區 </string>
<string name="title_checkbox_vibrate_fallback">以手機模擬手柄震動</string>
<string name="summary_checkbox_vibrate_fallback">當手柄不支援震動時, 以手機來模擬</string>
<string name="title_seekbar_deadzone"> 調整手柄死區 </string>
<string name="suffix_seekbar_deadzone">%</string>
<string name="title_checkbox_xb1_driver">Xbox 360/One 手柄驅動 </string>
<string name="summary_checkbox_xb1_driver"> 若要在那些沒有原生Xbox手柄驅動的設備上使用Xbox手柄,請勾上此複選框 </string>
<string name="title_checkbox_usb_bind_all">覆蓋Android控制器支援</string>
<string name="summary_checkbox_usb_bind_all">強制 Moonlight USB驅動程式接管所有支持的Xbox手柄</string>
<string name="title_checkbox_mouse_emulation">透過手柄模擬滑鼠</string>
<string name="summary_checkbox_mouse_emulation">長按 [Start] 鍵將會切換至滑鼠模式</string>
<string name="title_checkbox_mouse_nav_buttons">Enable back and forward mouse buttons</string>
<string name="summary_checkbox_mouse_nav_buttons">Enabling this option may break right clicking on some buggy devices</string>
<string name="category_on_screen_controls_settings">設置 </string>
<string name="category_on_screen_controls_settings">設置 </string>
<string name="title_checkbox_show_onscreen_controls"> 啟用虛擬手柄 </string>
<string name="summary_checkbox_show_onscreen_controls"> 將在串流畫面上顯示一層虛擬手柄 </string>
<string name="title_checkbox_vibrate_osc">啟用震動</string>
<string name="summary_checkbox_vibrate_osc">在手機上模擬搖桿震動</string>
<string name="title_only_l3r3">只顯示[L3]及[R3]</string>
<string name="summary_only_l3r3">隱藏所有虛擬按鈕除了L3和R3</string>
<string name="title_reset_osc">重設已經保存的觸控按鈕布局</string>
<string name="summary_reset_osc">將所有觸控按鈕重設為默認之大小和位置</string>
<string name="dialog_title_reset_osc">重設按鈕布局</string>
<string name="dialog_text_reset_osc">你確定要刪除所保存的按鈕布局嗎?</string>
<string name="toast_reset_osc_success">按鈕布局已經重設</string>
<string name="category_ui_settings"> 界面設置 </string>
<string name="title_language_list">語言</string>
@@ -134,7 +158,10 @@
<string name="summary_checkbox_host_audio"> 將在電腦和本設備同時輸出聲音 </string>
<string name="category_advanced_settings"> 高級設置 </string>
<string name="title_disable_frame_drop">永遠不掉幀</string>
<string name="summary_disable_frame_drop">在一些手機上可能可以減少micro-stuttering, 但可能導致延遲</string>
<string name="title_video_format"> H.265設置 </string>
<string name="summary_video_format">H.265能降低寬需求,但是需要設備支持 </string>
<string name="summary_video_format">H.265能降低寬需求,但是需要設備支持 </string>
<string name="title_enable_hdr">啟用 HDR (實驗中)</string>
<string name="summary_enable_hdr">啟用 HDR 當遊戲與電腦的顯示卡支援時. HDR 需要 GTX 1000 系列之顯示卡或更高.</string>
</resources>
+2
View File
@@ -84,6 +84,8 @@
<string name="title_details">Details</string>
<string name="help">Help</string>
<string name="delete_pc_msg">Are you sure you want to delete this PC?</string>
<string name="slow_connection_msg">Slow connection to PC\nReduce your bitrate</string>
<string name="poor_connection_msg">Poor connection to PC</string>
<!-- AppList activity -->
<string name="applist_connect_msg">Connecting to PC…</string>
+5
View File
@@ -149,6 +149,11 @@
</PreferenceCategory>
<PreferenceCategory android:title="@string/category_advanced_settings"
android:key="category_advanced_settings">
<CheckBoxPreference
android:key="checkbox_disable_warnings"
android:title="@string/title_checkbox_disable_warnings"
android:summary="@string/summary_checkbox_disable_warnings"
android:defaultValue="false" />
<ListPreference
android:key="video_format"
android:title="@string/title_video_format"
+1 -1
View File
@@ -5,7 +5,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.1'
classpath 'com.android.tools.build:gradle:3.4.1'
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
#Tue Feb 05 20:54:22 PST 2019
#Fri Apr 26 18:29:34 PDT 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip