|
14 | 14 | import com.limelight.nvstream.http.NvApp; |
15 | 15 | import com.limelight.nvstream.http.NvHTTP; |
16 | 16 | import com.limelight.nvstream.http.PairingManager; |
| 17 | +import com.limelight.nvstream.http.NvHTTP.DisplayInfo; |
| 18 | +import com.limelight.binding.PlatformBinding; |
17 | 19 | import com.limelight.preferences.PreferenceConfiguration; |
18 | 20 | import com.limelight.ui.AdapterFragment; |
19 | 21 | import com.limelight.ui.AdapterFragmentCallbacks; |
|
27 | 29 | import com.limelight.utils.SpinnerDialog; |
28 | 30 | import com.limelight.utils.UiHelper; |
29 | 31 | import com.limelight.utils.AppSettingsManager; |
| 32 | +import com.limelight.LimeLog; |
| 33 | +import com.limelight.Game; |
| 34 | +import com.limelight.binding.PlatformBinding; |
30 | 35 |
|
31 | 36 | import android.annotation.SuppressLint; |
32 | 37 | import android.app.Activity; |
@@ -101,6 +106,11 @@ public class AppView extends Activity implements AdapterFragmentCallbacks { |
101 | 106 | private LinearLayout lastSettingsInfo; |
102 | 107 | private TextView lastSettingsText; |
103 | 108 | private CheckBox useLastSettingsCheckbox; |
| 109 | + |
| 110 | + // 显示器选择相关 |
| 111 | + private LinearLayout displaySelectionInfo; |
| 112 | + private android.widget.RadioGroup displayRadioGroup; |
| 113 | + private List<DisplayInfo> availableDisplays; |
104 | 114 |
|
105 | 115 | private final static int START_OR_RESUME_ID = 1; |
106 | 116 | private final static int QUIT_ID = 2; |
@@ -355,6 +365,10 @@ protected void onCreate(Bundle savedInstanceState) { |
355 | 365 | lastSettingsText = findViewById(R.id.lastSettingsText); |
356 | 366 | useLastSettingsCheckbox = findViewById(R.id.useLastSettingsCheckbox); |
357 | 367 |
|
| 368 | + // Initialize display selection UI components |
| 369 | + displaySelectionInfo = findViewById(R.id.displaySelectionInfo); |
| 370 | + displayRadioGroup = findViewById(R.id.displayRadioGroup); |
| 371 | + |
358 | 372 | // Set up event listeners |
359 | 373 | useLastSettingsCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> { |
360 | 374 | appSettingsManager.setUseLastSettingsEnabled(isChecked); |
@@ -401,6 +415,11 @@ protected void onCreate(Bundle savedInstanceState) { |
401 | 415 | // Bind to the computer manager service |
402 | 416 | bindService(new Intent(this, ComputerManagerService.class), serviceConnection, |
403 | 417 | Service.BIND_AUTO_CREATE); |
| 418 | + |
| 419 | + // Delay checking displays to allow service connection to complete |
| 420 | + new Handler(Looper.getMainLooper()).postDelayed(() -> { |
| 421 | + checkDisplaysAndUpdateUI(); |
| 422 | + }, 500); |
404 | 423 | } |
405 | 424 |
|
406 | 425 | private void updateHiddenApps(boolean hideImmediately) { |
@@ -551,7 +570,6 @@ private void handleSelectionChange(int position, AppObject app) { |
551 | 570 | isFirstFocus = false; // 第一次后设置为false |
552 | 571 | } |
553 | 572 |
|
554 | | - // 更新上一次设置信息显示 |
555 | 573 | updateLastSettingsInfo(app); |
556 | 574 | } |
557 | 575 |
|
@@ -591,14 +609,115 @@ private void updateLastSettingsInfo(AppObject app) { |
591 | 609 | * @param app 应用对象 |
592 | 610 | */ |
593 | 611 | private void startStreamWithLastSettingsIfEnabled(AppObject app) { |
| 612 | + String displayGuid = null; |
| 613 | + if (displaySelectionInfo.getVisibility() == View.VISIBLE |
| 614 | + && availableDisplays != null) { |
| 615 | + int selectedId = displayRadioGroup.getCheckedRadioButtonId(); |
| 616 | + if (selectedId >= 0 && selectedId < availableDisplays.size()) { |
| 617 | + DisplayInfo selectedDisplay = availableDisplays.get(selectedId); |
| 618 | + displayGuid = selectedDisplay.guid != null && !selectedDisplay.guid.isEmpty() |
| 619 | + ? selectedDisplay.guid : selectedDisplay.name; |
| 620 | + } |
| 621 | + } |
| 622 | + |
| 623 | + doStartStream(app, displayGuid); |
| 624 | + } |
| 625 | + |
| 626 | + /** |
| 627 | + * 检查显示器并更新UI |
| 628 | + */ |
| 629 | + private void checkDisplaysAndUpdateUI() { |
| 630 | + if (computer == null || computer.activeAddress == null || managerBinder == null) { |
| 631 | + displaySelectionInfo.setVisibility(View.GONE); |
| 632 | + return; |
| 633 | + } |
| 634 | + |
| 635 | + new Thread(() -> { |
| 636 | + try { |
| 637 | + NvHTTP httpConn = new NvHTTP(computer.activeAddress, computer.httpsPort, |
| 638 | + managerBinder.getUniqueId(), "", computer.serverCert, |
| 639 | + PlatformBinding.getCryptoProvider(this)); |
| 640 | + |
| 641 | + List<DisplayInfo> displays = httpConn.getDisplays(); |
| 642 | + |
| 643 | + runOnUiThread(() -> { |
| 644 | + if (displays != null && displays.size() > 1) { |
| 645 | + updateDisplaySelectionUI(displays); |
| 646 | + } else { |
| 647 | + displaySelectionInfo.setVisibility(View.GONE); |
| 648 | + } |
| 649 | + }); |
| 650 | + } catch (Exception e) { |
| 651 | + LimeLog.warning("Failed to get displays: " + e.getMessage()); |
| 652 | + runOnUiThread(() -> displaySelectionInfo.setVisibility(View.GONE)); |
| 653 | + } |
| 654 | + }).start(); |
| 655 | + } |
| 656 | + |
| 657 | + /** |
| 658 | + * 更新显示器选择UI |
| 659 | + * |
| 660 | + * @param displays 显示器列表 |
| 661 | + */ |
| 662 | + private void updateDisplaySelectionUI(List<DisplayInfo> displays) { |
| 663 | + availableDisplays = displays; |
| 664 | + |
| 665 | + // 清除之前的单选按钮 |
| 666 | + displayRadioGroup.removeAllViews(); |
| 667 | + |
| 668 | + LimeLog.info("Displays: " + displays.size()); |
| 669 | + for (int i = 0; i < displays.size(); i++) { |
| 670 | + DisplayInfo display = displays.get(i); |
| 671 | + // 使用友好名字显示 |
| 672 | + String displayName = display.name != null && !display.name.isEmpty() |
| 673 | + ? display.name : "Display " + (display.index + 1); |
| 674 | + LimeLog.info("Display " + (display.index + 1) + ": " + display.name + " (guid: " + display.guid + ")"); |
| 675 | + |
| 676 | + // 创建单选按钮 |
| 677 | + android.widget.RadioButton radioButton = new android.widget.RadioButton(this); |
| 678 | + radioButton.setId(i); |
| 679 | + radioButton.setText(displayName); |
| 680 | + radioButton.setTextColor(0xCCFFFFFF); |
| 681 | + radioButton.setTextSize(12); |
| 682 | + radioButton.setTypeface(android.graphics.Typeface.create("sans-serif-light", android.graphics.Typeface.NORMAL)); |
| 683 | + radioButton.setButtonTintList(android.content.res.ColorStateList.valueOf(0xFFFFFFFF)); |
| 684 | + radioButton.setPadding(0, 0, 20, 0); // 右边距 |
| 685 | + |
| 686 | + displayRadioGroup.addView(radioButton); |
| 687 | + } |
| 688 | + |
| 689 | + // 默认不选择任何显示器 |
| 690 | + displayRadioGroup.clearCheck(); |
| 691 | + |
| 692 | + displaySelectionInfo.setVisibility(View.VISIBLE); |
| 693 | + } |
| 694 | + |
| 695 | + /** |
| 696 | + * 执行启动串流 |
| 697 | + * |
| 698 | + * @param app 应用对象 |
| 699 | + * @param displayName 选择的显示器名称,如果为null则不指定显示器 |
| 700 | + */ |
| 701 | + private void doStartStream(AppObject app, String displayName) { |
594 | 702 | if (appSettingsManager != null && computer != null) { |
595 | 703 | // 使用AppSettingsManager统一管理启动逻辑 |
596 | 704 | Intent startIntent = appSettingsManager.createStartIntentWithLastSettingsIfEnabled( |
597 | 705 | this, app.app, computer, managerBinder); |
| 706 | + if (displayName != null) { |
| 707 | + startIntent.putExtra(Game.EXTRA_DISPLAY_NAME, displayName); |
| 708 | + } |
598 | 709 | startActivity(startIntent); |
599 | 710 | } else { |
600 | 711 | // 回退到默认方式启动 |
601 | | - ServerHelper.doStart(this, app.app, computer, managerBinder); |
| 712 | + if (displayName != null) { |
| 713 | + Intent startIntent = ServerHelper.createStartIntent(this, app.app, computer, managerBinder); |
| 714 | + startIntent.putExtra(Game.EXTRA_DISPLAY_NAME, displayName); |
| 715 | + startActivity(startIntent); |
| 716 | + } else { |
| 717 | + if (computer != null) { |
| 718 | + ServerHelper.doStart(this, app.app, computer, managerBinder); |
| 719 | + } |
| 720 | + } |
602 | 721 | } |
603 | 722 | } |
604 | 723 |
|
|
0 commit comments