From 5f746204067314a2b35d7d8d6e11a3dd70bfa668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Olszewski?= Date: Thu, 27 Mar 2025 01:20:53 +0100 Subject: [PATCH 01/26] Split button added, swagger changed manually, but should be the same when regenerated --- .../limesdroutput/limesdroutput.cpp | 4 +++- .../limesdrinput/limesdrinput.cpp | 17 ++++++++++++-- .../limesdrinput/limesdrinputgui.cpp | 9 ++++++++ .../limesdrinput/limesdrinputgui.h | 1 + .../limesdrinput/limesdrinputgui.ui | 12 +++++++++- .../limesdrinput/limesdrinputsettings.cpp | 9 ++++++++ .../limesdrinput/limesdrinputsettings.h | 1 + .../sdrangel/api/swagger/include/LimeSdr.yaml | 2 ++ .../qt5/client/SWGLimeSdrInputSettings.cpp | 22 +++++++++++++++++++ .../code/qt5/client/SWGLimeSdrInputSettings.h | 8 ++++++- 10 files changed, 80 insertions(+), 5 deletions(-) diff --git a/plugins/samplesink/limesdroutput/limesdroutput.cpp b/plugins/samplesink/limesdroutput/limesdroutput.cpp index 9551a18df..b8604d8be 100644 --- a/plugins/samplesink/limesdroutput/limesdroutput.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutput.cpp @@ -807,7 +807,9 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, const Q if (settingsKeys.contains("devSampleRate") || settingsKeys.contains("log2HardInterp") || force) { - forwardChangeAllDSP = true; //m_settings.m_devSampleRate != settings.m_devSampleRate; + //forwardChangeAllDSP = true; //m_settings.m_devSampleRate != settings.m_devSampleRate; + forwardChangeTxDSP = m_settings.m_log2HardInterp != settings.m_log2HardInterp; + forwardChangeAllDSP = m_settings.m_devSampleRate != settings.m_devSampleRate; if (m_deviceShared.m_deviceParams->getDevice()) { diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index 62d1a6efc..be6fccbfb 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -969,8 +969,14 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, const QLi if (settingsKeys.contains("devSampleRate") || settingsKeys.contains("log2HardDecim") || force) { - forwardChangeAllDSP = true; //m_settings.m_devSampleRate != settings.m_devSampleRate; - + + if(!settings.m_splitFreq) { + forwardChangeAllDSP = true; //m_settings.m_devSampleRate != settings.m_devSampleRate; + qDebug() << "LimeSDRInput::applySettings: Split is false, val:" << settings.m_splitFreq; + }else{ + forwardChangeRxDSP = m_settings.m_log2HardDecim != settings.m_log2HardDecim; + forwardChangeAllDSP = m_settings.m_devSampleRate != settings.m_devSampleRate; + } if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired) { if (LMS_SetSampleRateDir(m_deviceShared.m_deviceParams->getDevice(), @@ -1439,6 +1445,9 @@ void LimeSDRInput::webapiUpdateDeviceSettings( if (deviceSettingsKeys.contains("dcBlock")) { settings.m_dcBlock = response.getLimeSdrInputSettings()->getDcBlock() != 0; } + if (deviceSettingsKeys.contains("splitFreq")) { + settings.m_splitFreq = response.getLimeSdrInputSettings()->getSplitFreq() != 0; + } if (deviceSettingsKeys.contains("devSampleRate")) { settings.m_devSampleRate = response.getLimeSdrInputSettings()->getDevSampleRate(); } @@ -1521,6 +1530,7 @@ void LimeSDRInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& re response.getLimeSdrInputSettings()->setAntennaPath((int) settings.m_antennaPath); response.getLimeSdrInputSettings()->setCenterFrequency(settings.m_centerFrequency); response.getLimeSdrInputSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0); + response.getLimeSdrInputSettings()->setSplitFreq(settings.m_splitFreq ? 1 : 0); response.getLimeSdrInputSettings()->setDevSampleRate(settings.m_devSampleRate); response.getLimeSdrInputSettings()->setExtClock(settings.m_extClock ? 1 : 0); response.getLimeSdrInputSettings()->setExtClockFreq(settings.m_extClockFreq); @@ -1653,6 +1663,9 @@ void LimeSDRInput::webapiReverseSendSettings(const QList& deviceSetting if (deviceSettingsKeys.contains("dcBlock") || force) { swgLimeSdrInputSettings->setDcBlock(settings.m_dcBlock ? 1 : 0); } + if (deviceSettingsKeys.contains("splitFreq") || force) { + swgLimeSdrInputSettings->setSplitFreq(settings.m_splitFreq ? 1 : 0); + } if (deviceSettingsKeys.contains("devSampleRate") || force) { swgLimeSdrInputSettings->setDevSampleRate(settings.m_devSampleRate); } diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp index 7b2b04929..6502c1bf2 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp @@ -428,6 +428,7 @@ void LimeSDRInputGUI::displaySettings() displaySampleRate(); ui->dcOffset->setChecked(m_settings.m_dcBlock); + ui->splitFreq->setChecked(m_settings.m_splitFreq); ui->iqImbalance->setChecked(m_settings.m_iqCorrection); ui->hwDecim->setCurrentIndex(m_settings.m_log2HardDecim); @@ -635,6 +636,13 @@ void LimeSDRInputGUI::on_dcOffset_toggled(bool checked) sendSettings(); } +void LimeSDRInputGUI::on_splitFreq_toggled(bool checked) +{ + m_settings.m_splitFreq = checked; + m_settingsKeys.append("splitFreq"); + sendSettings(); +} + void LimeSDRInputGUI::on_iqImbalance_toggled(bool checked) { m_settings.m_iqCorrection = checked; @@ -939,6 +947,7 @@ void LimeSDRInputGUI::makeUIConnections() QObject::connect(ui->ncoFrequency, &ValueDialZ::changed, this, &LimeSDRInputGUI::on_ncoFrequency_changed); QObject::connect(ui->ncoEnable, &ButtonSwitch::toggled, this, &LimeSDRInputGUI::on_ncoEnable_toggled); QObject::connect(ui->dcOffset, &ButtonSwitch::toggled, this, &LimeSDRInputGUI::on_dcOffset_toggled); + QObject::connect(ui->splitFreq, &ButtonSwitch::toggled, this, &LimeSDRInputGUI::on_splitFreq_toggled); QObject::connect(ui->iqImbalance, &ButtonSwitch::toggled, this, &LimeSDRInputGUI::on_iqImbalance_toggled); QObject::connect(ui->sampleRate, &ValueDial::changed, this, &LimeSDRInputGUI::on_sampleRate_changed); QObject::connect(ui->hwDecim, QOverload::of(&QComboBox::currentIndexChanged), this, &LimeSDRInputGUI::on_hwDecim_currentIndexChanged); diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.h b/plugins/samplesource/limesdrinput/limesdrinputgui.h index 3da20c14e..7818c69b1 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.h +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.h @@ -89,6 +89,7 @@ private slots: void on_ncoFrequency_changed(qint64 value); void on_ncoEnable_toggled(bool checked); void on_dcOffset_toggled(bool checked); + void on_splitFreq_toggled(bool checked); void on_iqImbalance_toggled(bool checked); void on_sampleRate_changed(quint64 value); void on_hwDecim_currentIndexChanged(int index); diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.ui b/plugins/samplesource/limesdrinput/limesdrinputgui.ui index c9a1dcbf0..d9576b9e4 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.ui +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.ui @@ -6,7 +6,7 @@ 0 0 - 360 + 386 255 @@ -312,6 +312,16 @@ + + + + Disable RX/TX frequency being locked + + + Split + + + diff --git a/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp b/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp index 088eafc0e..d87b81d59 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp @@ -31,6 +31,7 @@ void LimeSDRInputSettings::resetToDefaults() m_devSampleRate = 5000000; m_log2HardDecim = 3; m_dcBlock = false; + m_splitFreq = false; m_iqCorrection = false; m_log2SoftDecim = 0; m_lpfBW = 4.5e6f; @@ -96,6 +97,7 @@ QByteArray LimeSDRInputSettings::serialize() const s.writeFloat(30, m_replayLength); s.writeFloat(31, m_replayStep); s.writeBool(32, m_replayLoop); + s.writeBool(33, m_splitFreq); return s.final(); } @@ -158,6 +160,7 @@ bool LimeSDRInputSettings::deserialize(const QByteArray& data) d.readFloat(30, &m_replayLength, 20.0f); d.readFloat(31, &m_replayStep, 5.0f); d.readBool(32, &m_replayLoop, false); + d.readBool(33, &m_splitFreq, false); return true; } @@ -183,6 +186,9 @@ void LimeSDRInputSettings::applySettings(const QStringList& settingsKeys, const if (settingsKeys.contains("dcBlock")) { m_dcBlock = settings.m_dcBlock; } + if (settingsKeys.contains("splitFreq")) { + m_splitFreq = settings.m_splitFreq; + } if (settingsKeys.contains("iqCorrection")) { m_iqCorrection = settings.m_iqCorrection; } @@ -285,6 +291,9 @@ QString LimeSDRInputSettings::getDebugString(const QStringList& settingsKeys, bo if (settingsKeys.contains("dcBlock") || force) { ostr << " m_dcBlock: " << m_dcBlock; } + if (settingsKeys.contains("splitFreq") || force) { + ostr << " m_splitFreq: " << m_splitFreq; + } if (settingsKeys.contains("iqCorrection") || force) { ostr << " m_iqCorrection: " << m_iqCorrection; } diff --git a/plugins/samplesource/limesdrinput/limesdrinputsettings.h b/plugins/samplesource/limesdrinput/limesdrinputsettings.h index 67b8a5c3c..bb2681ba6 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputsettings.h +++ b/plugins/samplesource/limesdrinput/limesdrinputsettings.h @@ -51,6 +51,7 @@ struct LimeSDRInputSettings uint32_t m_log2HardDecim; // channel settings bool m_dcBlock; + bool m_splitFreq; bool m_iqCorrection; uint32_t m_log2SoftDecim; float m_lpfBW; //!< LMS amalog lowpass filter bandwidth (Hz) diff --git a/swagger/sdrangel/api/swagger/include/LimeSdr.yaml b/swagger/sdrangel/api/swagger/include/LimeSdr.yaml index 7c54b524f..5fae3ce0c 100644 --- a/swagger/sdrangel/api/swagger/include/LimeSdr.yaml +++ b/swagger/sdrangel/api/swagger/include/LimeSdr.yaml @@ -10,6 +10,8 @@ LimeSdrInputSettings: type: integer dcBlock: type: integer + splitFreq: + type: integer iqCorrection: type: integer log2SoftDecim: diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp index 0b917ec86..dd21d8a9e 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp @@ -35,7 +35,9 @@ SWGLimeSdrInputSettings::SWGLimeSdrInputSettings() { log2_hard_decim = 0; m_log2_hard_decim_isSet = false; dc_block = 0; + splitFreq = 0; m_dc_block_isSet = false; + m_splitFreq_isSet = false; iq_correction = 0; m_iq_correction_isSet = false; log2_soft_decim = 0; @@ -100,6 +102,8 @@ SWGLimeSdrInputSettings::init() { m_log2_hard_decim_isSet = false; dc_block = 0; m_dc_block_isSet = false; + splitFreq = 0; + m_splitFreq_isSet = false; iq_correction = 0; m_iq_correction_isSet = false; log2_soft_decim = 0; @@ -202,6 +206,8 @@ SWGLimeSdrInputSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&log2_hard_decim, pJson["log2HardDecim"], "qint32", ""); ::SWGSDRangel::setValue(&dc_block, pJson["dcBlock"], "qint32", ""); + + ::SWGSDRangel::setValue(&splitFreq, pJson["splitFreq"], "qint32", ""); ::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "qint32", ""); @@ -279,6 +285,9 @@ SWGLimeSdrInputSettings::asJsonObject() { if(m_dc_block_isSet){ obj->insert("dcBlock", QJsonValue(dc_block)); } + if(m_splitFreq_isSet){ + obj->insert("splitFreq", QJsonValue(splitFreq)); + } if(m_iq_correction_isSet){ obj->insert("iqCorrection", QJsonValue(iq_correction)); } @@ -395,6 +404,16 @@ SWGLimeSdrInputSettings::setDcBlock(qint32 dc_block) { this->m_dc_block_isSet = true; } +qint32 +SWGLimeSdrInputSettings::getSplitFreq() { + return splitFreq; +} +void +SWGLimeSdrInputSettings::setSplitFreq(qint32 splitFreq) { + this->splitFreq = splitFreq; + this->m_splitFreq_isSet = true; +} + qint32 SWGLimeSdrInputSettings::getIqCorrection() { return iq_correction; @@ -652,6 +671,9 @@ SWGLimeSdrInputSettings::isSet(){ if(m_dc_block_isSet){ isObjectUpdated = true; break; } + if(m_splitFreq_isSet){ + isObjectUpdated = true; break; + } if(m_iq_correction_isSet){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h index 0f872fcb6..9e948f8f0 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h @@ -52,7 +52,10 @@ public: void setLog2HardDecim(qint32 log2_hard_decim); qint32 getDcBlock(); - void setDcBlock(qint32 dc_block); + void setDcBlock(qint32 splitFreq); + + qint32 getSplitFreq(); + void setSplitFreq(qint32 splitFreq); qint32 getIqCorrection(); void setIqCorrection(qint32 iq_correction); @@ -142,6 +145,9 @@ private: qint32 dc_block; bool m_dc_block_isSet; + qint32 splitFreq; + bool m_splitFreq_isSet; + qint32 iq_correction; bool m_iq_correction_isSet; From c7e2a7890329100533dee9e514dac28c176700cb Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 5 Apr 2025 09:39:09 +0200 Subject: [PATCH 02/26] Use SerialDV 1.1.5 --- external/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 90dd9b8dc..6f6343318 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -11,7 +11,7 @@ set(CODEC2_TAG "v1.0.3") set(CM256CC_TAG c0e92b92aca3d1d36c990b642b937c64d363c559) set(MBELIB_TAG fe83b32c6a60cdd7bce8cecf3c7a0b9ec87a7667) -set(SERIALDV_TAG "v1.1.4") +set(SERIALDV_TAG "v1.1.5") set(DSDCC_TAG "v1.9.5") set(LIMESUITE_TAG b39cb61ed03d74c35a2de757d495e901acbb6404) set(BLADERF_TAG "2021.02") From 356e5e42be49efdca114d949dca90daa6a3c07fb Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 5 Apr 2025 21:59:21 +0200 Subject: [PATCH 03/26] Use -DCMAKE_POLICY_VERSION_MINIMUM=3.5 for external packages Windows build --- external/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 6f6343318..d1df38ba3 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -54,6 +54,7 @@ if (WIN32) -DCMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG=${SDRANGEL_BINARY_LIB_DIR} -DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE=${SDRANGEL_BINARY_LIB_DIR} -DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO=${SDRANGEL_BINARY_LIB_DIR} + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ) elseif (LINUX) set(COMMON_CMAKE_ARGS From 90ddb543718e9a0b07ef33e0560885522723f2e5 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Mon, 14 Apr 2025 09:13:44 +0100 Subject: [PATCH 04/26] ChannelWebAPIUtils: Add double version of patchDeviceSetting. Fix #2428 --- sdrbase/channel/channelwebapiutils.cpp | 57 ++++++++++++++++++++++++++ sdrbase/channel/channelwebapiutils.h | 1 + 2 files changed, 58 insertions(+) diff --git a/sdrbase/channel/channelwebapiutils.cpp b/sdrbase/channel/channelwebapiutils.cpp index e5e09ee0a..73743a354 100644 --- a/sdrbase/channel/channelwebapiutils.cpp +++ b/sdrbase/channel/channelwebapiutils.cpp @@ -1354,6 +1354,63 @@ bool ChannelWebAPIUtils::patchDeviceSetting(unsigned int deviceIndex, const QStr } } +bool ChannelWebAPIUtils::patchDeviceSetting(unsigned int deviceIndex, const QString &setting, double value) +{ + SWGSDRangel::SWGDeviceSettings deviceSettingsResponse; + QString errorResponse; + int httpRC; + DeviceSet *deviceSet; + + if (getDeviceSettings(deviceIndex, deviceSettingsResponse, deviceSet)) + { + // Patch setting + QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject(); + double oldValue; + if (WebAPIUtils::getSubObjectDouble(*jsonObj, setting, oldValue)) + { + WebAPIUtils::setSubObjectDouble(*jsonObj, setting, value); + QStringList deviceSettingsKeys; + deviceSettingsKeys.append(setting); + deviceSettingsResponse.init(); + deviceSettingsResponse.fromJsonObject(*jsonObj); + SWGSDRangel::SWGErrorResponse errorResponse2; + delete jsonObj; + + if (DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource()) { + httpRC = source->webapiSettingsPutPatch(false, deviceSettingsKeys, deviceSettingsResponse, *errorResponse2.getMessage()); + } else if (DeviceSampleSink *sink = deviceSet->m_deviceAPI->getSampleSink()) { + httpRC = sink->webapiSettingsPutPatch(false, deviceSettingsKeys, deviceSettingsResponse, *errorResponse2.getMessage()); + } else if (DeviceSampleMIMO *mimo = deviceSet->m_deviceAPI->getSampleMIMO()) { + httpRC = mimo->webapiSettingsPutPatch(false, deviceSettingsKeys, deviceSettingsResponse, *errorResponse2.getMessage()); + } else { + httpRC = 404; + } + + if (httpRC/100 == 2) + { + qDebug("ChannelWebAPIUtils::patchDeviceSetting: set device setting %s OK", qPrintable(setting)); + return true; + } + else + { + qWarning("ChannelWebAPIUtils::patchDeviceSetting: set device setting error %d: %s", + httpRC, qPrintable(*errorResponse2.getMessage())); + return false; + } + } + else + { + delete jsonObj; + qWarning("ChannelWebAPIUtils::patchDeviceSetting: no key %s in device settings", qPrintable(setting)); + return false; + } + } + else + { + return false; + } +} + // Set feature setting bool ChannelWebAPIUtils::patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, const QString &value) { diff --git a/sdrbase/channel/channelwebapiutils.h b/sdrbase/channel/channelwebapiutils.h index be11eb02b..d22773aa5 100644 --- a/sdrbase/channel/channelwebapiutils.h +++ b/sdrbase/channel/channelwebapiutils.h @@ -96,6 +96,7 @@ public: static bool getDeviceReportList(unsigned int deviceIndex, const QString &key, const QString &subKey, QList &values); static bool getDevicePosition(unsigned int deviceIndex, float& latitude, float& longitude, float& altitude); static bool patchDeviceSetting(unsigned int deviceIndex, const QString &setting, int value); + static bool patchDeviceSetting(unsigned int deviceIndex, const QString &setting, double value); static bool runFeature(unsigned int featureSetIndex, unsigned int featureIndex); static bool stopFeature(unsigned int featureSetIndex, unsigned int featureIndex); static bool patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, const QString &value); From e33d6e9b647b7ea9e537847cfdea13471ed7cc68 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Wed, 16 Apr 2025 11:23:38 +0100 Subject: [PATCH 05/26] Satellite Tracker: Fix crash when doppler enabled. --- .../satellitetrackerworker.cpp | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/plugins/feature/satellitetracker/satellitetrackerworker.cpp b/plugins/feature/satellitetracker/satellitetrackerworker.cpp index 9b6db8e24..b9ad7d1d4 100644 --- a/plugins/feature/satellitetracker/satellitetrackerworker.cpp +++ b/plugins/feature/satellitetracker/satellitetrackerworker.cpp @@ -854,23 +854,26 @@ void SatelliteTrackerWorker::disableDoppler(SatWorkerState *satWorkerState) { for (int i = 0; i < m_deviceSettingsList->size(); i++) { - SatelliteTrackerSettings::SatelliteDeviceSettings *devSettings = m_deviceSettingsList->at(i); - if (devSettings->m_doppler.size() > 0) + if (i < satWorkerState->m_doppler.size()) { - for (int j = 0; j < devSettings->m_doppler.size(); j++) + SatelliteTrackerSettings::SatelliteDeviceSettings *devSettings = m_deviceSettingsList->at(i); + if (devSettings->m_doppler.size() > 0) { - int offset; - if (ChannelWebAPIUtils::getFrequencyOffset(devSettings->m_deviceSetIndex, devSettings->m_doppler[j], offset)) + for (int j = 0; j < devSettings->m_doppler.size(); j++) { - // Remove old doppler - offset += satWorkerState->m_doppler[i]; - if (!ChannelWebAPIUtils::setFrequencyOffset(devSettings->m_deviceSetIndex, devSettings->m_doppler[j], offset)) - qDebug() << "SatelliteTrackerWorker::doppler: Failed to set frequency offset"; + int offset; + if (ChannelWebAPIUtils::getFrequencyOffset(devSettings->m_deviceSetIndex, devSettings->m_doppler[j], offset)) + { + // Remove old doppler + offset += satWorkerState->m_doppler[i]; + if (!ChannelWebAPIUtils::setFrequencyOffset(devSettings->m_deviceSetIndex, devSettings->m_doppler[j], offset)) + qDebug() << "SatelliteTrackerWorker::disableDoppler: Failed to set frequency offset"; + } + else + qDebug() << "SatelliteTrackerWorker::disableDoppler: Failed to get frequency offset"; } - else - qDebug() << "SatelliteTrackerWorker::doppler: Failed to get frequency offset"; + satWorkerState->m_doppler[i] = 0; } - satWorkerState->m_doppler[i] = 0; } } } From bafcb7531327ab7d62dacb586bc01f29e8e07170 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Wed, 16 Apr 2025 14:43:47 +0100 Subject: [PATCH 06/26] Fix doppler correction. --- .../satellitetrackerworker.cpp | 46 +++++++++++++------ .../satellitetracker/satellitetrackerworker.h | 1 + 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/plugins/feature/satellitetracker/satellitetrackerworker.cpp b/plugins/feature/satellitetracker/satellitetrackerworker.cpp index b9ad7d1d4..122f2e913 100644 --- a/plugins/feature/satellitetracker/satellitetrackerworker.cpp +++ b/plugins/feature/satellitetracker/satellitetrackerworker.cpp @@ -826,9 +826,7 @@ void SatelliteTrackerWorker::enableDoppler(SatWorkerState *satWorkerState) if (devSettings->m_doppler.size() > 0) { requiresDoppler = true; - for (int j = 0; j < devSettings->m_doppler.size(); j++) { - satWorkerState->m_doppler.append(0); - } + satWorkerState->m_doppler.append(0); } } if (requiresDoppler) @@ -836,7 +834,8 @@ void SatelliteTrackerWorker::enableDoppler(SatWorkerState *satWorkerState) qDebug() << "SatelliteTrackerWorker::applyDeviceAOSSettings: Enabling doppler for " << satWorkerState->m_name; satWorkerState->m_dopplerTimer.setInterval(m_settings.m_dopplerPeriod * 1000); satWorkerState->m_dopplerTimer.start(); - connect(&satWorkerState->m_dopplerTimer, &QTimer::timeout, [this, satWorkerState]() { + disconnect(satWorkerState->m_connection); + satWorkerState->m_connection = connect(&satWorkerState->m_dopplerTimer, &QTimer::timeout, [this, satWorkerState]() { doppler(satWorkerState); }); } @@ -848,13 +847,16 @@ void SatelliteTrackerWorker::disableDoppler(SatWorkerState *satWorkerState) // Stop Doppler timer, and set interval to 0, so we don't restart it in start() satWorkerState->m_dopplerTimer.stop(); satWorkerState->m_dopplerTimer.setInterval(0); + disconnect(satWorkerState->m_connection); // Remove doppler correction from any channel - QList *m_deviceSettingsList = m_settings.m_deviceSettings.value(satWorkerState->m_name); - if (m_deviceSettingsList) + if (satWorkerState->m_doppler.size() > 0) { - for (int i = 0; i < m_deviceSettingsList->size(); i++) + QList *m_deviceSettingsList = m_settings.m_deviceSettings.value(satWorkerState->m_name); + if (m_deviceSettingsList) { - if (i < satWorkerState->m_doppler.size()) + int idx = 0; + + for (int i = 0; i < m_deviceSettingsList->size(); i++) { SatelliteTrackerSettings::SatelliteDeviceSettings *devSettings = m_deviceSettingsList->at(i); if (devSettings->m_doppler.size() > 0) @@ -865,14 +867,25 @@ void SatelliteTrackerWorker::disableDoppler(SatWorkerState *satWorkerState) if (ChannelWebAPIUtils::getFrequencyOffset(devSettings->m_deviceSetIndex, devSettings->m_doppler[j], offset)) { // Remove old doppler - offset += satWorkerState->m_doppler[i]; - if (!ChannelWebAPIUtils::setFrequencyOffset(devSettings->m_deviceSetIndex, devSettings->m_doppler[j], offset)) + std::vector& deviceSets = MainCore::instance()->getDeviceSets(); + ChannelAPI *channel = deviceSets[devSettings->m_deviceSetIndex]->getChannelAt(j); + int tx = false; + if (channel) { + tx = channel->getStreamType() == ChannelAPI::StreamSingleSource; // What if MIMO? + } + if (tx) { + offset -= satWorkerState->m_doppler[idx]; + } else { + offset += satWorkerState->m_doppler[idx]; + } + if (!ChannelWebAPIUtils::setFrequencyOffset(devSettings->m_deviceSetIndex, devSettings->m_doppler[j], offset)) qDebug() << "SatelliteTrackerWorker::disableDoppler: Failed to set frequency offset"; } else qDebug() << "SatelliteTrackerWorker::disableDoppler: Failed to get frequency offset"; } - satWorkerState->m_doppler[i] = 0; + satWorkerState->m_doppler[idx] = 0; + idx++; } } } @@ -886,6 +899,8 @@ void SatelliteTrackerWorker::doppler(SatWorkerState *satWorkerState) QList *m_deviceSettingsList = m_settings.m_deviceSettings.value(satWorkerState->m_name); if (m_deviceSettingsList) { + int idx = 0; + for (int i = 0; i < m_deviceSettingsList->size(); i++) { SatelliteTrackerSettings::SatelliteDeviceSettings *devSettings = m_deviceSettingsList->at(i); @@ -918,15 +933,14 @@ void SatelliteTrackerWorker::doppler(SatWorkerState *satWorkerState) int initOffset; if (tx) { - initOffset = offset - satWorkerState->m_doppler[i]; + initOffset = offset - satWorkerState->m_doppler[idx]; offset = initOffset + doppler; } else { - initOffset = offset + satWorkerState->m_doppler[i]; + initOffset = offset + satWorkerState->m_doppler[idx]; offset = initOffset - doppler; } - if (!ChannelWebAPIUtils::setFrequencyOffset(devSettings->m_deviceSetIndex, devSettings->m_doppler[j], offset)) qDebug() << "SatelliteTrackerWorker::doppler: Failed to set frequency offset"; } @@ -934,10 +948,12 @@ void SatelliteTrackerWorker::doppler(SatWorkerState *satWorkerState) qDebug() << "SatelliteTrackerWorker::doppler: Failed to get frequency offset"; } - satWorkerState->m_doppler[i] = doppler; + satWorkerState->m_doppler[idx] = doppler; } else qDebug() << "SatelliteTrackerWorker::doppler: couldn't get centre frequency for device at " << devSettings->m_deviceSetIndex; + + idx++; } } } diff --git a/plugins/feature/satellitetracker/satellitetrackerworker.h b/plugins/feature/satellitetracker/satellitetrackerworker.h index 3e764d29b..e2df7c327 100644 --- a/plugins/feature/satellitetracker/satellitetrackerworker.h +++ b/plugins/feature/satellitetracker/satellitetrackerworker.h @@ -65,6 +65,7 @@ protected: QList m_doppler; // How much doppler we've applied to a channel SatelliteState m_satState; bool m_hasSignalledAOS; // For pass specified by m_aos and m_los + QMetaObject::Connection m_connection; friend SatelliteTrackerWorker; }; From fa6a8014119477107d6562766ec2620dfd345614 Mon Sep 17 00:00:00 2001 From: Matt Paine Date: Sun, 20 Apr 2025 17:56:11 +1000 Subject: [PATCH 07/26] Also accept +0179+0001 as an acceptable gs232 format for reporting position --- .../feature/gs232controller/gs232protocol.cpp | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/plugins/feature/gs232controller/gs232protocol.cpp b/plugins/feature/gs232controller/gs232protocol.cpp index 7c4cc52ab..c1d2de9b3 100644 --- a/plugins/feature/gs232controller/gs232protocol.cpp +++ b/plugins/feature/gs232controller/gs232protocol.cpp @@ -54,23 +54,37 @@ void GS232Protocol::readData() if (len != -1) { QString response = QString::fromUtf8(buf, len); - // MD-02 can return AZ=-00 EL=-00 and other negative angles - QRegularExpression re("AZ=([-\\d]\\d\\d) *EL=([-\\d]\\d\\d)"); - QRegularExpressionMatch match = re.match(response); - if (match.hasMatch()) + // Handle both formats: + // 1. AZ=XXX EL=XXX (MD-02 can return negative angles like AZ=-00 EL=-00) + // 2. +XXXX+YYYY (direct angle format) + QRegularExpression reAzEl("AZ=([-\\d]\\d\\d) *EL=([-\\d]\\d\\d)"); + QRegularExpression reAngles("([+-]\\d{4})([+-]\\d{4})"); + + QRegularExpressionMatch matchAzEl = reAzEl.match(response); + QRegularExpressionMatch matchAngles = reAngles.match(response); + if (matchAzEl.hasMatch()) { - QString az = match.captured(1); - QString el = match.captured(2); - //qDebug() << "SPIDProtocol::readData read Az " << az << " El " << el; + QString az = matchAzEl.captured(1); + QString el = matchAzEl.captured(2); + qDebug() << "GS232Protocol::readData read Az " << az << " El " << el; reportAzEl(az.toFloat(), el.toFloat()); } + else if (matchAngles.hasMatch()) + { + // Convert from +XXXX format to float + QString az = matchAngles.captured(1); + QString el = matchAngles.captured(2); + qDebug() << "GS232Protocol::readData read direct angles Az " << az << " El " << el; + // The format gives angles in tenths of a degree, so divide by 10 + reportAzEl(az.toFloat()/10.0f, el.toFloat()/10.0f); + } else if (response == "\r\n") { // Ignore } else { - qWarning() << "SPIDProtocol::readData - unexpected GS-232 response \"" << response << "\""; + qWarning() << "GS232Protocol::readData - unexpected GS-232 response \"" << response << "\""; reportError(QString("Unexpected GS-232 response: %1").arg(response)); } } From 88b2f2989456f259922516cd9176877e509e5f2c Mon Sep 17 00:00:00 2001 From: Matt Paine Date: Mon, 21 Apr 2025 19:22:21 +1000 Subject: [PATCH 08/26] Comment out the debug statements --- plugins/feature/gs232controller/gs232protocol.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/feature/gs232controller/gs232protocol.cpp b/plugins/feature/gs232controller/gs232protocol.cpp index c1d2de9b3..97851e97e 100644 --- a/plugins/feature/gs232controller/gs232protocol.cpp +++ b/plugins/feature/gs232controller/gs232protocol.cpp @@ -66,7 +66,7 @@ void GS232Protocol::readData() { QString az = matchAzEl.captured(1); QString el = matchAzEl.captured(2); - qDebug() << "GS232Protocol::readData read Az " << az << " El " << el; + //qDebug() << "GS232Protocol::readData read Az " << az << " El " << el; reportAzEl(az.toFloat(), el.toFloat()); } else if (matchAngles.hasMatch()) @@ -74,7 +74,7 @@ void GS232Protocol::readData() // Convert from +XXXX format to float QString az = matchAngles.captured(1); QString el = matchAngles.captured(2); - qDebug() << "GS232Protocol::readData read direct angles Az " << az << " El " << el; + //qDebug() << "GS232Protocol::readData read direct angles Az " << az << " El " << el; // The format gives angles in tenths of a degree, so divide by 10 reportAzEl(az.toFloat()/10.0f, el.toFloat()/10.0f); } From 60869b74f96b26e8a173f3f215c2badeaef9a136 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Mon, 21 Apr 2025 10:59:54 +0100 Subject: [PATCH 09/26] Fix build with Qt 6.9.0. --- plugins/channelrx/demodnavtex/navtexdemodsink.cpp | 2 +- plugins/channelrx/remotesink/remotesinksink.cpp | 1 + plugins/channeltx/remotesource/remotesourcesource.cpp | 2 ++ plugins/samplemimo/metismiso/metismisoudphandler.cpp | 2 ++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/channelrx/demodnavtex/navtexdemodsink.cpp b/plugins/channelrx/demodnavtex/navtexdemodsink.cpp index c894dc30b..81a8be5d8 100644 --- a/plugins/channelrx/demodnavtex/navtexdemodsink.cpp +++ b/plugins/channelrx/demodnavtex/navtexdemodsink.cpp @@ -354,7 +354,7 @@ void NavtexDemodSink::receiveBit(bool bit) getMessageQueueToChannel()->push(msg); } // Add character to message buffer - m_messageBuffer.append(QChar(c)); + m_messageBuffer.append(QChar((char) c)); } else { diff --git a/plugins/channelrx/remotesink/remotesinksink.cpp b/plugins/channelrx/remotesink/remotesinksink.cpp index 84b9d31a7..6c9a4d4e9 100644 --- a/plugins/channelrx/remotesink/remotesinksink.cpp +++ b/plugins/channelrx/remotesink/remotesinksink.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include diff --git a/plugins/channeltx/remotesource/remotesourcesource.cpp b/plugins/channeltx/remotesource/remotesourcesource.cpp index 601edf980..05adf7db1 100644 --- a/plugins/channeltx/remotesource/remotesourcesource.cpp +++ b/plugins/channeltx/remotesource/remotesourcesource.cpp @@ -15,6 +15,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include + #include #include diff --git a/plugins/samplemimo/metismiso/metismisoudphandler.cpp b/plugins/samplemimo/metismiso/metismisoudphandler.cpp index 0beb168fb..a42d3eb08 100644 --- a/plugins/samplemimo/metismiso/metismisoudphandler.cpp +++ b/plugins/samplemimo/metismiso/metismisoudphandler.cpp @@ -16,6 +16,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include + #include "dsp/samplemififo.h" #include "dsp/samplemofifo.h" From 77b2b815b8ddf9e66a8962d4dd46d9626c1d2100 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 21 Apr 2025 13:31:12 +0200 Subject: [PATCH 10/26] Replace sprintf by snprintf wherever possible --- ft8/packing.cpp | 26 ++++++++--------- plugins/channelrx/demoddatv/leansdr/dvbs2.h | 9 +++--- plugins/channelrx/demoddatv/leansdr/gui.h | 10 +++---- plugins/channeltx/modpacket/packetmodgui.cpp | 4 +-- plugins/feature/ambe/ambeengine.cpp | 2 +- .../rigctlserver/rigctlserverworker.cpp | 28 +++++++++---------- .../limesdroutput/limesdroutputgui.cpp | 2 +- .../samplesink/usrpoutput/usrpoutputgui.cpp | 2 +- sdrbase/util/serialutil.cpp | 2 +- 9 files changed, 43 insertions(+), 42 deletions(-) diff --git a/ft8/packing.cpp b/ft8/packing.cpp index 30f5ea783..7be99f27d 100644 --- a/ft8/packing.cpp +++ b/ft8/packing.cpp @@ -82,7 +82,7 @@ std::string Packing::unpackcall(int x) if (x <= 1002) { - sprintf(tmp, "CQ %d", x - 3); + snprintf(tmp, sizeof(tmp), "CQ %d", x - 3); return std::string(tmp); } @@ -96,7 +96,7 @@ std::string Packing::unpackcall(int x) int ci3 = x / 27; x %= 27; int ci4 = x; - sprintf(tmp, "CQ %c%c%c%c", c4[ci1], c4[ci2], c4[ci3], c4[ci4]); + snprintf(tmp, sizeof(tmp), "CQ %c%c%c%c", c4[ci1], c4[ci2], c4[ci3], c4[ci4]); return std::string(tmp); } @@ -193,9 +193,9 @@ std::string Packing::unpackgrid15(int ng, int ir) char tmp[16]; if (db >= 0) { - sprintf(tmp, "%s+%02d", ir ? "R" : "", db); + snprintf(tmp, sizeof(tmp), "%s+%02d", ir ? "R" : "", db); } else { - sprintf(tmp, "%s-%02d", ir ? "R" : "", 0 - db); + snprintf(tmp, sizeof(tmp), "%s-%02d", ir ? "R" : "", 0 - db); } return std::string(tmp); @@ -396,7 +396,7 @@ std::string Packing::unpack_5(int a77[], std::string& call1str, std::string& cal i += 3; int qsonb = un64(a77, i, 11); char report[16]; - sprintf(report, "%d%04d", rst, qsonb); + snprintf(report, sizeof(report), "%d%04d", rst, qsonb); i += 11; // g25 int ng = un64(a77, i, 25); @@ -467,9 +467,9 @@ std::string Packing::unpack_0_1(int a77[], std::string& call1str, std::string& c char tmp[32]; if (r >= 0) { - sprintf(tmp, "+%02d", r); + snprintf(tmp, sizeof(tmp), "+%02d", r); } else { - sprintf(tmp, "-%02d", -r); + snprintf(tmp, sizeof(tmp), "-%02d", -r); } locstr = std::string(tmp); @@ -553,7 +553,7 @@ std::string Packing::unpack_3(int a77[], std::string& call1str, std::string& cal else { char tmp[32]; - sprintf(tmp, "%04d", serial); + snprintf(tmp, sizeof(tmp), "%04d", serial); serialstr = std::string(tmp); } @@ -571,7 +571,7 @@ std::string Packing::unpack_3(int a77[], std::string& call1str, std::string& cal } { char tmp[16]; - sprintf(tmp, "%d ", rst); + snprintf(tmp, sizeof(tmp), "%d ", rst); msg += std::string(tmp); } @@ -634,7 +634,7 @@ std::string Packing::unpack_0_3(int a77[], int n3, std::string& call1str, std::s { char tmp[16]; - sprintf(tmp, "%d%c ", n_transmitters + 1, clss + 'A'); + snprintf(tmp, sizeof(tmp), "%d%c ", n_transmitters + 1, clss + 'A'); msg += std::string(tmp); } @@ -658,9 +658,9 @@ std::string Packing::unpack(int a77[], std::string& call1, std::string& call2, s char tmp[64]; if (i3 == 0) { - sprintf(tmp, "%d.%d", i3, n3); + snprintf(tmp, sizeof(tmp), "%d.%d", i3, n3); } else { - sprintf(tmp, "%d", i3); + snprintf(tmp, sizeof(tmp), "%d", i3); } type = std::string(tmp); @@ -714,7 +714,7 @@ std::string Packing::unpack(int a77[], std::string& call1, std::string& call2, s } call1 = "UNK"; - sprintf(tmp, "UNK i3=%d n3=%d", i3, n3); + snprintf(tmp, sizeof(tmp), "UNK i3=%d n3=%d", i3, n3); return std::string(tmp); } diff --git a/plugins/channelrx/demoddatv/leansdr/dvbs2.h b/plugins/channelrx/demoddatv/leansdr/dvbs2.h index 69ad0d315..9c17afec4 100644 --- a/plugins/channelrx/demoddatv/leansdr/dvbs2.h +++ b/plugins/channelrx/demoddatv/leansdr/dvbs2.h @@ -700,8 +700,9 @@ struct s2_frame_receiver : runnable char *format() { static char buf[256]; - sprintf( + snprintf( buf, + sizeof(buf), "%9.2lf %+6.0f ppm %+3.0f ° %f", (double)((p-(std::complex*)NULL)&262143)+mu, // Arbitrary wrap fw16*1e6/65536, @@ -3516,11 +3517,11 @@ struct s2_fecdec_helper : runnable close(rx[0]); dup2(rx[1], 1); char max_trials_arg[16]; - sprintf(max_trials_arg, "%d", max_trials); + snprintf(max_trials_arg, sizeof(max_trial_args), "%d", max_trials); char batch_size_arg[16]; - sprintf(batch_size_arg, "%d", batch_size); + snprintf(batch_size_arg, sizeof(batch_size_args), "%d", batch_size); char mc_arg[16]; - sprintf(mc_arg, "%d", pls->modcod); + snprintf(mc_arg, sizeof(mc_arg), "%d", pls->modcod); const char *sf_arg = pls->sf ? "--shortframes" : nullptr; const char *argv[] = { command, diff --git a/plugins/channelrx/demoddatv/leansdr/gui.h b/plugins/channelrx/demoddatv/leansdr/gui.h index 70f9c914f..00a4f08cd 100644 --- a/plugins/channelrx/demoddatv/leansdr/gui.h +++ b/plugins/channelrx/demoddatv/leansdr/gui.h @@ -368,7 +368,7 @@ struct slowmultiscope : runnable channel *c = &chans[i]; g.setfg(c->spec.rgb[0], c->spec.rgb[1], c->spec.rgb[2]); char text[256]; - sprintf(text, c->spec.format, c->print_val); + snprintf(text, sizeof(text), c->spec.format, c->print_val); g.transient_text(5, 20 + 16 * i, text); } run_gui(); @@ -445,7 +445,7 @@ struct slowmultiscope : runnable float ct = g.mx * samples_per_pixel / sample_freq; float tt = total_samples / sample_freq; char text[256]; - sprintf(text, "%.3f / %.3f s", ct, tt); + snprintf(text, sizeof(text), "%.3f / %.3f s", ct, tt); g.setfg(255, 255, 255); g.transient_text(g.w * 3 / 4, 20, text); } @@ -529,7 +529,7 @@ struct spectrumscope : runnable { char s[256]; float f = 2.4e6 * (g.mx - g.w / 2) / g.w; - sprintf(s, "%f", f); + snprintf(s, sizeof(s), "%f", f); g.text(16, 16, s); } g.show(); @@ -637,7 +637,7 @@ struct rfscope : runnable char s[256]; float freq = Fc + Fs * (g.mx - g.w / 2) / g.w / hzoom; float val = db0 + (float)((g.h - 1) - g.my) * dbrange / g.h; - sprintf(s, "%f.3 Hz %f.2 dB", freq, val); + snprintf(s, sizeof(s), "%f.3 Hz %f.2 dB", freq, val); g.setfg(255, 255, 255); g.text(16, 16, s); } @@ -726,7 +726,7 @@ struct genscope : runnable g.line(pc->spec.r.x - dx, pc->spec.r.y - dy, pc->spec.r.x + dx, pc->spec.r.y + dy); char txt[16]; - sprintf(txt, "%d", (int)last); + snprintf(txt, sizeof(txt), "%d", (int)last); g.text(pc->spec.r.x + 5, pc->spec.r.y - 2, txt); } struct timeval newtv; diff --git a/plugins/channeltx/modpacket/packetmodgui.cpp b/plugins/channeltx/modpacket/packetmodgui.cpp index 8c281ac59..adc634962 100644 --- a/plugins/channeltx/modpacket/packetmodgui.cpp +++ b/plugins/channeltx/modpacket/packetmodgui.cpp @@ -258,8 +258,8 @@ void PacketModGUI::on_insertPosition_clicked() longFrac = round(longitude); // Insert position with house symbol (-) in to data field - sprintf(latBuf, "%02d%02d.%02d%c", latDeg, latMin, latFrac, latNorth ? 'N' : 'S'); - sprintf(longBuf, "%03d%02d.%02d%c", longDeg, longMin, longFrac, longEast ? 'E' : 'W'); + snprintf(latBuf, sizeof(latBuf), "%02d%02d.%02d%c", latDeg, latMin, latFrac, latNorth ? 'N' : 'S'); + snprintf(longBuf, sizeof(longBuf), "%03d%02d.%02d%c", longDeg, longMin, longFrac, longEast ? 'E' : 'W'); QString packet = QString("%1/%2-").arg(latBuf).arg(longBuf); ui->packet->insert(packet); } diff --git a/plugins/feature/ambe/ambeengine.cpp b/plugins/feature/ambe/ambeengine.cpp index 8f0211b85..ca8f66f61 100644 --- a/plugins/feature/ambe/ambeengine.cpp +++ b/plugins/feature/ambe/ambeengine.cpp @@ -75,7 +75,7 @@ void AMBEEngine::getComList() // Arbitrarily set the list to the 20 first COM ports for (int i = 1; i <= 20; i++) { - sprintf(comCStr, "COM%d", i); + snprintf(comCStr, sizeof(comCStr), "COM%d", i); m_comList.push_back(std::string(comCStr)); } } diff --git a/plugins/feature/rigctlserver/rigctlserverworker.cpp b/plugins/feature/rigctlserver/rigctlserverworker.cpp index d772226b1..2b02b2c0d 100644 --- a/plugins/feature/rigctlserver/rigctlserverworker.cpp +++ b/plugins/feature/rigctlserver/rigctlserverworker.cpp @@ -203,7 +203,7 @@ void RigCtlServerWorker::getCommand() // Set frequency double targetFrequency = atof(cmd[0] == 'F' ? &cmd[2] : &cmd[9]); setFrequency(targetFrequency, rigCtlRC); - sprintf(response, "RPRT %d\n", rigCtlRC); + snprintf(response, sizeof(response), "RPRT %d\n", rigCtlRC); } else if (!strncmp(cmd, "f", 1) || !strncmp(cmd, "get_freq", 8)) { @@ -211,9 +211,9 @@ void RigCtlServerWorker::getCommand() double frequency; if (getFrequency(frequency, rigCtlRC)) { - sprintf(response, "%u\n", (unsigned int) frequency); + snprintf(response, sizeof(response), "%u\n", (unsigned int) frequency); } else { - sprintf(response, "RPRT %d\n", rigCtlRC); + snprintf(response, sizeof(response), "RPRT %d\n", rigCtlRC); } } else if (!strncmp(cmd, "M ?", 3) || !(strncmp(cmd, "set_mode ?", 10))) @@ -263,11 +263,11 @@ void RigCtlServerWorker::getCommand() if (m_modeMap[i].modem != nullptr) { changeModem(targetMode, targetModem, targetBW, rigCtlRC); - sprintf(response, "RPRT %d\n", rigCtlRC); + snprintf(response, sizeof(response), "RPRT %d\n", rigCtlRC); } else { - sprintf(response, "RPRT %d\n", RIG_EINVAL); + snprintf(response, sizeof(response), "RPRT %d\n", RIG_EINVAL); m_clientConnection->write(response, strlen(response)); } } @@ -280,27 +280,27 @@ void RigCtlServerWorker::getCommand() if (getMode(&mode, passband, rigCtlRC)) { if (passband < 0) { - sprintf(response, "%s\n", mode); + snprintf(response, sizeof(response), "%s\n", mode); } else { - sprintf(response, "%s %u\n", mode, (unsigned int) passband); + snprintf(response, sizeof(response), "%s %u\n", mode, (unsigned int) passband); } } else { - sprintf(response, "RPRT %d\n", rigCtlRC); + snprintf(response, sizeof(response), "RPRT %d\n", rigCtlRC); } } else if (!strncmp(cmd, "set_powerstat 0", 15)) { // Power off radio setPowerOff(rigCtlRC); - sprintf(response, "RPRT %d\n", rigCtlRC); + snprintf(response, sizeof(response), "RPRT %d\n", rigCtlRC); } else if (!strncmp(cmd, "set_powerstat 1", 15)) { // Power on radio setPowerOn(rigCtlRC); - sprintf(response, "RPRT %d\n", rigCtlRC); + snprintf(response, sizeof(response), "RPRT %d\n", rigCtlRC); } else if (!strncmp(cmd, "get_powerstat", 13)) { @@ -309,20 +309,20 @@ void RigCtlServerWorker::getCommand() if (getPower(power, rigCtlRC)) { if (power) { - sprintf(response, "1\n"); + snprintf(response, sizeof(response), "1\n"); } else { - sprintf(response, "0\n"); + snprintf(response, sizeof(response), "0\n"); } } else { - sprintf(response, "RPRT %d\n", rigCtlRC); + snprintf(response, sizeof(response), "RPRT %d\n", rigCtlRC); } } else { // Unimplemented command - sprintf(response, "RPRT %d\n", RIG_ENIMPL); + snprintf(response, sizeof(response), "RPRT %d\n", RIG_ENIMPL); m_clientConnection->write(response, strlen(response)); } } diff --git a/plugins/samplesink/limesdroutput/limesdroutputgui.cpp b/plugins/samplesink/limesdroutput/limesdroutputgui.cpp index d77b6c0ec..c90d53e96 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputgui.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutputgui.cpp @@ -90,7 +90,7 @@ LimeSDROutputGUI::LimeSDROutputGUI(DeviceUISet *deviceUISet, QWidget* parent) : displaySettings(); char recFileNameCStr[30]; - sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceUISet->m_deviceAPI->getDeviceUID()); + snprintf(recFileNameCStr, sizeof(recFileNameCStr), "test_%d.sdriq", m_deviceUISet->m_deviceAPI->getDeviceUID()); connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); diff --git a/plugins/samplesink/usrpoutput/usrpoutputgui.cpp b/plugins/samplesink/usrpoutput/usrpoutputgui.cpp index 59bce9fd8..98b5e5b17 100644 --- a/plugins/samplesink/usrpoutput/usrpoutputgui.cpp +++ b/plugins/samplesink/usrpoutput/usrpoutputgui.cpp @@ -82,7 +82,7 @@ USRPOutputGUI::USRPOutputGUI(DeviceUISet *deviceUISet, QWidget* parent) : displaySettings(); char recFileNameCStr[30]; - sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceUISet->m_deviceAPI->getDeviceUID()); + snprintf(recFileNameCStr, sizeof(recFileNameCStr), "test_%d.sdriq", m_deviceUISet->m_deviceAPI->getDeviceUID()); connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); diff --git a/sdrbase/util/serialutil.cpp b/sdrbase/util/serialutil.cpp index dd949603f..183718efd 100644 --- a/sdrbase/util/serialutil.cpp +++ b/sdrbase/util/serialutil.cpp @@ -44,7 +44,7 @@ void SerialUtil::getComPorts(std::vector& comPorts, const std::stri for (int i = 0; i<255; i++) // checking ports from COM0 to COM255 { - sprintf(portName, "COM%d", i); + snprintf(portName, sizeof(portName), "COM%d", i); test = QueryDosDeviceA((LPCSTR)portName, (LPSTR)lpTargetPath, 5000); From 1c8d7bdaf17a49271c16242e9df1fa322e71c22e Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 21 Apr 2025 13:33:14 +0200 Subject: [PATCH 11/26] AudioCATSISO: accept ttyS* serial ports for CAT. Fixes #2420 --- plugins/samplemimo/audiocatsiso/audiocatsiso.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/samplemimo/audiocatsiso/audiocatsiso.cpp b/plugins/samplemimo/audiocatsiso/audiocatsiso.cpp index 24429e1a6..2bfe262ff 100644 --- a/plugins/samplemimo/audiocatsiso/audiocatsiso.cpp +++ b/plugins/samplemimo/audiocatsiso/audiocatsiso.cpp @@ -627,7 +627,7 @@ void AudioCATSISO::listComPorts() { m_comPorts.clear(); std::vector comPorts; - SerialUtil::getComPorts(comPorts, "tty(USB|ACM)[0-9]+"); // regex is for Linux only + SerialUtil::getComPorts(comPorts, "tty(S|USB|ACM)[0-9]+"); // regex is for Linux only for (std::vector::const_iterator it = comPorts.begin(); it != comPorts.end(); ++it) { m_comPorts.push_back(QString(it->c_str())); From a5d1f48580a51ce04e74d38c5e3bf466419800a4 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Wed, 23 Apr 2025 08:25:47 +0100 Subject: [PATCH 12/26] Try setup-python: true to fix #2441 --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 14136e65e..be0c0d991 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -70,7 +70,7 @@ jobs: version: '6.7.3' dir: ${{matrix.config.QT_INST_DIR}} arch: ${{matrix.config.QT_ARCH}} - setup-python: false + setup-python: true modules: 'qtcharts qtscxml qt5compat qtlocation qtmultimedia qtpositioning qtserialport qtspeech qtwebsockets qtwebengine qtshadertools qtwebchannel' - name: build sdrangel on Windows if: startsWith(matrix.config.os, 'windows') From 1074bd01055eb25ab206d1f95bed59318c3464f7 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Wed, 23 Apr 2025 08:40:40 +0100 Subject: [PATCH 13/26] Try earlier versions to work around #2441 --- .github/workflows/windows.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index be0c0d991..8197c1aaf 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -71,6 +71,8 @@ jobs: dir: ${{matrix.config.QT_INST_DIR}} arch: ${{matrix.config.QT_ARCH}} setup-python: true + aqtversion: '==3.1.*' + py7zrversion: '==0.20.*' modules: 'qtcharts qtscxml qt5compat qtlocation qtmultimedia qtpositioning qtserialport qtspeech qtwebsockets qtwebengine qtshadertools qtwebchannel' - name: build sdrangel on Windows if: startsWith(matrix.config.os, 'windows') From c108f5be4001ace5cc1240e83fb6c0483e98a500 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Wed, 23 Apr 2025 09:10:24 +0100 Subject: [PATCH 14/26] Try using Python 3.12 instead --- .github/workflows/windows.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 8197c1aaf..166f893ed 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -37,6 +37,9 @@ jobs: echo github.event_name: ${{ github.event_name }} echo github.ref: ${{ github.ref }} echo github.workspace: ${{ github.workspace }} + - uses: actions/setup-python@v5 + with: + python-version: '3.12' - name: Install basic dependencies on Windows if: startsWith(matrix.config.os, 'windows') run: | @@ -70,9 +73,7 @@ jobs: version: '6.7.3' dir: ${{matrix.config.QT_INST_DIR}} arch: ${{matrix.config.QT_ARCH}} - setup-python: true - aqtversion: '==3.1.*' - py7zrversion: '==0.20.*' + setup-python: 'false' modules: 'qtcharts qtscxml qt5compat qtlocation qtmultimedia qtpositioning qtserialport qtspeech qtwebsockets qtwebengine qtshadertools qtwebchannel' - name: build sdrangel on Windows if: startsWith(matrix.config.os, 'windows') From 0111ce247be956a43c5971f9ea4001e9d57603d6 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Wed, 23 Apr 2025 09:20:55 +0100 Subject: [PATCH 15/26] Try Python 3.12 for CI build as well. --- .github/workflows/sdrangel.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/sdrangel.yml b/.github/workflows/sdrangel.yml index 84d54112c..8a2c0e321 100644 --- a/.github/workflows/sdrangel.yml +++ b/.github/workflows/sdrangel.yml @@ -41,6 +41,9 @@ jobs: echo github.event_name: ${{ github.event_name }} echo github.ref: ${{ github.ref }} echo github.workspace: ${{ github.workspace }} + - uses: actions/setup-python@v5 + with: + python-version: '3.12' - name: Install basic dependencies on Windows if: startsWith(matrix.config.os, 'windows') run: | From 379c802d3942679fc29f1cf1b1e368ea1a887e3e Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 2 May 2025 23:57:25 +0200 Subject: [PATCH 16/26] Move datvideorender.h outside datvdemodsink.h --- plugins/channelrx/demoddatv/datvdemodgui.cpp | 1 + plugins/channelrx/demoddatv/datvdemodgui.h | 1 + plugins/channelrx/demoddatv/datvdemodsink.cpp | 1 + plugins/channelrx/demoddatv/datvdemodsink.h | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/channelrx/demoddatv/datvdemodgui.cpp b/plugins/channelrx/demoddatv/datvdemodgui.cpp index cce1efe84..cc0fb5c22 100644 --- a/plugins/channelrx/demoddatv/datvdemodgui.cpp +++ b/plugins/channelrx/demoddatv/datvdemodgui.cpp @@ -37,6 +37,7 @@ #include "maincore.h" #include "ui_datvdemodgui.h" +#include "datvideorender.h" #include "datvdemodreport.h" #include "datvdvbs2ldpcdialog.h" #include "datvdemodgui.h" diff --git a/plugins/channelrx/demoddatv/datvdemodgui.h b/plugins/channelrx/demoddatv/datvdemodgui.h index 0a4780e30..150f367f6 100644 --- a/plugins/channelrx/demoddatv/datvdemodgui.h +++ b/plugins/channelrx/demoddatv/datvdemodgui.h @@ -32,6 +32,7 @@ #include +class DataTSMetaData2; class PluginAPI; class DeviceUISet; class BasebandSampleSink; diff --git a/plugins/channelrx/demoddatv/datvdemodsink.cpp b/plugins/channelrx/demoddatv/datvdemodsink.cpp index 7328bdc8f..d7cb0a520 100644 --- a/plugins/channelrx/demoddatv/datvdemodsink.cpp +++ b/plugins/channelrx/demoddatv/datvdemodsink.cpp @@ -17,6 +17,7 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include "datvideorender.h" #include "datvdemodsink.h" #include "leansdr/dvbs2.h" diff --git a/plugins/channelrx/demoddatv/datvdemodsink.h b/plugins/channelrx/demoddatv/datvdemodsink.h index b56cb6531..f75f4417b 100644 --- a/plugins/channelrx/demoddatv/datvdemodsink.h +++ b/plugins/channelrx/demoddatv/datvdemodsink.h @@ -36,7 +36,6 @@ #include "datvvideoplayer.h" #include "datvideostream.h" #include "datvudpstream.h" -#include "datvideorender.h" #include "datvdemodsettings.h" #include "dsp/channelsamplesink.h" @@ -50,6 +49,7 @@ class TVScreen; class DATVideoRender; +class DATVideoRenderThread; class QLabel; class DATVDemodSink : public ChannelSampleSink { From ab54ac7a63839d276ff3fbb8c8b506b27895d338 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 3 May 2025 01:43:35 +0200 Subject: [PATCH 17/26] DATV demod: prepare for server version --- plugins/channelrx/demoddatv/CMakeLists.txt | 43 ++++++++++++------- plugins/channelrx/demoddatv/datvdemodsink.cpp | 23 ++++++---- plugins/channelrx/demoddatv/datvdemodsink.h | 6 ++- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/plugins/channelrx/demoddatv/CMakeLists.txt b/plugins/channelrx/demoddatv/CMakeLists.txt index 627bdd694..421ac2b0a 100644 --- a/plugins/channelrx/demoddatv/CMakeLists.txt +++ b/plugins/channelrx/demoddatv/CMakeLists.txt @@ -3,17 +3,14 @@ project(datv) set(datv_SOURCES datvdemod.cpp - datvdemodgui.cpp datvdemodplugin.cpp datvdemodsettings.cpp datvdemodwebapiadapter.cpp datvideostream.cpp datvudpstream.cpp - datvideorender.cpp datvdemodreport.cpp datvdemodsink.cpp datvdemodbaseband.cpp - datvdvbs2ldpcdialog.cpp leansdr/dvb.cpp leansdr/filtergen.cpp leansdr/framework.cpp @@ -30,19 +27,14 @@ set(ldpc_SOURCES set(datv_HEADERS datvdemod.h - datvdemodgui.h datvdemodplugin.h datvdemodsettings.h datvdemodwebapiadapter.h datvideostream.h datvudpstream.h - datvideorender.h - datvconstellation.h - datvdvbs2constellation.h datvdemodreport.h datvdemodsink.h datvdemodbaseband.h - datvdvbs2ldpcdialog.h leansdr/dvb.h leansdr/dvbs2.h leansdr/filtergen.h @@ -59,6 +51,31 @@ set(ldpc_HEADERS ldpctool/ldpcworker.h ) +if(NOT SERVER_MODE) + set(datv_SOURCES + ${datv_SOURCES} + datvdemodgui.ui + datvdvbs2ldpcdialog.ui + datvideorender.cpp + ) + set(datv_HEADERS ${datv_HEADERS} + datvdemodgui.h + datvdvbs2ldpcdialog.h + datvideorender.h + datvconstellation.h + datvdvbs2constellation.h + ) + set(TARGET_NAME ${PLUGINS_PREFIX}demoddatv) + set(TARGET_LIB Qt::Widgets Qt::Multimedia Qt::MultimediaWidgets) + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME ${PLUGINSSRV_PREFIX}demoddatvsrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + include_directories( ${AVCODEC_INCLUDE_DIRS} ${AVFORMAT_INCLUDE_DIRS} @@ -68,10 +85,6 @@ include_directories( ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client ) -set(TARGET_NAME ${PLUGINS_PREFIX}demoddatv) -set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) - - if(NOT Qt6_FOUND) add_library(${TARGET_NAME} ${datv_SOURCES} ${ldpc_SOURCES}) else() @@ -84,11 +97,9 @@ endif() target_link_libraries(${TARGET_NAME} PRIVATE Qt::Core - Qt::Widgets - Qt::Multimedia - Qt::MultimediaWidgets + ${TARGET_LIB} sdrbase - sdrgui + ${TARGET_LIB_GUI} ${AVCODEC_LIBRARIES} ${AVFORMAT_LIBRARIES} ${AVUTIL_LIBRARIES} diff --git a/plugins/channelrx/demoddatv/datvdemodsink.cpp b/plugins/channelrx/demoddatv/datvdemodsink.cpp index d7cb0a520..10d7a65ac 100644 --- a/plugins/channelrx/demoddatv/datvdemodsink.cpp +++ b/plugins/channelrx/demoddatv/datvdemodsink.cpp @@ -342,10 +342,11 @@ void DATVDemodSink::CleanUpDATVFramework() } //CONSTELLATION +#ifndef SERVER_MODE if (r_scope_symbols != nullptr) { delete r_scope_symbols; } - +#endif // INPUT if (p_rawiq != nullptr) { delete p_rawiq; @@ -406,11 +407,11 @@ void DATVDemodSink::CleanUpDATVFramework() if (p_deframer != nullptr) { delete (leansdr::s2_deframer*) p_deframer; } - +#ifndef SERVER_MODE if (r_scope_symbols_dvbs2 != nullptr) { delete r_scope_symbols_dvbs2; } - +#endif ResetDATVFrameworkPointers(); } @@ -499,7 +500,9 @@ void DATVDemodSink::ResetDATVFrameworkPointers() r_videoplayer = nullptr; //CONSTELLATION +#ifndef SERVER_MODE r_scope_symbols = nullptr; +#endif //DVB-S2 p_slots_dvbs2 = nullptr; @@ -514,7 +517,9 @@ void DATVDemodSink::ResetDATVFrameworkPointers() r_fecdecsoft = nullptr; r_fecdechelper = nullptr; p_deframer = nullptr; +#ifndef SERVER_MODE r_scope_symbols_dvbs2 = nullptr; +#endif } void DATVDemodSink::InitDATVFramework() @@ -762,7 +767,7 @@ void DATVDemodSink::InitDATVFramework() } //constellation - +#ifndef SERVER_MODE if (m_tvScreen) { qDebug("DATVDemodSink::InitDATVFramework: Register DVB constellation TV screen"); @@ -772,7 +777,7 @@ void DATVDemodSink::InitDATVFramework() r_scope_symbols->cstln = &m_objDemodulator->cstln; r_scope_symbols->calculate_cstln_points(); } - +#endif r_merMeter = new leansdr::datvmeter(m_objScheduler, *p_mer); r_cnrMeter = new leansdr::datvmeter(m_objScheduler, *p_cnr); @@ -1068,7 +1073,7 @@ void DATVDemodSink::InitDATVS2Framework() m_cstlnSetByModcod = false; //constellation - +#ifndef SERVER_MODE if (m_tvScreen) { qDebug("DATVDemodSink::InitDATVS2Framework: Register DVBS 2 TVSCREEN"); @@ -1077,7 +1082,7 @@ void DATVDemodSink::InitDATVS2Framework() r_scope_symbols_dvbs2->cstln = (leansdr::cstln_base**) &objDemodulatorDVBS2->cstln; r_scope_symbols_dvbs2->calculate_cstln_points(); } - +#endif r_merMeter = new leansdr::datvmeter(m_objScheduler, *p_mer); r_cnrMeter = new leansdr::datvmeter(m_objScheduler, *p_cnr); @@ -1206,10 +1211,12 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample { qDebug("DATVDemodSink::feed: change by MODCOD detected"); + // Update constellation +#ifndef SERVER_MODE if (r_scope_symbols_dvbs2) { r_scope_symbols_dvbs2->calculate_cstln_points(); } - +#endif if (getMessageQueueToGUI()) { DATVDemodReport::MsgReportModcodCstlnChange *msg = DATVDemodReport::MsgReportModcodCstlnChange::create( diff --git a/plugins/channelrx/demoddatv/datvdemodsink.h b/plugins/channelrx/demoddatv/datvdemodsink.h index f75f4417b..7670b1c9e 100644 --- a/plugins/channelrx/demoddatv/datvdemodsink.h +++ b/plugins/channelrx/demoddatv/datvdemodsink.h @@ -30,9 +30,11 @@ #include "leansdr/hdlc.h" #include "leansdr/iess.h" +#ifndef SERVER_MODE #include "datvconstellation.h" -#include "datvmeter.h" #include "datvdvbs2constellation.h" +#endif +#include "datvmeter.h" #include "datvvideoplayer.h" #include "datvideostream.h" #include "datvudpstream.h" @@ -314,8 +316,10 @@ private: leansdr::datvvideoplayer *r_videoplayer; //CONSTELLATION +#ifndef SERVER_MODE leansdr::datvconstellation *r_scope_symbols; leansdr::datvdvbs2constellation *r_scope_symbols_dvbs2; +#endif leansdr::datvmeter *r_merMeter; leansdr::datvmeter *r_cnrMeter; From fc82606e6ea139a015226041f0420282ee381a74 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 3 May 2025 02:38:48 +0200 Subject: [PATCH 18/26] DATV demod: completely remove LDPC external command references --- plugins/channelrx/demoddatv/CMakeLists.txt | 12 ++-- plugins/channelrx/demoddatv/datvdemod.cpp | 16 ----- plugins/channelrx/demoddatv/datvdemodgui.cpp | 2 - .../channelrx/demoddatv/datvdemodsettings.cpp | 11 ---- .../channelrx/demoddatv/datvdemodsettings.h | 1 - plugins/channelrx/demoddatv/datvdemodsink.cpp | 12 +--- .../demoddatv/datvdvbs2ldpcdialog.cpp | 31 --------- .../channelrx/demoddatv/datvdvbs2ldpcdialog.h | 4 -- .../demoddatv/datvdvbs2ldpcdialog.ui | 64 +------------------ plugins/channelrx/demoddatv/leansdr/dvbs2.h | 3 - plugins/channelrx/demoddatv/readme.md | 2 +- 11 files changed, 8 insertions(+), 150 deletions(-) diff --git a/plugins/channelrx/demoddatv/CMakeLists.txt b/plugins/channelrx/demoddatv/CMakeLists.txt index 421ac2b0a..100fab375 100644 --- a/plugins/channelrx/demoddatv/CMakeLists.txt +++ b/plugins/channelrx/demoddatv/CMakeLists.txt @@ -56,15 +56,17 @@ if(NOT SERVER_MODE) ${datv_SOURCES} datvdemodgui.ui datvdvbs2ldpcdialog.ui + datvdemodgui.cpp + datvdvbs2ldpcdialog.cpp datvideorender.cpp ) set(datv_HEADERS ${datv_HEADERS} datvdemodgui.h datvdvbs2ldpcdialog.h - datvideorender.h datvconstellation.h datvdvbs2constellation.h - ) + datvideorender.h + ) set(TARGET_NAME ${PLUGINS_PREFIX}demoddatv) set(TARGET_LIB Qt::Widgets Qt::Multimedia Qt::MultimediaWidgets) set(TARGET_LIB_GUI "sdrgui") @@ -107,12 +109,6 @@ target_link_libraries(${TARGET_NAME} PRIVATE ${SWRESAMPLE_LIBRARIES} ) -add_executable(ldpctool - ldpctool/ldpc_tool.cpp - ldpctool/tables_handler.cpp -) -install(TARGETS ldpctool DESTINATION ${INSTALL_BIN_DIR}) - if(DEFINED FFMPEG_DEPENDS) add_dependencies(${TARGET_NAME} ${FFMPEG_DEPENDS}) endif() diff --git a/plugins/channelrx/demoddatv/datvdemod.cpp b/plugins/channelrx/demoddatv/datvdemod.cpp index b6fa69e1b..78fb44057 100644 --- a/plugins/channelrx/demoddatv/datvdemod.cpp +++ b/plugins/channelrx/demoddatv/datvdemod.cpp @@ -212,9 +212,6 @@ void DATVDemod::applySettings(const DATVDemodSettings& settings, bool force) if (settings.m_softLDPC != m_settings.m_softLDPC) { reverseAPIKeys.append("softLDPC"); } - if (settings.m_softLDPCToolPath != m_settings.m_softLDPCToolPath) { - reverseAPIKeys.append("softLDPCToolPath"); - } if (settings.m_softLDPCMaxTrials != m_settings.m_softLDPCMaxTrials) { reverseAPIKeys.append("softLDPCMaxTrials"); } @@ -401,9 +398,6 @@ void DATVDemod::webapiUpdateChannelSettings( if (channelSettingsKeys.contains("softLDPC")) { settings.m_softLDPC = response.getDatvDemodSettings()->getSoftLdpc() == 1; } - if (channelSettingsKeys.contains("softLDPCToolPath")) { - settings.m_softLDPCToolPath = *response.getDatvDemodSettings()->getSoftLdpcToolPath(); - } if (channelSettingsKeys.contains("softLDPCMaxTrials")) { settings.m_softLDPCMaxTrials = response.getDatvDemodSettings()->getSoftLdpcMaxTrials(); } @@ -503,13 +497,6 @@ void DATVDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& res response.getDatvDemodSettings()->setModulation((int) settings.m_modulation); response.getDatvDemodSettings()->setFec((int) settings.m_fec); response.getDatvDemodSettings()->setSoftLdpc((int) settings.m_softLDPC ? 1 : 0); - - if (response.getDatvDemodSettings()->getSoftLdpcToolPath()) { - *response.getDatvDemodSettings()->getSoftLdpcToolPath() = settings.m_softLDPCToolPath; - } else { - response.getDatvDemodSettings()->setSoftLdpcToolPath(new QString(settings.m_softLDPCToolPath)); - } - response.getDatvDemodSettings()->setSoftLdpcMaxTrials(settings.m_softLDPCMaxTrials); response.getDatvDemodSettings()->setMaxBitflips(settings.m_maxBitflips); response.getDatvDemodSettings()->setAudioMute(settings.m_audioMute ? 1 : 0); @@ -664,9 +651,6 @@ void DATVDemod::webapiFormatChannelSettings( if (channelSettingsKeys.contains("softLDPC") || force) { swgDATVDemodSettings->setSoftLdpc(settings.m_softLDPC ? 1 : 0); } - if (channelSettingsKeys.contains("softLDPCToolPath") || force) { - swgDATVDemodSettings->setSoftLdpcToolPath(new QString(settings.m_softLDPCToolPath)); - } if (channelSettingsKeys.contains("softLDPCMaxTrials") || force) { swgDATVDemodSettings->setSoftLdpcMaxTrials(settings.m_softLDPCMaxTrials); } diff --git a/plugins/channelrx/demoddatv/datvdemodgui.cpp b/plugins/channelrx/demoddatv/datvdemodgui.cpp index cc0fb5c22..6fa1805f0 100644 --- a/plugins/channelrx/demoddatv/datvdemodgui.cpp +++ b/plugins/channelrx/demoddatv/datvdemodgui.cpp @@ -532,14 +532,12 @@ void DATVDemodGUI::ldpcToolSelect(const QPoint& p) { qDebug("DATVDemodGUI::ldpcToolSelect"); DatvDvbS2LdpcDialog ldpcDialog; - ldpcDialog.setFileName(m_settings.m_softLDPCToolPath); ldpcDialog.setMaxTrials(m_settings.m_softLDPCMaxTrials); ldpcDialog.move(p); if (ldpcDialog.exec() == QDialog::Accepted) { m_settings.m_softLDPCMaxTrials = ldpcDialog.getMaxTrials(); - m_settings.m_softLDPCToolPath = ldpcDialog.getFileName(); applySettings(); } } diff --git a/plugins/channelrx/demoddatv/datvdemodsettings.cpp b/plugins/channelrx/demoddatv/datvdemodsettings.cpp index b9179e7d3..73b9d5d26 100644 --- a/plugins/channelrx/demoddatv/datvdemodsettings.cpp +++ b/plugins/channelrx/demoddatv/datvdemodsettings.cpp @@ -28,12 +28,6 @@ #include "datvdemodsettings.h" -#ifdef _MSC_VER -#define DEFAULT_LDPCTOOLPATH "C:/Program Files/SDRangel/ldpctool.exe" -#else -#define DEFAULT_LDPCTOOLPATH "/opt/install/sdrangel/bin/ldpctool" -#endif - DATVDemodSettings::DATVDemodSettings() : m_channelMarker(nullptr), m_rollupState(nullptr) @@ -51,7 +45,6 @@ void DATVDemodSettings::resetToDefaults() m_modulation = BPSK; m_fec = FEC12; m_softLDPC = false; - m_softLDPCToolPath = DEFAULT_LDPCTOOLPATH; m_softLDPCMaxTrials = 8; m_maxBitflips = 0; m_symbolRate = 250000; @@ -120,7 +113,6 @@ QByteArray DATVDemodSettings::serialize() const s.writeU32(31, m_reverseAPIChannelIndex); s.writeBool(32, m_softLDPC); s.writeS32(33, m_maxBitflips); - s.writeString(34, m_softLDPCToolPath); s.writeS32(35, m_softLDPCMaxTrials); s.writeBool(36, m_playerEnable); @@ -215,7 +207,6 @@ bool DATVDemodSettings::deserialize(const QByteArray& data) d.readBool(32, &m_softLDPC, false); d.readS32(33, &m_maxBitflips, 0); - d.readString(34, &m_softLDPCToolPath, DEFAULT_LDPCTOOLPATH); d.readS32(35, &tmp, 8); m_softLDPCMaxTrials = tmp < 1 ? 1 : tmp > m_softLDPCMaxMaxTrials ? m_softLDPCMaxMaxTrials : tmp; d.readBool(36, &m_playerEnable, true); @@ -256,7 +247,6 @@ void DATVDemodSettings::debug(const QString& msg) const << " m_fec: " << m_fec << " m_softLDPC: " << m_softLDPC << " m_softLDPCMaxTrials: " << m_softLDPCMaxTrials - << " m_softLDPCToolPath: " << m_softLDPCToolPath << " m_maxBitflips: " << m_maxBitflips << " m_modulation: " << m_modulation << " m_standard: " << m_standard @@ -284,7 +274,6 @@ bool DATVDemodSettings::isDifferent(const DATVDemodSettings& other) || (m_fec != other.m_fec) || (m_softLDPC != other.m_softLDPC) || (m_softLDPCMaxTrials != other.m_softLDPCMaxTrials) - || (m_softLDPCToolPath != other.m_softLDPCToolPath) || (m_maxBitflips != other.m_maxBitflips) || (m_modulation != other.m_modulation) || (m_notchFilters != other.m_notchFilters) diff --git a/plugins/channelrx/demoddatv/datvdemodsettings.h b/plugins/channelrx/demoddatv/datvdemodsettings.h index 301145caf..1d646bf01 100644 --- a/plugins/channelrx/demoddatv/datvdemodsettings.h +++ b/plugins/channelrx/demoddatv/datvdemodsettings.h @@ -84,7 +84,6 @@ struct DATVDemodSettings DATVModulation m_modulation; DATVCodeRate m_fec; bool m_softLDPC; - QString m_softLDPCToolPath; int m_softLDPCMaxTrials; int m_maxBitflips; bool m_audioMute; diff --git a/plugins/channelrx/demoddatv/datvdemodsink.cpp b/plugins/channelrx/demoddatv/datvdemodsink.cpp index 10d7a65ac..b2c4acdb2 100644 --- a/plugins/channelrx/demoddatv/datvdemodsink.cpp +++ b/plugins/channelrx/demoddatv/datvdemodsink.cpp @@ -879,8 +879,7 @@ void DATVDemodSink::InitDATVS2Framework() << " Excursion: " << m_settings.m_excursion << " Channel sample rate: " << m_channelSampleRate << " Input sample rate: " << 2 * m_settings.m_symbolRate - << " m_softLDPCMaxTrials: " << m_settings.m_softLDPCMaxTrials - << " m_softLDPCToolPath: " << m_settings.m_softLDPCToolPath; + << " m_softLDPCMaxTrials: " << m_settings.m_softLDPCMaxTrials; m_objCfg.standard = m_settings.m_standard; @@ -1104,12 +1103,6 @@ void DATVDemodSink::InitDATVS2Framework() // bool commandFileValid = false; - if (QFileInfo::exists(m_settings.m_softLDPCToolPath)) - { - QFileInfo fileInfo = QFileInfo(m_settings.m_softLDPCToolPath); - // commandFileValid = fileInfo.isExecutable(); - } - if (m_settings.m_softLDPC /*&& commandFileValid*/) { #if 0 @@ -1134,8 +1127,6 @@ void DATVDemodSink::InitDATVS2Framework() // External LDPC decoder mode. // Deinterleave into soft bits. // TBD Latency - QByteArray ba = m_settings.m_softLDPCToolPath.toLocal8Bit(); - const char *c_str2 = ba.data(); p_fecframes = new leansdr::pipebuf >(m_objScheduler, "FEC frames", BUF_FRAMES); p_s2_deinterleaver = new leansdr::s2_deinterleaver( m_objScheduler, @@ -1147,7 +1138,6 @@ void DATVDemodSink::InitDATVS2Framework() m_objScheduler, *(leansdr::pipebuf< leansdr::fecframe > *) p_fecframes, *(leansdr::pipebuf *) p_bbframes, - c_str2, p_vbitcount, p_verrcount) ; diff --git a/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.cpp b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.cpp index 33cf263f6..79bae70e3 100644 --- a/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.cpp +++ b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.cpp @@ -42,12 +42,6 @@ void DatvDvbS2LdpcDialog::accept() QDialog::accept(); } -void DatvDvbS2LdpcDialog::setFileName(const QString& fileName) -{ - m_fileName = fileName; - ui->ldpcToolText->setText(m_fileName); -} - void DatvDvbS2LdpcDialog::setMaxTrials(int maxTrials) { m_maxTrials = maxTrials < 1 ? 1 : @@ -55,31 +49,6 @@ void DatvDvbS2LdpcDialog::setMaxTrials(int maxTrials) ui->maxTrials->setValue(m_maxTrials); } -void DatvDvbS2LdpcDialog::on_showFileDialog_clicked(bool checked) -{ - (void) checked; - - QFileDialog fileDialog(this, "Select LDPC tool"); - fileDialog.setOption(QFileDialog::DontUseNativeDialog, true); -#ifdef _MSC_VER - fileDialog.setNameFilter("*.exe"); -#else - fileDialog.setFilter(QDir::Executable | QDir::Files); -#endif - fileDialog.selectFile(m_fileName); - - if (fileDialog.exec() == QDialog::Accepted) - { - QStringList fileNames = fileDialog.selectedFiles(); - - if (fileNames.size() > 0) - { - m_fileName = fileNames[0]; - ui->ldpcToolText->setText(m_fileName); - } - } -} - void DatvDvbS2LdpcDialog::on_maxTrials_valueChanged(int value) { m_maxTrials = value; diff --git a/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.h b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.h index 91745ab17..26a2f3865 100644 --- a/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.h +++ b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.h @@ -33,19 +33,15 @@ public: explicit DatvDvbS2LdpcDialog(QWidget* parent = nullptr); ~DatvDvbS2LdpcDialog(); - void setFileName(const QString& fileName); void setMaxTrials(int maxTrials); - QString& getFileName() { return m_fileName; } int getMaxTrials() { return m_maxTrials; } private: Ui::DatvDvbS2LdpcDialog* ui; - QString m_fileName; int m_maxTrials; private slots: void accept(); - void on_showFileDialog_clicked(bool checked); void on_maxTrials_valueChanged(int value); }; diff --git a/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.ui b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.ui index 52244ce03..753c9b954 100644 --- a/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.ui +++ b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.ui @@ -6,8 +6,8 @@ 0 0 - 461 - 121 + 454 + 80 @@ -63,66 +63,6 @@ - - - - - - LDPC tool - - - - - - - - 24 - 16777215 - - - - Choose a log file - - - - - - - :/preset-load.png:/preset-load.png - - - - - - - - 300 - 0 - - - - Log file - - - ... - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - diff --git a/plugins/channelrx/demoddatv/leansdr/dvbs2.h b/plugins/channelrx/demoddatv/leansdr/dvbs2.h index 9c17afec4..ee4b59830 100644 --- a/plugins/channelrx/demoddatv/leansdr/dvbs2.h +++ b/plugins/channelrx/demoddatv/leansdr/dvbs2.h @@ -3644,7 +3644,6 @@ struct s2_fecdec_helper : runnable scheduler *sch, pipebuf> &_in, pipebuf &_out, - const char *_command, pipebuf *_bitcount = nullptr, pipebuf *_errcount = nullptr ) : @@ -3658,7 +3657,6 @@ struct s2_fecdec_helper : runnable bitcount(opt_writer(_bitcount, 1)), errcount(opt_writer(_errcount, 1)) { - command = strdup(_command); for (int mc = 0; mc < 32; ++mc) { for (int sf = 0; sf < 2; ++sf) { @@ -3669,7 +3667,6 @@ struct s2_fecdec_helper : runnable ~s2_fecdec_helper() { - free(command); killall(); // also deletes pools[mc][sf].procs if necessary } diff --git a/plugins/channelrx/demoddatv/readme.md b/plugins/channelrx/demoddatv/readme.md index 957c51a25..783d006a9 100644 --- a/plugins/channelrx/demoddatv/readme.md +++ b/plugins/channelrx/demoddatv/readme.md @@ -191,7 +191,7 @@ It can be used to decode signals lower that ~10 db MER which is the limit of LDP Right clicking on this control opens a dialog where you can choose: - - The `ldpctool` executable. Obsolete. + - ~~The `ldpctool` executable.~~ Obsolete removed. - The maximum of retries in LDPC decoding from 1 to 8.
B.2b.7: DVB-S2 specific - LDPC maximum number of bit flips allowed
From ce007419e8c2493751e7b654e226fac8fe0fd0c6 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 3 May 2025 04:29:19 +0200 Subject: [PATCH 19/26] DATV demod server plugin --- plugins/channelrx/CMakeLists.txt | 41 ++-- .../channelrx/demoddatv/datvconstellation.h | 78 ------- plugins/channelrx/demoddatv/datvcstlnlut.h | 194 ++++++++++++++++++ .../channelrx/demoddatv/datvdemodplugin.cpp | 15 +- plugins/channelrx/demoddatv/datvdemodsink.cpp | 30 ++- .../demoddatv/datvdvbs2constellation.h | 82 -------- sdrbase/resources/webapi/doc/html2/index.html | 9 +- .../webapi/doc/swagger/include/DATVDemod.yaml | 3 - .../webapi/doc/swagger/include/LimeSdr.yaml | 2 + .../api/swagger/include/DATVDemod.yaml | 3 - swagger/sdrangel/code/html2/index.html | 9 +- .../code/qt5/client/SWGDATVDemodSettings.cpp | 25 --- .../code/qt5/client/SWGDATVDemodSettings.h | 6 - .../qt5/client/SWGLimeSdrInputSettings.cpp | 27 +-- .../code/qt5/client/SWGLimeSdrInputSettings.h | 8 +- 15 files changed, 285 insertions(+), 247 deletions(-) create mode 100644 plugins/channelrx/demoddatv/datvcstlnlut.h diff --git a/plugins/channelrx/CMakeLists.txt b/plugins/channelrx/CMakeLists.txt index 5d8a3aa3d..3b9f2129b 100644 --- a/plugins/channelrx/CMakeLists.txt +++ b/plugins/channelrx/CMakeLists.txt @@ -211,6 +211,26 @@ else() message(STATUS "Not building wdsprx (ENABLE_CHANNELRX_WDSPRX=${ENABLE_CHANNELRX_WDSPRX} WDSP_SUPPORT=${WDSP_SUPPORT})") endif() +# need ffmpeg 3.1 that correstonds to +# libavutil 55.27.100 +# libavcodec 57.48.101 +# libavformat 57.40.101 +find_package(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) + +if (ENABLE_CHANNELRX_DEMODDATV AND FFMPEG_FOUND) + if(WIN32) + add_subdirectory(demoddatv) + else() + if(((AVUTIL_VERSION VERSION_GREATER "55.27.99") AND (AVCODEC_VERSION VERSION_GREATER "57.48.101")) OR FFMPEG_EXTERNAL OR FFMPEG_SKIP_CHECK) + message(STATUS "Include demoddatv") + add_subdirectory(demoddatv) + else() + message(STATUS "FFmpeg too old to compile demoddatv; needs at least avutil: 55.27.100, avcodec/avformat: 57.48.101") + endif() + endif() +else() + message(STATUS "Not building demoddatv (ENABLE_CHANNELRX_DEMODDATV=${ENABLE_CHANNELRX_DEMODDATV} FFMPEG_FOUND=${FFMPEG_FOUND})") +endif() if(NOT SERVER_MODE) if (ENABLE_CHANNELRX_HEATMAP) @@ -230,25 +250,4 @@ if(NOT SERVER_MODE) else() message(STATUS "Not building demodatv (ENABLE_CHANNELRX_DEMODATV=${ENABLE_CHANNELRX_DEMODATV})") endif() - - # need ffmpeg 3.1 that correstonds to - # libavutil 55.27.100 - # libavcodec 57.48.101 - # libavformat 57.40.101 - find_package(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) - - if (ENABLE_CHANNELRX_DEMODDATV AND FFMPEG_FOUND) - if(WIN32) - add_subdirectory(demoddatv) - else() - if(((AVUTIL_VERSION VERSION_GREATER "55.27.99") AND (AVCODEC_VERSION VERSION_GREATER "57.48.101")) OR FFMPEG_EXTERNAL OR FFMPEG_SKIP_CHECK) - message(STATUS "Include demoddatv") - add_subdirectory(demoddatv) - else() - message(STATUS "FFmpeg too old to compile demoddatv; needs at least avutil: 55.27.100, avcodec/avformat: 57.48.101") - endif() - endif() - else() - message(STATUS "Not building demoddatv (ENABLE_CHANNELRX_DEMODDATV=${ENABLE_CHANNELRX_DEMODDATV} FFMPEG_FOUND=${FFMPEG_FOUND})") - endif() endif() diff --git a/plugins/channelrx/demoddatv/datvconstellation.h b/plugins/channelrx/demoddatv/datvconstellation.h index 3b4838cad..5beefede9 100644 --- a/plugins/channelrx/demoddatv/datvconstellation.h +++ b/plugins/channelrx/demoddatv/datvconstellation.h @@ -31,84 +31,6 @@ namespace leansdr { static const int DEFAULT_GUI_DECIMATION = 64; -static inline cstln_lut * make_dvbs_constellation(cstln_lut::predef c, - code_rate r) -{ - float gamma1 = 1, gamma2 = 1, gamma3 = 1; - switch (c) - { - case cstln_lut::APSK16: - // EN 302 307, section 5.4.3, Table 9 - switch (r) - { - case FEC23: - case FEC46: - gamma1 = 3.15; - break; - case FEC34: - gamma1 = 2.85; - break; - case FEC45: - gamma1 = 2.75; - break; - case FEC56: - gamma1 = 2.70; - break; - case FEC89: - gamma1 = 2.60; - break; - case FEC910: - gamma1 = 2.57; - break; - default: - fail("cstln_lut<256>::make_dvbs_constellation: Code rate not supported with APSK16"); - return 0; - } - break; - case cstln_lut::APSK32: - // EN 302 307, section 5.4.4, Table 10 - switch (r) - { - case FEC34: - gamma1 = 2.84; - gamma2 = 5.27; - break; - case FEC45: - gamma1 = 2.72; - gamma2 = 4.87; - break; - case FEC56: - gamma1 = 2.64; - gamma2 = 4.64; - break; - case FEC89: - gamma1 = 2.54; - gamma2 = 4.33; - break; - case FEC910: - gamma1 = 2.53; - gamma2 = 4.30; - break; - default: - fail("cstln_lut::make_dvbs_constellation: Code rate not supported with APSK32"); - return 0; - } - break; - case cstln_lut::APSK64E: - // EN 302 307-2, section 5.4.5, Table 13f - gamma1 = 2.4; - gamma2 = 4.3; - gamma3 = 7; - break; - default: - break; - } - cstln_lut *newCstln = new cstln_lut(c, 10, gamma1, gamma2, gamma3); - newCstln->m_rateCode = (int) r; - newCstln->m_typeCode = (int) c; - newCstln->m_setByModcod = false; - return newCstln; -} template struct datvconstellation: runnable { diff --git a/plugins/channelrx/demoddatv/datvcstlnlut.h b/plugins/channelrx/demoddatv/datvcstlnlut.h new file mode 100644 index 000000000..ac9888398 --- /dev/null +++ b/plugins/channelrx/demoddatv/datvcstlnlut.h @@ -0,0 +1,194 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2025 Edouard Griffiths, F4EXB // +// using LeanSDR Framework (C) 2016 F4DAV // +// // +// 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 DATV_CSTLN_LUT_H +#define DATV_CSTLN_LUT_H + +#include "leansdr/dvb.h" +#include "leansdr/framework.h" + +namespace leansdr { + +static cstln_lut * make_dvbs_constellation( + cstln_lut::predef c, + code_rate r +) +{ + float gamma1 = 1, gamma2 = 1, gamma3 = 1; + + switch (c) + { + case cstln_lut::APSK16: + // EN 302 307, section 5.4.3, Table 9 + switch (r) + { + case FEC23: + case FEC46: + gamma1 = 3.15; + break; + case FEC34: + gamma1 = 2.85; + break; + case FEC45: + gamma1 = 2.75; + break; + case FEC56: + gamma1 = 2.70; + break; + case FEC89: + gamma1 = 2.60; + break; + case FEC910: + gamma1 = 2.57; + break; + default: + fail("cstln_lut<256>::make_dvbs_constellation: Code rate not supported with APSK16"); + return 0; + } + break; + case cstln_lut::APSK32: + // EN 302 307, section 5.4.4, Table 10 + switch (r) + { + case FEC34: + gamma1 = 2.84; + gamma2 = 5.27; + break; + case FEC45: + gamma1 = 2.72; + gamma2 = 4.87; + break; + case FEC56: + gamma1 = 2.64; + gamma2 = 4.64; + break; + case FEC89: + gamma1 = 2.54; + gamma2 = 4.33; + break; + case FEC910: + gamma1 = 2.53; + gamma2 = 4.30; + break; + default: + fail("cstln_lut::make_dvbs_constellation: Code rate not supported with APSK32"); + return 0; + } + break; + case cstln_lut::APSK64E: + // EN 302 307-2, section 5.4.5, Table 13f + gamma1 = 2.4; + gamma2 = 4.3; + gamma3 = 7; + break; + default: + break; + } + cstln_lut *newCstln = new cstln_lut(c, 10, gamma1, gamma2, gamma3); + newCstln->m_rateCode = (int) r; + newCstln->m_typeCode = (int) c; + newCstln->m_setByModcod = false; + return newCstln; +} + +static cstln_lut * make_dvbs2_constellation( + cstln_lut::predef c, + code_rate r +) +{ + float gamma1 = 1, gamma2 = 1, gamma3 = 1; + + switch (c) + { + case cstln_lut::APSK16: + // EN 302 307, section 5.4.3, Table 9 + switch (r) + { + case FEC23: + case FEC46: + gamma1 = 3.15; + break; + case FEC34: + gamma1 = 2.85; + break; + case FEC45: + gamma1 = 2.75; + break; + case FEC56: + gamma1 = 2.70; + break; + case FEC89: + gamma1 = 2.60; + break; + case FEC910: + gamma1 = 2.57; + break; + default: + fail("cstln_lut<256>::make_dvbs2_constellation: Code rate not supported with APSK16"); + return 0; + } + break; + case cstln_lut::APSK32: + // EN 302 307, section 5.4.4, Table 10 + switch (r) + { + case FEC34: + gamma1 = 2.84; + gamma2 = 5.27; + break; + case FEC45: + gamma1 = 2.72; + gamma2 = 4.87; + break; + case FEC56: + gamma1 = 2.64; + gamma2 = 4.64; + break; + case FEC89: + gamma1 = 2.54; + gamma2 = 4.33; + break; + case FEC910: + gamma1 = 2.53; + gamma2 = 4.30; + break; + default: + fail("cstln_lut::make_dvbs2_constellation: Code rate not supported with APSK32"); + return 0; + } + break; + case cstln_lut::APSK64E: + // EN 302 307-2, section 5.4.5, Table 13f + gamma1 = 2.4; + gamma2 = 4.3; + gamma3 = 7; + break; + default: + break; + } + + cstln_lut *newCstln = new cstln_lut(c, 10, gamma1, gamma2, gamma3); + newCstln->m_rateCode = r < code_rate::FEC_COUNT ? r : -1; + newCstln->m_typeCode = c < cstln_lut::predef::COUNT ? c : -1; + newCstln->m_setByModcod = false; + return newCstln; +} + +} + +#endif // DATV_CSTLN_LUT_H \ No newline at end of file diff --git a/plugins/channelrx/demoddatv/datvdemodplugin.cpp b/plugins/channelrx/demoddatv/datvdemodplugin.cpp index 133d27266..0c54986e7 100644 --- a/plugins/channelrx/demoddatv/datvdemodplugin.cpp +++ b/plugins/channelrx/demoddatv/datvdemodplugin.cpp @@ -20,10 +20,12 @@ #include -#include #include "plugin/pluginapi.h" +#ifndef SERVER_MODE #include "datvdemodgui.h" +#endif +#include "datvdemod.h" #include "datvdemodplugin.h" #include "datvdemodwebapiadapter.h" @@ -75,10 +77,21 @@ void DATVDemodPlugin::createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink * } } +#ifdef SERVER_MODE +ChannelGUI* DATVDemodPlugin::createRxChannelGUI( + DeviceUISet *deviceUISet, + BasebandSampleSink *rxChannel) const +{ + (void) deviceUISet; + (void) rxChannel; + return 0; +} +#else ChannelGUI* DATVDemodPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const { return DATVDemodGUI::create(m_ptrPluginAPI, deviceUISet, rxChannel); } +#endif ChannelWebAPIAdapter* DATVDemodPlugin::createChannelWebAPIAdapter() const { diff --git a/plugins/channelrx/demoddatv/datvdemodsink.cpp b/plugins/channelrx/demoddatv/datvdemodsink.cpp index b2c4acdb2..cb396726d 100644 --- a/plugins/channelrx/demoddatv/datvdemodsink.cpp +++ b/plugins/channelrx/demoddatv/datvdemodsink.cpp @@ -17,7 +17,10 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#ifndef SERVER_MODE #include "datvideorender.h" +#endif +#include "datvcstlnlut.h" #include "datvdemodsink.h" #include "leansdr/dvbs2.h" @@ -34,7 +37,9 @@ const unsigned int DATVDemodSink::m_rfFilterFftLength = 512; DATVDemodSink::DATVDemodSink() : m_blnNeedConfigUpdate(false), m_tvScreen(nullptr), +#ifndef SERVER_MODE m_videoRender(nullptr), +#endif m_videoStream(new DATVideostream()), m_udpStream(leansdr::tspacket::SIZE), m_videoThread(nullptr), @@ -70,6 +75,7 @@ DATVDemodSink::~DATVDemodSink() void DATVDemodSink::stopVideo() { +#ifndef SERVER_MODE if (m_videoThread) { if (m_videoThread->isRunning()) @@ -79,6 +85,7 @@ void DATVDemodSink::stopVideo() m_videoThread->wait(); } } +#endif } void DATVDemodSink::setTVScreen(TVScreen *tvScreen) @@ -88,46 +95,64 @@ void DATVDemodSink::setTVScreen(TVScreen *tvScreen) void DATVDemodSink::SetVideoRender(DATVideoRender *screen) { +#ifndef SERVER_MODE m_videoRender = screen; m_videoRender->setAudioFIFO(&m_audioFifo); m_videoThread = new DATVideoRenderThread(m_videoRender, m_videoStream); m_videoThread->setObjectName("vtDATVDemodSink"); +#endif } bool DATVDemodSink::audioActive() { +#ifndef SERVER_MODE if (m_videoRender) { return m_videoRender->getAudioStreamIndex() >= 0; } else { return false; } +#else + return false; +#endif } bool DATVDemodSink::videoActive() { +#ifndef SERVER_MODE if (m_videoRender) { return m_videoRender->getVideoStreamIndex() >= 0; } else { return false; } +#else + return false; +#endif } bool DATVDemodSink::audioDecodeOK() { +#ifndef SERVER_MODE if (m_videoRender) { return m_videoRender->getAudioDecodeOK(); } else { return false; } +#else + return false; +#endif } bool DATVDemodSink::videoDecodeOK() { +#ifndef SERVER_MODE if (m_videoRender) { return m_videoRender->getVideoDecodeOK(); } else { return false; } +#else + return false; +#endif } bool DATVDemodSink::udpRunning() @@ -146,6 +171,7 @@ bool DATVDemodSink::playVideo() { QMutexLocker mlock(&m_mutex); +#ifndef SERVER_MODE if (m_videoStream == nullptr) { return false; } @@ -168,7 +194,7 @@ bool DATVDemodSink::playVideo() m_videoStream->setThreadTimeout(DATVideoRenderThread::videoThreadTimeoutMs); m_videoThread->start(); } - +#endif return false; } @@ -1360,6 +1386,7 @@ void DATVDemodSink::applySettings(const DATVDemodSettings& settings, bool force) return; } +#ifndef SERVER_MODE if ((settings.m_audioVolume) != (m_settings.m_audioVolume) || force) { if (m_videoRender) { @@ -1380,6 +1407,7 @@ void DATVDemodSink::applySettings(const DATVDemodSettings& settings, bool force) m_videoRender->setVideoMute(settings.m_videoMute); } } +#endif if ((m_settings.m_rfBandwidth != settings.m_rfBandwidth) || (m_settings.m_symbolRate != settings.m_symbolRate) diff --git a/plugins/channelrx/demoddatv/datvdvbs2constellation.h b/plugins/channelrx/demoddatv/datvdvbs2constellation.h index 33150ed55..f631a2f32 100644 --- a/plugins/channelrx/demoddatv/datvdvbs2constellation.h +++ b/plugins/channelrx/demoddatv/datvdvbs2constellation.h @@ -31,88 +31,6 @@ namespace leansdr { static const int DEFAULT_GUI_DVBS2_DECIMATION = 64; -static inline cstln_lut * make_dvbs2_constellation( - cstln_lut::predef c, - code_rate r -) -{ - float gamma1 = 1, gamma2 = 1, gamma3 = 1; - - switch (c) - { - case cstln_lut::APSK16: - // EN 302 307, section 5.4.3, Table 9 - switch (r) - { - case FEC23: - case FEC46: - gamma1 = 3.15; - break; - case FEC34: - gamma1 = 2.85; - break; - case FEC45: - gamma1 = 2.75; - break; - case FEC56: - gamma1 = 2.70; - break; - case FEC89: - gamma1 = 2.60; - break; - case FEC910: - gamma1 = 2.57; - break; - default: - fail("cstln_lut<256>::make_dvbs2_constellation: Code rate not supported with APSK16"); - return 0; - } - break; - case cstln_lut::APSK32: - // EN 302 307, section 5.4.4, Table 10 - switch (r) - { - case FEC34: - gamma1 = 2.84; - gamma2 = 5.27; - break; - case FEC45: - gamma1 = 2.72; - gamma2 = 4.87; - break; - case FEC56: - gamma1 = 2.64; - gamma2 = 4.64; - break; - case FEC89: - gamma1 = 2.54; - gamma2 = 4.33; - break; - case FEC910: - gamma1 = 2.53; - gamma2 = 4.30; - break; - default: - fail("cstln_lut::make_dvbs2_constellation: Code rate not supported with APSK32"); - return 0; - } - break; - case cstln_lut::APSK64E: - // EN 302 307-2, section 5.4.5, Table 13f - gamma1 = 2.4; - gamma2 = 4.3; - gamma3 = 7; - break; - default: - break; - } - - cstln_lut *newCstln = new cstln_lut(c, 10, gamma1, gamma2, gamma3); - newCstln->m_rateCode = r < code_rate::FEC_COUNT ? r : -1; - newCstln->m_typeCode = c < cstln_lut::predef::COUNT ? c : -1; - newCstln->m_setByModcod = false; - return newCstln; -} template struct datvdvbs2constellation: runnable { diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index ff653dee9..1c0a1eb6e 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -4930,10 +4930,6 @@ margin-bottom: 20px; "type" : "integer", "description" : "(boolean) engage sodt LDPC with LDPC tool sub processes (Linux only)" }, - "softLDPCToolPath" : { - "type" : "string", - "description" : "O/S path to the LDPC tool binary" - }, "softLDPCMaxTrials" : { "type" : "integer", "description" : "maximum number of trials in the soft LDPC algorithm (LDPC tool parameter)" @@ -8962,6 +8958,9 @@ margin-bottom: 20px; "dcBlock" : { "type" : "integer" }, + "splitFreq" : { + "type" : "integer" + }, "iqCorrection" : { "type" : "integer" }, @@ -59469,7 +59468,7 @@ except ApiException as e:
- Generated 2024-12-24T11:56:24.260+01:00 + Generated 2025-05-03T03:12:21.688+02:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/DATVDemod.yaml b/sdrbase/resources/webapi/doc/swagger/include/DATVDemod.yaml index 1b8164f70..39c01c646 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/DATVDemod.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/DATVDemod.yaml @@ -48,9 +48,6 @@ DATVDemodSettings: softLDPC: description: (boolean) engage sodt LDPC with LDPC tool sub processes (Linux only) type: integer - softLDPCToolPath: - description: O/S path to the LDPC tool binary - type: string softLDPCMaxTrials: description: maximum number of trials in the soft LDPC algorithm (LDPC tool parameter) type: integer diff --git a/sdrbase/resources/webapi/doc/swagger/include/LimeSdr.yaml b/sdrbase/resources/webapi/doc/swagger/include/LimeSdr.yaml index 7c54b524f..5fae3ce0c 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/LimeSdr.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/LimeSdr.yaml @@ -10,6 +10,8 @@ LimeSdrInputSettings: type: integer dcBlock: type: integer + splitFreq: + type: integer iqCorrection: type: integer log2SoftDecim: diff --git a/swagger/sdrangel/api/swagger/include/DATVDemod.yaml b/swagger/sdrangel/api/swagger/include/DATVDemod.yaml index 3dfd2ce49..51f32fc7e 100644 --- a/swagger/sdrangel/api/swagger/include/DATVDemod.yaml +++ b/swagger/sdrangel/api/swagger/include/DATVDemod.yaml @@ -48,9 +48,6 @@ DATVDemodSettings: softLDPC: description: (boolean) engage sodt LDPC with LDPC tool sub processes (Linux only) type: integer - softLDPCToolPath: - description: O/S path to the LDPC tool binary - type: string softLDPCMaxTrials: description: maximum number of trials in the soft LDPC algorithm (LDPC tool parameter) type: integer diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index ff653dee9..1c0a1eb6e 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -4930,10 +4930,6 @@ margin-bottom: 20px; "type" : "integer", "description" : "(boolean) engage sodt LDPC with LDPC tool sub processes (Linux only)" }, - "softLDPCToolPath" : { - "type" : "string", - "description" : "O/S path to the LDPC tool binary" - }, "softLDPCMaxTrials" : { "type" : "integer", "description" : "maximum number of trials in the soft LDPC algorithm (LDPC tool parameter)" @@ -8962,6 +8958,9 @@ margin-bottom: 20px; "dcBlock" : { "type" : "integer" }, + "splitFreq" : { + "type" : "integer" + }, "iqCorrection" : { "type" : "integer" }, @@ -59469,7 +59468,7 @@ except ApiException as e:
- Generated 2024-12-24T11:56:24.260+01:00 + Generated 2025-05-03T03:12:21.688+02:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGDATVDemodSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGDATVDemodSettings.cpp index 0af29c5d0..c8c587260 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDATVDemodSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDATVDemodSettings.cpp @@ -44,8 +44,6 @@ SWGDATVDemodSettings::SWGDATVDemodSettings() { m_fec_isSet = false; soft_ldpc = 0; m_soft_ldpc_isSet = false; - soft_ldpc_tool_path = nullptr; - m_soft_ldpc_tool_path_isSet = false; soft_ldpc_max_trials = 0; m_soft_ldpc_max_trials_isSet = false; max_bitflips = 0; @@ -124,8 +122,6 @@ SWGDATVDemodSettings::init() { m_fec_isSet = false; soft_ldpc = 0; m_soft_ldpc_isSet = false; - soft_ldpc_tool_path = new QString(""); - m_soft_ldpc_tool_path_isSet = false; soft_ldpc_max_trials = 0; m_soft_ldpc_max_trials_isSet = false; max_bitflips = 0; @@ -194,9 +190,6 @@ SWGDATVDemodSettings::cleanup() { - if(soft_ldpc_tool_path != nullptr) { - delete soft_ldpc_tool_path; - } @@ -263,8 +256,6 @@ SWGDATVDemodSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&soft_ldpc, pJson["softLDPC"], "qint32", ""); - ::SWGSDRangel::setValue(&soft_ldpc_tool_path, pJson["softLDPCToolPath"], "QString", "QString"); - ::SWGSDRangel::setValue(&soft_ldpc_max_trials, pJson["softLDPCMaxTrials"], "qint32", ""); ::SWGSDRangel::setValue(&max_bitflips, pJson["maxBitflips"], "qint32", ""); @@ -359,9 +350,6 @@ SWGDATVDemodSettings::asJsonObject() { if(m_soft_ldpc_isSet){ obj->insert("softLDPC", QJsonValue(soft_ldpc)); } - if(soft_ldpc_tool_path != nullptr && *soft_ldpc_tool_path != QString("")){ - toJsonValue(QString("softLDPCToolPath"), soft_ldpc_tool_path, obj, QString("QString")); - } if(m_soft_ldpc_max_trials_isSet){ obj->insert("softLDPCMaxTrials", QJsonValue(soft_ldpc_max_trials)); } @@ -527,16 +515,6 @@ SWGDATVDemodSettings::setSoftLdpc(qint32 soft_ldpc) { this->m_soft_ldpc_isSet = true; } -QString* -SWGDATVDemodSettings::getSoftLdpcToolPath() { - return soft_ldpc_tool_path; -} -void -SWGDATVDemodSettings::setSoftLdpcToolPath(QString* soft_ldpc_tool_path) { - this->soft_ldpc_tool_path = soft_ldpc_tool_path; - this->m_soft_ldpc_tool_path_isSet = true; -} - qint32 SWGDATVDemodSettings::getSoftLdpcMaxTrials() { return soft_ldpc_max_trials; @@ -836,9 +814,6 @@ SWGDATVDemodSettings::isSet(){ if(m_soft_ldpc_isSet){ isObjectUpdated = true; break; } - if(soft_ldpc_tool_path && *soft_ldpc_tool_path != QString("")){ - isObjectUpdated = true; break; - } if(m_soft_ldpc_max_trials_isSet){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDATVDemodSettings.h b/swagger/sdrangel/code/qt5/client/SWGDATVDemodSettings.h index 391d6c112..ad46b6652 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDATVDemodSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGDATVDemodSettings.h @@ -68,9 +68,6 @@ public: qint32 getSoftLdpc(); void setSoftLdpc(qint32 soft_ldpc); - QString* getSoftLdpcToolPath(); - void setSoftLdpcToolPath(QString* soft_ldpc_tool_path); - qint32 getSoftLdpcMaxTrials(); void setSoftLdpcMaxTrials(qint32 soft_ldpc_max_trials); @@ -180,9 +177,6 @@ private: qint32 soft_ldpc; bool m_soft_ldpc_isSet; - QString* soft_ldpc_tool_path; - bool m_soft_ldpc_tool_path_isSet; - qint32 soft_ldpc_max_trials; bool m_soft_ldpc_max_trials_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp index dd21d8a9e..5fc9eed09 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp @@ -35,9 +35,9 @@ SWGLimeSdrInputSettings::SWGLimeSdrInputSettings() { log2_hard_decim = 0; m_log2_hard_decim_isSet = false; dc_block = 0; - splitFreq = 0; m_dc_block_isSet = false; - m_splitFreq_isSet = false; + split_freq = 0; + m_split_freq_isSet = false; iq_correction = 0; m_iq_correction_isSet = false; log2_soft_decim = 0; @@ -102,8 +102,8 @@ SWGLimeSdrInputSettings::init() { m_log2_hard_decim_isSet = false; dc_block = 0; m_dc_block_isSet = false; - splitFreq = 0; - m_splitFreq_isSet = false; + split_freq = 0; + m_split_freq_isSet = false; iq_correction = 0; m_iq_correction_isSet = false; log2_soft_decim = 0; @@ -179,6 +179,7 @@ SWGLimeSdrInputSettings::cleanup() { + if(reverse_api_address != nullptr) { @@ -206,8 +207,8 @@ SWGLimeSdrInputSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&log2_hard_decim, pJson["log2HardDecim"], "qint32", ""); ::SWGSDRangel::setValue(&dc_block, pJson["dcBlock"], "qint32", ""); - - ::SWGSDRangel::setValue(&splitFreq, pJson["splitFreq"], "qint32", ""); + + ::SWGSDRangel::setValue(&split_freq, pJson["splitFreq"], "qint32", ""); ::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "qint32", ""); @@ -285,8 +286,8 @@ SWGLimeSdrInputSettings::asJsonObject() { if(m_dc_block_isSet){ obj->insert("dcBlock", QJsonValue(dc_block)); } - if(m_splitFreq_isSet){ - obj->insert("splitFreq", QJsonValue(splitFreq)); + if(m_split_freq_isSet){ + obj->insert("splitFreq", QJsonValue(split_freq)); } if(m_iq_correction_isSet){ obj->insert("iqCorrection", QJsonValue(iq_correction)); @@ -406,12 +407,12 @@ SWGLimeSdrInputSettings::setDcBlock(qint32 dc_block) { qint32 SWGLimeSdrInputSettings::getSplitFreq() { - return splitFreq; + return split_freq; } void -SWGLimeSdrInputSettings::setSplitFreq(qint32 splitFreq) { - this->splitFreq = splitFreq; - this->m_splitFreq_isSet = true; +SWGLimeSdrInputSettings::setSplitFreq(qint32 split_freq) { + this->split_freq = split_freq; + this->m_split_freq_isSet = true; } qint32 @@ -671,7 +672,7 @@ SWGLimeSdrInputSettings::isSet(){ if(m_dc_block_isSet){ isObjectUpdated = true; break; } - if(m_splitFreq_isSet){ + if(m_split_freq_isSet){ isObjectUpdated = true; break; } if(m_iq_correction_isSet){ diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h index 9e948f8f0..22fc8865c 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h @@ -52,10 +52,10 @@ public: void setLog2HardDecim(qint32 log2_hard_decim); qint32 getDcBlock(); - void setDcBlock(qint32 splitFreq); + void setDcBlock(qint32 dc_block); qint32 getSplitFreq(); - void setSplitFreq(qint32 splitFreq); + void setSplitFreq(qint32 split_freq); qint32 getIqCorrection(); void setIqCorrection(qint32 iq_correction); @@ -145,8 +145,8 @@ private: qint32 dc_block; bool m_dc_block_isSet; - qint32 splitFreq; - bool m_splitFreq_isSet; + qint32 split_freq; + bool m_split_freq_isSet; qint32 iq_correction; bool m_iq_correction_isSet; From 002f5e8af3a107697331f8115da598e31f1d0015 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 3 May 2025 17:16:19 +0200 Subject: [PATCH 20/26] Demod DATV: improve UDP TS output detection --- plugins/channelrx/demoddatv/datvdemodsink.cpp | 26 ++++++++++++++----- plugins/channelrx/demoddatv/datvvideoplayer.h | 26 +++++++++++++++++-- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/plugins/channelrx/demoddatv/datvdemodsink.cpp b/plugins/channelrx/demoddatv/datvdemodsink.cpp index cb396726d..25ded47ac 100644 --- a/plugins/channelrx/demoddatv/datvdemodsink.cpp +++ b/plugins/channelrx/demoddatv/datvdemodsink.cpp @@ -37,7 +37,7 @@ const unsigned int DATVDemodSink::m_rfFilterFftLength = 512; DATVDemodSink::DATVDemodSink() : m_blnNeedConfigUpdate(false), m_tvScreen(nullptr), -#ifndef SERVER_MODE +#ifndef SERVER_MODE m_videoRender(nullptr), #endif m_videoStream(new DATVideostream()), @@ -95,7 +95,7 @@ void DATVDemodSink::setTVScreen(TVScreen *tvScreen) void DATVDemodSink::SetVideoRender(DATVideoRender *screen) { -#ifndef SERVER_MODE +#ifndef SERVER_MODE m_videoRender = screen; m_videoRender->setAudioFIFO(&m_audioFifo); m_videoThread = new DATVideoRenderThread(m_videoRender, m_videoStream); @@ -162,7 +162,6 @@ bool DATVDemodSink::udpRunning() } bool udpRunning = r_videoplayer->isUDPRunning(); - r_videoplayer->resetUDPRunning(); return udpRunning; } @@ -526,7 +525,7 @@ void DATVDemodSink::ResetDATVFrameworkPointers() r_videoplayer = nullptr; //CONSTELLATION -#ifndef SERVER_MODE +#ifndef SERVER_MODE r_scope_symbols = nullptr; #endif @@ -543,7 +542,7 @@ void DATVDemodSink::ResetDATVFrameworkPointers() r_fecdecsoft = nullptr; r_fecdechelper = nullptr; p_deframer = nullptr; -#ifndef SERVER_MODE +#ifndef SERVER_MODE r_scope_symbols_dvbs2 = nullptr; #endif } @@ -879,6 +878,7 @@ void DATVDemodSink::InitDATVFramework() r_videoplayer = new leansdr::datvvideoplayer(m_objScheduler, *p_tspackets, nullptr, &m_udpStream); } + r_videoplayer->setSymbolRate(m_settings.m_symbolRate); m_blnDVBInitialized = true; } @@ -1212,6 +1212,7 @@ void DATVDemodSink::InitDATVS2Framework() r_videoplayer = new leansdr::datvvideoplayer(m_objScheduler, *p_tspackets, nullptr, &m_udpStream); } + r_videoplayer->setSymbolRate(m_settings.m_symbolRate); m_blnDVBInitialized = true; } @@ -1228,7 +1229,7 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample qDebug("DATVDemodSink::feed: change by MODCOD detected"); // Update constellation -#ifndef SERVER_MODE +#ifndef SERVER_MODE if (r_scope_symbols_dvbs2) { r_scope_symbols_dvbs2->calculate_cstln_points(); } @@ -1419,8 +1420,19 @@ void DATVDemodSink::applySettings(const DATVDemodSettings& settings, bool force) m_nco.setFreq(-(float) settings.m_centerFrequency, (float) m_channelSampleRate); } - if ((m_settings.m_udpTS != settings.m_udpTS) || force) { + if ((m_settings.m_udpTS != settings.m_udpTS) || force) + { m_udpStream.setActive(settings.m_udpTS); + + if (r_videoplayer && !settings.m_udpTS) { + r_videoplayer->resetUDPRunning(); + } + } + + if ((m_settings.m_symbolRate != settings.m_symbolRate) || force) { + if (r_videoplayer) { + r_videoplayer->setSymbolRate(settings.m_symbolRate); + } } if ((m_settings.m_udpTSAddress != settings.m_udpTSAddress) || force) { diff --git a/plugins/channelrx/demoddatv/datvvideoplayer.h b/plugins/channelrx/demoddatv/datvvideoplayer.h index 199bfd6d0..d4cf6502d 100644 --- a/plugins/channelrx/demoddatv/datvvideoplayer.h +++ b/plugins/channelrx/demoddatv/datvvideoplayer.h @@ -42,7 +42,9 @@ template struct datvvideoplayer: runnable in(_in), m_videoStream(videoStream), m_udpStream(udpStream), - m_atomicUDPRunning(0) + m_atomicUDPRunning(0), + m_count(0), + m_sr(1500000) { } @@ -50,7 +52,18 @@ template struct datvvideoplayer: runnable { int size = in.readable() * sizeof(T); - if (!size) { + if (!size) + { + if (m_count == 0) + { + #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + m_atomicUDPRunning.storeRelaxed(0); + #else + m_atomicUDPRunning.store(0); + #endif + } else { + m_count--; + } return; } @@ -62,6 +75,8 @@ template struct datvvideoplayer: runnable #else m_atomicUDPRunning.store(m_udpStream->isActive() && (size > 0) ? 1 : 0); #endif + m_count = m_sr / 10000; + if (m_videoStream) { nw = m_videoStream->pushData((const char *) in.rd(), size); @@ -114,11 +129,18 @@ template struct datvvideoplayer: runnable #endif } + void setSymbolRate(unsigned int sr) + { + m_sr = sr; + } + private: pipereader in; DATVideostream *m_videoStream; DATVUDPStream *m_udpStream; QAtomicInt m_atomicUDPRunning; + unsigned int m_count; + unsigned int m_sr; // Symbol rate in S/s used for UDP running detection }; } From de4147b853391aa450fef6ba25fc8a77256fbe27 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 4 May 2025 01:44:51 +0200 Subject: [PATCH 21/26] DATV demod: pass symbol rate in report --- plugins/channelrx/demoddatv/datvdemod.cpp | 1 + sdrbase/resources/webapi/doc/html2/index.html | 6 ++++- .../webapi/doc/swagger/include/DATVDemod.yaml | 4 ++++ .../api/swagger/include/DATVDemod.yaml | 4 ++++ swagger/sdrangel/code/html2/index.html | 6 ++++- .../code/qt5/client/SWGDATVDemodReport.cpp | 23 +++++++++++++++++++ .../code/qt5/client/SWGDATVDemodReport.h | 6 +++++ 7 files changed, 48 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/demoddatv/datvdemod.cpp b/plugins/channelrx/demoddatv/datvdemod.cpp index 78fb44057..4834f2217 100644 --- a/plugins/channelrx/demoddatv/datvdemod.cpp +++ b/plugins/channelrx/demoddatv/datvdemod.cpp @@ -576,6 +576,7 @@ void DATVDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respons response.getDatvDemodReport()->setChannelPowerDb(CalcDb::dbPower(magsq)); response.getDatvDemodReport()->setAudioActive(audioActive() ? 1 : 0); response.getDatvDemodReport()->setAudioDecodeOk(audioDecodeOK() ? 1 : 0); + response.getDatvDemodReport()->setSymbolRate(m_settings.m_symbolRate); // This is repeated from settings for convenience response.getDatvDemodReport()->setModcodCodeRate(getModcodCodeRate()); response.getDatvDemodReport()->setModcodModulation(getModcodModulation()); response.getDatvDemodReport()->setSetByModcod(isCstlnSetByModcod() ? 1 : 0); diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 1c0a1eb6e..1161844fd 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -4877,6 +4877,10 @@ margin-bottom: 20px; "type" : "integer", "description" : "UDP thread (1 running, 0 idle)" }, + "symbolRate" : { + "type" : "integer", + "description" : "Symbol rate in symbols per second - repeated from settings for convenience\n" + }, "modcodModulation" : { "type" : "integer", "description" : "Modulation set by DVB-S2 MODCOD\n * -1: Unset\n * 0: BPSK\n * 1: QPSK\n * 2: PSK8\n * 3: APSK16\n * 4: APSK32\n * 5: APSK64E\n * 6: QAM16\n * 7: QAM64\n * 8: QAM256\n" @@ -59468,7 +59472,7 @@ except ApiException as e:
- Generated 2025-05-03T03:12:21.688+02:00 + Generated 2025-05-03T17:59:40.379+02:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/DATVDemod.yaml b/sdrbase/resources/webapi/doc/swagger/include/DATVDemod.yaml index 39c01c646..c254382af 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/DATVDemod.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/DATVDemod.yaml @@ -145,6 +145,10 @@ DATVDemodReport: udpRunning: description: UDP thread (1 running, 0 idle) type: integer + symbolRate: + type: integer + description: > + Symbol rate in symbols per second - repeated from settings for convenience modcodModulation: type: integer description: > diff --git a/swagger/sdrangel/api/swagger/include/DATVDemod.yaml b/swagger/sdrangel/api/swagger/include/DATVDemod.yaml index 51f32fc7e..538c9b71c 100644 --- a/swagger/sdrangel/api/swagger/include/DATVDemod.yaml +++ b/swagger/sdrangel/api/swagger/include/DATVDemod.yaml @@ -145,6 +145,10 @@ DATVDemodReport: udpRunning: description: UDP thread (1 running, 0 idle) type: integer + symbolRate: + type: integer + description: > + Symbol rate in symbols per second - repeated from settings for convenience modcodModulation: type: integer description: > diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 1c0a1eb6e..1161844fd 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -4877,6 +4877,10 @@ margin-bottom: 20px; "type" : "integer", "description" : "UDP thread (1 running, 0 idle)" }, + "symbolRate" : { + "type" : "integer", + "description" : "Symbol rate in symbols per second - repeated from settings for convenience\n" + }, "modcodModulation" : { "type" : "integer", "description" : "Modulation set by DVB-S2 MODCOD\n * -1: Unset\n * 0: BPSK\n * 1: QPSK\n * 2: PSK8\n * 3: APSK16\n * 4: APSK32\n * 5: APSK64E\n * 6: QAM16\n * 7: QAM64\n * 8: QAM256\n" @@ -59468,7 +59472,7 @@ except ApiException as e:
- Generated 2025-05-03T03:12:21.688+02:00 + Generated 2025-05-03T17:59:40.379+02:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGDATVDemodReport.cpp b/swagger/sdrangel/code/qt5/client/SWGDATVDemodReport.cpp index d90cca7d6..b99ae33ed 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDATVDemodReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDATVDemodReport.cpp @@ -40,6 +40,8 @@ SWGDATVDemodReport::SWGDATVDemodReport() { m_video_decode_ok_isSet = false; udp_running = 0; m_udp_running_isSet = false; + symbol_rate = 0; + m_symbol_rate_isSet = false; modcod_modulation = 0; m_modcod_modulation_isSet = false; modcod_code_rate = 0; @@ -70,6 +72,8 @@ SWGDATVDemodReport::init() { m_video_decode_ok_isSet = false; udp_running = 0; m_udp_running_isSet = false; + symbol_rate = 0; + m_symbol_rate_isSet = false; modcod_modulation = 0; m_modcod_modulation_isSet = false; modcod_code_rate = 0; @@ -95,6 +99,7 @@ SWGDATVDemodReport::cleanup() { + } SWGDATVDemodReport* @@ -120,6 +125,8 @@ SWGDATVDemodReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&udp_running, pJson["udpRunning"], "qint32", ""); + ::SWGSDRangel::setValue(&symbol_rate, pJson["symbolRate"], "qint32", ""); + ::SWGSDRangel::setValue(&modcod_modulation, pJson["modcodModulation"], "qint32", ""); ::SWGSDRangel::setValue(&modcod_code_rate, pJson["modcodCodeRate"], "qint32", ""); @@ -164,6 +171,9 @@ SWGDATVDemodReport::asJsonObject() { if(m_udp_running_isSet){ obj->insert("udpRunning", QJsonValue(udp_running)); } + if(m_symbol_rate_isSet){ + obj->insert("symbolRate", QJsonValue(symbol_rate)); + } if(m_modcod_modulation_isSet){ obj->insert("modcodModulation", QJsonValue(modcod_modulation)); } @@ -243,6 +253,16 @@ SWGDATVDemodReport::setUdpRunning(qint32 udp_running) { this->m_udp_running_isSet = true; } +qint32 +SWGDATVDemodReport::getSymbolRate() { + return symbol_rate; +} +void +SWGDATVDemodReport::setSymbolRate(qint32 symbol_rate) { + this->symbol_rate = symbol_rate; + this->m_symbol_rate_isSet = true; +} + qint32 SWGDATVDemodReport::getModcodModulation() { return modcod_modulation; @@ -316,6 +336,9 @@ SWGDATVDemodReport::isSet(){ if(m_udp_running_isSet){ isObjectUpdated = true; break; } + if(m_symbol_rate_isSet){ + isObjectUpdated = true; break; + } if(m_modcod_modulation_isSet){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDATVDemodReport.h b/swagger/sdrangel/code/qt5/client/SWGDATVDemodReport.h index a99e0249f..f2cb07c0f 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDATVDemodReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGDATVDemodReport.h @@ -59,6 +59,9 @@ public: qint32 getUdpRunning(); void setUdpRunning(qint32 udp_running); + qint32 getSymbolRate(); + void setSymbolRate(qint32 symbol_rate); + qint32 getModcodModulation(); void setModcodModulation(qint32 modcod_modulation); @@ -96,6 +99,9 @@ private: qint32 udp_running; bool m_udp_running_isSet; + qint32 symbol_rate; + bool m_symbol_rate_isSet; + qint32 modcod_modulation; bool m_modcod_modulation_isSet; From 2f47258605055c0cd7a8f5a484b30418c8429a24 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 4 May 2025 19:57:24 +0200 Subject: [PATCH 22/26] Added Python script to control PlutoDVB2 --- scriptsapi/Readme.md | 17 +++ scriptsapi/plutodvbrpt.py | 304 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 321 insertions(+) create mode 100755 scriptsapi/plutodvbrpt.py diff --git a/scriptsapi/Readme.md b/scriptsapi/Readme.md index 81fbdf642..a180baa1c 100644 --- a/scriptsapi/Readme.md +++ b/scriptsapi/Readme.md @@ -32,6 +32,23 @@ Normal sequence of operations: - In SDRangel connect the Frequency Tracker plugin by clicking on the grey square at the left of the top bar of the Frequency Tracker GUI. It opens the channel settings dialog. Check the 'Reverse API' box. Next to this box is the address and port at which the channel will be connected. If you use the defaults for `freqtracking.py` you may leave it as it is else you have to adjust it to the address and port of `freqtracking.py` (options `-A` and `-P`). - In the same manner connect the channel you want to be controlled by `freqtracking.py`. You may connect any number of channels like this. When a channel is removed `freqtracking.py` will automatically remove it from its list at the first attempt to synchronize that will fail. +

plutodvbrpt.py

+ +Control PlutoDVB2 Tx firmware from SDRangel DATV demod as Rx. This is to effectively implement a DATV repeater based on SDRangel (supposedly sdrangelsrv running on a RPi5 or mini PC) as the receiver and a Pluto equipped with F5OEO PlutoDVB2 firmware as the transmitter. PlutoDVB2 has not such a thing as a "vox" on its UDP TS input so it needs an external command (via MQTT) to switch on/off Tx when the UDP flux starts or stops. + +This script polls the DATV Demod channel report every second via the REST API interface and sends appropriate command to the Pluto to switch Tx on or off according to the UDP status. In addition it can clone the DVBS2 essential parameters to the Tx to match exactly the input parameters on the Rx. These are symbol rate, modulation and FEC. + + - `-h` or `--help` show help message and exit + - `-a` or `--sdr_address` SDRangel address and port. Default: `127.0.0.1:8091` + - `-d` or `--device` index of device set. Default `0` + - `-c` or `--channel` Index of DATV demod channel. Default `0` + - `-A` or `--pluto_address` Pluto MQTT address. Mandatory + - `-P` or `--pluto_port` Pluto MQTT port. Default `1883` + - `-C` or `--callsign` Amateur Radio callsign. Mandatory + - `-l` or `--clone` Clone symbol rate, constellation and fec to Pluto + +The Pluto address and amateur radio callsign have to be specified. The rest have default values as mentioned. +

ptt_feature.py

Control a PTT feature and optionally a LimeRFE feature in coordination. diff --git a/scriptsapi/plutodvbrpt.py b/scriptsapi/plutodvbrpt.py new file mode 100755 index 000000000..ab4207022 --- /dev/null +++ b/scriptsapi/plutodvbrpt.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python3 +""" +Control PlutoDVB2 enabled Pluto Tx switchover watching UDP status of a DATV demodulator channel +This is a way to implement a DATV repeater system +Uses PlutoDVB2 MQTT "mute" command to switch on/off the Tx +""" +from optparse import OptionParser # pylint: disable=deprecated-module + +import json +import os +import socket +import signal +import traceback +import sys +import time +import requests +import paho.mqtt.client as mqttclient +import logging + +logger = logging.getLogger(__name__) +mqtt_client = None +pluto_state = {} + +FEC_TABLE = { + 0: "1/2", + 1: "2/3", + 2: "4/6", + 3: "3/4", + 4: "5/6", + 5: "7/8", + 6: "4/5", + 7: "8/9", + 8: "9/10", + 9: "1/4", + 10: "1/3", + 11: "2/5", + 12: "3/5" +} + +CONSTEL_TABLE = { + 0: "BPSK", + 1: "QPSK", + 2: "PSK8", + 3: "APSK16", + 4: "APSK32", + 5: "APSK64E", + 6: "QAM16", + 7: "QAM64", + 8: "QAM256" +} + +# ====================================================================== +def signal_handler(signum, frame): + """ Signal handler """ + logger.info("Signal handler called with signal %d", signum) + # Clean up and exit + # Close MQTT connection + if mqtt_client: + mqtt_client.disconnect() + sys.exit(0) + +signal.signal(signal.SIGINT, signal_handler) +signal.signal(signal.SIGTERM, signal_handler) + +# ====================================================================== +def get_input_options(): + """ Parse options """ +# ---------------------------------------------------------------------- + parser = OptionParser(usage="usage: %%prog [-t]\n") + parser.add_option("-a", "--sdr_address", dest="sdr_address", help="SDRangel address and port. Default: 127.0.0.1:8091", metavar="ADDRESS:PORT", type="string") + parser.add_option("-d", "--device", dest="device_index", help="Index of device set. Default 0", metavar="INT", type="int") + parser.add_option("-c", "--channel", dest="channel_index", help="Index of DATV demod channel. Default 0", metavar="INT", type="int") + parser.add_option("-A", "--pluto_address", dest="pluto_address", help="Pluto MQTT address and port. Mandatory", metavar="ADDRESS", type="string") + parser.add_option("-P", "--pluto_port", dest="pluto_port", help="Pluto MQTT port. Default 1883", metavar="INT", type="int") + parser.add_option("-C", "--callsign", dest="callsign", help="Amateur Radio callsign", metavar="CALLSIGN", type="string") + parser.add_option("-l", "--clone", dest="clone", help="Clone symbol rate, constellation and fec to Pluto", metavar="BOOL", action="store_true", default=False) + + (options, args) = parser.parse_args() + if options.sdr_address is None: + options.sdr_address = "127.0.0.1:8091" + if options.device_index is None: + options.device_index = 0 + if options.channel_index is None: + options.channel_index = 0 + if options.pluto_port is None: + options.pluto_port = 1883 + if options.pluto_address is None: + raise RuntimeError("Pluto address (-A or --pluto_address) is mandatory") + if options.callsign is None: + raise RuntimeError("Callsign (-C or --callsign) is mandatory") + + return options + +# ====================================================================== +def pluto_state_change(state, value): + """ Change Pluto state """ +# ---------------------------------------------------------------------- + global pluto_state + if state not in pluto_state: + pluto_state[state] = value + else: + pluto_state[state] = value + logger.debug("Pluto state changed: %s = %s", state, value) + return + +# ====================================================================== +def connect_mqtt(options): + """ Connect to Pluto MQTT broker """ +# ---------------------------------------------------------------------- + global mqtt_client + mqtt_client = mqttclient.Client() + mqtt_client.enable_logger(logger) + mqtt_client.on_connect = on_connect + mqtt_client.on_message = on_message + mqtt_client.on_subscribe = on_subscribe + + # Connect to the MQTT broker + logger.info("Connecting to Pluto MQTT broker at %s:%d", options.pluto_address, options.pluto_port) + try: + mqtt_client.connect(options.pluto_address, options.pluto_port, 60) + mqtt_client.loop_start() + except Exception as ex: + raise RuntimeError(f"Failed to connect to Pluto MQTT broker: {ex}") + logger.info("Connected to Pluto MQTT broker at %s:%d", options.pluto_address, options.pluto_port) + return mqtt_client + +# ====================================================================== +def on_connect(client, userdata, flags, rc): + """ Callback for MQTT connection """ +# ---------------------------------------------------------------------- + logger.info("Connected to MQTT broker with result code %d", rc) + return + +# ====================================================================== +def on_message(client, userdata, msg): + """ Callback for MQTT message """ +# ---------------------------------------------------------------------- + logger.debug("Received message on topic %s: %s", msg.topic, msg.payload) + # Parse the message + try: + if msg.topic.endswith("/mute"): + logger.debug("Tx mute message received") + pluto_state_change("muted", msg.payload == b'1') + elif msg.topic.endswith("/sr"): + logger.debug("Tx symbol rate message received: %d", int(msg.payload)) + pluto_state_change("symbol_rate", int(msg.payload)) + elif msg.topic.endswith("/constel"): + logger.debug("Tx constellation message received: %s", msg.payload.decode('utf-8')) + pluto_state_change("constellation", msg.payload.decode('utf-8')) + elif msg.topic.endswith("/fec"): + logger.debug("Tx fec message received: %s", msg.payload.decode('utf-8')) + pluto_state_change("fec", msg.payload.decode('utf-8')) + else: + message = json.loads(msg.payload) + logger.debug("Message payload is JSON: %s", message) + except json.JSONDecodeError as ex: + logger.error("Failed to decode JSON message: %s", ex) + except Exception as ex: + logger.error("Failed to handle message: %s", ex) + return + +# ====================================================================== +def on_subscribe(client, userdata, mid, granted_qos): + """ Callback for MQTT subscription """ +# ---------------------------------------------------------------------- + logger.info("Subscribed to topic with mid %d and granted QoS %s", mid, granted_qos) + return + +# ====================================================================== +def subscribe_to_pluto(options, mqtt_client): + """ Subscribe to Pluto MQTT broker """ +# ---------------------------------------------------------------------- + if mqtt_client is None: + raise RuntimeError("MQTT client is not connected") + tx_base_topic = f"dt/pluto/{options.callsign.upper()}/tx" + mute_dt_topic = f"{tx_base_topic}/mute" + logger.info("Subscribing to topic %s", mute_dt_topic) + mqtt_client.subscribe(mute_dt_topic) + logger.info("Subscribed to topic %s", mute_dt_topic) + if options.clone: + # Subscribe to Pluto Tx symbol rate + symbol_rate_topic = f"{tx_base_topic}/dvbs2/sr" + logger.info("Subscribing to topic %s", symbol_rate_topic) + mqtt_client.subscribe(symbol_rate_topic) + # Subscribe to Pluto Tx constellation + constellation_topic = f"{tx_base_topic}/dvbs2/constel" + logger.info("Subscribing to topic %s", constellation_topic) + mqtt_client.subscribe(constellation_topic) + # Subscribe to Pluto Tx fec + fec_topic = f"{tx_base_topic}/dvbs2/fec" + logger.info("Subscribing to topic %s", fec_topic) + mqtt_client.subscribe(fec_topic) + return + +# ====================================================================== +def mute_pluto_tx(options, mute): + """ Mute or unmute Pluto Tx """ +# ---------------------------------------------------------------------- + global mqtt_client + if mqtt_client is None: + raise RuntimeError("MQTT client is not connected") + topic = f"cmd/pluto/{options.callsign.upper()}/tx/mute" + message = b'1' if mute else b'0' + logger.info("Publishing message to topic %s: %s", topic, message) + mqtt_client.publish(topic, message) + logger.info("Published message to topic %s", topic) + # Update Pluto state + pluto_state_change("muted", mute) + return + +# ====================================================================== +def set_pluto_tx_dvbs2(options, symbol_rate, constellation, fec): + """ Set Pluto Tx DVBS2 parameters """ +# ---------------------------------------------------------------------- + global mqtt_client + if mqtt_client is None: + raise RuntimeError("MQTT client is not connected") + topic_dvbs2 = f"cmd/pluto/{options.callsign.upper()}/tx/dvbs2" + topic_sr = f"{topic_dvbs2}/sr" + topic_constel = f"{topic_dvbs2}/constel" + topic_fec = f"{topic_dvbs2}/fec" + logger.info("Publishing message to topic %s: %d", topic_sr, symbol_rate) + mqtt_client.publish(topic_sr, symbol_rate) + logger.info("Published message to topic %s", topic_sr) + logger.info("Publishing message to topic %s: %s", topic_constel, constellation) + mqtt_client.publish(topic_constel, constellation) + logger.info("Published message to topic %s", topic_constel) + logger.info("Publishing message to topic %s: %s", topic_fec, fec) + mqtt_client.publish(topic_fec, fec) + logger.info("Published message to topic %s", topic_fec) + # Update Pluto state + pluto_state_change("symbol_rate", symbol_rate) + pluto_state_change("constellation", constellation) + pluto_state_change("fec", fec) + return + +# ====================================================================== +def monitor_datv_demod(options): + """ Monitor DATV demodulator channel and control Pluto Tx """ +# ---------------------------------------------------------------------- + # Check DATV demodulator channel status + sdrangel_url = f"http://{options.sdr_address}/sdrangel" + report_url = f"{sdrangel_url}/deviceset/{options.device_index}/channel/{options.channel_index}/report" + response = requests.get(report_url) + if response.status_code != 200: + raise RuntimeError(f"Failed to read report at {report_url}") + datv_channel_report = response.json().get("DATVDemodReport", None) + if not datv_channel_report: + raise RuntimeError(f"Failed to read DATV demodulator report at {report_url}") + udp_running = datv_channel_report.get("udpRunning", None) + if udp_running is None: + raise RuntimeError(f"Failed to read udpRunning in {datv_channel_report}") + logger.debug("DATV UDP: %d", udp_running) + if "muted" in pluto_state and pluto_state["muted"] == udp_running or "muted" not in pluto_state: + logger.info("Pluto Tx %s", "muted" if not udp_running else "unmuted") + mute_pluto_tx(options, not udp_running) + logger.info("Pluto state: %s", pluto_state) + if options.clone and datv_channel_report.get("setByModcod", None): + mod = datv_channel_report.get("modcodModulation", -1) + logger.debug("DATV Modulation: %s", CONSTEL_TABLE.get(mod, "Unknown")) + fec = datv_channel_report.get("modcodCodeRate", -1) + logger.debug("DATV FEC: %s", FEC_TABLE.get(fec, "Unknown")) + symbol_rate = datv_channel_report.get("symbolRate", 0) + logger.debug("DATV Symbol Rate: %d", symbol_rate) + if "symbol_rate" in pluto_state and pluto_state["symbol_rate"] == symbol_rate and \ + "constellation" in pluto_state and pluto_state["constellation"].upper() == CONSTEL_TABLE.get(mod, "Unknown") and \ + "fec" in pluto_state and pluto_state["fec"] == FEC_TABLE.get(fec, "Unknown"): + logger.debug("Pluto Tx parameters unchanged") + else: + logger.info("Pluto Tx parameters changed") + set_pluto_tx_dvbs2(options, symbol_rate, CONSTEL_TABLE.get(mod, "Unknown").lower(), FEC_TABLE.get(fec, "Unknown")) + logger.info("Pluto state: %s", pluto_state) + return + +# ====================================================================== +def main(): + """ Main program """ +# ---------------------------------------------------------------------- + try: + FORMAT = '%(asctime)s %(levelname)s %(message)s' + logging.basicConfig(format=FORMAT, level=logging.INFO) + options = get_input_options() + + connect_mqtt(options) + subscribe_to_pluto(options, mqtt_client) + + # Run forever + logger.info("Start monitoring SDRangel channel %d:%d at %s", options.device_index, options.channel_index, options.sdr_address) + while True: + # Monitor DATV demodulator channel + monitor_datv_demod(options) + + # Sleep for a while before checking again + time.sleep(1) + + except Exception as ex: # pylint: disable=broad-except + tb = traceback.format_exc() + print(f"Exception caught {ex}") + print(tb, file=sys.stderr) + sys.exit(1) + +# ====================================================================== +if __name__ == "__main__": + main() From 89d7fe736f99a48b0a5ec95050025ef28646b4c7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 4 May 2025 20:01:51 +0200 Subject: [PATCH 23/26] Updated versions and changelogs --- CHANGELOG | 6 ++++++ CMakeLists.txt | 2 +- debian/changelog | 6 ++++++ gitdiff.sh | 3 +-- plugins/channelrx/demoddatv/datvdemodplugin.cpp | 2 +- plugins/channelrx/demodnavtex/navtexdemodplugin.cpp | 2 +- plugins/channelrx/remotesink/remotesinkplugin.cpp | 2 +- plugins/channeltx/modpacket/packetmodplugin.cpp | 2 +- plugins/channeltx/remotesource/remotesourceplugin.cpp | 2 +- plugins/feature/ambe/ambeplugin.cpp | 2 +- plugins/feature/gs232controller/gs232controllerplugin.cpp | 2 +- plugins/feature/rigctlserver/rigctlserverplugin.cpp | 2 +- plugins/feature/satellitetracker/satellitetrackerplugin.cpp | 2 +- plugins/samplemimo/audiocatsiso/audiocatsisoplugin.cpp | 2 +- plugins/samplemimo/metismiso/metismisoplugin.cpp | 2 +- plugins/samplesink/limesdroutput/limesdroutputplugin.cpp | 2 +- plugins/samplesink/usrpoutput/usrpoutputplugin.cpp | 2 +- plugins/samplesource/hackrfinput/hackrfinputplugin.cpp | 2 +- plugins/samplesource/limesdrinput/limesdrinputplugin.cpp | 2 +- 19 files changed, 29 insertions(+), 18 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 684d21059..1f63638e8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +sdrangel (7.22.7-1) unstable; urgency=medium + + * See Github release + + -- Edouard Griffiths, F4EXB Sun, 04 May 2025 17:58:14 +0200 + sdrangel (7.22.6-1) unstable; urgency=medium * See Github release diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ab7abda1..1f1c4ebd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # configure version set(sdrangel_VERSION_MAJOR "7") set(sdrangel_VERSION_MINOR "22") -set(sdrangel_VERSION_PATCH "6") +set(sdrangel_VERSION_PATCH "7") set(sdrangel_VERSION_SUFFIX "") # SDRAngel cmake options diff --git a/debian/changelog b/debian/changelog index f83d75ef6..3cf276338 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +sdrangel (7.22.7-1) unstable; urgency=medium + + * See Github release + + -- Edouard Griffiths, F4EXB Sun, 04 May 2025 17:58:14 +0200 + sdrangel (7.22.6-1) unstable; urgency=medium * See Github release diff --git a/gitdiff.sh b/gitdiff.sh index e6deb2802..abcf8cf36 100755 --- a/gitdiff.sh +++ b/gitdiff.sh @@ -5,6 +5,5 @@ for plugin in $PLUGINS do FILE=$(find $BASEDIR/plugins/$plugin -name "*plugin.cpp") echo $FILE - sed -i -E "s/QStringLiteral\(\"7\.(.*)\"\)/QStringLiteral\(\"7\.22\.6\"\)/" $FILE + sed -i -E "s/QStringLiteral\(\"7\.(.*)\"\)/QStringLiteral\(\"7\.22\.7\"\)/" $FILE done - diff --git a/plugins/channelrx/demoddatv/datvdemodplugin.cpp b/plugins/channelrx/demoddatv/datvdemodplugin.cpp index 0c54986e7..84b828c53 100644 --- a/plugins/channelrx/demoddatv/datvdemodplugin.cpp +++ b/plugins/channelrx/demoddatv/datvdemodplugin.cpp @@ -33,7 +33,7 @@ const PluginDescriptor DATVDemodPlugin::m_ptrPluginDescriptor = { DATVDemod::m_channelId, QStringLiteral("DATV Demodulator"), - QStringLiteral("7.22.5"), + QStringLiteral("7.22.7"), QStringLiteral("(c) F4HKW for SDRAngel using LeanSDR framework (c) F4DAV"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/channelrx/demodnavtex/navtexdemodplugin.cpp b/plugins/channelrx/demodnavtex/navtexdemodplugin.cpp index 5857b7726..5cb2bf016 100644 --- a/plugins/channelrx/demodnavtex/navtexdemodplugin.cpp +++ b/plugins/channelrx/demodnavtex/navtexdemodplugin.cpp @@ -33,7 +33,7 @@ const PluginDescriptor NavtexDemodPlugin::m_pluginDescriptor = { NavtexDemod::m_channelId, QStringLiteral("Navtex Demodulator"), - QStringLiteral("7.22.5"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Jon Beniston, M7RCE"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/channelrx/remotesink/remotesinkplugin.cpp b/plugins/channelrx/remotesink/remotesinkplugin.cpp index b4638ef90..61844ff3e 100644 --- a/plugins/channelrx/remotesink/remotesinkplugin.cpp +++ b/plugins/channelrx/remotesink/remotesinkplugin.cpp @@ -34,7 +34,7 @@ const PluginDescriptor RemoteSinkPlugin::m_pluginDescriptor = { RemoteSink::m_channelId, QStringLiteral("Remote channel sink"), - QStringLiteral("7.22.5"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/channeltx/modpacket/packetmodplugin.cpp b/plugins/channeltx/modpacket/packetmodplugin.cpp index 821f5ea2d..714fed2a2 100644 --- a/plugins/channeltx/modpacket/packetmodplugin.cpp +++ b/plugins/channeltx/modpacket/packetmodplugin.cpp @@ -33,7 +33,7 @@ const PluginDescriptor PacketModPlugin::m_pluginDescriptor = { PacketMod::m_channelId, QStringLiteral("Packet Modulator"), - QStringLiteral("7.22.5"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Jon Beniston, M7RCE"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/channeltx/remotesource/remotesourceplugin.cpp b/plugins/channeltx/remotesource/remotesourceplugin.cpp index 5674a6e9f..f2d97be6c 100644 --- a/plugins/channeltx/remotesource/remotesourceplugin.cpp +++ b/plugins/channeltx/remotesource/remotesourceplugin.cpp @@ -32,7 +32,7 @@ const PluginDescriptor RemoteSourcePlugin::m_pluginDescriptor = { RemoteSource::m_channelId, QStringLiteral("Remote channel source"), - QStringLiteral("7.22.5"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/feature/ambe/ambeplugin.cpp b/plugins/feature/ambe/ambeplugin.cpp index 94573db21..fb65242ec 100644 --- a/plugins/feature/ambe/ambeplugin.cpp +++ b/plugins/feature/ambe/ambeplugin.cpp @@ -31,7 +31,7 @@ const PluginDescriptor AMBEPlugin::m_pluginDescriptor = { AMBE::m_featureId, QStringLiteral("AMBE Controller"), - QStringLiteral("7.22.1"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/feature/gs232controller/gs232controllerplugin.cpp b/plugins/feature/gs232controller/gs232controllerplugin.cpp index ba546a7c0..8a76dcca1 100644 --- a/plugins/feature/gs232controller/gs232controllerplugin.cpp +++ b/plugins/feature/gs232controller/gs232controllerplugin.cpp @@ -34,7 +34,7 @@ const PluginDescriptor GS232ControllerPlugin::m_pluginDescriptor = { GS232Controller::m_featureId, QStringLiteral("Rotator Controller"), - QStringLiteral("7.22.1"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Jon Beniston, M7RCE"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/feature/rigctlserver/rigctlserverplugin.cpp b/plugins/feature/rigctlserver/rigctlserverplugin.cpp index 863550b6b..634f7c4f5 100644 --- a/plugins/feature/rigctlserver/rigctlserverplugin.cpp +++ b/plugins/feature/rigctlserver/rigctlserverplugin.cpp @@ -31,7 +31,7 @@ const PluginDescriptor RigCtlServerPlugin::m_pluginDescriptor = { RigCtlServer::m_featureId, QStringLiteral("RigCtl Server"), - QStringLiteral("7.22.1"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Jon Beniston, M7RCE and Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/feature/satellitetracker/satellitetrackerplugin.cpp b/plugins/feature/satellitetracker/satellitetrackerplugin.cpp index 55f42d7e2..edb625430 100644 --- a/plugins/feature/satellitetracker/satellitetrackerplugin.cpp +++ b/plugins/feature/satellitetracker/satellitetrackerplugin.cpp @@ -34,7 +34,7 @@ const PluginDescriptor SatelliteTrackerPlugin::m_pluginDescriptor = { SatelliteTracker::m_featureId, QStringLiteral("Satellite Tracker"), - QStringLiteral("7.22.3"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Jon Beniston, M7RCE and Daniel Warner (SGP4 library)"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplemimo/audiocatsiso/audiocatsisoplugin.cpp b/plugins/samplemimo/audiocatsiso/audiocatsisoplugin.cpp index e98c82cd6..52461528c 100644 --- a/plugins/samplemimo/audiocatsiso/audiocatsisoplugin.cpp +++ b/plugins/samplemimo/audiocatsiso/audiocatsisoplugin.cpp @@ -32,7 +32,7 @@ const PluginDescriptor AudioCATSISOPlugin::m_pluginDescriptor = { QStringLiteral("AudioCATSISO"), QStringLiteral("Audio CAT SISO"), - QStringLiteral("7.22.1"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplemimo/metismiso/metismisoplugin.cpp b/plugins/samplemimo/metismiso/metismisoplugin.cpp index 3a6049d3a..2195299de 100644 --- a/plugins/samplemimo/metismiso/metismisoplugin.cpp +++ b/plugins/samplemimo/metismiso/metismisoplugin.cpp @@ -33,7 +33,7 @@ const PluginDescriptor MetisMISOPlugin::m_pluginDescriptor = { QStringLiteral("MetisMISO"), QStringLiteral("Metis MISO"), - QStringLiteral("7.22.1"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp b/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp index a4dec5901..53ae6d260 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp @@ -36,7 +36,7 @@ const PluginDescriptor LimeSDROutputPlugin::m_pluginDescriptor = { QStringLiteral("LimeSDR"), QStringLiteral("LimeSDR Output"), - QStringLiteral("7.22.1"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesink/usrpoutput/usrpoutputplugin.cpp b/plugins/samplesink/usrpoutput/usrpoutputplugin.cpp index b693d9274..8fc5d20af 100644 --- a/plugins/samplesink/usrpoutput/usrpoutputplugin.cpp +++ b/plugins/samplesink/usrpoutput/usrpoutputplugin.cpp @@ -36,7 +36,7 @@ const PluginDescriptor USRPOutputPlugin::m_pluginDescriptor = { QStringLiteral("USRP"), QStringLiteral("URSP Output"), - QStringLiteral("7.22.6"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Jon Beniston, M7RCE and Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/hackrfinput/hackrfinputplugin.cpp b/plugins/samplesource/hackrfinput/hackrfinputplugin.cpp index 7f01d35ee..af8b93c95 100644 --- a/plugins/samplesource/hackrfinput/hackrfinputplugin.cpp +++ b/plugins/samplesource/hackrfinput/hackrfinputplugin.cpp @@ -33,7 +33,7 @@ const PluginDescriptor HackRFInputPlugin::m_pluginDescriptor = { QStringLiteral("HackRF"), QStringLiteral("HackRF Input"), - QStringLiteral("7.22.1"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp b/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp index 3fdfa22f5..1fc5bc270 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp @@ -36,7 +36,7 @@ const PluginDescriptor LimeSDRInputPlugin::m_pluginDescriptor = { QStringLiteral("LimeSDR"), QStringLiteral("LimeSDR Input"), - QStringLiteral("7.22.3"), + QStringLiteral("7.22.7"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, From 3d3195489a280d9d15bb43adc1b05014163537ce Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 29 May 2025 12:47:57 +0200 Subject: [PATCH 24/26] Added Swagger schema validation container in the compose stack --- swagger/docker/compose/compose.yml | 12 ++++++++++++ swagger/docker/readme.md | 10 ++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/swagger/docker/compose/compose.yml b/swagger/docker/compose/compose.yml index a4b2ba99f..86912e634 100644 --- a/swagger/docker/compose/compose.yml +++ b/swagger/docker/compose/compose.yml @@ -22,6 +22,18 @@ services: networks: default: ipv4_address: 172.20.0.3 + swaggerclient: + image: "jeanberu/swagger-cli" + user: "1000:1000" + entrypoint: "/bin/sh" + container_name: "sdrangel_swaggerclient" + volumes: + - "${SDRANGEL_BASE}:/opt/build/sdrangel:rw" + stdin_open: true + tty: true + networks: + default: + ipv4_address: 172.20.0.4 networks: default: driver: bridge diff --git a/swagger/docker/readme.md b/swagger/docker/readme.md index 3ec65185e..1e40ab4b5 100644 --- a/swagger/docker/readme.md +++ b/swagger/docker/readme.md @@ -41,8 +41,14 @@ Use `run.sh` to create or delete the Docker compose stack. It takes the followin - `-b`: SDRangel source code root path (default `/opt/build/sdrangel`) - `-c`: Compose stack name (default `sdrangelswg`) -The stack is composed of two containers sharing the `172.20.0.0/16` network internally. +The stack is composed of three containers sharing the `172.20.0.0/16` network internally. - `sdrangel_swgserver`: The http server that listens on port `8081` serving files in `/opt/build/sdrangel/swagger/sdrangel` - - `sdrangel_swgcodegen`: The container with the Swagger code generator. The working directory is `/opt/build/sdrangel/swagger/sdrangel`. + - `sdrangel_swgcodegen`: The container with the Swagger code generator. The working directory is `/opt/build/sdrangel/swagger/sdrangel` + - `sdrangel_swaggerclient`: based on the `jeanberu/swagger-cli` image it can be used to validate the swagger schema (see next). Use `login.sh` to start a shell in the `sdrangel_swgcodegen` container. At the prompt run `generate.sh` to generate the code from the Swagger definition files. + +To validate the swagger schema: + - Enter the `sdrangel_swaggerclient` container with: `docker exec -it sdrangel_swaggerclient /bin/sh` + - Validate the schema with the command: `swagger-cli validate /opt/build/sdrangel/swagger/sdrangel/api/swagger/swagger.yaml` + - Correct errors from the most inner ones (maximum tabs). Top level errors usually result from low level errors and are therefore quite cryptic. From 28077752a9b464c49d54c3beb53f90a69c163920 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 29 May 2025 12:48:11 +0200 Subject: [PATCH 25/26] Swagger schema fixes --- sdrbase/resources/webapi/doc/html2/index.html | 13 +++++++++---- .../webapi/doc/swagger/include/DemodAnalyzer.yaml | 5 +++-- .../webapi/doc/swagger/include/MorseDecoder.yaml | 5 +++-- .../webapi/doc/swagger/include/RemoteOutput.yaml | 4 ++-- .../webapi/doc/swagger/include/WDSPRx.yaml | 2 +- sdrbase/resources/webapi/doc/swagger/swagger.yaml | 4 ---- .../sdrangel/api/swagger/include/DemodAnalyzer.yaml | 5 +++-- .../sdrangel/api/swagger/include/MorseDecoder.yaml | 5 +++-- .../sdrangel/api/swagger/include/RemoteOutput.yaml | 4 ++-- swagger/sdrangel/api/swagger/include/WDSPRx.yaml | 2 +- swagger/sdrangel/api/swagger/swagger.yaml | 4 ---- swagger/sdrangel/code/html2/index.html | 13 +++++++++---- 12 files changed, 36 insertions(+), 30 deletions(-) diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 1161844fd..2dfe30f5e 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -5530,6 +5530,7 @@ margin-bottom: 20px; "description" : "List of DV serial devices available in the system" }; defs.DemodAnalyzerActions = { + "required" : [ "channelId", "deviceId" ], "properties" : { "deviceId" : { "type" : "integer", @@ -10587,6 +10588,7 @@ margin-bottom: 20px; "description" : "MetisMISOSettings" }; defs.MorseDecoderActions = { + "required" : [ "channelId", "deviceId" ], "properties" : { "deviceId" : { "type" : "integer", @@ -13257,10 +13259,12 @@ margin-bottom: 20px; "type" : "integer" }, "deviceIndex" : { - "type" : "integer" + "type" : "integer", + "description" : "remote SDRangel instance deviceset index" }, "channelIndex" : { - "type" : "integer" + "type" : "integer", + "description" : "remote SDRangel instance channel index" }, "useReverseAPI" : { "type" : "integer", @@ -17230,7 +17234,8 @@ margin-bottom: 20px; }, "nbLeadTime" : { "type" : "number", - "format" : "float" + "format" : "float", + "description" : "Advance time (s)" }, "nbLagTime" : { "type" : "number", @@ -59472,7 +59477,7 @@ except ApiException as e:
- Generated 2025-05-03T17:59:40.379+02:00 + Generated 2025-05-29T12:27:25.321+02:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/DemodAnalyzer.yaml b/sdrbase/resources/webapi/doc/swagger/include/DemodAnalyzer.yaml index 7680007fd..c0399bc7f 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/DemodAnalyzer.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/DemodAnalyzer.yaml @@ -42,12 +42,13 @@ DemodAnalyzerSettings: DemodAnalyzerActions: description: "Demod Analyzer actions" + required: + - deviceId + - channelId properties: deviceId: type: integer - required: true description: "Device Id/Number that channel belongs to" channelId: type: integer - required: true description: "Channel Id/Number of the channel within the device" diff --git a/sdrbase/resources/webapi/doc/swagger/include/MorseDecoder.yaml b/sdrbase/resources/webapi/doc/swagger/include/MorseDecoder.yaml index e0ddbe609..2354110cb 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/MorseDecoder.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/MorseDecoder.yaml @@ -59,12 +59,13 @@ MorseDecoderSettings: MorseDecoderActions: description: "Morse Decoder actions" + required: + - deviceId + - channelId properties: deviceId: type: integer - required: true description: "Device Id/Number that channel belongs to" channelId: type: integer - required: true description: "Channel Id/Number of the channel within the device" diff --git a/sdrbase/resources/webapi/doc/swagger/include/RemoteOutput.yaml b/sdrbase/resources/webapi/doc/swagger/include/RemoteOutput.yaml index 2f9a95804..9fdd76ccb 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/RemoteOutput.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/RemoteOutput.yaml @@ -19,10 +19,10 @@ RemoteOutputSettings: dataPort: type: integer deviceIndex: - device: remote SDRangel instance deviceset index + description: remote SDRangel instance deviceset index type: integer channelIndex: - device: remote SDRangel instance channel index + description: remote SDRangel instance channel index type: integer useReverseAPI: description: Synchronize with reverse API (1 for yes, 0 for no) diff --git a/sdrbase/resources/webapi/doc/swagger/include/WDSPRx.yaml b/sdrbase/resources/webapi/doc/swagger/include/WDSPRx.yaml index e14629fb7..25a758c2e 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/WDSPRx.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/WDSPRx.yaml @@ -76,7 +76,7 @@ WDSPRxSettings: nbLeadTime: type: number format: float - descriuption: Advance time (s) + description: Advance time (s) nbLagTime: type: number format: float diff --git a/sdrbase/resources/webapi/doc/swagger/swagger.yaml b/sdrbase/resources/webapi/doc/swagger/swagger.yaml index 3c50a474d..e1c049d43 100644 --- a/sdrbase/resources/webapi/doc/swagger/swagger.yaml +++ b/sdrbase/resources/webapi/doc/swagger/swagger.yaml @@ -2973,7 +2973,6 @@ definitions: FeatureSet: description: "Grouping of features" required: - - index - featurecount properties: featurecount: @@ -3018,7 +3017,6 @@ definitions: required: - index - hwType - - streamIndex - sequence - serial - centerFrequency @@ -3422,7 +3420,6 @@ definitions: description: "Group of configuration" required: - groupName - - nbPresets properties: groupName: description: "Name of the configuration group" @@ -3530,4 +3527,3 @@ responses: description: Function not implemented schema: $ref: "#/definitions/ErrorResponse" - diff --git a/swagger/sdrangel/api/swagger/include/DemodAnalyzer.yaml b/swagger/sdrangel/api/swagger/include/DemodAnalyzer.yaml index 68b1e9911..f18530ad0 100644 --- a/swagger/sdrangel/api/swagger/include/DemodAnalyzer.yaml +++ b/swagger/sdrangel/api/swagger/include/DemodAnalyzer.yaml @@ -42,12 +42,13 @@ DemodAnalyzerSettings: DemodAnalyzerActions: description: "Demod Analyzer actions" + required: + - deviceId + - channelId properties: deviceId: type: integer - required: true description: "Device Id/Number that channel belongs to" channelId: type: integer - required: true description: "Channel Id/Number of the channel within the device" diff --git a/swagger/sdrangel/api/swagger/include/MorseDecoder.yaml b/swagger/sdrangel/api/swagger/include/MorseDecoder.yaml index abacc57cd..4859b1371 100644 --- a/swagger/sdrangel/api/swagger/include/MorseDecoder.yaml +++ b/swagger/sdrangel/api/swagger/include/MorseDecoder.yaml @@ -59,12 +59,13 @@ MorseDecoderSettings: MorseDecoderActions: description: "Morse Decoder actions" + required: + - deviceId + - channelId properties: deviceId: type: integer - required: true description: "Device Id/Number that channel belongs to" channelId: type: integer - required: true description: "Channel Id/Number of the channel within the device" diff --git a/swagger/sdrangel/api/swagger/include/RemoteOutput.yaml b/swagger/sdrangel/api/swagger/include/RemoteOutput.yaml index 2f9a95804..9fdd76ccb 100644 --- a/swagger/sdrangel/api/swagger/include/RemoteOutput.yaml +++ b/swagger/sdrangel/api/swagger/include/RemoteOutput.yaml @@ -19,10 +19,10 @@ RemoteOutputSettings: dataPort: type: integer deviceIndex: - device: remote SDRangel instance deviceset index + description: remote SDRangel instance deviceset index type: integer channelIndex: - device: remote SDRangel instance channel index + description: remote SDRangel instance channel index type: integer useReverseAPI: description: Synchronize with reverse API (1 for yes, 0 for no) diff --git a/swagger/sdrangel/api/swagger/include/WDSPRx.yaml b/swagger/sdrangel/api/swagger/include/WDSPRx.yaml index ebafad988..21a72ccc6 100644 --- a/swagger/sdrangel/api/swagger/include/WDSPRx.yaml +++ b/swagger/sdrangel/api/swagger/include/WDSPRx.yaml @@ -76,7 +76,7 @@ WDSPRxSettings: nbLeadTime: type: number format: float - descriuption: Advance time (s) + description: Advance time (s) nbLagTime: type: number format: float diff --git a/swagger/sdrangel/api/swagger/swagger.yaml b/swagger/sdrangel/api/swagger/swagger.yaml index c22ee88be..37b56f6f4 100644 --- a/swagger/sdrangel/api/swagger/swagger.yaml +++ b/swagger/sdrangel/api/swagger/swagger.yaml @@ -2973,7 +2973,6 @@ definitions: FeatureSet: description: "Grouping of features" required: - - index - featurecount properties: featurecount: @@ -3018,7 +3017,6 @@ definitions: required: - index - hwType - - streamIndex - sequence - serial - centerFrequency @@ -3422,7 +3420,6 @@ definitions: description: "Group of configuration" required: - groupName - - nbPresets properties: groupName: description: "Name of the configuration group" @@ -3530,4 +3527,3 @@ responses: description: Function not implemented schema: $ref: "#/definitions/ErrorResponse" - diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 1161844fd..2dfe30f5e 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -5530,6 +5530,7 @@ margin-bottom: 20px; "description" : "List of DV serial devices available in the system" }; defs.DemodAnalyzerActions = { + "required" : [ "channelId", "deviceId" ], "properties" : { "deviceId" : { "type" : "integer", @@ -10587,6 +10588,7 @@ margin-bottom: 20px; "description" : "MetisMISOSettings" }; defs.MorseDecoderActions = { + "required" : [ "channelId", "deviceId" ], "properties" : { "deviceId" : { "type" : "integer", @@ -13257,10 +13259,12 @@ margin-bottom: 20px; "type" : "integer" }, "deviceIndex" : { - "type" : "integer" + "type" : "integer", + "description" : "remote SDRangel instance deviceset index" }, "channelIndex" : { - "type" : "integer" + "type" : "integer", + "description" : "remote SDRangel instance channel index" }, "useReverseAPI" : { "type" : "integer", @@ -17230,7 +17234,8 @@ margin-bottom: 20px; }, "nbLeadTime" : { "type" : "number", - "format" : "float" + "format" : "float", + "description" : "Advance time (s)" }, "nbLagTime" : { "type" : "number", @@ -59472,7 +59477,7 @@ except ApiException as e:
- Generated 2025-05-03T17:59:40.379+02:00 + Generated 2025-05-29T12:27:25.321+02:00
From 76b4623375e9b5e56b01cde15b712c3d09fe0c5e Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 29 May 2025 15:10:16 +0200 Subject: [PATCH 26/26] Upgrade Swagger UI to 5.22.0 and added WDSPRx.yaml to resources --- sdrbase/resources/webapi.qrc | 3 ++ .../resources/webapi/doc/swagger-ui/index.css | 16 ++++++++ .../webapi/doc/swagger-ui/index.html | 25 +------------ .../doc/swagger-ui/oauth2-redirect.html | 37 +++++++++++-------- .../doc/swagger-ui/swagger-initializer.js | 20 ++++++++++ .../doc/swagger-ui/swagger-ui-bundle.js | 3 +- .../doc/swagger-ui/swagger-ui-bundle.js.map | 2 +- .../swagger-ui/swagger-ui-es-bundle-core.js | 2 +- .../swagger-ui-es-bundle-core.js.map | 2 +- .../doc/swagger-ui/swagger-ui-es-bundle.js | 3 +- .../swagger-ui/swagger-ui-es-bundle.js.map | 2 +- .../swagger-ui-standalone-preset.js | 3 +- .../swagger-ui-standalone-preset.js.map | 2 +- .../webapi/doc/swagger-ui/swagger-ui.css | 3 +- .../webapi/doc/swagger-ui/swagger-ui.css.map | 2 +- .../webapi/doc/swagger-ui/swagger-ui.js | 3 +- .../webapi/doc/swagger-ui/swagger-ui.js.map | 2 +- 17 files changed, 74 insertions(+), 56 deletions(-) create mode 100644 sdrbase/resources/webapi/doc/swagger-ui/index.css create mode 100644 sdrbase/resources/webapi/doc/swagger-ui/swagger-initializer.js diff --git a/sdrbase/resources/webapi.qrc b/sdrbase/resources/webapi.qrc index bc93514d8..d9480d0bc 100644 --- a/sdrbase/resources/webapi.qrc +++ b/sdrbase/resources/webapi.qrc @@ -135,10 +135,12 @@ webapi/doc/swagger/include/VORLocalizer.yaml webapi/doc/swagger/include/WFMDemod.yaml webapi/doc/swagger/include/WFMMod.yaml + webapi/doc/swagger/include/WDSPRx.yaml webapi/doc/swagger/include/Xtrx.yaml webapi/doc/swagger-ui/favicon-16x16.png webapi/doc/swagger-ui/favicon-32x32.png webapi/doc/swagger-ui/index.html + webapi/doc/swagger-ui/index.css webapi/doc/swagger-ui/oauth2-redirect.html webapi/doc/swagger-ui/swagger-ui-bundle.js webapi/doc/swagger-ui/swagger-ui-bundle.js.map @@ -148,6 +150,7 @@ webapi/doc/swagger-ui/swagger-ui-es-bundle.js.map webapi/doc/swagger-ui/swagger-ui-standalone-preset.js.map webapi/doc/swagger-ui/swagger-ui-standalone-preset.js + webapi/doc/swagger-ui/swagger-initializer.js webapi/doc/swagger-ui/swagger-ui.css webapi/doc/swagger-ui/swagger-ui.css.map webapi/doc/swagger-ui/swagger-ui.js diff --git a/sdrbase/resources/webapi/doc/swagger-ui/index.css b/sdrbase/resources/webapi/doc/swagger-ui/index.css new file mode 100644 index 000000000..f2376fdaa --- /dev/null +++ b/sdrbase/resources/webapi/doc/swagger-ui/index.css @@ -0,0 +1,16 @@ +html { + box-sizing: border-box; + overflow: -moz-scrollbars-vertical; + overflow-y: scroll; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +body { + margin: 0; + background: #fafafa; +} diff --git a/sdrbase/resources/webapi/doc/swagger-ui/index.html b/sdrbase/resources/webapi/doc/swagger-ui/index.html index d811595ce..3c3257e53 100644 --- a/sdrbase/resources/webapi/doc/swagger-ui/index.html +++ b/sdrbase/resources/webapi/doc/swagger-ui/index.html @@ -4,35 +4,14 @@ Swagger UI - + + -
- + + diff --git a/sdrbase/resources/webapi/doc/swagger-ui/swagger-initializer.js b/sdrbase/resources/webapi/doc/swagger-ui/swagger-initializer.js new file mode 100644 index 000000000..8ea0ea3af --- /dev/null +++ b/sdrbase/resources/webapi/doc/swagger-ui/swagger-initializer.js @@ -0,0 +1,20 @@ +window.onload = function() { + // + + // the following lines will be replaced by docker/configurator, when it runs in a docker-container + window.ui = SwaggerUIBundle({ + url: "https://petstore.swagger.io/v2/swagger.json", + dom_id: '#swagger-ui', + deepLinking: true, + presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIStandalonePreset + ], + plugins: [ + SwaggerUIBundle.plugins.DownloadUrl + ], + layout: "StandaloneLayout" + }); + + // +}; diff --git a/sdrbase/resources/webapi/doc/swagger-ui/swagger-ui-bundle.js b/sdrbase/resources/webapi/doc/swagger-ui/swagger-ui-bundle.js index 54d90a984..dfff077dd 100644 --- a/sdrbase/resources/webapi/doc/swagger-ui/swagger-ui-bundle.js +++ b/sdrbase/resources/webapi/doc/swagger-ui/swagger-ui-bundle.js @@ -1,3 +1,2 @@ /*! For license information please see swagger-ui-bundle.js.LICENSE.txt */ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(function(){try{return require("esprima")}catch(e){}}()):"function"==typeof define&&define.amd?define(["esprima"],t):"object"==typeof exports?exports.SwaggerUIBundle=t(function(){try{return require("esprima")}catch(e){}}()):e.SwaggerUIBundle=t(e.esprima)}(this,(function(e){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist",n(n.s=540)}([function(e,t,n){"use strict";e.exports=n(128)},function(e,t,n){e.exports=function(){"use strict";var e=Array.prototype.slice;function t(e,t){t&&(e.prototype=Object.create(t.prototype)),e.prototype.constructor=e}function n(e){return i(e)?e:$(e)}function r(e){return s(e)?e:K(e)}function o(e){return u(e)?e:Y(e)}function a(e){return i(e)&&!c(e)?e:G(e)}function i(e){return!(!e||!e[p])}function s(e){return!(!e||!e[f])}function u(e){return!(!e||!e[h])}function c(e){return s(e)||u(e)}function l(e){return!(!e||!e[d])}t(r,n),t(o,n),t(a,n),n.isIterable=i,n.isKeyed=s,n.isIndexed=u,n.isAssociative=c,n.isOrdered=l,n.Keyed=r,n.Indexed=o,n.Set=a;var p="@@__IMMUTABLE_ITERABLE__@@",f="@@__IMMUTABLE_KEYED__@@",h="@@__IMMUTABLE_INDEXED__@@",d="@@__IMMUTABLE_ORDERED__@@",v="delete",m=5,g=1<>>0;if(""+n!==t||4294967295===n)return NaN;t=n}return t<0?A(e)+t:t}function O(){return!0}function j(e,t,n){return(0===e||void 0!==n&&e<=-n)&&(void 0===t||void 0!==n&&t>=n)}function T(e,t){return N(e,t,0)}function I(e,t){return N(e,t,t)}function N(e,t,n){return void 0===e?n:e<0?Math.max(0,t+e):void 0===t?e:Math.min(t,e)}var M=0,P=1,R=2,D="function"==typeof Symbol&&Symbol.iterator,L="@@iterator",B=D||L;function F(e){this.next=e}function U(e,t,n,r){var o=0===e?t:1===e?n:[t,n];return r?r.value=o:r={value:o,done:!1},r}function q(){return{value:void 0,done:!0}}function z(e){return!!H(e)}function V(e){return e&&"function"==typeof e.next}function W(e){var t=H(e);return t&&t.call(e)}function H(e){var t=e&&(D&&e[D]||e[L]);if("function"==typeof t)return t}function J(e){return e&&"number"==typeof e.length}function $(e){return null==e?ie():i(e)?e.toSeq():ce(e)}function K(e){return null==e?ie().toKeyedSeq():i(e)?s(e)?e.toSeq():e.fromEntrySeq():se(e)}function Y(e){return null==e?ie():i(e)?s(e)?e.entrySeq():e.toIndexedSeq():ue(e)}function G(e){return(null==e?ie():i(e)?s(e)?e.entrySeq():e:ue(e)).toSetSeq()}F.prototype.toString=function(){return"[Iterator]"},F.KEYS=M,F.VALUES=P,F.ENTRIES=R,F.prototype.inspect=F.prototype.toSource=function(){return this.toString()},F.prototype[B]=function(){return this},t($,n),$.of=function(){return $(arguments)},$.prototype.toSeq=function(){return this},$.prototype.toString=function(){return this.__toString("Seq {","}")},$.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},$.prototype.__iterate=function(e,t){return pe(this,e,t,!0)},$.prototype.__iterator=function(e,t){return fe(this,e,t,!0)},t(K,$),K.prototype.toKeyedSeq=function(){return this},t(Y,$),Y.of=function(){return Y(arguments)},Y.prototype.toIndexedSeq=function(){return this},Y.prototype.toString=function(){return this.__toString("Seq [","]")},Y.prototype.__iterate=function(e,t){return pe(this,e,t,!1)},Y.prototype.__iterator=function(e,t){return fe(this,e,t,!1)},t(G,$),G.of=function(){return G(arguments)},G.prototype.toSetSeq=function(){return this},$.isSeq=ae,$.Keyed=K,$.Set=G,$.Indexed=Y;var Z,X,Q,ee="@@__IMMUTABLE_SEQ__@@";function te(e){this._array=e,this.size=e.length}function ne(e){var t=Object.keys(e);this._object=e,this._keys=t,this.size=t.length}function re(e){this._iterable=e,this.size=e.length||e.size}function oe(e){this._iterator=e,this._iteratorCache=[]}function ae(e){return!(!e||!e[ee])}function ie(){return Z||(Z=new te([]))}function se(e){var t=Array.isArray(e)?new te(e).fromEntrySeq():V(e)?new oe(e).fromEntrySeq():z(e)?new re(e).fromEntrySeq():"object"==typeof e?new ne(e):void 0;if(!t)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+e);return t}function ue(e){var t=le(e);if(!t)throw new TypeError("Expected Array or iterable object of values: "+e);return t}function ce(e){var t=le(e)||"object"==typeof e&&new ne(e);if(!t)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+e);return t}function le(e){return J(e)?new te(e):V(e)?new oe(e):z(e)?new re(e):void 0}function pe(e,t,n,r){var o=e._cache;if(o){for(var a=o.length-1,i=0;i<=a;i++){var s=o[n?a-i:i];if(!1===t(s[1],r?s[0]:i,e))return i+1}return i}return e.__iterateUncached(t,n)}function fe(e,t,n,r){var o=e._cache;if(o){var a=o.length-1,i=0;return new F((function(){var e=o[n?a-i:i];return i++>a?q():U(t,r?e[0]:i-1,e[1])}))}return e.__iteratorUncached(t,n)}function he(e,t){return t?de(t,e,"",{"":e}):ve(e)}function de(e,t,n,r){return Array.isArray(t)?e.call(r,n,Y(t).map((function(n,r){return de(e,n,r,t)}))):me(t)?e.call(r,n,K(t).map((function(n,r){return de(e,n,r,t)}))):t}function ve(e){return Array.isArray(e)?Y(e).map(ve).toList():me(e)?K(e).map(ve).toMap():e}function me(e){return e&&(e.constructor===Object||void 0===e.constructor)}function ge(e,t){if(e===t||e!=e&&t!=t)return!0;if(!e||!t)return!1;if("function"==typeof e.valueOf&&"function"==typeof t.valueOf){if((e=e.valueOf())===(t=t.valueOf())||e!=e&&t!=t)return!0;if(!e||!t)return!1}return!("function"!=typeof e.equals||"function"!=typeof t.equals||!e.equals(t))}function ye(e,t){if(e===t)return!0;if(!i(t)||void 0!==e.size&&void 0!==t.size&&e.size!==t.size||void 0!==e.__hash&&void 0!==t.__hash&&e.__hash!==t.__hash||s(e)!==s(t)||u(e)!==u(t)||l(e)!==l(t))return!1;if(0===e.size&&0===t.size)return!0;var n=!c(e);if(l(e)){var r=e.entries();return t.every((function(e,t){var o=r.next().value;return o&&ge(o[1],e)&&(n||ge(o[0],t))}))&&r.next().done}var o=!1;if(void 0===e.size)if(void 0===t.size)"function"==typeof e.cacheResult&&e.cacheResult();else{o=!0;var a=e;e=t,t=a}var p=!0,f=t.__iterate((function(t,r){if(n?!e.has(t):o?!ge(t,e.get(r,b)):!ge(e.get(r,b),t))return p=!1,!1}));return p&&e.size===f}function be(e,t){if(!(this instanceof be))return new be(e,t);if(this._value=e,this.size=void 0===t?1/0:Math.max(0,t),0===this.size){if(X)return X;X=this}}function _e(e,t){if(!e)throw new Error(t)}function we(e,t,n){if(!(this instanceof we))return new we(e,t,n);if(_e(0!==n,"Cannot step a Range by 0"),e=e||0,void 0===t&&(t=1/0),n=void 0===n?1:Math.abs(n),tr?q():U(e,o,n[t?r-o++:o++])}))},t(ne,K),ne.prototype.get=function(e,t){return void 0===t||this.has(e)?this._object[e]:t},ne.prototype.has=function(e){return this._object.hasOwnProperty(e)},ne.prototype.__iterate=function(e,t){for(var n=this._object,r=this._keys,o=r.length-1,a=0;a<=o;a++){var i=r[t?o-a:a];if(!1===e(n[i],i,this))return a+1}return a},ne.prototype.__iterator=function(e,t){var n=this._object,r=this._keys,o=r.length-1,a=0;return new F((function(){var i=r[t?o-a:a];return a++>o?q():U(e,i,n[i])}))},ne.prototype[d]=!0,t(re,Y),re.prototype.__iterateUncached=function(e,t){if(t)return this.cacheResult().__iterate(e,t);var n=W(this._iterable),r=0;if(V(n))for(var o;!(o=n.next()).done&&!1!==e(o.value,r++,this););return r},re.prototype.__iteratorUncached=function(e,t){if(t)return this.cacheResult().__iterator(e,t);var n=W(this._iterable);if(!V(n))return new F(q);var r=0;return new F((function(){var t=n.next();return t.done?t:U(e,r++,t.value)}))},t(oe,Y),oe.prototype.__iterateUncached=function(e,t){if(t)return this.cacheResult().__iterate(e,t);for(var n,r=this._iterator,o=this._iteratorCache,a=0;a=r.length){var t=n.next();if(t.done)return t;r[o]=t.value}return U(e,o,r[o++])}))},t(be,Y),be.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},be.prototype.get=function(e,t){return this.has(e)?this._value:t},be.prototype.includes=function(e){return ge(this._value,e)},be.prototype.slice=function(e,t){var n=this.size;return j(e,t,n)?this:new be(this._value,I(t,n)-T(e,n))},be.prototype.reverse=function(){return this},be.prototype.indexOf=function(e){return ge(this._value,e)?0:-1},be.prototype.lastIndexOf=function(e){return ge(this._value,e)?this.size:-1},be.prototype.__iterate=function(e,t){for(var n=0;n=0&&t=0&&nn?q():U(e,a++,i)}))},we.prototype.equals=function(e){return e instanceof we?this._start===e._start&&this._end===e._end&&this._step===e._step:ye(this,e)},t(xe,n),t(Ee,xe),t(Ce,xe),t(Se,xe),xe.Keyed=Ee,xe.Indexed=Ce,xe.Set=Se;var Ae="function"==typeof Math.imul&&-2===Math.imul(4294967295,2)?Math.imul:function(e,t){var n=65535&(e|=0),r=65535&(t|=0);return n*r+((e>>>16)*r+n*(t>>>16)<<16>>>0)|0};function ke(e){return e>>>1&1073741824|3221225471&e}function Oe(e){if(!1===e||null==e)return 0;if("function"==typeof e.valueOf&&(!1===(e=e.valueOf())||null==e))return 0;if(!0===e)return 1;var t=typeof e;if("number"===t){if(e!=e||e===1/0)return 0;var n=0|e;for(n!==e&&(n^=4294967295*e);e>4294967295;)n^=e/=4294967295;return ke(n)}if("string"===t)return e.length>Fe?je(e):Te(e);if("function"==typeof e.hashCode)return e.hashCode();if("object"===t)return Ie(e);if("function"==typeof e.toString)return Te(e.toString());throw new Error("Value type "+t+" cannot be hashed.")}function je(e){var t=ze[e];return void 0===t&&(t=Te(e),qe===Ue&&(qe=0,ze={}),qe++,ze[e]=t),t}function Te(e){for(var t=0,n=0;n0)switch(e.nodeType){case 1:return e.uniqueID;case 9:return e.documentElement&&e.documentElement.uniqueID}}var Re,De="function"==typeof WeakMap;De&&(Re=new WeakMap);var Le=0,Be="__immutablehash__";"function"==typeof Symbol&&(Be=Symbol(Be));var Fe=16,Ue=255,qe=0,ze={};function Ve(e){_e(e!==1/0,"Cannot perform this action with an infinite size.")}function We(e){return null==e?ot():He(e)&&!l(e)?e:ot().withMutations((function(t){var n=r(e);Ve(n.size),n.forEach((function(e,n){return t.set(n,e)}))}))}function He(e){return!(!e||!e[$e])}t(We,Ee),We.of=function(){var t=e.call(arguments,0);return ot().withMutations((function(e){for(var n=0;n=t.length)throw new Error("Missing value for key: "+t[n]);e.set(t[n],t[n+1])}}))},We.prototype.toString=function(){return this.__toString("Map {","}")},We.prototype.get=function(e,t){return this._root?this._root.get(0,void 0,e,t):t},We.prototype.set=function(e,t){return at(this,e,t)},We.prototype.setIn=function(e,t){return this.updateIn(e,b,(function(){return t}))},We.prototype.remove=function(e){return at(this,e,b)},We.prototype.deleteIn=function(e){return this.updateIn(e,(function(){return b}))},We.prototype.update=function(e,t,n){return 1===arguments.length?e(this):this.updateIn([e],t,n)},We.prototype.updateIn=function(e,t,n){n||(n=t,t=void 0);var r=mt(this,xn(e),t,n);return r===b?void 0:r},We.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):ot()},We.prototype.merge=function(){return ft(this,void 0,arguments)},We.prototype.mergeWith=function(t){return ft(this,t,e.call(arguments,1))},We.prototype.mergeIn=function(t){var n=e.call(arguments,1);return this.updateIn(t,ot(),(function(e){return"function"==typeof e.merge?e.merge.apply(e,n):n[n.length-1]}))},We.prototype.mergeDeep=function(){return ft(this,ht,arguments)},We.prototype.mergeDeepWith=function(t){var n=e.call(arguments,1);return ft(this,dt(t),n)},We.prototype.mergeDeepIn=function(t){var n=e.call(arguments,1);return this.updateIn(t,ot(),(function(e){return"function"==typeof e.mergeDeep?e.mergeDeep.apply(e,n):n[n.length-1]}))},We.prototype.sort=function(e){return zt(pn(this,e))},We.prototype.sortBy=function(e,t){return zt(pn(this,t,e))},We.prototype.withMutations=function(e){var t=this.asMutable();return e(t),t.wasAltered()?t.__ensureOwner(this.__ownerID):this},We.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new C)},We.prototype.asImmutable=function(){return this.__ensureOwner()},We.prototype.wasAltered=function(){return this.__altered},We.prototype.__iterator=function(e,t){return new et(this,e,t)},We.prototype.__iterate=function(e,t){var n=this,r=0;return this._root&&this._root.iterate((function(t){return r++,e(t[1],t[0],n)}),t),r},We.prototype.__ensureOwner=function(e){return e===this.__ownerID?this:e?rt(this.size,this._root,e,this.__hash):(this.__ownerID=e,this.__altered=!1,this)},We.isMap=He;var Je,$e="@@__IMMUTABLE_MAP__@@",Ke=We.prototype;function Ye(e,t){this.ownerID=e,this.entries=t}function Ge(e,t,n){this.ownerID=e,this.bitmap=t,this.nodes=n}function Ze(e,t,n){this.ownerID=e,this.count=t,this.nodes=n}function Xe(e,t,n){this.ownerID=e,this.keyHash=t,this.entries=n}function Qe(e,t,n){this.ownerID=e,this.keyHash=t,this.entry=n}function et(e,t,n){this._type=t,this._reverse=n,this._stack=e._root&&nt(e._root)}function tt(e,t){return U(e,t[0],t[1])}function nt(e,t){return{node:e,index:0,__prev:t}}function rt(e,t,n,r){var o=Object.create(Ke);return o.size=e,o._root=t,o.__ownerID=n,o.__hash=r,o.__altered=!1,o}function ot(){return Je||(Je=rt(0))}function at(e,t,n){var r,o;if(e._root){var a=x(_),i=x(w);if(r=it(e._root,e.__ownerID,0,void 0,t,n,a,i),!i.value)return e;o=e.size+(a.value?n===b?-1:1:0)}else{if(n===b)return e;o=1,r=new Ye(e.__ownerID,[[t,n]])}return e.__ownerID?(e.size=o,e._root=r,e.__hash=void 0,e.__altered=!0,e):r?rt(o,r):ot()}function it(e,t,n,r,o,a,i,s){return e?e.update(t,n,r,o,a,i,s):a===b?e:(E(s),E(i),new Qe(t,r,[o,a]))}function st(e){return e.constructor===Qe||e.constructor===Xe}function ut(e,t,n,r,o){if(e.keyHash===r)return new Xe(t,r,[e.entry,o]);var a,i=(0===n?e.keyHash:e.keyHash>>>n)&y,s=(0===n?r:r>>>n)&y;return new Ge(t,1<>>=1)i[s]=1&n?t[a++]:void 0;return i[r]=o,new Ze(e,a+1,i)}function ft(e,t,n){for(var o=[],a=0;a>1&1431655765))+(e>>2&858993459))+(e>>4)&252645135,e+=e>>8,127&(e+=e>>16)}function yt(e,t,n,r){var o=r?e:S(e);return o[t]=n,o}function bt(e,t,n,r){var o=e.length+1;if(r&&t+1===o)return e[t]=n,e;for(var a=new Array(o),i=0,s=0;s=wt)return ct(e,u,r,o);var f=e&&e===this.ownerID,h=f?u:S(u);return p?s?c===l-1?h.pop():h[c]=h.pop():h[c]=[r,o]:h.push([r,o]),f?(this.entries=h,this):new Ye(e,h)}},Ge.prototype.get=function(e,t,n,r){void 0===t&&(t=Oe(n));var o=1<<((0===e?t:t>>>e)&y),a=this.bitmap;return 0==(a&o)?r:this.nodes[gt(a&o-1)].get(e+m,t,n,r)},Ge.prototype.update=function(e,t,n,r,o,a,i){void 0===n&&(n=Oe(r));var s=(0===t?n:n>>>t)&y,u=1<=xt)return pt(e,f,c,s,d);if(l&&!d&&2===f.length&&st(f[1^p]))return f[1^p];if(l&&d&&1===f.length&&st(d))return d;var v=e&&e===this.ownerID,g=l?d?c:c^u:c|u,_=l?d?yt(f,p,d,v):_t(f,p,v):bt(f,p,d,v);return v?(this.bitmap=g,this.nodes=_,this):new Ge(e,g,_)},Ze.prototype.get=function(e,t,n,r){void 0===t&&(t=Oe(n));var o=(0===e?t:t>>>e)&y,a=this.nodes[o];return a?a.get(e+m,t,n,r):r},Ze.prototype.update=function(e,t,n,r,o,a,i){void 0===n&&(n=Oe(r));var s=(0===t?n:n>>>t)&y,u=o===b,c=this.nodes,l=c[s];if(u&&!l)return this;var p=it(l,e,t+m,n,r,o,a,i);if(p===l)return this;var f=this.count;if(l){if(!p&&--f0&&r=0&&e>>t&y;if(r>=this.array.length)return new Ot([],e);var o,a=0===r;if(t>0){var i=this.array[r];if((o=i&&i.removeBefore(e,t-m,n))===i&&a)return this}if(a&&!o)return this;var s=Lt(this,e);if(!a)for(var u=0;u>>t&y;if(o>=this.array.length)return this;if(t>0){var a=this.array[o];if((r=a&&a.removeAfter(e,t-m,n))===a&&o===this.array.length-1)return this}var i=Lt(this,e);return i.array.splice(o+1),r&&(i.array[o]=r),i};var jt,Tt,It={};function Nt(e,t){var n=e._origin,r=e._capacity,o=qt(r),a=e._tail;return i(e._root,e._level,0);function i(e,t,n){return 0===t?s(e,n):u(e,t,n)}function s(e,i){var s=i===o?a&&a.array:e&&e.array,u=i>n?0:n-i,c=r-i;return c>g&&(c=g),function(){if(u===c)return It;var e=t?--c:u++;return s&&s[e]}}function u(e,o,a){var s,u=e&&e.array,c=a>n?0:n-a>>o,l=1+(r-a>>o);return l>g&&(l=g),function(){for(;;){if(s){var e=s();if(e!==It)return e;s=null}if(c===l)return It;var n=t?--l:c++;s=i(u&&u[n],o-m,a+(n<=e.size||t<0)return e.withMutations((function(e){t<0?Ft(e,t).set(0,n):Ft(e,0,t+1).set(t,n)}));t+=e._origin;var r=e._tail,o=e._root,a=x(w);return t>=qt(e._capacity)?r=Dt(r,e.__ownerID,0,t,n,a):o=Dt(o,e.__ownerID,e._level,t,n,a),a.value?e.__ownerID?(e._root=o,e._tail=r,e.__hash=void 0,e.__altered=!0,e):Mt(e._origin,e._capacity,e._level,o,r):e}function Dt(e,t,n,r,o,a){var i,s=r>>>n&y,u=e&&s0){var c=e&&e.array[s],l=Dt(c,t,n-m,r,o,a);return l===c?e:((i=Lt(e,t)).array[s]=l,i)}return u&&e.array[s]===o?e:(E(a),i=Lt(e,t),void 0===o&&s===i.array.length-1?i.array.pop():i.array[s]=o,i)}function Lt(e,t){return t&&e&&t===e.ownerID?e:new Ot(e?e.array.slice():[],t)}function Bt(e,t){if(t>=qt(e._capacity))return e._tail;if(t<1<0;)n=n.array[t>>>r&y],r-=m;return n}}function Ft(e,t,n){void 0!==t&&(t|=0),void 0!==n&&(n|=0);var r=e.__ownerID||new C,o=e._origin,a=e._capacity,i=o+t,s=void 0===n?a:n<0?a+n:o+n;if(i===o&&s===a)return e;if(i>=s)return e.clear();for(var u=e._level,c=e._root,l=0;i+l<0;)c=new Ot(c&&c.array.length?[void 0,c]:[],r),l+=1<<(u+=m);l&&(i+=l,o+=l,s+=l,a+=l);for(var p=qt(a),f=qt(s);f>=1<p?new Ot([],r):h;if(h&&f>p&&im;g-=m){var b=p>>>g&y;v=v.array[b]=Lt(v.array[b],r)}v.array[p>>>m&y]=h}if(s=f)i-=f,s-=f,u=m,c=null,d=d&&d.removeBefore(r,0,i);else if(i>o||f>>u&y;if(_!==f>>>u&y)break;_&&(l+=(1<o&&(c=c.removeBefore(r,u,i-l)),c&&fa&&(a=c.size),i(u)||(c=c.map((function(e){return he(e)}))),r.push(c)}return a>e.size&&(e=e.setSize(a)),vt(e,t,r)}function qt(e){return e>>m<=g&&i.size>=2*a.size?(r=(o=i.filter((function(e,t){return void 0!==e&&s!==t}))).toKeyedSeq().map((function(e){return e[0]})).flip().toMap(),e.__ownerID&&(r.__ownerID=o.__ownerID=e.__ownerID)):(r=a.remove(t),o=s===i.size-1?i.pop():i.set(s,void 0))}else if(u){if(n===i.get(s)[1])return e;r=a,o=i.set(s,[t,n])}else r=a.set(t,i.size),o=i.set(i.size,[t,n]);return e.__ownerID?(e.size=r.size,e._map=r,e._list=o,e.__hash=void 0,e):Wt(r,o)}function $t(e,t){this._iter=e,this._useKeys=t,this.size=e.size}function Kt(e){this._iter=e,this.size=e.size}function Yt(e){this._iter=e,this.size=e.size}function Gt(e){this._iter=e,this.size=e.size}function Zt(e){var t=bn(e);return t._iter=e,t.size=e.size,t.flip=function(){return e},t.reverse=function(){var t=e.reverse.apply(this);return t.flip=function(){return e.reverse()},t},t.has=function(t){return e.includes(t)},t.includes=function(t){return e.has(t)},t.cacheResult=_n,t.__iterateUncached=function(t,n){var r=this;return e.__iterate((function(e,n){return!1!==t(n,e,r)}),n)},t.__iteratorUncached=function(t,n){if(t===R){var r=e.__iterator(t,n);return new F((function(){var e=r.next();if(!e.done){var t=e.value[0];e.value[0]=e.value[1],e.value[1]=t}return e}))}return e.__iterator(t===P?M:P,n)},t}function Xt(e,t,n){var r=bn(e);return r.size=e.size,r.has=function(t){return e.has(t)},r.get=function(r,o){var a=e.get(r,b);return a===b?o:t.call(n,a,r,e)},r.__iterateUncached=function(r,o){var a=this;return e.__iterate((function(e,o,i){return!1!==r(t.call(n,e,o,i),o,a)}),o)},r.__iteratorUncached=function(r,o){var a=e.__iterator(R,o);return new F((function(){var o=a.next();if(o.done)return o;var i=o.value,s=i[0];return U(r,s,t.call(n,i[1],s,e),o)}))},r}function Qt(e,t){var n=bn(e);return n._iter=e,n.size=e.size,n.reverse=function(){return e},e.flip&&(n.flip=function(){var t=Zt(e);return t.reverse=function(){return e.flip()},t}),n.get=function(n,r){return e.get(t?n:-1-n,r)},n.has=function(n){return e.has(t?n:-1-n)},n.includes=function(t){return e.includes(t)},n.cacheResult=_n,n.__iterate=function(t,n){var r=this;return e.__iterate((function(e,n){return t(e,n,r)}),!n)},n.__iterator=function(t,n){return e.__iterator(t,!n)},n}function en(e,t,n,r){var o=bn(e);return r&&(o.has=function(r){var o=e.get(r,b);return o!==b&&!!t.call(n,o,r,e)},o.get=function(r,o){var a=e.get(r,b);return a!==b&&t.call(n,a,r,e)?a:o}),o.__iterateUncached=function(o,a){var i=this,s=0;return e.__iterate((function(e,a,u){if(t.call(n,e,a,u))return s++,o(e,r?a:s-1,i)}),a),s},o.__iteratorUncached=function(o,a){var i=e.__iterator(R,a),s=0;return new F((function(){for(;;){var a=i.next();if(a.done)return a;var u=a.value,c=u[0],l=u[1];if(t.call(n,l,c,e))return U(o,r?c:s++,l,a)}}))},o}function tn(e,t,n){var r=We().asMutable();return e.__iterate((function(o,a){r.update(t.call(n,o,a,e),0,(function(e){return e+1}))})),r.asImmutable()}function nn(e,t,n){var r=s(e),o=(l(e)?zt():We()).asMutable();e.__iterate((function(a,i){o.update(t.call(n,a,i,e),(function(e){return(e=e||[]).push(r?[i,a]:a),e}))}));var a=yn(e);return o.map((function(t){return vn(e,a(t))}))}function rn(e,t,n,r){var o=e.size;if(void 0!==t&&(t|=0),void 0!==n&&(n===1/0?n=o:n|=0),j(t,n,o))return e;var a=T(t,o),i=I(n,o);if(a!=a||i!=i)return rn(e.toSeq().cacheResult(),t,n,r);var s,u=i-a;u==u&&(s=u<0?0:u);var c=bn(e);return c.size=0===s?s:e.size&&s||void 0,!r&&ae(e)&&s>=0&&(c.get=function(t,n){return(t=k(this,t))>=0&&ts)return q();var e=o.next();return r||t===P?e:U(t,u-1,t===M?void 0:e.value[1],e)}))},c}function on(e,t,n){var r=bn(e);return r.__iterateUncached=function(r,o){var a=this;if(o)return this.cacheResult().__iterate(r,o);var i=0;return e.__iterate((function(e,o,s){return t.call(n,e,o,s)&&++i&&r(e,o,a)})),i},r.__iteratorUncached=function(r,o){var a=this;if(o)return this.cacheResult().__iterator(r,o);var i=e.__iterator(R,o),s=!0;return new F((function(){if(!s)return q();var e=i.next();if(e.done)return e;var o=e.value,u=o[0],c=o[1];return t.call(n,c,u,a)?r===R?e:U(r,u,c,e):(s=!1,q())}))},r}function an(e,t,n,r){var o=bn(e);return o.__iterateUncached=function(o,a){var i=this;if(a)return this.cacheResult().__iterate(o,a);var s=!0,u=0;return e.__iterate((function(e,a,c){if(!s||!(s=t.call(n,e,a,c)))return u++,o(e,r?a:u-1,i)})),u},o.__iteratorUncached=function(o,a){var i=this;if(a)return this.cacheResult().__iterator(o,a);var s=e.__iterator(R,a),u=!0,c=0;return new F((function(){var e,a,l;do{if((e=s.next()).done)return r||o===P?e:U(o,c++,o===M?void 0:e.value[1],e);var p=e.value;a=p[0],l=p[1],u&&(u=t.call(n,l,a,i))}while(u);return o===R?e:U(o,a,l,e)}))},o}function sn(e,t){var n=s(e),o=[e].concat(t).map((function(e){return i(e)?n&&(e=r(e)):e=n?se(e):ue(Array.isArray(e)?e:[e]),e})).filter((function(e){return 0!==e.size}));if(0===o.length)return e;if(1===o.length){var a=o[0];if(a===e||n&&s(a)||u(e)&&u(a))return a}var c=new te(o);return n?c=c.toKeyedSeq():u(e)||(c=c.toSetSeq()),(c=c.flatten(!0)).size=o.reduce((function(e,t){if(void 0!==e){var n=t.size;if(void 0!==n)return e+n}}),0),c}function un(e,t,n){var r=bn(e);return r.__iterateUncached=function(r,o){var a=0,s=!1;function u(e,c){var l=this;e.__iterate((function(e,o){return(!t||c0}function dn(e,t,r){var o=bn(e);return o.size=new te(r).map((function(e){return e.size})).min(),o.__iterate=function(e,t){for(var n,r=this.__iterator(P,t),o=0;!(n=r.next()).done&&!1!==e(n.value,o++,this););return o},o.__iteratorUncached=function(e,o){var a=r.map((function(e){return e=n(e),W(o?e.reverse():e)})),i=0,s=!1;return new F((function(){var n;return s||(n=a.map((function(e){return e.next()})),s=n.some((function(e){return e.done}))),s?q():U(e,i++,t.apply(null,n.map((function(e){return e.value}))))}))},o}function vn(e,t){return ae(e)?t:e.constructor(t)}function mn(e){if(e!==Object(e))throw new TypeError("Expected [K, V] tuple: "+e)}function gn(e){return Ve(e.size),A(e)}function yn(e){return s(e)?r:u(e)?o:a}function bn(e){return Object.create((s(e)?K:u(e)?Y:G).prototype)}function _n(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):$.prototype.cacheResult.call(this)}function wn(e,t){return e>t?1:e=0;n--)t={value:arguments[n],next:t};return this.__ownerID?(this.size=e,this._head=t,this.__hash=void 0,this.__altered=!0,this):Kn(e,t)},Vn.prototype.pushAll=function(e){if(0===(e=o(e)).size)return this;Ve(e.size);var t=this.size,n=this._head;return e.reverse().forEach((function(e){t++,n={value:e,next:n}})),this.__ownerID?(this.size=t,this._head=n,this.__hash=void 0,this.__altered=!0,this):Kn(t,n)},Vn.prototype.pop=function(){return this.slice(1)},Vn.prototype.unshift=function(){return this.push.apply(this,arguments)},Vn.prototype.unshiftAll=function(e){return this.pushAll(e)},Vn.prototype.shift=function(){return this.pop.apply(this,arguments)},Vn.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):Yn()},Vn.prototype.slice=function(e,t){if(j(e,t,this.size))return this;var n=T(e,this.size);if(I(t,this.size)!==this.size)return Ce.prototype.slice.call(this,e,t);for(var r=this.size-n,o=this._head;n--;)o=o.next;return this.__ownerID?(this.size=r,this._head=o,this.__hash=void 0,this.__altered=!0,this):Kn(r,o)},Vn.prototype.__ensureOwner=function(e){return e===this.__ownerID?this:e?Kn(this.size,this._head,e,this.__hash):(this.__ownerID=e,this.__altered=!1,this)},Vn.prototype.__iterate=function(e,t){if(t)return this.reverse().__iterate(e);for(var n=0,r=this._head;r&&!1!==e(r.value,n++,this);)r=r.next;return n},Vn.prototype.__iterator=function(e,t){if(t)return this.reverse().__iterator(e);var n=0,r=this._head;return new F((function(){if(r){var t=r.value;return r=r.next,U(e,n++,t)}return q()}))},Vn.isStack=Wn;var Hn,Jn="@@__IMMUTABLE_STACK__@@",$n=Vn.prototype;function Kn(e,t,n,r){var o=Object.create($n);return o.size=e,o._head=t,o.__ownerID=n,o.__hash=r,o.__altered=!1,o}function Yn(){return Hn||(Hn=Kn(0))}function Gn(e,t){var n=function(n){e.prototype[n]=t[n]};return Object.keys(t).forEach(n),Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(t).forEach(n),e}$n[Jn]=!0,$n.withMutations=Ke.withMutations,$n.asMutable=Ke.asMutable,$n.asImmutable=Ke.asImmutable,$n.wasAltered=Ke.wasAltered,n.Iterator=F,Gn(n,{toArray:function(){Ve(this.size);var e=new Array(this.size||0);return this.valueSeq().__iterate((function(t,n){e[n]=t})),e},toIndexedSeq:function(){return new Kt(this)},toJS:function(){return this.toSeq().map((function(e){return e&&"function"==typeof e.toJS?e.toJS():e})).__toJS()},toJSON:function(){return this.toSeq().map((function(e){return e&&"function"==typeof e.toJSON?e.toJSON():e})).__toJS()},toKeyedSeq:function(){return new $t(this,!0)},toMap:function(){return We(this.toKeyedSeq())},toObject:function(){Ve(this.size);var e={};return this.__iterate((function(t,n){e[n]=t})),e},toOrderedMap:function(){return zt(this.toKeyedSeq())},toOrderedSet:function(){return Ln(s(this)?this.valueSeq():this)},toSet:function(){return jn(s(this)?this.valueSeq():this)},toSetSeq:function(){return new Yt(this)},toSeq:function(){return u(this)?this.toIndexedSeq():s(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return Vn(s(this)?this.valueSeq():this)},toList:function(){return Ct(s(this)?this.valueSeq():this)},toString:function(){return"[Iterable]"},__toString:function(e,t){return 0===this.size?e+t:e+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+t},concat:function(){return vn(this,sn(this,e.call(arguments,0)))},includes:function(e){return this.some((function(t){return ge(t,e)}))},entries:function(){return this.__iterator(R)},every:function(e,t){Ve(this.size);var n=!0;return this.__iterate((function(r,o,a){if(!e.call(t,r,o,a))return n=!1,!1})),n},filter:function(e,t){return vn(this,en(this,e,t,!0))},find:function(e,t,n){var r=this.findEntry(e,t);return r?r[1]:n},forEach:function(e,t){return Ve(this.size),this.__iterate(t?e.bind(t):e)},join:function(e){Ve(this.size),e=void 0!==e?""+e:",";var t="",n=!0;return this.__iterate((function(r){n?n=!1:t+=e,t+=null!=r?r.toString():""})),t},keys:function(){return this.__iterator(M)},map:function(e,t){return vn(this,Xt(this,e,t))},reduce:function(e,t,n){var r,o;return Ve(this.size),arguments.length<2?o=!0:r=t,this.__iterate((function(t,a,i){o?(o=!1,r=t):r=e.call(n,r,t,a,i)})),r},reduceRight:function(e,t,n){var r=this.toKeyedSeq().reverse();return r.reduce.apply(r,arguments)},reverse:function(){return vn(this,Qt(this,!0))},slice:function(e,t){return vn(this,rn(this,e,t,!0))},some:function(e,t){return!this.every(tr(e),t)},sort:function(e){return vn(this,pn(this,e))},values:function(){return this.__iterator(P)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some((function(){return!0}))},count:function(e,t){return A(e?this.toSeq().filter(e,t):this)},countBy:function(e,t){return tn(this,e,t)},equals:function(e){return ye(this,e)},entrySeq:function(){var e=this;if(e._cache)return new te(e._cache);var t=e.toSeq().map(er).toIndexedSeq();return t.fromEntrySeq=function(){return e.toSeq()},t},filterNot:function(e,t){return this.filter(tr(e),t)},findEntry:function(e,t,n){var r=n;return this.__iterate((function(n,o,a){if(e.call(t,n,o,a))return r=[o,n],!1})),r},findKey:function(e,t){var n=this.findEntry(e,t);return n&&n[0]},findLast:function(e,t,n){return this.toKeyedSeq().reverse().find(e,t,n)},findLastEntry:function(e,t,n){return this.toKeyedSeq().reverse().findEntry(e,t,n)},findLastKey:function(e,t){return this.toKeyedSeq().reverse().findKey(e,t)},first:function(){return this.find(O)},flatMap:function(e,t){return vn(this,cn(this,e,t))},flatten:function(e){return vn(this,un(this,e,!0))},fromEntrySeq:function(){return new Gt(this)},get:function(e,t){return this.find((function(t,n){return ge(n,e)}),void 0,t)},getIn:function(e,t){for(var n,r=this,o=xn(e);!(n=o.next()).done;){var a=n.value;if((r=r&&r.get?r.get(a,b):b)===b)return t}return r},groupBy:function(e,t){return nn(this,e,t)},has:function(e){return this.get(e,b)!==b},hasIn:function(e){return this.getIn(e,b)!==b},isSubset:function(e){return e="function"==typeof e.includes?e:n(e),this.every((function(t){return e.includes(t)}))},isSuperset:function(e){return(e="function"==typeof e.isSubset?e:n(e)).isSubset(this)},keyOf:function(e){return this.findKey((function(t){return ge(t,e)}))},keySeq:function(){return this.toSeq().map(Qn).toIndexedSeq()},last:function(){return this.toSeq().reverse().first()},lastKeyOf:function(e){return this.toKeyedSeq().reverse().keyOf(e)},max:function(e){return fn(this,e)},maxBy:function(e,t){return fn(this,t,e)},min:function(e){return fn(this,e?nr(e):ar)},minBy:function(e,t){return fn(this,t?nr(t):ar,e)},rest:function(){return this.slice(1)},skip:function(e){return this.slice(Math.max(0,e))},skipLast:function(e){return vn(this,this.toSeq().reverse().skip(e).reverse())},skipWhile:function(e,t){return vn(this,an(this,e,t,!0))},skipUntil:function(e,t){return this.skipWhile(tr(e),t)},sortBy:function(e,t){return vn(this,pn(this,t,e))},take:function(e){return this.slice(0,Math.max(0,e))},takeLast:function(e){return vn(this,this.toSeq().reverse().take(e).reverse())},takeWhile:function(e,t){return vn(this,on(this,e,t))},takeUntil:function(e,t){return this.takeWhile(tr(e),t)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=ir(this))}});var Zn=n.prototype;Zn[p]=!0,Zn[B]=Zn.values,Zn.__toJS=Zn.toArray,Zn.__toStringMapper=rr,Zn.inspect=Zn.toSource=function(){return this.toString()},Zn.chain=Zn.flatMap,Zn.contains=Zn.includes,Gn(r,{flip:function(){return vn(this,Zt(this))},mapEntries:function(e,t){var n=this,r=0;return vn(this,this.toSeq().map((function(o,a){return e.call(t,[a,o],r++,n)})).fromEntrySeq())},mapKeys:function(e,t){var n=this;return vn(this,this.toSeq().flip().map((function(r,o){return e.call(t,r,o,n)})).flip())}});var Xn=r.prototype;function Qn(e,t){return t}function er(e,t){return[t,e]}function tr(e){return function(){return!e.apply(this,arguments)}}function nr(e){return function(){return-e.apply(this,arguments)}}function rr(e){return"string"==typeof e?JSON.stringify(e):String(e)}function or(){return S(arguments)}function ar(e,t){return et?-1:0}function ir(e){if(e.size===1/0)return 0;var t=l(e),n=s(e),r=t?1:0;return sr(e.__iterate(n?t?function(e,t){r=31*r+ur(Oe(e),Oe(t))|0}:function(e,t){r=r+ur(Oe(e),Oe(t))|0}:t?function(e){r=31*r+Oe(e)|0}:function(e){r=r+Oe(e)|0}),r)}function sr(e,t){return t=Ae(t,3432918353),t=Ae(t<<15|t>>>-15,461845907),t=Ae(t<<13|t>>>-13,5),t=Ae((t=(t+3864292196|0)^e)^t>>>16,2246822507),t=ke((t=Ae(t^t>>>13,3266489909))^t>>>16)}function ur(e,t){return e^t+2654435769+(e<<6)+(e>>2)|0}return Xn[f]=!0,Xn[B]=Zn.entries,Xn.__toJS=Zn.toObject,Xn.__toStringMapper=function(e,t){return JSON.stringify(t)+": "+rr(e)},Gn(o,{toKeyedSeq:function(){return new $t(this,!1)},filter:function(e,t){return vn(this,en(this,e,t,!1))},findIndex:function(e,t){var n=this.findEntry(e,t);return n?n[0]:-1},indexOf:function(e){var t=this.keyOf(e);return void 0===t?-1:t},lastIndexOf:function(e){var t=this.lastKeyOf(e);return void 0===t?-1:t},reverse:function(){return vn(this,Qt(this,!1))},slice:function(e,t){return vn(this,rn(this,e,t,!1))},splice:function(e,t){var n=arguments.length;if(t=Math.max(0|t,0),0===n||2===n&&!t)return this;e=T(e,e<0?this.count():this.size);var r=this.slice(0,e);return vn(this,1===n?r:r.concat(S(arguments,2),this.slice(e+t)))},findLastIndex:function(e,t){var n=this.findLastEntry(e,t);return n?n[0]:-1},first:function(){return this.get(0)},flatten:function(e){return vn(this,un(this,e,!1))},get:function(e,t){return(e=k(this,e))<0||this.size===1/0||void 0!==this.size&&e>this.size?t:this.find((function(t,n){return n===e}),void 0,t)},has:function(e){return(e=k(this,e))>=0&&(void 0!==this.size?this.size===1/0||e1)try{return decodeURIComponent(t[1])}catch(e){console.error(e)}return null}function Te(e){return t=e.replace(/\.[^./]*$/,""),$()(H()(t));var t}var Ie=function(e,t){if(e>t)return"Value must be less than ".concat(t)},Ne=function(e,t){if(et)return T()(n="Value must be no longer than ".concat(t," character")).call(n,1!==t?"s":"")},qe=function(e,t){var n;if(e.length2&&void 0!==arguments[2]?arguments[2]:{},r=n.isOAS3,o=void 0!==r&&r,a=n.bypassRequiredCheck,i=void 0!==a&&a,s=[],u=e.get("required"),c=Object(ue.a)(e,{isOAS3:o}),l=c.schema,p=c.parameterContentMediaType;if(!l)return s;var f=l.get("required"),h=l.get("maximum"),d=l.get("minimum"),v=l.get("type"),g=l.get("format"),y=l.get("maxLength"),b=l.get("minLength"),_=l.get("pattern");if(v&&(u||f||t)){var w="string"===v&&t,x="array"===v&&B()(t)&&t.length,E="array"===v&&z.a.List.isList(t)&&t.count(),C="array"===v&&"string"==typeof t&&t,S="file"===v&&t instanceof ae.a.File,A="boolean"===v&&(t||!1===t),k="number"===v&&(t||0===t),j="integer"===v&&(t||0===t),T="object"===v&&"object"===U()(t)&&null!==t,I="object"===v&&"string"==typeof t&&t,N=[w,x,E,C,S,A,k,j,T,I],M=m()(N).call(N,(function(e){return!!e}));if((u||f)&&!M&&!i)return s.push("Required field is not provided"),s;if("object"===v&&"string"==typeof t&&(null===p||"application/json"===p))try{JSON.parse(t)}catch(e){return s.push("Parameter string value must be valid JSON"),s}if(_){var P=ze(t,_);P&&s.push(P)}if(y||0===y){var R=Ue(t,y);R&&s.push(R)}if(b){var D=qe(t,b);D&&s.push(D)}if(h||0===h){var L=Ie(t,h);L&&s.push(L)}if(d||0===d){var F=Ne(t,d);F&&s.push(F)}if("string"===v){var q;if(!(q="date-time"===g?Be(t):"uuid"===g?Fe(t):Le(t)))return s;s.push(q)}else if("boolean"===v){var V=De(t);if(!V)return s;s.push(V)}else if("number"===v){var W=Me(t);if(!W)return s;s.push(W)}else if("integer"===v){var H=Pe(t);if(!H)return s;s.push(H)}else if("array"===v){var J;if(!E||!t.count())return s;J=l.getIn(["items","type"]),O()(t).call(t,(function(e,t){var n;"number"===J?n=Me(e):"integer"===J?n=Pe(e):"string"===J&&(n=Le(e)),n&&s.push({index:t,error:n})}))}else if("file"===v){var $=Re(t);if(!$)return s;s.push($)}}return s},We=function(e,t,n){if(e&&(!e.xml||!e.xml.name)){if(e.xml=e.xml||{},!e.$$ref)return e.type||e.items||e.properties||e.additionalProperties?'\n\x3c!-- XML example cannot be generated; root element name is undefined --\x3e':null;var r=e.$$ref.match(/\S*\/(\S+)$/);e.xml.name=r[1]}return Object(oe.memoizedCreateXMLExample)(e,t,n)},He=[{when:/json/,shouldStringifyTypes:["string"]}],Je=["object"],$e=function(e,t,n,r){var o=Object(oe.memoizedSampleFromSchema)(e,t,r),a=U()(o),i=x()(He).call(He,(function(e,t){var r;return t.when.test(n)?T()(r=[]).call(r,d()(e),d()(t.shouldStringifyTypes)):e}),Je);return Q()(i,(function(e){return e===a}))?f()(o,null,2):o},Ke=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:void 0;return e&&we(e.toJS)&&(e=e.toJS()),r&&we(r.toJS)&&(r=r.toJS()),/xml/.test(t)?We(e,n,r):$e(e,n,t,r)},Ye=function(){var e={},t=ae.a.location.search;if(!t)return{};if(""!=t){var n=t.substr(1).split("&");for(var r in n)n.hasOwnProperty(r)&&(r=n[r].split("="),e[decodeURIComponent(r[0])]=r[1]&&decodeURIComponent(r[1])||"")}return e},Ge=function(t){return(t instanceof e?t:e.from(t.toString(),"utf-8")).toString("base64")},Ze={operationsSorter:{alpha:function(e,t){return e.get("path").localeCompare(t.get("path"))},method:function(e,t){return e.get("method").localeCompare(t.get("method"))}},tagsSorter:{alpha:function(e,t){return e.localeCompare(t)}}},Xe=function(e){var t=[];for(var n in e){var r=e[n];void 0!==r&&""!==r&&t.push([n,"=",encodeURIComponent(r).replace(/%20/g,"+")].join(""))}return t.join("&")},Qe=function(e,t,n){return!!Z()(n,(function(n){return te()(e[n],t[n])}))};function et(e){return"string"!=typeof e||""===e?"":Object(V.sanitizeUrl)(e)}function tt(e){return!(!e||l()(e).call(e,"localhost")>=0||l()(e).call(e,"127.0.0.1")>=0||"none"===e)}function nt(e){if(!z.a.OrderedMap.isOrderedMap(e))return null;if(!e.size)return null;var t=u()(e).call(e,(function(e,t){return i()(t).call(t,"2")&&C()(e.get("content")||{}).length>0})),n=e.get("default")||z.a.OrderedMap(),r=(n.get("content")||z.a.OrderedMap()).keySeq().toJS().length?n:null;return t||r}var rt=function(e){return"string"==typeof e||e instanceof String?o()(e).call(e).replace(/\s/g,"%20"):""},ot=function(e){return se()(rt(e).replace(/%20/g,"_"))},at=function(e){return A()(e).call(e,(function(e,t){return/^x-/.test(t)}))},it=function(e){return A()(e).call(e,(function(e,t){return/^pattern|maxLength|minLength|maximum|minimum/.test(t)}))};function st(e,t){var n,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){return!0};if("object"!==U()(e)||B()(e)||null===e||!t)return e;var o=_()({},e);return O()(n=C()(o)).call(n,(function(e){e===t&&r(o[e],e)?delete o[e]:o[e]=st(o[e],t,r)})),o}function ut(e){if("string"==typeof e)return e;if(e&&e.toJS&&(e=e.toJS()),"object"===U()(e)&&null!==e)try{return f()(e,null,2)}catch(t){return String(e)}return null==e?"":e.toString()}function ct(e){return"number"==typeof e?e.toString():e}function lt(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.returnAll,r=void 0!==n&&n,o=t.allowHashes,a=void 0===o||o;if(!z.a.Map.isMap(e))throw new Error("paramToIdentifier: received a non-Im.Map parameter as input");var i,s,u,c=e.get("name"),l=e.get("in"),p=[];e&&e.hashCode&&l&&c&&a&&p.push(T()(i=T()(s="".concat(l,".")).call(s,c,".hash-")).call(i,e.hashCode()));l&&c&&p.push(T()(u="".concat(l,".")).call(u,c));return p.push(c),r?p:p[0]||""}function pt(e,t){var n,r=lt(e,{returnAll:!0});return A()(n=D()(r).call(r,(function(e){return t[e]}))).call(n,(function(e){return void 0!==e}))[0]}function ft(){return dt(le()(32).toString("base64"))}function ht(e){return dt(fe()("sha256").update(e).digest("base64"))}function dt(e){return e.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}var vt=function(e){return!e||!(!de(e)||!e.isEmpty())}}).call(this,n(77).Buffer)},function(e,t,n){var r=n(896),o=n(899);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=r(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&o(e,t)}},function(e,t,n){var r=n(462),o=n(206),a=n(910),i=n(911);e.exports=function(e){var t=a();return function(){var n,a=o(e);if(t){var s=o(this).constructor;n=r(a,arguments,s)}else n=a.apply(this,arguments);return i(this,n)}}},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t,n){e.exports=n(989)()},function(e,t,n){e.exports=n(641)},function(e,t,n){e.exports=n(576)},function(e,t,n){e.exports=n(593)},function(e,t,n){e.exports=n(544)},function(e,t,n){var r=n(398),o=n(663),a=n(182),i=n(401);e.exports=function(e,t){return r(e)||o(e,t)||a(e,t)||i()}},function(e,t,n){var r=n(644),o=n(390),a=n(182),i=n(652);e.exports=function(e){return r(e)||o(e)||a(e)||i()}},function(e,t,n){e.exports=n(402)},function(e,t,n){"use strict";function r(e,t){return e===t}function o(e,t,n){if(null===t||null===n||t.length!==n.length)return!1;for(var r=t.length,o=0;o1?t-1:0),r=1;r1&&void 0!==arguments[1]?arguments[1]:r,n=null,a=null;return function(){return o(t,n,arguments)||(a=e.apply(null,arguments)),n=arguments,a}}))},function(e,t,n){var r=n(546),o=n(179);function a(t){return e.exports=a="function"==typeof o&&"symbol"==typeof r?function(e){return typeof e}:function(e){return e&&"function"==typeof o&&e.constructor===o&&e!==o.prototype?"symbol":typeof e},a(t)}e.exports=a},function(e,t,n){e.exports=n(600)},function(e,t,n){e.exports=n(588)},function(e,t,n){e.exports=n(597)},function(e,t,n){"use strict";var r=n(41),o=n(106).f,a=n(354),i=n(34),s=n(109),u=n(70),c=n(52),l=function(e){var t=function(t,n,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,r)}return e.apply(this,arguments)};return t.prototype=e.prototype,t};e.exports=function(e,t){var n,p,f,h,d,v,m,g,y=e.target,b=e.global,_=e.stat,w=e.proto,x=b?r:_?r[y]:(r[y]||{}).prototype,E=b?i:i[y]||(i[y]={}),C=E.prototype;for(f in t)n=!a(b?f:y+(_?".":"#")+f,e.forced)&&x&&c(x,f),d=E[f],n&&(v=e.noTargetGet?(g=o(x,f))&&g.value:x[f]),h=n&&v?v:t[f],n&&typeof d==typeof h||(m=e.bind&&n?s(h,r):e.wrap&&n?l(h):w&&"function"==typeof h?s(Function.call,h):h,(e.sham||h&&h.sham||d&&d.sham)&&u(m,"sham",!0),E[f]=m,w&&(c(i,p=y+"Prototype")||u(i,p,{}),i[p][f]=h,e.real&&C&&!C[f]&&u(C,f,h)))}},function(e,t,n){var r=n(240),o=n(833),a=n(837),i=n(842),s=n(443),u=n(847),c=n(444),l=n(445),p=n(3);function f(e,t){var n=l(e);if(c){var r=c(e);t&&(r=u(r).call(r,(function(t){return s(e,t).enumerable}))),n.push.apply(n,r)}return n}e.exports=function(e){for(var t=1;t>",a={listOf:function(e){return c(e,"List",r.List.isList)},mapOf:function(e,t){return p(e,t,"Map",r.Map.isMap)},orderedMapOf:function(e,t){return p(e,t,"OrderedMap",r.OrderedMap.isOrderedMap)},setOf:function(e){return c(e,"Set",r.Set.isSet)},orderedSetOf:function(e){return c(e,"OrderedSet",r.OrderedSet.isOrderedSet)},stackOf:function(e){return c(e,"Stack",r.Stack.isStack)},iterableOf:function(e){return c(e,"Iterable",r.Iterable.isIterable)},recordOf:function(e){return s((function(t,n,o,a,s){for(var u=arguments.length,c=Array(u>5?u-5:0),l=5;l6?u-6:0),l=6;l5?c-5:0),p=5;p5?i-5:0),u=5;u key("+l[p]+")"].concat(s));if(h instanceof Error)return h}}))}function p(e,t,n,r){return s((function(){for(var o=arguments.length,a=Array(o),i=0;i5?c-5:0),p=5;p4)}function l(e){var t=e.get("swagger");return"string"==typeof t&&i()(t).call(t,"2.0")}function p(e){return function(t,n){return function(r){return n&&n.specSelectors&&n.specSelectors.specJson?c(n.specSelectors.specJson())?u.a.createElement(e,o()({},r,n,{Ori:t})):u.a.createElement(t,r):(console.warn("OAS3 wrapper: couldn't get spec"),null)}}}},function(e,t,n){var r=n(41),o=n(228),a=n(52),i=n(177),s=n(229),u=n(359),c=o("wks"),l=r.Symbol,p=u?l:l&&l.withoutSetter||i;e.exports=function(e){return a(c,e)||(s&&a(l,e)?c[e]=l[e]:c[e]=p("Symbol."+e)),c[e]}},function(e,t,n){"use strict";var r=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;function i(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,s,u=i(e),c=1;c0){var o=P()(n).call(n,(function(e){return console.error(e),e.line=e.fullPath?g(y,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",N()(e,"message",{enumerable:!0,value:e.message}),e}));a.newThrownErrBatch(o)}return r.updateResolved(t)}))}},Ee=[],Ce=Y()(T()(C.a.mark((function e(){var t,n,r,o,a,i,s,u,c,l,p,f,h,d,v,m,g;return C.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(t=Ee.system){e.next=4;break}return console.error("debResolveSubtrees: don't have a system to operate on, aborting."),e.abrupt("return");case 4:if(n=t.errActions,r=t.errSelectors,o=t.fn,a=o.resolveSubtree,i=o.AST,s=void 0===i?{}:i,u=t.specSelectors,c=t.specActions,a){e.next=8;break}return console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing."),e.abrupt("return");case 8:return l=s.getLineNumberForPath?s.getLineNumberForPath:function(){},p=u.specStr(),f=t.getConfigs(),h=f.modelPropertyMacro,d=f.parameterMacro,v=f.requestInterceptor,m=f.responseInterceptor,e.prev=11,e.next=14,O()(Ee).call(Ee,function(){var e=T()(C.a.mark((function e(t,o){var i,s,c,f,g,y,b;return C.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t;case 2:return i=e.sent,s=i.resultMap,c=i.specWithCurrentSubtrees,e.next=7,a(c,o,{baseDoc:u.url(),modelPropertyMacro:h,parameterMacro:d,requestInterceptor:v,responseInterceptor:m});case 7:return f=e.sent,g=f.errors,y=f.spec,r.allErrors().size&&n.clearBy((function(e){var t;return"thrown"!==e.get("type")||"resolver"!==e.get("source")||!A()(t=e.get("fullPath")).call(t,(function(e,t){return e===o[t]||void 0===o[t]}))})),D()(g)&&g.length>0&&(b=P()(g).call(g,(function(e){return e.line=e.fullPath?l(p,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",N()(e,"message",{enumerable:!0,value:e.message}),e})),n.newThrownErrBatch(b)),Z()(s,o,y),Z()(c,o,y),e.abrupt("return",{resultMap:s,specWithCurrentSubtrees:c});case 15:case"end":return e.stop()}}),e)})));return function(t,n){return e.apply(this,arguments)}}(),x.a.resolve({resultMap:(u.specResolvedSubtree([])||Object(q.Map)()).toJS(),specWithCurrentSubtrees:u.specJson().toJS()}));case 14:g=e.sent,delete Ee.system,Ee=[],e.next=22;break;case 19:e.prev=19,e.t0=e.catch(11),console.error(e.t0);case 22:c.updateResolvedSubtree([],g.resultMap);case 23:case"end":return e.stop()}}),e,null,[[11,19]])}))),35),Se=function(e){return function(t){var n;_()(n=P()(Ee).call(Ee,(function(e){return e.join("@@")}))).call(n,e.join("@@"))>-1||(Ee.push(e),Ee.system=t,Ce())}};function Ae(e,t,n,r,o){return{type:ne,payload:{path:e,value:r,paramName:t,paramIn:n,isXml:o}}}function ke(e,t,n,r){return{type:ne,payload:{path:e,param:t,value:n,isXml:r}}}var Oe=function(e,t){return{type:de,payload:{path:e,value:t}}},je=function(){return{type:de,payload:{path:[],value:Object(q.Map)()}}},Te=function(e,t){return{type:oe,payload:{pathMethod:e,isOAS3:t}}},Ie=function(e,t,n,r){return{type:re,payload:{pathMethod:e,paramName:t,paramIn:n,includeEmptyValue:r}}};function Ne(e){return{type:pe,payload:{pathMethod:e}}}function Me(e,t){return{type:fe,payload:{path:e,value:t,key:"consumes_value"}}}function Pe(e,t){return{type:fe,payload:{path:e,value:t,key:"produces_value"}}}var Re=function(e,t,n){return{payload:{path:e,method:t,res:n},type:ae}},De=function(e,t,n){return{payload:{path:e,method:t,req:n},type:ie}},Le=function(e,t,n){return{payload:{path:e,method:t,req:n},type:se}},Be=function(e){return{payload:e,type:ue}},Fe=function(e){return function(t){var n,r,o=t.fn,a=t.specActions,i=t.specSelectors,s=t.getConfigs,c=t.oas3Selectors,p=e.pathName,h=e.method,v=e.operation,g=s(),b=g.requestInterceptor,_=g.responseInterceptor,w=v.toJS();v&&v.get("parameters")&&y()(n=m()(r=v.get("parameters")).call(r,(function(e){return e&&!0===e.get("allowEmptyValue")}))).call(n,(function(t){if(i.parameterInclusionSettingFor([p,h],t.get("name"),t.get("in"))){e.parameters=e.parameters||{};var n=Object(X.C)(t,e.parameters);(!n||n&&0===n.size)&&(e.parameters[t.get("name")]="")}}));if(e.contextUrl=V()(i.url()).toString(),w&&w.operationId?e.operationId=w.operationId:w&&p&&h&&(e.operationId=o.opId(w,p,h)),i.isOAS3()){var x,E=d()(x="".concat(p,":")).call(x,h);e.server=c.selectedServer(E)||c.selectedServer();var S=c.serverVariables({server:e.server,namespace:E}).toJS(),A=c.serverVariables({server:e.server}).toJS();e.serverVariables=f()(S).length?S:A,e.requestContentType=c.requestContentType(p,h),e.responseContentType=c.responseContentType(p,h)||"*/*";var k=c.requestBodyValue(p,h),O=c.requestBodyInclusionSetting(p,h);if(Object(X.t)(k))e.requestBody=JSON.parse(k);else if(k&&k.toJS){var j;e.requestBody=m()(j=P()(k).call(k,(function(e){return q.Map.isMap(e)?e.get("value"):e}))).call(j,(function(e,t){return(D()(e)?0!==e.length:!Object(X.q)(e))||O.get(t)})).toJS()}else e.requestBody=k}var I=l()({},e);I=o.buildRequest(I),a.setRequest(e.pathName,e.method,I);var N=function(){var t=T()(C.a.mark((function t(n){var r,o;return C.a.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,b.apply(undefined,[n]);case 2:return r=t.sent,o=l()({},r),a.setMutatedRequest(e.pathName,e.method,o),t.abrupt("return",r);case 6:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}();e.requestInterceptor=N,e.responseInterceptor=_;var M=u()();return o.execute(e).then((function(t){t.duration=u()()-M,a.setResponse(e.pathName,e.method,t)})).catch((function(t){console.error(t),a.setResponse(e.pathName,e.method,{error:!0,err:H()(t)})}))}},Ue=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.path,n=e.method,r=i()(e,["path","method"]);return function(e){var a=e.fn.fetch,i=e.specSelectors,s=e.specActions,u=i.specJsonWithResolvedSubtrees().toJS(),c=i.operationScheme(t,n),l=i.contentTypeValues([t,n]).toJS(),p=l.requestContentType,f=l.responseContentType,h=/xml/i.test(p),d=i.parameterValues([t,n],h).toJS();return s.executeRequest(o()(o()({},r),{},{fetch:a,spec:u,pathName:t,method:n,parameters:d,requestContentType:p,scheme:c,responseContentType:f}))}};function qe(e,t){return{type:ce,payload:{path:e,method:t}}}function ze(e,t){return{type:le,payload:{path:e,method:t}}}function Ve(e,t,n){return{type:ve,payload:{scheme:e,path:t,method:n}}}},function(e,t,n){var r=n(36);e.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},function(e,t,n){var r=n(34),o=n(52),a=n(227),i=n(63).f;e.exports=function(e){var t=r.Symbol||(r.Symbol={});o(t,e)||i(t,e,{value:a.f(e)})}},function(e,t,n){"use strict";var r=n(163),o=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],a=["scalar","sequence","mapping"];e.exports=function(e,t){var n,i;if(t=t||{},Object.keys(t).forEach((function(t){if(-1===o.indexOf(t))throw new r('Unknown option "'+t+'" is met in definition of "'+e+'" YAML type.')})),this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.defaultStyle=t.defaultStyle||null,this.styleAliases=(n=t.styleAliases||null,i={},null!==n&&Object.keys(n).forEach((function(e){n[e].forEach((function(t){i[String(t)]=e}))})),i),-1===a.indexOf(this.kind))throw new r('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')}},function(e,t,n){var r=n(399),o=n(241),a=n(673),i=n(179),s=n(182);e.exports=function(e,t){var n;if(void 0===i||null==a(e)){if(o(e)||(n=s(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var u=0,c=function(){};return{s:c,n:function(){return u>=e.length?{done:!0}:{done:!1,value:e[u++]}},e:function(e){throw e},f:c}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var l,p=!0,f=!1;return{s:function(){n=r(e)},n:function(){var e=n.next();return p=e.done,e},e:function(e){f=!0,l=e},f:function(){try{p||null==n.return||n.return()}finally{if(f)throw l}}}}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t){var n=Array.isArray;e.exports=n},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){var r=n(45);e.exports=function(e){if(!r(e))throw TypeError(String(e)+" is not an object");return e}},function(e,t,n){var r=n(446),o=n(444),a=n(853);e.exports=function(e,t){if(null==e)return{};var n,i,s=a(e,t);if(o){var u=o(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}},function(e,t,n){"use strict";var r=!("undefined"==typeof window||!window.document||!window.document.createElement),o={canUseDOM:r,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:r&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:r&&!!window.screen,isInWorker:!r};e.exports=o},function(e,t,n){e.exports=n(637)},function(e,t,n){"use strict";n.r(t),n.d(t,"UPDATE_SELECTED_SERVER",(function(){return r})),n.d(t,"UPDATE_REQUEST_BODY_VALUE",(function(){return o})),n.d(t,"UPDATE_REQUEST_BODY_INCLUSION",(function(){return a})),n.d(t,"UPDATE_ACTIVE_EXAMPLES_MEMBER",(function(){return i})),n.d(t,"UPDATE_REQUEST_CONTENT_TYPE",(function(){return s})),n.d(t,"UPDATE_RESPONSE_CONTENT_TYPE",(function(){return u})),n.d(t,"UPDATE_SERVER_VARIABLE_VALUE",(function(){return c})),n.d(t,"SET_REQUEST_BODY_VALIDATE_ERROR",(function(){return l})),n.d(t,"CLEAR_REQUEST_BODY_VALIDATE_ERROR",(function(){return p})),n.d(t,"CLEAR_REQUEST_BODY_VALUE",(function(){return f})),n.d(t,"setSelectedServer",(function(){return h})),n.d(t,"setRequestBodyValue",(function(){return d})),n.d(t,"setRequestBodyInclusion",(function(){return v})),n.d(t,"setActiveExamplesMember",(function(){return m})),n.d(t,"setRequestContentType",(function(){return g})),n.d(t,"setResponseContentType",(function(){return y})),n.d(t,"setServerVariableValue",(function(){return b})),n.d(t,"setRequestBodyValidateError",(function(){return _})),n.d(t,"clearRequestBodyValidateError",(function(){return w})),n.d(t,"initRequestBodyValidateError",(function(){return x})),n.d(t,"clearRequestBodyValue",(function(){return E}));var r="oas3_set_servers",o="oas3_set_request_body_value",a="oas3_set_request_body_inclusion",i="oas3_set_active_examples_member",s="oas3_set_request_content_type",u="oas3_set_response_content_type",c="oas3_set_server_variable_value",l="oas3_set_request_body_validate_error",p="oas3_clear_request_body_validate_error",f="oas3_clear_request_body_value";function h(e,t){return{type:r,payload:{selectedServerUrl:e,namespace:t}}}function d(e){var t=e.value,n=e.pathMethod;return{type:o,payload:{value:t,pathMethod:n}}}function v(e){var t=e.value,n=e.pathMethod,r=e.name;return{type:a,payload:{value:t,pathMethod:n,name:r}}}function m(e){var t=e.name,n=e.pathMethod,r=e.contextType,o=e.contextName;return{type:i,payload:{name:t,pathMethod:n,contextType:r,contextName:o}}}function g(e){var t=e.value,n=e.pathMethod;return{type:s,payload:{value:t,pathMethod:n}}}function y(e){var t=e.value,n=e.path,r=e.method;return{type:u,payload:{value:t,path:n,method:r}}}function b(e){var t=e.server,n=e.namespace,r=e.key,o=e.val;return{type:c,payload:{server:t,namespace:n,key:r,val:o}}}var _=function(e){var t=e.path,n=e.method,r=e.validationErrors;return{type:l,payload:{path:t,method:n,validationErrors:r}}},w=function(e){var t=e.path,n=e.method;return{type:p,payload:{path:t,method:n}}},x=function(e){var t=e.pathMethod;return{type:p,payload:{path:t[0],method:t[1]}}},E=function(e){var t=e.pathMethod;return{type:f,payload:{pathMethod:t}}}},function(e,t){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},function(e,t,n){"use strict";n.d(t,"b",(function(){return b})),n.d(t,"e",(function(){return _})),n.d(t,"c",(function(){return x})),n.d(t,"a",(function(){return E})),n.d(t,"d",(function(){return C}));var r=n(51),o=n.n(r),a=n(18),i=n.n(a),s=n(35),u=n.n(s),c=n(2),l=n.n(c),p=n(20),f=n.n(p),h=n(60),d=n.n(h),v=n(349),m=n.n(v),g=function(e){return String.prototype.toLowerCase.call(e)},y=function(e){return e.replace(/[^\w]/gi,"_")};function b(e){var t=e.openapi;return!!t&&m()(t,"3")}function _(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=r.v2OperationIdCompatibilityMode;if(!e||"object"!==f()(e))return null;var a=(e.operationId||"").replace(/\s/g,"");return a.length?y(e.operationId):w(t,n,{v2OperationIdCompatibilityMode:o})}function w(e,t){var n,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=r.v2OperationIdCompatibilityMode;if(o){var a,i,s=l()(a="".concat(t.toLowerCase(),"_")).call(a,e).replace(/[\s!@#$%^&*()_+=[{\]};:<>|./?,\\'""-]/g,"_");return(s=s||l()(i="".concat(e.substring(1),"_")).call(i,t)).replace(/((_){2,})/g,"_").replace(/^(_)*/g,"").replace(/([_])*$/g,"")}return l()(n="".concat(g(t))).call(n,y(e))}function x(e,t){var n;return l()(n="".concat(g(t),"-")).call(n,e)}function E(e,t){return e&&e.paths?function(e,t){return function(e,t,n){if(!e||"object"!==f()(e)||!e.paths||"object"!==f()(e.paths))return null;var r=e.paths;for(var o in r)for(var a in r[o])if("PARAMETERS"!==a.toUpperCase()){var i=r[o][a];if(i&&"object"===f()(i)){var s={spec:e,pathName:o,method:a.toUpperCase(),operation:i},u=t(s);if(n&&u)return s}}return}(e,t,!0)||null}(e,(function(e){var n,r=e.pathName,o=e.method,a=e.operation;if(!a||"object"!==f()(a))return!1;var i=a.operationId,s=_(a,r,o),c=x(r,o);return u()(n=[s,c,i]).call(n,(function(e){return e&&e===t}))})):null}function C(e){var t=e.spec,n=t.paths,r={};if(!n||t.$$normalized)return e;for(var a in n){var s=n[a];if(d()(s)){var c=s.parameters,p=function(e){var n=s[e];if(!d()(n))return"continue";var p=_(n,a,e);if(p){r[p]?r[p].push(n):r[p]=[n];var f=r[p];if(f.length>1)i()(f).call(f,(function(e,t){var n;e.__originalOperationId=e.__originalOperationId||e.operationId,e.operationId=l()(n="".concat(p)).call(n,t+1)}));else if(void 0!==n.operationId){var h=f[0];h.__originalOperationId=h.__originalOperationId||n.operationId,h.operationId=p}}if("parameters"!==e){var v=[],m={};for(var g in t)"produces"!==g&&"consumes"!==g&&"security"!==g||(m[g]=t[g],v.push(m));if(c&&(m.parameters=c,v.push(m)),v.length){var y,b=o()(v);try{for(b.s();!(y=b.n()).done;){var w=y.value;for(var x in w)if(n[x]){if("parameters"===x){var E,C=o()(w[x]);try{var S=function(){var e,t=E.value;u()(e=n[x]).call(e,(function(e){return e.name&&e.name===t.name||e.$ref&&e.$ref===t.$ref||e.$$ref&&e.$$ref===t.$$ref||e===t}))||n[x].push(t)};for(C.s();!(E=C.n()).done;)S()}catch(e){C.e(e)}finally{C.f()}}}else n[x]=w[x]}}catch(e){b.e(e)}finally{b.f()}}}};for(var f in s)p(f)}}return t.$$normalized=!0,e}},function(e,t,n){"use strict";n.r(t),n.d(t,"NEW_THROWN_ERR",(function(){return a})),n.d(t,"NEW_THROWN_ERR_BATCH",(function(){return i})),n.d(t,"NEW_SPEC_ERR",(function(){return s})),n.d(t,"NEW_SPEC_ERR_BATCH",(function(){return u})),n.d(t,"NEW_AUTH_ERR",(function(){return c})),n.d(t,"CLEAR",(function(){return l})),n.d(t,"CLEAR_BY",(function(){return p})),n.d(t,"newThrownErr",(function(){return f})),n.d(t,"newThrownErrBatch",(function(){return h})),n.d(t,"newSpecErr",(function(){return d})),n.d(t,"newSpecErrBatch",(function(){return v})),n.d(t,"newAuthErr",(function(){return m})),n.d(t,"clear",(function(){return g})),n.d(t,"clearBy",(function(){return y}));var r=n(142),o=n.n(r),a="err_new_thrown_err",i="err_new_thrown_err_batch",s="err_new_spec_err",u="err_new_spec_err_batch",c="err_new_auth_err",l="err_clear",p="err_clear_by";function f(e){return{type:a,payload:o()(e)}}function h(e){return{type:i,payload:e}}function d(e){return{type:s,payload:e}}function v(e){return{type:u,payload:e}}function m(e){return{type:c,payload:e}}function g(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{type:l,payload:e}}function y(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){return!0};return{type:p,payload:e}}},function(e,t,n){var r=n(48),o=n(353),a=n(55),i=n(176),s=Object.defineProperty;t.f=r?s:function(e,t,n){if(a(e),t=i(t,!0),a(n),o)try{return s(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(e[t]=n.value),e}},function(e,t,n){var r=n(48),o=n(36),a=n(52),i=Object.defineProperty,s={},u=function(e){throw e};e.exports=function(e,t){if(a(s,e))return s[e];t||(t={});var n=[][e],c=!!a(t,"ACCESSORS")&&t.ACCESSORS,l=a(t,0)?t[0]:u,p=a(t,1)?t[1]:void 0;return s[e]=!!n&&!o((function(){if(c&&!r)return!0;var e={length:-1};c?i(e,1,{enumerable:!0,get:u}):e[1]=1,n.call(e,l,p)}))}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){var r=n(77),o=r.Buffer;function a(e,t){for(var n in e)t[n]=e[n]}function i(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(a(r,t),t.Buffer=i),a(o,i),i.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},i.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},i.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},i.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){var r;!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t=i())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+i().toString(16)+" bytes");return 0|e}function d(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return q(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return z(e).length;default:if(r)return q(e).length;t=(""+t).toLowerCase(),r=!0}}function v(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return T(this,t,n);case"utf8":case"utf-8":return A(this,t,n);case"ascii":return O(this,t,n);case"latin1":case"binary":return j(this,t,n);case"base64":return S(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return I(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function m(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function g(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:y(e,t,n,r,o);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):y(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function y(e,t,n,r,o){var a,i=1,s=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;i=2,s/=2,u/=2,n/=2}function c(e,t){return 1===i?e[t]:e.readUInt16BE(t*i)}if(o){var l=-1;for(a=n;as&&(n=s-u),a=n;a>=0;a--){for(var p=!0,f=0;fo&&(r=o):r=o;var a=t.length;if(a%2!=0)throw new TypeError("Invalid hex string");r>a/2&&(r=a/2);for(var i=0;i>8,o=n%256,a.push(o),a.push(r);return a}(t,e.length-n),e,n,r)}function S(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function A(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:c>223?3:c>191?2:1;if(o+p<=n)switch(p){case 1:c<128&&(l=c);break;case 2:128==(192&(a=e[o+1]))&&(u=(31&c)<<6|63&a)>127&&(l=u);break;case 3:a=e[o+1],i=e[o+2],128==(192&a)&&128==(192&i)&&(u=(15&c)<<12|(63&a)<<6|63&i)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:a=e[o+1],i=e[o+2],s=e[o+3],128==(192&a)&&128==(192&i)&&128==(192&s)&&(u=(15&c)<<18|(63&a)<<12|(63&i)<<6|63&s)>65535&&u<1114112&&(l=u)}null===l?(l=65533,p=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=p}return function(e){var t=e.length;if(t<=k)return String.fromCharCode.apply(String,e);var n="",r=0;for(;r0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},u.prototype.compare=function(e,t,n,r,o){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var a=(o>>>=0)-(r>>>=0),i=(n>>>=0)-(t>>>=0),s=Math.min(a,i),c=this.slice(r,o),l=e.slice(t,n),p=0;po)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var a=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return _(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return x(this,e,t,n);case"base64":return E(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return C(this,e,t,n);default:if(a)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),a=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var k=4096;function O(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",a=t;an)throw new RangeError("Trying to access beyond buffer length")}function M(e,t,n,r,o,a){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function P(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,a=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function R(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,a=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function D(e,t,n,r,o,a){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function L(e,t,n,r,a){return a||D(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function B(e,t,n,r,a){return a||D(e,0,n,8),o.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},u.prototype.readUInt8=function(e,t){return t||N(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||N(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||N(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||N(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||N(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||N(e,t,this.length);for(var r=this[e],o=1,a=0;++a=(o*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||N(e,t,this.length);for(var r=t,o=1,a=this[e+--r];r>0&&(o*=256);)a+=this[e+--r]*o;return a>=(o*=128)&&(a-=Math.pow(2,8*t)),a},u.prototype.readInt8=function(e,t){return t||N(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||N(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||N(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||N(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||N(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||N(e,4,this.length),o.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||N(e,4,this.length),o.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||N(e,8,this.length),o.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||N(e,8,this.length),o.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||M(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,a=0;for(this[t]=255&e;++a=0&&(a*=256);)this[t+o]=e/a&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):P(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):P(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):R(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);M(this,e,t,n,o-1,-o)}var a=0,i=1,s=0;for(this[t]=255&e;++a>0)-s&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);M(this,e,t,n,o-1,-o)}var a=n-1,i=1,s=0;for(this[t+a]=255&e;--a>=0&&(i*=256);)e<0&&0===s&&0!==this[t+a+1]&&(s=1),this[t+a]=(e/i>>0)-s&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):P(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):P(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):R(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return L(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return L(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return B(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return B(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(a<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(a=t;a55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&a.push(239,191,189);continue}if(i+1===r){(t-=3)>-1&&a.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&a.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&a.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;a.push(n)}else if(n<2048){if((t-=2)<0)break;a.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;a.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;a.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return a}function z(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(F,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function V(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(54))},function(e,t,n){e.exports=n(857)},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},function(e,t,n){var r=n(149),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t,n){"use strict";function r(e){return function(){return e}}var o=function(){};o.thatReturns=r,o.thatReturnsFalse=r(!1),o.thatReturnsTrue=r(!0),o.thatReturnsNull=r(null),o.thatReturnsThis=function(){return this},o.thatReturnsArgument=function(e){return e},e.exports=o},function(e,t,n){"use strict";var r=n(31),o=n(40),a=n(467),i=n(123),s=n(468),u=n(139),c=n(200),l=n(26),p=[],f=0,h=a.getPooled(),d=!1,v=null;function m(){x.ReactReconcileTransaction&&v||r("123")}var g=[{initialize:function(){this.dirtyComponentsLength=p.length},close:function(){this.dirtyComponentsLength!==p.length?(p.splice(0,this.dirtyComponentsLength),w()):p.length=0}},{initialize:function(){this.callbackQueue.reset()},close:function(){this.callbackQueue.notifyAll()}}];function y(){this.reinitializeTransaction(),this.dirtyComponentsLength=null,this.callbackQueue=a.getPooled(),this.reconcileTransaction=x.ReactReconcileTransaction.getPooled(!0)}function b(e,t){return e._mountOrder-t._mountOrder}function _(e){var t=e.dirtyComponentsLength;t!==p.length&&r("124",t,p.length),p.sort(b),f++;for(var n=0;nE;E++)if((f||E in _)&&(y=w(g=_[E],E,b),e))if(t)S[E]=y;else if(y)switch(e){case 3:return!0;case 5:return g;case 6:return E;case 2:u.call(S,g)}else if(l)return!1;return p?-1:c||l?l:S}};e.exports={forEach:c(0),map:c(1),filter:c(2),some:c(3),every:c(4),find:c(5),findIndex:c(6)}},function(e,t,n){"use strict";e.exports={current:null}},function(e,t){e.exports=function(e){return null!=e&&"object"==typeof e}},function(e,t){var n,r,o=e.exports={};function a(){throw new Error("setTimeout has not been defined")}function i(){throw new Error("clearTimeout has not been defined")}function s(e){if(n===setTimeout)return setTimeout(e,0);if((n===a||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:a}catch(e){n=a}try{r="function"==typeof clearTimeout?clearTimeout:i}catch(e){r=i}}();var u,c=[],l=!1,p=-1;function f(){l&&u&&(l=!1,u.length?c=u.concat(c):p=-1,c.length&&h())}function h(){if(!l){var e=s(f);l=!0;for(var t=c.length;t;){for(u=c,c=[];++p1)for(var n=1;n0&&"/"!==t[0]}));function Ce(e,t,n){var r;t=t||[];var o=we.apply(void 0,A()(r=[e]).call(r,O()(t))).get("parameters",Object(I.List)());return f()(o).call(o,(function(e,t){var r=n&&"body"===t.get("in")?t.get("value_xml"):t.get("value");return e.set(Object(T.B)(t,{allowHashes:!1}),r)}),Object(I.fromJS)({}))}function Se(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(I.List.isList(e))return u()(e).call(e,(function(e){return I.Map.isMap(e)&&e.get("in")===t}))}function Ae(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(I.List.isList(e))return u()(e).call(e,(function(e){return I.Map.isMap(e)&&e.get("type")===t}))}function ke(e,t){var n,r;t=t||[];var o=z(e).getIn(A()(n=["paths"]).call(n,O()(t)),Object(I.fromJS)({})),a=e.getIn(A()(r=["meta","paths"]).call(r,O()(t)),Object(I.fromJS)({})),i=Oe(e,t),s=o.get("parameters")||new I.List,u=a.get("consumes_value")?a.get("consumes_value"):Ae(s,"file")?"multipart/form-data":Ae(s,"formData")?"application/x-www-form-urlencoded":void 0;return Object(I.fromJS)({requestContentType:u,responseContentType:i})}function Oe(e,t){var n,r;t=t||[];var o=z(e).getIn(A()(n=["paths"]).call(n,O()(t)),null);if(null!==o){var a=e.getIn(A()(r=["meta","paths"]).call(r,O()(t),["produces_value"]),null),i=o.getIn(["produces",0],null);return a||i||"application/json"}}function je(e,t){var n;t=t||[];var r=z(e),o=r.getIn(A()(n=["paths"]).call(n,O()(t)),null);if(null!==o){var a=t,s=i()(a,1)[0],u=o.get("produces",null),c=r.getIn(["paths",s,"produces"],null),l=r.getIn(["produces"],null);return u||c||l}}function Te(e,t){var n;t=t||[];var r=z(e),o=r.getIn(A()(n=["paths"]).call(n,O()(t)),null);if(null!==o){var a=t,s=i()(a,1)[0],u=o.get("consumes",null),c=r.getIn(["paths",s,"consumes"],null),l=r.getIn(["consumes"],null);return u||c||l}}var Ie=function(e,t,n){var r=e.get("url").match(/^([a-z][a-z0-9+\-.]*):/),a=o()(r)?r[1]:null;return e.getIn(["scheme",t,n])||e.getIn(["scheme","_defaultScheme"])||a||""},Ne=function(e,t,n){var r;return _()(r=["http","https"]).call(r,Ie(e,t,n))>-1},Me=function(e,t){var n;t=t||[];var r=e.getIn(A()(n=["meta","paths"]).call(n,O()(t),["parameters"]),Object(I.fromJS)([])),o=!0;return x()(r).call(r,(function(e){var t=e.get("errors");t&&t.count()&&(o=!1)})),o},Pe=function(e,t){var n,r,o={requestBody:!1,requestContentType:{}},a=e.getIn(A()(n=["resolvedSubtrees","paths"]).call(n,O()(t),["requestBody"]),Object(I.fromJS)([]));return a.size<1||(a.getIn(["required"])&&(o.requestBody=a.getIn(["required"])),x()(r=a.getIn(["content"]).entrySeq()).call(r,(function(e){var t=e[0];if(e[1].getIn(["schema","required"])){var n=e[1].getIn(["schema","required"]).toJS();o.requestContentType[t]=n}}))),o},Re=function(e,t,n,r){var o,a=e.getIn(A()(o=["resolvedSubtrees","paths"]).call(o,O()(t),["requestBody","content"]),Object(I.fromJS)([]));if(a.size<2||!n||!r)return!1;var i=a.getIn([n,"schema","properties"],Object(I.fromJS)([])),s=a.getIn([r,"schema","properties"],Object(I.fromJS)([]));return!!i.equals(s)};function De(e){return I.Map.isMap(e)?e:new I.Map}},function(e,t,n){"use strict";(function(t){var r=n(891),o=n(892),a=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,i=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i,s=new RegExp("^[\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF]+");function u(e){return(e||"").toString().replace(s,"")}var c=[["#","hash"],["?","query"],function(e){return e.replace("\\","/")},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d+)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],l={hash:1,query:1};function p(e){var n,r=("undefined"!=typeof window?window:void 0!==t?t:"undefined"!=typeof self?self:{}).location||{},o={},i=typeof(e=e||r);if("blob:"===e.protocol)o=new h(unescape(e.pathname),{});else if("string"===i)for(n in o=new h(e,{}),l)delete o[n];else if("object"===i){for(n in e)n in l||(o[n]=e[n]);void 0===o.slashes&&(o.slashes=a.test(e.href))}return o}function f(e){e=u(e);var t=i.exec(e);return{protocol:t[1]?t[1].toLowerCase():"",slashes:!!t[2],rest:t[3]}}function h(e,t,n){if(e=u(e),!(this instanceof h))return new h(e,t,n);var a,i,s,l,d,v,m=c.slice(),g=typeof t,y=this,b=0;for("object"!==g&&"string"!==g&&(n=t,t=null),n&&"function"!=typeof n&&(n=o.parse),t=p(t),a=!(i=f(e||"")).protocol&&!i.slashes,y.slashes=i.slashes||a&&t.slashes,y.protocol=i.protocol||t.protocol||"",e=i.rest,i.slashes||(m[3]=[/(.*)/,"pathname"]);b=n.length?{value:void 0,done:!0}:(e=r(n,o),t.index+=e.length,{value:e,done:!1})}))},function(e,t,n){"use strict";e.exports=function(e){if("function"!=typeof e)throw new TypeError(e+" is not a function");return e}},function(e,t,n){e.exports=n(626)},function(e,t,n){e.exports=n(828)},function(e,t,n){"use strict";var r=n(870);e.exports=r},function(e,t,n){"use strict";n.r(t),n.d(t,"UPDATE_LAYOUT",(function(){return o})),n.d(t,"UPDATE_FILTER",(function(){return a})),n.d(t,"UPDATE_MODE",(function(){return i})),n.d(t,"SHOW",(function(){return s})),n.d(t,"updateLayout",(function(){return u})),n.d(t,"updateFilter",(function(){return c})),n.d(t,"show",(function(){return l})),n.d(t,"changeMode",(function(){return p}));var r=n(7),o="layout_update_layout",a="layout_update_filter",i="layout_update_mode",s="layout_show";function u(e){return{type:o,payload:e}}function c(e){return{type:a,payload:e}}function l(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return e=Object(r.w)(e),{type:s,payload:{thing:e,shown:t}}}function p(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return e=Object(r.w)(e),{type:i,payload:{thing:e,mode:t}}}},function(e,t,n){"use strict";var r=n(1052),o=n(1053);function a(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}t.parse=b,t.resolve=function(e,t){return b(e,!1,!0).resolve(t)},t.resolveObject=function(e,t){return e?b(e,!1,!0).resolveObject(t):t},t.format=function(e){o.isString(e)&&(e=b(e));return e instanceof a?e.format():a.prototype.format.call(e)},t.Url=a;var i=/^([a-z0-9.+-]+:)/i,s=/:[0-9]*$/,u=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,c=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),l=["'"].concat(c),p=["%","/","?",";","#"].concat(l),f=["/","?","#"],h=/^[+a-z0-9A-Z_-]{0,63}$/,d=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,v={javascript:!0,"javascript:":!0},m={javascript:!0,"javascript:":!0},g={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},y=n(1054);function b(e,t,n){if(e&&o.isObject(e)&&e instanceof a)return e;var r=new a;return r.parse(e,t,n),r}a.prototype.parse=function(e,t,n){if(!o.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var a=e.indexOf("?"),s=-1!==a&&a127?M+="x":M+=N[P];if(!M.match(h)){var D=T.slice(0,k),L=T.slice(k+1),B=N.match(d);B&&(D.push(B[1]),L.unshift(B[2])),L.length&&(b="/"+L.join(".")+b),this.hostname=D.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),j||(this.hostname=r.toASCII(this.hostname));var F=this.port?":"+this.port:"",U=this.hostname||"";this.host=U+F,this.href+=this.host,j&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==b[0]&&(b="/"+b))}if(!v[x])for(k=0,I=l.length;k0)&&n.host.split("@"))&&(n.auth=j.shift(),n.host=n.hostname=j.shift());return n.search=e.search,n.query=e.query,o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.href=n.format(),n}if(!E.length)return n.pathname=null,n.search?n.path="/"+n.search:n.path=null,n.href=n.format(),n;for(var S=E.slice(-1)[0],A=(n.host||e.host||E.length>1)&&("."===S||".."===S)||""===S,k=0,O=E.length;O>=0;O--)"."===(S=E[O])?E.splice(O,1):".."===S?(E.splice(O,1),k++):k&&(E.splice(O,1),k--);if(!w&&!x)for(;k--;k)E.unshift("..");!w||""===E[0]||E[0]&&"/"===E[0].charAt(0)||E.unshift(""),A&&"/"!==E.join("/").substr(-1)&&E.push("");var j,T=""===E[0]||E[0]&&"/"===E[0].charAt(0);C&&(n.hostname=n.host=T?"":E.length?E.shift():"",(j=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@"))&&(n.auth=j.shift(),n.host=n.hostname=j.shift()));return(w=w||n.host&&E.length)&&!T&&E.unshift(""),E.length?n.pathname=E.join("/"):(n.pathname=null,n.path=null),o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.auth=e.auth||n.auth,n.slashes=n.slashes||e.slashes,n.href=n.format(),n},a.prototype.parseHost=function(){var e=this.host,t=s.exec(e);t&&(":"!==(t=t[0])&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},function(e,t,n){var r=n(418),o=n(159),a=n(189),i=n(53),s=n(117),u=n(190),c=n(158),l=n(247),p=Object.prototype.hasOwnProperty;e.exports=function(e){if(null==e)return!0;if(s(e)&&(i(e)||"string"==typeof e||"function"==typeof e.splice||u(e)||l(e)||a(e)))return!e.length;var t=o(e);if("[object Map]"==t||"[object Set]"==t)return!e.size;if(c(e))return!r(e).length;for(var n in e)if(p.call(e,n))return!1;return!0}},function(e,t,n){var r=n(48),o=n(174),a=n(107),i=n(69),s=n(176),u=n(52),c=n(353),l=Object.getOwnPropertyDescriptor;t.f=r?l:function(e,t){if(e=i(e),t=s(t,!0),c)try{return l(e,t)}catch(e){}if(u(e,t))return a(!o.f.call(e,t),e[t])}},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t){var n={}.toString;e.exports=function(e){return n.call(e).slice(8,-1)}},function(e,t,n){var r=n(79);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t,n){var r,o=n(55),a=n(231),i=n(226),s=n(150),u=n(366),c=n(223),l=n(178),p=l("IE_PROTO"),f=function(){},h=function(e){return"