From 6320716eb99af4b22d8e6eb04a2f7fa013d7a21b Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 15 Apr 2018 02:22:54 +0200 Subject: [PATCH] ATV modulator: Web API: add possibility to set image and video files --- plugins/channeltx/modatv/atvmod.cpp | 65 +++++++++++++++--- plugins/channeltx/modatv/atvmod.h | 23 +------ plugins/channeltx/modatv/atvmodgui.cpp | 19 ++++-- sdrbase/resources/webapi/doc/html2/index.html | 11 ++- .../webapi/doc/swagger/include/ATVMod.yaml | 6 ++ .../sdrangel/api/swagger/include/ATVMod.yaml | 6 ++ swagger/sdrangel/code/html2/index.html | 11 ++- .../code/qt5/client/SWGATVModSettings.cpp | 67 +++++++++++++++++++ .../code/qt5/client/SWGATVModSettings.h | 18 +++++ swagger/sdrangel/examples/tx_test.py | 4 +- 10 files changed, 191 insertions(+), 39 deletions(-) diff --git a/plugins/channeltx/modatv/atvmod.cpp b/plugins/channeltx/modatv/atvmod.cpp index 28feca73e..c98025b09 100644 --- a/plugins/channeltx/modatv/atvmod.cpp +++ b/plugins/channeltx/modatv/atvmod.cpp @@ -42,7 +42,6 @@ MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportVideoFileSourceStreamData, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureCameraIndex, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureCameraData, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportCameraData, Message) -MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureOverlayText, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportEffectiveSampleRate, Message) const QString ATVMod::m_channelIdURI = "sdrangel.channeltx.modatv"; @@ -613,12 +612,6 @@ bool ATVMod::handleMessage(const Message& cmd) return true; } - else if (MsgConfigureOverlayText::match(cmd)) - { - MsgConfigureOverlayText& cfg = (MsgConfigureOverlayText&) cmd; - m_overlayText = cfg.getOverlayText().toStdString(); - return true; - } else if (DSPSignalNotification::match(cmd)) { return true; @@ -800,6 +793,7 @@ void ATVMod::openImage(const QString& fileName) if (m_imageOK) { + m_imageFileName = fileName; m_imageFromFile.copyTo(m_imageOriginal); if (m_settings.m_showOverlayText) { @@ -808,6 +802,11 @@ void ATVMod::openImage(const QString& fileName) resizeImage(); } + else + { + m_imageFileName.clear(); + qDebug("ATVMod::openImage: cannot open image file %s", qPrintable(fileName)); + } } void ATVMod::openVideo(const QString& fileName) @@ -818,6 +817,7 @@ void ATVMod::openVideo(const QString& fileName) if (m_videoOK) { + m_videoFileName = fileName; m_videoFPS = m_video.get(CV_CAP_PROP_FPS); m_videoWidth = (int) m_video.get(CV_CAP_PROP_FRAME_WIDTH); m_videoHeight = (int) m_video.get(CV_CAP_PROP_FRAME_HEIGHT); @@ -845,7 +845,8 @@ void ATVMod::openVideo(const QString& fileName) } else { - qDebug("ATVMod::openVideo: cannot open video file"); + m_videoFileName.clear(); + qDebug("ATVMod::openVideo: cannot open video file %s", qPrintable(fileName)); } } @@ -1001,13 +1002,13 @@ void ATVMod::mixImageAndText(cv::Mat& image) int baseline=0; fontScale = fontScale < 4.0f ? 4.0f : fontScale; // minimum size - cv::Size textSize = cv::getTextSize(m_overlayText, fontFace, fontScale, thickness, &baseline); + cv::Size textSize = cv::getTextSize(m_settings.m_overlayText.toStdString(), fontFace, fontScale, thickness, &baseline); baseline += thickness; // position the text in the top left corner cv::Point textOrg(6, textSize.height+10); // then put the text itself - cv::putText(image, m_overlayText, textOrg, fontFace, fontScale, cv::Scalar::all(255*m_settings.m_uniformLevel), thickness, CV_AA); + cv::putText(image, m_settings.m_overlayText.toStdString(), textOrg, fontFace, fontScale, cv::Scalar::all(255*m_settings.m_uniformLevel), thickness, CV_AA); } void ATVMod::applyChannelSettings(int outputSampleRate, int inputFrequencyOffset, bool force) @@ -1250,6 +1251,9 @@ int ATVMod::webapiSettingsPutPatch( if (channelSettingsKeys.contains("forceDecimator")) { settings.m_forceDecimator = response.getAtvModSettings()->getForceDecimator() != 0; } + if (channelSettingsKeys.contains("showOverlayText")) { + settings.m_showOverlayText = response.getAtvModSettings()->getShowOverlayText() != 0; + } if (channelSettingsKeys.contains("overlayText")) { settings.m_overlayText = *response.getAtvModSettings()->getOverlayText(); } @@ -1276,6 +1280,34 @@ int ATVMod::webapiSettingsPutPatch( m_guiMessageQueue->push(msgToGUI); } + if (channelSettingsKeys.contains("imageFileName")) + { + MsgConfigureImageFileName *msg = MsgConfigureImageFileName::create( + *response.getAtvModSettings()->getImageFileName()); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureImageFileName *msgToGUI = MsgConfigureImageFileName::create( + *response.getAtvModSettings()->getImageFileName()); + m_guiMessageQueue->push(msgToGUI); + } + } + + if (channelSettingsKeys.contains("videoFileName")) + { + MsgConfigureVideoFileName *msg = MsgConfigureVideoFileName::create( + *response.getAtvModSettings()->getVideoFileName()); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureVideoFileName *msgToGUI = MsgConfigureVideoFileName::create( + *response.getAtvModSettings()->getVideoFileName()); + m_guiMessageQueue->push(msgToGUI); + } + } + webapiFormatChannelSettings(response, settings); return 200; @@ -1310,6 +1342,7 @@ void ATVMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon response.getAtvModSettings()->setRfScalingFactor(settings.m_rfScalingFactor); response.getAtvModSettings()->setFmExcursion(settings.m_fmExcursion); response.getAtvModSettings()->setForceDecimator(settings.m_forceDecimator ? 1 : 0); + response.getAtvModSettings()->setShowOverlayText(settings.m_showOverlayText ? 1 : 0); if (response.getAtvModSettings()->getOverlayText()) { *response.getAtvModSettings()->getOverlayText() = settings.m_overlayText; @@ -1324,6 +1357,18 @@ void ATVMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon } else { response.getAtvModSettings()->setTitle(new QString(settings.m_title)); } + + if (response.getAtvModSettings()->getImageFileName()) { + *response.getAtvModSettings()->getImageFileName() = m_imageFileName; + } else { + response.getAtvModSettings()->setImageFileName(new QString(m_imageFileName)); + } + + if (response.getAtvModSettings()->getVideoFileName()) { + *response.getAtvModSettings()->getVideoFileName() = m_videoFileName; + } else { + response.getAtvModSettings()->setVideoFileName(new QString(m_videoFileName)); + } } void ATVMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) diff --git a/plugins/channeltx/modatv/atvmod.h b/plugins/channeltx/modatv/atvmod.h index bcf3796f9..55ba9d780 100644 --- a/plugins/channeltx/modatv/atvmod.h +++ b/plugins/channeltx/modatv/atvmod.h @@ -324,27 +324,6 @@ public: { } }; - class MsgConfigureOverlayText : public Message - { - MESSAGE_CLASS_DECLARATION - - public: - const QString& getOverlayText() const { return m_overlayText; } - - static MsgConfigureOverlayText* create(const QString& overlayText) - { - return new MsgConfigureOverlayText(overlayText); - } - - private: - QString m_overlayText; - - MsgConfigureOverlayText(const QString& overlayText) : - Message(), - m_overlayText(overlayText) - { } - }; - class MsgReportEffectiveSampleRate : public Message { MESSAGE_CLASS_DECLARATION @@ -534,6 +513,8 @@ private: int m_cameraIndex; //!< curent camera index in list of available cameras std::string m_overlayText; + QString m_imageFileName; + QString m_videoFileName; // Used for standard SSB fftfilt* m_SSBFilter; diff --git a/plugins/channeltx/modatv/atvmodgui.cpp b/plugins/channeltx/modatv/atvmodgui.cpp index 6324c57ac..107e5832e 100644 --- a/plugins/channeltx/modatv/atvmodgui.cpp +++ b/plugins/channeltx/modatv/atvmodgui.cpp @@ -158,6 +158,18 @@ bool ATVModGUI::handleMessage(const Message& message) blockApplySettings(false); return true; } + else if (ATVMod::MsgConfigureImageFileName::match(message)) + { + const ATVMod::MsgConfigureImageFileName& cfg = (ATVMod::MsgConfigureImageFileName&) message; + ui->imageFileText->setText(cfg.getFileName()); + return true; + } + else if (ATVMod::MsgConfigureVideoFileName::match(message)) + { + const ATVMod::MsgConfigureVideoFileName& cfg = (ATVMod::MsgConfigureVideoFileName&) message; + ui->videoFileText->setText(cfg.getFileName()); + return true; + } else { return false; @@ -570,8 +582,7 @@ void ATVModGUI::on_overlayTextShow_toggled(bool checked) void ATVModGUI::on_overlayText_textEdited(const QString& arg1 __attribute__((unused))) { m_settings.m_overlayText = arg1; - ATVMod::MsgConfigureOverlayText* message = ATVMod::MsgConfigureOverlayText::create(ui->overlayText->text()); - m_atvMod->getInputMessageQueue()->push(message); + applySettings(); } void ATVModGUI::configureImageFileName() @@ -731,9 +742,7 @@ void ATVModGUI::displaySettings() ui->uniformLevelText->setText(QString("%1").arg(ui->uniformLevel->value())); ui->overlayText->setText(m_settings.m_overlayText); - - ATVMod::MsgConfigureOverlayText* message = ATVMod::MsgConfigureOverlayText::create(ui->overlayText->text()); - m_atvMod->getInputMessageQueue()->push(message); + ui->overlayTextShow->setChecked(m_settings.m_showOverlayText); blockApplySettings(false); } diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index f2d0a64eb..7c6cbfa73 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -891,6 +891,9 @@ margin-bottom: 20px; "forceDecimator" : { "type" : "integer" }, + "showOverlayText" : { + "type" : "integer" + }, "overlayText" : { "type" : "string" }, @@ -899,6 +902,12 @@ margin-bottom: 20px; }, "title" : { "type" : "string" + }, + "imageFileName" : { + "type" : "string" + }, + "videoFileName" : { + "type" : "string" } }, "description" : "ATVMod" @@ -20529,7 +20538,7 @@ except ApiException as e:
- Generated 2018-04-14T22:10:55.895+02:00 + Generated 2018-04-15T01:40:30.919+02:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/ATVMod.yaml b/sdrbase/resources/webapi/doc/swagger/include/ATVMod.yaml index ba9bea1cd..58acb2067 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/ATVMod.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/ATVMod.yaml @@ -41,12 +41,18 @@ ATVModSettings: format: float forceDecimator: type: integer + showOverlayText: + type: integer overlayText: type: string rgbColor: type: integer title: type: string + imageFileName: + type: string + videoFileName: + type: string ATVModReport: description: ATVMod diff --git a/swagger/sdrangel/api/swagger/include/ATVMod.yaml b/swagger/sdrangel/api/swagger/include/ATVMod.yaml index ba9bea1cd..58acb2067 100644 --- a/swagger/sdrangel/api/swagger/include/ATVMod.yaml +++ b/swagger/sdrangel/api/swagger/include/ATVMod.yaml @@ -41,12 +41,18 @@ ATVModSettings: format: float forceDecimator: type: integer + showOverlayText: + type: integer overlayText: type: string rgbColor: type: integer title: type: string + imageFileName: + type: string + videoFileName: + type: string ATVModReport: description: ATVMod diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index f2d0a64eb..7c6cbfa73 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -891,6 +891,9 @@ margin-bottom: 20px; "forceDecimator" : { "type" : "integer" }, + "showOverlayText" : { + "type" : "integer" + }, "overlayText" : { "type" : "string" }, @@ -899,6 +902,12 @@ margin-bottom: 20px; }, "title" : { "type" : "string" + }, + "imageFileName" : { + "type" : "string" + }, + "videoFileName" : { + "type" : "string" } }, "description" : "ATVMod" @@ -20529,7 +20538,7 @@ except ApiException as e:
- Generated 2018-04-14T22:10:55.895+02:00 + Generated 2018-04-15T01:40:30.919+02:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGATVModSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGATVModSettings.cpp index 7d67f490c..9272797a1 100644 --- a/swagger/sdrangel/code/qt5/client/SWGATVModSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGATVModSettings.cpp @@ -62,12 +62,18 @@ SWGATVModSettings::SWGATVModSettings() { m_fm_excursion_isSet = false; force_decimator = 0; m_force_decimator_isSet = false; + show_overlay_text = 0; + m_show_overlay_text_isSet = false; overlay_text = nullptr; m_overlay_text_isSet = false; rgb_color = 0; m_rgb_color_isSet = false; title = nullptr; m_title_isSet = false; + image_file_name = nullptr; + m_image_file_name_isSet = false; + video_file_name = nullptr; + m_video_file_name_isSet = false; } SWGATVModSettings::~SWGATVModSettings() { @@ -110,12 +116,18 @@ SWGATVModSettings::init() { m_fm_excursion_isSet = false; force_decimator = 0; m_force_decimator_isSet = false; + show_overlay_text = 0; + m_show_overlay_text_isSet = false; overlay_text = new QString(""); m_overlay_text_isSet = false; rgb_color = 0; m_rgb_color_isSet = false; title = new QString(""); m_title_isSet = false; + image_file_name = new QString(""); + m_image_file_name_isSet = false; + video_file_name = new QString(""); + m_video_file_name_isSet = false; } void @@ -137,6 +149,7 @@ SWGATVModSettings::cleanup() { + if(overlay_text != nullptr) { delete overlay_text; } @@ -144,6 +157,12 @@ SWGATVModSettings::cleanup() { if(title != nullptr) { delete title; } + if(image_file_name != nullptr) { + delete image_file_name; + } + if(video_file_name != nullptr) { + delete video_file_name; + } } SWGATVModSettings* @@ -191,12 +210,18 @@ SWGATVModSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&force_decimator, pJson["forceDecimator"], "qint32", ""); + ::SWGSDRangel::setValue(&show_overlay_text, pJson["showOverlayText"], "qint32", ""); + ::SWGSDRangel::setValue(&overlay_text, pJson["overlayText"], "QString", "QString"); ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); + ::SWGSDRangel::setValue(&image_file_name, pJson["imageFileName"], "QString", "QString"); + + ::SWGSDRangel::setValue(&video_file_name, pJson["videoFileName"], "QString", "QString"); + } QString @@ -264,6 +289,9 @@ SWGATVModSettings::asJsonObject() { if(m_force_decimator_isSet){ obj->insert("forceDecimator", QJsonValue(force_decimator)); } + if(m_show_overlay_text_isSet){ + obj->insert("showOverlayText", QJsonValue(show_overlay_text)); + } if(overlay_text != nullptr && *overlay_text != QString("")){ toJsonValue(QString("overlayText"), overlay_text, obj, QString("QString")); } @@ -273,6 +301,12 @@ SWGATVModSettings::asJsonObject() { if(title != nullptr && *title != QString("")){ toJsonValue(QString("title"), title, obj, QString("QString")); } + if(image_file_name != nullptr && *image_file_name != QString("")){ + toJsonValue(QString("imageFileName"), image_file_name, obj, QString("QString")); + } + if(video_file_name != nullptr && *video_file_name != QString("")){ + toJsonValue(QString("videoFileName"), video_file_name, obj, QString("QString")); + } return obj; } @@ -447,6 +481,16 @@ SWGATVModSettings::setForceDecimator(qint32 force_decimator) { this->m_force_decimator_isSet = true; } +qint32 +SWGATVModSettings::getShowOverlayText() { + return show_overlay_text; +} +void +SWGATVModSettings::setShowOverlayText(qint32 show_overlay_text) { + this->show_overlay_text = show_overlay_text; + this->m_show_overlay_text_isSet = true; +} + QString* SWGATVModSettings::getOverlayText() { return overlay_text; @@ -477,6 +521,26 @@ SWGATVModSettings::setTitle(QString* title) { this->m_title_isSet = true; } +QString* +SWGATVModSettings::getImageFileName() { + return image_file_name; +} +void +SWGATVModSettings::setImageFileName(QString* image_file_name) { + this->image_file_name = image_file_name; + this->m_image_file_name_isSet = true; +} + +QString* +SWGATVModSettings::getVideoFileName() { + return video_file_name; +} +void +SWGATVModSettings::setVideoFileName(QString* video_file_name) { + this->video_file_name = video_file_name; + this->m_video_file_name_isSet = true; +} + bool SWGATVModSettings::isSet(){ @@ -499,9 +563,12 @@ SWGATVModSettings::isSet(){ if(m_rf_scaling_factor_isSet){ isObjectUpdated = true; break;} if(m_fm_excursion_isSet){ isObjectUpdated = true; break;} if(m_force_decimator_isSet){ isObjectUpdated = true; break;} + if(m_show_overlay_text_isSet){ isObjectUpdated = true; break;} if(overlay_text != nullptr && *overlay_text != QString("")){ isObjectUpdated = true; break;} if(m_rgb_color_isSet){ isObjectUpdated = true; break;} if(title != nullptr && *title != QString("")){ isObjectUpdated = true; break;} + if(image_file_name != nullptr && *image_file_name != QString("")){ isObjectUpdated = true; break;} + if(video_file_name != nullptr && *video_file_name != QString("")){ isObjectUpdated = true; break;} }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGATVModSettings.h b/swagger/sdrangel/code/qt5/client/SWGATVModSettings.h index 0239f8887..9f6208b2a 100644 --- a/swagger/sdrangel/code/qt5/client/SWGATVModSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGATVModSettings.h @@ -93,6 +93,9 @@ public: qint32 getForceDecimator(); void setForceDecimator(qint32 force_decimator); + qint32 getShowOverlayText(); + void setShowOverlayText(qint32 show_overlay_text); + QString* getOverlayText(); void setOverlayText(QString* overlay_text); @@ -102,6 +105,12 @@ public: QString* getTitle(); void setTitle(QString* title); + QString* getImageFileName(); + void setImageFileName(QString* image_file_name); + + QString* getVideoFileName(); + void setVideoFileName(QString* video_file_name); + virtual bool isSet() override; @@ -157,6 +166,9 @@ private: qint32 force_decimator; bool m_force_decimator_isSet; + qint32 show_overlay_text; + bool m_show_overlay_text_isSet; + QString* overlay_text; bool m_overlay_text_isSet; @@ -166,6 +178,12 @@ private: QString* title; bool m_title_isSet; + QString* image_file_name; + bool m_image_file_name_isSet; + + QString* video_file_name; + bool m_video_file_name_isSet; + }; } diff --git a/swagger/sdrangel/examples/tx_test.py b/swagger/sdrangel/examples/tx_test.py index 1d8c48a2b..3a1e45390 100644 --- a/swagger/sdrangel/examples/tx_test.py +++ b/swagger/sdrangel/examples/tx_test.py @@ -171,14 +171,16 @@ def setupChannel(options): settings["ATVModSettings"]["inputFrequencyOffset"] = options.channel_freq settings["ATVModSettings"]["rfBandwidth"] = 30000 settings["ATVModSettings"]["forceDecimator"] = 1 # This is to engage filter + settings["ATVModSettings"]["imageFileName"] = "/home/f4exb/sdrangel/lena_4.3.png" settings["ATVModSettings"]["atvStd"] = 5 # ATVStdHSkip - settings["ATVModSettings"]["atvModInput"] = 1 # ATVModInputHBars + settings["ATVModSettings"]["atvModInput"] = 6 # ATVModInputImage settings["ATVModSettings"]["atvModulation"] = 1 # ATVModulationFM settings["ATVModSettings"]["fps"] = 2 settings["ATVModSettings"]["nbLines"] = 90 settings["ATVModSettings"]["uniformLevel"] = 1.0 # 100% white settings["ATVModSettings"]["fmExcursion"] = 0.2 # FM excursion is 20% of channel bandwidth settings["ATVModSettings"]["overlayText"] = "F4EXB" + settings["ATVModSettings"]["showOverlayText"] = 1 elif options.channel_id == "SSBMod": settings["SSBModSettings"]["title"] = "Test SSB" settings["SSBModSettings"]["inputFrequencyOffset"] = options.channel_freq