DolphinWX: Add USB passthrough settings

Allows adding/removing devices from USB passthrough.
This commit is contained in:
Léo Lam 2016-10-31 21:51:35 +01:00
parent 69a13a12e2
commit b7cc25535f
7 changed files with 313 additions and 3 deletions

View File

@ -7,6 +7,7 @@ set(GUI_SRCS
Cheats/CheatsWindow.cpp
Cheats/CreateCodeDialog.cpp
Cheats/GeckoCodeDiag.cpp
Config/AddUSBDeviceDiag.cpp
Config/AdvancedConfigPane.cpp
Config/AudioConfigPane.cpp
Config/ConfigMain.cpp

View File

@ -0,0 +1,164 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <algorithm>
#include <wx/button.h>
#include <wx/dialog.h>
#include <wx/listbox.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/window.h>
#include "Common/StringUtil.h"
#include "Core/ConfigManager.h"
#include "DolphinWX/Config/AddUSBDeviceDiag.h"
#include "DolphinWX/WxUtils.h"
#include "UICommon/USBUtils.h"
AddUSBDeviceDiag::AddUSBDeviceDiag(wxWindow* const parent)
: wxDialog(parent, wxID_ANY, _("Add New USB Device"))
{
InitControls();
RefreshDeviceList();
Bind(wxEVT_TIMER, &AddUSBDeviceDiag::OnRefreshDevicesTimer, this,
m_refresh_devices_timer.GetId());
m_refresh_devices_timer.Start(DEVICE_REFRESH_INTERVAL_MS, wxTIMER_CONTINUOUS);
auto* const btn_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
btn_sizer->GetAffirmativeButton()->SetLabel(_("Add"));
Bind(wxEVT_BUTTON, &AddUSBDeviceDiag::OnSave, this, wxID_OK);
auto* const sizer = new wxBoxSizer(wxVERTICAL);
const int space5 = FromDIP(5);
sizer->AddSpacer(FromDIP(10));
sizer->Add(new wxStaticText(this, wxID_ANY, _("Enter USB device ID"), wxDefaultPosition,
wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL),
0, wxEXPAND | wxBOTTOM, FromDIP(10));
sizer->Add(CreateManualControlsSizer(), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
sizer->Add(new wxStaticText(this, wxID_ANY, _("or select a device"), wxDefaultPosition,
wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL),
0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(10));
auto* const device_list_sizer = CreateDeviceListSizer();
sizer->Add(device_list_sizer, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, space5);
sizer->SetItemMinSize(device_list_sizer, FromDIP(350), FromDIP(150));
sizer->Add(btn_sizer, 0, wxEXPAND);
sizer->AddSpacer(space5);
SetSizerAndFit(sizer);
Center();
}
void AddUSBDeviceDiag::InitControls()
{
m_new_device_vid_ctrl = new wxTextCtrl(this, wxID_ANY);
m_new_device_pid_ctrl = new wxTextCtrl(this, wxID_ANY);
// i18n: VID means Vendor ID (in the context of a USB device)
m_new_device_vid_ctrl->SetHint(_("Device VID (e.g., 057e)"));
// i18n: PID means Product ID (in the context of a USB device), not Process ID
m_new_device_pid_ctrl->SetHint(_("Device PID (e.g., 0305)"));
m_inserted_devices_listbox = new wxListBox(this, wxID_ANY);
m_inserted_devices_listbox->Bind(wxEVT_LISTBOX, &AddUSBDeviceDiag::OnDeviceSelection, this);
m_inserted_devices_listbox->Bind(wxEVT_LISTBOX_DCLICK, &AddUSBDeviceDiag::OnSave, this);
}
void AddUSBDeviceDiag::RefreshDeviceList()
{
const auto& current_devices = USBUtils::GetInsertedDevices();
if (current_devices == m_shown_devices)
return;
m_inserted_devices_listbox->Freeze();
const auto selection_string = m_inserted_devices_listbox->GetStringSelection();
m_inserted_devices_listbox->Clear();
for (const auto& device : current_devices)
{
if (SConfig::GetInstance().IsUSBDeviceWhitelisted(device.first))
continue;
m_inserted_devices_listbox->Append(device.second, new USBPassthroughDeviceEntry(device.first));
}
if (!selection_string.empty())
m_inserted_devices_listbox->SetStringSelection(selection_string);
m_inserted_devices_listbox->Thaw();
m_shown_devices = current_devices;
}
wxSizer* AddUSBDeviceDiag::CreateManualControlsSizer()
{
const int space5 = FromDIP(5);
auto* const sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(m_new_device_vid_ctrl, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
sizer->Add(m_new_device_pid_ctrl, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
return sizer;
}
wxSizer* AddUSBDeviceDiag::CreateDeviceListSizer()
{
const int space5 = FromDIP(5);
auto* const sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(m_inserted_devices_listbox, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
return sizer;
}
static bool IsValidUSBIDString(const std::string& string)
{
if (string.empty() || string.length() > 4)
return false;
return std::all_of(string.begin(), string.end(),
[](const auto character) { return std::isxdigit(character) != 0; });
}
void AddUSBDeviceDiag::OnRefreshDevicesTimer(wxTimerEvent&)
{
RefreshDeviceList();
}
void AddUSBDeviceDiag::OnDeviceSelection(wxCommandEvent&)
{
const int index = m_inserted_devices_listbox->GetSelection();
if (index == wxNOT_FOUND)
return;
auto* const entry = static_cast<const USBPassthroughDeviceEntry*>(
m_inserted_devices_listbox->GetClientObject(index));
m_new_device_vid_ctrl->SetValue(StringFromFormat("%04x", entry->m_vid));
m_new_device_pid_ctrl->SetValue(StringFromFormat("%04x", entry->m_pid));
}
void AddUSBDeviceDiag::OnSave(wxCommandEvent&)
{
const std::string vid_string = StripSpaces(WxStrToStr(m_new_device_vid_ctrl->GetValue()));
const std::string pid_string = StripSpaces(WxStrToStr(m_new_device_pid_ctrl->GetValue()));
if (!IsValidUSBIDString(vid_string))
{
// i18n: Here, VID means Vendor ID (for a USB device).
WxUtils::ShowErrorDialog(_("The entered VID is invalid."));
return;
}
if (!IsValidUSBIDString(pid_string))
{
// i18n: Here, PID means Product ID (for a USB device).
WxUtils::ShowErrorDialog(_("The entered PID is invalid."));
return;
}
const u16 vid = static_cast<u16>(std::stoul(vid_string, nullptr, 16));
const u16 pid = static_cast<u16>(std::stoul(pid_string, nullptr, 16));
if (SConfig::GetInstance().IsUSBDeviceWhitelisted({vid, pid}))
{
WxUtils::ShowErrorDialog(_("This USB device is already whitelisted."));
return;
}
SConfig::GetInstance().m_usb_passthrough_devices.emplace(vid, pid);
AcceptAndClose();
}

View File

@ -0,0 +1,56 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <map>
#include <utility>
#include <wx/clntdata.h>
#include <wx/dialog.h>
#include <wx/timer.h>
#include "Common/CommonTypes.h"
class wxListBox;
class wxSizer;
class wxTextCtrl;
class USBPassthroughDeviceEntry final : public wxClientData
{
public:
explicit USBPassthroughDeviceEntry(const std::pair<u16, u16> pair)
: m_vid(pair.first), m_pid(pair.second)
{
}
const u16 m_vid;
const u16 m_pid;
};
// This dialog is used to add a new USB device to the USB passthrough whitelist,
// either by selecting a connected USB device or by entering the PID/VID manually.
class AddUSBDeviceDiag final : public wxDialog
{
public:
explicit AddUSBDeviceDiag(wxWindow* parent);
private:
static constexpr int DEVICE_REFRESH_INTERVAL_MS = 100;
void InitControls();
void RefreshDeviceList();
wxSizer* CreateManualControlsSizer();
wxSizer* CreateDeviceListSizer();
void OnRefreshDevicesTimer(wxTimerEvent&);
void OnDeviceSelection(wxCommandEvent&);
void OnSave(wxCommandEvent&);
std::map<std::pair<u16, u16>, std::string> m_shown_devices;
wxTimer m_refresh_devices_timer{this};
wxTextCtrl* m_new_device_vid_ctrl;
wxTextCtrl* m_new_device_pid_ctrl;
wxListBox* m_inserted_devices_listbox;
};

View File

@ -2,11 +2,11 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "DolphinWX/Config/WiiConfigPane.h"
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/choice.h>
#include <wx/gbsizer.h>
#include <wx/listbox.h>
#include <wx/sizer.h>
#include <wx/slider.h>
#include <wx/stattext.h>
@ -14,9 +14,12 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/IOS/IPC.h"
#include "DolphinWX/Config/AddUSBDeviceDiag.h"
#include "DolphinWX/Config/WiiConfigPane.h"
#include "DolphinWX/DolphinSlider.h"
#include "DolphinWX/WxEventUtils.h"
#include "DolphinWX/WxUtils.h"
#include "UICommon/USBUtils.h"
WiiConfigPane::WiiConfigPane(wxWindow* parent, wxWindowID id) : wxPanel(parent, id)
{
@ -52,6 +55,10 @@ void WiiConfigPane::InitializeGUI()
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_system_language_strings);
m_sd_card_checkbox = new wxCheckBox(this, wxID_ANY, _("Insert SD Card"));
m_connect_keyboard_checkbox = new wxCheckBox(this, wxID_ANY, _("Connect USB Keyboard"));
m_usb_passthrough_devices_listbox =
new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 100));
m_usb_passthrough_add_device_btn = new wxButton(this, wxID_ANY, _("Add..."));
m_usb_passthrough_rem_device_btn = new wxButton(this, wxID_ANY, _("Remove"));
m_bt_sensor_bar_pos =
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_bt_sensor_bar_pos_strings);
m_bt_sensor_bar_sens = new DolphinSlider(this, wxID_ANY, 0, 0, 4);
@ -79,6 +86,12 @@ void WiiConfigPane::InitializeGUI()
misc_settings_grid_sizer->Add(m_system_language_choice, wxGBPosition(3, 1), wxDefaultSpan,
wxALIGN_CENTER_VERTICAL);
auto* const usb_passthrough_btn_sizer = new wxBoxSizer(wxHORIZONTAL);
usb_passthrough_btn_sizer->AddStretchSpacer();
usb_passthrough_btn_sizer->Add(m_usb_passthrough_add_device_btn, 0,
wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, space5);
usb_passthrough_btn_sizer->Add(m_usb_passthrough_rem_device_btn, 0, wxALIGN_CENTER_VERTICAL);
auto* const bt_sensor_bar_pos_sizer = new wxBoxSizer(wxHORIZONTAL);
bt_sensor_bar_pos_sizer->Add(new wxStaticText(this, wxID_ANY, _("Min")), 0,
wxALIGN_CENTER_VERTICAL);
@ -123,6 +136,15 @@ void WiiConfigPane::InitializeGUI()
device_settings_sizer->Add(m_connect_keyboard_checkbox, 0, wxLEFT | wxRIGHT, space5);
device_settings_sizer->AddSpacer(space5);
auto* const usb_passthrough_sizer =
new wxStaticBoxSizer(wxVERTICAL, this, _("Whitelisted USB Passthrough Devices"));
usb_passthrough_sizer->AddSpacer(space5);
usb_passthrough_sizer->Add(m_usb_passthrough_devices_listbox, 0, wxEXPAND | wxLEFT | wxRIGHT,
space5);
usb_passthrough_sizer->AddSpacer(space5);
usb_passthrough_sizer->Add(usb_passthrough_btn_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
usb_passthrough_sizer->AddSpacer(space5);
auto* const bt_settings_static_sizer =
new wxStaticBoxSizer(wxVERTICAL, this, _("Wii Remote Settings"));
bt_settings_static_sizer->AddSpacer(space5);
@ -135,6 +157,8 @@ void WiiConfigPane::InitializeGUI()
main_sizer->AddSpacer(space5);
main_sizer->Add(device_settings_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
main_sizer->AddSpacer(space5);
main_sizer->Add(usb_passthrough_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
main_sizer->AddSpacer(space5);
main_sizer->Add(bt_settings_static_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
main_sizer->AddSpacer(space5);
@ -151,12 +175,26 @@ void WiiConfigPane::LoadGUIValues()
m_sd_card_checkbox->SetValue(SConfig::GetInstance().m_WiiSDCard);
m_connect_keyboard_checkbox->SetValue(SConfig::GetInstance().m_WiiKeyboard);
PopulateUSBPassthroughListbox();
m_bt_sensor_bar_pos->SetSelection(SConfig::GetInstance().m_sensor_bar_position);
m_bt_sensor_bar_sens->SetValue(SConfig::GetInstance().m_sensor_bar_sensitivity);
m_bt_speaker_volume->SetValue(SConfig::GetInstance().m_speaker_volume);
m_bt_wiimote_motor->SetValue(SConfig::GetInstance().m_wiimote_motor);
}
void WiiConfigPane::PopulateUSBPassthroughListbox()
{
m_usb_passthrough_devices_listbox->Freeze();
m_usb_passthrough_devices_listbox->Clear();
for (const auto& device : SConfig::GetInstance().m_usb_passthrough_devices)
{
m_usb_passthrough_devices_listbox->Append(USBUtils::GetDeviceName(device),
new USBPassthroughDeviceEntry(device));
}
m_usb_passthrough_devices_listbox->Thaw();
}
void WiiConfigPane::BindEvents()
{
m_screensaver_checkbox->Bind(wxEVT_CHECKBOX, &WiiConfigPane::OnScreenSaverCheckBoxChanged, this);
@ -186,6 +224,38 @@ void WiiConfigPane::BindEvents()
m_bt_wiimote_motor->Bind(wxEVT_CHECKBOX, &WiiConfigPane::OnWiimoteMotorChanged, this);
m_bt_wiimote_motor->Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreNotRunning);
m_usb_passthrough_add_device_btn->Bind(wxEVT_BUTTON, &WiiConfigPane::OnUSBWhitelistAddButton,
this);
m_usb_passthrough_rem_device_btn->Bind(wxEVT_BUTTON, &WiiConfigPane::OnUSBWhitelistRemoveButton,
this);
m_usb_passthrough_rem_device_btn->Bind(wxEVT_UPDATE_UI,
&WiiConfigPane::OnUSBWhitelistRemoveButtonUpdate, this);
}
void WiiConfigPane::OnUSBWhitelistAddButton(wxCommandEvent&)
{
AddUSBDeviceDiag add_dialog{this};
// Reload the USB device whitelist
if (add_dialog.ShowModal() == wxID_OK)
PopulateUSBPassthroughListbox();
}
void WiiConfigPane::OnUSBWhitelistRemoveButton(wxCommandEvent&)
{
const int index = m_usb_passthrough_devices_listbox->GetSelection();
if (index == wxNOT_FOUND)
return;
auto* const entry = static_cast<const USBPassthroughDeviceEntry*>(
m_usb_passthrough_devices_listbox->GetClientObject(index));
SConfig::GetInstance().m_usb_passthrough_devices.erase({entry->m_vid, entry->m_pid});
m_usb_passthrough_devices_listbox->Delete(index);
}
void WiiConfigPane::OnUSBWhitelistRemoveButtonUpdate(wxUpdateUIEvent& event)
{
event.Enable(m_usb_passthrough_devices_listbox->GetSelection() != wxNOT_FOUND);
}
void WiiConfigPane::OnScreenSaverCheckBoxChanged(wxCommandEvent& event)

View File

@ -6,11 +6,12 @@
#include <wx/arrstr.h>
#include <wx/panel.h>
#include "Common/CommonTypes.h"
class DolphinSlider;
class wxButton;
class wxCheckBox;
class wxChoice;
class wxListBox;
class wxSlider;
class WiiConfigPane final : public wxPanel
@ -23,6 +24,8 @@ private:
void LoadGUIValues();
void BindEvents();
void PopulateUSBPassthroughListbox();
void OnScreenSaverCheckBoxChanged(wxCommandEvent&);
void OnPAL60CheckBoxChanged(wxCommandEvent&);
void OnSDCardCheckBoxChanged(wxCommandEvent&);
@ -30,6 +33,10 @@ private:
void OnSystemLanguageChoiceChanged(wxCommandEvent&);
void OnAspectRatioChoiceChanged(wxCommandEvent&);
void OnUSBWhitelistAddButton(wxCommandEvent&);
void OnUSBWhitelistRemoveButton(wxCommandEvent&);
void OnUSBWhitelistRemoveButtonUpdate(wxUpdateUIEvent&);
void OnSensorBarPosChanged(wxCommandEvent&);
void OnSensorBarSensChanged(wxCommandEvent&);
void OnSpeakerVolumeChanged(wxCommandEvent&);
@ -46,6 +53,10 @@ private:
wxChoice* m_system_language_choice;
wxChoice* m_aspect_ratio_choice;
wxListBox* m_usb_passthrough_devices_listbox;
wxButton* m_usb_passthrough_add_device_btn;
wxButton* m_usb_passthrough_rem_device_btn;
wxChoice* m_bt_sensor_bar_pos;
DolphinSlider* m_bt_sensor_bar_sens;
DolphinSlider* m_bt_speaker_volume;

View File

@ -62,6 +62,7 @@
<ClCompile Include="Cheats\CheatsWindow.cpp" />
<ClCompile Include="Cheats\CreateCodeDialog.cpp" />
<ClCompile Include="Cheats\GeckoCodeDiag.cpp" />
<ClCompile Include="Config\AddUSBDeviceDiag.cpp" />
<ClCompile Include="Config\AdvancedConfigPane.cpp" />
<ClCompile Include="Config\AudioConfigPane.cpp" />
<ClCompile Include="Config\ConfigMain.cpp" />
@ -139,6 +140,7 @@
<ItemGroup>
<ClInclude Include="Cheats\ActionReplayCodesPanel.h" />
<ClInclude Include="Cheats\ARCodeAddEdit.h" />
<ClInclude Include="Config\AddUSBDeviceDiag.h" />
<ClInclude Include="Config\AdvancedConfigPane.h" />
<ClInclude Include="Config\AudioConfigPane.h" />
<ClInclude Include="Config\GameCubeConfigPane.h" />

View File

@ -224,6 +224,9 @@
<ClCompile Include="Config\PathConfigPane.cpp">
<Filter>GUI\Config</Filter>
</ClCompile>
<ClCompile Include="Config\AddUSBDeviceDiag.cpp">
<Filter>GUI\Config</Filter>
</ClCompile>
<ClCompile Include="Config\AdvancedConfigPane.cpp">
<Filter>GUI\Config</Filter>
</ClCompile>
@ -443,6 +446,9 @@
<ClInclude Include="Config\PathConfigPane.h">
<Filter>GUI\Config</Filter>
</ClInclude>
<ClCompile Include="Config\AddUSBDeviceDiag.h">
<Filter>GUI\Config</Filter>
</ClCompile>
<ClInclude Include="Config\AdvancedConfigPane.h">
<Filter>GUI\Config</Filter>
</ClInclude>