From 6fd0d4e76310794a5b5a19d93bfcd3f890eb0ea0 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sun, 26 Mar 2023 16:08:53 +0100 Subject: [PATCH] various other fixes and stability improvements --- controllersetup.cpp | 178 ++++++++++++++++++++++---------------------- controllersetup.h | 4 + usbcontroller.cpp | 100 +++++++++++++------------ usbcontroller.h | 3 +- wfmain.cpp | 9 ++- 5 files changed, 153 insertions(+), 141 deletions(-) diff --git a/controllersetup.cpp b/controllersetup.cpp index 99ff73f..76d0fdb 100644 --- a/controllersetup.cpp +++ b/controllersetup.cpp @@ -22,7 +22,7 @@ controllerSetup::~controllerSetup() void controllerSetup::hideEvent(QHideEvent *event) { - qDebug(logUsbControl()) << "Controller window hiding"; + qDebug(logUsbControl()) << "Controller window hideEvent()"; updateDialog->hide(); } @@ -63,6 +63,12 @@ void controllerSetup::init() udLayout->addWidget(buttonLatch,3,1); udLayout->setAlignment(buttonLatch,Qt::AlignRight); + buttonIcon = new QPushButton("Icon"); + udLayout->addWidget(buttonIcon,4,0); + iconLabel = new QLabel(""); + udLayout->addWidget(iconLabel,4,1); + udLayout->setAlignment(iconLabel,Qt::AlignCenter); + udLayout->setSizeConstraint(QLayout::SetFixedSize); updateDialog->hide(); @@ -71,6 +77,7 @@ void controllerSetup::init() connect(onEvent, SIGNAL(currentIndexChanged(int)), this, SLOT(onEventIndexChanged(int))); connect(knobEvent, SIGNAL(currentIndexChanged(int)), this, SLOT(knobEventIndexChanged(int))); connect(buttonColor, SIGNAL(clicked()), this, SLOT(buttonColorClicked())); + connect(buttonIcon, SIGNAL(clicked()), this, SLOT(buttonIconClicked())); connect(buttonLatch, SIGNAL(stateChanged(int)), this, SLOT(latchStateChanged(int))); } @@ -81,87 +88,90 @@ void controllerSetup::mousePressed(controllerScene* scene, QPoint p) // Receive mouse event from the scene qDebug() << "Looking for knob or button at Point x=" << p.x() << " y=" << p.y(); - bool found = false; QPoint gp = this->mapToGlobal(p); - for (auto b = buttons->begin(); b != buttons->end(); b++) + // Did the user click on a button? + auto b = std::find_if(buttons->begin(), buttons->end(), [p, this](BUTTON& b) + { return (b.parent != Q_NULLPTR && b.pos.contains(p) && b.page == b.parent->currentPage && ui->tabWidget->currentWidget()->objectName() == b.path ); }); + + if (b != buttons->end()) { - if (b->parent != Q_NULLPTR && b->parent != Q_NULLPTR && b->pos.contains(p) && b->page == b->parent->currentPage && ui->tabWidget->currentWidget()->objectName() == b->path) - { - found = true; - currentButton = b; - qDebug() << "Button" << currentButton->num << "On Event" << currentButton->onCommand->text << "Off Event" << currentButton->offCommand->text; + currentButton = b; + currentKnob = Q_NULLPTR; + qDebug() << "Button" << currentButton->num << "On Event" << currentButton->onCommand->text << "Off Event" << currentButton->offCommand->text; - updateDialog->setWindowTitle(QString("Update button %0").arg(b->num)); + updateDialog->setWindowTitle(QString("Update button %0").arg(b->num)); - onEvent->blockSignals(true); - onEvent->setCurrentIndex(onEvent->findData(currentButton->onCommand->index)); - onEvent->show(); - onLabel->show(); - onEvent->blockSignals(false); + onEvent->blockSignals(true); + onEvent->setCurrentIndex(onEvent->findData(currentButton->onCommand->index)); + onEvent->show(); + onLabel->show(); + onEvent->blockSignals(false); - offEvent->blockSignals(true); - offEvent->setCurrentIndex(offEvent->findData(currentButton->offCommand->index)); - offEvent->show(); - offLabel->show(); - offEvent->blockSignals(false); - knobEvent->hide(); - knobLabel->hide(); + offEvent->blockSignals(true); + offEvent->setCurrentIndex(offEvent->findData(currentButton->offCommand->index)); + offEvent->show(); + offLabel->show(); + offEvent->blockSignals(false); + knobEvent->hide(); + knobLabel->hide(); - buttonLatch->blockSignals(true); - buttonLatch->setChecked(currentButton->toggle); - buttonLatch->blockSignals(false); + buttonLatch->blockSignals(true); + buttonLatch->setChecked(currentButton->toggle); + buttonLatch->blockSignals(false); - buttonLatch->show(); - buttonColor->show(); - //currentKnob = Q_NULLPTR; - break; - } - } + buttonLatch->show(); + buttonColor->show(); + buttonIcon->show(); + iconLabel->show(); - if (!found) { - for (auto k = knobs->begin(); k != knobs->end(); k++) - { - if (k->parent != Q_NULLPTR && k->pos.contains(p) && k->page == k->parent->currentPage && ui->tabWidget->currentWidget()->objectName() == k->path) - { - found = true; - currentKnob = k; - qDebug() << "Knob" << currentKnob->num << "Event" << currentKnob->command->text; - - updateDialog->setWindowTitle(QString("Update knob %0").arg(k->num)); - - knobEvent->blockSignals(true); - knobEvent->setCurrentIndex(knobEvent->findData(currentKnob->command->index)); - knobEvent->show(); - knobLabel->show(); - knobEvent->blockSignals(false); - onEvent->hide(); - offEvent->hide(); - onLabel->hide(); - offLabel->hide(); - buttonLatch->hide(); - buttonColor->hide(); - //currentButton = Q_NULLPTR; - break; - } - } - } - - if(found) - { updateDialog->show(); updateDialog->move(gp); updateDialog->adjustSize(); updateDialog->raise(); - } - else - { - updateDialog->hide(); - // currentButton = Q_NULLPTR; - //currentKnob = Q_NULLPTR; + } else { + // It wasn't a button so was it a knob? + auto k = std::find_if(knobs->begin(), knobs->end(), [p, this](KNOB& k) + { return (k.parent != Q_NULLPTR && k.pos.contains(p) && k.page == k.parent->currentPage && ui->tabWidget->currentWidget()->objectName() == k.path ); }); + + if (k != knobs->end()) + { + currentKnob = k; + currentButton = Q_NULLPTR; + qDebug() << "Knob" << currentKnob->num << "Event" << currentKnob->command->text; + + updateDialog->setWindowTitle(QString("Update knob %0").arg(k->num)); + + knobEvent->blockSignals(true); + knobEvent->setCurrentIndex(knobEvent->findData(currentKnob->command->index)); + knobEvent->show(); + knobLabel->show(); + knobEvent->blockSignals(false); + onEvent->hide(); + offEvent->hide(); + onLabel->hide(); + offLabel->hide(); + buttonLatch->hide(); + buttonColor->hide(); + buttonIcon->hide(); + iconLabel->hide(); + + updateDialog->show(); + updateDialog->move(gp); + updateDialog->adjustSize(); + updateDialog->raise(); + } + else + { + // It wasn't either so hide the updateDialog(); + updateDialog->hide(); + currentButton = Q_NULLPTR; + currentKnob = Q_NULLPTR; + } } } + void controllerSetup::onEventIndexChanged(int index) { Q_UNUSED(index); // If command is changed, delete current command and deep copy the new command @@ -230,6 +240,19 @@ void controllerSetup::buttonColorClicked() } } +void controllerSetup::buttonIconClicked() +{ + QString file = QFileDialog::getOpenFileName(this,"Select Icon Filename",".","Images (*png *.jpg)"); + if (!file.isEmpty()) { + QFileInfo info = QFileInfo(file); + iconLabel->setText(info.fileName()); + QImage image; + image.load(file); + currentButton->icon = image.scaled(currentButton->parent->type.iconSize,currentButton->parent->type.iconSize); + emit sendRequest(currentButton->parent,usbFeatureType::featureButton,currentButton->num,currentButton->onCommand->text,¤tButton->icon, Q_NULLPTR); + } +} + void controllerSetup::latchStateChanged(int state) { if (currentButton != Q_NULLPTR) { @@ -458,9 +481,6 @@ void controllerSetup::newDevice(USBDEVICE* dev, CONTROLLER* cntrl, QVectorsetAlignment(Qt::AlignCenter); layout->addWidget(helpText); - - - onEvent->blockSignals(true); offEvent->blockSignals(true); knobEvent->blockSignals(true); @@ -469,20 +489,6 @@ void controllerSetup::newDevice(USBDEVICE* dev, CONTROLLER* cntrl, QVectorclear(); knobEvent->clear(); - /* - onEvent->setMaxVisibleItems(5); - offEvent->setMaxVisibleItems(5); - knobEvent->setMaxVisibleItems(5); - - onEvent->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - offEvent->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - knobEvent->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - - onEvent->setStyleSheet("combobox-popup: 0;"); - offEvent->setStyleSheet("combobox-popup: 0;"); - knobEvent->setStyleSheet("combobox-popup: 0;"); - */ - for (COMMAND& c : *commands) { if (c.cmdType == commandButton || c.text == "None") { onEvent->addItem(c.text, c.index); @@ -498,10 +504,6 @@ void controllerSetup::newDevice(USBDEVICE* dev, CONTROLLER* cntrl, QVectorblockSignals(false); knobEvent->blockSignals(false); - onEvent->hide(); - offEvent->hide(); - knobEvent->hide(); - locker.unlock(); pageChanged(dev,1); locker.relock(); @@ -587,6 +589,8 @@ void controllerSetup::pageChanged(USBDEVICE* dev, int val) if (val < 1) val = dev->pages; + updateDialog->hide(); // Hide the dialog if the page changes. + QMutexLocker locker(mutex); int lastPage = dev->currentPage; diff --git a/controllersetup.h b/controllersetup.h index 31b08f2..5993a61 100644 --- a/controllersetup.h +++ b/controllersetup.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -83,6 +84,7 @@ public slots: void speedChanged(USBDEVICE* dev, int index); void colorPicker(USBDEVICE* dev); void buttonColorClicked(); + void buttonIconClicked(); void latchStateChanged(int state); void timeoutChanged(USBDEVICE* dev, int val); @@ -118,6 +120,8 @@ private: QLabel* knobLabel; QPushButton* buttonColor; QCheckBox *buttonLatch; + QPushButton* buttonIcon; + QLabel* iconLabel; QString deviceName; QMutex* mutex; diff --git a/usbcontroller.cpp b/usbcontroller.cpp index 082ed15..c313306 100644 --- a/usbcontroller.cpp +++ b/usbcontroller.cpp @@ -328,9 +328,9 @@ void usbController::run() if (dev.handle) { qInfo(logUsbControl()) << QString("Connected to device: %0 from %1 S/N %2").arg(dev.product).arg(dev.manufacturer).arg(dev.serial); + hid_set_nonblocking(dev.handle, 1); devicesConnected++; dev.connected=true; - hid_set_nonblocking(dev.handle, 1); locker.unlock(); // Unlock the mutex so other devices can use it @@ -656,7 +656,6 @@ void usbController::runTimer() } } - qInfo(logUsbControl()) << "DATA:" << data; } // Step through all buttons and emit ones that have been pressed. @@ -668,7 +667,7 @@ void usbController::runTimer() for (unsigned char i = 0; i begin(), buttonList->end(), [dev, i](const BUTTON& b) - { return (b.path == dev.path && b.num == i); }); + { return (b.path == dev.path && b.page == dev.currentPage && b.num == i); }); if (but != buttonList->end()) { if ((!but->isOn) && ((tempButtons >> i & 1) && !(dev.buttons >> i & 1))) { @@ -755,7 +754,7 @@ void usbController::runTimer() for (unsigned char i = 0; i < dev.knobValues.size(); i++) { auto kb = std::find_if(knobList->begin(), knobList->end(), [dev, i](const KNOB& k) - { return (k.command && k.path == dev.path && k.num == i && dev.knobValues[i] != dev.knobPrevious[i]); }); + { return (k.command && k.path == dev.path && k.page == dev.currentPage && k.num == i && dev.knobValues[i] != dev.knobPrevious[i]); }); if (kb != knobList->end()) { // sendCommand mustn't be deleted so we ensure it stays in-scope by declaring it private. @@ -865,14 +864,15 @@ void usbController::ledControl(bool on, unsigned char num) void usbController::sendRequest(USBDEVICE *dev, usbFeatureType feature, quint8 val, QString text, QImage* img, QColor* color) { - if (!dev->connected) + if (dev == Q_NULLPTR || !dev->connected || dev->disabled || !dev->handle) return; + QMutexLocker locker(mutex); QByteArray data(64, 0x0); QByteArray data2; int res=0; - + bool sdv1=false; switch (dev->type.model) { case QuickKeys: @@ -975,36 +975,8 @@ void usbController::sendRequest(USBDEVICE *dev, usbFeatureType feature, quint8 v case StreamDeckMini: case StreamDeckMiniV2: data.resize(17); - switch (feature) - { - case usbFeatureType::featureFirmware: - data[0] = 0x04; - hid_get_feature_report(dev->handle,(unsigned char*)data.data(),(size_t)data.size()); - qInfo(logUsbControl()) << QString("%0: Firmware = %1").arg(dev->product).arg(QString::fromLatin1(data.mid(5,8))); - break; - case usbFeatureType::featureSerial: - data[0] = 0x03; - hid_get_feature_report(dev->handle,(unsigned char*)data.data(),(size_t)data.size()); - qInfo(logUsbControl()) << QString("%0: Firmware = %1").arg(dev->product).arg(QString::fromLatin1(data.mid(2,12))); - break; - case usbFeatureType::featureReset: - data[0] = (qint8)0x0b; - data[1] = (qint8)0x63; - hid_send_feature_report(dev->handle, (const unsigned char*)data.constData(), data.size()); - case usbFeatureType::featureBrightness: - data[0] = (qint8)0x05; - data[1] = (qint8)0x55; - data[2] = (qint8)0xaa; - data[3] = (qint8)0xd1; - data[4] = (qint8)0x01; - data[5] = val*25; - hid_send_feature_report(dev->handle, (const unsigned char*)data.constData(), data.size()); - break; - default: - break; - } - break; - + sdv1=true; + // Allow pass through. // Below are StreamDeck Generation 2 h/w case StreamDeckOriginalMK2: case StreamDeckOriginalV2: @@ -1016,18 +988,31 @@ void usbController::sendRequest(USBDEVICE *dev, usbFeatureType feature, quint8 v switch (feature) { case usbFeatureType::featureFirmware: - data[0] = 0x05; + if (sdv1) { + data[0] = 0x04; + } else { + data[0] = 0x05; + } hid_get_feature_report(dev->handle,(unsigned char*)data.data(),(size_t)data.size()); qInfo(logUsbControl()) << QString("%0: Firmware = %1").arg(dev->product).arg(QString::fromLatin1(data.mid(2,12))); break; case usbFeatureType::featureSerial: - data[0] = 0x06; + if (sdv1) { + data[0] = 0x03; + } else { + data[0] = 0x06; + } hid_get_feature_report(dev->handle,(unsigned char*)data.data(),(size_t)data.size()); qInfo(logUsbControl()) << QString("%0: Serial Number = %1").arg(dev->product).arg(QString::fromLatin1(data.mid(5,8))); break; case usbFeatureType::featureReset: - data[0] = (qint8)0x03; - data[1] = (qint8)0x02; + if (sdv1) { + data[0] = (qint8)0x0b; + data[1] = (qint8)0x63; + } else { + data[0] = (qint8)0x03; + data[1] = (qint8)0x02; + } hid_send_feature_report(dev->handle, (const unsigned char*)data.constData(), data.size()); break; case usbFeatureType::featureResetKeys: @@ -1037,9 +1022,18 @@ void usbController::sendRequest(USBDEVICE *dev, usbFeatureType feature, quint8 v res=hid_write(dev->handle, (const unsigned char*)data.constData(), data.size()); break; case usbFeatureType::featureBrightness: - data[0] = (qint8)0x03; - data[1] = (qint8)0x08; - data[2] = val*25; // Stream Deck brightness is in % + if (sdv1) { + data[0] = (qint8)0x05; + data[1] = (qint8)0x55; + data[2] = (qint8)0xaa; + data[3] = (qint8)0xd1; + data[4] = (qint8)0x01; + data[5] = val*25; + } else { + data[0] = (qint8)0x03; + data[1] = (qint8)0x08; + data[2] = val*25; // Stream Deck brightness is in % + } res = hid_send_feature_report(dev->handle, (const unsigned char*)data.constData(), data.size()); break; case usbFeatureType::featureColor: @@ -1068,6 +1062,7 @@ void usbController::sendRequest(USBDEVICE *dev, usbFeatureType feature, quint8 v { if (img != Q_NULLPTR) { + *img = img->scaled(800,100); data2.clear(); QBuffer buffer(&data2); img->save(&buffer, "JPG"); @@ -1106,14 +1101,21 @@ void usbController::sendRequest(USBDEVICE *dev, usbFeatureType feature, quint8 v case usbFeatureType::featureButton: { if (val < 8) { QImage butImage(dev->type.iconSize,dev->type.iconSize, QImage::Format_RGB888); - QPainter butPaint(&butImage); - butPaint.setFont(QFont("times",16)); - if (color == Q_NULLPTR) - butPaint.fillRect(butImage.rect(), (*controllers)[dev->path].color); + if (img != Q_NULLPTR) + { + butImage = *img; + } else - butPaint.fillRect(butImage.rect(), *color); + { + QPainter butPaint(&butImage); + butPaint.setFont(QFont("times",16)); + if (color == Q_NULLPTR) + butPaint.fillRect(butImage.rect(), (*controllers)[dev->path].color); + else + butPaint.fillRect(butImage.rect(), *color); - butPaint.drawText(butImage.rect(),Qt::AlignCenter | Qt::AlignVCenter, text); + butPaint.drawText(butImage.rect(),Qt::AlignCenter | Qt::AlignVCenter, text); + } QBuffer butBuffer(&data2); butImage.save(&butBuffer, "JPG"); //butImage.save("test.jpg"); diff --git a/usbcontroller.h b/usbcontroller.h index 20c3335..e61e8b1 100644 --- a/usbcontroller.h +++ b/usbcontroller.h @@ -161,6 +161,7 @@ struct BUTTON { QString off; QString path; QColor background = Qt::white; + QImage icon; bool toggle = false; bool isOn = false; }; @@ -198,7 +199,7 @@ struct CONTROLLER { QColor color=Qt::white; int pages=1; cmds lcd=cmdNone; - USBDEVICE* dev; + USBDEVICE* dev = Q_NULLPTR; }; diff --git a/wfmain.cpp b/wfmain.cpp index 0cc067d..a745f5e 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -5258,18 +5258,19 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e wf->xAxis->setRange(0, spectWidth-1); wf->replot(); + // Send to USB Controllers if requested usbMap::const_iterator i = usbControllers.constBegin(); while (i != usbControllers.constEnd()) { - if (i.value().dev != Q_NULLPTR && i.value().lcd == cmdLCDWaterfall ) + if (i.value().dev != Q_NULLPTR && i.value().dev->connected && i.value().lcd == cmdLCDWaterfall ) { - lcdImage = wf->toPixmap(800,100,1.0).toImage(); + lcdImage = plot->toPixmap().toImage(); emit sendControllerRequest(i.value().dev, usbFeatureType::featureLCD, 0, "", &lcdImage); } - else if (i.value().dev != Q_NULLPTR && i.value().lcd == cmdLCDSpectrum) + else if (i.value().dev != Q_NULLPTR && i.value().dev->connected && i.value().lcd == cmdLCDSpectrum) { - lcdImage = plot->toPixmap(800,100,1.0).toImage(); + lcdImage = plot->toPixmap().toImage(); emit sendControllerRequest(i.value().dev, usbFeatureType::featureLCD, 0, "", &lcdImage); } ++i;