diff --git a/plugins/feature/gs232controller/CMakeLists.txt b/plugins/feature/gs232controller/CMakeLists.txt index 2d3a24fd4..9961e3e43 100644 --- a/plugins/feature/gs232controller/CMakeLists.txt +++ b/plugins/feature/gs232controller/CMakeLists.txt @@ -55,8 +55,15 @@ if(NOT SERVER_MODE) if(Qt${QT_DEFAULT_MAJOR_VERSION}Gamepad_FOUND) add_compile_definitions(QT_GAMEPAD_FOUND) set(TARGET_LIB ${TARGET_LIB} Qt::Gamepad) - set(gs232controller_SOURCES ${gs232controller_SOURCES} gamepadinputcontroller.cpp) - set(gs232controller_HEADERS ${gs232controller_HEADERS} gamepadinputcontroller.h) + set(gs232controller_SOURCES + ${gs232controller_SOURCES} + gamepadinputcontroller.cpp + gamepadconfigurationdialog.cpp + gamepadconfigurationdialog.ui) + set(gs232controller_HEADERS + ${gs232controller_HEADERS} + gamepadinputcontroller.h + gamepadconfiguration.h) endif() else() diff --git a/plugins/feature/gs232controller/gamepadconfigurationdialog.cpp b/plugins/feature/gs232controller/gamepadconfigurationdialog.cpp new file mode 100644 index 000000000..79abdcb4b --- /dev/null +++ b/plugins/feature/gs232controller/gamepadconfigurationdialog.cpp @@ -0,0 +1,139 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "gamepadconfigurationdialog.h" + +GamepadConfigurationDialog::GamepadConfigurationDialog(QGamepad *gamepad, QWidget* parent) : + QDialog(parent), + ui(new Ui::GamepadConfigurationDialog), + m_gamepad(gamepad) +{ + ui->setupUi(this); + connect(m_gamepad, &QGamepad::axisRightXChanged, this, &GamepadConfigurationDialog::axisRightXChanged); + connect(m_gamepad, &QGamepad::axisRightYChanged, this, &GamepadConfigurationDialog::axisRightYChanged); + connect(m_gamepad, &QGamepad::axisLeftXChanged, this, &GamepadConfigurationDialog::axisLeftXChanged); + connect(m_gamepad, &QGamepad::axisLeftYChanged, this, &GamepadConfigurationDialog::axisLeftYChanged); +} + +GamepadConfigurationDialog::~GamepadConfigurationDialog() +{ + delete ui; +} + +void GamepadConfigurationDialog::accept() +{ + QDialog::accept(); +} + +void GamepadConfigurationDialog::on_config0_clicked() +{ + if (ui->config0->text() == "Configure") + { + ui->config0->setText("Done"); + ui->config1->setEnabled(false); + ui->config2->setEnabled(false); + ui->config3->setEnabled(false); + QGamepadManager::instance()->configureAxis(m_gamepad->deviceId(), QGamepadManager ::AxisRightX); + } + else + { + ui->config0->setText("Configure"); + ui->config1->setEnabled(true); + ui->config2->setEnabled(true); + ui->config3->setEnabled(true); + } +} + +void GamepadConfigurationDialog::on_config1_clicked() +{ + if (ui->config1->text() == "Configure") + { + ui->config1->setText("Done"); + ui->config0->setEnabled(false); + ui->config2->setEnabled(false); + ui->config3->setEnabled(false); + QGamepadManager::instance()->configureAxis(m_gamepad->deviceId(), QGamepadManager ::AxisRightY); + } + else + { + ui->config1->setText("Configure"); + ui->config0->setEnabled(true); + ui->config2->setEnabled(true); + ui->config3->setEnabled(true); + } +} + +void GamepadConfigurationDialog::on_config2_clicked() +{ + if (ui->config2->text() == "Configure") + { + ui->config2->setText("Done"); + ui->config0->setEnabled(false); + ui->config1->setEnabled(false); + ui->config3->setEnabled(false); + QGamepadManager::instance()->configureAxis(m_gamepad->deviceId(), QGamepadManager ::AxisLeftX); + } + else + { + ui->config2->setText("Configure"); + ui->config0->setEnabled(true); + ui->config1->setEnabled(true); + ui->config3->setEnabled(true); + } +} + +void GamepadConfigurationDialog::on_config3_clicked() +{ + if (ui->config3->text() == "Configure") + { + ui->config3->setText("Done"); + ui->config0->setEnabled(false); + ui->config1->setEnabled(false); + ui->config2->setEnabled(false); + QGamepadManager::instance()->configureAxis(m_gamepad->deviceId(), QGamepadManager ::AxisLeftY); + } + else + { + ui->config3->setText("Configure"); + ui->config0->setEnabled(true); + ui->config1->setEnabled(true); + ui->config2->setEnabled(true); + } +} + +void GamepadConfigurationDialog::axisRightXChanged(double value) +{ + ui->value0->setText(QString::number(value)); +} + +void GamepadConfigurationDialog::axisRightYChanged(double value) +{ + ui->value1->setText(QString::number(value)); +} + +void GamepadConfigurationDialog::axisLeftXChanged(double value) +{ + ui->value2->setText(QString::number(value)); +} + +void GamepadConfigurationDialog::axisLeftYChanged(double value) +{ + ui->value3->setText(QString::number(value)); +} diff --git a/plugins/feature/gs232controller/gamepadconfigurationdialog.h b/plugins/feature/gs232controller/gamepadconfigurationdialog.h new file mode 100644 index 000000000..4f0db8551 --- /dev/null +++ b/plugins/feature/gs232controller/gamepadconfigurationdialog.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_GAMEPADCONFIGURATIONDIALOG_H +#define INCLUDE_GAMEPADCONFIGURATIONDIALOG_H + +#include "ui_gamepadconfigurationdialog.h" + +class QGamepad; + +class GamepadConfigurationDialog : public QDialog { + Q_OBJECT + +public: + explicit GamepadConfigurationDialog(QGamepad *gamepad, QWidget* parent = 0); + ~GamepadConfigurationDialog(); + +private slots: + void accept(); + void on_config0_clicked(); + void on_config1_clicked(); + void on_config2_clicked(); + void on_config3_clicked(); + void axisRightXChanged(double value); + void axisRightYChanged(double value); + void axisLeftXChanged(double value); + void axisLeftYChanged(double value); + +private: + Ui::GamepadConfigurationDialog* ui; + QGamepad *m_gamepad; +}; + +#endif // INCLUDE_GAMEPADCONFIGURATIONDIALOG_H + diff --git a/plugins/feature/gs232controller/gamepadconfigurationdialog.ui b/plugins/feature/gs232controller/gamepadconfigurationdialog.ui new file mode 100644 index 000000000..34a83f83c --- /dev/null +++ b/plugins/feature/gs232controller/gamepadconfigurationdialog.ui @@ -0,0 +1,196 @@ + + + GamepadConfigurationDialog + + + + 0 + 0 + 380 + 309 + + + + + Liberation Sans + 9 + + + + Gamepad Configuration + + + + + + + + + 0 + + + + + + + Configure + + + + + + + 0 + + + + + + + Configure + + + + + + + Azimuth Offset Axis + + + + + + + 0 + + + + + + + Configure + + + + + + + Elevation Offset Axis + + + + + + + Target Elevation/Y Axis + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Target Aziumth/X Axis + + + + + + + 0 + + + + + + + + 0 + 80 + + + + To configure a controller axis: + + - press the Configure button, + - move the controller axis, + - then press Done + + + + + + + Configure + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + config0 + config1 + config2 + config3 + + + + + buttonBox + accepted() + GamepadConfigurationDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + GamepadConfigurationDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/feature/gs232controller/gamepadinputcontroller.cpp b/plugins/feature/gs232controller/gamepadinputcontroller.cpp index 7dc8c78d9..3585446e2 100644 --- a/plugins/feature/gs232controller/gamepadinputcontroller.cpp +++ b/plugins/feature/gs232controller/gamepadinputcontroller.cpp @@ -19,6 +19,7 @@ #include #include "gamepadinputcontroller.h" +#include "gamepadconfigurationdialog.h" GamepadInputController::GamepadInputController(int deviceId) : m_gamepad(deviceId), @@ -54,6 +55,28 @@ int GamepadInputController::getNumberOfAxes() const return 4; } +bool GamepadInputController::supportsConfiguration() const +{ + // Should only return true on Linux evdev or Android + return QGamepadManager::instance()->isConfigurationNeeded(m_gamepad.deviceId()); +} + +void GamepadInputController::configure() +{ + disconnect(&m_gamepad, &QGamepad::axisRightXChanged, this, &GamepadInputController::axisRightXChanged); + disconnect(&m_gamepad, &QGamepad::axisRightYChanged, this, &GamepadInputController::axisRightYChanged); + disconnect(&m_gamepad, &QGamepad::axisLeftXChanged, this, &GamepadInputController::axisLeftXChanged); + disconnect(&m_gamepad, &QGamepad::axisLeftYChanged, this, &GamepadInputController::axisLeftYChanged); + + GamepadConfigurationDialog dialog(&m_gamepad); + dialog.exec(); + + connect(&m_gamepad, &QGamepad::axisRightXChanged, this, &GamepadInputController::axisRightXChanged); + connect(&m_gamepad, &QGamepad::axisRightYChanged, this, &GamepadInputController::axisRightYChanged); + connect(&m_gamepad, &QGamepad::axisLeftXChanged, this, &GamepadInputController::axisLeftXChanged); + connect(&m_gamepad, &QGamepad::axisLeftYChanged, this, &GamepadInputController::axisLeftYChanged); +} + void GamepadInputController::axisRightXChanged(double value) { m_rightX = value; diff --git a/plugins/feature/gs232controller/gamepadinputcontroller.h b/plugins/feature/gs232controller/gamepadinputcontroller.h index d881b03d2..996d12f94 100644 --- a/plugins/feature/gs232controller/gamepadinputcontroller.h +++ b/plugins/feature/gs232controller/gamepadinputcontroller.h @@ -29,6 +29,8 @@ public: GamepadInputController(int deviceId); double getAxisValue(int axis) override; int getNumberOfAxes() const override; + bool supportsConfiguration() const override; + void configure() override; static QStringList getAllControllers(); static GamepadInputController* open(const QString& name); diff --git a/plugins/feature/gs232controller/gs232controllergui.cpp b/plugins/feature/gs232controller/gs232controllergui.cpp index 4dd44c30a..63e31bb7f 100644 --- a/plugins/feature/gs232controller/gs232controllergui.cpp +++ b/plugins/feature/gs232controller/gs232controllergui.cpp @@ -304,6 +304,8 @@ void GS232ControllerGUI::updateInputController() ui->inputSensitivityLabel->setEnabled(enabled); ui->inputSensitivity->setEnabled(enabled); ui->inputSensitivityText->setEnabled(enabled); + ui->inputConfigure->setEnabled(enabled); + ui->inputConfigure->setVisible(enabled); } void GS232ControllerGUI::checkInputController() @@ -383,6 +385,13 @@ void GS232ControllerGUI::on_inputSensitivty_valueChanged(int value) applySettings(); } +void GS232ControllerGUI::on_inputConfigure_clicked() +{ + if (m_inputController) { + m_inputController->configure(); + } +} + GS232ControllerGUI::~GS232ControllerGUI() { m_dfmStatusDialog.close(); @@ -949,6 +958,7 @@ void GS232ControllerGUI::makeUIConnections() QObject::connect(ui->coordinates, qOverload(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_coordinates_currentIndexChanged); QObject::connect(ui->inputController, qOverload(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_inputController_currentIndexChanged); QObject::connect(ui->inputSensitivity, qOverload(&QSlider::valueChanged), this, &GS232ControllerGUI::on_inputSensitivty_valueChanged); + QObject::connect(ui->inputConfigure, &QToolButton::clicked, this, &GS232ControllerGUI::on_inputConfigure_clicked); QObject::connect(ui->dfmTrack, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmTrack_clicked); QObject::connect(ui->dfmLubePumps, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmLubePumps_clicked); QObject::connect(ui->dfmBrakes, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmBrakes_clicked); diff --git a/plugins/feature/gs232controller/gs232controllergui.h b/plugins/feature/gs232controller/gs232controllergui.h index 55bf01612..61d5ebf0d 100644 --- a/plugins/feature/gs232controller/gs232controllergui.h +++ b/plugins/feature/gs232controller/gs232controllergui.h @@ -127,6 +127,7 @@ private slots: void updateStatus(); void on_inputController_currentIndexChanged(int index); void on_inputSensitivty_valueChanged(int value); + void on_inputConfigure_clicked(); void updateInputControllerList(); void checkInputController(); }; diff --git a/plugins/feature/gs232controller/gs232controllergui.ui b/plugins/feature/gs232controller/gs232controllergui.ui index 6edfed6f0..9cfd053dc 100644 --- a/plugins/feature/gs232controller/gs232controllergui.ui +++ b/plugins/feature/gs232controller/gs232controllergui.ui @@ -337,18 +337,6 @@ - - - - Gamepad / joystick to use - - - - None - - - - @@ -742,6 +730,32 @@ + + + + + + Gamepad / joystick to use + + + + None + + + + + + + + Configure input + + + C + + + + + diff --git a/plugins/feature/gs232controller/inputcontroller.h b/plugins/feature/gs232controller/inputcontroller.h index d35306c4b..56a0d66a5 100644 --- a/plugins/feature/gs232controller/inputcontroller.h +++ b/plugins/feature/gs232controller/inputcontroller.h @@ -29,6 +29,8 @@ public: // value returned should be current axis position in range [-1,1] virtual double getAxisValue(int axis) = 0; virtual int getNumberOfAxes() const = 0; + virtual bool supportsConfiguration() const { return false; } + virtual void configure() {}; }; diff --git a/plugins/feature/gs232controller/readme.md b/plugins/feature/gs232controller/readme.md index 34770c183..b25d66c88 100644 --- a/plugins/feature/gs232controller/readme.md +++ b/plugins/feature/gs232controller/readme.md @@ -5,7 +5,7 @@ The Rotator Controller feature plugin allows SDRangel to send commands to GS-232 and SPID rotators as well as hamlib's rotctld, via a serial or TCP connection. This allows SDRangel to point antennas mounted on a rotator to a specified azimuth and elevation. -Azimuth and elevation can be set manually by a user in the GUI, via the REST API, via another plugin, such as the Map Feature, the ADS-B Demodulator, or the Star Tracker, or by controller/gamepads (such as an XBox Controller). +Azimuth and elevation can be set manually by a user in the GUI, via the REST API, via another plugin, such as the Map Feature, the ADS-B Demodulator, or the Star Tracker, or by controller/gamepads (such as an XBox Wireless Controller).

