diff --git a/controllersetup.cpp b/controllersetup.cpp index 76d0fdb..5cee26e 100644 --- a/controllersetup.cpp +++ b/controllersetup.cpp @@ -55,13 +55,18 @@ void controllerSetup::init() udLayout->addWidget(knobEvent,2,1); knobLabel->setBuddy(knobEvent); - buttonColor = new QPushButton("Color"); - udLayout->addWidget(buttonColor,3,0); - buttonLatch = new QCheckBox(); buttonLatch->setText("Toggle"); - udLayout->addWidget(buttonLatch,3,1); - udLayout->setAlignment(buttonLatch,Qt::AlignRight); + udLayout->addWidget(buttonLatch,3,0); + + QHBoxLayout* colorLayout = new QHBoxLayout(); + udLayout->addLayout(colorLayout,3,1); + + buttonOnColor = new QPushButton("Color"); + colorLayout->addWidget(buttonOnColor); + + buttonOffColor = new QPushButton("Pressed"); + colorLayout->addWidget(buttonOffColor); buttonIcon = new QPushButton("Icon"); udLayout->addWidget(buttonIcon,4,0); @@ -76,7 +81,8 @@ void controllerSetup::init() connect(offEvent, SIGNAL(currentIndexChanged(int)), this, SLOT(offEventIndexChanged(int))); 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(buttonOnColor, SIGNAL(clicked()), this, SLOT(buttonOnColorClicked())); + connect(buttonOffColor, SIGNAL(clicked()), this, SLOT(buttonOffColorClicked())); connect(buttonIcon, SIGNAL(clicked()), this, SLOT(buttonIconClicked())); connect(buttonLatch, SIGNAL(stateChanged(int)), this, SLOT(latchStateChanged(int))); @@ -121,7 +127,8 @@ void controllerSetup::mousePressed(controllerScene* scene, QPoint p) buttonLatch->blockSignals(false); buttonLatch->show(); - buttonColor->show(); + buttonOnColor->show(); + buttonOffColor->show(); buttonIcon->show(); iconLabel->show(); @@ -152,7 +159,8 @@ void controllerSetup::mousePressed(controllerScene* scene, QPoint p) onLabel->hide(); offLabel->hide(); buttonLatch->hide(); - buttonColor->hide(); + buttonOnColor->hide(); + buttonOffColor->hide(); buttonIcon->hide(); iconLabel->hide(); @@ -184,7 +192,7 @@ void controllerSetup::onEventIndexChanged(int index) { currentButton->onText->setPos(currentButton->pos.center().x() - currentButton->onText->boundingRect().width() / 2, (currentButton->pos.center().y() - currentButton->onText->boundingRect().height() / 2)-6); // Signal that any button programming on the device should be completed. - emit sendRequest(currentButton->parent,usbFeatureType::featureButton,currentButton->num,currentButton->onCommand->text); + emit sendRequest(currentButton->parent,usbFeatureType::featureButton,currentButton->num,currentButton->onCommand->text,Q_NULLPTR,¤tButton->backgroundOn); } } @@ -221,22 +229,32 @@ void controllerSetup::knobEventIndexChanged(int index) { } -void controllerSetup::buttonColorClicked() +void controllerSetup::buttonOnColorClicked() { QColorDialog::ColorDialogOptions options; options.setFlag(QColorDialog::ShowAlphaChannel, false); options.setFlag(QColorDialog::DontUseNativeDialog, false); - QColor selColor = QColorDialog::getColor(initialColor, this, "Select Color", options); + QColor selColor = QColorDialog::getColor(currentButton->backgroundOn, this, "Select Color to use for unpressed button", options); - if(!selColor.isValid()) + if(selColor.isValid() && currentButton != Q_NULLPTR) { - return; - } - - if (currentButton != Q_NULLPTR) { QMutexLocker locker(mutex); - currentButton->background = selColor; - emit sendRequest(currentButton->parent,usbFeatureType::featureButton,currentButton->num,currentButton->onCommand->text,Q_NULLPTR,¤tButton->background); + currentButton->backgroundOn = selColor; + emit sendRequest(currentButton->parent,usbFeatureType::featureButton,currentButton->num,currentButton->onCommand->text,currentButton->icon,¤tButton->backgroundOn); + } +} + +void controllerSetup::buttonOffColorClicked() +{ + QColorDialog::ColorDialogOptions options; + options.setFlag(QColorDialog::ShowAlphaChannel, false); + options.setFlag(QColorDialog::DontUseNativeDialog, false); + QColor selColor = QColorDialog::getColor(currentButton->backgroundOff, this, "Select Color to use for pressed button", options); + + if(selColor.isValid() && currentButton != Q_NULLPTR) + { + QMutexLocker locker(mutex); + currentButton->backgroundOff = selColor; } } @@ -248,8 +266,10 @@ void controllerSetup::buttonIconClicked() 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); + if (currentButton->icon != Q_NULLPTR) + delete currentButton->icon; + currentButton->icon = new QImage(image.scaled(currentButton->parent->type.iconSize,currentButton->parent->type.iconSize)); + emit sendRequest(currentButton->parent,usbFeatureType::featureButton,currentButton->num,currentButton->onCommand->text,currentButton->icon, ¤tButton->backgroundOn); } } @@ -622,7 +642,7 @@ void controllerSetup::pageChanged(USBDEVICE* dev, int val) dev->scene->addItem(b->onText); b->onText->setPos(b->pos.center().x() - b->onText->boundingRect().width() / 2, (b->pos.center().y() - b->onText->boundingRect().height() / 2) - 6); - emit sendRequest(dev,usbFeatureType::featureButton,b->num,b->onCommand->text,Q_NULLPTR,&b->background); + emit sendRequest(dev,usbFeatureType::featureButton,b->num,b->onCommand->text,b->icon,&b->backgroundOn); b->offText = new QGraphicsTextItem(b->offCommand->text); b->offText->setDefaultTextColor(b->textColour); diff --git a/controllersetup.h b/controllersetup.h index 5993a61..eaf865b 100644 --- a/controllersetup.h +++ b/controllersetup.h @@ -83,7 +83,8 @@ public slots: void orientationChanged(USBDEVICE* dev, int index); void speedChanged(USBDEVICE* dev, int index); void colorPicker(USBDEVICE* dev); - void buttonColorClicked(); + void buttonOnColorClicked(); + void buttonOffColorClicked(); void buttonIconClicked(); void latchStateChanged(int state); @@ -118,7 +119,8 @@ private: QLabel* onLabel; QLabel* offLabel; QLabel* knobLabel; - QPushButton* buttonColor; + QPushButton* buttonOnColor; + QPushButton* buttonOffColor; QCheckBox *buttonLatch; QPushButton* buttonIcon; QLabel* iconLabel; diff --git a/packettypes.h b/packettypes.h index b91bcdd..112b6ac 100644 --- a/packettypes.h +++ b/packettypes.h @@ -412,6 +412,19 @@ typedef union streamdeck_image_header { char packet[8]; } *streamdeck_image_header_t; +typedef union streamdeck_v1_image_header { + struct + { + quint8 cmd; + quint8 suffix; + quint16 index; + quint8 isLast; + quint8 button; + quint8 unused[10]; + }; + char packet[16]; +} *streamdeck_v1_image_header_t; + typedef union streamdeck_lcd_header { struct { diff --git a/usbcontroller.cpp b/usbcontroller.cpp index c313306..58f7223 100644 --- a/usbcontroller.cpp +++ b/usbcontroller.cpp @@ -686,7 +686,7 @@ void usbController::runTimer() // Change the button text to reflect the off Button if (but->offCommand->index != 0) { locker.unlock(); - sendRequest(&dev,usbFeatureType::featureButton,i,but->offCommand->text,Q_NULLPTR,&but->background); + sendRequest(&dev,usbFeatureType::featureButton,i,but->offCommand->text,but->icon,&but->backgroundOff); locker.relock(); } but->isOn=true; @@ -706,7 +706,7 @@ void usbController::runTimer() emit button(but->offCommand); } locker.unlock(); - sendRequest(&dev,usbFeatureType::featureButton,i,but->onCommand->text,Q_NULLPTR,&but->background); + sendRequest(&dev,usbFeatureType::featureButton,i,but->onCommand->text,but->icon,&but->backgroundOn); locker.relock(); but->isOn=false; } @@ -723,7 +723,7 @@ void usbController::runTimer() } // Change the button text to reflect the on Button locker.unlock(); - sendRequest(&dev,usbFeatureType::featureButton,i,but->onCommand->text,Q_NULLPTR,&but->background); + sendRequest(&dev,usbFeatureType::featureButton,i,but->onCommand->text,but->icon,&but->backgroundOn); locker.relock(); but->isOn=false; } @@ -757,7 +757,7 @@ void usbController::runTimer() { 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. + // sendCommand mustn't be deleted so we ensure it stays in-scope by declaring it private (we will only ever send one command). sendCommand = *kb->command; if (sendCommand.command != cmdSetFreq) { int tempVal = dev.knobValues[i] * dev.sensitivity; @@ -1044,89 +1044,45 @@ void usbController::sendRequest(USBDEVICE *dev, usbFeatureType feature, quint8 v break; case usbFeatureType::featureOverlay: { - QImage image(800,100, QImage::Format_RGB888); - QPainter paint(&image); - if (val) { - paint.setFont(QFont("times",16)); - paint.fillRect(image.rect(), (*controllers)[dev->path].color); - paint.drawText(image.rect(),Qt::AlignCenter | Qt::AlignVCenter, text); - QTimer::singleShot(val*1000, this, [=]() { sendRequest(dev,usbFeatureType::featureOverlay); }); - } else { - paint.fillRect(image.rect(), (*controllers)[dev->path].color); + if (dev->type.model == usbDeviceType::StreamDeckPlus) + { + QImage image(800,100, QImage::Format_RGB888); + QPainter paint(&image); + if (val) { + paint.setFont(QFont("times",16)); + paint.fillRect(image.rect(), (*controllers)[dev->path].color); + paint.drawText(image.rect(),Qt::AlignCenter | Qt::AlignVCenter, text); + QTimer::singleShot(val*1000, this, [=]() { sendRequest(dev,usbFeatureType::featureOverlay); }); + } else { + paint.fillRect(image.rect(), (*controllers)[dev->path].color); + } + QBuffer buffer(&data2); + image.save(&buffer, "JPG"); } - QBuffer buffer(&data2); - image.save(&buffer, "JPG"); // Fall through } case usbFeatureType::featureLCD: { - if (img != Q_NULLPTR) + if (dev->type.model == usbDeviceType::StreamDeckPlus) { - *img = img->scaled(800,100); - data2.clear(); - QBuffer buffer(&data2); - img->save(&buffer, "JPG"); - } - quint32 rem = data2.size(); - quint16 index = 0; - - streamdeck_lcd_header h; - memset(h.packet, 0x0, sizeof(h)); // We can't be sure it is initialized with 0x00! - h.cmd = 0x02; - h.suffix = 0x0c; - h.x=0; - h.y=0; - h.width=800; - h.height=100; - - while (rem > 0) - { - quint16 length = qMin(rem,dev->type.maxPayload-sizeof(h)); - data.clear(); - h.isLast = (quint8)(rem <= dev->type.maxPayload-sizeof(h) ? 1 : 0); // isLast ? 1 : 0,3 - h.length = length; - h.index = index; - rem -= length; - data.append(QByteArray::fromRawData((const char*)h.packet,sizeof(h))); - data.append(data2.mid(0,length)); - data.resize(dev->type.maxPayload); - memset(data.data()+length+sizeof(h),0x0,data.size()-(length+sizeof(h))); - res=hid_write(dev->handle, (const unsigned char*)data.constData(), data.size()); - //qInfo(logUsbControl()) << "Sending" << (((quint8)data[7] << 8) | ((quint8)data[6] & 0xff)) << "total=" << data.size() << "payload=" << (((quint8)data[5] << 8) | ((quint8)data[4] & 0xff)) << "last" << (quint8)data[3]; - data2.remove(0,length); - index++; - } - break; - } - case usbFeatureType::featureButton: { - if (val < 8) { - QImage butImage(dev->type.iconSize,dev->type.iconSize, QImage::Format_RGB888); if (img != Q_NULLPTR) { - butImage = *img; + QImage image = img->scaled(800,100,Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + data2.clear(); + QBuffer buffer(&data2); + image.save(&buffer, "JPG"); } - else - { - 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); - } - QBuffer butBuffer(&data2); - butImage.save(&butBuffer, "JPG"); - //butImage.save("test.jpg"); quint32 rem = data2.size(); quint16 index = 0; - streamdeck_image_header h; + streamdeck_lcd_header h; memset(h.packet, 0x0, sizeof(h)); // We can't be sure it is initialized with 0x00! h.cmd = 0x02; - h.suffix = 0x07; - h.button = val; + h.suffix = 0x0c; + h.x=0; + h.y=0; + h.width=800; + h.height=100; while (rem > 0) { @@ -1146,6 +1102,91 @@ void usbController::sendRequest(USBDEVICE *dev, usbFeatureType feature, quint8 v index++; } } + break; + } + case usbFeatureType::featureButton: { + // StreamDeckPedal is the only model without oled buttons + // Plus has 12 buttons but only 8 oled + if (dev->type.model != usbDeviceType::StreamDeckPedal && + ((dev->type.model == usbDeviceType::StreamDeckPlus && val < 8) || + (val < dev->type.buttons))) + { + if (val < 8) { + QImage butImage(dev->type.iconSize,dev->type.iconSize, QImage::Format_RGB888); + if (color != Q_NULLPTR) + butImage.fill(*color); + else + butImage.fill((*controllers)[dev->path].color); + + QPainter butPaint(&butImage); + + if ( img == Q_NULLPTR) { + butPaint.setFont(QFont("times",16)); + butPaint.drawText(butImage.rect(),Qt::AlignCenter | Qt::AlignVCenter, text); + } else { + butPaint.setCompositionMode(QPainter::CompositionMode_SourceAtop); + butPaint.drawImage(0, 0, *img); + } + + QBuffer butBuffer(&data2); + + if (sdv1) + { + butImage.save(&butBuffer, "BMP"); + quint32 rem = data2.size(); + quint16 index = 0; + streamdeck_v1_image_header h1; + memset(h1.packet, 0x0, sizeof(h1)); // We can't be sure it is initialized with 0x00! + h1.cmd = 0x02; + h1.suffix = 0x01; + h1.button = val; + while (rem > 0) + { + quint16 length = qMin(rem,dev->type.maxPayload-sizeof(h1)); + data.clear(); + h1.isLast = (quint8)(rem <= dev->type.maxPayload-sizeof(h1) ? 1 : 0); // isLast ? 1 : 0,3 + h1.index = index; + data.append(QByteArray::fromRawData((const char*)h1.packet,sizeof(h1))); + rem -= length; + data.append(data2.mid(0,length)); + data.resize(dev->type.maxPayload); + memset(data.data()+length+sizeof(h1),0x0,data.size()-(length+sizeof(h1))); + res=hid_write(dev->handle, (const unsigned char*)data.constData(), data.size()); + //qInfo(logUsbControl()) << "Sending" << (((quint8)data[7] << 8) | ((quint8)data[6] & 0xff)) << "total=" << data.size() << "payload=" << (((quint8)data[5] << 8) | ((quint8)data[4] & 0xff)) << "last" << (quint8)data[3]; + data2.remove(0,length); + index++; + } + } + else + { + butImage.save(&butBuffer, "JPG"); + quint32 rem = data2.size(); + quint16 index = 0; + streamdeck_image_header h; + memset(h.packet, 0x0, sizeof(h)); // We can't be sure it is initialized with 0x00! + h.cmd = 0x02; + h.suffix = 0x07; + h.button = val; + while (rem > 0) + { + quint16 length = qMin(rem,dev->type.maxPayload-sizeof(h)); + data.clear(); + h.isLast = (quint8)(rem <= dev->type.maxPayload-sizeof(h) ? 1 : 0); // isLast ? 1 : 0,3 + h.length = length; + h.index = index; + data.append(QByteArray::fromRawData((const char*)h.packet,sizeof(h))); + rem -= length; + data.append(data2.mid(0,length)); + data.resize(dev->type.maxPayload); + memset(data.data()+length+sizeof(h),0x0,data.size()-(length+sizeof(h))); + res=hid_write(dev->handle, (const unsigned char*)data.constData(), data.size()); + //qInfo(logUsbControl()) << "Sending" << (((quint8)data[7] << 8) | ((quint8)data[6] & 0xff)) << "total=" << data.size() << "payload=" << (((quint8)data[5] << 8) | ((quint8)data[4] & 0xff)) << "last" << (quint8)data[3]; + data2.remove(0,length); + index++; + } + } + } + } } default: break; diff --git a/usbcontroller.h b/usbcontroller.h index e61e8b1..e9a41fd 100644 --- a/usbcontroller.h +++ b/usbcontroller.h @@ -160,8 +160,9 @@ struct BUTTON { QString on; QString off; QString path; - QColor background = Qt::white; - QImage icon; + QColor backgroundOn = Qt::lightGray; + QColor backgroundOff = Qt::blue; + QImage* icon = Q_NULLPTR; bool toggle = false; bool isOn = false; }; diff --git a/wfmain.cpp b/wfmain.cpp index a745f5e..c4f7737 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2531,9 +2531,11 @@ void wfmain::loadSettings() settings->value("Width", 0).toInt(), settings->value("Height", 0).toInt()); butt.textColour.setNamedColor(settings->value("Colour", QColor(Qt::white).name(QColor::HexArgb)).toString()); - butt.background.setNamedColor(settings->value("Background", QColor(Qt::white).name(QColor::HexArgb)).toString()); + butt.backgroundOn.setNamedColor(settings->value("BackgroundOn", QColor(Qt::lightGray).name(QColor::HexArgb)).toString()); + butt.backgroundOff.setNamedColor(settings->value("BackgroundOff", QColor(Qt::blue).name(QColor::HexArgb)).toString()); butt.toggle = settings->value("Toggle", false).toBool(); - + if (settings->value("Icon",NULL) != NULL) + butt.icon = new QImage(settings->value("Icon",NULL).value()); butt.on = settings->value("OnCommand", "None").toString(); butt.off = settings->value("OffCommand", "None").toString(); if (!butt.path.isEmpty()) @@ -3026,7 +3028,10 @@ void wfmain::saveSettings() settings->setValue("Width", usbButtons[nb].pos.width()); settings->setValue("Height", usbButtons[nb].pos.height()); settings->setValue("Colour", usbButtons[nb].textColour.name(QColor::HexArgb)); - settings->setValue("Background", usbButtons[nb].background.name(QColor::HexArgb)); + settings->setValue("BackgroundOn", usbButtons[nb].backgroundOn.name(QColor::HexArgb)); + settings->setValue("BackgroundOff", usbButtons[nb].backgroundOff.name(QColor::HexArgb)); + if (usbButtons[nb].icon != Q_NULLPTR) + settings->setValue("Icon", *usbButtons[nb].icon); settings->setValue("Toggle", usbButtons[nb].toggle); if (usbButtons[nb].onCommand != Q_NULLPTR) @@ -5258,24 +5263,26 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e wf->xAxis->setRange(0, spectWidth-1); wf->replot(); - +#if defined (USB_CONTROLLER) // Send to USB Controllers if requested usbMap::const_iterator i = usbControllers.constBegin(); while (i != usbControllers.constEnd()) { - if (i.value().dev != Q_NULLPTR && i.value().dev->connected && i.value().lcd == cmdLCDWaterfall ) + if (i.value().dev != Q_NULLPTR && i.value().dev->connected + && i.value().dev->type.model == usbDeviceType::StreamDeckPlus && i.value().lcd == cmdLCDWaterfall ) { - lcdImage = plot->toPixmap().toImage(); + lcdImage = wf->toPixmap().toImage(); emit sendControllerRequest(i.value().dev, usbFeatureType::featureLCD, 0, "", &lcdImage); } - else if (i.value().dev != Q_NULLPTR && i.value().dev->connected && i.value().lcd == cmdLCDSpectrum) + else if (i.value().dev != Q_NULLPTR && i.value().dev->connected + && i.value().dev->type.model == usbDeviceType::StreamDeckPlus && i.value().lcd == cmdLCDSpectrum) { lcdImage = plot->toPixmap().toImage(); emit sendControllerRequest(i.value().dev, usbFeatureType::featureLCD, 0, "", &lcdImage); } ++i; } - +#endif } oldPlotFloor = plotFloor;