From 6dcf66b06408bda54da9d5e9c20e1e48dff22999 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 22 Dec 2018 17:48:42 +0100 Subject: [PATCH] Qt/Input: add disconnected label to the devicenames --- rpcs3/Emu/Io/PadHandler.h | 2 +- rpcs3/ds4_pad_handler.cpp | 10 ++-- rpcs3/ds4_pad_handler.h | 2 +- rpcs3/evdev_joystick_handler.cpp | 25 ++++----- rpcs3/evdev_joystick_handler.h | 2 +- rpcs3/mm_joystick_handler.cpp | 29 +++++----- rpcs3/mm_joystick_handler.h | 2 +- rpcs3/rpcs3qt/pad_settings_dialog.cpp | 76 ++++++++++++++++++++++----- rpcs3/rpcs3qt/pad_settings_dialog.h | 12 +++++ rpcs3/xinput_pad_handler.cpp | 10 ++-- rpcs3/xinput_pad_handler.h | 2 +- 11 files changed, 119 insertions(+), 53 deletions(-) diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index a2b29e6403..115e1dcf37 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -448,7 +448,7 @@ public: PadHandlerBase(pad_handler type = pad_handler::null); virtual ~PadHandlerBase() = default; //Sets window to config the controller(optional) - virtual void GetNextButtonPress(const std::string& /*padId*/, const std::function& /*callback*/, const std::function& /*fail_callback*/, bool /*get_blacklist*/ = false, std::vector /*buttons*/ = {}) {}; + virtual void GetNextButtonPress(const std::string& /*padId*/, const std::function& /*callback*/, const std::function& /*fail_callback*/, bool /*get_blacklist*/ = false, std::vector /*buttons*/ = {}) {}; virtual void TestVibration(const std::string& /*padId*/, u32 /*largeMotor*/, u32 /*smallMotor*/) {}; //Return list of devices for that handler virtual std::vector ListDevices() = 0; diff --git a/rpcs3/ds4_pad_handler.cpp b/rpcs3/ds4_pad_handler.cpp index 6ba2948d34..b1f3cc18fb 100644 --- a/rpcs3/ds4_pad_handler.cpp +++ b/rpcs3/ds4_pad_handler.cpp @@ -151,14 +151,14 @@ void ds4_pad_handler::init_config(pad_config* cfg, const std::string& name) cfg->from_default(); } -void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist, std::vector buttons) +void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist, std::vector buttons) { if (get_blacklist) blacklist.clear(); std::shared_ptr device = GetDevice(padId, true); if (device == nullptr || device->hidDevice == nullptr) - return fail_callback(); + return fail_callback(padId); // Now that we have found a device, get its status DS4DataStatus status = GetRawData(device); @@ -168,7 +168,7 @@ void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::fu // this also can mean disconnected, either way deal with it on next loop and reconnect hid_close(device->hidDevice); device->hidDevice = nullptr; - return fail_callback(); + return fail_callback(padId); } // return if nothing new has happened. ignore this to get the current state for blacklist @@ -216,9 +216,9 @@ void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::fu int preview_values[6] = { data[L2], data[R2], data[LSXPos] - data[LSXNeg], data[LSYPos] - data[LSYNeg], data[RSXPos] - data[RSXNeg], data[RSYPos] - data[RSYNeg] }; if (pressed_button.first > 0) - return callback(pressed_button.first, pressed_button.second, preview_values); + return callback(pressed_button.first, pressed_button.second, padId, preview_values); else - return callback(0, "", preview_values); + return callback(0, "", padId, preview_values); } void ds4_pad_handler::TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) diff --git a/rpcs3/ds4_pad_handler.h b/rpcs3/ds4_pad_handler.h index e738b13222..d70f12b9a0 100644 --- a/rpcs3/ds4_pad_handler.h +++ b/rpcs3/ds4_pad_handler.h @@ -142,7 +142,7 @@ public: std::vector ListDevices() override; bool bindPadToDevice(std::shared_ptr pad, const std::string& device) override; void ThreadProc() override; - void GetNextButtonPress(const std::string& padId, const std::function& buttonCallback, const std::function& fail_callback, bool get_blacklist = false, std::vector buttons = {}) override; + void GetNextButtonPress(const std::string& padId, const std::function& buttonCallback, const std::function& fail_callback, bool get_blacklist = false, std::vector buttons = {}) override; void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override; void init_config(pad_config* cfg, const std::string& name) override; diff --git a/rpcs3/evdev_joystick_handler.cpp b/rpcs3/evdev_joystick_handler.cpp index 5df7301126..f5a32941ae 100644 --- a/rpcs3/evdev_joystick_handler.cpp +++ b/rpcs3/evdev_joystick_handler.cpp @@ -257,7 +257,7 @@ evdev_joystick_handler::EvdevDevice* evdev_joystick_handler::get_device(const st return &dev; } -void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist, std::vector buttons) +void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist, std::vector buttons) { if (get_blacklist) blacklist.clear(); @@ -265,7 +265,7 @@ void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const // Get our evdev device EvdevDevice* device = get_device(padId); if (device == nullptr || device->device == nullptr) - return fail_callback(); + return fail_callback(padId); libevdev* dev = device->device; // Try to query the latest event from the joystick. @@ -381,20 +381,21 @@ void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const return it != data.end() && dir == it->second.second ? it->second.first : 0; }; - int preview_values[6] = + int preview_values[6] = { 0, 0, 0, 0, 0, 0 }; + if (buttons.size() == 10) { - find_value(buttons[0]), // Left Trigger - find_value(buttons[1]), // Right Trigger - find_value(buttons[3]) - find_value(buttons[2]), // Left Stick X - find_value(buttons[5]) - find_value(buttons[4]), // Left Stick Y - find_value(buttons[7]) - find_value(buttons[6]), // Right Stick X - find_value(buttons[9]) - find_value(buttons[8]), // Right Stick Y - }; + preview_values[0] = find_value(buttons[0]); // Left Trigger + preview_values[1] = find_value(buttons[1]); // Right Trigger + preview_values[2] = find_value(buttons[3]) - find_value(buttons[2]); // Left Stick X + preview_values[3] = find_value(buttons[5]) - find_value(buttons[4]); // Left Stick Y + preview_values[4] = find_value(buttons[7]) - find_value(buttons[6]); // Right Stick X + preview_values[5] = find_value(buttons[9]) - find_value(buttons[8]); // Right Stick Y + } if (pressed_button.first > 0) - return callback(pressed_button.first, pressed_button.second, preview_values); + return callback(pressed_button.first, pressed_button.second, padId, preview_values); else - return callback(0, "", preview_values); + return callback(0, "", padId, preview_values); } // https://github.com/dolphin-emu/dolphin/blob/master/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp diff --git a/rpcs3/evdev_joystick_handler.h b/rpcs3/evdev_joystick_handler.h index 9518ded6ef..ac706ce1df 100644 --- a/rpcs3/evdev_joystick_handler.h +++ b/rpcs3/evdev_joystick_handler.h @@ -338,7 +338,7 @@ public: bool bindPadToDevice(std::shared_ptr pad, const std::string& device) override; void ThreadProc() override; void Close(); - void GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist = false, std::vector buttons = {}) override; + void GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist = false, std::vector buttons = {}) override; void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override; private: diff --git a/rpcs3/mm_joystick_handler.cpp b/rpcs3/mm_joystick_handler.cpp index 66293670e7..e64b548c42 100644 --- a/rpcs3/mm_joystick_handler.cpp +++ b/rpcs3/mm_joystick_handler.cpp @@ -283,13 +283,13 @@ void mm_joystick_handler::ThreadProc() } } -void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist, std::vector buttons) +void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist, std::vector buttons) { if (get_blacklist) blacklist.clear(); if (!Init()) - return fail_callback(); + return fail_callback(padId); static std::string cur_pad = ""; static int id = -1; @@ -301,7 +301,7 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std if (id < 0) { LOG_ERROR(GENERAL, "MMJOY GetNextButtonPress for device [%s] failed with id = %d", padId, id); - return fail_callback(); + return fail_callback(padId); } } @@ -316,7 +316,7 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std switch (status) { case JOYERR_UNPLUGGED: - return fail_callback(); + return fail_callback(padId); case JOYERR_NOERROR: auto data = GetButtonValues(js_info, js_caps); @@ -403,20 +403,21 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std return static_cast(key); }; - int preview_values[6] = + int preview_values[6] = { 0, 0, 0, 0, 0, 0 }; + if (buttons.size() == 10) { - data[find_key(buttons[0])], - data[find_key(buttons[1])], - data[find_key(buttons[3])] - data[find_key(buttons[2])], - data[find_key(buttons[5])] - data[find_key(buttons[4])], - data[find_key(buttons[7])] - data[find_key(buttons[6])], - data[find_key(buttons[9])] - data[find_key(buttons[8])], - }; + preview_values[0] = data[find_key(buttons[0])]; + preview_values[1] = data[find_key(buttons[1])]; + preview_values[2] = data[find_key(buttons[3])] - data[find_key(buttons[2])]; + preview_values[3] = data[find_key(buttons[5])] - data[find_key(buttons[4])]; + preview_values[4] = data[find_key(buttons[7])] - data[find_key(buttons[6])]; + preview_values[5] = data[find_key(buttons[9])] - data[find_key(buttons[8])]; + } if (pressed_button.first > 0) - return callback(pressed_button.first, pressed_button.second, preview_values); + return callback(pressed_button.first, pressed_button.second, padId, preview_values); else - return callback(0, "", preview_values); + return callback(0, "", padId, preview_values); break; } diff --git a/rpcs3/mm_joystick_handler.h b/rpcs3/mm_joystick_handler.h index 616abb962f..82548ba197 100644 --- a/rpcs3/mm_joystick_handler.h +++ b/rpcs3/mm_joystick_handler.h @@ -108,7 +108,7 @@ public: std::vector ListDevices() override; bool bindPadToDevice(std::shared_ptr pad, const std::string& device) override; void ThreadProc() override; - void GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist = false, std::vector buttons = {}) override; + void GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist = false, std::vector buttons = {}) override; void init_config(pad_config* cfg, const std::string& name) override; private: diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.cpp b/rpcs3/rpcs3qt/pad_settings_dialog.cpp index 3f3baaf050..a175b088f2 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/pad_settings_dialog.cpp @@ -90,13 +90,14 @@ pad_settings_dialog::pad_settings_dialog(QWidget *parent) connect(ui->chooseHandler, &QComboBox::currentTextChanged, this, &pad_settings_dialog::ChangeInputType); // Combobox: Devices - connect(ui->chooseDevice, &QComboBox::currentTextChanged, [this](const QString& dev) + connect(ui->chooseDevice, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { - if (dev.isEmpty()) + if (index < 0) { return; } - m_device_name = sstr(dev); + const pad_info info = ui->chooseDevice->itemData(index).value(); + m_device_name = info.name; if (!g_cfg_input.player[m_tabs->currentIndex()]->device.from_string(m_device_name)) { // Something went wrong @@ -316,8 +317,10 @@ void pad_settings_dialog::InitButtons() }); // Enable Button Remapping - const auto& callback = [=](u16 val, std::string name, int preview_values[6]) + const auto& callback = [=](u16 val, std::string name, std::string pad_name, int preview_values[6]) { + SwitchPadInfo(pad_name, true); + if (!m_enable_buttons && !m_timer.isActive()) { SwitchButtons(true); @@ -354,8 +357,9 @@ void pad_settings_dialog::InitButtons() }; // Disable Button Remapping - const auto& fail_callback = [this]() + const auto& fail_callback = [this](const std::string& pad_name) { + SwitchPadInfo(pad_name, false); if (m_enable_buttons) { SwitchButtons(false); @@ -374,6 +378,35 @@ void pad_settings_dialog::InitButtons() }; m_handler->GetNextButtonPress(m_device_name, callback, fail_callback, false, buttons); }); + + // Use timer to refresh pad connection status + connect(&m_timer_pad_refresh, &QTimer::timeout, [this]() + { + for (int i = 0; i < ui->chooseDevice->count(); i++) + { + if (!ui->chooseDevice->itemData(i).canConvert()) + { + LOG_FATAL(GENERAL, "Cannot convert itemData for index %d and itemText %s", i, sstr(ui->chooseDevice->itemText(i))); + continue; + } + const pad_info info = ui->chooseDevice->itemData(i).value(); + m_handler->GetNextButtonPress(info.name, [=](u16 val, std::string name, std::string pad_name, int preview_values[6]) { SwitchPadInfo(pad_name, true); }, [=](std::string pad_name) { SwitchPadInfo(pad_name, false); }, false); + } + }); +} + +void pad_settings_dialog::SwitchPadInfo(const std::string& pad_name, bool is_connected) +{ + for (int i = 0; i < ui->chooseDevice->count(); i++) + { + const pad_info info = ui->chooseDevice->itemData(i).value(); + if (info.name == pad_name && info.is_connected != is_connected) + { + ui->chooseDevice->setItemData(i, QVariant::fromValue(pad_info{ pad_name, is_connected })); + ui->chooseDevice->setItemText(i, is_connected ? qstr(pad_name) : (qstr(pad_name) + Disconnected_suffix)); + break; + } + } } void pad_settings_dialog::ReloadButtons() @@ -785,7 +818,7 @@ void pad_settings_dialog::ChangeInputType() // Get this player's current handler and it's currently available devices m_handler = GetHandler(g_cfg_input.player[player]->handler); - const std::vector list_devices = m_handler->ListDevices(); + const auto device_list = m_handler->ListDevices(); // Refill the device combobox with currently available devices switch (m_handler->m_type) @@ -797,7 +830,8 @@ void pad_settings_dialog::ChangeInputType() const QString name_string = qstr(m_handler->name_string()); for (int i = 1; i <= m_handler->max_devices(); i++) // Controllers 1-n in GUI { - ui->chooseDevice->addItem(name_string + QString::number(i), i); + const QString device_name = name_string + QString::number(i); + ui->chooseDevice->addItem(device_name, QVariant::fromValue(pad_info{ sstr(device_name), false })); } force_enable = true; break; @@ -805,21 +839,34 @@ void pad_settings_dialog::ChangeInputType() #endif default: { - for (int i = 0; i < list_devices.size(); i++) + for (int i = 0; i < device_list.size(); i++) { - ui->chooseDevice->addItem(qstr(list_devices[i]), i); + ui->chooseDevice->addItem(qstr(device_list[i]), QVariant::fromValue(pad_info{ device_list[i], true })); } break; } } // Handle empty device list - bool config_enabled = force_enable || (m_handler->m_type != pad_handler::null && list_devices.size() > 0); + bool config_enabled = force_enable || (m_handler->m_type != pad_handler::null && ui->chooseDevice->count() > 0); ui->chooseDevice->setEnabled(config_enabled); if (config_enabled) { - ui->chooseDevice->setCurrentText(qstr(device)); + for (int i = 0; i < ui->chooseDevice->count(); i++) + { + if (!ui->chooseDevice->itemData(i).canConvert()) + { + LOG_FATAL(GENERAL, "Cannot convert itemData for index %d and itemText %s", i, sstr(ui->chooseDevice->itemText(i))); + continue; + } + const pad_info info = ui->chooseDevice->itemData(i).value(); + m_handler->GetNextButtonPress(info.name, [=](u16 val, std::string name, std::string pad_name, int preview_values[6]) { SwitchPadInfo(pad_name, true); }, [=](std::string pad_name) { SwitchPadInfo(pad_name, false); }, false); + if (info.name == device) + { + ui->chooseDevice->setCurrentIndex(i); + } + } QString profile_dir = qstr(PadHandlerBase::get_config_dir(m_handler->m_type)); QStringList profiles = gui::utils::get_dir_entries(QDir(profile_dir), QStringList() << "*.yml"); @@ -852,7 +899,7 @@ void pad_settings_dialog::ChangeInputType() } // enable configuration and profile list if possible - SwitchButtons(false || config_enabled && m_handler->m_type == pad_handler::keyboard); + SwitchButtons(config_enabled && m_handler->m_type == pad_handler::keyboard); ui->b_addProfile->setEnabled(config_enabled); ui->chooseProfile->setEnabled(config_enabled); } @@ -873,6 +920,10 @@ void pad_settings_dialog::ChangeProfile() { m_timer_input.stop(); } + if (m_timer_pad_refresh.isActive()) + { + m_timer_pad_refresh.stop(); + } // Change handler const std::string cfg_name = PadHandlerBase::get_config_dir(m_handler->m_type) + m_profile + ".yml"; @@ -917,6 +968,7 @@ void pad_settings_dialog::ChangeProfile() if (ui->chooseDevice->isEnabled() && ui->chooseDevice->currentIndex() >= 0) { m_timer_input.start(1); + m_timer_pad_refresh.start(1000); } } diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.h b/rpcs3/rpcs3qt/pad_settings_dialog.h index f15d758729..99484a681e 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.h +++ b/rpcs3/rpcs3qt/pad_settings_dialog.h @@ -14,6 +14,14 @@ namespace Ui class pad_settings_dialog; } +struct pad_info +{ + std::string name; + bool is_connected; +}; + +Q_DECLARE_METATYPE(pad_info); + class pad_settings_dialog : public QDialog { Q_OBJECT @@ -73,6 +81,8 @@ class pad_settings_dialog : public QDialog QString text; }; + const QString Disconnected_suffix = tr(" (disconnected)"); + public: explicit pad_settings_dialog(QWidget *parent = nullptr); ~pad_settings_dialog(); @@ -121,6 +131,7 @@ private: pad_config m_handler_cfg; std::string m_device_name; std::string m_profile; + QTimer m_timer_pad_refresh; // Remap Timer const int MAX_SECONDS = 5; @@ -135,6 +146,7 @@ private: /** Update all the Button Labels with current button mapping */ void UpdateLabel(bool is_reset = false); + void SwitchPadInfo(const std::string& name, bool is_connected); /** Enable/Disable Buttons while trying to remap an other */ void SwitchButtons(bool is_enabled); diff --git a/rpcs3/xinput_pad_handler.cpp b/rpcs3/xinput_pad_handler.cpp index d1f8c145b5..14f40942ce 100644 --- a/rpcs3/xinput_pad_handler.cpp +++ b/rpcs3/xinput_pad_handler.cpp @@ -74,14 +74,14 @@ void xinput_pad_handler::init_config(pad_config* cfg, const std::string& name) cfg->from_default(); } -void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist, std::vector buttons) +void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist, std::vector buttons) { if (get_blacklist) blacklist.clear(); int device_number = GetDeviceNumber(padId); if (device_number < 0) - return fail_callback(); + return fail_callback(padId); DWORD dwResult; XINPUT_STATE state; @@ -90,7 +90,7 @@ void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std: // Simply get the state of the controller from XInput. dwResult = (*xinputGetState)(static_cast(device_number), &state); if (dwResult != ERROR_SUCCESS) - return fail_callback(); + return fail_callback(padId); // Check for each button in our list if its corresponding (maybe remapped) button or axis was pressed. // Return the new value if the button was pressed (aka. its value was bigger than 0 or the defined threshold) @@ -131,9 +131,9 @@ void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std: int preview_values[6] = { data[LT], data[RT], data[LSXPos] - data[LSXNeg], data[LSYPos] - data[LSYNeg], data[RSXPos] - data[RSXNeg], data[RSYPos] - data[RSYNeg] }; if (pressed_button.first > 0) - return callback(pressed_button.first, pressed_button.second, preview_values); + return callback(pressed_button.first, pressed_button.second, padId, preview_values); else - return callback(0, "", preview_values); + return callback(0, "", padId, preview_values); } void xinput_pad_handler::TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) diff --git a/rpcs3/xinput_pad_handler.h b/rpcs3/xinput_pad_handler.h index 57a7a044a2..b6c3c34ff6 100644 --- a/rpcs3/xinput_pad_handler.h +++ b/rpcs3/xinput_pad_handler.h @@ -107,7 +107,7 @@ public: std::vector ListDevices() override; bool bindPadToDevice(std::shared_ptr pad, const std::string& device) override; void ThreadProc() override; - void GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist = false, std::vector buttons = {}) override; + void GetNextButtonPress(const std::string& padId, const std::function& callback, const std::function& fail_callback, bool get_blacklist = false, std::vector buttons = {}) override; void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override; void init_config(pad_config* cfg, const std::string& name) override;