Interface

@@ -109,13 +109,16 @@ Equations for translating between these coordinate systems can be found [here](h

22: Input Control

-Specifies a controller/gamepad (such as an XBox Wireless Controller) that can be used to specify target coordinates or azimuth and elevation offset. +Specifies a controller/gamepad that can be used to specify target coordinates or azimuth and elevation offset. -When a controller with 2 sticks (4 axes) such as the XBox Wireless Controller is used, the right stick is used for controlling target coordinates, +When a gamepad with 2 sticks (4 axes) such as the XBox Wireless Controller is used, the right stick is used for controlling target coordinates, while the left stick is for controlling azimuth and elevation offset. If a controller only has 2 axes, target coordinates will be controlled when not tracking (6) and offset will be controlled when tracking. The [Qt Gamepad](https://doc.qt.io/qt-5/qtgamepad-index.html) library is used to implement gamepad support. +On Linux, using Qt Gamepad with the evdev backend, all joysticks & gamepads appear as though they have 4 axes (a limitation of Qt Gamepad). +If using a joystick which only has 2 axes, whether it corresponds to the left or right stick can be configured by pressing the 'C' button. +On Linux, the [xone driver](https://github.com/medusalix/xone) has support for the Xbox Wireless Controller, that isn't supported by the older xpad driver that is included with Ubuntu.

23: Sensitivity