feat(radio,cpn): Updates for new joystick system (#3400)

* Reduce RAM usage for advanced joystick system on radio:
- Don't allocate memory blocks unless joystick mode is being used.
Support multiple radio joystick configurations in Companion:
- Save configured joystick settings by joystick name in Companion settings.
- Save last joystick name used in each profile.
- Reload joystick settings by name when profile is changed.

* Only show configuration for used axes and buttons in Companion.
Send actual number of configured joystick buttons from radio in USB packet.

* Fix issue where USB joystick not recognised if no buttons configured.

* Fix compiler warnings.

* Remove debugging.

* Fix crash in Companion.

* Change channel 8 to type 'dial', workaround for Linux mapping issue.

---------

Co-authored-by: Phil Mitchell <phil.a.mitchell@gmail.com>
This commit is contained in:
philmoz
2023-04-21 14:27:41 +10:00
committed by GitHub
co-authored by Phil Mitchell
parent 62a40f1c47
commit e1fe7fce89
10 changed files with 537 additions and 294 deletions
+9 -6
View File
@@ -97,12 +97,13 @@ void AppPreferencesDialog::accept()
if (ui->joystickChkB ->isChecked()) {
g.jsSupport(ui->joystickChkB ->isChecked());
// Don't overwrite selected joystick if not connected. Avoid surprising the user.
if (ui->joystickCB->isEnabled())
g.jsCtrl(ui->joystickCB ->currentIndex());
if (ui->joystickCB->isEnabled()) {
profile.jsName(ui->joystickCB->currentText());
g.loadNamedJS();
}
}
else {
g.jsSupport(false);
g.jsCtrl(0);
}
// Updates tab
@@ -287,7 +288,8 @@ void AppPreferencesDialog::initSettings()
}
ui->joystickCB->clear();
ui->joystickCB->insertItems(0, joystickNames);
ui->joystickCB->setCurrentIndex(g.jsCtrl());
int stick = joystick->findCurrent(g.currentProfile().jsName());
ui->joystickCB->setCurrentIndex(stick);
}
else {
ui->joystickCB->clear();
@@ -614,8 +616,9 @@ void AppPreferencesDialog::on_joystickChkB_clicked() {
}
void AppPreferencesDialog::on_joystickcalButton_clicked() {
joystickDialog * jd=new joystickDialog(this, ui->joystickCB->currentIndex());
jd->exec();
g.currentProfile().jsName(ui->joystickCB->currentText());
joystickDialog * jd = new joystickDialog(this);
jd->exec();
}
#endif
+10
View File
@@ -167,3 +167,13 @@ int Joystick::getAxisValue(int axis)
} else
return 0;
}
int Joystick::findCurrent(QString jsName)
{
for (int i = 0; i < joystickNames.size(); i += 1) {
if (joystickNames[i] == jsName) {
return i;
}
}
return 0;
}
+2
View File
@@ -62,6 +62,8 @@ class Joystick : public QObject
}
int getAxisValue(int);
int findCurrent(QString jsName);
private:
QMap<int, Sint16> axes;
QMap<int, Uint8> buttons;
+113 -82
View File
@@ -25,90 +25,29 @@
#include "boards.h"
#include "constants.h"
joystickDialog::joystickDialog(QWidget *parent, int stick) :
joystickDialog::joystickDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::joystickDialog),
step(0),
numAxes(0),
numButtons(0),
started(false)
{
ui->setupUi(this);
int i;
char s[20];
for (i = 0; i < MAX_JS_AXES; i += 1) {
jscal[i][0] = 32767;
jscal[i][1] = 0;
jscal[i][2] = -32767;
}
QGridLayout *grid = findChild<QGridLayout*>("gridLayout");
int row = 0;
int col = 0;
if (grid) {
for (i = 0; i < MAX_JS_AXES; i += 1, row += 1) {
col = (i & 1) * 4;
sprintf(s, "Ch%d", i + 1);
QLabel *l = new QLabel(s);
grid->addWidget(l, row/2, col+0, 1, 1);
QSlider *s = new QSlider(Qt::Horizontal);
s->setMinimum(-32767);
s->setMaximum(32767);
sliders[row] = s;
grid->addWidget(s, row/2, col+1, 1, 1);
QCheckBox *c = new QCheckBox("");
invert[row] = c;
grid->addWidget(c, row/2, col+2, 1, 1);
QComboBox *d = new QComboBox();
populateSourceCombo(d);
sticks[row] = d;
grid->addWidget(d, row/2, col+3, 1, 1);
}
if (row & 1) row += 1;
for (i = 0; i < MAX_JS_BUTTONS; i += 1, row += 1) {
col = (i & 1) * 4;
sprintf(s, "Btn%d", i + 1);
QLabel *l = new QLabel(s);
grid->addWidget(l, row/2, col+0, 1, 1);
QSlider *s = new QSlider(Qt::Horizontal);
s->setMinimum(0);
s->setMaximum(1);
sliders[row] = s;
grid->addWidget(s, row/2, col+1, 1, 1);
QComboBox *d = new QComboBox();
populateButtonCombo(d);
sticks[row] = d;
grid->addWidget(d, row/2, col+3, 1, 1);
}
}
for (int i = 0; i < MAX_JS_AXES; ++i) {
if (g.joystick[i].existsOnDisk()) {
jscal[i][0] = g.joystick[i].stick_min();
jscal[i][1] = g.joystick[i].stick_med();
jscal[i][2] = g.joystick[i].stick_max();
sliders[i]->setMinimum(jscal[i][0]);
sliders[i]->setMaximum(jscal[i][2]);
invert[i]->setChecked(g.joystick[i].stick_inv());
sticks[i]->setCurrentIndex(sticks[i]->findData(g.joystick[i].stick_axe()));
}
}
for (int i = 0; i < MAX_JS_BUTTONS; ++i) {
if (g.jsButton[i].existsOnDisk()) {
sticks[i+MAX_JS_AXES]->setCurrentIndex(sticks[i+MAX_JS_AXES]->findData(g.jsButton[i].button_idx()));
}
jscal[i][2] = -32768;
}
ui->backButton->setEnabled(false);
ui->joystickChkB->setChecked(g.jsSupport() || stick > -1);
ui->joystickChkB->setChecked(g.jsSupport());
if (stick < 0)
stick = g.jsCtrl();
if (loadJoysticks(stick)) {
if (loadJoysticks()) {
joystickSetEnabled(ui->joystickChkB->isChecked());
joystickOpen(ui->joystickCB->currentIndex());
}
@@ -128,6 +67,82 @@ joystickDialog::~joystickDialog()
delete ui;
}
void joystickDialog::loadGrid()
{
int i;
char s[20];
QGridLayout *grid = findChild<QGridLayout*>("gridLayout");
QLayoutItem* item;
while ((item = grid->takeAt(0)) != NULL)
{
delete item->widget();
delete item;
}
memset(sliders, 0, sizeof(sliders));
memset(sticks, 0, sizeof(sliders));
memset(invert, 0, sizeof(sliders));
int row = 0;
int col = 0;
if (grid) {
for (i = 0; i < numAxes; i += 1, row += 1) {
col = (i & 1) * 4;
sprintf(s, "Ch%d", i + 1);
QLabel *l = new QLabel(s);
grid->addWidget(l, row/2, col+0, 1, 1);
QSlider *s = new QSlider(Qt::Horizontal);
s->setMinimum(-32767);
s->setMaximum(32767);
sliders[i] = s;
grid->addWidget(s, row/2, col+1, 1, 1);
QCheckBox *c = new QCheckBox("");
invert[i] = c;
grid->addWidget(c, row/2, col+2, 1, 1);
QComboBox *d = new QComboBox();
populateSourceCombo(d);
sticks[i] = d;
grid->addWidget(d, row/2, col+3, 1, 1);
}
if (row & 1) row += 1;
for (i = 0; i < numButtons; i += 1, row += 1) {
col = (i & 1) * 4;
sprintf(s, "Btn%d", i + 1);
QLabel *l = new QLabel(s);
grid->addWidget(l, row/2, col+0, 1, 1);
QSlider *s = new QSlider(Qt::Horizontal);
s->setMinimum(0);
s->setMaximum(1);
sliders[i+numAxes] = s;
grid->addWidget(s, row/2, col+1, 1, 1);
QComboBox *d = new QComboBox();
populateButtonCombo(d);
sticks[i+numAxes] = d;
grid->addWidget(d, row/2, col+3, 1, 1);
}
}
for (int i = 0; i < numAxes; ++i) {
if (g.joystick[i].existsOnDisk()) {
jscal[i][0] = g.joystick[i].stick_min();
jscal[i][1] = g.joystick[i].stick_med();
jscal[i][2] = g.joystick[i].stick_max();
sliders[i]->setMinimum(jscal[i][0]);
sliders[i]->setMaximum(jscal[i][2]);
invert[i]->setChecked(g.joystick[i].stick_inv());
sticks[i]->setCurrentIndex(sticks[i]->findData(g.joystick[i].stick_axe()));
}
}
for (int i = 0; i < numButtons; ++i) {
if (g.jsButton[i].existsOnDisk()) {
sticks[i+numAxes]->setCurrentIndex(sticks[i+numAxes]->findData(g.jsButton[i].button_idx()));
}
}
}
void joystickDialog::populateSourceCombo(QComboBox * cb)
{
int i;
@@ -194,16 +209,16 @@ void joystickDialog::populateButtonCombo(QComboBox * cb)
for (i = 0; i < ttlTrims; i += 1) {
wname = RawSource(RawSourceType::SOURCE_TYPE_TRIM, i).toString(nullptr, &radioSettings);
if ((i == 0) || (i == 3)) {
cb->addItem(wname + " Left", i + ttlSwitches | JS_BUTTON_3POS_DN);
cb->addItem(wname + " Right", i + ttlSwitches | JS_BUTTON_3POS_UP);
cb->addItem(wname + " Left", (i + ttlSwitches) | JS_BUTTON_3POS_DN);
cb->addItem(wname + " Right", (i + ttlSwitches) | JS_BUTTON_3POS_UP);
} else {
cb->addItem(wname + " Down", i + ttlSwitches | JS_BUTTON_3POS_DN);
cb->addItem(wname + " Up", i + ttlSwitches | JS_BUTTON_3POS_UP);
cb->addItem(wname + " Down", (i + ttlSwitches) | JS_BUTTON_3POS_DN);
cb->addItem(wname + " Up", (i + ttlSwitches) | JS_BUTTON_3POS_UP);
}
}
}
bool joystickDialog::loadJoysticks(int stick)
bool joystickDialog::loadJoysticks()
{
QStringList joystickNames;
bool found = false;
@@ -219,7 +234,8 @@ bool joystickDialog::loadJoysticks(int stick)
joystick->close();
}
ui->joystickCB->insertItems(0, joystickNames);
if (found && stick < joystickNames.size()) {
if (found) {
int stick = joystick->findCurrent(g.currentProfile().jsName());
ui->joystickCB->setCurrentIndex(stick);
}
else if (!found) {
@@ -230,12 +246,16 @@ bool joystickDialog::loadJoysticks(int stick)
void joystickDialog::joystickOpen(int stick)
{
numAxes = 0;
numButtons = 0;
if (stick < 0)
return;
joystick = new Joystick(this, 1, false, 0);
if (joystick && joystick->open(stick)) {
numAxes = std::min(joystick->numAxes, MAX_JS_AXES);
numButtons = std::min(joystick->numButtons, MAX_JS_BUTTONS);
for (int j=0; j<numAxes; j++) {
joystick->sensitivities[j] = 0;
joystick->deadzones[j] = 20;
@@ -244,6 +264,9 @@ void joystickDialog::joystickOpen(int stick)
else {
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Cannot open joystick."));
}
g.currentProfile().jsName(ui->joystickCB->currentText());
g.loadNamedJS();
loadGrid();
}
void joystickDialog::joystickSetEnabled(bool enable)
@@ -256,7 +279,7 @@ void joystickDialog::joystickSetEnabled(bool enable)
void joystickDialog::onjoystickAxisValueChanged(int axis, int value)
{
if (axis >= MAX_JS_AXES)
if (axis >= numAxes)
return;
if (started) {
@@ -274,10 +297,10 @@ void joystickDialog::onjoystickAxisValueChanged(int axis, int value)
void joystickDialog::onjoystickButtonValueChanged(int button, bool state)
{
if (button >= MAX_JS_BUTTONS)
if (button >= numButtons)
return;
sliders[button + MAX_JS_AXES]->setValue(state);
sliders[button + numAxes]->setValue(state);
}
void joystickDialog::loadStep()
@@ -290,6 +313,10 @@ void joystickDialog::loadStep()
break;
case 1:
started = true;
for (int i=0; i < numAxes; i++) {
jscal[i][0] = 0;
jscal[i][2] = 0;
}
ui->howtoLabel->setText(tr("Move sticks and pots in every direction making full movement\nPress Next when finished"));
ui->nextButton->setText(tr("Next"));
ui->backButton->setDisabled(true);
@@ -345,12 +372,12 @@ void joystickDialog::on_cancelButton_clicked()
void joystickDialog::on_okButton_clicked()
{
g.jsSupport(ui->joystickChkB->isChecked());
g.jsCtrl(ui->joystickCB->currentIndex());
g.currentProfile().jsName(ui->joystickCB->currentText());
if (joystick)
joystick->close();
if (!g.jsSupport() || g.jsCtrl() < 0) {
if (!g.jsSupport()) {
this->accept();
return;
}
@@ -362,7 +389,9 @@ void joystickDialog::on_okButton_clicked()
return;
}
for (int i = 0; i < MAX_JS_AXES; ++i) {
g.clearJSData();
for (int i = 0; i < numAxes; ++i) {
auto stick = sticks[i]->currentData().toInt();
if (stick < 0) {
g.joystick[i].stick_axe(-1);
@@ -373,20 +402,22 @@ void joystickDialog::on_okButton_clicked()
g.joystick[i].stick_med(jscal[i][1]);
g.joystick[i].stick_min(jscal[i][0]);
g.joystick[i].stick_inv(invert[i]->isChecked() );
qDebug() << "joystick mapping " << sticks[i]->objectName() << "stick:" << i << "axe:" << stick;
qDebug() << "joystick mapping " << sticks[i]->currentText() << "stick:" << i << "axe:" << stick << jscal[i][0] << jscal[i][1] << jscal[i][2];
}
}
for (int i = 0; i < MAX_JS_BUTTONS; ++i) {
auto btn = sticks[i+MAX_JS_AXES]->currentData().toInt();
for (int i = 0; i < numButtons; ++i) {
auto btn = sticks[i+numAxes]->currentData().toInt();
if (btn < 0) {
g.jsButton[i].button_idx(-1);
}
else {
g.jsButton[i].button_idx(btn);
qDebug() << "joystick button mapping " << sticks[i+MAX_JS_AXES]->objectName() << "stick:" << i << "idx:" << btn;
qDebug() << "joystick button mapping " << sticks[i+numAxes]->currentText() << "button:" << i << "idx:" << btn;
}
}
g.saveNamedJS();
this->accept();
}
+5 -2
View File
@@ -46,7 +46,7 @@ class joystickDialog : public QDialog
Q_OBJECT
public:
explicit joystickDialog(QWidget *parent = 0, int stick=-1);
explicit joystickDialog(QWidget *parent = 0);
~joystickDialog();
Joystick *joystick;
@@ -58,12 +58,15 @@ class joystickDialog : public QDialog
QSlider * sliders[MAX_JS_AXES + MAX_JS_BUTTONS];
int step;
int numAxes;
int numButtons;
bool started;
void loadGrid();
private slots:
void populateSourceCombo(QComboBox * cb);
void populateButtonCombo(QComboBox * cb);
bool loadJoysticks(int stick = -1);
bool loadJoysticks();
void joystickOpen(int stick);
void joystickSetEnabled(bool enable);
void onjoystickAxisValueChanged(int axis, int value);
+6 -7
View File
@@ -670,13 +670,15 @@ void SimulatorWidget::setupJoysticks()
#ifdef JOYSTICKS
bool joysticksEnabled = false;
if (g.jsSupport() && g.jsCtrl() > -1) {
if (g.jsSupport()) {
if (!joystick)
joystick = new Joystick(this, SDL_JOYSTICK_DEFAULT_EVENT_TIMEOUT, false, SDL_JOYSTICK_DEFAULT_AUTOREPEAT_DELAY);
else
joystick->close();
if (joystick && joystick->open(g.jsCtrl())) {
int stick = joystick->findCurrent(g.currentProfile().jsName());
if (joystick && joystick->open(stick)) {
int numAxes = std::min(joystick->numAxes, MAX_JS_AXES);
for (int j=0; j<numAxes; j++) {
joystick->sensitivities[j] = 0;
@@ -860,8 +862,8 @@ void SimulatorWidget::onjoystickAxisValueChanged(int axis, int value)
{
#ifdef JOYSTICKS
static const int ttlSticks = 4;
static const int ttlKnobs = Boards::getCapability(m_board, Board::Pots);
static const int ttlFaders = Boards::getCapability(m_board, Board::Sliders);
const int ttlKnobs = Boards::getCapability(m_board, Board::Pots);
const int ttlFaders = Boards::getCapability(m_board, Board::Sliders);
static const int valueRange = 1024;
if (!joystick || axis >= MAX_JS_AXES)
@@ -916,9 +918,6 @@ void SimulatorWidget::onjoystickButtonValueChanged(int button, bool state)
int btn = g.jsButton[button].button_idx();
if (g.jsButton[button].button_inv())
state = !state;
int swtch = btn & JS_BUTTON_SWITCH_MASK;
if (swtch < ttlSwitches) {
+128 -1
View File
@@ -266,6 +266,36 @@ bool JButtonData::existsOnDisk()
return (m_settings.value(settingsPath() % button_idx_key(), -1).toInt() > -1);
}
NamedJStickData::NamedJStickData() : CompStoreObj(), index(-1)
{
CompStoreObj::addObjectMapping(propertyGroup(), this);
}
bool NamedJStickData::existsOnDisk()
{
return (m_settings.value(settingsPath() % stick_axe_key(), -1).toInt() > -1);
}
NamedJButtonData::NamedJButtonData() : CompStoreObj(), index(-1)
{
CompStoreObj::addObjectMapping(propertyGroup(), this);
}
bool NamedJButtonData::existsOnDisk()
{
return (m_settings.value(settingsPath() % button_idx_key(), -1).toInt() > -1);
}
NamedJSData::NamedJSData() : CompStoreObj(), index(-1)
{
CompStoreObj::addObjectMapping(propertyGroup(), this);
}
bool NamedJSData::existsOnDisk()
{
return (m_settings.value(settingsPath() % jsName(), -1).toInt() > -1);
}
// ** Profile class********************
@@ -411,6 +441,13 @@ AppData::AppData() :
joystick[i].setIndex(i);
for (int i = 0; i < MAX_JS_BUTTONS; i++)
jsButton[i].setIndex(i);
for (int i = 0; i < MAX_NAMED_JOYSTICKS; i++) {
namedJS[i].setIndex(i);
for (int a = 0; a < MAX_JS_AXES; a += 1)
namedJS[i].joystick[a].setIndex(a, i);
for (int b = 0; b < MAX_JS_BUTTONS; b += 1)
namedJS[i].jsButton[b].setIndex(b, i);
}
// Configure the updates
for (int i = 0; i < MAX_COMPONENTS; i++) {
@@ -421,6 +458,74 @@ AppData::AppData() :
}
}
void AppData::saveNamedJS(int i)
{
namedJS[i].jsName(currentProfile().jsName());
for (int a = 0; a < MAX_JS_AXES; a += 1) {
namedJS[i].joystick[a].stick_axe(joystick[a].stick_axe());
namedJS[i].joystick[a].stick_max(joystick[a].stick_max());
namedJS[i].joystick[a].stick_med(joystick[a].stick_med());
namedJS[i].joystick[a].stick_min(joystick[a].stick_min());
namedJS[i].joystick[a].stick_min(joystick[a].stick_min());
}
for (int b = 0; b < MAX_JS_BUTTONS; b += 1) {
namedJS[i].jsButton[b].button_idx(jsButton[b].button_idx());
}
namedJS[i].jsLastUsed(time(NULL));
}
void AppData::saveNamedJS()
{
for (int i = 0; i < MAX_NAMED_JOYSTICKS; i += 1) {
if (namedJS[i].jsName() == currentProfile().jsName()) {
saveNamedJS(i);
return;
}
}
for (int i = 0; i < MAX_NAMED_JOYSTICKS; i += 1) {
if (namedJS[i].jsName() == "") {
saveNamedJS(i);
return;
}
}
unsigned int oldestTime = namedJS[0].jsLastUsed();
int oldestN = 0;
for (int i = 1; i < MAX_NAMED_JOYSTICKS; i += 1) {
if (namedJS[i].jsLastUsed() < oldestTime) {
oldestTime = namedJS[i].jsLastUsed();
oldestN = i;
}
}
saveNamedJS(oldestN);
}
void AppData::loadNamedJS(int i)
{
for (int a = 0; a < MAX_JS_AXES; a += 1) {
joystick[a].stick_axe(namedJS[i].joystick[a].stick_axe());
joystick[a].stick_max(namedJS[i].joystick[a].stick_max());
joystick[a].stick_med(namedJS[i].joystick[a].stick_med());
joystick[a].stick_min(namedJS[i].joystick[a].stick_min());
joystick[a].stick_min(namedJS[i].joystick[a].stick_min());
}
for (int b = 0; b < MAX_JS_BUTTONS; b += 1) {
jsButton[b].button_idx(namedJS[i].jsButton[b].button_idx());
}
namedJS[i].jsLastUsed(time(NULL));
}
void AppData::loadNamedJS()
{
for (int i = 0; i < MAX_NAMED_JOYSTICKS; i += 1) {
if (namedJS[i].jsName() == currentProfile().jsName()) {
loadNamedJS(i);
return;
}
}
}
static QString fmtHex(quint32 num)
{
return QString::number(num, 16).toUpper();
@@ -452,7 +557,14 @@ void AppData::initAll()
joystick[i].init();
for (int i = 0; i < MAX_JS_BUTTONS; i++)
jsButton[i].init();
// Initialize the updatess
for (int i = 0; i < MAX_NAMED_JOYSTICKS; i++) {
namedJS[i].init();
for (int a = 0; a < MAX_JS_AXES; a += 1)
namedJS[i].joystick[a].init();
for (int b = 0; b < MAX_JS_BUTTONS; b += 1)
namedJS[i].jsButton[b].init();
}
// Initialize the updates
for (int i = 0; i < MAX_COMPONENTS; i++) {
component[i].init();
for (int j = 0; j < MAX_COMPONENT_ASSETS; j++) {
@@ -471,6 +583,13 @@ void AppData::resetAllSettings()
joystick[i].resetAll();
for (int i = 0; i < MAX_JS_BUTTONS; i++)
jsButton[i].resetAll();
for (int i = 0; i < MAX_NAMED_JOYSTICKS; i++) {
namedJS[i].resetAll();
for (int a = 0; a < MAX_JS_AXES; a += 1)
namedJS[i].joystick[a].resetAll();
for (int b = 0; b < MAX_JS_BUTTONS; b += 1)
namedJS[i].jsButton[b].resetAll();
}
for (int i = 0; i < MAX_COMPONENTS; i++) {
component[i].resetAll();
for (int j = 0; j < MAX_COMPONENT_ASSETS; j++) {
@@ -489,6 +608,13 @@ void AppData::storeAllSettings()
joystick[i].storeAll();
for (int i = 0; i < MAX_JS_BUTTONS; i++)
jsButton[i].storeAll();
for (int i = 0; i < MAX_NAMED_JOYSTICKS; i++) {
namedJS[i].storeAll();
for (int a = 0; a < MAX_JS_AXES; a += 1)
namedJS[i].joystick[a].storeAll();
for (int b = 0; b < MAX_JS_BUTTONS; b += 1)
namedJS[i].jsButton[b].storeAll();
}
for (int i = 0; i < MAX_COMPONENTS; i++) {
component[i].storeAll();
for (int j = 0; j < MAX_COMPONENT_ASSETS; j++)
@@ -506,6 +632,7 @@ void AppData::sessionId(int index)
if (index < 0 || index >= MAX_PROFILES || index == m_sessionId)
return;
m_sessionId = index;
loadNamedJS();
emit sessionIdChanged(index);
emit currentProfileChanged();
}
+105 -2
View File
@@ -63,6 +63,7 @@
#define MAX_JS_BUTTONS 32
#define MAX_COMPONENTS 10
#define MAX_COMPONENT_ASSETS 5
#define MAX_NAMED_JOYSTICKS 10
// It important that these function names are consistent everywhere.
#define PROP_FSIG_INIT_IMPL _init()
@@ -331,12 +332,22 @@ class JStickData: public CompStoreObj
public slots:
bool existsOnDisk();
public:
void clear() {
stick_axe(-1);
stick_med(-32768);
stick_max(32767);
stick_med(0);
stick_inv(0);
}
protected:
explicit JStickData();
void setIndex(int idx) { index = idx; }
inline QString propertyGroup() const override { return QStringLiteral("JsCalibration"); }
inline QString settingsPath() const override { return QString("%1/%2/").arg(propertyGroup()).arg(index); }
friend class AppData;
friend class NamedJSData;
private:
PROPERTY(int, stick_axe, -1)
@@ -348,22 +359,100 @@ class JStickData: public CompStoreObj
int index;
};
//! \brief JButtonData class stores properties related to each joystick button (button number).
class JButtonData: public CompStoreObj
{
Q_OBJECT
public slots:
bool existsOnDisk();
public:
void clear() {
button_idx(-1);
}
protected:
explicit JButtonData();
void setIndex(int idx) { index = idx; }
inline QString propertyGroup() const override { return QStringLiteral("JsButton"); }
inline QString settingsPath() const override { return QString("%1/%2/").arg(propertyGroup()).arg(index); }
friend class AppData;
friend class NamedJSData;
private:
PROPERTY(int, button_idx, -1)
PROPERTY(int, button_inv, 0)
int index;
};
//! \brief NamedJStickData class stores properties related to each joystick axis (calibration/assignment/direction).
class NamedJStickData: public CompStoreObj
{
Q_OBJECT
public slots:
bool existsOnDisk();
protected:
explicit NamedJStickData();
void setIndex(int idx, int nmIdx) { index = idx; namedIdx = nmIdx; }
inline QString propertyGroup() const override { return QStringLiteral("NamedJSData/%1").arg(namedIdx); }
inline QString settingsPath() const override { return QString("%1/JsCalibration/%2/").arg(propertyGroup()).arg(index); }
friend class AppData;
friend class NamedJSData;
private:
PROPERTY(int, stick_axe, -1)
PROPERTY(int, stick_min, -32768)
PROPERTY(int, stick_med, 0)
PROPERTY(int, stick_max, 32767)
PROPERTY(int, stick_inv, 0)
int namedIdx;
int index;
};
//! \brief NamedJButtonData class stores properties related to each joystick button (button number).
class NamedJButtonData: public CompStoreObj
{
Q_OBJECT
public slots:
bool existsOnDisk();
protected:
explicit NamedJButtonData();
void setIndex(int idx, int nmIdx) { index = idx; namedIdx = nmIdx; }
inline QString propertyGroup() const override { return QStringLiteral("NamedJSData/%1").arg(namedIdx); }
inline QString settingsPath() const override { return QString("%1/JsButton/%2/").arg(propertyGroup()).arg(index); }
friend class AppData;
friend class NamedJSData;
private:
PROPERTY(int, button_idx, -1)
int namedIdx;
int index;
};
class NamedJSData: public CompStoreObj
{
Q_OBJECT
public slots:
bool existsOnDisk();
protected:
explicit NamedJSData();
void setIndex(int idx) { index = idx; }
inline QString propertyGroup() const override { return QStringLiteral("NamedJSData"); }
inline QString settingsPath() const override { return QString("%1/%2/").arg(propertyGroup()).arg(index); }
friend class AppData;
public:
NamedJStickData joystick[MAX_JS_AXES];
NamedJButtonData jsButton[MAX_JS_BUTTONS];
private:
PROPERTYSTRD(jsName, "")
PROPERTY(unsigned int, jsLastUsed, 0)
int index;
};
@@ -432,6 +521,8 @@ class Profile: public CompStoreObj
PROPERTY4(int, txCurrentCalibration, "currentCalib", 0)
PROPERTY4(int, txVoltageCalibration, "VbatCalib", 0)
PROPERTYSTRD(jsName, "")
int index;
static const QStringList fwVarsList() //! for resetFwVariables()... TODO: make this go away
@@ -615,9 +706,19 @@ class AppData: public CompStoreObj
Profile profile[MAX_PROFILES];
JStickData joystick[MAX_JS_AXES];
JButtonData jsButton[MAX_JS_BUTTONS];
NamedJSData namedJS[MAX_NAMED_JOYSTICKS];
FwRevision fwRev;
ComponentData component[MAX_COMPONENTS];
void clearJSData() {
for (int i = 0; i < MAX_JS_AXES; i += 1)
joystick[i].clear();
for (int i = 0; i < MAX_JS_BUTTONS; i += 1)
jsButton[i].clear();
}
void saveNamedJS();
void loadNamedJS();
signals:
void currentProfileChanged();
@@ -625,6 +726,9 @@ class AppData: public CompStoreObj
inline QString propertyGroup() const override { return QStringLiteral("General"); }
inline QString settingsPath() const override { return QString(); }
void saveNamedJS(int i);
void loadNamedJS(int i);
private:
PROPERTY_META(int, sessionId, 0) // currently active radio profile ID, NOT saved to persistent storage -- Initialize before profileId!
@@ -679,7 +783,6 @@ class AppData: public CompStoreObj
PROPERTY4(int, embedSplashes, "embedded_splashes", 0)
PROPERTY4(int, fwServerFails, "fwserver", 0)
PROPERTY4(int, iconSize, "icon_size", 2)
PROPERTY4(int, jsCtrl, "js_ctrl", 0)
PROPERTY4(int, historySize, "history_size", 10)
PROPERTY (int, generalEditTab, 0)
PROPERTY (int, theme, 1)