diff --git a/Source/Core/DolphinQt/Config/ControllersWindow.cpp b/Source/Core/DolphinQt/Config/ControllersWindow.cpp index bb0e7a0489..2470910e8e 100644 --- a/Source/Core/DolphinQt/Config/ControllersWindow.cpp +++ b/Source/Core/DolphinQt/Config/ControllersWindow.cpp @@ -27,7 +27,6 @@ void ControllersWindow::showEvent(QShowEvent* event) { QDialog::showEvent(event); m_wiimote_controllers->UpdateBluetoothAvailableStatus(); - m_wiimote_controllers->RefreshBluetoothAdapters(); } void ControllersWindow::CreateMainLayout() diff --git a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp index 69de3837ad..960cfac080 100644 --- a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp +++ b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp @@ -19,6 +19,7 @@ #include #include "Common/Config/Config.h" +#include "Common/WorkQueueThread.h" #include "Core/Config/MainSettings.h" #include "Core/Config/WiimoteSettings.h" @@ -35,6 +36,7 @@ #include "DolphinQt/Config/Mapping/MappingWindow.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" +#include "DolphinQt/QtUtils/QueueOnObject.h" #include "DolphinQt/QtUtils/SetWindowDecorations.h" #include "DolphinQt/QtUtils/SignalBlocking.h" #include "DolphinQt/Settings.h" @@ -51,6 +53,14 @@ WiimoteControllersWidget::WiimoteControllersWidget(QWidget* parent) : QWidget(pa connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) { LoadSettings(state); }); LoadSettings(Core::GetState(Core::System::GetInstance())); + + m_bluetooth_adapter_refresh_thread.Reset("Bluetooth Adapter Refresh Thread"); + StartBluetoothAdapterRefresh(); +} + +WiimoteControllersWidget::~WiimoteControllersWidget() +{ + m_bluetooth_adapter_refresh_thread.WaitForCompletion(); } void WiimoteControllersWidget::UpdateBluetoothAvailableStatus() @@ -58,17 +68,46 @@ void WiimoteControllersWidget::UpdateBluetoothAvailableStatus() m_bluetooth_unavailable->setHidden(WiimoteReal::IsScannerReady()); } -void WiimoteControllersWidget::RefreshBluetoothAdapters() +void WiimoteControllersWidget::StartBluetoothAdapterRefresh() { - m_bluetooth_adapters->clear(); + if (m_bluetooth_adapter_scan_in_progress) + return; + m_bluetooth_adapters->clear(); + m_bluetooth_adapters->setDisabled(true); + m_bluetooth_adapters->addItem(tr("Scanning for adapters...")); + + m_bluetooth_adapter_scan_in_progress = true; + + const auto scan_func = [this]() { + INFO_LOG_FMT(COMMON, "Refreshing Bluetooth adapter list..."); + auto device_list = IOS::HLE::BluetoothRealDevice::ListDevices(); + INFO_LOG_FMT(COMMON, "{} Bluetooth adapters available.", device_list.size()); + const auto refresh_complete_func = [this, devices = std::move(device_list)]() { + OnBluetoothAdapterRefreshComplete(devices); + }; + QueueOnObject(this, refresh_complete_func); + }; + + m_bluetooth_adapter_refresh_thread.Push(scan_func); +} + +void WiimoteControllersWidget::OnBluetoothAdapterRefreshComplete( + const std::vector& devices) +{ const int configured_vid = Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_VID); const int configured_pid = Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_PID); bool found_configured_device = configured_vid == -1 || configured_pid == -1; + m_bluetooth_adapters->clear(); + m_bluetooth_adapter_scan_in_progress = false; + + const auto state = Core::GetState(Core::System::GetInstance()); + UpdateBluetoothAdapterWidgetsEnabled(state); + m_bluetooth_adapters->addItem(tr("Automatic")); - for (auto& device : IOS::HLE::BluetoothRealDevice::ListDevices()) + for (auto& device : devices) { std::string name = device.name.empty() ? tr("Unknown Device").toStdString() : device.name; QString device_info = @@ -149,8 +188,9 @@ void WiimoteControllersWidget::CreateLayout() m_wiimote_box->setLayout(m_wiimote_layout); m_wiimote_passthrough = new QRadioButton(tr("Passthrough a Bluetooth adapter")); - m_bluetooth_adapters_label = new QLabel(tr("Bluetooth adapter")); + m_bluetooth_adapters_label = new QLabel(tr("Adapter")); m_bluetooth_adapters = new QComboBox(); + m_bluetooth_adapters_refresh = new NonDefaultQPushButton(tr("Refresh")); m_wiimote_sync = new NonDefaultQPushButton(tr("Sync")); m_wiimote_reset = new NonDefaultQPushButton(tr("Reset")); m_wiimote_refresh = new NonDefaultQPushButton(tr("Refresh")); @@ -172,7 +212,8 @@ void WiimoteControllersWidget::CreateLayout() int adapter_row = m_wiimote_layout->rowCount(); m_wiimote_layout->addWidget(m_bluetooth_adapters_label, adapter_row, 1, 1, 1); - m_wiimote_layout->addWidget(m_bluetooth_adapters, adapter_row, 2, 1, 2); + m_wiimote_layout->addWidget(m_bluetooth_adapters, adapter_row, 2, 1, 1); + m_wiimote_layout->addWidget(m_bluetooth_adapters_refresh, adapter_row, 3, 1, 1); int sync_row = m_wiimote_layout->rowCount(); m_wiimote_layout->addWidget(m_wiimote_pt_labels[0], sync_row, 1, 1, 2); @@ -242,6 +283,8 @@ void WiimoteControllersWidget::ConnectWidgets() &WiimoteControllersWidget::SaveSettings); connect(m_bluetooth_adapters, &QComboBox::activated, this, &WiimoteControllersWidget::OnBluetoothPassthroughDeviceChanged); + connect(m_bluetooth_adapters_refresh, &QPushButton::clicked, this, + &WiimoteControllersWidget::StartBluetoothAdapterRefresh); connect(m_wiimote_sync, &QPushButton::clicked, this, &WiimoteControllersWidget::OnBluetoothPassthroughSyncPressed); connect(m_wiimote_reset, &QPushButton::clicked, this, @@ -339,6 +382,19 @@ void WiimoteControllersWidget::OnWiimoteConfigure(size_t index) window->show(); } +void WiimoteControllersWidget::UpdateBluetoothAdapterWidgetsEnabled(const Core::State state) +{ + const bool running = state != Core::State::Uninitialized; + const bool running_wii = running && Core::System::GetInstance().IsWii(); + const bool enable_adapter_refresh = m_wiimote_passthrough->isChecked() && !running_wii; + const bool enable_adapter_selection = + enable_adapter_refresh && !m_bluetooth_adapter_scan_in_progress; + + m_bluetooth_adapters_label->setEnabled(enable_adapter_selection); + m_bluetooth_adapters->setEnabled(enable_adapter_selection); + m_bluetooth_adapters_refresh->setEnabled(enable_adapter_refresh); +} + void WiimoteControllersWidget::LoadSettings(Core::State state) { for (size_t i = 0; i < m_wiimote_groups.size(); i++) @@ -369,15 +425,13 @@ void WiimoteControllersWidget::LoadSettings(Core::State state) m_wiimote_passthrough->setEnabled(!running); const bool running_gc = running && !Core::System::GetInstance().IsWii(); - const bool running_wii = running && Core::System::GetInstance().IsWii(); const bool enable_passthrough = m_wiimote_passthrough->isChecked() && !running_gc; - const bool enable_adapter_selection = m_wiimote_passthrough->isChecked() && !running_wii; const bool enable_emu_bt = !m_wiimote_passthrough->isChecked() && !running_gc; const bool is_netplay = NetPlay::IsNetPlayRunning(); const bool running_netplay = running && is_netplay; - m_bluetooth_adapters_label->setEnabled(enable_adapter_selection); - m_bluetooth_adapters->setEnabled(enable_adapter_selection); + UpdateBluetoothAdapterWidgetsEnabled(state); + m_wiimote_sync->setEnabled(enable_passthrough); m_wiimote_reset->setEnabled(enable_passthrough); diff --git a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h index bb2f50caad..b174c1b786 100644 --- a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h +++ b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h @@ -3,9 +3,12 @@ #pragma once +#include + #include -#include +#include "Common/WorkQueueThread.h" +#include "Core/IOS/USB/Bluetooth/BTReal.h" class QCheckBox; class QComboBox; @@ -26,17 +29,21 @@ class WiimoteControllersWidget final : public QWidget Q_OBJECT public: explicit WiimoteControllersWidget(QWidget* parent); + ~WiimoteControllersWidget(); void UpdateBluetoothAvailableStatus(); - void RefreshBluetoothAdapters(); private: void SaveSettings(); void OnBluetoothPassthroughDeviceChanged(int index); void OnBluetoothPassthroughSyncPressed(); void OnBluetoothPassthroughResetPressed(); + void OnBluetoothAdapterRefreshComplete( + const std::vector& devices); void OnWiimoteRefreshPressed(); void OnWiimoteConfigure(size_t index); + void StartBluetoothAdapterRefresh(); + void UpdateBluetoothAdapterWidgetsEnabled(Core::State state); void CreateLayout(); void ConnectWidgets(); @@ -50,10 +57,14 @@ private: std::array m_wiimote_groups; std::array m_wiimote_pt_labels; + Common::AsyncWorkThreadSP m_bluetooth_adapter_refresh_thread; + bool m_bluetooth_adapter_scan_in_progress = false; + QRadioButton* m_wiimote_emu; QRadioButton* m_wiimote_passthrough; QLabel* m_bluetooth_adapters_label; QComboBox* m_bluetooth_adapters; + QPushButton* m_bluetooth_adapters_refresh; QPushButton* m_wiimote_sync; QPushButton* m_wiimote_reset; QCheckBox* m_wiimote_continuous_scanning;