diff --git a/app/src/main/java/com/limelight/AppView.java b/app/src/main/java/com/limelight/AppView.java index 18e2f695..fe33f193 100644 --- a/app/src/main/java/com/limelight/AppView.java +++ b/app/src/main/java/com/limelight/AppView.java @@ -21,6 +21,7 @@ import com.limelight.ui.AdapterFragment; import com.limelight.ui.AdapterFragmentCallbacks; import com.limelight.utils.CacheHelper; import com.limelight.utils.Dialog; +import com.limelight.utils.ServerHelper; import com.limelight.utils.SpinnerDialog; import com.limelight.utils.UiHelper; @@ -113,11 +114,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks { } }; - private InetAddress getAddress() { - return computer.reachability == ComputerDetails.Reachability.LOCAL ? - computer.localIp : computer.remoteIp; - } - private void startComputerUpdates() { if (managerBinder == null) { return; @@ -308,33 +304,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks { public void onContextMenuClosed(Menu menu) { } - private void displayQuitConfirmationDialog(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(this); - builder.setMessage(getResources().getString(R.string.applist_quit_confirmation)) - .setPositiveButton(getResources().getString(R.string.yes), dialogClickListener) - .setNegativeButton(getResources().getString(R.string.no), dialogClickListener) - .show(); - } - @Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); @@ -342,25 +311,37 @@ public class AppView extends Activity implements AdapterFragmentCallbacks { switch (item.getItemId()) { case START_WTIH_QUIT: // Display a confirmation dialog first - displayQuitConfirmationDialog(new Runnable() { + UiHelper.displayQuitConfirmationDialog(this, new Runnable() { @Override public void run() { - doStart(app.app); + ServerHelper.doStart(AppView.this, app.app, computer, managerBinder); } }, null); return true; case START_OR_RESUME_ID: // Resume is the same as start for us - doStart(app.app); + ServerHelper.doStart(AppView.this, app.app, computer, managerBinder); return true; case QUIT_ID: // Display a confirmation dialog first - displayQuitConfirmationDialog(new Runnable() { + UiHelper.displayQuitConfirmationDialog(this, new Runnable() { @Override public void run() { - doQuit(app.app); + suspendGridUpdates = true; + ServerHelper.doQuit(AppView.this, + ServerHelper.getCurrentAddressFromComputer(computer), + app.app, managerBinder, new Runnable() { + @Override + public void run() { + // Trigger a poll immediately + suspendGridUpdates = false; + if (poller != null) { + poller.pollNow(); + } + } + }); } }, null); return true; @@ -482,69 +463,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks { }); } - private void doStart(NvApp app) { - Intent intent = new Intent(this, Game.class); - intent.putExtra(Game.EXTRA_HOST, - computer.reachability == ComputerDetails.Reachability.LOCAL ? - computer.localIp.getHostAddress() : computer.remoteIp.getHostAddress()); - intent.putExtra(Game.EXTRA_APP_NAME, app.getAppName()); - intent.putExtra(Game.EXTRA_APP_ID, app.getAppId()); - intent.putExtra(Game.EXTRA_UNIQUEID, managerBinder.getUniqueId()); - intent.putExtra(Game.EXTRA_STREAMING_REMOTE, - computer.reachability != ComputerDetails.Reachability.LOCAL); - startActivity(intent); - } - - private void doQuit(final NvApp app) { - Toast.makeText(AppView.this, getResources().getString(R.string.applist_quit_app)+" "+app.getAppName()+"...", Toast.LENGTH_SHORT).show(); - new Thread(new Runnable() { - @Override - public void run() { - NvHTTP httpConn; - String message; - try { - suspendGridUpdates = true; - httpConn = new NvHTTP(getAddress(), - managerBinder.getUniqueId(), null, PlatformBinding.getCryptoProvider(AppView.this)); - if (httpConn.quitApp()) { - message = getResources().getString(R.string.applist_quit_success) + " " + app.getAppName(); - } else { - message = getResources().getString(R.string.applist_quit_fail) + " " + app.getAppName(); - } - } catch (GfeHttpResponseException e) { - if (e.getErrorCode() == 599) { - message = "This session wasn't started by this device," + - " so it cannot be quit. End streaming on the original " + - "device or the PC itself. (Error code: "+e.getErrorCode()+")"; - } - else { - message = e.getMessage(); - } - } catch (UnknownHostException e) { - message = getResources().getString(R.string.error_unknown_host); - } catch (FileNotFoundException e) { - message = getResources().getString(R.string.error_404); - } catch (Exception e) { - message = e.getMessage(); - } finally { - // Trigger a poll immediately - suspendGridUpdates = false; - if (poller != null) { - poller.pollNow(); - } - } - - final String toastMessage = message; - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(AppView.this, toastMessage, Toast.LENGTH_LONG).show(); - } - }); - } - }).start(); - } - @Override public int getAdapterFragmentLayoutId() { return PreferenceConfiguration.readPreferences(this).listMode ? @@ -565,7 +483,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks { if (getRunningAppId() != -1) { openContextMenu(arg1); } else { - doStart(app.app); + ServerHelper.doStart(AppView.this, app.app, computer, managerBinder); } } }); diff --git a/app/src/main/java/com/limelight/PcView.java b/app/src/main/java/com/limelight/PcView.java index 689a7fc7..03709836 100644 --- a/app/src/main/java/com/limelight/PcView.java +++ b/app/src/main/java/com/limelight/PcView.java @@ -12,6 +12,7 @@ import com.limelight.computers.ComputerManagerListener; import com.limelight.computers.ComputerManagerService; import com.limelight.grid.PcGridAdapter; import com.limelight.nvstream.http.ComputerDetails; +import com.limelight.nvstream.http.NvApp; import com.limelight.nvstream.http.NvHTTP; import com.limelight.nvstream.http.PairingManager; import com.limelight.nvstream.http.PairingManager.PairState; @@ -22,6 +23,7 @@ import com.limelight.preferences.StreamSettings; import com.limelight.ui.AdapterFragment; import com.limelight.ui.AdapterFragmentCallbacks; import com.limelight.utils.Dialog; +import com.limelight.utils.ServerHelper; import com.limelight.utils.UiHelper; import android.app.Activity; @@ -93,6 +95,8 @@ public class PcView extends Activity implements AdapterFragmentCallbacks { private final static int UNPAIR_ID = 3; private final static int WOL_ID = 4; private final static int DELETE_ID = 5; + private final static int RESUME_ID = 6; + private final static int QUIT_ID = 7; private void initializeViews() { setContentView(R.layout.activity_pc_view); @@ -252,11 +256,16 @@ public class PcView extends Activity implements AdapterFragmentCallbacks { menu.add(Menu.NONE, DELETE_ID, 2, getResources().getString(R.string.pcview_menu_delete_pc)); } else { - menu.add(Menu.NONE, APP_LIST_ID, 1, getResources().getString(R.string.pcview_menu_app_list)); + if (computer.details.runningGameId != 0) { + menu.add(Menu.NONE, RESUME_ID, 1, getResources().getString(R.string.applist_menu_resume)); + menu.add(Menu.NONE, QUIT_ID, 2, getResources().getString(R.string.applist_menu_quit)); + } + + menu.add(Menu.NONE, APP_LIST_ID, 3, getResources().getString(R.string.pcview_menu_app_list)); // FIXME: We used to be able to unpair here but it's been broken since GFE 2.1.x, so I've replaced // it with delete which actually work - menu.add(Menu.NONE, DELETE_ID, 2, getResources().getString(R.string.pcview_menu_delete_pc)); + menu.add(Menu.NONE, DELETE_ID, 4, getResources().getString(R.string.pcview_menu_delete_pc)); } } @@ -477,36 +486,61 @@ public class PcView extends Activity implements AdapterFragmentCallbacks { @Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); - ComputerObject computer = (ComputerObject) pcGridAdapter.getItem(info.position); - switch (item.getItemId()) - { - case PAIR_ID: - doPair(computer.details); - return true; - - case UNPAIR_ID: - doUnpair(computer.details); - return true; - - case WOL_ID: - doWakeOnLan(computer.details); - return true; - - case DELETE_ID: - if (managerBinder == null) { - Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show(); + final ComputerObject computer = (ComputerObject) pcGridAdapter.getItem(info.position); + switch (item.getItemId()) { + case PAIR_ID: + doPair(computer.details); return true; - } - managerBinder.removeComputer(computer.details.name); - removeComputer(computer.details); - return true; - case APP_LIST_ID: - doAppList(computer.details); - return true; + case UNPAIR_ID: + doUnpair(computer.details); + return true; - default: - return super.onContextItemSelected(item); + case WOL_ID: + doWakeOnLan(computer.details); + return true; + + case DELETE_ID: + if (managerBinder == null) { + Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show(); + return true; + } + managerBinder.removeComputer(computer.details.name); + removeComputer(computer.details); + return true; + + case APP_LIST_ID: + doAppList(computer.details); + return true; + + case RESUME_ID: + if (managerBinder == null) { + Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show(); + return true; + } + + ServerHelper.doStart(this, new NvApp("app", computer.details.runningGameId), computer.details, managerBinder); + return true; + + case QUIT_ID: + if (managerBinder == null) { + Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show(); + return true; + } + + // Display a confirmation dialog first + UiHelper.displayQuitConfirmationDialog(this, new Runnable() { + @Override + public void run() { + ServerHelper.doQuit(PcView.this, + ServerHelper.getCurrentAddressFromComputer(computer.details), + new NvApp("app", 0), managerBinder, null); + } + }, null); + return true; + + default: + return super.onContextItemSelected(item); } } diff --git a/app/src/main/java/com/limelight/utils/UiHelper.java b/app/src/main/java/com/limelight/utils/UiHelper.java index 6eb22e3a..32827b4b 100644 --- a/app/src/main/java/com/limelight/utils/UiHelper.java +++ b/app/src/main/java/com/limelight/utils/UiHelper.java @@ -1,11 +1,15 @@ package com.limelight.utils; import android.app.Activity; +import android.app.AlertDialog; import android.app.UiModeManager; import android.content.Context; +import android.content.DialogInterface; import android.content.res.Configuration; import android.view.View; +import com.limelight.R; + public class UiHelper { // Values from https://developer.android.com/training/tv/start/layouts.html @@ -28,4 +32,31 @@ public class UiHelper { horizontalPaddingPixels, verticalPaddingPixels); } } + + public static void displayQuitConfirmationDialog(Activity parent, 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.applist_quit_confirmation)) + .setPositiveButton(parent.getResources().getString(R.string.yes), dialogClickListener) + .setNegativeButton(parent.getResources().getString(R.string.no), dialogClickListener) + .show(); + } }