From 238a40b9e09d64433e14de848f7ff1f4fe21ad02 Mon Sep 17 00:00:00 2001 From: srcejon <jon@beniston.com> Date: Wed, 6 Dec 2023 10:09:30 +0000 Subject: [PATCH 1/5] Allow replay time offset to be set by ctrl+left click in waterfall. --- plugins/samplesource/airspyhf/airspyhfgui.cpp | 5 +++++ plugins/samplesource/airspyhf/airspyhfgui.h | 1 + plugins/samplesource/rtlsdr/rtlsdrgui.cpp | 5 +++++ plugins/samplesource/rtlsdr/rtlsdrgui.h | 1 + .../samplesource/sdrplayv3/sdrplayv3gui.cpp | 5 +++++ plugins/samplesource/sdrplayv3/sdrplayv3gui.h | 1 + .../samplesource/usrpinput/usrpinputgui.cpp | 5 +++++ plugins/samplesource/usrpinput/usrpinputgui.h | 1 + .../samplesource/usrpinput/usrpinputgui.ui | 22 +++++++++---------- .../usrpinput/usrpinputsettings.h | 2 +- sdrgui/device/devicegui.h | 1 + sdrgui/device/deviceuiset.cpp | 9 ++++++++ sdrgui/device/deviceuiset.h | 1 + sdrgui/gui/glspectrumview.cpp | 12 ++++++++++ sdrgui/gui/glspectrumview.h | 2 ++ sdrgui/mainspectrum/mainspectrumgui.cpp | 7 ++++++ sdrgui/mainspectrum/mainspectrumgui.h | 2 ++ 17 files changed, 70 insertions(+), 12 deletions(-) diff --git a/plugins/samplesource/airspyhf/airspyhfgui.cpp b/plugins/samplesource/airspyhf/airspyhfgui.cpp index 59e464db7..159f996f2 100644 --- a/plugins/samplesource/airspyhf/airspyhfgui.cpp +++ b/plugins/samplesource/airspyhf/airspyhfgui.cpp @@ -623,6 +623,11 @@ void AirspyHFGui::on_replayLoop_toggled(bool checked) sendSettings(); } +void AirspyHFGui::setReplayTime(float time) +{ + ui->replayOffset->setValue(std::ceil(time * 10.0f)); +} + void AirspyHFGui::makeUIConnections() { QObject::connect(ui->centerFrequency, &ValueDial::changed, this, &AirspyHFGui::on_centerFrequency_changed); diff --git a/plugins/samplesource/airspyhf/airspyhfgui.h b/plugins/samplesource/airspyhf/airspyhfgui.h index 877dd3e90..d3d48cd42 100644 --- a/plugins/samplesource/airspyhf/airspyhfgui.h +++ b/plugins/samplesource/airspyhf/airspyhfgui.h @@ -46,6 +46,7 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; } + void setReplayTime(float time) override; uint32_t getDevSampleRate(unsigned int index); int getDevSampleRateIndex(uint32_t sampleRate); diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.cpp b/plugins/samplesource/rtlsdr/rtlsdrgui.cpp index 963e224c4..1cb0e9b21 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.cpp @@ -691,6 +691,11 @@ void RTLSDRGui::on_replayLoop_toggled(bool checked) sendSettings(); } +void RTLSDRGui::setReplayTime(float time) +{ + ui->replayOffset->setValue(std::ceil(time * 10.0f)); +} + void RTLSDRGui::makeUIConnections() { QObject::connect(ui->centerFrequency, &ValueDial::changed, this, &RTLSDRGui::on_centerFrequency_changed); diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.h b/plugins/samplesource/rtlsdr/rtlsdrgui.h index 3cac63c4d..7abfaeba3 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.h +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.h @@ -50,6 +50,7 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + void setReplayTime(float time) override; private: Ui::RTLSDRGui* ui; diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3gui.cpp b/plugins/samplesource/sdrplayv3/sdrplayv3gui.cpp index 1b7d6e43c..a1df4ec8d 100644 --- a/plugins/samplesource/sdrplayv3/sdrplayv3gui.cpp +++ b/plugins/samplesource/sdrplayv3/sdrplayv3gui.cpp @@ -687,6 +687,11 @@ void SDRPlayV3Gui::on_replayLoop_toggled(bool checked) sendSettings(); } +void SDRPlayV3Gui::setReplayTime(float time) +{ + ui->replayOffset->setValue(std::ceil(time * 10.0f)); +} + void SDRPlayV3Gui::makeUIConnections() { QObject::connect(ui->centerFrequency, &ValueDial::changed, this, &SDRPlayV3Gui::on_centerFrequency_changed); diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3gui.h b/plugins/samplesource/sdrplayv3/sdrplayv3gui.h index 7a130bebc..8e65a9fa5 100644 --- a/plugins/samplesource/sdrplayv3/sdrplayv3gui.h +++ b/plugins/samplesource/sdrplayv3/sdrplayv3gui.h @@ -46,6 +46,7 @@ public: virtual QByteArray serialize() const; virtual bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + void setReplayTime(float time) override; private: Ui::SDRPlayV3Gui* ui; diff --git a/plugins/samplesource/usrpinput/usrpinputgui.cpp b/plugins/samplesource/usrpinput/usrpinputgui.cpp index 523dff5a5..5a856f5fb 100644 --- a/plugins/samplesource/usrpinput/usrpinputgui.cpp +++ b/plugins/samplesource/usrpinput/usrpinputgui.cpp @@ -769,6 +769,11 @@ void USRPInputGUI::on_replayLoop_toggled(bool checked) sendSettings(); } +void USRPInputGUI::setReplayTime(float time) +{ + ui->replayOffset->setValue(std::ceil(time * 10.0f)); +} + void USRPInputGUI::makeUIConnections() { QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &USRPInputGUI::on_startStop_toggled); diff --git a/plugins/samplesource/usrpinput/usrpinputgui.h b/plugins/samplesource/usrpinput/usrpinputgui.h index 9a0f3dfcc..1a5fa8107 100644 --- a/plugins/samplesource/usrpinput/usrpinputgui.h +++ b/plugins/samplesource/usrpinput/usrpinputgui.h @@ -50,6 +50,7 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + void setReplayTime(float time) override; private: Ui::USRPInputGUI* ui; diff --git a/plugins/samplesource/usrpinput/usrpinputgui.ui b/plugins/samplesource/usrpinput/usrpinputgui.ui index b20bc042b..1110ab685 100644 --- a/plugins/samplesource/usrpinput/usrpinputgui.ui +++ b/plugins/samplesource/usrpinput/usrpinputgui.ui @@ -875,28 +875,28 @@ </layout> </widget> <customwidgets> - <customwidget> - <class>ValueDial</class> - <extends>QWidget</extends> - <header>gui/valuedial.h</header> - <container>1</container> - </customwidget> <customwidget> <class>ButtonSwitch</class> <extends>QToolButton</extends> <header>gui/buttonswitch.h</header> </customwidget> - <customwidget> - <class>TransverterButton</class> - <extends>QPushButton</extends> - <header>gui/transverterbutton.h</header> - </customwidget> <customwidget> <class>ValueDialZ</class> <extends>QWidget</extends> <header>gui/valuedialz.h</header> <container>1</container> </customwidget> + <customwidget> + <class>ValueDial</class> + <extends>QWidget</extends> + <header>gui/valuedial.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>TransverterButton</class> + <extends>QPushButton</extends> + <header>gui/transverterbutton.h</header> + </customwidget> </customwidgets> <resources> <include location="../../../sdrgui/resources/res.qrc"/> diff --git a/plugins/samplesource/usrpinput/usrpinputsettings.h b/plugins/samplesource/usrpinput/usrpinputsettings.h index 6bd90fa36..ae2f6e15d 100644 --- a/plugins/samplesource/usrpinput/usrpinputsettings.h +++ b/plugins/samplesource/usrpinput/usrpinputsettings.h @@ -55,7 +55,7 @@ struct USRPInputSettings float m_replayOffset; //!< Replay offset in seconds float m_replayLength; //!< Replay buffer size in seconds float m_replayStep; //!< Replay forward/back step size in seconds - bool m_replayLoop; //!< Replay buffer repeatedly without recording new data + bool m_replayLoop; //!< Replay buffer repeatedly without recording new data bool m_useReverseAPI; QString m_reverseAPIAddress; uint16_t m_reverseAPIPort; diff --git a/sdrgui/device/devicegui.h b/sdrgui/device/devicegui.h index 69f78ee3a..94eb2a4c6 100644 --- a/sdrgui/device/devicegui.h +++ b/sdrgui/device/devicegui.h @@ -81,6 +81,7 @@ public: void setCurrentDeviceIndex(int index) { m_currentDeviceIndex = index; } //!< index in plugins list void setChannelNames(const QStringList& channelNames) { m_channelAddDialog.addChannelNames(channelNames); } DeviceUISet* getDeviceUISet() { return m_deviceUISet; } + virtual void setReplayTime(float time) {} //!< Not supported by all devices protected: void closeEvent(QCloseEvent *event) override; diff --git a/sdrgui/device/deviceuiset.cpp b/sdrgui/device/deviceuiset.cpp index 28c1dfe03..53bde72f2 100644 --- a/sdrgui/device/deviceuiset.cpp +++ b/sdrgui/device/deviceuiset.cpp @@ -73,6 +73,8 @@ DeviceUISet::DeviceUISet(int deviceSetIndex, DeviceSet *deviceSet) font.setFamily(QStringLiteral("Liberation Sans")); font.setPointSize(9); m_spectrum->setFont(font); + + connect(m_mainSpectrumGUI, &MainSpectrumGUI::timeSelected, this, &DeviceUISet::onTimeSelected); } DeviceUISet::~DeviceUISet() @@ -825,3 +827,10 @@ int DeviceUISet::webapiSpectrumServerDelete(SWGSDRangel::SWGSuccessResponse& res { return m_spectrumVis->webapiSpectrumServerDelete(response, errorMessage); } + +void DeviceUISet::onTimeSelected(int deviceSetIndex, float time) +{ + if (m_deviceGUI) { + m_deviceGUI->setReplayTime(time); + } +} diff --git a/sdrgui/device/deviceuiset.h b/sdrgui/device/deviceuiset.h index d0cd6f38b..f195364fd 100644 --- a/sdrgui/device/deviceuiset.h +++ b/sdrgui/device/deviceuiset.h @@ -167,6 +167,7 @@ private: private slots: void handleChannelGUIClosing(ChannelGUI* channelGUI); void handleDeleteChannel(ChannelAPI *channelAPI); + void onTimeSelected(int deviceSetIndex, float time); }; diff --git a/sdrgui/gui/glspectrumview.cpp b/sdrgui/gui/glspectrumview.cpp index 8b0edc547..a6d83347f 100644 --- a/sdrgui/gui/glspectrumview.cpp +++ b/sdrgui/gui/glspectrumview.cpp @@ -4175,6 +4175,18 @@ void GLSpectrumView::mousePressEvent(QMouseEvent* event) { frequencyPan(event); } + else if (event->modifiers() & Qt::ControlModifier) + { + if (!m_display3DSpectrogram && pointInWaterfallOrSpectrogram(ep)) + { + QPointF pWat = ep; + pWat.rx() = (ep.x()/width() - m_waterfallRect.left()) / m_waterfallRect.width(); + pWat.ry() = (ep.y()/height() - m_waterfallRect.top()) / m_waterfallRect.height(); + float time = m_timeScale.getRangeMin() + pWat.y()*m_timeScale.getRange(); + emit timeSelected(time); + } + return; + } else if (m_display3DSpectrogram) { // Detect click and drag to rotate 3D spectrogram diff --git a/sdrgui/gui/glspectrumview.h b/sdrgui/gui/glspectrumview.h index 6bc21fe30..8bef04239 100644 --- a/sdrgui/gui/glspectrumview.h +++ b/sdrgui/gui/glspectrumview.h @@ -541,6 +541,8 @@ signals: void requestCenterFrequency(qint64 frequency); // Emitted when annotations are changed void updateAnnotations(); + // Emitted when user ctrl-clicks on waterfall to select a time. time is in seconds. + void timeSelected(float time); }; diff --git a/sdrgui/mainspectrum/mainspectrumgui.cpp b/sdrgui/mainspectrum/mainspectrumgui.cpp index bdaf66a43..d01381e13 100644 --- a/sdrgui/mainspectrum/mainspectrumgui.cpp +++ b/sdrgui/mainspectrum/mainspectrumgui.cpp @@ -157,6 +157,8 @@ MainSpectrumGUI::MainSpectrumGUI(GLSpectrum *spectrum, GLSpectrumGUI *spectrumGU connect(spectrum->getSpectrumView(), &GLSpectrumView::requestCenterFrequency, this, &MainSpectrumGUI::onRequestCenterFrequency); connect(spectrumGUI, &GLSpectrumGUI::requestCenterFrequency, this, &MainSpectrumGUI::onRequestCenterFrequency); + connect(spectrum->getSpectrumView(), &GLSpectrumView::timeSelected, this, &MainSpectrumGUI::onTimeSelected); + m_resizer.enableChildMouseTracking(); shrinkWindow(); } @@ -380,3 +382,8 @@ void MainSpectrumGUI::onRequestCenterFrequency(qint64 frequency) { emit requestCenterFrequency(m_deviceSetIndex, frequency); } + +void MainSpectrumGUI::onTimeSelected(float time) +{ + emit timeSelected(m_deviceSetIndex, time); +} diff --git a/sdrgui/mainspectrum/mainspectrumgui.h b/sdrgui/mainspectrum/mainspectrumgui.h index 608e27800..ce8a21b9c 100644 --- a/sdrgui/mainspectrum/mainspectrumgui.h +++ b/sdrgui/mainspectrum/mainspectrumgui.h @@ -113,12 +113,14 @@ private slots: void shrinkWindow(); void maximizeWindow(); void onRequestCenterFrequency(qint64 frequency); + void onTimeSelected(float time); signals: void closing(); void moveToWorkspace(int workspaceIndex); void forceShrink(); void requestCenterFrequency(int deviceSetIndex, qint64 frequency); // an action from the user to move device center frequency + void timeSelected(int deviceSetIndex, float time); // user ctrl-clicked waterfall to set a time }; From 2ac7cfd800a63fc66374cf80ddfaaaf7cc41d0e7 Mon Sep 17 00:00:00 2001 From: srcejon <jon@beniston.com> Date: Wed, 6 Dec 2023 10:09:46 +0000 Subject: [PATCH 2/5] Add replay support to Lime Input --- .../limesdrinput/limesdrinput.cpp | 24 ++- .../samplesource/limesdrinput/limesdrinput.h | 23 ++- .../limesdrinput/limesdrinputgui.cpp | 110 ++++++++++++ .../limesdrinput/limesdrinputgui.h | 10 ++ .../limesdrinput/limesdrinputgui.ui | 106 +++++++++++- .../limesdrinput/limesdrinputsettings.cpp | 36 ++++ .../limesdrinput/limesdrinputsettings.h | 4 + .../limesdrinput/limesdrinputthread.cpp | 157 ++++++++++++------ .../limesdrinput/limesdrinputthread.h | 4 +- 9 files changed, 413 insertions(+), 61 deletions(-) diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index 9757df2c3..f0eaae215 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -48,6 +48,7 @@ MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgGetDeviceInfo, Message) MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgReportStreamInfo, Message) MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgStartStop, Message) MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgCalibrationResult, Message) +MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgSaveReplay, Message) LimeSDRInput::LimeSDRInput(DeviceAPI *deviceAPI) : m_deviceAPI(deviceAPI), @@ -422,7 +423,7 @@ bool LimeSDRInput::start() // start / stop streaming is done in the thread. - m_limeSDRInputThread = new LimeSDRInputThread(&m_streamId, &m_sampleFifo); + m_limeSDRInputThread = new LimeSDRInputThread(&m_streamId, &m_sampleFifo, &m_replayBuffer); qDebug("LimeSDRInput::start: thread created"); applySettings(m_settings, QList<QString>(), true); @@ -778,6 +779,12 @@ bool LimeSDRInput::handleMessage(const Message& message) return true; } + else if (MsgSaveReplay::match(message)) + { + MsgSaveReplay& cmd = (MsgSaveReplay&) message; + m_replayBuffer.save(cmd.getFilename(), m_settings.m_devSampleRate, getCenterFrequency()); + return true; + } else { return false; @@ -977,6 +984,9 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, const QLi settings.m_devSampleRate, 1<<settings.m_log2HardDecim); } + if (settings.m_devSampleRate != m_settings.m_devSampleRate) { + m_replayBuffer.clear(); + } } } @@ -1168,6 +1178,18 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, const QLi m_settings.applySettings(settingsKeys, settings); } + if (settingsKeys.contains("replayLength") || settingsKeys.contains("devSampleRate") || force) { + m_replayBuffer.setSize(m_settings.m_replayLength, m_settings.m_devSampleRate); + } + + if (settingsKeys.contains("replayOffset") || settingsKeys.contains("devSampleRate") || force) { + m_replayBuffer.setReadOffset(((unsigned)(m_settings.m_replayOffset * m_settings.m_devSampleRate)) * 2); + } + + if (settingsKeys.contains("replayLoop") || force) { + m_replayBuffer.setLoop(m_settings.m_replayLoop); + } + double clockGenFreqAfter; if (LMS_GetClockFreq(m_deviceShared.m_deviceParams->getDevice(), LMS_CLOCK_CGEN, &clockGenFreqAfter) != 0) diff --git a/plugins/samplesource/limesdrinput/limesdrinput.h b/plugins/samplesource/limesdrinput/limesdrinput.h index 64df518b9..d86128e48 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.h +++ b/plugins/samplesource/limesdrinput/limesdrinput.h @@ -29,6 +29,7 @@ #include <QNetworkRequest> #include "dsp/devicesamplesource.h" +#include "dsp/replaybuffer.h" #include "limesdr/devicelimesdrshared.h" #include "limesdrinputsettings.h" @@ -209,7 +210,26 @@ public: { } }; - LimeSDRInput(DeviceAPI *deviceAPI); + class MsgSaveReplay : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QString getFilename() const { return m_filename; } + + static MsgSaveReplay* create(const QString& filename) { + return new MsgSaveReplay(filename); + } + + protected: + QString m_filename; + + MsgSaveReplay(const QString& filename) : + Message(), + m_filename(filename) + { } + }; + + LimeSDRInput(DeviceAPI *deviceAPI); virtual ~LimeSDRInput(); virtual void destroy(); @@ -280,6 +300,7 @@ private: lms_stream_t m_streamId; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; + ReplayBuffer<qint16> m_replayBuffer; bool openDevice(); void closeDevice(); diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp index 3a387c44c..b5e72e3bf 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp @@ -469,6 +469,10 @@ void LimeSDRInputGUI::displaySettings() setNCODisplay(); ui->ncoEnable->setChecked(m_settings.m_ncoEnable); + displayReplayLength(); + displayReplayOffset(); + displayReplayStep(); + ui->replayLoop->setChecked(m_settings.m_replayLoop); } void LimeSDRInputGUI::setNCODisplay() @@ -805,6 +809,9 @@ void LimeSDRInputGUI::openDeviceSettingsDialog(const QPoint& p) if (m_contextMenuType == ContextMenuDeviceSettings) { BasicDeviceSettingsDialog dialog(this); + dialog.setReplayBytesPerSecond(m_settings.m_devSampleRate * 2 * sizeof(qint16)); + dialog.setReplayLength(m_settings.m_replayLength); + dialog.setReplayStep(m_settings.m_replayStep); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -818,10 +825,17 @@ void LimeSDRInputGUI::openDeviceSettingsDialog(const QPoint& p) m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex(); + m_settings.m_replayLength = dialog.getReplayLength(); + m_settings.m_replayStep = dialog.getReplayStep(); + displayReplayLength(); + displayReplayOffset(); + displayReplayStep(); m_settingsKeys.append("useReverseAPI"); m_settingsKeys.append("reverseAPIAddress"); m_settingsKeys.append("reverseAPIPort"); m_settingsKeys.append("reverseAPIDeviceIndex"); + m_settingsKeys.append("replayLength"); + m_settingsKeys.append("replayStep"); sendSettings(); } @@ -829,6 +843,96 @@ void LimeSDRInputGUI::openDeviceSettingsDialog(const QPoint& p) resetContextMenuType(); } +void LimeSDRInputGUI::displayReplayLength() +{ + bool replayEnabled = m_settings.m_replayLength > 0.0f; + if (!replayEnabled) { + ui->replayOffset->setMaximum(0); + } else { + ui->replayOffset->setMaximum(m_settings.m_replayLength * 10 - 1); + } + ui->replayLabel->setEnabled(replayEnabled); + ui->replayOffset->setEnabled(replayEnabled); + ui->replayOffsetText->setEnabled(replayEnabled); + ui->replaySave->setEnabled(replayEnabled); +} + +void LimeSDRInputGUI::displayReplayOffset() +{ + bool replayEnabled = m_settings.m_replayLength > 0.0f; + ui->replayOffset->setValue(m_settings.m_replayOffset * 10); + ui->replayOffsetText->setText(QString("%1s").arg(m_settings.m_replayOffset, 0, 'f', 1)); + ui->replayNow->setEnabled(replayEnabled && (m_settings.m_replayOffset > 0.0f)); + ui->replayPlus->setEnabled(replayEnabled && (std::round(m_settings.m_replayOffset * 10) < ui->replayOffset->maximum())); + ui->replayMinus->setEnabled(replayEnabled && (m_settings.m_replayOffset > 0.0f)); +} + +void LimeSDRInputGUI::displayReplayStep() +{ + QString step; + float intpart; + float frac = modf(m_settings.m_replayStep, &intpart); + if (frac == 0.0f) { + step = QString::number((int)intpart); + } else { + step = QString::number(m_settings.m_replayStep, 'f', 1); + } + ui->replayPlus->setText(QString("+%1s").arg(step)); + ui->replayPlus->setToolTip(QString("Add %1 seconds to time delay").arg(step)); + ui->replayMinus->setText(QString("-%1s").arg(step)); + ui->replayMinus->setToolTip(QString("Remove %1 seconds from time delay").arg(step)); +} + +void LimeSDRInputGUI::on_replayOffset_valueChanged(int value) +{ + m_settings.m_replayOffset = value / 10.0f; + displayReplayOffset(); + m_settingsKeys.append("replayOffset"); + sendSettings(); +} + +void LimeSDRInputGUI::on_replayNow_clicked() +{ + ui->replayOffset->setValue(0); +} + +void LimeSDRInputGUI::on_replayPlus_clicked() +{ + ui->replayOffset->setValue(ui->replayOffset->value() + m_settings.m_replayStep * 10); +} + +void LimeSDRInputGUI::on_replayMinus_clicked() +{ + ui->replayOffset->setValue(ui->replayOffset->value() - m_settings.m_replayStep * 10); +} + +void LimeSDRInputGUI::on_replaySave_clicked() +{ + QFileDialog fileDialog(nullptr, "Select file to save IQ data to", "", "*.wav"); + fileDialog.setAcceptMode(QFileDialog::AcceptSave); + if (fileDialog.exec()) + { + QStringList fileNames = fileDialog.selectedFiles(); + if (fileNames.size() > 0) + { + LimeSDRInput::MsgSaveReplay *message = LimeSDRInput::MsgSaveReplay::create(fileNames[0]); + m_limeSDRInput->getInputMessageQueue()->push(message); + } + } +} + +void LimeSDRInputGUI::on_replayLoop_toggled(bool checked) +{ + m_settings.m_replayLoop = checked; + m_settingsKeys.append("replayLoop"); + sendSettings(); +} + +void LimeSDRInputGUI::setReplayTime(float time) +{ + ui->replayOffset->setValue(std::ceil(time * 10.0f)); +} + void LimeSDRInputGUI::makeUIConnections() { QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &LimeSDRInputGUI::on_startStop_toggled); @@ -852,4 +956,10 @@ void LimeSDRInputGUI::makeUIConnections() QObject::connect(ui->extClock, &ExternalClockButton::clicked, this, &LimeSDRInputGUI::on_extClock_clicked); QObject::connect(ui->transverter, &TransverterButton::clicked, this, &LimeSDRInputGUI::on_transverter_clicked); QObject::connect(ui->sampleRateMode, &QToolButton::toggled, this, &LimeSDRInputGUI::on_sampleRateMode_toggled); + QObject::connect(ui->replayOffset, &QSlider::valueChanged, this, &LimeSDRInputGUI::on_replayOffset_valueChanged); + QObject::connect(ui->replayNow, &QToolButton::clicked, this, &LimeSDRInputGUI::on_replayNow_clicked); + QObject::connect(ui->replayPlus, &QToolButton::clicked, this, &LimeSDRInputGUI::on_replayPlus_clicked); + QObject::connect(ui->replayMinus, &QToolButton::clicked, this, &LimeSDRInputGUI::on_replayMinus_clicked); + QObject::connect(ui->replaySave, &QToolButton::clicked, this, &LimeSDRInputGUI::on_replaySave_clicked); + QObject::connect(ui->replayLoop, &ButtonSwitch::toggled, this, &LimeSDRInputGUI::on_replayLoop_toggled); } diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.h b/plugins/samplesource/limesdrinput/limesdrinputgui.h index 8f49c22fa..3da20c14e 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.h +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.h @@ -45,6 +45,7 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + void setReplayTime(float time) override; private: Ui::LimeSDRInputGUI* ui; @@ -66,6 +67,9 @@ private: void displaySettings(); void displaySampleRate(); + void displayReplayLength(); + void displayReplayOffset(); + void displayReplayStep(); void setNCODisplay(); void setCenterFrequencyDisplay(); void setCenterFrequencySetting(uint64_t kHzValue); @@ -101,6 +105,12 @@ private slots: void on_extClock_clicked(); void on_transverter_clicked(); void on_sampleRateMode_toggled(bool checked); + void on_replayOffset_valueChanged(int value); + void on_replayNow_clicked(); + void on_replayPlus_clicked(); + void on_replayMinus_clicked(); + void on_replaySave_clicked(); + void on_replayLoop_toggled(bool checked); void openDeviceSettingsDialog(const QPoint& p); void updateHardware(); diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.ui b/plugins/samplesource/limesdrinput/limesdrinputgui.ui index baba795b6..5ed2119ce 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.ui +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>360</width> - <height>230</height> + <height>255</height> </rect> </property> <property name="sizePolicy"> @@ -19,13 +19,13 @@ <property name="minimumSize"> <size> <width>360</width> - <height>230</height> + <height>255</height> </size> </property> <property name="maximumSize"> <size> - <width>380</width> - <height>266</height> + <width>386</width> + <height>280</height> </size> </property> <property name="font"> @@ -1169,6 +1169,104 @@ QToolTip{background-color: white; color: black;}</string> </item> </layout> </item> + <item> + <layout class="QHBoxLayout" name="replayLayout"> + <item> + <widget class="QLabel" name="replayLabel"> + <property name="minimumSize"> + <size> + <width>65</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Time Delay</string> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="replayOffset"> + <property name="toolTip"> + <string>Replay time delay in seconds</string> + </property> + <property name="maximum"> + <number>500</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="replayOffsetText"> + <property name="toolTip"> + <string>Replay time delay in seconds</string> + </property> + <property name="text"> + <string>0.0s</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="replayNow"> + <property name="toolTip"> + <string>Set time delay to 0 seconds</string> + </property> + <property name="text"> + <string>Now</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="replayPlus"> + <property name="toolTip"> + <string>Add displayed number of seconds to time delay</string> + </property> + <property name="text"> + <string>+5s</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="replayMinus"> + <property name="toolTip"> + <string>Remove displayed number of seconds from time delay</string> + </property> + <property name="text"> + <string>-5s</string> + </property> + </widget> + </item> + <item> + <widget class="ButtonSwitch" name="replayLoop"> + <property name="toolTip"> + <string>Repeatedly replay data in replay buffer</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../../sdrgui/resources/res.qrc"> + <normaloff>:/playloop.png</normaloff>:/playloop.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="replaySave"> + <property name="toolTip"> + <string>Save replay buffer to a file</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../../sdrgui/resources/res.qrc"> + <normaloff>:/save.png</normaloff>:/save.png</iconset> + </property> + </widget> + </item> + </layout> + </item> </layout> </widget> <customwidgets> diff --git a/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp b/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp index 1112d721c..088eafc0e 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp @@ -51,6 +51,10 @@ void LimeSDRInputSettings::resetToDefaults() m_iqOrder = true; m_gpioDir = 0; m_gpioPins = 0; + m_replayOffset = 0.0f; + m_replayLength = 20.0f; + m_replayStep = 5.0f; + m_replayLoop = false; m_useReverseAPI = false; m_reverseAPIAddress = "127.0.0.1"; m_reverseAPIPort = 8888; @@ -88,6 +92,10 @@ QByteArray LimeSDRInputSettings::serialize() const s.writeU32(26, m_reverseAPIPort); s.writeU32(27, m_reverseAPIDeviceIndex); s.writeBool(28, m_iqOrder); + s.writeFloat(29, m_replayOffset); + s.writeFloat(30, m_replayLength); + s.writeFloat(31, m_replayStep); + s.writeBool(32, m_replayLoop); return s.final(); } @@ -146,6 +154,10 @@ bool LimeSDRInputSettings::deserialize(const QByteArray& data) d.readU32(27, &uintval, 0); m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval; d.readBool(28, &m_iqOrder, true); + d.readFloat(29, &m_replayOffset, 0.0f); + d.readFloat(30, &m_replayLength, 20.0f); + d.readFloat(31, &m_replayStep, 5.0f); + d.readBool(32, &m_replayLoop, false); return true; } @@ -231,6 +243,18 @@ void LimeSDRInputSettings::applySettings(const QStringList& settingsKeys, const if (settingsKeys.contains("gpioPins")) { m_gpioPins = settings.m_gpioPins; } + if (settingsKeys.contains("replayOffset")) { + m_replayOffset = settings.m_replayOffset; + } + if (settingsKeys.contains("replayLength")) { + m_replayLength = settings.m_replayLength; + } + if (settingsKeys.contains("replayStep")) { + m_replayStep = settings.m_replayStep; + } + if (settingsKeys.contains("replayLoop")) { + m_replayLoop = settings.m_replayLoop; + } if (settingsKeys.contains("useReverseAPI")) { m_useReverseAPI = settings.m_useReverseAPI; } @@ -321,6 +345,18 @@ QString LimeSDRInputSettings::getDebugString(const QStringList& settingsKeys, bo if (settingsKeys.contains("gpioPins") || force) { ostr << " m_gpioPins: " << m_gpioPins; } + if (settingsKeys.contains("replayOffset") || force) { + ostr << " m_replayOffset: " << m_replayOffset; + } + if (settingsKeys.contains("replayLength") || force) { + ostr << " m_replayLength: " << m_replayLength; + } + if (settingsKeys.contains("replayStep") || force) { + ostr << " m_replayStep: " << m_replayStep; + } + if (settingsKeys.contains("replayLoop") || force) { + ostr << " m_replayLoop: " << m_replayLoop; + } if (settingsKeys.contains("useReverseAPI") || force) { ostr << " m_useReverseAPI: " << m_useReverseAPI; } diff --git a/plugins/samplesource/limesdrinput/limesdrinputsettings.h b/plugins/samplesource/limesdrinput/limesdrinputsettings.h index 84c2a3a93..67b8a5c3c 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputsettings.h +++ b/plugins/samplesource/limesdrinput/limesdrinputsettings.h @@ -71,6 +71,10 @@ struct LimeSDRInputSettings bool m_iqOrder; uint8_t m_gpioDir; //!< GPIO pin direction LSB first; 0 input, 1 output uint8_t m_gpioPins; //!< GPIO pins to write; LSB first + float m_replayOffset; //!< Replay offset in seconds + float m_replayLength; //!< Replay buffer size in seconds + float m_replayStep; //!< Replay forward/back step size in seconds + bool m_replayLoop; //!< Replay buffer repeatedly without recording new data bool m_useReverseAPI; QString m_reverseAPIAddress; uint16_t m_reverseAPIPort; diff --git a/plugins/samplesource/limesdrinput/limesdrinputthread.cpp b/plugins/samplesource/limesdrinput/limesdrinputthread.cpp index cb5df8c20..7ec9ebca0 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputthread.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputthread.cpp @@ -18,15 +18,18 @@ #include <errno.h> #include <algorithm> +#include "dsp/replaybuffer.h" #include "limesdrinputsettings.h" #include "limesdrinputthread.h" -LimeSDRInputThread::LimeSDRInputThread(lms_stream_t* stream, SampleSinkFifo* sampleFifo, QObject* parent) : +LimeSDRInputThread::LimeSDRInputThread(lms_stream_t* stream, SampleSinkFifo* sampleFifo, + ReplayBuffer<qint16> *replayBuffer, QObject* parent) : QThread(parent), m_running(false), m_stream(stream), m_convertBuffer(DeviceLimeSDR::blockSize), m_sampleFifo(sampleFifo), + m_replayBuffer(replayBuffer), m_log2Decim(0), m_iqOrder(true) { @@ -106,70 +109,116 @@ void LimeSDRInputThread::run() } // Decimate according to specified log2 (ex: log2=4 => decim=16) -void LimeSDRInputThread::callbackIQ(const qint16* buf, qint32 len) +void LimeSDRInputThread::callbackIQ(const qint16* inBuf, qint32 len) { SampleVector::iterator it = m_convertBuffer.begin(); - switch (m_log2Decim) - { - case 0: - m_decimatorsIQ.decimate1(&it, buf, len); - break; - case 1: - m_decimatorsIQ.decimate2_cen(&it, buf, len); - break; - case 2: - m_decimatorsIQ.decimate4_cen(&it, buf, len); - break; - case 3: - m_decimatorsIQ.decimate8_cen(&it, buf, len); - break; - case 4: - m_decimatorsIQ.decimate16_cen(&it, buf, len); - break; - case 5: - m_decimatorsIQ.decimate32_cen(&it, buf, len); - break; - case 6: - m_decimatorsIQ.decimate64_cen(&it, buf, len); - break; - default: - break; + // Save data to replay buffer + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } + + const qint16* buf = inBuf; + qint32 remaining = len; + + while (remaining > 0) + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; + + switch (m_log2Decim) + { + case 0: + m_decimatorsIQ.decimate1(&it, buf, len); + break; + case 1: + m_decimatorsIQ.decimate2_cen(&it, buf, len); + break; + case 2: + m_decimatorsIQ.decimate4_cen(&it, buf, len); + break; + case 3: + m_decimatorsIQ.decimate8_cen(&it, buf, len); + break; + case 4: + m_decimatorsIQ.decimate16_cen(&it, buf, len); + break; + case 5: + m_decimatorsIQ.decimate32_cen(&it, buf, len); + break; + case 6: + m_decimatorsIQ.decimate64_cen(&it, buf, len); + break; + default: + break; + } } + m_replayBuffer->unlock(); + m_sampleFifo->write(m_convertBuffer.begin(), it); } -void LimeSDRInputThread::callbackQI(const qint16* buf, qint32 len) +void LimeSDRInputThread::callbackQI(const qint16* inBuf, qint32 len) { SampleVector::iterator it = m_convertBuffer.begin(); - switch (m_log2Decim) - { - case 0: - m_decimatorsQI.decimate1(&it, buf, len); - break; - case 1: - m_decimatorsQI.decimate2_cen(&it, buf, len); - break; - case 2: - m_decimatorsQI.decimate4_cen(&it, buf, len); - break; - case 3: - m_decimatorsQI.decimate8_cen(&it, buf, len); - break; - case 4: - m_decimatorsQI.decimate16_cen(&it, buf, len); - break; - case 5: - m_decimatorsQI.decimate32_cen(&it, buf, len); - break; - case 6: - m_decimatorsQI.decimate64_cen(&it, buf, len); - break; - default: - break; - } + // Save data to replay buffer + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } + + const qint16* buf = inBuf; + qint32 remaining = len; + + while (remaining > 0) + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; + + switch (m_log2Decim) + { + case 0: + m_decimatorsQI.decimate1(&it, buf, len); + break; + case 1: + m_decimatorsQI.decimate2_cen(&it, buf, len); + break; + case 2: + m_decimatorsQI.decimate4_cen(&it, buf, len); + break; + case 3: + m_decimatorsQI.decimate8_cen(&it, buf, len); + break; + case 4: + m_decimatorsQI.decimate16_cen(&it, buf, len); + break; + case 5: + m_decimatorsQI.decimate32_cen(&it, buf, len); + break; + case 6: + m_decimatorsQI.decimate64_cen(&it, buf, len); + break; + default: + break; + } + } + + m_replayBuffer->unlock(); m_sampleFifo->write(m_convertBuffer.begin(), it); } diff --git a/plugins/samplesource/limesdrinput/limesdrinputthread.h b/plugins/samplesource/limesdrinput/limesdrinputthread.h index 7fe318494..1c473de40 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputthread.h +++ b/plugins/samplesource/limesdrinput/limesdrinputthread.h @@ -37,7 +37,8 @@ class LimeSDRInputThread : public QThread, public DeviceLimeSDRShared::ThreadInt Q_OBJECT public: - LimeSDRInputThread(lms_stream_t* stream, SampleSinkFifo* sampleFifo, QObject* parent = 0); + LimeSDRInputThread(lms_stream_t* stream, SampleSinkFifo* sampleFifo, + ReplayBuffer<qint16> *replayBuffer, QObject* parent = 0); ~LimeSDRInputThread(); virtual void startWork(); @@ -56,6 +57,7 @@ private: qint16 m_buf[2*DeviceLimeSDR::blockSize]; //must hold I+Q values of each sample hence 2xcomplex size SampleVector m_convertBuffer; SampleSinkFifo* m_sampleFifo; + ReplayBuffer<qint16> *m_replayBuffer; unsigned int m_log2Decim; // soft decimation bool m_iqOrder; From c30af7f39f8d5f910052098b32020ac5ebd03ec7 Mon Sep 17 00:00:00 2001 From: srcejon <jon@beniston.com> Date: Wed, 6 Dec 2023 10:14:01 +0000 Subject: [PATCH 3/5] Fix gcc warnings. --- sdrgui/device/devicegui.h | 2 +- sdrgui/device/deviceuiset.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sdrgui/device/devicegui.h b/sdrgui/device/devicegui.h index 94eb2a4c6..c376c2c7e 100644 --- a/sdrgui/device/devicegui.h +++ b/sdrgui/device/devicegui.h @@ -81,7 +81,7 @@ public: void setCurrentDeviceIndex(int index) { m_currentDeviceIndex = index; } //!< index in plugins list void setChannelNames(const QStringList& channelNames) { m_channelAddDialog.addChannelNames(channelNames); } DeviceUISet* getDeviceUISet() { return m_deviceUISet; } - virtual void setReplayTime(float time) {} //!< Not supported by all devices + virtual void setReplayTime(float time) { (void) time; } //!< Not supported by all devices protected: void closeEvent(QCloseEvent *event) override; diff --git a/sdrgui/device/deviceuiset.cpp b/sdrgui/device/deviceuiset.cpp index 53bde72f2..0de391efc 100644 --- a/sdrgui/device/deviceuiset.cpp +++ b/sdrgui/device/deviceuiset.cpp @@ -830,6 +830,8 @@ int DeviceUISet::webapiSpectrumServerDelete(SWGSDRangel::SWGSuccessResponse& res void DeviceUISet::onTimeSelected(int deviceSetIndex, float time) { + (void) deviceSetIndex; + if (m_deviceGUI) { m_deviceGUI->setReplayTime(time); } From 720630c2fbd154cd1ac5a84b7d02a1fa89230430 Mon Sep 17 00:00:00 2001 From: srcejon <jon@beniston.com> Date: Wed, 6 Dec 2023 10:53:28 +0000 Subject: [PATCH 4/5] Remove tabs. --- .../samplesource/airspyhf/airspyhfworker.cpp | 68 +-- .../limesdrinput/limesdrinputthread.cpp | 62 +-- plugins/samplesource/rtlsdr/rtlsdrthread.cpp | 432 +++++++++--------- .../sdrplayv3/sdrplayv3thread.cpp | 60 +-- .../usrpinput/usrpinputthread.cpp | 30 +- 5 files changed, 326 insertions(+), 326 deletions(-) diff --git a/plugins/samplesource/airspyhf/airspyhfworker.cpp b/plugins/samplesource/airspyhf/airspyhfworker.cpp index 82d6549ad..8c1977df2 100644 --- a/plugins/samplesource/airspyhf/airspyhfworker.cpp +++ b/plugins/samplesource/airspyhf/airspyhfworker.cpp @@ -77,27 +77,27 @@ void AirspyHFWorker::setLog2Decimation(unsigned int log2_decim) // Decimate according to specified log2 (ex: log2=4 => decim=16) void AirspyHFWorker::callbackIQ(const float* inBuf, qint32 len) { - SampleVector::iterator it = m_convertBuffer.begin(); + SampleVector::iterator it = m_convertBuffer.begin(); // Save data to replay buffer - m_replayBuffer->lock(); - bool replayEnabled = m_replayBuffer->getSize() > 0; - if (replayEnabled) { - m_replayBuffer->write(inBuf, len); - } + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } - const float* buf = inBuf; - qint32 remaining = len; + const float* buf = inBuf; + qint32 remaining = len; while (remaining > 0) - { - // Choose between live data or replayed data - if (replayEnabled && m_replayBuffer->useReplay()) { - len = m_replayBuffer->read(remaining, buf); - } else { - len = remaining; - } - remaining -= len; + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; switch (m_log2Decim) { @@ -135,32 +135,32 @@ void AirspyHFWorker::callbackIQ(const float* inBuf, qint32 len) m_replayBuffer->unlock(); - m_sampleFifo->write(m_convertBuffer.begin(), it); + m_sampleFifo->write(m_convertBuffer.begin(), it); } void AirspyHFWorker::callbackQI(const float* inBuf, qint32 len) { - SampleVector::iterator it = m_convertBuffer.begin(); + SampleVector::iterator it = m_convertBuffer.begin(); // Save data to replay buffer - m_replayBuffer->lock(); - bool replayEnabled = m_replayBuffer->getSize() > 0; - if (replayEnabled) { - m_replayBuffer->write(inBuf, len); - } + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } - const float* buf = inBuf; - qint32 remaining = len; + const float* buf = inBuf; + qint32 remaining = len; while (remaining > 0) - { - // Choose between live data or replayed data - if (replayEnabled && m_replayBuffer->useReplay()) { - len = m_replayBuffer->read(remaining, buf); - } else { - len = remaining; - } - remaining -= len; + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; switch (m_log2Decim) { @@ -198,7 +198,7 @@ void AirspyHFWorker::callbackQI(const float* inBuf, qint32 len) m_replayBuffer->unlock(); - m_sampleFifo->write(m_convertBuffer.begin(), it); + m_sampleFifo->write(m_convertBuffer.begin(), it); } int AirspyHFWorker::rx_callback(airspyhf_transfer_t* transfer) diff --git a/plugins/samplesource/limesdrinput/limesdrinputthread.cpp b/plugins/samplesource/limesdrinput/limesdrinputthread.cpp index 7ec9ebca0..2ec3f4164 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputthread.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputthread.cpp @@ -114,24 +114,24 @@ void LimeSDRInputThread::callbackIQ(const qint16* inBuf, qint32 len) SampleVector::iterator it = m_convertBuffer.begin(); // Save data to replay buffer - m_replayBuffer->lock(); - bool replayEnabled = m_replayBuffer->getSize() > 0; - if (replayEnabled) { - m_replayBuffer->write(inBuf, len); - } + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } - const qint16* buf = inBuf; - qint32 remaining = len; + const qint16* buf = inBuf; + qint32 remaining = len; while (remaining > 0) - { - // Choose between live data or replayed data - if (replayEnabled && m_replayBuffer->useReplay()) { - len = m_replayBuffer->read(remaining, buf); - } else { - len = remaining; - } - remaining -= len; + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; switch (m_log2Decim) { @@ -171,24 +171,24 @@ void LimeSDRInputThread::callbackQI(const qint16* inBuf, qint32 len) SampleVector::iterator it = m_convertBuffer.begin(); // Save data to replay buffer - m_replayBuffer->lock(); - bool replayEnabled = m_replayBuffer->getSize() > 0; - if (replayEnabled) { - m_replayBuffer->write(inBuf, len); - } + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } - const qint16* buf = inBuf; - qint32 remaining = len; + const qint16* buf = inBuf; + qint32 remaining = len; while (remaining > 0) - { - // Choose between live data or replayed data - if (replayEnabled && m_replayBuffer->useReplay()) { - len = m_replayBuffer->read(remaining, buf); - } else { - len = remaining; - } - remaining -= len; + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; switch (m_log2Decim) { @@ -216,7 +216,7 @@ void LimeSDRInputThread::callbackQI(const qint16* inBuf, qint32 len) default: break; } - } + } m_replayBuffer->unlock(); diff --git a/plugins/samplesource/rtlsdr/rtlsdrthread.cpp b/plugins/samplesource/rtlsdr/rtlsdrthread.cpp index a51e7a0ed..49e81a3fc 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrthread.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrthread.cpp @@ -98,240 +98,240 @@ void RTLSDRThread::run() // Len is total samples (i.e. one I and Q pair will have len=2) void RTLSDRThread::callbackIQ(const quint8* inBuf, qint32 len) { - SampleVector::iterator it = m_convertBuffer.begin(); + SampleVector::iterator it = m_convertBuffer.begin(); - // Save data to replay buffer - m_replayBuffer->lock(); - bool replayEnabled = m_replayBuffer->getSize() > 0; - if (replayEnabled) { - m_replayBuffer->write(inBuf, len); - } + // Save data to replay buffer + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } - const quint8* buf = inBuf; - qint32 remaining = len; + const quint8* buf = inBuf; + qint32 remaining = len; - while (remaining > 0) - { - // Choose between live data or replayed data - if (replayEnabled && m_replayBuffer->useReplay()) { - len = m_replayBuffer->read(remaining, buf); - } else { - len = remaining; - } - remaining -= len; + while (remaining > 0) + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; - if (m_log2Decim == 0) - { - m_decimatorsIQ.decimate1(&it, buf, len); - } - else - { - if (m_fcPos == 0) // Infradyne - { - switch (m_log2Decim) - { - case 1: - m_decimatorsIQ.decimate2_inf(&it, buf, len); - break; - case 2: - m_decimatorsIQ.decimate4_inf(&it, buf, len); - break; - case 3: - m_decimatorsIQ.decimate8_inf(&it, buf, len); - break; - case 4: - m_decimatorsIQ.decimate16_inf(&it, buf, len); - break; - case 5: - m_decimatorsIQ.decimate32_inf(&it, buf, len); - break; - case 6: - m_decimatorsIQ.decimate64_inf(&it, buf, len); - break; - default: - break; - } - } - else if (m_fcPos == 1) // Supradyne - { - switch (m_log2Decim) - { - case 1: - m_decimatorsIQ.decimate2_sup(&it, buf, len); - break; - case 2: - m_decimatorsIQ.decimate4_sup(&it, buf, len); - break; - case 3: - m_decimatorsIQ.decimate8_sup(&it, buf, len); - break; - case 4: - m_decimatorsIQ.decimate16_sup(&it, buf, len); - break; - case 5: - m_decimatorsIQ.decimate32_sup(&it, buf, len); - break; - case 6: - m_decimatorsIQ.decimate64_sup(&it, buf, len); - break; - default: - break; - } - } - else // Centered - { - switch (m_log2Decim) - { - case 1: - m_decimatorsIQ.decimate2_cen(&it, buf, len); - break; - case 2: - m_decimatorsIQ.decimate4_cen(&it, buf, len); - break; - case 3: - m_decimatorsIQ.decimate8_cen(&it, buf, len); - break; - case 4: - m_decimatorsIQ.decimate16_cen(&it, buf, len); - break; - case 5: - m_decimatorsIQ.decimate32_cen(&it, buf, len); - break; - case 6: - m_decimatorsIQ.decimate64_cen(&it, buf, len); - break; - default: - break; - } - } - } - } + if (m_log2Decim == 0) + { + m_decimatorsIQ.decimate1(&it, buf, len); + } + else + { + if (m_fcPos == 0) // Infradyne + { + switch (m_log2Decim) + { + case 1: + m_decimatorsIQ.decimate2_inf(&it, buf, len); + break; + case 2: + m_decimatorsIQ.decimate4_inf(&it, buf, len); + break; + case 3: + m_decimatorsIQ.decimate8_inf(&it, buf, len); + break; + case 4: + m_decimatorsIQ.decimate16_inf(&it, buf, len); + break; + case 5: + m_decimatorsIQ.decimate32_inf(&it, buf, len); + break; + case 6: + m_decimatorsIQ.decimate64_inf(&it, buf, len); + break; + default: + break; + } + } + else if (m_fcPos == 1) // Supradyne + { + switch (m_log2Decim) + { + case 1: + m_decimatorsIQ.decimate2_sup(&it, buf, len); + break; + case 2: + m_decimatorsIQ.decimate4_sup(&it, buf, len); + break; + case 3: + m_decimatorsIQ.decimate8_sup(&it, buf, len); + break; + case 4: + m_decimatorsIQ.decimate16_sup(&it, buf, len); + break; + case 5: + m_decimatorsIQ.decimate32_sup(&it, buf, len); + break; + case 6: + m_decimatorsIQ.decimate64_sup(&it, buf, len); + break; + default: + break; + } + } + else // Centered + { + switch (m_log2Decim) + { + case 1: + m_decimatorsIQ.decimate2_cen(&it, buf, len); + break; + case 2: + m_decimatorsIQ.decimate4_cen(&it, buf, len); + break; + case 3: + m_decimatorsIQ.decimate8_cen(&it, buf, len); + break; + case 4: + m_decimatorsIQ.decimate16_cen(&it, buf, len); + break; + case 5: + m_decimatorsIQ.decimate32_cen(&it, buf, len); + break; + case 6: + m_decimatorsIQ.decimate64_cen(&it, buf, len); + break; + default: + break; + } + } + } + } - m_replayBuffer->unlock(); + m_replayBuffer->unlock(); - m_sampleFifo->write(m_convertBuffer.begin(), it); + m_sampleFifo->write(m_convertBuffer.begin(), it); - if(!m_running) - rtlsdr_cancel_async(m_dev); + if(!m_running) + rtlsdr_cancel_async(m_dev); } void RTLSDRThread::callbackQI(const quint8* inBuf, qint32 len) { - SampleVector::iterator it = m_convertBuffer.begin(); + SampleVector::iterator it = m_convertBuffer.begin(); - // Save data to replay buffer - m_replayBuffer->lock(); - bool replayEnabled = m_replayBuffer->getSize() > 0; - if (replayEnabled) { - m_replayBuffer->write(inBuf, len); - } + // Save data to replay buffer + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } - const quint8* buf = inBuf; - qint32 remaining = len; + const quint8* buf = inBuf; + qint32 remaining = len; - while (remaining > 0) - { - // Choose between live data or replayed data - if (replayEnabled && m_replayBuffer->useReplay()) { - len = m_replayBuffer->read(remaining, buf); - } else { - len = remaining; - } - remaining -= len; + while (remaining > 0) + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; - if (m_log2Decim == 0) - { - m_decimatorsQI.decimate1(&it, buf, len); - } - else - { - if (m_fcPos == 0) // Infradyne - { - switch (m_log2Decim) - { - case 1: - m_decimatorsQI.decimate2_inf(&it, buf, len); - break; - case 2: - m_decimatorsQI.decimate4_inf(&it, buf, len); - break; - case 3: - m_decimatorsQI.decimate8_inf(&it, buf, len); - break; - case 4: - m_decimatorsQI.decimate16_inf(&it, buf, len); - break; - case 5: - m_decimatorsQI.decimate32_inf(&it, buf, len); - break; - case 6: - m_decimatorsQI.decimate64_inf(&it, buf, len); - break; - default: - break; - } - } - else if (m_fcPos == 1) // Supradyne - { - switch (m_log2Decim) - { - case 1: - m_decimatorsQI.decimate2_sup(&it, buf, len); - break; - case 2: - m_decimatorsQI.decimate4_sup(&it, buf, len); - break; - case 3: - m_decimatorsQI.decimate8_sup(&it, buf, len); - break; - case 4: - m_decimatorsQI.decimate16_sup(&it, buf, len); - break; - case 5: - m_decimatorsQI.decimate32_sup(&it, buf, len); - break; - case 6: - m_decimatorsQI.decimate64_sup(&it, buf, len); - break; - default: - break; - } - } - else // Centered - { - switch (m_log2Decim) - { - case 1: - m_decimatorsQI.decimate2_cen(&it, buf, len); - break; - case 2: - m_decimatorsQI.decimate4_cen(&it, buf, len); - break; - case 3: - m_decimatorsQI.decimate8_cen(&it, buf, len); - break; - case 4: - m_decimatorsQI.decimate16_cen(&it, buf, len); - break; - case 5: - m_decimatorsQI.decimate32_cen(&it, buf, len); - break; - case 6: - m_decimatorsQI.decimate64_cen(&it, buf, len); - break; - default: - break; - } - } - } - } + if (m_log2Decim == 0) + { + m_decimatorsQI.decimate1(&it, buf, len); + } + else + { + if (m_fcPos == 0) // Infradyne + { + switch (m_log2Decim) + { + case 1: + m_decimatorsQI.decimate2_inf(&it, buf, len); + break; + case 2: + m_decimatorsQI.decimate4_inf(&it, buf, len); + break; + case 3: + m_decimatorsQI.decimate8_inf(&it, buf, len); + break; + case 4: + m_decimatorsQI.decimate16_inf(&it, buf, len); + break; + case 5: + m_decimatorsQI.decimate32_inf(&it, buf, len); + break; + case 6: + m_decimatorsQI.decimate64_inf(&it, buf, len); + break; + default: + break; + } + } + else if (m_fcPos == 1) // Supradyne + { + switch (m_log2Decim) + { + case 1: + m_decimatorsQI.decimate2_sup(&it, buf, len); + break; + case 2: + m_decimatorsQI.decimate4_sup(&it, buf, len); + break; + case 3: + m_decimatorsQI.decimate8_sup(&it, buf, len); + break; + case 4: + m_decimatorsQI.decimate16_sup(&it, buf, len); + break; + case 5: + m_decimatorsQI.decimate32_sup(&it, buf, len); + break; + case 6: + m_decimatorsQI.decimate64_sup(&it, buf, len); + break; + default: + break; + } + } + else // Centered + { + switch (m_log2Decim) + { + case 1: + m_decimatorsQI.decimate2_cen(&it, buf, len); + break; + case 2: + m_decimatorsQI.decimate4_cen(&it, buf, len); + break; + case 3: + m_decimatorsQI.decimate8_cen(&it, buf, len); + break; + case 4: + m_decimatorsQI.decimate16_cen(&it, buf, len); + break; + case 5: + m_decimatorsQI.decimate32_cen(&it, buf, len); + break; + case 6: + m_decimatorsQI.decimate64_cen(&it, buf, len); + break; + default: + break; + } + } + } + } - m_replayBuffer->unlock(); + m_replayBuffer->unlock(); - m_sampleFifo->write(m_convertBuffer.begin(), it); + m_sampleFifo->write(m_convertBuffer.begin(), it); - if(!m_running) - rtlsdr_cancel_async(m_dev); + if(!m_running) + rtlsdr_cancel_async(m_dev); } void RTLSDRThread::callbackHelper(unsigned char* buf, uint32_t len, void* ctx) diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3thread.cpp b/plugins/samplesource/sdrplayv3/sdrplayv3thread.cpp index e4f069ac2..7e6a52617 100644 --- a/plugins/samplesource/sdrplayv3/sdrplayv3thread.cpp +++ b/plugins/samplesource/sdrplayv3/sdrplayv3thread.cpp @@ -177,24 +177,24 @@ void SDRPlayV3Thread::callbackIQ(const qint16* inBuf, qint32 len) SampleVector::iterator it = m_convertBuffer.begin(); // Save data to replay buffer - m_replayBuffer->lock(); - bool replayEnabled = m_replayBuffer->getSize() > 0; - if (replayEnabled) { - m_replayBuffer->write(inBuf, len); - } + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } - const qint16* buf = inBuf; - qint32 remaining = len; + const qint16* buf = inBuf; + qint32 remaining = len; while (remaining > 0) - { - // Choose between live data or replayed data - if (replayEnabled && m_replayBuffer->useReplay()) { - len = m_replayBuffer->read(remaining, buf); - } else { - len = remaining; - } - remaining -= len; + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; if (m_log2Decim == 0) { @@ -293,24 +293,24 @@ void SDRPlayV3Thread::callbackQI(const qint16* inBuf, qint32 len) SampleVector::iterator it = m_convertBuffer.begin(); // Save data to replay buffer - m_replayBuffer->lock(); - bool replayEnabled = m_replayBuffer->getSize() > 0; - if (replayEnabled) { - m_replayBuffer->write(inBuf, len); - } + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } - const qint16* buf = inBuf; - qint32 remaining = len; + const qint16* buf = inBuf; + qint32 remaining = len; while (remaining > 0) - { - // Choose between live data or replayed data - if (replayEnabled && m_replayBuffer->useReplay()) { - len = m_replayBuffer->read(remaining, buf); - } else { - len = remaining; - } - remaining -= len; + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; if (m_log2Decim == 0) { diff --git a/plugins/samplesource/usrpinput/usrpinputthread.cpp b/plugins/samplesource/usrpinput/usrpinputthread.cpp index 5f2ffd5c8..b53d60b2a 100644 --- a/plugins/samplesource/usrpinput/usrpinputthread.cpp +++ b/plugins/samplesource/usrpinput/usrpinputthread.cpp @@ -198,24 +198,24 @@ void USRPInputThread::callbackIQ(const qint16* inBuf, qint32 len) SampleVector::iterator it = m_convertBuffer.begin(); // Save data to replay buffer - m_replayBuffer->lock(); - bool replayEnabled = m_replayBuffer->getSize() > 0; - if (replayEnabled) { - m_replayBuffer->write(inBuf, len); - } + m_replayBuffer->lock(); + bool replayEnabled = m_replayBuffer->getSize() > 0; + if (replayEnabled) { + m_replayBuffer->write(inBuf, len); + } - const qint16* buf = inBuf; - qint32 remaining = len; + const qint16* buf = inBuf; + qint32 remaining = len; while (remaining > 0) - { - // Choose between live data or replayed data - if (replayEnabled && m_replayBuffer->useReplay()) { - len = m_replayBuffer->read(remaining, buf); - } else { - len = remaining; - } - remaining -= len; + { + // Choose between live data or replayed data + if (replayEnabled && m_replayBuffer->useReplay()) { + len = m_replayBuffer->read(remaining, buf); + } else { + len = remaining; + } + remaining -= len; switch (m_log2Decim) { From 30497b5204828d8241fa22479a26f43b94fa442d Mon Sep 17 00:00:00 2001 From: srcejon <jon@beniston.com> Date: Wed, 6 Dec 2023 13:08:09 +0000 Subject: [PATCH 5/5] More fixes for Mac build --- .github/workflows/sdrangel.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/sdrangel.yml b/.github/workflows/sdrangel.yml index 5ad2b6e86..5fb05eada 100644 --- a/.github/workflows/sdrangel.yml +++ b/.github/workflows/sdrangel.yml @@ -130,6 +130,14 @@ jobs: id: get_filename run: echo "filename=$(grep CPACK_PACKAGE_FILE_NAME build/CMakeCache.txt | cut -d "=" -f2)" >> $GITHUB_OUTPUT - name: Build SDRangel on Mac + run: | + cd build + make -j3 + - name: Stop XProtectBehaviorService + run: | + echo "killing XProject as it can interfere with hdiutil"; sudo pkill -9 XProtect >/dev/null || true; + echo "waiting..."; while pgrep XProtect; do sleep 3; done; + - name: Build DMG run: | cd build make package -j3