mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-22 09:09:18 +01:00
Add a pairing utility for Wiimotes to Cemu (#941)
This commit is contained in:
parent
2abf1c2059
commit
d7f0d67904
@ -97,6 +97,8 @@ add_library(CemuGui
|
|||||||
MemorySearcherTool.h
|
MemorySearcherTool.h
|
||||||
PadViewFrame.cpp
|
PadViewFrame.cpp
|
||||||
PadViewFrame.h
|
PadViewFrame.h
|
||||||
|
PairingDialog.cpp
|
||||||
|
PairingDialog.h
|
||||||
TitleManager.cpp
|
TitleManager.cpp
|
||||||
TitleManager.h
|
TitleManager.h
|
||||||
windows/PPCThreadsViewer
|
windows/PPCThreadsViewer
|
||||||
@ -170,3 +172,7 @@ if (ENABLE_WXWIDGETS)
|
|||||||
# PUBLIC because wx/app.h is included in CemuApp.h
|
# PUBLIC because wx/app.h is included in CemuApp.h
|
||||||
target_link_libraries(CemuGui PUBLIC wx::base wx::core wx::gl wx::propgrid wx::xrc)
|
target_link_libraries(CemuGui PUBLIC wx::base wx::core wx::gl wx::propgrid wx::xrc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(CemuGui PRIVATE bthprops)
|
||||||
|
endif()
|
||||||
|
@ -2160,6 +2160,7 @@ void MainWindow::RecreateMenu()
|
|||||||
m_memorySearcherMenuItem->Enable(false);
|
m_memorySearcherMenuItem->Enable(false);
|
||||||
toolsMenu->Append(MAINFRAME_MENU_ID_TOOLS_TITLE_MANAGER, _("&Title Manager"));
|
toolsMenu->Append(MAINFRAME_MENU_ID_TOOLS_TITLE_MANAGER, _("&Title Manager"));
|
||||||
toolsMenu->Append(MAINFRAME_MENU_ID_TOOLS_DOWNLOAD_MANAGER, _("&Download Manager"));
|
toolsMenu->Append(MAINFRAME_MENU_ID_TOOLS_DOWNLOAD_MANAGER, _("&Download Manager"));
|
||||||
|
|
||||||
m_menuBar->Append(toolsMenu, _("&Tools"));
|
m_menuBar->Append(toolsMenu, _("&Tools"));
|
||||||
|
|
||||||
// cpu timer speed menu
|
// cpu timer speed menu
|
||||||
|
236
src/gui/PairingDialog.cpp
Normal file
236
src/gui/PairingDialog.cpp
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
#include "gui/wxgui.h"
|
||||||
|
#include "gui/PairingDialog.h"
|
||||||
|
|
||||||
|
#if BOOST_OS_WINDOWS
|
||||||
|
#include <bluetoothapis.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wxDECLARE_EVENT(wxEVT_PROGRESS_PAIR, wxCommandEvent);
|
||||||
|
wxDEFINE_EVENT(wxEVT_PROGRESS_PAIR, wxCommandEvent);
|
||||||
|
|
||||||
|
PairingDialog::PairingDialog(wxWindow* parent)
|
||||||
|
: wxDialog(parent, wxID_ANY, _("Pairing..."), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxMINIMIZE_BOX | wxSYSTEM_MENU | wxTAB_TRAVERSAL | wxCLOSE_BOX)
|
||||||
|
{
|
||||||
|
auto* sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
m_gauge = new wxGauge(this, wxID_ANY, 100, wxDefaultPosition, wxSize(350, 20), wxGA_HORIZONTAL);
|
||||||
|
m_gauge->SetValue(0);
|
||||||
|
sizer->Add(m_gauge, 0, wxALL | wxEXPAND, 5);
|
||||||
|
|
||||||
|
auto* rows = new wxFlexGridSizer(0, 2, 0, 0);
|
||||||
|
rows->AddGrowableCol(1);
|
||||||
|
|
||||||
|
m_text = new wxStaticText(this, wxID_ANY, _("Searching for controllers..."));
|
||||||
|
rows->Add(m_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto* right_side = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
|
m_cancelButton = new wxButton(this, wxID_ANY, _("Cancel"));
|
||||||
|
m_cancelButton->Bind(wxEVT_BUTTON, &PairingDialog::OnCancelButton, this);
|
||||||
|
right_side->Add(m_cancelButton, 0, wxALL, 5);
|
||||||
|
|
||||||
|
rows->Add(right_side, 1, wxALIGN_RIGHT, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
sizer->Add(rows, 0, wxALL | wxEXPAND, 5);
|
||||||
|
|
||||||
|
SetSizerAndFit(sizer);
|
||||||
|
Centre(wxBOTH);
|
||||||
|
|
||||||
|
Bind(wxEVT_CLOSE_WINDOW, &PairingDialog::OnClose, this);
|
||||||
|
Bind(wxEVT_PROGRESS_PAIR, &PairingDialog::OnGaugeUpdate, this);
|
||||||
|
|
||||||
|
m_thread = std::thread(&PairingDialog::WorkerThread, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PairingDialog::~PairingDialog()
|
||||||
|
{
|
||||||
|
Unbind(wxEVT_CLOSE_WINDOW, &PairingDialog::OnClose, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PairingDialog::OnClose(wxCloseEvent& event)
|
||||||
|
{
|
||||||
|
event.Skip();
|
||||||
|
|
||||||
|
m_threadShouldQuit = true;
|
||||||
|
if (m_thread.joinable())
|
||||||
|
m_thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PairingDialog::OnCancelButton(const wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PairingDialog::OnGaugeUpdate(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
PairingState state = (PairingState)event.GetInt();
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case PairingState::Pairing:
|
||||||
|
{
|
||||||
|
m_text->SetLabel(_("Found controller. Pairing..."));
|
||||||
|
m_gauge->SetValue(50);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PairingState::Finished:
|
||||||
|
{
|
||||||
|
m_text->SetLabel(_("Successfully paired the controller."));
|
||||||
|
m_gauge->SetValue(100);
|
||||||
|
m_cancelButton->SetLabel(_("Close"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PairingState::NoBluetoothAvailable:
|
||||||
|
{
|
||||||
|
m_text->SetLabel(_("Failed to find a suitable Bluetooth radio."));
|
||||||
|
m_gauge->SetValue(0);
|
||||||
|
m_cancelButton->SetLabel(_("Close"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PairingState::BluetoothFailed:
|
||||||
|
{
|
||||||
|
m_text->SetLabel(_("Failed to search for controllers."));
|
||||||
|
m_gauge->SetValue(0);
|
||||||
|
m_cancelButton->SetLabel(_("Close"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PairingState::PairingFailed:
|
||||||
|
{
|
||||||
|
m_text->SetLabel(_("Failed to pair with the found controller."));
|
||||||
|
m_gauge->SetValue(0);
|
||||||
|
m_cancelButton->SetLabel(_("Close"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PairingState::BluetoothUnusable:
|
||||||
|
{
|
||||||
|
m_text->SetLabel(_("Please use your system's Bluetooth manager instead."));
|
||||||
|
m_gauge->SetValue(0);
|
||||||
|
m_cancelButton->SetLabel(_("Close"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PairingDialog::WorkerThread()
|
||||||
|
{
|
||||||
|
const std::wstring wiimoteName = L"Nintendo RVL-CNT-01";
|
||||||
|
const std::wstring wiiUProControllerName = L"Nintendo RVL-CNT-01-UC";
|
||||||
|
|
||||||
|
#if BOOST_OS_WINDOWS
|
||||||
|
const GUID bthHidGuid = {0x00001124,0x0000,0x1000,{0x80,0x00,0x00,0x80,0x5F,0x9B,0x34,0xFB}};
|
||||||
|
|
||||||
|
const BLUETOOTH_FIND_RADIO_PARAMS radioFindParams =
|
||||||
|
{
|
||||||
|
.dwSize = sizeof(BLUETOOTH_FIND_RADIO_PARAMS)
|
||||||
|
};
|
||||||
|
|
||||||
|
HANDLE radio = INVALID_HANDLE_VALUE;
|
||||||
|
HBLUETOOTH_RADIO_FIND radioFind = BluetoothFindFirstRadio(&radioFindParams, &radio);
|
||||||
|
if (radioFind == nullptr)
|
||||||
|
{
|
||||||
|
UpdateCallback(PairingState::NoBluetoothAvailable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BluetoothFindRadioClose(radioFind);
|
||||||
|
|
||||||
|
BLUETOOTH_RADIO_INFO radioInfo =
|
||||||
|
{
|
||||||
|
.dwSize = sizeof(BLUETOOTH_RADIO_INFO)
|
||||||
|
};
|
||||||
|
|
||||||
|
DWORD result = BluetoothGetRadioInfo(radio, &radioInfo);
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
UpdateCallback(PairingState::NoBluetoothAvailable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BLUETOOTH_DEVICE_SEARCH_PARAMS searchParams =
|
||||||
|
{
|
||||||
|
.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS),
|
||||||
|
|
||||||
|
.fReturnAuthenticated = FALSE,
|
||||||
|
.fReturnRemembered = FALSE,
|
||||||
|
.fReturnUnknown = TRUE,
|
||||||
|
.fReturnConnected = FALSE,
|
||||||
|
|
||||||
|
.fIssueInquiry = TRUE,
|
||||||
|
.cTimeoutMultiplier = 5,
|
||||||
|
|
||||||
|
.hRadio = radio
|
||||||
|
};
|
||||||
|
|
||||||
|
BLUETOOTH_DEVICE_INFO info =
|
||||||
|
{
|
||||||
|
.dwSize = sizeof(BLUETOOTH_DEVICE_INFO)
|
||||||
|
};
|
||||||
|
|
||||||
|
while (!m_threadShouldQuit)
|
||||||
|
{
|
||||||
|
HBLUETOOTH_DEVICE_FIND deviceFind = BluetoothFindFirstDevice(&searchParams, &info);
|
||||||
|
if (deviceFind == nullptr)
|
||||||
|
{
|
||||||
|
UpdateCallback(PairingState::BluetoothFailed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!m_threadShouldQuit)
|
||||||
|
{
|
||||||
|
if (info.szName == wiimoteName || info.szName == wiiUProControllerName)
|
||||||
|
{
|
||||||
|
BluetoothFindDeviceClose(deviceFind);
|
||||||
|
|
||||||
|
UpdateCallback(PairingState::Pairing);
|
||||||
|
|
||||||
|
wchar_t passwd[6] = { radioInfo.address.rgBytes[0], radioInfo.address.rgBytes[1], radioInfo.address.rgBytes[2], radioInfo.address.rgBytes[3], radioInfo.address.rgBytes[4], radioInfo.address.rgBytes[5] };
|
||||||
|
DWORD bthResult = BluetoothAuthenticateDevice(nullptr, radio, &info, passwd, 6);
|
||||||
|
if (bthResult != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
UpdateCallback(PairingState::PairingFailed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bthResult = BluetoothSetServiceState(radio, &info, &bthHidGuid, BLUETOOTH_SERVICE_ENABLE);
|
||||||
|
if (bthResult != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
UpdateCallback(PairingState::PairingFailed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateCallback(PairingState::Finished);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL nextDevResult = BluetoothFindNextDevice(deviceFind, &info);
|
||||||
|
if (nextDevResult == FALSE)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BluetoothFindDeviceClose(deviceFind);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
UpdateCallback(PairingState::BluetoothUnusable);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PairingDialog::UpdateCallback(PairingState state)
|
||||||
|
{
|
||||||
|
auto* event = new wxCommandEvent(wxEVT_PROGRESS_PAIR);
|
||||||
|
event->SetInt((int)state);
|
||||||
|
wxQueueEvent(this, event);
|
||||||
|
}
|
38
src/gui/PairingDialog.h
Normal file
38
src/gui/PairingDialog.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wx/button.h>
|
||||||
|
#include <wx/dialog.h>
|
||||||
|
#include <wx/gauge.h>
|
||||||
|
#include <wx/stattext.h>
|
||||||
|
|
||||||
|
class PairingDialog : public wxDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PairingDialog(wxWindow* parent);
|
||||||
|
~PairingDialog();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class PairingState
|
||||||
|
{
|
||||||
|
Pairing,
|
||||||
|
Finished,
|
||||||
|
NoBluetoothAvailable,
|
||||||
|
BluetoothFailed,
|
||||||
|
PairingFailed,
|
||||||
|
BluetoothUnusable
|
||||||
|
};
|
||||||
|
|
||||||
|
void OnClose(wxCloseEvent& event);
|
||||||
|
void OnCancelButton(const wxCommandEvent& event);
|
||||||
|
void OnGaugeUpdate(wxCommandEvent& event);
|
||||||
|
|
||||||
|
void WorkerThread();
|
||||||
|
void UpdateCallback(PairingState state);
|
||||||
|
|
||||||
|
wxStaticText* m_text;
|
||||||
|
wxGauge* m_gauge;
|
||||||
|
wxButton* m_cancelButton;
|
||||||
|
|
||||||
|
std::thread m_thread;
|
||||||
|
bool m_threadShouldQuit = false;
|
||||||
|
};
|
@ -1,5 +1,6 @@
|
|||||||
#include "gui/input/panels/WiimoteInputPanel.h"
|
#include "gui/input/panels/WiimoteInputPanel.h"
|
||||||
|
|
||||||
|
#include <wx/button.h>
|
||||||
#include <wx/gbsizer.h>
|
#include <wx/gbsizer.h>
|
||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
#include <wx/statline.h>
|
#include <wx/statline.h>
|
||||||
@ -11,6 +12,7 @@
|
|||||||
#include "input/emulated/WiimoteController.h"
|
#include "input/emulated/WiimoteController.h"
|
||||||
#include "gui/helpers/wxHelpers.h"
|
#include "gui/helpers/wxHelpers.h"
|
||||||
#include "gui/components/wxInputDraw.h"
|
#include "gui/components/wxInputDraw.h"
|
||||||
|
#include "gui/PairingDialog.h"
|
||||||
|
|
||||||
constexpr WiimoteController::ButtonId g_kFirstColumnItems[] =
|
constexpr WiimoteController::ButtonId g_kFirstColumnItems[] =
|
||||||
{
|
{
|
||||||
@ -36,10 +38,18 @@ WiimoteInputPanel::WiimoteInputPanel(wxWindow* parent)
|
|||||||
bold_font.MakeBold();
|
bold_font.MakeBold();
|
||||||
|
|
||||||
auto* main_sizer = new wxBoxSizer(wxVERTICAL);
|
auto* main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
auto* horiz_main_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
auto* extensions_sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto* pair_button = new wxButton(this, wxID_ANY, _("Pair a Wii or Wii U controller"));
|
||||||
extensions_sizer->Add(new wxStaticText(this, wxID_ANY, _("Extensions:")));
|
pair_button->Bind(wxEVT_BUTTON, &WiimoteInputPanel::on_pair_button, this);
|
||||||
extensions_sizer->AddSpacer(10);
|
horiz_main_sizer->Add(pair_button);
|
||||||
|
horiz_main_sizer->AddSpacer(10);
|
||||||
|
|
||||||
|
auto* extensions_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
horiz_main_sizer->Add(extensions_sizer, wxSizerFlags(0).Align(wxALIGN_CENTER_VERTICAL));
|
||||||
|
|
||||||
|
extensions_sizer->Add(new wxStaticText(this, wxID_ANY, _("Extensions:")));
|
||||||
|
extensions_sizer->AddSpacer(10);
|
||||||
|
|
||||||
m_motion_plus = new wxCheckBox(this, wxID_ANY, _("MotionPlus"));
|
m_motion_plus = new wxCheckBox(this, wxID_ANY, _("MotionPlus"));
|
||||||
m_motion_plus->Bind(wxEVT_CHECKBOX, &WiimoteInputPanel::on_extension_change, this);
|
m_motion_plus->Bind(wxEVT_CHECKBOX, &WiimoteInputPanel::on_extension_change, this);
|
||||||
@ -54,7 +64,7 @@ WiimoteInputPanel::WiimoteInputPanel(wxWindow* parent)
|
|||||||
m_classic->Hide();
|
m_classic->Hide();
|
||||||
extensions_sizer->Add(m_classic);
|
extensions_sizer->Add(m_classic);
|
||||||
|
|
||||||
main_sizer->Add(extensions_sizer, 0, wxEXPAND | wxALL, 5);
|
main_sizer->Add(horiz_main_sizer, 0, wxEXPAND | wxALL, 5);
|
||||||
main_sizer->Add(new wxStaticLine(this), 0, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, 5);
|
main_sizer->Add(new wxStaticLine(this), 0, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, 5);
|
||||||
|
|
||||||
m_item_sizer = new wxGridBagSizer();
|
m_item_sizer = new wxGridBagSizer();
|
||||||
@ -254,3 +264,9 @@ void WiimoteInputPanel::load_controller(const EmulatedControllerPtr& emulated_co
|
|||||||
set_active_device_type(wiimote->get_device_type());
|
set_active_device_type(wiimote->get_device_type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WiimoteInputPanel::on_pair_button(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
PairingDialog pairing_dialog(this);
|
||||||
|
pairing_dialog.ShowModal();
|
||||||
|
}
|
||||||
|
@ -25,6 +25,7 @@ private:
|
|||||||
|
|
||||||
void on_volume_change(wxCommandEvent& event);
|
void on_volume_change(wxCommandEvent& event);
|
||||||
void on_extension_change(wxCommandEvent& event);
|
void on_extension_change(wxCommandEvent& event);
|
||||||
|
void on_pair_button(wxCommandEvent& event);
|
||||||
|
|
||||||
wxGridBagSizer* m_item_sizer;
|
wxGridBagSizer* m_item_sizer;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user