Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2fbe6ad91 | |||
| cf07c02398 | |||
| 42dc928ad5 | |||
| 11597f0aa7 | |||
| cdcd4d48f2 | |||
| a9af4e54a9 | |||
| 7eac609219 | |||
| fa761debc4 | |||
| 62e175f069 | |||
| d7d8c40565 | |||
| 64de13ab50 | |||
| 2f02939638 | |||
| 1d7c8697e9 | |||
| 7dea322bbd | |||
| 349ecb16ab | |||
| a3867735c1 | |||
| 5b087e9f70 | |||
| eed18223eb | |||
| 30d4d2a918 | |||
| 30f666c70e | |||
| 209fead0e8 | |||
| 5c6889bf6d | |||
| 7d24900756 | |||
| 79a75b9d19 | |||
| 29b64992bd | |||
| c9b14540f2 | |||
| 546843a26c | |||
| d03d260535 | |||
| 6946e3c7a2 | |||
| b79d328961 | |||
| c313797d93 | |||
| c8cb8e1346 | |||
| 6a9f8da14e | |||
| ff9260a0fd | |||
| 62bedb1609 | |||
| a519723d44 |
@@ -0,0 +1,8 @@
|
||||
# ProBot No Response (https://probot.github.io/apps/no-response/)
|
||||
|
||||
daysUntilClose: 7
|
||||
responseRequiredLabel: 'need more info'
|
||||
closeComment: >
|
||||
This issue has been automatically closed because there was no response to a
|
||||
request for more information from the issue opener. Please leave a comment or
|
||||
open a new issue if you have additional information related to this issue.
|
||||
@@ -0,0 +1,14 @@
|
||||
# ProBot Stale (https://probot.github.io/apps/stale/)
|
||||
|
||||
daysUntilStale: 90
|
||||
daysUntilClose: 7
|
||||
exemptLabels:
|
||||
- accepted
|
||||
- bug
|
||||
- enhancement
|
||||
- meta
|
||||
staleLabel: stale
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs.
|
||||
closeComment: false
|
||||
@@ -1,4 +1,4 @@
|
||||
# Moonlight
|
||||
# Moonlight Android
|
||||
|
||||
[Moonlight](http://moonlight-stream.com) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield.
|
||||
We reverse engineered the Shield streaming software and created a version that can be run on any Android device.
|
||||
@@ -6,8 +6,6 @@ We reverse engineered the Shield streaming software and created a version that c
|
||||
Moonlight will allow you to stream your full collection of games from your Windows PC to your Android device,
|
||||
whether in your own home or over the internet.
|
||||
|
||||
[Moonlight-pc](https://github.com/moonlight-stream/moonlight-pc) is also currently in development for Windows, OS X and Linux. Versions for [iOS](https://github.com/moonlight-stream/moonlight-ios) and [Windows and Windows Phone](https://github.com/moonlight-stream/moonlight-windows) are also in development.
|
||||
|
||||
Check our [wiki](https://github.com/moonlight-stream/moonlight-docs/wiki) for more detailed information or a troubleshooting guide.
|
||||
|
||||
## Features
|
||||
|
||||
+3
-3
@@ -1,15 +1,15 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
buildToolsVersion '28.0.0'
|
||||
buildToolsVersion '28.0.3'
|
||||
compileSdkVersion 28
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
|
||||
versionName "5.8.2"
|
||||
versionCode = 167
|
||||
versionName "5.9.4"
|
||||
versionCode = 173
|
||||
}
|
||||
|
||||
flavorDimensions "root"
|
||||
|
||||
@@ -67,8 +67,9 @@
|
||||
</activity>
|
||||
<!-- Small hack to support launcher shortcuts without relaunching over and over again when the back button is pressed -->
|
||||
<activity
|
||||
android:name=".AppViewShortcutTrampoline"
|
||||
android:name=".ShortcutTrampoline"
|
||||
android:noHistory="true"
|
||||
android:exported="true"
|
||||
android:resizeableActivity="true"
|
||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
||||
<meta-data
|
||||
|
||||
@@ -26,6 +26,10 @@ import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.view.ContextMenu;
|
||||
@@ -36,6 +40,7 @@ import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||
@@ -56,7 +61,9 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
private final static int START_OR_RESUME_ID = 1;
|
||||
private final static int QUIT_ID = 2;
|
||||
private final static int CANCEL_ID = 3;
|
||||
private final static int START_WTIH_QUIT = 4;
|
||||
private final static int START_WITH_QUIT = 4;
|
||||
private final static int VIEW_DETAILS_ID = 5;
|
||||
private final static int CREATE_SHORTCUT_ID = 6;
|
||||
|
||||
public final static String NAME_EXTRA = "Name";
|
||||
public final static String UUID_EXTRA = "UUID";
|
||||
@@ -251,10 +258,9 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
|
||||
String computerName = getIntent().getStringExtra(NAME_EXTRA);
|
||||
|
||||
String labelText = getResources().getString(R.string.title_applist)+" "+computerName;
|
||||
TextView label = findViewById(R.id.appListText);
|
||||
setTitle(labelText);
|
||||
label.setText(labelText);
|
||||
setTitle(computerName);
|
||||
label.setText(computerName);
|
||||
|
||||
// Add a launcher shortcut for this PC (forced, since this is user interaction)
|
||||
shortcutHelper.createAppViewShortcut(uuidString, computerName, uuidString, true);
|
||||
@@ -331,10 +337,25 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
menu.add(Menu.NONE, QUIT_ID, 2, getResources().getString(R.string.applist_menu_quit));
|
||||
}
|
||||
else {
|
||||
menu.add(Menu.NONE, START_WTIH_QUIT, 1, getResources().getString(R.string.applist_menu_quit_and_start));
|
||||
menu.add(Menu.NONE, START_WITH_QUIT, 1, getResources().getString(R.string.applist_menu_quit_and_start));
|
||||
menu.add(Menu.NONE, CANCEL_ID, 2, getResources().getString(R.string.applist_menu_cancel));
|
||||
}
|
||||
}
|
||||
menu.add(Menu.NONE, VIEW_DETAILS_ID, 3, getResources().getString(R.string.applist_menu_details));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// Only add an option to create shortcut if box art is loaded
|
||||
// and when we're in grid-mode (not list-mode).
|
||||
ImageView appImageView = info.targetView.findViewById(R.id.grid_image);
|
||||
if (appImageView != null) {
|
||||
// We have a grid ImageView, so we must be in grid-mode
|
||||
BitmapDrawable drawable = (BitmapDrawable)appImageView.getDrawable();
|
||||
if (drawable != null && drawable.getBitmap() != null) {
|
||||
// We have a bitmap loaded too
|
||||
menu.add(Menu.NONE, CREATE_SHORTCUT_ID, 4, getResources().getString(R.string.applist_menu_scut));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -346,7 +367,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
|
||||
final AppObject app = (AppObject) appGridAdapter.getItem(info.position);
|
||||
switch (item.getItemId()) {
|
||||
case START_WTIH_QUIT:
|
||||
case START_WITH_QUIT:
|
||||
// Display a confirmation dialog first
|
||||
UiHelper.displayQuitConfirmationDialog(this, new Runnable() {
|
||||
@Override
|
||||
@@ -386,6 +407,19 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
case CANCEL_ID:
|
||||
return true;
|
||||
|
||||
case VIEW_DETAILS_ID:
|
||||
Dialog.displayDialog(AppView.this, getResources().getString(R.string.title_details),
|
||||
getResources().getString(R.string.applist_details_id) + " " + app.app.getAppId(), false);
|
||||
return true;
|
||||
|
||||
case CREATE_SHORTCUT_ID:
|
||||
ImageView appImageView = info.targetView.findViewById(R.id.grid_image);
|
||||
Bitmap appBits = ((BitmapDrawable)appImageView.getDrawable()).getBitmap();
|
||||
if (!shortcutHelper.createPinnedGameShortcut(uuidString + Integer.valueOf(app.app.getAppId()).toString(), appBits, computer, app.app)) {
|
||||
Toast.makeText(AppView.this, getResources().getString(R.string.unable_to_pin_shortcut), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
package com.limelight;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
import com.limelight.computers.ComputerManagerListener;
|
||||
import com.limelight.computers.ComputerManagerService;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.nvstream.http.NvApp;
|
||||
import com.limelight.utils.Dialog;
|
||||
import com.limelight.utils.ServerHelper;
|
||||
import com.limelight.utils.SpinnerDialog;
|
||||
import com.limelight.utils.UiHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AppViewShortcutTrampoline extends Activity {
|
||||
private String uuidString;
|
||||
|
||||
private ComputerDetails computer;
|
||||
private SpinnerDialog blockingLoadSpinner;
|
||||
|
||||
public final static String UUID_EXTRA = "UUID";
|
||||
|
||||
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder binder) {
|
||||
final ComputerManagerService.ComputerManagerBinder localBinder =
|
||||
((ComputerManagerService.ComputerManagerBinder)binder);
|
||||
|
||||
// Wait in a separate thread to avoid stalling the UI
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Wait for the binder to be ready
|
||||
localBinder.waitForReady();
|
||||
|
||||
// Now make the binder visible
|
||||
managerBinder = localBinder;
|
||||
|
||||
// Get the computer object
|
||||
computer = managerBinder.getComputer(UUID.fromString(uuidString));
|
||||
|
||||
// Force CMS to repoll this machine
|
||||
managerBinder.invalidateStateForComputer(computer.uuid);
|
||||
|
||||
// Start polling
|
||||
managerBinder.startPolling(new ComputerManagerListener() {
|
||||
@Override
|
||||
public void notifyComputerUpdated(final ComputerDetails details) {
|
||||
// Don't care about other computers
|
||||
if (!details.uuid.toString().equalsIgnoreCase(uuidString)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (details.state != ComputerDetails.State.UNKNOWN) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Stop showing the spinner
|
||||
if (blockingLoadSpinner != null) {
|
||||
blockingLoadSpinner.dismiss();
|
||||
blockingLoadSpinner = null;
|
||||
}
|
||||
|
||||
// If the managerBinder was destroyed before this callback,
|
||||
// just finish the activity.
|
||||
if (managerBinder == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (details.state == ComputerDetails.State.ONLINE) {
|
||||
// Close this activity
|
||||
finish();
|
||||
|
||||
// Create a new activity stack for this launch
|
||||
ArrayList<Intent> intentStack = new ArrayList<>();
|
||||
Intent i;
|
||||
|
||||
// Add the PC view at the back (and clear the task)
|
||||
i = new Intent(AppViewShortcutTrampoline.this, PcView.class);
|
||||
i.setAction(Intent.ACTION_MAIN);
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intentStack.add(i);
|
||||
|
||||
// Take this intent's data and create an intent to start the app view
|
||||
i = new Intent(getIntent());
|
||||
i.setClass(AppViewShortcutTrampoline.this, AppView.class);
|
||||
intentStack.add(i);
|
||||
|
||||
// If a game is running, we'll make the stream the top level activity
|
||||
if (details.runningGameId != 0) {
|
||||
intentStack.add(ServerHelper.createStartIntent(AppViewShortcutTrampoline.this,
|
||||
new NvApp("app", details.runningGameId, false), details, managerBinder));
|
||||
}
|
||||
|
||||
// Now start the activities
|
||||
startActivities(intentStack.toArray(new Intent[]{}));
|
||||
}
|
||||
else if (details.state == ComputerDetails.State.OFFLINE) {
|
||||
// Computer offline - display an error dialog
|
||||
Dialog.displayDialog(AppViewShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.error_pc_offline),
|
||||
true);
|
||||
}
|
||||
|
||||
// We don't want any more callbacks from now on, so go ahead
|
||||
// and unbind from the service
|
||||
if (managerBinder != null) {
|
||||
managerBinder.stopPolling();
|
||||
unbindService(serviceConnection);
|
||||
managerBinder = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
managerBinder = null;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
UiHelper.notifyNewRootView(this);
|
||||
|
||||
uuidString = getIntent().getStringExtra(UUID_EXTRA);
|
||||
|
||||
// Bind to the computer manager service
|
||||
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
|
||||
Service.BIND_AUTO_CREATE);
|
||||
|
||||
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
|
||||
getResources().getString(R.string.applist_connect_msg), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (blockingLoadSpinner != null) {
|
||||
blockingLoadSpinner.dismiss();
|
||||
blockingLoadSpinner = null;
|
||||
}
|
||||
|
||||
Dialog.closeDialogs();
|
||||
|
||||
if (managerBinder != null) {
|
||||
managerBinder.stopPolling();
|
||||
unbindService(serviceConnection);
|
||||
managerBinder = null;
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
private boolean grabbedInput = true;
|
||||
private boolean grabComboDown = false;
|
||||
private StreamView streamView;
|
||||
private boolean gotBackPointerEvent = false;
|
||||
private boolean syntheticBackDown = false;
|
||||
|
||||
private ShortcutHelper shortcutHelper;
|
||||
|
||||
@@ -838,9 +840,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// the right mouse button is held down, so we ignore those.
|
||||
if ((event.getSource() == InputDevice.SOURCE_MOUSE ||
|
||||
event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE) &&
|
||||
event.getKeyCode() == KeyEvent.KEYCODE_BACK &&
|
||||
event.getRepeatCount() == 0) {
|
||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
||||
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
||||
// It appears this may get turned into a right-click pointer event
|
||||
// if we don't return true to indicate that we handled it on
|
||||
// some devices. https://github.com/moonlight-stream/moonlight-android/issues/634
|
||||
if (event.getRepeatCount() == 0 && !gotBackPointerEvent) {
|
||||
syntheticBackDown = true;
|
||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -892,7 +899,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
if ((event.getSource() == InputDevice.SOURCE_MOUSE ||
|
||||
event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE) &&
|
||||
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||
// It appears this may get turned into a right-click pointer event
|
||||
// if we don't return true to indicate that we handled it on
|
||||
// some devices. https://github.com/moonlight-stream/moonlight-android/issues/634
|
||||
if (!gotBackPointerEvent || syntheticBackDown) {
|
||||
// We need to raise the button if gotBackPointerEvent is true
|
||||
// in the case where it transitioned to true after we already
|
||||
// sent the right click down event.
|
||||
syntheticBackDown = false;
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -999,6 +1015,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
else {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||
}
|
||||
|
||||
// Don't use the KEYCODE_BACK hack (which interferes with mice
|
||||
// with actual back buttons) since we're getting right clicks
|
||||
// using this callback.
|
||||
gotBackPointerEvent = true;
|
||||
}
|
||||
|
||||
if ((changedButtons & MotionEvent.BUTTON_TERTIARY) != 0) {
|
||||
@@ -1010,6 +1031,28 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
}
|
||||
|
||||
if ((changedButtons & MotionEvent.BUTTON_BACK) != 0) {
|
||||
if ((event.getButtonState() & MotionEvent.BUTTON_BACK) != 0) {
|
||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_X1);
|
||||
}
|
||||
else {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_X1);
|
||||
}
|
||||
|
||||
// Don't use the KEYCODE_BACK hack. That will cause this
|
||||
// button press to trigger a right-click.
|
||||
gotBackPointerEvent = true;
|
||||
}
|
||||
|
||||
if ((changedButtons & MotionEvent.BUTTON_FORWARD) != 0) {
|
||||
if ((event.getButtonState() & MotionEvent.BUTTON_FORWARD) != 0) {
|
||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_X2);
|
||||
}
|
||||
else {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_X2);
|
||||
}
|
||||
}
|
||||
|
||||
// Get relative axis values if we can
|
||||
if (inputCaptureProvider.eventHasRelativeMouseAxes(event)) {
|
||||
// Send the deltas straight from the motion event
|
||||
@@ -1360,6 +1403,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
case EvdevListener.BUTTON_RIGHT:
|
||||
buttonIndex = MouseButtonPacket.BUTTON_RIGHT;
|
||||
break;
|
||||
case EvdevListener.BUTTON_X1:
|
||||
buttonIndex = MouseButtonPacket.BUTTON_X1;
|
||||
break;
|
||||
case EvdevListener.BUTTON_X2:
|
||||
buttonIndex = MouseButtonPacket.BUTTON_X2;
|
||||
break;
|
||||
default:
|
||||
LimeLog.warning("Unhandled button: "+buttonId);
|
||||
return;
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.limelight.utils.ShortcutHelper;
|
||||
import com.limelight.utils.UiHelper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
@@ -112,6 +113,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
private final static int DELETE_ID = 5;
|
||||
private final static int RESUME_ID = 6;
|
||||
private final static int QUIT_ID = 7;
|
||||
private final static int VIEW_DETAILS_ID = 8;
|
||||
|
||||
private void initializeViews() {
|
||||
setContentView(R.layout.activity_pc_view);
|
||||
@@ -332,6 +334,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
// it with delete which actually work
|
||||
menu.add(Menu.NONE, DELETE_ID, 4, getResources().getString(R.string.pcview_menu_delete_pc));
|
||||
}
|
||||
menu.add(Menu.NONE, VIEW_DETAILS_ID, 5, getResources().getString(R.string.pcview_menu_details));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -560,12 +563,21 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
return true;
|
||||
|
||||
case DELETE_ID:
|
||||
if (managerBinder == null) {
|
||||
Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show();
|
||||
if (ActivityManager.isUserAMonkey()) {
|
||||
LimeLog.info("Ignoring delete PC request from monkey");
|
||||
return true;
|
||||
}
|
||||
managerBinder.removeComputer(computer.details.name);
|
||||
removeComputer(computer.details);
|
||||
UiHelper.displayDeletePcConfirmationDialog(this, computer.details, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (managerBinder == null) {
|
||||
Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
managerBinder.removeComputer(computer.details.name);
|
||||
removeComputer(computer.details);
|
||||
}
|
||||
}, null);
|
||||
return true;
|
||||
|
||||
case APP_LIST_ID:
|
||||
@@ -598,6 +610,10 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
}, null);
|
||||
return true;
|
||||
|
||||
case VIEW_DETAILS_ID:
|
||||
Dialog.displayDialog(PcView.this, getResources().getString(R.string.title_details), computer.details.toString(), false);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
package com.limelight;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
import com.limelight.computers.ComputerManagerListener;
|
||||
import com.limelight.computers.ComputerManagerService;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.nvstream.http.NvApp;
|
||||
import com.limelight.nvstream.http.PairingManager;
|
||||
import com.limelight.utils.Dialog;
|
||||
import com.limelight.utils.ServerHelper;
|
||||
import com.limelight.utils.SpinnerDialog;
|
||||
import com.limelight.utils.UiHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ShortcutTrampoline extends Activity {
|
||||
private String uuidString;
|
||||
private String appIdString;
|
||||
private ArrayList<Intent> intentStack = new ArrayList<>();
|
||||
|
||||
private ComputerDetails computer;
|
||||
private SpinnerDialog blockingLoadSpinner;
|
||||
|
||||
public final static String APP_ID_EXTRA = "AppId";
|
||||
|
||||
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder binder) {
|
||||
final ComputerManagerService.ComputerManagerBinder localBinder =
|
||||
((ComputerManagerService.ComputerManagerBinder)binder);
|
||||
|
||||
// Wait in a separate thread to avoid stalling the UI
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Wait for the binder to be ready
|
||||
localBinder.waitForReady();
|
||||
|
||||
// Now make the binder visible
|
||||
managerBinder = localBinder;
|
||||
|
||||
// Get the computer object
|
||||
computer = managerBinder.getComputer(UUID.fromString(uuidString));
|
||||
|
||||
if (computer == null) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_pc_not_found),
|
||||
true);
|
||||
|
||||
if (blockingLoadSpinner != null) {
|
||||
blockingLoadSpinner.dismiss();
|
||||
blockingLoadSpinner = null;
|
||||
}
|
||||
|
||||
if (managerBinder != null) {
|
||||
unbindService(serviceConnection);
|
||||
managerBinder = null;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Force CMS to repoll this machine
|
||||
managerBinder.invalidateStateForComputer(computer.uuid);
|
||||
|
||||
// Start polling
|
||||
managerBinder.startPolling(new ComputerManagerListener() {
|
||||
@Override
|
||||
public void notifyComputerUpdated(final ComputerDetails details) {
|
||||
// Don't care about other computers
|
||||
if (!details.uuid.toString().equalsIgnoreCase(uuidString)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (details.state != ComputerDetails.State.UNKNOWN) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Stop showing the spinner
|
||||
if (blockingLoadSpinner != null) {
|
||||
blockingLoadSpinner.dismiss();
|
||||
blockingLoadSpinner = null;
|
||||
}
|
||||
|
||||
// If the managerBinder was destroyed before this callback,
|
||||
// just finish the activity.
|
||||
if (managerBinder == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (details.state == ComputerDetails.State.ONLINE && details.pairState == PairingManager.PairState.PAIRED) {
|
||||
|
||||
// Launch game if provided app ID, otherwise launch app view
|
||||
if (appIdString != null && appIdString.length() > 0) {
|
||||
if (details.runningGameId == 0 || details.runningGameId == Integer.parseInt(appIdString)) {
|
||||
intentStack.add(ServerHelper.createStartIntent(ShortcutTrampoline.this,
|
||||
new NvApp("app", Integer.parseInt(appIdString), false), details, managerBinder));
|
||||
|
||||
// Close this activity
|
||||
finish();
|
||||
|
||||
// Now start the activities
|
||||
startActivities(intentStack.toArray(new Intent[]{}));
|
||||
} else {
|
||||
// Create the start intent immediately, so we can safely unbind the managerBinder
|
||||
// below before we return.
|
||||
final Intent startIntent = ServerHelper.createStartIntent(ShortcutTrampoline.this,
|
||||
new NvApp("app", Integer.parseInt(appIdString), false), details, managerBinder);
|
||||
|
||||
UiHelper.displayQuitConfirmationDialog(ShortcutTrampoline.this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
intentStack.add(startIntent);
|
||||
|
||||
// Close this activity
|
||||
finish();
|
||||
|
||||
// Now start the activities
|
||||
startActivities(intentStack.toArray(new Intent[]{}));
|
||||
}
|
||||
}, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Close this activity
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Close this activity
|
||||
finish();
|
||||
|
||||
// Add the PC view at the back (and clear the task)
|
||||
Intent i;
|
||||
i = new Intent(ShortcutTrampoline.this, PcView.class);
|
||||
i.setAction(Intent.ACTION_MAIN);
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intentStack.add(i);
|
||||
|
||||
// Take this intent's data and create an intent to start the app view
|
||||
i = new Intent(getIntent());
|
||||
i.setClass(ShortcutTrampoline.this, AppView.class);
|
||||
intentStack.add(i);
|
||||
|
||||
// If a game is running, we'll make the stream the top level activity
|
||||
if (details.runningGameId != 0) {
|
||||
intentStack.add(ServerHelper.createStartIntent(ShortcutTrampoline.this,
|
||||
new NvApp("app", details.runningGameId, false), details, managerBinder));
|
||||
}
|
||||
|
||||
// Now start the activities
|
||||
startActivities(intentStack.toArray(new Intent[]{}));
|
||||
}
|
||||
|
||||
}
|
||||
else if (details.state == ComputerDetails.State.OFFLINE) {
|
||||
// Computer offline - display an error dialog
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.error_pc_offline),
|
||||
true);
|
||||
} else if (details.pairState != PairingManager.PairState.PAIRED) {
|
||||
// Computer not paired - display an error dialog
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_not_paired),
|
||||
true);
|
||||
}
|
||||
|
||||
// We don't want any more callbacks from now on, so go ahead
|
||||
// and unbind from the service
|
||||
if (managerBinder != null) {
|
||||
managerBinder.stopPolling();
|
||||
unbindService(serviceConnection);
|
||||
managerBinder = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
managerBinder = null;
|
||||
}
|
||||
};
|
||||
|
||||
protected boolean validateInput() {
|
||||
// Validate UUID
|
||||
try {
|
||||
UUID.fromString(uuidString);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_invalid_uuid),
|
||||
true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate App ID (if provided)
|
||||
if (appIdString != null && !appIdString.isEmpty()) {
|
||||
try {
|
||||
Integer.parseInt(appIdString);
|
||||
} catch (NumberFormatException ex) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_invalid_app_id),
|
||||
true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
UiHelper.notifyNewRootView(this);
|
||||
|
||||
uuidString = getIntent().getStringExtra(AppView.UUID_EXTRA);
|
||||
appIdString = getIntent().getStringExtra(APP_ID_EXTRA);
|
||||
|
||||
if (validateInput()) {
|
||||
// Bind to the computer manager service
|
||||
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
|
||||
Service.BIND_AUTO_CREATE);
|
||||
|
||||
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
|
||||
getResources().getString(R.string.applist_connect_msg), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if (blockingLoadSpinner != null) {
|
||||
blockingLoadSpinner.dismiss();
|
||||
blockingLoadSpinner = null;
|
||||
}
|
||||
|
||||
Dialog.closeDialogs();
|
||||
|
||||
if (managerBinder != null) {
|
||||
managerBinder.stopPolling();
|
||||
unbindService(serviceConnection);
|
||||
managerBinder = null;
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ public interface EvdevListener {
|
||||
int BUTTON_LEFT = 1;
|
||||
int BUTTON_MIDDLE = 2;
|
||||
int BUTTON_RIGHT = 3;
|
||||
int BUTTON_X1 = 4;
|
||||
int BUTTON_X2 = 5;
|
||||
|
||||
void mouseMove(int deltaX, int deltaY);
|
||||
void mouseButtonEvent(int buttonId, boolean down);
|
||||
|
||||
+1
@@ -60,6 +60,7 @@ public class VirtualController {
|
||||
|
||||
buttonConfigure = new Button(context);
|
||||
buttonConfigure.setAlpha(0.25f);
|
||||
buttonConfigure.setFocusable(false);
|
||||
buttonConfigure.setBackgroundResource(R.drawable.ic_settings);
|
||||
buttonConfigure.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
||||
@@ -62,9 +62,8 @@ public class StreamView extends SurfaceView {
|
||||
@Override
|
||||
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
|
||||
// This callbacks allows us to override dumb IME behavior like when
|
||||
// Samsung's default keyboard consumes Shift+Space. We'll process
|
||||
// the input event directly if any modifier keys are down.
|
||||
if (inputCallbacks != null && event.getModifiers() != 0) {
|
||||
// Samsung's default keyboard consumes Shift+Space.
|
||||
if (inputCallbacks != null) {
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
if (inputCallbacks.handleKeyDown(event)) {
|
||||
return true;
|
||||
|
||||
@@ -5,13 +5,15 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
|
||||
import com.limelight.AppView;
|
||||
import com.limelight.AppViewShortcutTrampoline;
|
||||
import com.limelight.ShortcutTrampoline;
|
||||
import com.limelight.R;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.nvstream.http.NvApp;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
@@ -80,8 +82,7 @@ public class ShortcutHelper {
|
||||
|
||||
public void reportShortcutUsed(String id) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
ShortcutInfo sinfo = getInfoForId(id);
|
||||
if (sinfo != null) {
|
||||
if (getInfoForId(id) != null) {
|
||||
sm.reportShortcutUsed(id);
|
||||
}
|
||||
}
|
||||
@@ -89,7 +90,7 @@ public class ShortcutHelper {
|
||||
|
||||
public void createAppViewShortcut(String id, String computerName, String computerUuid, boolean forceAdd) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
Intent i = new Intent(context, AppViewShortcutTrampoline.class);
|
||||
Intent i = new Intent(context, ShortcutTrampoline.class);
|
||||
i.putExtra(AppView.NAME_EXTRA, computerName);
|
||||
i.putExtra(AppView.UUID_EXTRA, computerUuid);
|
||||
i.setAction(Intent.ACTION_DEFAULT);
|
||||
@@ -127,10 +128,42 @@ public class ShortcutHelper {
|
||||
createAppViewShortcut(id, details.name, details.uuid.toString(), forceAdd);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public boolean createPinnedGameShortcut(String id, Bitmap iconBits, String computerName, String computerUuid, String appName, String appId) {
|
||||
if (sm.isRequestPinShortcutSupported()) {
|
||||
Icon appIcon;
|
||||
Intent i = new Intent(context, ShortcutTrampoline.class);
|
||||
|
||||
i.putExtra(AppView.NAME_EXTRA, computerName);
|
||||
i.putExtra(AppView.UUID_EXTRA, computerUuid);
|
||||
i.putExtra(ShortcutTrampoline.APP_ID_EXTRA, appId);
|
||||
i.setAction(Intent.ACTION_DEFAULT);
|
||||
|
||||
if (iconBits != null) {
|
||||
appIcon = Icon.createWithAdaptiveBitmap(iconBits);
|
||||
} else {
|
||||
appIcon = Icon.createWithResource(context, R.mipmap.ic_pc_scut);
|
||||
}
|
||||
|
||||
ShortcutInfo sInfo = new ShortcutInfo.Builder(context, id)
|
||||
.setIntent(i)
|
||||
.setShortLabel(appName + " (" + computerName + ")")
|
||||
.setIcon(appIcon)
|
||||
.build();
|
||||
|
||||
return sm.requestPinShortcut(sInfo, null);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean createPinnedGameShortcut(String id, Bitmap iconBits, ComputerDetails cDetails, NvApp app) {
|
||||
return createPinnedGameShortcut(id, iconBits, cDetails.name, cDetails.uuid.toString(), app.getAppName(), Integer.valueOf(app.getAppId()).toString());
|
||||
}
|
||||
|
||||
public void disableShortcut(String id, CharSequence reason) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
ShortcutInfo sinfo = getInfoForId(id);
|
||||
if (sinfo != null) {
|
||||
if (getInfoForId(id) != null) {
|
||||
sm.disableShortcuts(Collections.singletonList(id), reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.limelight.R;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.preferences.PreferenceConfiguration;
|
||||
|
||||
import java.util.Locale;
|
||||
@@ -135,4 +136,32 @@ public class UiHelper {
|
||||
.setNegativeButton(parent.getResources().getString(R.string.no), dialogClickListener)
|
||||
.show();
|
||||
}
|
||||
|
||||
public static void displayDeletePcConfirmationDialog(Activity parent, ComputerDetails computer, final Runnable onYes, final Runnable onNo) {
|
||||
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which){
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
if (onYes != null) {
|
||||
onYes.run();
|
||||
}
|
||||
break;
|
||||
|
||||
case DialogInterface.BUTTON_NEGATIVE:
|
||||
if (onNo != null) {
|
||||
onNo.run();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(parent);
|
||||
builder.setMessage(parent.getResources().getString(R.string.delete_pc_msg))
|
||||
.setTitle(computer.name)
|
||||
.setPositiveButton(parent.getResources().getString(R.string.yes), dialogClickListener)
|
||||
.setNegativeButton(parent.getResources().getString(R.string.no), dialogClickListener)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
<string name="lost_connection">Conexión perdida</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">Aplicaciones en</string>
|
||||
<string name="applist_menu_resume">Reanudar sesión</string>
|
||||
<string name="applist_menu_quit">Cerrar sesión</string>
|
||||
<string name="applist_menu_quit_and_start">Cerrar juego actual e iniciar</string>
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
<!-- Shortcut strings -->
|
||||
<string name="scut_deleted_pc">PC supprimé</string>
|
||||
<string name="scut_not_paired">PC non appairé</string>
|
||||
<string name="scut_pc_not_found">PC non trouvé</string>
|
||||
<string name="scut_invalid_uuid">Le PC fourni n\'est pas valide</string>
|
||||
<string name="scut_invalid_app_id">L\'application fournie n\'est pas valide</string>
|
||||
|
||||
<!-- Help strings -->
|
||||
<string name="help_loading_title">Visionneuse d\'aide</string>
|
||||
@@ -14,6 +17,7 @@
|
||||
<string name="pcview_menu_unpair_pc">Désappairer</string>
|
||||
<string name="pcview_menu_send_wol">Envoyer la requête Wake-On-LAN</string>
|
||||
<string name="pcview_menu_delete_pc">Supprimer PC</string>
|
||||
<string name="pcview_menu_details">Voir les détails</string>
|
||||
|
||||
<!-- Pair messages -->
|
||||
<string name="pairing">Appariement…</string>
|
||||
@@ -47,6 +51,12 @@
|
||||
<string name="error_404">GFE renvoi une erreur HTTP 404. Assurez-vous que votre PC exécute un GPU pris en charge.
|
||||
L\'utilisation d\'un logiciel de bureau à distance peut également provoquer cette erreur. Essayez de redémarrer votre machine ou de réinstaller GFE.
|
||||
</string>
|
||||
<string name="title_decoding_error">Le décodeur vidéo s\'est écrasé</string>
|
||||
<string name="message_decoding_error">Moonlight s\'est écrasé en raison d\'une incompatibilité avec le décodeur vidéo de cet appareil. Assurez-vous que GeForce Experience soit mis à jour vers la dernière version sur votre PC. Essayez de régler les paramètres de diffusion si les plantages continuent.</string>
|
||||
<string name="title_decoding_reset">Paramètres vidéo réinitialiser</string>
|
||||
<string name="message_decoding_reset">Le décodeur vidéo de votre appareil continue de planter avec les paramètres de diffusion sélectionnés. Vos paramètres de diffusion ont été réinitialisés par défaut.</string>
|
||||
<string name="error_usb_prohibited">L\'accès USB est interdit par votre appareil. Vérifiez vos paramètres Knox ou MDM.</string>
|
||||
<string name="unable_to_pin_shortcut">Votre lanceur actuel ne permet pas de créer des raccourcis épinglés.</string>
|
||||
|
||||
<!-- Start application messages -->
|
||||
<string name="conn_establishing_title">Établissement de la connexion</string>
|
||||
@@ -63,20 +73,22 @@
|
||||
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">Adresse IP de GeForce PC</string>
|
||||
<string name="searching_pc">Recherche de PC avec GameStream en cours...\n\n
|
||||
<string name="searching_pc">Recherche de PC avec GameStream en cours…\n\n
|
||||
Assurez-vous que GameStream est activé dans les paramètres GeForce Experience SHIELD.</string>
|
||||
<string name="yes">Oui</string>
|
||||
<string name="no">Non</string>
|
||||
<string name="lost_connection">Perte de connexion avec le PC</string>
|
||||
<string name="title_details">Détails</string>
|
||||
<string name="help">Aide</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">Applications sur</string>
|
||||
<string name="applist_connect_msg">Connexion au PC…</string>
|
||||
<string name="applist_menu_resume">Reprise de la session</string>
|
||||
<string name="applist_menu_quit">Quitter la session</string>
|
||||
<string name="applist_menu_quit_and_start">Quitter le jeu actuel et démarrer</string>
|
||||
<string name="applist_menu_cancel">Annuler</string>
|
||||
<string name="applist_menu_details">Voir les détails</string>
|
||||
<string name="applist_menu_scut">Créer un raccourci</string>
|
||||
<string name="applist_refresh_title">Liste des applications</string>
|
||||
<string name="applist_refresh_msg">Actualisation des applications…</string>
|
||||
<string name="applist_refresh_error_title">Erreur</string>
|
||||
@@ -85,6 +97,7 @@
|
||||
<string name="applist_quit_success">Fermeture avec succès</string>
|
||||
<string name="applist_quit_fail">Échec de la fermeture</string>
|
||||
<string name="applist_quit_confirmation">Voulez-vous vraiment quitter l\'application en cours d\'exécution? Toutes les données non enregistrées seront perdues.</string>
|
||||
<string name="applist_details_id">ID app:</string>
|
||||
|
||||
<!-- Add computer manually activity -->
|
||||
<string name="title_add_pc">Ajouter un PC manuellement</string>
|
||||
@@ -93,6 +106,7 @@
|
||||
<string name="addpc_success">Ajouté avec succès de l\'ordinateur</string>
|
||||
<string name="addpc_unknown_host">Impossible de résoudre l\'adresse du PC. Assurez-vous que vous n\'avez pas fait une faute de frappe dans l\'adresse.</string>
|
||||
<string name="addpc_enter_ip">Vous devez entrer une adresse IP</string>
|
||||
<string name="addpc_wrong_sitelocal">Cette adresse ne semble pas correcte. Vous devez utiliser l\'adresse IP publique de votre routeur pour la diffusion en continu sur Internet..</string>
|
||||
|
||||
<!-- Preferences -->
|
||||
<string name="category_basic_settings">Paramètres de base</string>
|
||||
@@ -104,6 +118,8 @@
|
||||
<string name="title_checkbox_stretch_video">Étirez la vidéo en plein écran</string>
|
||||
<string name="title_checkbox_disable_warnings">Désactiver les messages d\'avertissement</string>
|
||||
<string name="summary_checkbox_disable_warnings">Désactiver les messages d\'avertissement de connexion à l\'écran pendant le streaming</string>
|
||||
<string name="title_checkbox_enable_pip">Activer le mode observateur dans l\'image</string>
|
||||
<string name="summary_checkbox_enable_pip">Permet de visualiser le flux (sans le contrôleur) tout en multitâche</string>
|
||||
|
||||
<string name="category_audio_settings">Paramètres audio</string>
|
||||
<string name="title_checkbox_51_surround">Activer son surround 5.1</string>
|
||||
@@ -116,12 +132,21 @@
|
||||
<string name="suffix_seekbar_deadzone">%</string>
|
||||
<string name="title_checkbox_xb1_driver">Pilote de contrôleur Xbox 360/One</string>
|
||||
<string name="summary_checkbox_xb1_driver">Active un pilote USB intégré pour les périphériques sans prise en charge du contrôleur Xbox natif.</string>
|
||||
<string name="title_checkbox_usb_bind_all">Ignorer le support du contrôleur Android</string>
|
||||
<string name="summary_checkbox_usb_bind_all">Force le pilote USB de Moonlight à prendre en charge tous les gamepads Xbox pris en charge</string>
|
||||
<string name="title_checkbox_mouse_emulation">Emulation de la souris via le gamepad</string>
|
||||
<string name="summary_checkbox_mouse_emulation">Appuyez longuement sur le bouton Start pour faire basculer la manette de jeu en mode souris.</string>
|
||||
|
||||
<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_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>
|
||||
<string name="summary_reset_osc">Rétablit la taille et la position par défaut de tous les contrôles à l\'écran</string>
|
||||
<string name="dialog_title_reset_osc">Réinitialiser la mise en page</string>
|
||||
<string name="dialog_text_reset_osc">Êtes-vous sûr de vouloir supprimer la disposition des commandes à l\'écran que vous avez sauvegardée?</string>
|
||||
<string name="toast_reset_osc_success">Les contrôles à l\'écran sont réinitialisés</string>
|
||||
|
||||
<string name="category_ui_settings">Paramètres de l\'interface utilisateur</string>
|
||||
<string name="title_language_list">Langue</string>
|
||||
@@ -139,5 +164,8 @@
|
||||
|
||||
<string name="category_advanced_settings">Réglages avancés</string>
|
||||
<string name="title_video_format">Modifier les paramètres H.265</string>
|
||||
<string name="summary_video_format">H.265 réduit les exigences de bande passante vidéo, mais requiert un périphérique très récent.</string>
|
||||
<string name="summary_video_format">H.265 réduit les besoins en bande passante vidéo mais nécessite un périphérique très récent</string>
|
||||
<string name="title_enable_hdr">Activer le HDR (expérimental)</string>
|
||||
<string name="summary_enable_hdr">Diffuser du HDR lorsque le jeu et le processeur graphique du PC le prennent en charge. HDR nécessite un GPU série GTX 1000 ou une version ultérieure.</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -76,7 +76,6 @@
|
||||
<string name="help">Assistenza</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">Applicazioni su</string>
|
||||
<string name="applist_connect_msg">Connessione al PC in corso…</string>
|
||||
<string name="applist_menu_resume">Riprendi sessione</string>
|
||||
<string name="applist_menu_quit">Chiudi sessione</string>
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
<string name="lost_connection">コンピュータとの接続が失われました</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">ゲーム</string>
|
||||
<string name="applist_menu_resume">セッションを続ける</string>
|
||||
<string name="applist_menu_quit">セッションを終了する</string>
|
||||
<string name="applist_menu_quit_and_start">現在のゲームを終了して新しいゲームを始める</string>
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
<string name="help">도움말</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">앱 사용 가능</string>
|
||||
<string name="applist_connect_msg">PC에 연결중…</string>
|
||||
<string name="applist_menu_resume">세션 계속</string>
|
||||
<string name="applist_menu_quit">세션 종료</string>
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
<string name="lost_connection">Verbinding met PC verloren</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">Apps op</string>
|
||||
<string name="applist_menu_resume">Hervat Sessie</string>
|
||||
<string name="applist_menu_quit">Stop Sessie</string>
|
||||
<string name="applist_menu_quit_and_start">Stop Huidige Spel en Start</string>
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
<string name="lost_connection">Потеряно соединение с PC</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">Приложения на</string>
|
||||
<string name="applist_menu_resume">Возобновить сессию</string>
|
||||
<string name="applist_menu_quit">Выйти из сессии</string>
|
||||
<string name="applist_menu_quit_and_start">Выйти из текущей игры и запустить</string>
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Material">
|
||||
<!-- API 21 theme customizations can go here. -->
|
||||
<item name="android:statusBarColor">#212121</item>
|
||||
<item name="android:navigationBarColor">#212121</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
<string name="help">帮助</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">Apps on</string>
|
||||
<string name="applist_connect_msg"> 连接到电脑中…… </string>
|
||||
<string name="applist_menu_resume"> 恢复串流 </string>
|
||||
<string name="applist_menu_quit"> 退出串流 </string>
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
<string name="help">幫助</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">Apps on</string>
|
||||
<string name="applist_connect_msg"> 連接到電腦中…… </string>
|
||||
<string name="applist_menu_resume"> 恢復串流 </string>
|
||||
<string name="applist_menu_quit"> 退出串流 </string>
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<!-- Shortcut strings -->
|
||||
<string name="scut_deleted_pc">PC deleted</string>
|
||||
<string name="scut_not_paired">PC not paired</string>
|
||||
<string name="scut_pc_not_found">PC not found</string>
|
||||
<string name="scut_invalid_uuid">Provided PC is not valid</string>
|
||||
<string name="scut_invalid_app_id">Provided App is not valid</string>
|
||||
|
||||
<!-- Help strings -->
|
||||
<string name="help_loading_title">Help Viewer</string>
|
||||
@@ -17,6 +20,7 @@
|
||||
<string name="pcview_menu_unpair_pc">Unpair</string>
|
||||
<string name="pcview_menu_send_wol">Send Wake-On-LAN request</string>
|
||||
<string name="pcview_menu_delete_pc">Delete PC</string>
|
||||
<string name="pcview_menu_details">View Details</string>
|
||||
|
||||
<!-- Pair messages -->
|
||||
<string name="pairing">Pairing…</string>
|
||||
@@ -55,6 +59,7 @@
|
||||
<string name="title_decoding_reset">Video Settings Reset</string>
|
||||
<string name="message_decoding_reset">Your device\'s video decoder continues to crash at your selected streaming settings. Your streaming settings have been reset to default.</string>
|
||||
<string name="error_usb_prohibited">USB access is prohibited by your device administrator. Check your Knox or MDM settings.</string>
|
||||
<string name="unable_to_pin_shortcut">Your current launcher does not allow for creating pinned shortcuts.</string>
|
||||
|
||||
<!-- Start application messages -->
|
||||
<string name="conn_establishing_title">Establishing Connection</string>
|
||||
@@ -76,15 +81,18 @@
|
||||
<string name="yes">Yes</string>
|
||||
<string name="no">No</string>
|
||||
<string name="lost_connection">Lost connection to PC</string>
|
||||
<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>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="title_applist">Apps on</string>
|
||||
<string name="applist_connect_msg">Connecting to PC…</string>
|
||||
<string name="applist_menu_resume">Resume Session</string>
|
||||
<string name="applist_menu_quit">Quit Session</string>
|
||||
<string name="applist_menu_quit_and_start">Quit Current Game and Start</string>
|
||||
<string name="applist_menu_cancel">Cancel</string>
|
||||
<string name="applist_menu_details">View Details</string>
|
||||
<string name="applist_menu_scut">Create Shortcut</string>
|
||||
<string name="applist_refresh_title">App List</string>
|
||||
<string name="applist_refresh_msg">Refreshing apps…</string>
|
||||
<string name="applist_refresh_error_title">Error</string>
|
||||
@@ -93,6 +101,7 @@
|
||||
<string name="applist_quit_success">Successfully quit</string>
|
||||
<string name="applist_quit_fail">Failed to quit</string>
|
||||
<string name="applist_quit_confirmation">Are you sure you want to quit the running app? All unsaved data will be lost.</string>
|
||||
<string name="applist_details_id">App ID:</string>
|
||||
|
||||
<!-- Add computer manually activity -->
|
||||
<string name="title_add_pc">Add PC Manually</string>
|
||||
|
||||
@@ -55,7 +55,7 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
// Launch evdev_reader directly via SU
|
||||
try {
|
||||
su = Runtime.getRuntime().exec("su -c "+evdevReaderCmd);
|
||||
su = new ProcessBuilder("su", "-c", evdevReaderCmd).start();
|
||||
} catch (IOException e) {
|
||||
reportDeviceNotRooted();
|
||||
e.printStackTrace();
|
||||
@@ -151,7 +151,15 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
|
||||
break;
|
||||
|
||||
case EvdevEvent.BTN_SIDE:
|
||||
listener.mouseButtonEvent(EvdevListener.BUTTON_X1,
|
||||
event.value != 0);
|
||||
break;
|
||||
|
||||
case EvdevEvent.BTN_EXTRA:
|
||||
listener.mouseButtonEvent(EvdevListener.BUTTON_X2,
|
||||
event.value != 0);
|
||||
break;
|
||||
|
||||
case EvdevEvent.BTN_FORWARD:
|
||||
case EvdevEvent.BTN_BACK:
|
||||
case EvdevEvent.BTN_TASK:
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.0-alpha18'
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
Submodule moonlight-common updated: 165a518adb...31d6b4cb9f
Reference in New Issue
Block a user