mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-21 15:51:47 -05:00
Compare commits
15 Commits
6a49c1d9f1
...
42cabeb96d
Author | SHA1 | Date | |
---|---|---|---|
|
42cabeb96d | ||
|
36349e2837 | ||
|
3a7de65ee5 | ||
|
38043ebdbc | ||
|
49074d1ce9 | ||
|
24dba6f7f1 | ||
|
0208d11376 | ||
|
7d1af5b24f | ||
|
7739dfd468 | ||
|
4a2032a26a | ||
|
436d1665ea | ||
|
f5e7708612 | ||
|
0ff75e1538 | ||
|
580fbda09c | ||
|
4a6943b4d9 |
@ -59,6 +59,7 @@ void WDSPRxBaseband::reset()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
m_sink.applyAudioSampleRate(DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate());
|
||||
mutexLocker.unlock();
|
||||
m_sampleFifo.reset();
|
||||
m_channelSampleRate = 0;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@
|
||||
|
||||
WDSPRxGUI* WDSPRxGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
|
||||
{
|
||||
WDSPRxGUI* gui = new WDSPRxGUI(pluginAPI, deviceUISet, rxChannel);
|
||||
auto* gui = new WDSPRxGUI(pluginAPI, deviceUISet, rxChannel);
|
||||
return gui;
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ bool WDSPRxGUI::handleMessage(const Message& message)
|
||||
if (WDSPRx::MsgConfigureWDSPRx::match(message))
|
||||
{
|
||||
qDebug("WDSPRxGUI::handleMessage: WDSPRx::MsgConfigureWDSPRx");
|
||||
const WDSPRx::MsgConfigureWDSPRx& cfg = (WDSPRx::MsgConfigureWDSPRx&) message;
|
||||
auto& cfg = (const WDSPRx::MsgConfigureWDSPRx&) message;
|
||||
m_settings = cfg.getSettings();
|
||||
blockApplySettings(true);
|
||||
ui->spectrumGUI->updateSettings();
|
||||
@ -118,7 +118,7 @@ bool WDSPRxGUI::handleMessage(const Message& message)
|
||||
}
|
||||
else if (DSPSignalNotification::match(message))
|
||||
{
|
||||
const DSPSignalNotification& notif = (const DSPSignalNotification&) message;
|
||||
auto& notif = (const DSPSignalNotification&) message;
|
||||
m_deviceCenterFrequency = notif.getCenterFrequency();
|
||||
m_basebandSampleRate = notif.getSampleRate();
|
||||
qDebug("WDSPRxGUI::handleMessage: DSPSignalNotification: centerFrequency: %lld sampleRate: %d",
|
||||
@ -138,7 +138,7 @@ void WDSPRxGUI::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
while ((message = getInputMessageQueue()->pop()) != nullptr)
|
||||
{
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
@ -183,7 +183,7 @@ void WDSPRxGUI::on_dsb_toggled(bool dsb)
|
||||
|
||||
void WDSPRxGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_channelMarker.setCenterFrequency((int) value);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
updateAbsoluteCenterFrequency();
|
||||
applySettings();
|
||||
@ -205,7 +205,7 @@ void WDSPRxGUI::on_lowCut_valueChanged(int value)
|
||||
void WDSPRxGUI::on_volume_valueChanged(int value)
|
||||
{
|
||||
ui->volumeText->setText(QString("%1").arg(value));
|
||||
m_settings.m_volume = CalcDb::powerFromdB(value);
|
||||
m_settings.m_volume = (Real) CalcDb::powerFromdB(value);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -279,7 +279,7 @@ void WDSPRxGUI::on_rit_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_rit = checked;
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_rit = m_settings.m_rit;
|
||||
m_channelMarker.setShift(checked ? m_settings.m_ritFrequency: 0);
|
||||
m_channelMarker.setShift(checked ? (int) m_settings.m_ritFrequency: 0);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -406,7 +406,7 @@ void WDSPRxGUI::on_profileIndex_valueChanged(int value)
|
||||
|
||||
void WDSPRxGUI::on_demod_currentIndexChanged(int index)
|
||||
{
|
||||
WDSPRxProfile::WDSPRxDemod demod = (WDSPRxProfile::WDSPRxDemod) index;
|
||||
auto demod = (WDSPRxProfile::WDSPRxDemod) index;
|
||||
|
||||
if ((m_settings.m_demod != WDSPRxProfile::DemodSSB) && (demod == WDSPRxProfile::DemodSSB)) {
|
||||
m_settings.m_dsb = false;
|
||||
@ -480,7 +480,7 @@ void WDSPRxGUI::onMenuDialogCalled(const QPoint &p)
|
||||
resetContextMenuType();
|
||||
}
|
||||
|
||||
void WDSPRxGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
void WDSPRxGUI::onWidgetRolled(const QWidget* widget, bool rollDown)
|
||||
{
|
||||
(void) widget;
|
||||
(void) rollDown;
|
||||
@ -524,7 +524,7 @@ WDSPRxGUI::WDSPRxGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam
|
||||
m_wdspRx = (WDSPRx*) rxChannel;
|
||||
m_spectrumVis = m_wdspRx->getSpectrumVis();
|
||||
m_spectrumVis->setGLSpectrum(ui->glSpectrum);
|
||||
m_wdspRx->setMessageQueueToGUI(getInputMessageQueue());
|
||||
m_wdspRx->setMessageQueueToGUI(WDSPRxGUI::getInputMessageQueue());
|
||||
|
||||
m_audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute);
|
||||
connect(m_audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect(const QPoint &)));
|
||||
@ -588,7 +588,7 @@ WDSPRxGUI::WDSPRxGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam
|
||||
m_deviceUISet->addChannelMarker(&m_channelMarker);
|
||||
connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
|
||||
connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
connect(WDSPRxGUI::getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
|
||||
|
||||
m_iconDSBUSB.addPixmap(QPixmap("://dsb.png"), QIcon::Normal, QIcon::On);
|
||||
@ -654,7 +654,7 @@ uint32_t WDSPRxGUI::getValidAudioSampleRate() const
|
||||
return sr;
|
||||
}
|
||||
|
||||
unsigned int WDSPRxGUI::spanLog2Max()
|
||||
unsigned int WDSPRxGUI::spanLog2Max() const
|
||||
{
|
||||
unsigned int spanLog2 = 0;
|
||||
for (; getValidAudioSampleRate() / (1<<spanLog2) >= 1000; spanLog2++);
|
||||
@ -668,7 +668,6 @@ void WDSPRxGUI::applyBandwidths(unsigned int spanLog2, bool force)
|
||||
unsigned int limit = s2max < 1 ? 0 : s2max - 1;
|
||||
ui->spanLog2->setMaximum(limit);
|
||||
bool dsb = ui->dsb->isChecked();
|
||||
//int spanLog2 = ui->spanLog2->value();
|
||||
m_spectrumRate = getValidAudioSampleRate() / (1<<spanLog2);
|
||||
int bw = ui->BW->value();
|
||||
int lw = ui->lowCut->value();
|
||||
@ -764,8 +763,8 @@ void WDSPRxGUI::applyBandwidths(unsigned int spanLog2, bool force)
|
||||
m_settings.m_dsb = dsb;
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_dsb = dsb;
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_spanLog2 = spanLog2;
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff = bw * 100;
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff = lw * 100;
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff = (Real) (bw * 100);
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff = (Real) (lw * 100);
|
||||
|
||||
applySettings(force);
|
||||
|
||||
@ -785,11 +784,11 @@ void WDSPRxGUI::displaySettings()
|
||||
{
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setBandwidth(m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff * 2);
|
||||
m_channelMarker.setBandwidth((int) (m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff * 2));
|
||||
m_channelMarker.setTitle(m_settings.m_title);
|
||||
m_channelMarker.setLowCutoff(m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff);
|
||||
m_channelMarker.setLowCutoff((int) m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff);
|
||||
int shift = m_settings.m_profiles[m_settings.m_profileIndex].m_rit ?
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_ritFrequency :
|
||||
(int) m_settings.m_profiles[m_settings.m_profileIndex].m_ritFrequency :
|
||||
0;
|
||||
m_channelMarker.setShift(shift);
|
||||
|
||||
@ -880,7 +879,7 @@ void WDSPRxGUI::displaySettings()
|
||||
ui->dsb->setChecked(m_settings.m_dsb);
|
||||
ui->spanLog2->setValue(1 + ui->spanLog2->maximum() - m_settings.m_profiles[m_settings.m_profileIndex].m_spanLog2);
|
||||
|
||||
ui->BW->setValue(m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff / 100.0);
|
||||
ui->BW->setValue((int) (m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff / 100.0));
|
||||
s = QString::number(m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff/1000.0, 'f', 1);
|
||||
|
||||
if (m_settings.m_dsb) {
|
||||
@ -899,10 +898,10 @@ void WDSPRxGUI::displaySettings()
|
||||
|
||||
// The only one of the four signals triggering applyBandwidths will trigger it once only with all other values
|
||||
// set correctly and therefore validate the settings and apply them to dependent widgets
|
||||
ui->lowCut->setValue(m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff / 100.0);
|
||||
ui->lowCut->setValue((int) (m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff / 100.0));
|
||||
ui->lowCutText->setText(tr("%1k").arg(m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff / 1000.0));
|
||||
|
||||
int volume = CalcDb::dbPower(m_settings.m_volume);
|
||||
auto volume = (int) CalcDb::dbPower(m_settings.m_volume);
|
||||
ui->volume->setValue(volume);
|
||||
ui->volumeText->setText(QString("%1").arg(volume));
|
||||
|
||||
@ -1199,15 +1198,11 @@ void WDSPRxGUI::amSetup(int iValueChanged)
|
||||
|
||||
auto valueChanged = (WDSPRxAMDialog::ValueChanged) iValueChanged;
|
||||
|
||||
switch (valueChanged)
|
||||
if (valueChanged == WDSPRxAMDialog::ChangedFadeLevel)
|
||||
{
|
||||
case WDSPRxAMDialog::ChangedFadeLevel:
|
||||
m_settings.m_amFadeLevel = m_amDialog->getFadeLevel();
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_amFadeLevel = m_settings.m_amFadeLevel;
|
||||
applySettings();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1369,21 +1364,18 @@ void WDSPRxGUI::panSetup(int iValueChanged)
|
||||
|
||||
auto valueChanged = (WDSPRxPanDialog::ValueChanged) iValueChanged;
|
||||
|
||||
switch (valueChanged)
|
||||
if (valueChanged == WDSPRxPanDialog::ChangedPan)
|
||||
{
|
||||
case WDSPRxPanDialog::ChangedPan:
|
||||
m_settings.m_audioPan = m_panDialog->getPan();
|
||||
m_settings.m_profiles[m_settings.m_profileIndex].m_audioPan = m_settings.m_audioPan;
|
||||
applySettings();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WDSPRxGUI::tick()
|
||||
{
|
||||
double powDbAvg, powDbPeak;
|
||||
double powDbAvg;
|
||||
double powDbPeak;
|
||||
int nbMagsqSamples;
|
||||
m_wdspRx->getMagSqLevels(powDbAvg, powDbPeak, nbMagsqSamples); // powers directly in dB
|
||||
|
||||
@ -1416,7 +1408,7 @@ void WDSPRxGUI::tick()
|
||||
m_tickCount++;
|
||||
}
|
||||
|
||||
void WDSPRxGUI::makeUIConnections()
|
||||
void WDSPRxGUI::makeUIConnections() const
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &WDSPRxGUI::on_deltaFrequency_changed);
|
||||
QObject::connect(ui->audioBinaural, &QToolButton::toggled, this, &WDSPRxGUI::on_audioBinaural_toggled);
|
||||
|
@ -58,21 +58,21 @@ public:
|
||||
static WDSPRxGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
|
||||
virtual void destroy();
|
||||
|
||||
void resetToDefaults();
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; };
|
||||
virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; };
|
||||
virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; };
|
||||
virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; };
|
||||
virtual QString getTitle() const { return m_settings.m_title; };
|
||||
virtual QColor getTitleColor() const { return m_settings.m_rgbColor; };
|
||||
virtual void zetHidden(bool hidden) { m_settings.m_hidden = hidden; }
|
||||
virtual bool getHidden() const { return m_settings.m_hidden; }
|
||||
virtual ChannelMarker& getChannelMarker() { return m_channelMarker; }
|
||||
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
|
||||
virtual void setStreamIndex(int streamIndex) { m_settings.m_streamIndex = streamIndex; }
|
||||
void resetToDefaults() final;
|
||||
QByteArray serialize() const final;
|
||||
bool deserialize(const QByteArray& data) final;
|
||||
MessageQueue *getInputMessageQueue() final { return &m_inputMessageQueue; }
|
||||
void setWorkspaceIndex(int index) final { m_settings.m_workspaceIndex = index; };
|
||||
int getWorkspaceIndex() const final { return m_settings.m_workspaceIndex; };
|
||||
void setGeometryBytes(const QByteArray& blob) final { m_settings.m_geometryBytes = blob; };
|
||||
QByteArray getGeometryBytes() const final { return m_settings.m_geometryBytes; };
|
||||
QString getTitle() const final { return m_settings.m_title; };
|
||||
QColor getTitleColor() const final { return m_settings.m_rgbColor; };
|
||||
void zetHidden(bool hidden) final { m_settings.m_hidden = hidden; }
|
||||
bool getHidden() const final { return m_settings.m_hidden; }
|
||||
ChannelMarker& getChannelMarker() final { return m_channelMarker; }
|
||||
int getStreamIndex() const final { return m_settings.m_streamIndex; }
|
||||
void setStreamIndex(int streamIndex) final { m_settings.m_streamIndex = streamIndex; }
|
||||
|
||||
public slots:
|
||||
void channelMarkerChangedByCursor();
|
||||
@ -122,21 +122,21 @@ private:
|
||||
QIcon m_iconDSBUSB;
|
||||
QIcon m_iconDSBLSB;
|
||||
|
||||
explicit WDSPRxGUI(PluginAPI* pluginAPI, DeviceUISet* deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
|
||||
virtual ~WDSPRxGUI();
|
||||
explicit WDSPRxGUI(PluginAPI* pluginAPI, DeviceUISet* deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = nullptr);
|
||||
~WDSPRxGUI() final;
|
||||
|
||||
bool blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
void applyBandwidths(unsigned int spanLog2, bool force = false);
|
||||
unsigned int spanLog2Max();
|
||||
unsigned int spanLog2Max() const;
|
||||
void displaySettings();
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
void makeUIConnections() const;
|
||||
void updateAbsoluteCenterFrequency();
|
||||
uint32_t getValidAudioSampleRate() const;
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(EnterEventType*);
|
||||
void leaveEvent(QEvent*) final;
|
||||
void enterEvent(EnterEventType*) final;
|
||||
|
||||
private slots:
|
||||
void on_deltaFrequency_changed(qint64 value);
|
||||
@ -164,7 +164,7 @@ private slots:
|
||||
void on_rit_toggled(bool checked);
|
||||
void on_ritFrequency_valueChanged(int value);
|
||||
void on_dbOrS_toggled(bool checked);
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onWidgetRolled(const QWidget* widget, bool rollDown);
|
||||
void onMenuDialogCalled(const QPoint& p);
|
||||
void handleInputMessages();
|
||||
void audioSelect(const QPoint& p);
|
||||
|
@ -55,19 +55,9 @@ const char* const AMMod::m_channelId ="AMMod";
|
||||
|
||||
AMMod::AMMod(DeviceAPI *deviceAPI) :
|
||||
ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_fileSize(0),
|
||||
m_recordLength(0),
|
||||
m_sampleRate(48000)
|
||||
m_deviceAPI(deviceAPI)
|
||||
{
|
||||
setObjectName(m_channelId);
|
||||
|
||||
m_thread = new QThread(this);
|
||||
m_basebandSource = new AMModBaseband();
|
||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||
m_basebandSource->setChannel(this);
|
||||
m_basebandSource->moveToThread(m_thread);
|
||||
|
||||
applySettings(m_settings, true);
|
||||
|
||||
m_deviceAPI->addChannelSource(this);
|
||||
@ -93,8 +83,8 @@ AMMod::~AMMod()
|
||||
delete m_networkManager;
|
||||
m_deviceAPI->removeChannelSourceAPI(this);
|
||||
m_deviceAPI->removeChannelSource(this);
|
||||
delete m_basebandSource;
|
||||
delete m_thread;
|
||||
|
||||
AMMod::stop();
|
||||
}
|
||||
|
||||
void AMMod::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
@ -116,21 +106,61 @@ uint32_t AMMod::getNumberOfDeviceStreams() const
|
||||
|
||||
void AMMod::start()
|
||||
{
|
||||
if (m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("AMMod::start");
|
||||
m_thread = new QThread(this);
|
||||
m_basebandSource = new AMModBaseband();
|
||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||
m_basebandSource->setChannel(this);
|
||||
m_basebandSource->reset();
|
||||
m_basebandSource->setCWKeyer(&m_cwKeyer);
|
||||
m_basebandSource->moveToThread(m_thread);
|
||||
|
||||
QObject::connect(
|
||||
m_thread,
|
||||
&QThread::finished,
|
||||
m_basebandSource,
|
||||
&QObject::deleteLater
|
||||
);
|
||||
QObject::connect(
|
||||
m_thread,
|
||||
&QThread::finished,
|
||||
m_thread,
|
||||
&QThread::deleteLater
|
||||
);
|
||||
|
||||
m_thread->start();
|
||||
|
||||
AMModBaseband::MsgConfigureAMModBaseband *msg = AMModBaseband::MsgConfigureAMModBaseband::create(m_settings, true);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
|
||||
if (m_levelMeter) {
|
||||
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), m_levelMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
}
|
||||
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
void AMMod::stop()
|
||||
{
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("AMMod::stop");
|
||||
m_running = false;
|
||||
m_thread->exit();
|
||||
m_thread->wait();
|
||||
}
|
||||
|
||||
void AMMod::pull(SampleVector::iterator& begin, unsigned int nbSamples)
|
||||
{
|
||||
m_basebandSource->pull(begin, nbSamples);
|
||||
if (m_running) {
|
||||
m_basebandSource->pull(begin, nbSamples);
|
||||
}
|
||||
}
|
||||
|
||||
void AMMod::setCenterFrequency(qint64 frequency)
|
||||
@ -150,7 +180,7 @@ bool AMMod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if (MsgConfigureAMMod::match(cmd))
|
||||
{
|
||||
MsgConfigureAMMod& cfg = (MsgConfigureAMMod&) cmd;
|
||||
auto& cfg = (const MsgConfigureAMMod&) cmd;
|
||||
qDebug() << "AMMod::handleMessage: MsgConfigureAMMod";
|
||||
|
||||
applySettings(cfg.getSettings(), cfg.getForce());
|
||||
@ -159,7 +189,7 @@ bool AMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MsgConfigureFileSourceName::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) cmd;
|
||||
auto& conf = (const MsgConfigureFileSourceName&) cmd;
|
||||
m_fileName = conf.getFileName();
|
||||
qDebug() << "AMMod::handleMessage: MsgConfigureFileSourceName";
|
||||
openFileStream();
|
||||
@ -167,7 +197,7 @@ bool AMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MsgConfigureFileSourceSeek::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceSeek& conf = (MsgConfigureFileSourceSeek&) cmd;
|
||||
auto& conf = (const MsgConfigureFileSourceSeek&) cmd;
|
||||
int seekPercentage = conf.getPercentage();
|
||||
qDebug() << "AMMod::handleMessage: MsgConfigureFileSourceSeek";
|
||||
seekFileStream(seekPercentage);
|
||||
@ -176,13 +206,13 @@ bool AMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MsgConfigureFileSourceStreamTiming::match(cmd))
|
||||
{
|
||||
std::size_t samplesCount;
|
||||
std::size_t samplesCount;
|
||||
|
||||
if (m_ifstream.eof()) {
|
||||
samplesCount = m_fileSize / sizeof(Real);
|
||||
} else {
|
||||
samplesCount = m_ifstream.tellg() / sizeof(Real);
|
||||
}
|
||||
if (m_ifstream.eof()) {
|
||||
samplesCount = m_fileSize / sizeof(Real);
|
||||
} else {
|
||||
samplesCount = m_ifstream.tellg() / sizeof(Real);
|
||||
}
|
||||
|
||||
MsgReportFileSourceStreamTiming *report;
|
||||
report = MsgReportFileSourceStreamTiming::create(samplesCount);
|
||||
@ -192,7 +222,7 @@ bool AMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (CWKeyer::MsgConfigureCWKeyer::match(cmd))
|
||||
{
|
||||
const CWKeyer::MsgConfigureCWKeyer& cfg = (CWKeyer::MsgConfigureCWKeyer&) cmd;
|
||||
auto& cfg = (const CWKeyer::MsgConfigureCWKeyer&) cmd;
|
||||
qDebug() << "AMMod::handleMessage: MsgConfigureCWKeyer";
|
||||
|
||||
if (m_settings.m_useReverseAPI) {
|
||||
@ -203,11 +233,13 @@ bool AMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
// Forward to the source
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy
|
||||
qDebug() << "AMMod::handleMessage: DSPSignalNotification";
|
||||
m_basebandSource->getInputMessageQueue()->push(rep);
|
||||
// Forward to the source
|
||||
auto& notif = (const DSPSignalNotification&) cmd;
|
||||
|
||||
if (m_running) {
|
||||
m_basebandSource->getInputMessageQueue()->push(new DSPSignalNotification(notif));
|
||||
}
|
||||
// Forward to GUI if any
|
||||
if (getMessageQueueToGUI()) {
|
||||
getMessageQueueToGUI()->push(new DSPSignalNotification(notif));
|
||||
@ -239,7 +271,7 @@ void AMMod::openFileStream()
|
||||
m_ifstream.seekg(0,std::ios_base::beg);
|
||||
|
||||
m_sampleRate = 48000; // fixed rate
|
||||
m_recordLength = m_fileSize / (sizeof(Real) * m_sampleRate);
|
||||
m_recordLength = (quint32) (m_fileSize / (sizeof(Real) * m_sampleRate));
|
||||
|
||||
qDebug() << "AMMod::openFileStream: " << m_fileName.toStdString().c_str()
|
||||
<< " fileSize: " << m_fileSize << "bytes"
|
||||
@ -338,8 +370,11 @@ void AMMod::applySettings(const AMModSettings& settings, bool force)
|
||||
reverseAPIKeys.append("streamIndex");
|
||||
}
|
||||
|
||||
AMModBaseband::MsgConfigureAMModBaseband *msg = AMModBaseband::MsgConfigureAMModBaseband::create(settings, force);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
if (m_running)
|
||||
{
|
||||
AMModBaseband::MsgConfigureAMModBaseband *msg = AMModBaseband::MsgConfigureAMModBaseband::create(settings, force);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
}
|
||||
|
||||
if (settings.m_useReverseAPI)
|
||||
{
|
||||
@ -354,7 +389,7 @@ void AMMod::applySettings(const AMModSettings& settings, bool force)
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "settings", pipes);
|
||||
|
||||
if (pipes.size() > 0) {
|
||||
if (!pipes.empty()) {
|
||||
sendChannelSettings(pipes, reverseAPIKeys, settings, force);
|
||||
}
|
||||
|
||||
@ -383,12 +418,12 @@ bool AMMod::deserialize(const QByteArray& data)
|
||||
}
|
||||
}
|
||||
|
||||
void AMMod::sendSampleRateToDemodAnalyzer()
|
||||
void AMMod::sendSampleRateToDemodAnalyzer() const
|
||||
{
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "reportdemod", pipes);
|
||||
|
||||
if (pipes.size() > 0)
|
||||
if (!pipes.empty())
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
@ -412,7 +447,7 @@ int AMMod::webapiSettingsGet(
|
||||
webapiFormatChannelSettings(response, m_settings);
|
||||
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getAmModSettings()->getCwKeyer();
|
||||
const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings();
|
||||
const CWKeyerSettings& cwKeyerSettings = getCWKeyer()->getSettings();
|
||||
CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
|
||||
return 200;
|
||||
@ -440,11 +475,11 @@ int AMMod::webapiSettingsPutPatch(
|
||||
if (channelSettingsKeys.contains("cwKeyer"))
|
||||
{
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getAmModSettings()->getCwKeyer();
|
||||
CWKeyerSettings cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings();
|
||||
CWKeyerSettings cwKeyerSettings = getCWKeyer()->getSettings();
|
||||
CWKeyer::webapiSettingsPutPatch(channelSettingsKeys, cwKeyerSettings, apiCwKeyerSettings);
|
||||
|
||||
CWKeyer::MsgConfigureCWKeyer *msgCwKeyer = CWKeyer::MsgConfigureCWKeyer::create(cwKeyerSettings, force);
|
||||
m_basebandSource->getCWKeyer().getInputMessageQueue()->push(msgCwKeyer);
|
||||
getCWKeyer()->getInputMessageQueue()->push(msgCwKeyer);
|
||||
|
||||
if (m_guiMessageQueue) // forward to GUI if any
|
||||
{
|
||||
@ -515,13 +550,13 @@ void AMMod::webapiUpdateChannelSettings(
|
||||
settings.m_reverseAPIAddress = *response.getAmModSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getAmModSettings()->getReverseApiPort();
|
||||
settings.m_reverseAPIPort = (uint16_t) response.getAmModSettings()->getReverseApiPort();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getAmModSettings()->getReverseApiDeviceIndex();
|
||||
settings.m_reverseAPIDeviceIndex = (uint16_t) response.getAmModSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
|
||||
settings.m_reverseAPIChannelIndex = response.getAmModSettings()->getReverseApiChannelIndex();
|
||||
settings.m_reverseAPIChannelIndex = (uint16_t) response.getAmModSettings()->getReverseApiChannelIndex();
|
||||
}
|
||||
if (settings.m_channelMarker && channelSettingsKeys.contains("channelMarker")) {
|
||||
settings.m_channelMarker->updateFrom(channelSettingsKeys, response.getAmModSettings()->getChannelMarker());
|
||||
@ -591,7 +626,7 @@ void AMMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respons
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
auto *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
response.getAmModSettings()->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
@ -605,23 +640,27 @@ void AMMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respons
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
auto *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
response.getAmModSettings()->setRollupState(swgRollupState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AMMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response)
|
||||
void AMMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) const
|
||||
{
|
||||
response.getAmModReport()->setChannelPowerDb(CalcDb::dbPower(getMagSq()));
|
||||
response.getAmModReport()->setAudioSampleRate(m_basebandSource->getAudioSampleRate());
|
||||
response.getAmModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate());
|
||||
response.getAmModReport()->setChannelPowerDb((float) CalcDb::dbPower(getMagSq()));
|
||||
|
||||
if (m_running)
|
||||
{
|
||||
response.getAmModReport()->setAudioSampleRate(m_basebandSource->getAudioSampleRate());
|
||||
response.getAmModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate());
|
||||
}
|
||||
}
|
||||
|
||||
void AMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AMModSettings& settings, bool force)
|
||||
void AMMod::webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const AMModSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
auto *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
|
||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
|
||||
@ -632,8 +671,8 @@ void AMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const
|
||||
m_networkRequest.setUrl(QUrl(channelSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgChannelSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -646,7 +685,7 @@ void AMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const
|
||||
|
||||
void AMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
auto *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
swgChannelSettings->setDirection(1); // single source (Tx)
|
||||
swgChannelSettings->setChannelType(new QString("AMMod"));
|
||||
swgChannelSettings->setAmModSettings(new SWGSDRangel::SWGAMModSettings());
|
||||
@ -654,7 +693,7 @@ void AMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
|
||||
swgAMModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings());
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgAMModSettings->getCwKeyer();
|
||||
m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
|
||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
|
||||
.arg(m_settings.m_reverseAPIAddress)
|
||||
@ -664,8 +703,8 @@ void AMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
m_networkRequest.setUrl(QUrl(channelSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgChannelSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -678,7 +717,7 @@ void AMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
|
||||
void AMMod::sendChannelSettings(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
const AMModSettings& settings,
|
||||
bool force)
|
||||
{
|
||||
@ -688,7 +727,7 @@ void AMMod::sendChannelSettings(
|
||||
|
||||
if (messageQueue)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
auto *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
MainCore::MsgChannelSettings *msg = MainCore::MsgChannelSettings::create(
|
||||
this,
|
||||
@ -702,7 +741,7 @@ void AMMod::sendChannelSettings(
|
||||
}
|
||||
|
||||
void AMMod::webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const AMModSettings& settings,
|
||||
bool force
|
||||
@ -756,28 +795,28 @@ void AMMod::webapiFormatChannelSettings(
|
||||
|
||||
if (force)
|
||||
{
|
||||
const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings();
|
||||
const CWKeyerSettings& cwKeyerSettings = getCWKeyer()->getSettings();
|
||||
swgAMModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings());
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgAMModSettings->getCwKeyer();
|
||||
m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
}
|
||||
|
||||
if (settings.m_channelMarker && (channelSettingsKeys.contains("channelMarker") || force))
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
auto *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
swgAMModSettings->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
|
||||
if (settings.m_rollupState && (channelSettingsKeys.contains("rollupState") || force))
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
auto *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
swgAMModSettings->setRollupState(swgRollupState);
|
||||
}
|
||||
}
|
||||
|
||||
void AMMod::networkManagerFinished(QNetworkReply *reply)
|
||||
void AMMod::networkManagerFinished(QNetworkReply *reply) const
|
||||
{
|
||||
QNetworkReply::NetworkError replyError = reply->error();
|
||||
|
||||
@ -800,25 +839,32 @@ void AMMod::networkManagerFinished(QNetworkReply *reply)
|
||||
|
||||
double AMMod::getMagSq() const
|
||||
{
|
||||
return m_basebandSource->getMagSq();
|
||||
if (m_running) {
|
||||
return m_basebandSource->getMagSq();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CWKeyer *AMMod::getCWKeyer()
|
||||
{
|
||||
return &m_basebandSource->getCWKeyer();
|
||||
}
|
||||
|
||||
void AMMod::setLevelMeter(QObject *levelMeter)
|
||||
{
|
||||
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
return &m_cwKeyer;
|
||||
}
|
||||
|
||||
int AMMod::getAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
if (m_running) {
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AMMod::getFeedbackAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
if (m_running) {
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include "dsp/basebandsamplesource.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
#include "channel/channelapi.h"
|
||||
#include "util/message.h"
|
||||
|
||||
@ -235,7 +236,7 @@ public:
|
||||
uint32_t getNumberOfDeviceStreams() const;
|
||||
double getMagSq() const;
|
||||
CWKeyer *getCWKeyer();
|
||||
void setLevelMeter(QObject *levelMeter);
|
||||
void setLevelMeter(QObject *levelMeter) { m_levelMeter = levelMeter; }
|
||||
int getAudioSampleRate() const;
|
||||
int getFeedbackAudioSampleRate() const;
|
||||
|
||||
@ -250,6 +251,7 @@ private:
|
||||
|
||||
DeviceAPI* m_deviceAPI;
|
||||
QThread *m_thread;
|
||||
bool m_running = false;
|
||||
AMModBaseband* m_basebandSource;
|
||||
AMModSettings m_settings;
|
||||
|
||||
@ -258,36 +260,38 @@ private:
|
||||
|
||||
std::ifstream m_ifstream;
|
||||
QString m_fileName;
|
||||
quint64 m_fileSize; //!< raw file size (bytes)
|
||||
quint32 m_recordLength; //!< record length in seconds computed from file size
|
||||
int m_sampleRate;
|
||||
quint64 m_fileSize = 0; //!< raw file size (bytes)
|
||||
quint32 m_recordLength = 0; //!< record length in seconds computed from file size
|
||||
int m_sampleRate = 48000;
|
||||
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
CWKeyer m_cwKeyer;
|
||||
QObject *m_levelMeter = nullptr;
|
||||
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
void applySettings(const AMModSettings& settings, bool force = false);
|
||||
void sendSampleRateToDemodAnalyzer();
|
||||
void sendSampleRateToDemodAnalyzer() const;
|
||||
void openFileStream();
|
||||
void seekFileStream(int seekPercentage);
|
||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
|
||||
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AMModSettings& settings, bool force);
|
||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) const;
|
||||
void webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const AMModSettings& settings, bool force);
|
||||
void webapiReverseSendCWSettings(const CWKeyerSettings& settings);
|
||||
void sendChannelSettings(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
const AMModSettings& settings,
|
||||
bool force
|
||||
);
|
||||
void webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const AMModSettings& settings,
|
||||
bool force
|
||||
);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void networkManagerFinished(QNetworkReply *reply) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "dsp/upchannelizer.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
|
||||
#include "ammodbaseband.h"
|
||||
|
||||
@ -171,8 +172,8 @@ bool AMModBaseband::handleMessage(const Message& cmd)
|
||||
qDebug() << "AMModBaseband::handleMessage: MsgConfigureCWKeyer";
|
||||
const CWKeyer::MsgConfigureCWKeyer& cfg = (CWKeyer::MsgConfigureCWKeyer&) cmd;
|
||||
CWKeyer::MsgConfigureCWKeyer *notif = new CWKeyer::MsgConfigureCWKeyer(cfg);
|
||||
CWKeyer& cwKeyer = m_source.getCWKeyer();
|
||||
cwKeyer.getInputMessageQueue()->push(notif);
|
||||
CWKeyer *cwKeyer = m_source.getCWKeyer();
|
||||
cwKeyer->getInputMessageQueue()->push(notif);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
void reset();
|
||||
void pull(const SampleVector::iterator& begin, unsigned int nbSamples);
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
CWKeyer& getCWKeyer() { return m_source.getCWKeyer(); }
|
||||
void setCWKeyer(CWKeyer *cwKeyer) { m_source.setCWKeyer(cwKeyer); }
|
||||
double getMagSq() const { return m_source.getMagSq(); }
|
||||
int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
|
@ -45,7 +45,7 @@
|
||||
|
||||
AMModGUI* AMModGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx)
|
||||
{
|
||||
AMModGUI* gui = new AMModGUI(pluginAPI, deviceUISet, channelTx);
|
||||
auto* gui = new AMModGUI(pluginAPI, deviceUISet, channelTx);
|
||||
return gui;
|
||||
}
|
||||
|
||||
@ -82,21 +82,23 @@ bool AMModGUI::handleMessage(const Message& message)
|
||||
{
|
||||
if (AMMod::MsgReportFileSourceStreamData::match(message))
|
||||
{
|
||||
m_recordSampleRate = ((AMMod::MsgReportFileSourceStreamData&)message).getSampleRate();
|
||||
m_recordLength = ((AMMod::MsgReportFileSourceStreamData&)message).getRecordLength();
|
||||
auto& cmd = (const AMMod::MsgReportFileSourceStreamData&) message;
|
||||
m_recordSampleRate = cmd.getSampleRate();
|
||||
m_recordLength = cmd.getRecordLength();
|
||||
m_samplesCount = 0;
|
||||
updateWithStreamData();
|
||||
return true;
|
||||
}
|
||||
else if (AMMod::MsgReportFileSourceStreamTiming::match(message))
|
||||
{
|
||||
m_samplesCount = ((AMMod::MsgReportFileSourceStreamTiming&)message).getSamplesCount();
|
||||
auto& cmd = (const AMMod::MsgReportFileSourceStreamTiming&) message;
|
||||
m_samplesCount = (int) cmd.getSamplesCount();
|
||||
updateWithStreamTime();
|
||||
return true;
|
||||
}
|
||||
else if (AMMod::MsgConfigureAMMod::match(message))
|
||||
{
|
||||
const AMMod::MsgConfigureAMMod& cfg = (AMMod::MsgConfigureAMMod&) message;
|
||||
auto& cfg = (const AMMod::MsgConfigureAMMod&) message;
|
||||
m_settings = cfg.getSettings();
|
||||
blockApplySettings(true);
|
||||
m_channelMarker.updateSettings(static_cast<const ChannelMarker*>(m_settings.m_channelMarker));
|
||||
@ -106,14 +108,14 @@ bool AMModGUI::handleMessage(const Message& message)
|
||||
}
|
||||
else if (CWKeyer::MsgConfigureCWKeyer::match(message))
|
||||
{
|
||||
const CWKeyer::MsgConfigureCWKeyer& cfg = (CWKeyer::MsgConfigureCWKeyer&) message;
|
||||
auto& cfg = (const CWKeyer::MsgConfigureCWKeyer&) message;
|
||||
ui->cwKeyerGUI->setSettings(cfg.getSettings());
|
||||
ui->cwKeyerGUI->displaySettings();
|
||||
return true;
|
||||
}
|
||||
else if (DSPSignalNotification::match(message))
|
||||
{
|
||||
const DSPSignalNotification& notif = (const DSPSignalNotification&) message;
|
||||
auto& notif = (const DSPSignalNotification&) message;
|
||||
m_deviceCenterFrequency = notif.getCenterFrequency();
|
||||
m_basebandSampleRate = notif.getSampleRate();
|
||||
ui->deltaFrequency->setValueRange(false, 7, -m_basebandSampleRate/2, m_basebandSampleRate/2);
|
||||
@ -138,7 +140,7 @@ void AMModGUI::handleSourceMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
while ((message = getInputMessageQueue()->pop()) != nullptr)
|
||||
{
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
@ -149,7 +151,7 @@ void AMModGUI::handleSourceMessages()
|
||||
|
||||
void AMModGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_channelMarker.setCenterFrequency((int) value);
|
||||
m_settings.m_inputFrequencyOffset = value;
|
||||
updateAbsoluteCenterFrequency();
|
||||
applySettings();
|
||||
@ -158,7 +160,7 @@ void AMModGUI::on_deltaFrequency_changed(qint64 value)
|
||||
void AMModGUI::on_rfBW_valueChanged(int value)
|
||||
{
|
||||
ui->rfBWText->setText(QString("%1 kHz").arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_rfBandwidth = value * 100.0;
|
||||
m_settings.m_rfBandwidth = (float) value * 100.0f;
|
||||
m_channelMarker.setBandwidth(value * 100);
|
||||
applySettings();
|
||||
}
|
||||
@ -166,21 +168,21 @@ void AMModGUI::on_rfBW_valueChanged(int value)
|
||||
void AMModGUI::on_modPercent_valueChanged(int value)
|
||||
{
|
||||
ui->modPercentText->setText(QString("%1").arg(value));
|
||||
m_settings.m_modFactor = value / 100.0;
|
||||
m_settings.m_modFactor = (float) value / 100.0f;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void AMModGUI::on_volume_valueChanged(int value)
|
||||
{
|
||||
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_volumeFactor = value / 10.0;
|
||||
m_settings.m_volumeFactor = (float) value / 10.0f;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void AMModGUI::on_toneFrequency_valueChanged(int value)
|
||||
{
|
||||
ui->toneFrequencyText->setText(QString("%1k").arg(value / 100.0, 0, 'f', 2));
|
||||
m_settings.m_toneFrequency = value * 10.0;
|
||||
m_settings.m_toneFrequency = (float) value * 10.0f;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -244,7 +246,7 @@ void AMModGUI::on_feedbackEnable_toggled(bool checked)
|
||||
void AMModGUI::on_feedbackVolume_valueChanged(int value)
|
||||
{
|
||||
ui->feedbackVolumeText->setText(QString("%1").arg(value / 100.0, 0, 'f', 2));
|
||||
m_settings.m_feedbackVolumeFactor = value / 100.0;
|
||||
m_settings.m_feedbackVolumeFactor = (float) value / 100.0f;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -265,7 +267,7 @@ void AMModGUI::on_showFileDialog_clicked(bool checked)
|
||||
{
|
||||
(void) checked;
|
||||
QString fileName = QFileDialog::getOpenFileName(this,
|
||||
tr("Open raw audio file"), ".", tr("Raw audio Files (*.raw)"), 0, QFileDialog::DontUseNativeDialog);
|
||||
tr("Open raw audio file"), ".", tr("Raw audio Files (*.raw)"), nullptr, QFileDialog::DontUseNativeDialog);
|
||||
|
||||
if (fileName != "")
|
||||
{
|
||||
@ -283,7 +285,7 @@ void AMModGUI::configureFileName()
|
||||
m_amMod->getInputMessageQueue()->push(message);
|
||||
}
|
||||
|
||||
void AMModGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
void AMModGUI::onWidgetRolled(const QWidget* widget, bool rollDown)
|
||||
{
|
||||
(void) widget;
|
||||
(void) rollDown;
|
||||
@ -367,15 +369,15 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampl
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
|
||||
m_amMod = (AMMod*) channelTx;
|
||||
m_amMod->setMessageQueueToGUI(getInputMessageQueue());
|
||||
m_amMod->setMessageQueueToGUI(AMModGUI::getInputMessageQueue());
|
||||
|
||||
connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
||||
|
||||
CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->mic);
|
||||
connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect(const QPoint &)));
|
||||
m_audioMuteRightClickEnabler = new CRightClickEnabler(ui->mic);
|
||||
connect(m_audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect(const QPoint &)));
|
||||
|
||||
CRightClickEnabler *feedbackRightClickEnabler = new CRightClickEnabler(ui->feedbackEnable);
|
||||
connect(feedbackRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioFeedbackSelect(const QPoint &)));
|
||||
m_feedbackRightClickEnabler = new CRightClickEnabler(ui->feedbackEnable);
|
||||
connect(m_feedbackRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioFeedbackSelect(const QPoint &)));
|
||||
|
||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
||||
@ -406,7 +408,7 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampl
|
||||
|
||||
ui->cwKeyerGUI->setCWKeyer(m_amMod->getCWKeyer());
|
||||
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
connect(AMModGUI::getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
m_amMod->setLevelMeter(ui->volumeMeter);
|
||||
|
||||
displaySettings();
|
||||
@ -419,6 +421,8 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampl
|
||||
AMModGUI::~AMModGUI()
|
||||
{
|
||||
delete ui;
|
||||
delete m_audioMuteRightClickEnabler;
|
||||
delete m_feedbackRightClickEnabler;
|
||||
}
|
||||
|
||||
void AMModGUI::blockApplySettings(bool block)
|
||||
@ -439,9 +443,9 @@ void AMModGUI::applySettings(bool force)
|
||||
void AMModGUI::displaySettings()
|
||||
{
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setCenterFrequency((int) m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setTitle(m_settings.m_title);
|
||||
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
|
||||
m_channelMarker.setBandwidth((int) m_settings.m_rfBandwidth);
|
||||
m_channelMarker.blockSignals(false);
|
||||
m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
|
||||
|
||||
@ -453,17 +457,17 @@ void AMModGUI::displaySettings()
|
||||
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
|
||||
ui->rfBW->setValue(roundf(m_settings.m_rfBandwidth / 100.0));
|
||||
ui->rfBW->setValue((int) roundf(m_settings.m_rfBandwidth / 100.f));
|
||||
ui->rfBWText->setText(QString("%1 kHz").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1));
|
||||
|
||||
int modPercent = roundf(m_settings.m_modFactor * 100.0);
|
||||
auto modPercent = (int) roundf(m_settings.m_modFactor * 100.0f);
|
||||
ui->modPercent->setValue(modPercent);
|
||||
ui->modPercentText->setText(QString("%1").arg(modPercent));
|
||||
|
||||
ui->toneFrequency->setValue(roundf(m_settings.m_toneFrequency / 10.0));
|
||||
ui->toneFrequency->setValue((int) roundf(m_settings.m_toneFrequency / 10.0f));
|
||||
ui->toneFrequencyText->setText(QString("%1k").arg(m_settings.m_toneFrequency / 1000.0, 0, 'f', 2));
|
||||
|
||||
ui->volume->setValue(roundf(m_settings.m_volumeFactor * 10.0));
|
||||
ui->volume->setValue((int) roundf(m_settings.m_volumeFactor * 10.0f));
|
||||
ui->volumeText->setText(QString("%1").arg(m_settings.m_volumeFactor, 0, 'f', 1));
|
||||
|
||||
ui->channelMute->setChecked(m_settings.m_channelMute);
|
||||
@ -480,7 +484,7 @@ void AMModGUI::displaySettings()
|
||||
ui->morseKeyer->setChecked(m_settings.m_modAFInput == AMModSettings::AMModInputAF::AMModInputCWTone);
|
||||
|
||||
ui->feedbackEnable->setChecked(m_settings.m_feedbackAudioEnable);
|
||||
ui->feedbackVolume->setValue(roundf(m_settings.m_feedbackVolumeFactor * 100.0));
|
||||
ui->feedbackVolume->setValue((int) roundf(m_settings.m_feedbackVolumeFactor * 100.0f));
|
||||
ui->feedbackVolumeText->setText(QString("%1").arg(m_settings.m_feedbackVolumeFactor, 0, 'f', 2));
|
||||
|
||||
updateIndexLabel();
|
||||
@ -605,7 +609,7 @@ void AMModGUI::updateWithStreamTime()
|
||||
}
|
||||
}
|
||||
|
||||
void AMModGUI::makeUIConnections()
|
||||
void AMModGUI::makeUIConnections() const
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &AMModGUI::on_deltaFrequency_changed);
|
||||
QObject::connect(ui->rfBW, &QSlider::valueChanged, this, &AMModGUI::on_rfBW_valueChanged);
|
||||
|
@ -33,6 +33,7 @@ class DeviceUISet;
|
||||
|
||||
class AMMod;
|
||||
class BasebandSampleSource;
|
||||
class CRightClickEnabler;
|
||||
|
||||
namespace Ui {
|
||||
class AMModGUI;
|
||||
@ -45,21 +46,21 @@ public:
|
||||
static AMModGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx);
|
||||
virtual void destroy();
|
||||
|
||||
void resetToDefaults();
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; };
|
||||
virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; };
|
||||
virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; };
|
||||
virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; };
|
||||
virtual QString getTitle() const { return m_settings.m_title; };
|
||||
virtual QColor getTitleColor() const { return m_settings.m_rgbColor; };
|
||||
virtual void zetHidden(bool hidden) { m_settings.m_hidden = hidden; }
|
||||
virtual bool getHidden() const { return m_settings.m_hidden; }
|
||||
virtual ChannelMarker& getChannelMarker() { return m_channelMarker; }
|
||||
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
|
||||
virtual void setStreamIndex(int streamIndex) { m_settings.m_streamIndex = streamIndex; }
|
||||
void resetToDefaults() final;
|
||||
QByteArray serialize() const final;
|
||||
bool deserialize(const QByteArray& data) final;
|
||||
MessageQueue *getInputMessageQueue() final { return &m_inputMessageQueue; }
|
||||
void setWorkspaceIndex(int index) final { m_settings.m_workspaceIndex = index; };
|
||||
int getWorkspaceIndex() const final { return m_settings.m_workspaceIndex; };
|
||||
void setGeometryBytes(const QByteArray& blob) final { m_settings.m_geometryBytes = blob; };
|
||||
QByteArray getGeometryBytes() const final { return m_settings.m_geometryBytes; };
|
||||
QString getTitle() const final { return m_settings.m_title; };
|
||||
QColor getTitleColor() const final { return m_settings.m_rgbColor; };
|
||||
void zetHidden(bool hidden) final { m_settings.m_hidden = hidden; }
|
||||
bool getHidden() const final { return m_settings.m_hidden; }
|
||||
ChannelMarker& getChannelMarker() final { return m_channelMarker; }
|
||||
int getStreamIndex() const final { return m_settings.m_streamIndex; }
|
||||
void setStreamIndex(int streamIndex) final { m_settings.m_streamIndex = streamIndex; }
|
||||
|
||||
public slots:
|
||||
void channelMarkerChangedByCursor();
|
||||
@ -75,6 +76,9 @@ private:
|
||||
int m_basebandSampleRate;
|
||||
bool m_doApplySettings;
|
||||
|
||||
CRightClickEnabler *m_audioMuteRightClickEnabler;
|
||||
CRightClickEnabler *m_feedbackRightClickEnabler;
|
||||
|
||||
AMMod* m_amMod;
|
||||
MovingAverageUtil<double, double, 20> m_channelPowerDbAvg;
|
||||
|
||||
@ -88,8 +92,8 @@ private:
|
||||
bool m_enableNavTime;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
|
||||
explicit AMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget* parent = 0);
|
||||
virtual ~AMModGUI();
|
||||
explicit AMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget* parent = nullptr);
|
||||
~AMModGUI() final;
|
||||
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
@ -97,11 +101,11 @@ private:
|
||||
void updateWithStreamData();
|
||||
void updateWithStreamTime();
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
void makeUIConnections() const;
|
||||
void updateAbsoluteCenterFrequency();
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(EnterEventType*);
|
||||
void leaveEvent(QEvent*) final;
|
||||
void enterEvent(EnterEventType*) final;
|
||||
|
||||
private slots:
|
||||
void handleSourceMessages();
|
||||
@ -124,7 +128,7 @@ private slots:
|
||||
void on_feedbackEnable_toggled(bool checked);
|
||||
void on_feedbackVolume_valueChanged(int value);
|
||||
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onWidgetRolled(const QWidget* widget, bool rollDown);
|
||||
void onMenuDialogCalled(const QPoint& p);
|
||||
|
||||
void configureFileName();
|
||||
|
@ -41,7 +41,7 @@ const PluginDescriptor AMModPlugin::m_pluginDescriptor = {
|
||||
|
||||
AMModPlugin::AMModPlugin(QObject* parent) :
|
||||
QObject(parent),
|
||||
m_pluginAPI(0)
|
||||
m_pluginAPI(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ void AMModPlugin::createTxChannel(DeviceAPI *deviceAPI, BasebandSampleSource **b
|
||||
{
|
||||
if (bs || cs)
|
||||
{
|
||||
AMMod *instance = new AMMod(deviceAPI);
|
||||
auto *instance = new AMMod(deviceAPI);
|
||||
|
||||
if (bs) {
|
||||
*bs = instance;
|
||||
|
@ -27,20 +27,20 @@
|
||||
class DeviceUISet;
|
||||
class BasebandSampleSource;
|
||||
|
||||
class AMModPlugin : public QObject, PluginInterface {
|
||||
class AMModPlugin : public QObject, public PluginInterface {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(PluginInterface)
|
||||
Q_PLUGIN_METADATA(IID "sdrangel.channeltx.ammod")
|
||||
|
||||
public:
|
||||
explicit AMModPlugin(QObject* parent = 0);
|
||||
explicit AMModPlugin(QObject* parent = nullptr);
|
||||
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
const PluginDescriptor& getPluginDescriptor() const final;
|
||||
void initPlugin(PluginAPI* pluginAPI) final;
|
||||
|
||||
virtual void createTxChannel(DeviceAPI *deviceAPI, BasebandSampleSource **bs, ChannelAPI **cs) const;
|
||||
virtual ChannelGUI* createTxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSource *txChannel) const;
|
||||
virtual ChannelWebAPIAdapter* createChannelWebAPIAdapter() const;
|
||||
void createTxChannel(DeviceAPI *deviceAPI, BasebandSampleSource **bs, ChannelAPI **cs) const final;
|
||||
ChannelGUI* createTxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSource *txChannel) const final;
|
||||
ChannelWebAPIAdapter* createChannelWebAPIAdapter() const final;
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "dsp/datafifo.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "maincore.h"
|
||||
|
||||
@ -27,15 +28,8 @@
|
||||
const int AMModSource::m_levelNbSamples = 480; // every 10ms
|
||||
|
||||
AMModSource::AMModSource() :
|
||||
m_channelSampleRate(48000),
|
||||
m_channelFrequencyOffset(0),
|
||||
m_audioSampleRate(48000),
|
||||
m_audioFifo(12000),
|
||||
m_feedbackAudioFifo(48000),
|
||||
m_levelCalcCount(0),
|
||||
m_peakLevel(0.0f),
|
||||
m_levelSum(0.0f),
|
||||
m_ifstream(nullptr)
|
||||
m_feedbackAudioFifo(48000)
|
||||
{
|
||||
m_audioFifo.setLabel("AMModSource.m_audioFifo");
|
||||
m_feedbackAudioFifo.setLabel("AMModSource.m_feedbackAudioFifo");
|
||||
@ -55,9 +49,7 @@ AMModSource::AMModSource() :
|
||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||
}
|
||||
|
||||
AMModSource::~AMModSource()
|
||||
{
|
||||
}
|
||||
AMModSource::~AMModSource() = default;
|
||||
|
||||
void AMModSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
|
||||
{
|
||||
@ -109,7 +101,7 @@ void AMModSource::pullOne(Sample& sample)
|
||||
sample.m_real = (FixReal) ci.real();
|
||||
sample.m_imag = (FixReal) ci.imag();
|
||||
|
||||
m_demodBuffer[m_demodBufferFill] = ci.real() + ci.imag();
|
||||
m_demodBuffer[m_demodBufferFill] = (qint16) (ci.real() + ci.imag());
|
||||
++m_demodBufferFill;
|
||||
|
||||
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||
@ -117,13 +109,11 @@ void AMModSource::pullOne(Sample& sample)
|
||||
QList<ObjectPipe*> dataPipes;
|
||||
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
|
||||
|
||||
if (dataPipes.size() > 0)
|
||||
if (!dataPipes.empty())
|
||||
{
|
||||
QList<ObjectPipe*>::iterator it = dataPipes.begin();
|
||||
|
||||
for (; it != dataPipes.end(); ++it)
|
||||
for (auto& dataPipe : dataPipes)
|
||||
{
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>(dataPipe->m_element);
|
||||
|
||||
if (fifo) {
|
||||
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
|
||||
@ -137,7 +127,7 @@ void AMModSource::pullOne(Sample& sample)
|
||||
|
||||
void AMModSource::prefetch(unsigned int nbSamples)
|
||||
{
|
||||
unsigned int nbSamplesAudio = nbSamples * ((Real) m_audioSampleRate / (Real) m_channelSampleRate);
|
||||
auto nbSamplesAudio = (nbSamples * (unsigned int) ((Real) m_audioSampleRate / (Real) m_channelSampleRate));
|
||||
pullAudio(nbSamplesAudio);
|
||||
}
|
||||
|
||||
@ -161,7 +151,7 @@ void AMModSource::pullAudio(unsigned int nbSamples)
|
||||
|
||||
void AMModSource::modulateSample()
|
||||
{
|
||||
Real t;
|
||||
Real t = 0.0f;
|
||||
|
||||
pullAF(t);
|
||||
|
||||
@ -184,17 +174,12 @@ void AMModSource::pullAF(Real& sample)
|
||||
sample = m_toneNco.next();
|
||||
break;
|
||||
case AMModSettings::AMModInputFile:
|
||||
// sox f4exb_call.wav --encoding float --endian little f4exb_call.raw
|
||||
// ffplay -f f32le -ar 48k -ac 1 f4exb_call.raw
|
||||
if (m_ifstream && m_ifstream->is_open())
|
||||
{
|
||||
if (m_ifstream->eof())
|
||||
if ((m_ifstream->eof()) && (m_settings.m_playLoop))
|
||||
{
|
||||
if (m_settings.m_playLoop)
|
||||
{
|
||||
m_ifstream->clear();
|
||||
m_ifstream->seekg(0, std::ios::beg);
|
||||
}
|
||||
m_ifstream->clear();
|
||||
m_ifstream->seekg(0, std::ios::beg);
|
||||
}
|
||||
|
||||
if (m_ifstream->eof())
|
||||
@ -218,14 +203,18 @@ void AMModSource::pullAF(Real& sample)
|
||||
case AMModSettings::AMModInputCWTone:
|
||||
Real fadeFactor;
|
||||
|
||||
if (m_cwKeyer.getSample())
|
||||
if (!m_cwKeyer) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_cwKeyer->getSample())
|
||||
{
|
||||
m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor);
|
||||
m_cwKeyer->getCWSmoother().getFadeSample(true, fadeFactor);
|
||||
sample = m_toneNco.next() * fadeFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor))
|
||||
if (m_cwKeyer->getCWSmoother().getFadeSample(false, fadeFactor))
|
||||
{
|
||||
sample = m_toneNco.next() * fadeFactor;
|
||||
}
|
||||
@ -236,7 +225,6 @@ void AMModSource::pullAF(Real& sample)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AMModSettings::AMModInputNone:
|
||||
default:
|
||||
sample = 0.0f;
|
||||
break;
|
||||
@ -266,10 +254,10 @@ void AMModSource::pushFeedback(Real sample)
|
||||
}
|
||||
}
|
||||
|
||||
void AMModSource::processOneSample(Complex& ci)
|
||||
void AMModSource::processOneSample(const Complex& ci)
|
||||
{
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = (qint16) ci.real();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = (qint16) ci.imag();
|
||||
++m_feedbackAudioBufferFill;
|
||||
|
||||
if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size())
|
||||
@ -287,7 +275,7 @@ void AMModSource::processOneSample(Complex& ci)
|
||||
}
|
||||
}
|
||||
|
||||
void AMModSource::calculateLevel(Real& sample)
|
||||
void AMModSource::calculateLevel(const Real& sample)
|
||||
{
|
||||
if (m_levelCalcCount < m_levelNbSamples)
|
||||
{
|
||||
@ -319,14 +307,18 @@ void AMModSource::applyAudioSampleRate(int sampleRate)
|
||||
m_interpolatorConsumed = false;
|
||||
m_interpolatorDistance = (Real) sampleRate / (Real) m_channelSampleRate;
|
||||
m_interpolator.create(48, sampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
|
||||
m_toneNco.setFreq(m_settings.m_toneFrequency, sampleRate);
|
||||
m_cwKeyer.setSampleRate(sampleRate);
|
||||
m_cwKeyer.reset();
|
||||
m_toneNco.setFreq(m_settings.m_toneFrequency, (float) sampleRate);
|
||||
|
||||
if (m_cwKeyer)
|
||||
{
|
||||
m_cwKeyer->setSampleRate(sampleRate);
|
||||
m_cwKeyer->reset();
|
||||
}
|
||||
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
|
||||
|
||||
if (pipes.size() > 0)
|
||||
if (!pipes.empty())
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
@ -352,7 +344,7 @@ void AMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||
|
||||
m_feedbackInterpolatorDistanceRemain = 0;
|
||||
m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate;
|
||||
Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f;
|
||||
Real cutoff = ((float) std::min(sampleRate, m_audioSampleRate)) / 2.2f;
|
||||
m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0);
|
||||
m_feedbackAudioSampleRate = sampleRate;
|
||||
}
|
||||
@ -365,9 +357,8 @@ void AMModSource::applySettings(const AMModSettings& settings, bool force)
|
||||
applyAudioSampleRate(m_audioSampleRate);
|
||||
}
|
||||
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force)
|
||||
{
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, m_audioSampleRate);
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force) {
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, (float) m_audioSampleRate);
|
||||
}
|
||||
|
||||
if ((settings.m_modAFInput != m_settings.m_modAFInput) || force)
|
||||
@ -391,7 +382,7 @@ void AMModSource::applyChannelSettings(int channelSampleRate, int channelFrequen
|
||||
if ((channelFrequencyOffset != m_channelFrequencyOffset)
|
||||
|| (channelSampleRate != m_channelSampleRate) || force)
|
||||
{
|
||||
m_carrierNco.setFreq(channelFrequencyOffset, channelSampleRate);
|
||||
m_carrierNco.setFreq((float) channelFrequencyOffset, (float) channelSampleRate);
|
||||
}
|
||||
|
||||
if ((channelSampleRate != m_channelSampleRate) || force)
|
||||
@ -408,7 +399,6 @@ void AMModSource::applyChannelSettings(int channelSampleRate, int channelFrequen
|
||||
|
||||
void AMModSource::handleAudio()
|
||||
{
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
unsigned int nbRead;
|
||||
|
||||
while ((nbRead = m_audioFifo.read(reinterpret_cast<quint8*>(&m_audioReadBuffer[m_audioReadBufferFill]), 4096)) != 0)
|
||||
|
@ -31,23 +31,23 @@
|
||||
#include "dsp/ncof.h"
|
||||
#include "dsp/interpolator.h"
|
||||
#include "util/movingaverage.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
#include "audio/audiofifo.h"
|
||||
|
||||
#include "ammodsettings.h"
|
||||
|
||||
class ChannelAPI;
|
||||
class CWKeyer;
|
||||
|
||||
class AMModSource : public QObject, public ChannelSampleSource
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AMModSource();
|
||||
virtual ~AMModSource();
|
||||
~AMModSource() final;
|
||||
|
||||
virtual void pull(SampleVector::iterator begin, unsigned int nbSamples);
|
||||
virtual void pullOne(Sample& sample);
|
||||
virtual void prefetch(unsigned int nbSamples);
|
||||
void pull(SampleVector::iterator begin, unsigned int nbSamples) final;
|
||||
void pullOne(Sample& sample) final;
|
||||
void prefetch(unsigned int nbSamples) final;
|
||||
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_ifstream = ifstream; }
|
||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||
@ -57,7 +57,8 @@ public:
|
||||
void applyFeedbackAudioSampleRate(int sampleRate);
|
||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||
void setCWKeyer(CWKeyer *cwKeyer) { m_cwKeyer = cwKeyer; }
|
||||
CWKeyer* getCWKeyer() { return m_cwKeyer; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||
{
|
||||
@ -69,8 +70,8 @@ public:
|
||||
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
|
||||
|
||||
private:
|
||||
int m_channelSampleRate;
|
||||
int m_channelFrequencyOffset;
|
||||
int m_channelSampleRate = 48000;
|
||||
int m_channelFrequencyOffset = 0;
|
||||
AMModSettings m_settings;
|
||||
ChannelAPI *m_channel;
|
||||
|
||||
@ -90,7 +91,7 @@ private:
|
||||
double m_magsq;
|
||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||
|
||||
int m_audioSampleRate;
|
||||
int m_audioSampleRate = 48000;
|
||||
AudioVector m_audioBuffer;
|
||||
unsigned int m_audioBufferFill;
|
||||
AudioVector m_audioReadBuffer;
|
||||
@ -105,24 +106,24 @@ private:
|
||||
int m_demodBufferFill;
|
||||
bool m_demodBufferEnabled;
|
||||
|
||||
quint32 m_levelCalcCount;
|
||||
quint32 m_levelCalcCount = 0;
|
||||
qreal m_rmsLevel;
|
||||
qreal m_peakLevelOut;
|
||||
Real m_peakLevel;
|
||||
Real m_levelSum;
|
||||
Real m_peakLevel = 0.0f;
|
||||
Real m_levelSum = 0.0f;
|
||||
|
||||
std::ifstream *m_ifstream;
|
||||
CWKeyer m_cwKeyer;
|
||||
std::ifstream *m_ifstream = nullptr;
|
||||
CWKeyer *m_cwKeyer = nullptr;
|
||||
|
||||
QRecursiveMutex m_mutex;
|
||||
|
||||
static const int m_levelNbSamples;
|
||||
|
||||
void processOneSample(Complex& ci);
|
||||
void processOneSample(const Complex& ci);
|
||||
void pullAF(Real& sample);
|
||||
void pullAudio(unsigned int nbSamples);
|
||||
void pushFeedback(Real sample);
|
||||
void calculateLevel(Real& sample);
|
||||
void calculateLevel(const Real& sample);
|
||||
void modulateSample();
|
||||
|
||||
private slots:
|
||||
|
@ -56,19 +56,10 @@ const char* const NFMMod::m_channelId = "NFMMod";
|
||||
|
||||
NFMMod::NFMMod(DeviceAPI *deviceAPI) :
|
||||
ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_fileSize(0),
|
||||
m_recordLength(0),
|
||||
m_sampleRate(48000)
|
||||
m_deviceAPI(deviceAPI)
|
||||
{
|
||||
setObjectName(m_channelId);
|
||||
|
||||
m_thread = new QThread(this);
|
||||
m_basebandSource = new NFMModBaseband();
|
||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||
m_basebandSource->setChannel(this);
|
||||
m_basebandSource->moveToThread(m_thread);
|
||||
|
||||
applySettings(m_settings, true);
|
||||
|
||||
m_deviceAPI->addChannelSource(this);
|
||||
@ -94,8 +85,8 @@ NFMMod::~NFMMod()
|
||||
delete m_networkManager;
|
||||
m_deviceAPI->removeChannelSourceAPI(this);
|
||||
m_deviceAPI->removeChannelSource(this);
|
||||
delete m_basebandSource;
|
||||
delete m_thread;
|
||||
|
||||
NFMMod::stop();
|
||||
}
|
||||
|
||||
void NFMMod::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
@ -112,21 +103,61 @@ void NFMMod::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
|
||||
void NFMMod::start()
|
||||
{
|
||||
if (m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("NFMMod::start");
|
||||
m_thread = new QThread(this);
|
||||
m_basebandSource = new NFMModBaseband();
|
||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||
m_basebandSource->setChannel(this);
|
||||
m_basebandSource->reset();
|
||||
m_basebandSource->setCWKeyer(&m_cwKeyer);
|
||||
m_basebandSource->moveToThread(m_thread);
|
||||
|
||||
QObject::connect(
|
||||
m_thread,
|
||||
&QThread::finished,
|
||||
m_basebandSource,
|
||||
&QObject::deleteLater
|
||||
);
|
||||
QObject::connect(
|
||||
m_thread,
|
||||
&QThread::finished,
|
||||
m_thread,
|
||||
&QThread::deleteLater
|
||||
);
|
||||
|
||||
m_thread->start();
|
||||
|
||||
if (m_levelMeter) {
|
||||
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), m_levelMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
}
|
||||
|
||||
NFMModBaseband::MsgConfigureNFMModBaseband *msg = NFMModBaseband::MsgConfigureNFMModBaseband::create(m_settings, true);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
void NFMMod::stop()
|
||||
{
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("NFMMod::stop");
|
||||
m_thread->exit();
|
||||
m_running = false;
|
||||
m_thread->quit();
|
||||
m_thread->wait();
|
||||
}
|
||||
|
||||
void NFMMod::pull(SampleVector::iterator& begin, unsigned int nbSamples)
|
||||
{
|
||||
m_basebandSource->pull(begin, nbSamples);
|
||||
if (m_running) {
|
||||
m_basebandSource->pull(begin, nbSamples);
|
||||
}
|
||||
}
|
||||
|
||||
void NFMMod::setCenterFrequency(qint64 frequency)
|
||||
@ -146,7 +177,7 @@ bool NFMMod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if (MsgConfigureNFMMod::match(cmd))
|
||||
{
|
||||
MsgConfigureNFMMod& cfg = (MsgConfigureNFMMod&) cmd;
|
||||
auto& cfg = (const MsgConfigureNFMMod&) cmd;
|
||||
qDebug() << "NFMMod::handleMessage: MsgConfigureNFMMod";
|
||||
|
||||
applySettings(cfg.getSettings(), cfg.getForce());
|
||||
@ -155,7 +186,7 @@ bool NFMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MsgConfigureFileSourceName::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) cmd;
|
||||
auto& conf = (const MsgConfigureFileSourceName&) cmd;
|
||||
m_fileName = conf.getFileName();
|
||||
openFileStream();
|
||||
qDebug() << "NFMMod::handleMessage: MsgConfigureFileSourceName:"
|
||||
@ -164,7 +195,7 @@ bool NFMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MsgConfigureFileSourceSeek::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceSeek& conf = (MsgConfigureFileSourceSeek&) cmd;
|
||||
auto& conf = (const MsgConfigureFileSourceSeek&) cmd;
|
||||
int seekPercentage = conf.getPercentage();
|
||||
seekFileStream(seekPercentage);
|
||||
qDebug() << "NFMMod::handleMessage: MsgConfigureFileSourceSeek:"
|
||||
@ -190,7 +221,7 @@ bool NFMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MsgConfigureFileSourceName::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) cmd;
|
||||
auto& conf = (const MsgConfigureFileSourceName&) cmd;
|
||||
m_fileName = conf.getFileName();
|
||||
openFileStream();
|
||||
qDebug() << "NFMMod::handleMessage: MsgConfigureFileSourceName:"
|
||||
@ -199,7 +230,7 @@ bool NFMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MsgConfigureFileSourceSeek::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceSeek& conf = (MsgConfigureFileSourceSeek&) cmd;
|
||||
auto& conf = (const MsgConfigureFileSourceSeek&) cmd;
|
||||
int seekPercentage = conf.getPercentage();
|
||||
seekFileStream(seekPercentage);
|
||||
qDebug() << "NFMMod::handleMessage: MsgConfigureFileSourceSeek:"
|
||||
@ -225,7 +256,7 @@ bool NFMMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (CWKeyer::MsgConfigureCWKeyer::match(cmd))
|
||||
{
|
||||
const CWKeyer::MsgConfigureCWKeyer& cfg = (CWKeyer::MsgConfigureCWKeyer&) cmd;
|
||||
auto& cfg = (const CWKeyer::MsgConfigureCWKeyer&) cmd;
|
||||
|
||||
if (m_settings.m_useReverseAPI) {
|
||||
webapiReverseSendCWSettings(cfg.getSettings());
|
||||
@ -236,13 +267,16 @@ bool NFMMod::handleMessage(const Message& cmd)
|
||||
else if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
// Forward to the source
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy
|
||||
qDebug() << "NFMMod::handleMessage: DSPSignalNotification";
|
||||
m_basebandSource->getInputMessageQueue()->push(rep);
|
||||
// Forward to GUI if any
|
||||
if (getMessageQueueToGUI()) {
|
||||
getMessageQueueToGUI()->push(new DSPSignalNotification(notif));
|
||||
if (m_running)
|
||||
{
|
||||
auto& notif = (const DSPSignalNotification&) cmd;
|
||||
auto* rep = new DSPSignalNotification(notif); // make a copy
|
||||
qDebug() << "NFMMod::handleMessage: DSPSignalNotification";
|
||||
m_basebandSource->getInputMessageQueue()->push(rep);
|
||||
// Forward to GUI if any
|
||||
if (getMessageQueueToGUI()) {
|
||||
getMessageQueueToGUI()->push(new DSPSignalNotification(notif));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -271,7 +305,7 @@ void NFMMod::openFileStream()
|
||||
m_ifstream.seekg(0,std::ios_base::beg);
|
||||
|
||||
m_sampleRate = 48000; // fixed rate
|
||||
m_recordLength = m_fileSize / (sizeof(Real) * m_sampleRate);
|
||||
m_recordLength = (quint32) (m_fileSize / (sizeof(Real) * m_sampleRate));
|
||||
|
||||
qDebug() << "NFMMod::openFileStream: " << m_fileName.toStdString().c_str()
|
||||
<< " fileSize: " << m_fileSize << "bytes"
|
||||
@ -386,8 +420,11 @@ void NFMMod::applySettings(const NFMModSettings& settings, bool force)
|
||||
reverseAPIKeys.append("streamIndex");
|
||||
}
|
||||
|
||||
NFMModBaseband::MsgConfigureNFMModBaseband *msg = NFMModBaseband::MsgConfigureNFMModBaseband::create(settings, force);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
if (m_running)
|
||||
{
|
||||
NFMModBaseband::MsgConfigureNFMModBaseband *msg = NFMModBaseband::MsgConfigureNFMModBaseband::create(settings, force);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
}
|
||||
|
||||
if (settings.m_useReverseAPI)
|
||||
{
|
||||
@ -402,7 +439,7 @@ void NFMMod::applySettings(const NFMModSettings& settings, bool force)
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "settings", pipes);
|
||||
|
||||
if (pipes.size() > 0) {
|
||||
if (!pipes.empty()) {
|
||||
sendChannelSettings(pipes, reverseAPIKeys, settings, force);
|
||||
}
|
||||
|
||||
@ -430,12 +467,12 @@ bool NFMMod::deserialize(const QByteArray& data)
|
||||
return success;
|
||||
}
|
||||
|
||||
void NFMMod::sendSampleRateToDemodAnalyzer()
|
||||
void NFMMod::sendSampleRateToDemodAnalyzer() const
|
||||
{
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "reportdemod", pipes);
|
||||
|
||||
if (pipes.size() > 0)
|
||||
if (!pipes.empty())
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
@ -459,7 +496,7 @@ int NFMMod::webapiSettingsGet(
|
||||
webapiFormatChannelSettings(response, m_settings);
|
||||
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getNfmModSettings()->getCwKeyer();
|
||||
const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings();
|
||||
const CWKeyerSettings& cwKeyerSettings = getCWKeyer()->getSettings();
|
||||
CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
|
||||
return 200;
|
||||
@ -487,11 +524,11 @@ int NFMMod::webapiSettingsPutPatch(
|
||||
if (channelSettingsKeys.contains("cwKeyer"))
|
||||
{
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getNfmModSettings()->getCwKeyer();
|
||||
CWKeyerSettings cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings();
|
||||
CWKeyerSettings cwKeyerSettings = getCWKeyer()->getSettings();
|
||||
CWKeyer::webapiSettingsPutPatch(channelSettingsKeys, cwKeyerSettings, apiCwKeyerSettings);
|
||||
|
||||
CWKeyer::MsgConfigureCWKeyer *msgCwKeyer = CWKeyer::MsgConfigureCWKeyer::create(cwKeyerSettings, force);
|
||||
m_basebandSource->getCWKeyer().getInputMessageQueue()->push(msgCwKeyer);
|
||||
getCWKeyer()->getInputMessageQueue()->push(msgCwKeyer);
|
||||
|
||||
if (m_guiMessageQueue) // forward to GUI if any
|
||||
{
|
||||
@ -583,13 +620,13 @@ void NFMMod::webapiUpdateChannelSettings(
|
||||
settings.m_reverseAPIAddress = *response.getNfmModSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getNfmModSettings()->getReverseApiPort();
|
||||
settings.m_reverseAPIPort = (uint16_t) response.getNfmModSettings()->getReverseApiPort();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getNfmModSettings()->getReverseApiDeviceIndex();
|
||||
settings.m_reverseAPIDeviceIndex = (uint16_t) response.getNfmModSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
|
||||
settings.m_reverseAPIChannelIndex = response.getNfmModSettings()->getReverseApiChannelIndex();
|
||||
settings.m_reverseAPIChannelIndex = (uint16_t) response.getNfmModSettings()->getReverseApiChannelIndex();
|
||||
}
|
||||
if (settings.m_channelMarker && channelSettingsKeys.contains("channelMarker")) {
|
||||
settings.m_channelMarker->updateFrom(channelSettingsKeys, response.getNfmModSettings()->getChannelMarker());
|
||||
@ -667,7 +704,7 @@ void NFMMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
auto *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
response.getNfmModSettings()->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
@ -681,23 +718,27 @@ void NFMMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
auto *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
response.getNfmModSettings()->setRollupState(swgRollupState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NFMMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response)
|
||||
void NFMMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) const
|
||||
{
|
||||
response.getNfmModReport()->setChannelPowerDb(CalcDb::dbPower(getMagSq()));
|
||||
response.getNfmModReport()->setAudioSampleRate(m_basebandSource->getAudioSampleRate());
|
||||
response.getNfmModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate());
|
||||
response.getNfmModReport()->setChannelPowerDb((float) CalcDb::dbPower(getMagSq()));
|
||||
|
||||
if (m_running)
|
||||
{
|
||||
response.getNfmModReport()->setAudioSampleRate(m_basebandSource->getAudioSampleRate());
|
||||
response.getNfmModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate());
|
||||
}
|
||||
}
|
||||
|
||||
void NFMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const NFMModSettings& settings, bool force)
|
||||
void NFMMod::webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const NFMModSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
auto *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
|
||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
|
||||
@ -708,8 +749,8 @@ void NFMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, cons
|
||||
m_networkRequest.setUrl(QUrl(channelSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgChannelSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -722,7 +763,7 @@ void NFMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, cons
|
||||
|
||||
void NFMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
auto *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
swgChannelSettings->setDirection(1); // single source (Tx)
|
||||
swgChannelSettings->setChannelType(new QString("NFMMod"));
|
||||
swgChannelSettings->setNfmModSettings(new SWGSDRangel::SWGNFMModSettings());
|
||||
@ -730,7 +771,7 @@ void NFMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
|
||||
swgNFModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings());
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgNFModSettings->getCwKeyer();
|
||||
m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
|
||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
|
||||
.arg(m_settings.m_reverseAPIAddress)
|
||||
@ -740,8 +781,8 @@ void NFMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
m_networkRequest.setUrl(QUrl(channelSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgChannelSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -754,7 +795,7 @@ void NFMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
|
||||
void NFMMod::sendChannelSettings(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
const NFMModSettings& settings,
|
||||
bool force)
|
||||
{
|
||||
@ -764,7 +805,7 @@ void NFMMod::sendChannelSettings(
|
||||
|
||||
if (messageQueue)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
auto *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
MainCore::MsgChannelSettings *msg = MainCore::MsgChannelSettings::create(
|
||||
this,
|
||||
@ -778,7 +819,7 @@ void NFMMod::sendChannelSettings(
|
||||
}
|
||||
|
||||
void NFMMod::webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const NFMModSettings& settings,
|
||||
bool force
|
||||
@ -856,28 +897,28 @@ void NFMMod::webapiFormatChannelSettings(
|
||||
|
||||
if (settings.m_channelMarker && (channelSettingsKeys.contains("channelMarker") || force))
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
auto *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
swgNFMModSettings->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
|
||||
if (settings.m_rollupState && (channelSettingsKeys.contains("rollupState") || force))
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
auto *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
swgNFMModSettings->setRollupState(swgRollupState);
|
||||
}
|
||||
|
||||
if (force)
|
||||
{
|
||||
const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings();
|
||||
const CWKeyerSettings& cwKeyerSettings = getCWKeyer()->getSettings();
|
||||
swgNFMModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings());
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgNFMModSettings->getCwKeyer();
|
||||
m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
}
|
||||
}
|
||||
|
||||
void NFMMod::networkManagerFinished(QNetworkReply *reply)
|
||||
void NFMMod::networkManagerFinished(QNetworkReply *reply) const
|
||||
{
|
||||
QNetworkReply::NetworkError replyError = reply->error();
|
||||
|
||||
@ -900,17 +941,11 @@ void NFMMod::networkManagerFinished(QNetworkReply *reply)
|
||||
|
||||
double NFMMod::getMagSq() const
|
||||
{
|
||||
return m_basebandSource->getMagSq();
|
||||
}
|
||||
if (m_running) {
|
||||
return m_basebandSource->getMagSq();
|
||||
}
|
||||
|
||||
CWKeyer *NFMMod::getCWKeyer()
|
||||
{
|
||||
return &m_basebandSource->getCWKeyer();
|
||||
}
|
||||
|
||||
void NFMMod::setLevelMeter(QObject *levelMeter)
|
||||
{
|
||||
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t NFMMod::getNumberOfDeviceStreams() const
|
||||
@ -920,10 +955,18 @@ uint32_t NFMMod::getNumberOfDeviceStreams() const
|
||||
|
||||
int NFMMod::getAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
if (m_running) {
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NFMMod::getFeedbackAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
if (m_running) {
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include "dsp/basebandsamplesource.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
#include "channel/channelapi.h"
|
||||
#include "util/message.h"
|
||||
|
||||
@ -81,7 +82,7 @@ public:
|
||||
private:
|
||||
QString m_fileName;
|
||||
|
||||
MsgConfigureFileSourceName(const QString& fileName) :
|
||||
explicit MsgConfigureFileSourceName(const QString& fileName) :
|
||||
Message(),
|
||||
m_fileName(fileName)
|
||||
{ }
|
||||
@ -99,10 +100,10 @@ public:
|
||||
return new MsgConfigureFileSourceSeek(seekPercentage);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
int m_seekPercentage; //!< percentage of seek position from the beginning 0..100
|
||||
|
||||
MsgConfigureFileSourceSeek(int seekPercentage) :
|
||||
explicit MsgConfigureFileSourceSeek(int seekPercentage) :
|
||||
Message(),
|
||||
m_seekPercentage(seekPercentage)
|
||||
{ }
|
||||
@ -137,10 +138,10 @@ public:
|
||||
return new MsgReportFileSourceStreamTiming(samplesCount);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::size_t m_samplesCount;
|
||||
|
||||
MsgReportFileSourceStreamTiming(std::size_t samplesCount) :
|
||||
explicit MsgReportFileSourceStreamTiming(std::size_t samplesCount) :
|
||||
Message(),
|
||||
m_samplesCount(samplesCount)
|
||||
{ }
|
||||
@ -159,7 +160,7 @@ public:
|
||||
return new MsgReportFileSourceStreamData(sampleRate, recordLength);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
int m_sampleRate;
|
||||
quint32 m_recordLength;
|
||||
|
||||
@ -173,55 +174,55 @@ public:
|
||||
|
||||
//=================================================================
|
||||
|
||||
NFMMod(DeviceAPI *deviceAPI);
|
||||
virtual ~NFMMod();
|
||||
virtual void destroy() { delete this; }
|
||||
virtual void setDeviceAPI(DeviceAPI *deviceAPI);
|
||||
virtual DeviceAPI *getDeviceAPI() { return m_deviceAPI; }
|
||||
explicit NFMMod(DeviceAPI *deviceAPI);
|
||||
~NFMMod() final;
|
||||
void destroy() final { delete this; }
|
||||
void setDeviceAPI(DeviceAPI *deviceAPI) final;
|
||||
DeviceAPI *getDeviceAPI() final { return m_deviceAPI; }
|
||||
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void pull(SampleVector::iterator& begin, unsigned int nbSamples);
|
||||
virtual void pushMessage(Message *msg) { m_inputMessageQueue.push(msg); }
|
||||
virtual QString getSourceName() { return objectName(); }
|
||||
void start() final;
|
||||
void stop() final;
|
||||
void pull(SampleVector::iterator& begin, unsigned int nbSamples) final;
|
||||
void pushMessage(Message *msg) final { m_inputMessageQueue.push(msg); }
|
||||
QString getSourceName() final { return objectName(); }
|
||||
|
||||
virtual void getIdentifier(QString& id) { id = objectName(); }
|
||||
virtual QString getIdentifier() const { return objectName(); }
|
||||
virtual void getTitle(QString& title) { title = m_settings.m_title; }
|
||||
virtual qint64 getCenterFrequency() const { return m_settings.m_inputFrequencyOffset; }
|
||||
virtual void setCenterFrequency(qint64 frequency);
|
||||
void getIdentifier(QString& id) final { id = objectName(); }
|
||||
QString getIdentifier() const final { return objectName(); }
|
||||
void getTitle(QString& title) final { title = m_settings.m_title; }
|
||||
qint64 getCenterFrequency() const final { return m_settings.m_inputFrequencyOffset; }
|
||||
void setCenterFrequency(qint64 frequency) final;
|
||||
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
QByteArray serialize() const final;
|
||||
bool deserialize(const QByteArray& data) final;
|
||||
|
||||
virtual int getNbSinkStreams() const { return 1; }
|
||||
virtual int getNbSourceStreams() const { return 0; }
|
||||
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
|
||||
int getNbSinkStreams() const final { return 1; }
|
||||
int getNbSourceStreams() const final { return 0; }
|
||||
int getStreamIndex() const final { return m_settings.m_streamIndex; }
|
||||
|
||||
virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const
|
||||
qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const final
|
||||
{
|
||||
(void) streamIndex;
|
||||
(void) sinkElseSource;
|
||||
return m_settings.m_inputFrequencyOffset;
|
||||
}
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
int webapiSettingsGet(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiWorkspaceGet(
|
||||
int webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage);
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiReportGet(
|
||||
int webapiReportGet(
|
||||
SWGSDRangel::SWGChannelReport& response,
|
||||
QString& errorMessage);
|
||||
QString& errorMessage) final;
|
||||
|
||||
static void webapiFormatChannelSettings(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
@ -233,8 +234,8 @@ public:
|
||||
SWGSDRangel::SWGChannelSettings& response);
|
||||
|
||||
double getMagSq() const;
|
||||
CWKeyer *getCWKeyer();
|
||||
void setLevelMeter(QObject *levelMeter);
|
||||
CWKeyer *getCWKeyer() { return &m_cwKeyer; }
|
||||
void setLevelMeter(QObject *levelMeter) { m_levelMeter = levelMeter; }
|
||||
uint32_t getNumberOfDeviceStreams() const;
|
||||
int getAudioSampleRate() const;
|
||||
int getFeedbackAudioSampleRate() const;
|
||||
@ -250,6 +251,7 @@ private:
|
||||
|
||||
DeviceAPI* m_deviceAPI;
|
||||
QThread *m_thread;
|
||||
bool m_running = false;
|
||||
NFMModBaseband* m_basebandSource;
|
||||
NFMModSettings m_settings;
|
||||
|
||||
@ -258,36 +260,39 @@ private:
|
||||
|
||||
std::ifstream m_ifstream;
|
||||
QString m_fileName;
|
||||
quint64 m_fileSize; //!< raw file size (bytes)
|
||||
quint32 m_recordLength; //!< record length in seconds computed from file size
|
||||
int m_sampleRate;
|
||||
quint64 m_fileSize = 0; //!< raw file size (bytes)
|
||||
quint32 m_recordLength = 0; //!< record length in seconds computed from file size
|
||||
int m_sampleRate = 48000;
|
||||
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
CWKeyer m_cwKeyer;
|
||||
QObject *m_levelMeter = nullptr;
|
||||
|
||||
bool handleMessage(const Message& cmd) final;
|
||||
void applySettings(const NFMModSettings& settings, bool force = false);
|
||||
void sendSampleRateToDemodAnalyzer();
|
||||
void sendSampleRateToDemodAnalyzer() const;
|
||||
void openFileStream();
|
||||
void seekFileStream(int seekPercentage);
|
||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
|
||||
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const NFMModSettings& settings, bool force);
|
||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) const;
|
||||
void webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const NFMModSettings& settings, bool force);
|
||||
void webapiReverseSendCWSettings(const CWKeyerSettings& settings);
|
||||
void sendChannelSettings(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
const NFMModSettings& settings,
|
||||
bool force
|
||||
);
|
||||
void webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const NFMModSettings& settings,
|
||||
bool force
|
||||
);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void networkManagerFinished(QNetworkReply *reply) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "dsp/upchannelizer.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
|
||||
#include "nfmmodbaseband.h"
|
||||
|
||||
@ -170,8 +171,8 @@ bool NFMModBaseband::handleMessage(const Message& cmd)
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
const CWKeyer::MsgConfigureCWKeyer& cfg = (CWKeyer::MsgConfigureCWKeyer&) cmd;
|
||||
CWKeyer::MsgConfigureCWKeyer *notif = new CWKeyer::MsgConfigureCWKeyer(cfg);
|
||||
CWKeyer& cwKeyer = m_source.getCWKeyer();
|
||||
cwKeyer.getInputMessageQueue()->push(notif);
|
||||
CWKeyer *cwKeyer = m_source.getCWKeyer();
|
||||
cwKeyer->getInputMessageQueue()->push(notif);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
void reset();
|
||||
void pull(const SampleVector::iterator& begin, unsigned int nbSamples);
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
CWKeyer& getCWKeyer() { return m_source.getCWKeyer(); }
|
||||
void setCWKeyer(CWKeyer *cwKeyer) { m_source.setCWKeyer(cwKeyer); }
|
||||
double getMagSq() const { return m_source.getMagSq(); }
|
||||
int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
|
@ -20,26 +20,19 @@
|
||||
|
||||
#include "dsp/datafifo.h"
|
||||
#include "dsp/misc.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "nfmmodsource.h"
|
||||
|
||||
const int NFMModSource::m_levelNbSamples = 480; // every 10ms
|
||||
const float NFMModSource::m_preemphasis = 120.0e-6; // 120us
|
||||
const float NFMModSource::m_preemphasis = 120.0e-6f; // 120us
|
||||
|
||||
NFMModSource::NFMModSource() :
|
||||
m_channelSampleRate(48000),
|
||||
m_channelFrequencyOffset(0),
|
||||
m_modPhasor(0.0f),
|
||||
m_preemphasisFilter(m_preemphasis*48000),
|
||||
m_audioSampleRate(48000),
|
||||
m_audioFifo(12000),
|
||||
m_feedbackAudioFifo(48000),
|
||||
m_levelCalcCount(0),
|
||||
m_peakLevel(0.0f),
|
||||
m_levelSum(0.0f),
|
||||
m_ifstream(nullptr)
|
||||
m_feedbackAudioFifo(48000)
|
||||
{
|
||||
m_audioFifo.setLabel("NFMModSource.m_audioFifo");
|
||||
m_feedbackAudioFifo.setLabel("NFMModSource.m_feedbackAudioFifo");
|
||||
@ -62,7 +55,7 @@ NFMModSource::NFMModSource() :
|
||||
-20, // threshold (dB)
|
||||
20, // knee (dB)
|
||||
15, // ratio (dB)
|
||||
0.003, // attack (s)
|
||||
0.003f,// attack (s)
|
||||
0.25 // release (s)
|
||||
);
|
||||
|
||||
@ -70,9 +63,7 @@ NFMModSource::NFMModSource() :
|
||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||
}
|
||||
|
||||
NFMModSource::~NFMModSource()
|
||||
{
|
||||
}
|
||||
NFMModSource::~NFMModSource() = default;
|
||||
|
||||
void NFMModSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
|
||||
{
|
||||
@ -128,7 +119,7 @@ void NFMModSource::pullOne(Sample& sample)
|
||||
|
||||
void NFMModSource::prefetch(unsigned int nbSamples)
|
||||
{
|
||||
unsigned int nbSamplesAudio = nbSamples * ((Real) m_audioSampleRate / (Real) m_channelSampleRate);
|
||||
unsigned int nbSamplesAudio = (nbSamples * (unsigned int) ((Real) m_audioSampleRate / (Real) m_channelSampleRate));
|
||||
pullAudio(nbSamplesAudio);
|
||||
}
|
||||
|
||||
@ -152,7 +143,9 @@ void NFMModSource::pullAudio(unsigned int nbSamplesAudio)
|
||||
|
||||
void NFMModSource::modulateSample()
|
||||
{
|
||||
Real t0, t1, t;
|
||||
Real t0 = 0.0f;
|
||||
Real t1 = 0.0f;
|
||||
Real t = 0.0f;
|
||||
|
||||
pullAF(t0);
|
||||
|
||||
@ -171,24 +164,24 @@ void NFMModSource::modulateSample()
|
||||
if (m_settings.m_ctcssOn) {
|
||||
t1 = 0.85f * m_bandpass.filter(t) + 0.15f * 0.625f * m_ctcssNco.next();
|
||||
} else if (m_settings.m_dcsOn) {
|
||||
t1 = 0.9f * m_bandpass.filter(t) + 0.1f * 0.625f * m_dcsMod.next();
|
||||
t1 = 0.9f * m_bandpass.filter(t) + 0.1f * 0.625f * (float) m_dcsMod.next();
|
||||
} else if (m_settings.m_bpfOn) {
|
||||
t1 = m_bandpass.filter(t);
|
||||
} else {
|
||||
t1 = m_lowpass.filter(t);
|
||||
}
|
||||
|
||||
m_modPhasor += (M_PI * m_settings.m_fmDeviation / (float) m_audioSampleRate) * t1;
|
||||
m_modPhasor += (float) ((M_PI * m_settings.m_fmDeviation / (float) m_audioSampleRate) * t1);
|
||||
|
||||
// limit phasor range to ]-pi,pi]
|
||||
if (m_modPhasor > M_PI) {
|
||||
m_modPhasor -= (2.0f * M_PI);
|
||||
m_modPhasor -= (float) (2.0 * M_PI);
|
||||
}
|
||||
|
||||
m_modSample.real(cos(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); // -1 dB
|
||||
m_modSample.imag(sin(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF);
|
||||
m_modSample.real((float) (cos(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF)); // -1 dB
|
||||
m_modSample.imag((float) (sin(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF));
|
||||
|
||||
m_demodBuffer[m_demodBufferFill] = t1 * std::numeric_limits<int16_t>::max();
|
||||
m_demodBuffer[m_demodBufferFill] = (qint16) (t1 * std::numeric_limits<int16_t>::max());
|
||||
++m_demodBufferFill;
|
||||
|
||||
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||
@ -196,13 +189,11 @@ void NFMModSource::modulateSample()
|
||||
QList<ObjectPipe*> dataPipes;
|
||||
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
|
||||
|
||||
if (dataPipes.size() > 0)
|
||||
if (!dataPipes.empty())
|
||||
{
|
||||
QList<ObjectPipe*>::iterator it = dataPipes.begin();
|
||||
|
||||
for (; it != dataPipes.end(); ++it)
|
||||
for (auto& dataPipe : dataPipes)
|
||||
{
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>(dataPipe->m_element);
|
||||
|
||||
if (fifo) {
|
||||
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
|
||||
@ -222,17 +213,12 @@ void NFMModSource::pullAF(Real& sample)
|
||||
sample = m_toneNco.next();
|
||||
break;
|
||||
case NFMModSettings::NFMModInputFile:
|
||||
// sox f4exb_call.wav --encoding float --endian little f4exb_call.raw
|
||||
// ffplay -f f32le -ar 48k -ac 1 f4exb_call.raw
|
||||
if (m_ifstream && m_ifstream->is_open())
|
||||
{
|
||||
if (m_ifstream->eof())
|
||||
if (m_ifstream->eof() && m_settings.m_playLoop)
|
||||
{
|
||||
if (m_settings.m_playLoop)
|
||||
{
|
||||
m_ifstream->clear();
|
||||
m_ifstream->seekg(0, std::ios::beg);
|
||||
}
|
||||
m_ifstream->clear();
|
||||
m_ifstream->seekg(0, std::ios::beg);
|
||||
}
|
||||
|
||||
if (m_ifstream->eof())
|
||||
@ -267,8 +253,8 @@ void NFMModSource::pullAF(Real& sample)
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int size = m_audioBuffer.size();
|
||||
qDebug("NFMModSource::pullAF: starve audio samples: size: %u", size);
|
||||
std::size_t size = m_audioBuffer.size();
|
||||
qDebug("NFMModSource::pullAF: starve audio samples: size: %lu", size);
|
||||
sample = ((m_audioBuffer[size-1].l + m_audioBuffer[size-1].r) / 65536.0f) * m_settings.m_volumeFactor;
|
||||
}
|
||||
|
||||
@ -276,14 +262,18 @@ void NFMModSource::pullAF(Real& sample)
|
||||
case NFMModSettings::NFMModInputCWTone:
|
||||
Real fadeFactor;
|
||||
|
||||
if (m_cwKeyer.getSample())
|
||||
if (!m_cwKeyer) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_cwKeyer->getSample())
|
||||
{
|
||||
m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor);
|
||||
m_cwKeyer->getCWSmoother().getFadeSample(true, fadeFactor);
|
||||
sample = m_toneNco.next() * fadeFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor))
|
||||
if (m_cwKeyer->getCWSmoother().getFadeSample(false, fadeFactor))
|
||||
{
|
||||
sample = m_toneNco.next() * fadeFactor;
|
||||
}
|
||||
@ -294,7 +284,6 @@ void NFMModSource::pullAF(Real& sample)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NFMModSettings::NFMModInputNone:
|
||||
default:
|
||||
sample = 0.0f;
|
||||
break;
|
||||
@ -324,10 +313,10 @@ void NFMModSource::pushFeedback(Real sample)
|
||||
}
|
||||
}
|
||||
|
||||
void NFMModSource::processOneSample(Complex& ci)
|
||||
void NFMModSource::processOneSample(const Complex& ci)
|
||||
{
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = (qint16) ci.real();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = (qint16) ci.imag();
|
||||
++m_feedbackAudioBufferFill;
|
||||
|
||||
if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size())
|
||||
@ -345,7 +334,7 @@ void NFMModSource::processOneSample(Complex& ci)
|
||||
}
|
||||
}
|
||||
|
||||
void NFMModSource::calculateLevel(Real& sample)
|
||||
void NFMModSource::calculateLevel(const Real& sample)
|
||||
{
|
||||
if (m_levelCalcCount < m_levelNbSamples)
|
||||
{
|
||||
@ -379,13 +368,18 @@ void NFMModSource::applyAudioSampleRate(int sampleRate)
|
||||
m_interpolator.create(48, sampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
|
||||
m_lowpass.create(301, sampleRate, m_settings.m_afBandwidth);
|
||||
m_bandpass.create(301, sampleRate, 300.0, m_settings.m_afBandwidth);
|
||||
m_toneNco.setFreq(m_settings.m_toneFrequency, sampleRate);
|
||||
m_ctcssNco.setFreq(NFMModSettings::getCTCSSFreq(m_settings.m_ctcssIndex), sampleRate);
|
||||
m_toneNco.setFreq(m_settings.m_toneFrequency, (float) sampleRate);
|
||||
m_ctcssNco.setFreq(NFMModSettings::getCTCSSFreq(m_settings.m_ctcssIndex), (float) sampleRate);
|
||||
m_dcsMod.setSampleRate(sampleRate);
|
||||
m_cwKeyer.setSampleRate(sampleRate);
|
||||
m_cwKeyer.reset();
|
||||
m_preemphasisFilter.configure(m_preemphasis*sampleRate);
|
||||
m_audioCompressor.m_rate = sampleRate;
|
||||
|
||||
if (m_cwKeyer)
|
||||
{
|
||||
m_cwKeyer->setSampleRate(sampleRate);
|
||||
m_cwKeyer->reset();
|
||||
}
|
||||
|
||||
m_preemphasisFilter.configure(m_preemphasis * (float) sampleRate);
|
||||
m_audioCompressor.m_rate = (float) sampleRate;
|
||||
m_audioCompressor.initState();
|
||||
m_audioSampleRate = sampleRate;
|
||||
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
||||
@ -393,7 +387,7 @@ void NFMModSource::applyAudioSampleRate(int sampleRate)
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
|
||||
|
||||
if (pipes.size() > 0)
|
||||
if (!pipes.empty())
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
@ -417,7 +411,7 @@ void NFMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||
m_feedbackInterpolatorDistanceRemain = 0;
|
||||
m_feedbackInterpolatorConsumed = false;
|
||||
m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate;
|
||||
Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f;
|
||||
Real cutoff = (float) std::min(sampleRate, m_audioSampleRate) / 2.2f;
|
||||
m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0);
|
||||
m_feedbackAudioSampleRate = sampleRate;
|
||||
}
|
||||
@ -433,11 +427,11 @@ void NFMModSource::applySettings(const NFMModSettings& settings, bool force)
|
||||
}
|
||||
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force) {
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, m_audioSampleRate);
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, (float) m_audioSampleRate);
|
||||
}
|
||||
|
||||
if ((settings.m_ctcssIndex != m_settings.m_ctcssIndex) || force) {
|
||||
m_ctcssNco.setFreq(NFMModSettings::getCTCSSFreq(settings.m_ctcssIndex), m_audioSampleRate);
|
||||
m_ctcssNco.setFreq(NFMModSettings::getCTCSSFreq(settings.m_ctcssIndex), (float) m_audioSampleRate);
|
||||
}
|
||||
|
||||
if ((settings.m_dcsCode != m_settings.m_dcsCode) || force) {
|
||||
@ -469,7 +463,7 @@ void NFMModSource::applyChannelSettings(int channelSampleRate, int channelFreque
|
||||
if ((channelFrequencyOffset != m_channelFrequencyOffset)
|
||||
|| (channelSampleRate != m_channelSampleRate) || force)
|
||||
{
|
||||
m_carrierNco.setFreq(channelFrequencyOffset, channelSampleRate);
|
||||
m_carrierNco.setFreq((float) channelFrequencyOffset, (float) channelSampleRate);
|
||||
}
|
||||
|
||||
if ((channelSampleRate != m_channelSampleRate) || force)
|
||||
@ -486,7 +480,6 @@ void NFMModSource::applyChannelSettings(int channelSampleRate, int channelFreque
|
||||
|
||||
void NFMModSource::handleAudio()
|
||||
{
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
unsigned int nbRead;
|
||||
|
||||
while ((nbRead = m_audioFifo.read(reinterpret_cast<quint8*>(&m_audioReadBuffer[m_audioReadBufferFill]), 4096)) != 0)
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "dsp/firfilter.h"
|
||||
#include "dsp/filterrc.h"
|
||||
#include "util/movingaverage.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
#include "audio/audiofifo.h"
|
||||
#include "audio/audiocompressorsnd.h"
|
||||
|
||||
@ -41,17 +40,18 @@
|
||||
#include "nfmmoddcs.h"
|
||||
|
||||
class ChannelAPI;
|
||||
class CWKeyer;
|
||||
|
||||
class NFMModSource : public QObject, public ChannelSampleSource
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NFMModSource();
|
||||
virtual ~NFMModSource();
|
||||
~NFMModSource() final;
|
||||
|
||||
virtual void pull(SampleVector::iterator begin, unsigned int nbSamples);
|
||||
virtual void pullOne(Sample& sample);
|
||||
virtual void prefetch(unsigned int nbSamples);
|
||||
void pull(SampleVector::iterator begin, unsigned int nbSamples) final;
|
||||
void pullOne(Sample& sample) final;
|
||||
void prefetch(unsigned int nbSamples) final;
|
||||
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_ifstream = ifstream; }
|
||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||
@ -61,7 +61,8 @@ public:
|
||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||
void setCWKeyer(CWKeyer *cwKeyer) { m_cwKeyer = cwKeyer; }
|
||||
CWKeyer *getCWKeyer() { return m_cwKeyer; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||
{
|
||||
@ -73,8 +74,8 @@ public:
|
||||
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
|
||||
|
||||
private:
|
||||
int m_channelSampleRate;
|
||||
int m_channelFrequencyOffset;
|
||||
int m_channelSampleRate = 48000;
|
||||
int m_channelFrequencyOffset = 0;
|
||||
NFMModSettings m_settings;
|
||||
ChannelAPI *m_channel;
|
||||
|
||||
@ -82,7 +83,7 @@ private:
|
||||
NCOF m_toneNco;
|
||||
NCOF m_ctcssNco;
|
||||
NFMModDCS m_dcsMod;
|
||||
float m_modPhasor; //!< baseband modulator phasor
|
||||
float m_modPhasor = 0.0f; //!< baseband modulator phasor
|
||||
Complex m_modSample;
|
||||
|
||||
Interpolator m_interpolator;
|
||||
@ -105,7 +106,7 @@ private:
|
||||
double m_magsq;
|
||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||
|
||||
int m_audioSampleRate;
|
||||
int m_audioSampleRate = 48000;
|
||||
AudioVector m_audioBuffer;
|
||||
unsigned int m_audioBufferFill;
|
||||
AudioVector m_audioReadBuffer;
|
||||
@ -117,14 +118,14 @@ private:
|
||||
uint m_feedbackAudioBufferFill;
|
||||
AudioFifo m_feedbackAudioFifo;
|
||||
|
||||
quint32 m_levelCalcCount;
|
||||
quint32 m_levelCalcCount = 0;
|
||||
qreal m_rmsLevel;
|
||||
qreal m_peakLevelOut;
|
||||
Real m_peakLevel;
|
||||
Real m_levelSum;
|
||||
Real m_peakLevel = 0.0f;
|
||||
Real m_levelSum = 0.0f;
|
||||
|
||||
std::ifstream *m_ifstream;
|
||||
CWKeyer m_cwKeyer;
|
||||
std::ifstream *m_ifstream = nullptr;
|
||||
CWKeyer *m_cwKeyer = nullptr;
|
||||
|
||||
AudioCompressorSnd m_audioCompressor;
|
||||
|
||||
@ -133,11 +134,11 @@ private:
|
||||
static const int m_levelNbSamples;
|
||||
static const float m_preemphasis;
|
||||
|
||||
void processOneSample(Complex& ci);
|
||||
void processOneSample(const Complex& ci);
|
||||
void pullAF(Real& sample);
|
||||
void pullAudio(unsigned int nbSamples);
|
||||
void pushFeedback(Real sample);
|
||||
void calculateLevel(Real& sample);
|
||||
void calculateLevel(const Real& sample);
|
||||
void modulateSample();
|
||||
|
||||
private slots:
|
||||
|
@ -57,20 +57,9 @@ const char* const SSBMod::m_channelId = "SSBMod";
|
||||
SSBMod::SSBMod(DeviceAPI *deviceAPI) :
|
||||
ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_spectrumVis(SDR_TX_SCALEF),
|
||||
m_fileSize(0),
|
||||
m_recordLength(0),
|
||||
m_sampleRate(48000)
|
||||
m_spectrumVis(SDR_TX_SCALEF)
|
||||
{
|
||||
setObjectName(m_channelId);
|
||||
|
||||
m_thread = new QThread(this);
|
||||
m_basebandSource = new SSBModBaseband();
|
||||
m_basebandSource->setSpectrumSink(&m_spectrumVis);
|
||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||
m_basebandSource->setChannel(this);
|
||||
m_basebandSource->moveToThread(m_thread);
|
||||
|
||||
applySettings(m_settings, true);
|
||||
|
||||
m_deviceAPI->addChannelSource(this);
|
||||
@ -96,8 +85,8 @@ SSBMod::~SSBMod()
|
||||
delete m_networkManager;
|
||||
m_deviceAPI->removeChannelSourceAPI(this);
|
||||
m_deviceAPI->removeChannelSource(this);
|
||||
delete m_basebandSource;
|
||||
delete m_thread;
|
||||
|
||||
SSBMod::stop();
|
||||
}
|
||||
|
||||
void SSBMod::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
@ -114,21 +103,62 @@ void SSBMod::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
|
||||
void SSBMod::start()
|
||||
{
|
||||
if (m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("SSBMod::start");
|
||||
m_thread = new QThread(this);
|
||||
m_basebandSource = new SSBModBaseband();
|
||||
m_basebandSource->setSpectrumSink(&m_spectrumVis);
|
||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||
m_basebandSource->setChannel(this);
|
||||
m_basebandSource->reset();
|
||||
m_basebandSource->setCWKeyer(&m_cwKeyer);
|
||||
m_basebandSource->moveToThread(m_thread);
|
||||
|
||||
QObject::connect(
|
||||
m_thread,
|
||||
&QThread::finished,
|
||||
m_basebandSource,
|
||||
&QObject::deleteLater
|
||||
);
|
||||
QObject::connect(
|
||||
m_thread,
|
||||
&QThread::finished,
|
||||
m_thread,
|
||||
&QThread::deleteLater
|
||||
);
|
||||
|
||||
m_thread->start();
|
||||
|
||||
SSBModBaseband::MsgConfigureSSBModBaseband *msg = SSBModBaseband::MsgConfigureSSBModBaseband::create(m_settings, true);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
|
||||
if (m_levelMeter) {
|
||||
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), m_levelMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
}
|
||||
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
void SSBMod::stop()
|
||||
{
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("SSBMod::stop");
|
||||
m_running = false;
|
||||
m_thread->exit();
|
||||
m_thread->wait();
|
||||
}
|
||||
|
||||
void SSBMod::pull(SampleVector::iterator& begin, unsigned int nbSamples)
|
||||
{
|
||||
m_basebandSource->pull(begin, nbSamples);
|
||||
if (m_running) {
|
||||
m_basebandSource->pull(begin, nbSamples);
|
||||
}
|
||||
}
|
||||
|
||||
void SSBMod::setCenterFrequency(qint64 frequency)
|
||||
@ -148,7 +178,7 @@ bool SSBMod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if (MsgConfigureSSBMod::match(cmd))
|
||||
{
|
||||
MsgConfigureSSBMod& cfg = (MsgConfigureSSBMod&) cmd;
|
||||
auto& cfg = (const MsgConfigureSSBMod&) cmd;
|
||||
qDebug() << "SSBMod::handleMessage: MsgConfigureSSBMod";
|
||||
|
||||
applySettings(cfg.getSettings(), cfg.getForce());
|
||||
@ -157,14 +187,14 @@ bool SSBMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MsgConfigureFileSourceName::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) cmd;
|
||||
auto& conf = (const MsgConfigureFileSourceName&) cmd;
|
||||
m_fileName = conf.getFileName();
|
||||
openFileStream();
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSourceSeek::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceSeek& conf = (MsgConfigureFileSourceSeek&) cmd;
|
||||
auto& conf = (const MsgConfigureFileSourceSeek&) cmd;
|
||||
int seekPercentage = conf.getPercentage();
|
||||
seekFileStream(seekPercentage);
|
||||
|
||||
@ -172,18 +202,17 @@ bool SSBMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MsgConfigureFileSourceStreamTiming::match(cmd))
|
||||
{
|
||||
std::size_t samplesCount;
|
||||
std::size_t samplesCount;
|
||||
|
||||
if (m_ifstream.eof()) {
|
||||
samplesCount = m_fileSize / sizeof(Real);
|
||||
} else {
|
||||
samplesCount = m_ifstream.tellg() / sizeof(Real);
|
||||
}
|
||||
if (m_ifstream.eof()) {
|
||||
samplesCount = m_fileSize / sizeof(Real);
|
||||
} else {
|
||||
samplesCount = m_ifstream.tellg() / sizeof(Real);
|
||||
}
|
||||
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportFileSourceStreamTiming *report;
|
||||
report = MsgReportFileSourceStreamTiming::create(samplesCount);
|
||||
auto *report = MsgReportFileSourceStreamTiming::create(samplesCount);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
|
||||
@ -191,7 +220,7 @@ bool SSBMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (CWKeyer::MsgConfigureCWKeyer::match(cmd))
|
||||
{
|
||||
const CWKeyer::MsgConfigureCWKeyer& cfg = (CWKeyer::MsgConfigureCWKeyer&) cmd;
|
||||
auto& cfg = (const CWKeyer::MsgConfigureCWKeyer&) cmd;
|
||||
|
||||
if (m_settings.m_useReverseAPI) {
|
||||
webapiReverseSendCWSettings(cfg.getSettings());
|
||||
@ -201,11 +230,14 @@ bool SSBMod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
auto& notif = (const DSPSignalNotification&) cmd;
|
||||
// Forward to the source
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy
|
||||
qDebug() << "SSBMod::handleMessage: DSPSignalNotification";
|
||||
m_basebandSource->getInputMessageQueue()->push(rep);
|
||||
if (m_running)
|
||||
{
|
||||
auto* rep = new DSPSignalNotification(notif); // make a copy
|
||||
qDebug() << "SSBMod::handleMessage: DSPSignalNotification";
|
||||
m_basebandSource->getInputMessageQueue()->push(rep);
|
||||
}
|
||||
// Forward to GUI if any
|
||||
if (getMessageQueueToGUI()) {
|
||||
getMessageQueueToGUI()->push(new DSPSignalNotification(notif));
|
||||
@ -237,7 +269,7 @@ void SSBMod::openFileStream()
|
||||
m_ifstream.seekg(0,std::ios_base::beg);
|
||||
|
||||
m_sampleRate = 48000; // fixed rate
|
||||
m_recordLength = m_fileSize / (sizeof(Real) * m_sampleRate);
|
||||
m_recordLength = (quint32) (m_fileSize / (sizeof(Real) * m_sampleRate));
|
||||
|
||||
qDebug() << "SSBMod::openFileStream: " << m_fileName.toStdString().c_str()
|
||||
<< " fileSize: " << m_fileSize << "bytes"
|
||||
@ -360,8 +392,11 @@ void SSBMod::applySettings(const SSBModSettings& settings, bool force)
|
||||
m_spectrumVis.getInputMessageQueue()->push(msg);
|
||||
}
|
||||
|
||||
SSBModBaseband::MsgConfigureSSBModBaseband *msg = SSBModBaseband::MsgConfigureSSBModBaseband::create(settings, force);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
if (m_running)
|
||||
{
|
||||
SSBModBaseband::MsgConfigureSSBModBaseband *msg = SSBModBaseband::MsgConfigureSSBModBaseband::create(settings, force);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
}
|
||||
|
||||
if (settings.m_useReverseAPI)
|
||||
{
|
||||
@ -376,7 +411,7 @@ void SSBMod::applySettings(const SSBModSettings& settings, bool force)
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "settings", pipes);
|
||||
|
||||
if (pipes.size() > 0) {
|
||||
if (!pipes.empty()) {
|
||||
sendChannelSettings(pipes, reverseAPIKeys, settings, force);
|
||||
}
|
||||
|
||||
@ -408,12 +443,12 @@ bool SSBMod::deserialize(const QByteArray& data)
|
||||
}
|
||||
}
|
||||
|
||||
void SSBMod::sendSampleRateToDemodAnalyzer()
|
||||
void SSBMod::sendSampleRateToDemodAnalyzer() const
|
||||
{
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "reportdemod", pipes);
|
||||
|
||||
if (pipes.size() > 0)
|
||||
if (!pipes.empty())
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
@ -437,7 +472,7 @@ int SSBMod::webapiSettingsGet(
|
||||
webapiFormatChannelSettings(response, m_settings);
|
||||
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getSsbModSettings()->getCwKeyer();
|
||||
const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings();
|
||||
const CWKeyerSettings& cwKeyerSettings = m_cwKeyer.getSettings();
|
||||
CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
|
||||
return 200;
|
||||
@ -465,11 +500,11 @@ int SSBMod::webapiSettingsPutPatch(
|
||||
if (channelSettingsKeys.contains("cwKeyer"))
|
||||
{
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getSsbModSettings()->getCwKeyer();
|
||||
CWKeyerSettings cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings();
|
||||
CWKeyerSettings cwKeyerSettings = m_cwKeyer.getSettings();
|
||||
CWKeyer::webapiSettingsPutPatch(channelSettingsKeys, cwKeyerSettings, apiCwKeyerSettings);
|
||||
|
||||
CWKeyer::MsgConfigureCWKeyer *msgCwKeyer = CWKeyer::MsgConfigureCWKeyer::create(cwKeyerSettings, force);
|
||||
m_basebandSource->getCWKeyer().getInputMessageQueue()->push(msgCwKeyer);
|
||||
m_cwKeyer.getInputMessageQueue()->push(msgCwKeyer);
|
||||
|
||||
if (m_guiMessageQueue) // forward to GUI if any
|
||||
{
|
||||
@ -564,13 +599,13 @@ void SSBMod::webapiUpdateChannelSettings(
|
||||
settings.m_reverseAPIAddress = *response.getSsbModSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getSsbModSettings()->getReverseApiPort();
|
||||
settings.m_reverseAPIPort = (uint16_t) response.getSsbModSettings()->getReverseApiPort();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getSsbModSettings()->getReverseApiDeviceIndex();
|
||||
settings.m_reverseAPIDeviceIndex = (uint16_t) response.getSsbModSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
|
||||
settings.m_reverseAPIChannelIndex = response.getSsbModSettings()->getReverseApiChannelIndex();
|
||||
settings.m_reverseAPIChannelIndex = (uint16_t) response.getSsbModSettings()->getReverseApiChannelIndex();
|
||||
}
|
||||
if (settings.m_spectrumGUI && channelSettingsKeys.contains("spectrumConfig")) {
|
||||
settings.m_spectrumGUI->updateFrom(channelSettingsKeys, response.getSsbModSettings()->getSpectrumConfig());
|
||||
@ -651,7 +686,7 @@ void SSBMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGGLSpectrum *swgGLSpectrum = new SWGSDRangel::SWGGLSpectrum();
|
||||
auto *swgGLSpectrum = new SWGSDRangel::SWGGLSpectrum();
|
||||
settings.m_spectrumGUI->formatTo(swgGLSpectrum);
|
||||
response.getSsbModSettings()->setSpectrumConfig(swgGLSpectrum);
|
||||
}
|
||||
@ -665,7 +700,7 @@ void SSBMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
auto *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
response.getSsbModSettings()->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
@ -679,23 +714,27 @@ void SSBMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
auto *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
response.getSsbModSettings()->setRollupState(swgRollupState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SSBMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response)
|
||||
void SSBMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) const
|
||||
{
|
||||
response.getSsbModReport()->setChannelPowerDb(CalcDb::dbPower(getMagSq()));
|
||||
response.getSsbModReport()->setAudioSampleRate(m_basebandSource->getAudioSampleRate());
|
||||
response.getSsbModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate());
|
||||
response.getSsbModReport()->setChannelPowerDb((float) CalcDb::dbPower(getMagSq()));
|
||||
|
||||
if (m_running)
|
||||
{
|
||||
response.getSsbModReport()->setAudioSampleRate(m_basebandSource->getAudioSampleRate());
|
||||
response.getSsbModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate());
|
||||
}
|
||||
}
|
||||
|
||||
void SSBMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const SSBModSettings& settings, bool force)
|
||||
void SSBMod::webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const SSBModSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
auto *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
|
||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
|
||||
@ -706,8 +745,8 @@ void SSBMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, cons
|
||||
m_networkRequest.setUrl(QUrl(channelSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgChannelSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -720,7 +759,7 @@ void SSBMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, cons
|
||||
|
||||
void SSBMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
auto *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
swgChannelSettings->setDirection(1); // single source (Tx)
|
||||
swgChannelSettings->setChannelType(new QString("SSBMod"));
|
||||
swgChannelSettings->setSsbModSettings(new SWGSDRangel::SWGSSBModSettings());
|
||||
@ -728,7 +767,7 @@ void SSBMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
|
||||
swgSSBModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings());
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgSSBModSettings->getCwKeyer();
|
||||
m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
|
||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
|
||||
.arg(m_settings.m_reverseAPIAddress)
|
||||
@ -738,8 +777,8 @@ void SSBMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
m_networkRequest.setUrl(QUrl(channelSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgChannelSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -752,9 +791,9 @@ void SSBMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings)
|
||||
|
||||
void SSBMod::sendChannelSettings(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
const SSBModSettings& settings,
|
||||
bool force)
|
||||
bool force) const
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
@ -762,7 +801,7 @@ void SSBMod::sendChannelSettings(
|
||||
|
||||
if (messageQueue)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
auto *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
MainCore::MsgChannelSettings *msg = MainCore::MsgChannelSettings::create(
|
||||
this,
|
||||
@ -776,11 +815,11 @@ void SSBMod::sendChannelSettings(
|
||||
}
|
||||
|
||||
void SSBMod::webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const SSBModSettings& settings,
|
||||
bool force
|
||||
)
|
||||
) const
|
||||
{
|
||||
swgChannelSettings->setDirection(1); // single source (Tx)
|
||||
swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
|
||||
@ -854,35 +893,35 @@ void SSBMod::webapiFormatChannelSettings(
|
||||
|
||||
if (settings.m_spectrumGUI && (channelSettingsKeys.contains("spectrunConfig") || force))
|
||||
{
|
||||
SWGSDRangel::SWGGLSpectrum *swgGLSpectrum = new SWGSDRangel::SWGGLSpectrum();
|
||||
auto *swgGLSpectrum = new SWGSDRangel::SWGGLSpectrum();
|
||||
settings.m_spectrumGUI->formatTo(swgGLSpectrum);
|
||||
swgSSBModSettings->setSpectrumConfig(swgGLSpectrum);
|
||||
}
|
||||
|
||||
if (settings.m_channelMarker && (channelSettingsKeys.contains("channelMarker") || force))
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
auto *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
swgSSBModSettings->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
|
||||
if (settings.m_rollupState && (channelSettingsKeys.contains("rollupState") || force))
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
auto *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
swgSSBModSettings->setRollupState(swgRollupState);
|
||||
}
|
||||
|
||||
if (force)
|
||||
{
|
||||
const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings();
|
||||
const CWKeyerSettings& cwKeyerSettings = m_cwKeyer.getSettings();
|
||||
swgSSBModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings());
|
||||
SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgSSBModSettings->getCwKeyer();
|
||||
m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
|
||||
}
|
||||
}
|
||||
|
||||
void SSBMod::networkManagerFinished(QNetworkReply *reply)
|
||||
void SSBMod::networkManagerFinished(QNetworkReply *reply) const
|
||||
{
|
||||
QNetworkReply::NetworkError replyError = reply->error();
|
||||
|
||||
@ -905,27 +944,34 @@ void SSBMod::networkManagerFinished(QNetworkReply *reply)
|
||||
|
||||
double SSBMod::getMagSq() const
|
||||
{
|
||||
return m_basebandSource->getMagSq();
|
||||
if (m_running) {
|
||||
return m_basebandSource->getMagSq();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CWKeyer *SSBMod::getCWKeyer()
|
||||
{
|
||||
return &m_basebandSource->getCWKeyer();
|
||||
}
|
||||
|
||||
void SSBMod::setLevelMeter(QObject *levelMeter)
|
||||
{
|
||||
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
return &m_cwKeyer;
|
||||
}
|
||||
|
||||
int SSBMod::getAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
if (m_running) {
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SSBMod::getFeedbackAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
if (m_running) {
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t SSBMod::getNumberOfDeviceStreams() const
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "dsp/basebandsamplesource.h"
|
||||
#include "dsp/spectrumvis.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
#include "channel/channelapi.h"
|
||||
#include "util/message.h"
|
||||
|
||||
@ -82,7 +83,7 @@ public:
|
||||
private:
|
||||
QString m_fileName;
|
||||
|
||||
MsgConfigureFileSourceName(const QString& fileName) :
|
||||
explicit MsgConfigureFileSourceName(const QString& fileName) :
|
||||
Message(),
|
||||
m_fileName(fileName)
|
||||
{ }
|
||||
@ -100,10 +101,10 @@ public:
|
||||
return new MsgConfigureFileSourceSeek(seekPercentage);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
int m_seekPercentage; //!< percentage of seek position from the beginning 0..100
|
||||
|
||||
MsgConfigureFileSourceSeek(int seekPercentage) :
|
||||
explicit MsgConfigureFileSourceSeek(int seekPercentage) :
|
||||
Message(),
|
||||
m_seekPercentage(seekPercentage)
|
||||
{ }
|
||||
@ -138,10 +139,10 @@ public:
|
||||
return new MsgReportFileSourceStreamTiming(samplesCount);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::size_t m_samplesCount;
|
||||
|
||||
MsgReportFileSourceStreamTiming(std::size_t samplesCount) :
|
||||
explicit MsgReportFileSourceStreamTiming(std::size_t samplesCount) :
|
||||
Message(),
|
||||
m_samplesCount(samplesCount)
|
||||
{ }
|
||||
@ -160,7 +161,7 @@ public:
|
||||
return new MsgReportFileSourceStreamData(sampleRate, recordLength);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
int m_sampleRate;
|
||||
quint32 m_recordLength;
|
||||
|
||||
@ -174,55 +175,55 @@ public:
|
||||
|
||||
//=================================================================
|
||||
|
||||
SSBMod(DeviceAPI *deviceAPI);
|
||||
virtual ~SSBMod();
|
||||
virtual void destroy() { delete this; }
|
||||
virtual void setDeviceAPI(DeviceAPI *deviceAPI);
|
||||
virtual DeviceAPI *getDeviceAPI() { return m_deviceAPI; }
|
||||
explicit SSBMod(DeviceAPI *deviceAPI);
|
||||
~SSBMod() final;
|
||||
void destroy() final { delete this; }
|
||||
void setDeviceAPI(DeviceAPI *deviceAPI) final;
|
||||
DeviceAPI *getDeviceAPI() final { return m_deviceAPI; }
|
||||
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void pull(SampleVector::iterator& begin, unsigned int nbSamples);
|
||||
virtual void pushMessage(Message *msg) { m_inputMessageQueue.push(msg); }
|
||||
virtual QString getSourceName() { return objectName(); }
|
||||
void start() final;
|
||||
void stop() final;
|
||||
void pull(SampleVector::iterator& begin, unsigned int nbSamples) final;
|
||||
void pushMessage(Message *msg) final { m_inputMessageQueue.push(msg); }
|
||||
QString getSourceName() final { return objectName(); }
|
||||
|
||||
virtual void getIdentifier(QString& id) { id = objectName(); }
|
||||
virtual QString getIdentifier() const { return objectName(); }
|
||||
virtual void getTitle(QString& title) { title = m_settings.m_title; }
|
||||
virtual qint64 getCenterFrequency() const { return m_settings.m_inputFrequencyOffset; }
|
||||
virtual void setCenterFrequency(qint64 frequency);
|
||||
void getIdentifier(QString& id) final { id = objectName(); }
|
||||
QString getIdentifier() const final { return objectName(); }
|
||||
void getTitle(QString& title) final { title = m_settings.m_title; }
|
||||
qint64 getCenterFrequency() const final { return m_settings.m_inputFrequencyOffset; }
|
||||
void setCenterFrequency(qint64 frequency) final;
|
||||
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
QByteArray serialize() const final;
|
||||
bool deserialize(const QByteArray& data) final;
|
||||
|
||||
virtual int getNbSinkStreams() const { return 1; }
|
||||
virtual int getNbSourceStreams() const { return 0; }
|
||||
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
|
||||
int getNbSinkStreams() const final { return 1; }
|
||||
int getNbSourceStreams() const final { return 0; }
|
||||
int getStreamIndex() const final { return m_settings.m_streamIndex; }
|
||||
|
||||
virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const
|
||||
qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const final
|
||||
{
|
||||
(void) streamIndex;
|
||||
(void) sinkElseSource;
|
||||
return m_settings.m_inputFrequencyOffset;
|
||||
}
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
int webapiSettingsGet(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiWorkspaceGet(
|
||||
int webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage);
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiReportGet(
|
||||
int webapiReportGet(
|
||||
SWGSDRangel::SWGChannelReport& response,
|
||||
QString& errorMessage);
|
||||
QString& errorMessage) final;
|
||||
|
||||
static void webapiFormatChannelSettings(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
@ -236,7 +237,7 @@ public:
|
||||
SpectrumVis *getSpectrumVis() { return &m_spectrumVis; }
|
||||
double getMagSq() const;
|
||||
CWKeyer *getCWKeyer();
|
||||
void setLevelMeter(QObject *levelMeter);
|
||||
void setLevelMeter(QObject *levelMeter) { m_levelMeter = levelMeter; }
|
||||
int getAudioSampleRate() const;
|
||||
int getFeedbackAudioSampleRate() const;
|
||||
uint32_t getNumberOfDeviceStreams() const;
|
||||
@ -252,6 +253,7 @@ private:
|
||||
|
||||
DeviceAPI* m_deviceAPI;
|
||||
QThread *m_thread;
|
||||
bool m_running = false;
|
||||
SSBModBaseband* m_basebandSource;
|
||||
SSBModSettings m_settings;
|
||||
SpectrumVis m_spectrumVis;
|
||||
@ -261,36 +263,38 @@ private:
|
||||
|
||||
std::ifstream m_ifstream;
|
||||
QString m_fileName;
|
||||
quint64 m_fileSize; //!< raw file size (bytes)
|
||||
quint32 m_recordLength; //!< record length in seconds computed from file size
|
||||
int m_sampleRate;
|
||||
quint64 m_fileSize = 0; //!< raw file size (bytes)
|
||||
quint32 m_recordLength = 0; //!< record length in seconds computed from file size
|
||||
int m_sampleRate = 48000;
|
||||
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
CWKeyer m_cwKeyer;
|
||||
QObject *m_levelMeter;
|
||||
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
bool handleMessage(const Message& cmd) final;
|
||||
void applySettings(const SSBModSettings& settings, bool force = false);
|
||||
void sendSampleRateToDemodAnalyzer();
|
||||
void sendSampleRateToDemodAnalyzer() const;
|
||||
void openFileStream();
|
||||
void seekFileStream(int seekPercentage);
|
||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
|
||||
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const SSBModSettings& settings, bool force);
|
||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) const;
|
||||
void webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const SSBModSettings& settings, bool force);
|
||||
void webapiReverseSendCWSettings(const CWKeyerSettings& settings);
|
||||
void sendChannelSettings(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
const SSBModSettings& settings,
|
||||
bool force
|
||||
);
|
||||
) const;
|
||||
void webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const SSBModSettings& settings,
|
||||
bool force
|
||||
);
|
||||
) const;
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void networkManagerFinished(QNetworkReply *reply) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -171,8 +171,8 @@ bool SSBModBaseband::handleMessage(const Message& cmd)
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
const CWKeyer::MsgConfigureCWKeyer& cfg = (CWKeyer::MsgConfigureCWKeyer&) cmd;
|
||||
CWKeyer::MsgConfigureCWKeyer *notif = new CWKeyer::MsgConfigureCWKeyer(cfg);
|
||||
CWKeyer& cwKeyer = m_source.getCWKeyer();
|
||||
cwKeyer.getInputMessageQueue()->push(notif);
|
||||
CWKeyer *cwKeyer = m_source.getCWKeyer();
|
||||
cwKeyer->getInputMessageQueue()->push(notif);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
void reset();
|
||||
void pull(const SampleVector::iterator& begin, unsigned int nbSamples);
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
CWKeyer& getCWKeyer() { return m_source.getCWKeyer(); }
|
||||
void setCWKeyer(CWKeyer *cwKeyer) { m_source.setCWKeyer(cwKeyer); }
|
||||
double getMagSq() const { return m_source.getMagSq(); }
|
||||
int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
|
@ -30,21 +30,13 @@ const int SSBModSource::m_ssbFftLen = 1024;
|
||||
const int SSBModSource::m_levelNbSamples = 480; // every 10ms
|
||||
|
||||
SSBModSource::SSBModSource() :
|
||||
m_channelSampleRate(48000),
|
||||
m_channelFrequencyOffset(0),
|
||||
m_spectrumSink(nullptr),
|
||||
m_audioSampleRate(48000),
|
||||
m_audioFifo(12000),
|
||||
m_feedbackAudioFifo(12000),
|
||||
m_levelCalcCount(0),
|
||||
m_peakLevel(0.0f),
|
||||
m_levelSum(0.0f),
|
||||
m_ifstream(nullptr)
|
||||
m_feedbackAudioFifo(12000)
|
||||
{
|
||||
m_audioFifo.setLabel("SSBModSource.m_audioFifo");
|
||||
m_feedbackAudioFifo.setLabel("SSBModSource.m_feedbackAudioFifo");
|
||||
m_SSBFilter = new fftfilt(m_settings.m_lowCutoff / m_audioSampleRate, m_settings.m_bandwidth / m_audioSampleRate, m_ssbFftLen);
|
||||
m_DSBFilter = new fftfilt((2.0f * m_settings.m_bandwidth) / m_audioSampleRate, 2 * m_ssbFftLen);
|
||||
m_SSBFilter = new fftfilt(m_settings.m_lowCutoff / (float) m_audioSampleRate, m_settings.m_bandwidth / (float) m_audioSampleRate, m_ssbFftLen);
|
||||
m_DSBFilter = new fftfilt((2.0f * m_settings.m_bandwidth) / (float) m_audioSampleRate, 2 * m_ssbFftLen);
|
||||
m_SSBFilterBuffer = new Complex[m_ssbFftLen>>1]; // filter returns data exactly half of its size
|
||||
m_DSBFilterBuffer = new Complex[m_ssbFftLen];
|
||||
std::fill(m_SSBFilterBuffer, m_SSBFilterBuffer+(m_ssbFftLen>>1), Complex{0,0});
|
||||
@ -67,18 +59,15 @@ SSBModSource::SSBModSource() :
|
||||
m_sumCount = 0;
|
||||
|
||||
m_magsq = 0.0;
|
||||
m_toneNco.setFreq(1000.0, m_audioSampleRate);
|
||||
|
||||
m_cwKeyer.setSampleRate(m_audioSampleRate);
|
||||
m_cwKeyer.reset();
|
||||
m_toneNco.setFreq(1000.0, (float) m_audioSampleRate);
|
||||
|
||||
m_audioCompressor.initSimple(
|
||||
m_audioSampleRate,
|
||||
m_settings.m_cmpPreGainDB, // pregain (dB)
|
||||
m_settings.m_cmpThresholdDB, // threshold (dB)
|
||||
(float) m_settings.m_cmpPreGainDB, // pregain (dB)
|
||||
(float) m_settings.m_cmpThresholdDB, // threshold (dB)
|
||||
20, // knee (dB)
|
||||
12, // ratio (dB)
|
||||
0.003, // attack (s)
|
||||
0.003f,// attack (s)
|
||||
0.25 // release (s)
|
||||
);
|
||||
|
||||
@ -142,7 +131,7 @@ void SSBModSource::pullOne(Sample& sample)
|
||||
|
||||
void SSBModSource::prefetch(unsigned int nbSamples)
|
||||
{
|
||||
unsigned int nbSamplesAudio = nbSamples * ((Real) m_audioSampleRate / (Real) m_channelSampleRate);
|
||||
unsigned int nbSamplesAudio = (nbSamples * (unsigned int) ((Real) m_audioSampleRate / (Real) m_channelSampleRate));
|
||||
pullAudio(nbSamplesAudio);
|
||||
}
|
||||
|
||||
@ -176,13 +165,16 @@ void SSBModSource::modulateSample()
|
||||
|
||||
if (m_settings.m_audioBinaural)
|
||||
{
|
||||
m_demodBuffer[m_demodBufferFill++] = m_modSample.real() * std::numeric_limits<int16_t>::max();
|
||||
m_demodBuffer[m_demodBufferFill++] = m_modSample.imag() * std::numeric_limits<int16_t>::max();
|
||||
m_demodBuffer[m_demodBufferFill] = (qint16) (m_modSample.real() * std::numeric_limits<int16_t>::max());
|
||||
m_demodBufferFill++;
|
||||
m_demodBuffer[m_demodBufferFill] = (qint16) (m_modSample.imag() * std::numeric_limits<int16_t>::max());
|
||||
m_demodBufferFill++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// take projection on real axis
|
||||
m_demodBuffer[m_demodBufferFill++] = m_modSample.real() * std::numeric_limits<int16_t>::max();
|
||||
m_demodBuffer[m_demodBufferFill] = (qint16) (m_modSample.real() * std::numeric_limits<int16_t>::max());
|
||||
m_demodBufferFill++;
|
||||
}
|
||||
|
||||
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||
@ -190,13 +182,11 @@ void SSBModSource::modulateSample()
|
||||
QList<ObjectPipe*> dataPipes;
|
||||
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
|
||||
|
||||
if (dataPipes.size() > 0)
|
||||
if (!dataPipes.empty())
|
||||
{
|
||||
QList<ObjectPipe*>::iterator it = dataPipes.begin();
|
||||
|
||||
for (; it != dataPipes.end(); ++it)
|
||||
for (auto& dataPipe : dataPipes)
|
||||
{
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>(dataPipe->m_element);
|
||||
|
||||
if (fifo)
|
||||
{
|
||||
@ -227,42 +217,33 @@ void SSBModSource::pullAF(Complex& sample)
|
||||
int n_out = 0;
|
||||
|
||||
int decim = 1<<(m_settings.m_spanLog2 - 1);
|
||||
unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
|
||||
auto decim_mask = (unsigned char) ((decim - 1) & 0xFF); // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
|
||||
|
||||
switch (m_settings.m_modAFInput)
|
||||
{
|
||||
case SSBModSettings::SSBModInputTone:
|
||||
if (m_settings.m_dsb)
|
||||
{
|
||||
Real t = m_toneNco.next()/1.25;
|
||||
sample.real(t);
|
||||
sample.imag(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_usb) {
|
||||
sample = m_toneNco.nextIQ();
|
||||
} else {
|
||||
sample = m_toneNco.nextQI();
|
||||
}
|
||||
}
|
||||
if (m_settings.m_dsb)
|
||||
{
|
||||
Real t = m_toneNco.next()/1.25f;
|
||||
sample.real(t);
|
||||
sample.imag(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_usb) {
|
||||
sample = m_toneNco.nextIQ();
|
||||
} else {
|
||||
sample = m_toneNco.nextQI();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSBModSettings::SSBModInputFile:
|
||||
// Monaural (mono):
|
||||
// sox f4exb_call.wav --encoding float --endian little f4exb_call.raw
|
||||
// ffplay -f f32le -ar 48k -ac 1 f4exb_call.raw
|
||||
// Binaural (stereo):
|
||||
// sox f4exb_call.wav --encoding float --endian little f4exb_call.raw
|
||||
// ffplay -f f32le -ar 48k -ac 2 f4exb_call.raw
|
||||
if (m_ifstream && m_ifstream->is_open())
|
||||
{
|
||||
if (m_ifstream->eof())
|
||||
if (m_ifstream->eof() && m_settings.m_playLoop)
|
||||
{
|
||||
if (m_settings.m_playLoop)
|
||||
{
|
||||
m_ifstream->clear();
|
||||
m_ifstream->seekg(0, std::ios::beg);
|
||||
}
|
||||
m_ifstream->clear();
|
||||
m_ifstream->seekg(0, std::ios::beg);
|
||||
}
|
||||
|
||||
if (m_ifstream->eof())
|
||||
@ -272,38 +253,38 @@ void SSBModSource::pullAF(Complex& sample)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_audioBinaural)
|
||||
{
|
||||
Complex c;
|
||||
m_ifstream->read(reinterpret_cast<char*>(&c), sizeof(Complex));
|
||||
if (m_settings.m_audioBinaural)
|
||||
{
|
||||
Complex c;
|
||||
m_ifstream->read(reinterpret_cast<char*>(&c), sizeof(Complex));
|
||||
|
||||
if (m_settings.m_audioFlipChannels)
|
||||
{
|
||||
if (m_settings.m_audioFlipChannels)
|
||||
{
|
||||
ci.real(c.imag() * m_settings.m_volumeFactor);
|
||||
ci.imag(c.real() * m_settings.m_volumeFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ci = c * m_settings.m_volumeFactor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ci = c * m_settings.m_volumeFactor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Real real;
|
||||
m_ifstream->read(reinterpret_cast<char*>(&real), sizeof(Real));
|
||||
m_ifstream->read(reinterpret_cast<char*>(&real), sizeof(Real));
|
||||
|
||||
if (m_settings.m_agc)
|
||||
{
|
||||
if (m_settings.m_agc)
|
||||
{
|
||||
ci.real(clamp<float>(m_audioCompressor.compress(real), -1.0f, 1.0f));
|
||||
ci.imag(0.0f);
|
||||
ci *= m_settings.m_volumeFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ci.real(real * m_settings.m_volumeFactor);
|
||||
ci.imag(0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -314,24 +295,24 @@ void SSBModSource::pullAF(Complex& sample)
|
||||
break;
|
||||
case SSBModSettings::SSBModInputAudio:
|
||||
if (m_settings.m_audioBinaural)
|
||||
{
|
||||
if (m_settings.m_audioFlipChannels)
|
||||
{
|
||||
{
|
||||
if (m_settings.m_audioFlipChannels)
|
||||
{
|
||||
ci.real((m_audioBuffer[m_audioBufferFill].r / SDR_TX_SCALEF) * m_settings.m_volumeFactor);
|
||||
ci.imag((m_audioBuffer[m_audioBufferFill].l / SDR_TX_SCALEF) * m_settings.m_volumeFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ci.real((m_audioBuffer[m_audioBufferFill].l / SDR_TX_SCALEF) * m_settings.m_volumeFactor);
|
||||
ci.imag((m_audioBuffer[m_audioBufferFill].r / SDR_TX_SCALEF) * m_settings.m_volumeFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_agc)
|
||||
{
|
||||
float sample = (m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f;
|
||||
ci.real(clamp<float>(m_audioCompressor.compress(sample), -1.0f, 1.0f));
|
||||
float xsample = (m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f;
|
||||
ci.real(clamp<float>(m_audioCompressor.compress(xsample), -1.0f, 1.0f));
|
||||
ci.imag(0.0f);
|
||||
ci *= m_settings.m_volumeFactor;
|
||||
}
|
||||
@ -349,61 +330,64 @@ void SSBModSource::pullAF(Complex& sample)
|
||||
else
|
||||
{
|
||||
qDebug("SSBModSource::pullAF: starve audio samples: size: %lu", m_audioBuffer.size());
|
||||
m_audioBufferFill = m_audioBuffer.size() - 1;
|
||||
m_audioBufferFill = (unsigned int) (m_audioBuffer.size() - 1);
|
||||
}
|
||||
|
||||
break;
|
||||
case SSBModSettings::SSBModInputCWTone:
|
||||
Real fadeFactor;
|
||||
if (!m_cwKeyer) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_cwKeyer.getSample())
|
||||
Real fadeFactor;
|
||||
|
||||
if (m_cwKeyer->getSample())
|
||||
{
|
||||
m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor);
|
||||
m_cwKeyer->getCWSmoother().getFadeSample(true, fadeFactor);
|
||||
|
||||
if (m_settings.m_dsb)
|
||||
{
|
||||
Real t = m_toneNco.next() * fadeFactor;
|
||||
sample.real(t);
|
||||
sample.imag(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_usb) {
|
||||
sample = m_toneNco.nextIQ() * fadeFactor;
|
||||
} else {
|
||||
sample = m_toneNco.nextQI() * fadeFactor;
|
||||
}
|
||||
}
|
||||
if (m_settings.m_dsb)
|
||||
{
|
||||
Real t = m_toneNco.next() * fadeFactor;
|
||||
sample.real(t);
|
||||
sample.imag(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_usb) {
|
||||
sample = m_toneNco.nextIQ() * fadeFactor;
|
||||
} else {
|
||||
sample = m_toneNco.nextQI() * fadeFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor))
|
||||
{
|
||||
if (m_settings.m_dsb)
|
||||
{
|
||||
Real t = (m_toneNco.next() * fadeFactor)/1.25;
|
||||
sample.real(t);
|
||||
sample.imag(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_usb) {
|
||||
sample = m_toneNco.nextIQ() * fadeFactor;
|
||||
} else {
|
||||
sample = m_toneNco.nextQI() * fadeFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_cwKeyer->getCWSmoother().getFadeSample(false, fadeFactor))
|
||||
{
|
||||
if (m_settings.m_dsb)
|
||||
{
|
||||
Real t = (m_toneNco.next() * fadeFactor)/1.25f;
|
||||
sample.real(t);
|
||||
sample.imag(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_usb) {
|
||||
sample = m_toneNco.nextIQ() * fadeFactor;
|
||||
} else {
|
||||
sample = m_toneNco.nextQI() * fadeFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sample.real(0.0f);
|
||||
sample.imag(0.0f);
|
||||
m_toneNco.setPhase(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SSBModSettings::SSBModInputNone:
|
||||
default:
|
||||
sample.real(0.0f);
|
||||
sample.imag(0.0f);
|
||||
@ -413,35 +397,35 @@ void SSBModSource::pullAF(Complex& sample)
|
||||
if ((m_settings.m_modAFInput == SSBModSettings::SSBModInputFile)
|
||||
|| (m_settings.m_modAFInput == SSBModSettings::SSBModInputAudio)) // real audio
|
||||
{
|
||||
if (m_settings.m_dsb)
|
||||
{
|
||||
n_out = m_DSBFilter->runDSB(ci, &filtered);
|
||||
if (m_settings.m_dsb)
|
||||
{
|
||||
n_out = m_DSBFilter->runDSB(ci, &filtered);
|
||||
|
||||
if (n_out > 0)
|
||||
{
|
||||
memcpy((void *) m_DSBFilterBuffer, (const void *) filtered, n_out*sizeof(Complex));
|
||||
m_DSBFilterBufferIndex = 0;
|
||||
}
|
||||
if (n_out > 0)
|
||||
{
|
||||
memcpy((void *) m_DSBFilterBuffer, (const void *) filtered, n_out*sizeof(Complex));
|
||||
m_DSBFilterBufferIndex = 0;
|
||||
}
|
||||
|
||||
sample = m_DSBFilterBuffer[m_DSBFilterBufferIndex];
|
||||
m_DSBFilterBufferIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
n_out = m_SSBFilter->runSSB(ci, &filtered, m_settings.m_usb);
|
||||
sample = m_DSBFilterBuffer[m_DSBFilterBufferIndex];
|
||||
m_DSBFilterBufferIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
n_out = m_SSBFilter->runSSB(ci, &filtered, m_settings.m_usb);
|
||||
|
||||
if (n_out > 0)
|
||||
{
|
||||
memcpy((void *) m_SSBFilterBuffer, (const void *) filtered, n_out*sizeof(Complex));
|
||||
m_SSBFilterBufferIndex = 0;
|
||||
}
|
||||
if (n_out > 0)
|
||||
{
|
||||
memcpy((void *) m_SSBFilterBuffer, (const void *) filtered, n_out*sizeof(Complex));
|
||||
m_SSBFilterBufferIndex = 0;
|
||||
}
|
||||
|
||||
sample = m_SSBFilterBuffer[m_SSBFilterBufferIndex];
|
||||
m_SSBFilterBufferIndex++;
|
||||
}
|
||||
sample = m_SSBFilterBuffer[m_SSBFilterBufferIndex];
|
||||
m_SSBFilterBufferIndex++;
|
||||
}
|
||||
|
||||
if (n_out > 0)
|
||||
{
|
||||
if (n_out > 0)
|
||||
{
|
||||
for (int i = 0; i < n_out; i++)
|
||||
{
|
||||
// Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
|
||||
@ -451,23 +435,23 @@ void SSBModSource::pullAF(Complex& sample)
|
||||
|
||||
if (!(m_undersampleCount++ & decim_mask))
|
||||
{
|
||||
Real avgr = (m_sum.real() / decim) * 0.891235351562f * SDR_TX_SCALEF; //scaling at -1 dB to account for possible filter overshoot
|
||||
Real avgi = (m_sum.imag() / decim) * 0.891235351562f * SDR_TX_SCALEF;
|
||||
Real avgr = (m_sum.real() / (float) decim) * 0.891235351562f * SDR_TX_SCALEF; //scaling at -1 dB to account for possible filter overshoot
|
||||
Real avgi = (m_sum.imag() / (float) decim) * 0.891235351562f * SDR_TX_SCALEF;
|
||||
|
||||
if (!m_settings.m_dsb & !m_settings.m_usb)
|
||||
if (!m_settings.m_dsb && !m_settings.m_usb)
|
||||
{ // invert spectrum for LSB
|
||||
m_sampleBuffer.push_back(Sample(avgi, avgr));
|
||||
m_sampleBuffer.push_back(Sample((FixReal) avgi, (FixReal) avgr));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sampleBuffer.push_back(Sample(avgr, avgi));
|
||||
m_sampleBuffer.push_back(Sample((FixReal) avgr, (FixReal)avgi));
|
||||
}
|
||||
|
||||
m_sum.real(0.0);
|
||||
m_sum.imag(0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Real audio
|
||||
else if ((m_settings.m_modAFInput == SSBModSettings::SSBModInputTone)
|
||||
|| (m_settings.m_modAFInput == SSBModSettings::SSBModInputCWTone)) // tone
|
||||
@ -476,16 +460,16 @@ void SSBModSource::pullAF(Complex& sample)
|
||||
|
||||
if (!(m_undersampleCount++ & decim_mask))
|
||||
{
|
||||
Real avgr = (m_sum.real() / decim) * 0.891235351562f * SDR_TX_SCALEF; //scaling at -1 dB to account for possible filter overshoot
|
||||
Real avgi = (m_sum.imag() / decim) * 0.891235351562f * SDR_TX_SCALEF;
|
||||
Real avgr = (m_sum.real() / (float) decim) * 0.891235351562f * SDR_TX_SCALEF; //scaling at -1 dB to account for possible filter overshoot
|
||||
Real avgi = (m_sum.imag() / (float) decim) * 0.891235351562f * SDR_TX_SCALEF;
|
||||
|
||||
if (!m_settings.m_dsb & !m_settings.m_usb)
|
||||
if (!m_settings.m_dsb && !m_settings.m_usb)
|
||||
{ // invert spectrum for LSB
|
||||
m_sampleBuffer.push_back(Sample(avgi, avgr));
|
||||
m_sampleBuffer.push_back(Sample((FixReal) avgi, (FixReal) avgr));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sampleBuffer.push_back(Sample(avgr, avgi));
|
||||
m_sampleBuffer.push_back(Sample((FixReal) avgr, (FixReal) avgi));
|
||||
}
|
||||
|
||||
m_sum.real(0.0);
|
||||
@ -536,18 +520,18 @@ void SSBModSource::pushFeedback(Complex c)
|
||||
}
|
||||
}
|
||||
|
||||
void SSBModSource::processOneSample(Complex& ci)
|
||||
void SSBModSource::processOneSample(const Complex& ci)
|
||||
{
|
||||
if (m_settings.m_modAFInput == SSBModSettings::SSBModInputCWTone) // minimize latency for CW
|
||||
{
|
||||
m_feedbackAudioBuffer[0].l = ci.real();
|
||||
m_feedbackAudioBuffer[0].r = ci.imag();
|
||||
m_feedbackAudioBuffer[0].l = (qint16) ci.real();
|
||||
m_feedbackAudioBuffer[0].r = (qint16) ci.imag();
|
||||
m_feedbackAudioFifo.writeOne((const quint8*) &m_feedbackAudioBuffer[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = (qint16) ci.real();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = (qint16) ci.imag();
|
||||
++m_feedbackAudioBufferFill;
|
||||
|
||||
if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size())
|
||||
@ -566,9 +550,9 @@ void SSBModSource::processOneSample(Complex& ci)
|
||||
}
|
||||
}
|
||||
|
||||
void SSBModSource::calculateLevel(Complex& sample)
|
||||
void SSBModSource::calculateLevel(const Complex& sample)
|
||||
{
|
||||
Real t = sample.real(); // TODO: possibly adjust depending on sample type
|
||||
Real t = sample.real();
|
||||
|
||||
if (m_levelCalcCount < m_levelNbSamples)
|
||||
{
|
||||
@ -615,18 +599,22 @@ void SSBModSource::applyAudioSampleRate(int sampleRate)
|
||||
lowCutoff = band - 100.0f;
|
||||
}
|
||||
|
||||
m_SSBFilter->create_filter(lowCutoff / sampleRate, band / sampleRate);
|
||||
m_DSBFilter->create_dsb_filter((2.0f * band) / sampleRate);
|
||||
m_SSBFilter->create_filter(lowCutoff / (float) sampleRate, band / (float) sampleRate);
|
||||
m_DSBFilter->create_dsb_filter((2.0f * band) / (float) sampleRate);
|
||||
|
||||
m_settings.m_bandwidth = band;
|
||||
m_settings.m_lowCutoff = lowCutoff;
|
||||
m_settings.m_usb = usb;
|
||||
|
||||
m_toneNco.setFreq(m_settings.m_toneFrequency, sampleRate);
|
||||
m_cwKeyer.setSampleRate(sampleRate);
|
||||
m_cwKeyer.reset();
|
||||
m_toneNco.setFreq(m_settings.m_toneFrequency, (float) sampleRate);
|
||||
|
||||
m_audioCompressor.m_rate = sampleRate;
|
||||
if (m_cwKeyer)
|
||||
{
|
||||
m_cwKeyer->setSampleRate(sampleRate);
|
||||
m_cwKeyer->reset();
|
||||
}
|
||||
|
||||
m_audioCompressor.m_rate = (float) sampleRate;
|
||||
m_audioCompressor.initState();
|
||||
m_audioSampleRate = sampleRate;
|
||||
|
||||
@ -635,7 +623,7 @@ void SSBModSource::applyAudioSampleRate(int sampleRate)
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
|
||||
|
||||
if (pipes.size() > 0)
|
||||
if (!pipes.empty())
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
@ -659,7 +647,7 @@ void SSBModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||
m_feedbackInterpolatorDistanceRemain = 0;
|
||||
m_feedbackInterpolatorConsumed = false;
|
||||
m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate;
|
||||
Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f;
|
||||
Real cutoff = (float) (std::min(sampleRate, m_audioSampleRate)) / 2.2f;
|
||||
m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0);
|
||||
m_feedbackAudioSampleRate = sampleRate;
|
||||
}
|
||||
@ -687,12 +675,12 @@ void SSBModSource::applySettings(const SSBModSettings& settings, bool force)
|
||||
m_interpolatorConsumed = false;
|
||||
m_interpolatorDistance = (Real) m_audioSampleRate / (Real) m_channelSampleRate;
|
||||
m_interpolator.create(48, m_audioSampleRate, band, 3.0);
|
||||
m_SSBFilter->create_filter(lowCutoff / m_audioSampleRate, band / m_audioSampleRate);
|
||||
m_DSBFilter->create_dsb_filter((2.0f * band) / m_audioSampleRate);
|
||||
m_SSBFilter->create_filter(lowCutoff / (float) m_audioSampleRate, band / (float) m_audioSampleRate);
|
||||
m_DSBFilter->create_dsb_filter((2.0f * band) / (float) m_audioSampleRate);
|
||||
}
|
||||
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force) {
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, m_audioSampleRate);
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, (float) m_audioSampleRate);
|
||||
}
|
||||
|
||||
if ((settings.m_dsb != m_settings.m_dsb) || force)
|
||||
@ -723,11 +711,11 @@ void SSBModSource::applySettings(const SSBModSettings& settings, bool force)
|
||||
{
|
||||
m_audioCompressor.initSimple(
|
||||
m_audioSampleRate,
|
||||
settings.m_cmpPreGainDB, // pregain (dB)
|
||||
settings.m_cmpThresholdDB, // threshold (dB)
|
||||
(float) settings.m_cmpPreGainDB, // pregain (dB)
|
||||
(float) settings.m_cmpThresholdDB, // threshold (dB)
|
||||
20, // knee (dB)
|
||||
12, // ratio (dB)
|
||||
0.003, // attack (s)
|
||||
0.003f,// attack (s)
|
||||
0.25 // release (s)
|
||||
);
|
||||
}
|
||||
@ -745,8 +733,8 @@ void SSBModSource::applyChannelSettings(int channelSampleRate, int channelFreque
|
||||
<< " channelFrequencyOffset: " << channelFrequencyOffset;
|
||||
|
||||
if ((channelFrequencyOffset != m_channelFrequencyOffset)
|
||||
|| (channelSampleRate != m_channelSampleRate) || force) {
|
||||
m_carrierNco.setFreq(channelFrequencyOffset, channelSampleRate);
|
||||
|| (channelSampleRate != m_channelSampleRate) || force) {
|
||||
m_carrierNco.setFreq((float) channelFrequencyOffset, (float) channelSampleRate);
|
||||
}
|
||||
|
||||
if ((channelSampleRate != m_channelSampleRate) || force)
|
||||
@ -763,7 +751,6 @@ void SSBModSource::applyChannelSettings(int channelSampleRate, int channelFreque
|
||||
|
||||
void SSBModSource::handleAudio()
|
||||
{
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
unsigned int nbRead;
|
||||
|
||||
while ((nbRead = m_audioFifo.read(reinterpret_cast<quint8*>(&m_audioReadBuffer[m_audioReadBufferFill]), 4096)) != 0)
|
||||
|
@ -39,17 +39,18 @@
|
||||
|
||||
class ChannelAPI;
|
||||
class SpectrumVis;
|
||||
class CWKeyer;
|
||||
|
||||
class SSBModSource : public QObject, public ChannelSampleSource
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SSBModSource();
|
||||
virtual ~SSBModSource();
|
||||
~SSBModSource() final;
|
||||
|
||||
virtual void pull(SampleVector::iterator begin, unsigned int nbSamples);
|
||||
virtual void pullOne(Sample& sample);
|
||||
virtual void prefetch(unsigned int nbSamples);
|
||||
void pull(SampleVector::iterator begin, unsigned int nbSamples) final;
|
||||
void pullOne(Sample& sample) final;
|
||||
void prefetch(unsigned int nbSamples) final;
|
||||
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_ifstream = ifstream; }
|
||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||
@ -59,7 +60,8 @@ public:
|
||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||
CWKeyer* getCWKeyer() { return m_cwKeyer; }
|
||||
void setCWKeyer(CWKeyer *cwKeyer) { m_cwKeyer = cwKeyer; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||
{
|
||||
@ -68,12 +70,12 @@ public:
|
||||
numSamples = m_levelNbSamples;
|
||||
}
|
||||
void applySettings(const SSBModSettings& settings, bool force = false);
|
||||
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = 0);
|
||||
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
|
||||
void setSpectrumSink(SpectrumVis *sampleSink) { m_spectrumSink = sampleSink; }
|
||||
|
||||
private:
|
||||
int m_channelSampleRate;
|
||||
int m_channelFrequencyOffset;
|
||||
int m_channelSampleRate = 48000;
|
||||
int m_channelFrequencyOffset = 0;
|
||||
SSBModSettings m_settings;
|
||||
ChannelAPI *m_channel;
|
||||
|
||||
@ -102,7 +104,7 @@ private:
|
||||
int m_DSBFilterBufferIndex;
|
||||
static const int m_ssbFftLen;
|
||||
|
||||
SpectrumVis* m_spectrumSink;
|
||||
SpectrumVis* m_spectrumSink = nullptr;
|
||||
SampleVector m_sampleBuffer;
|
||||
|
||||
fftfilt::cmplx m_sum;
|
||||
@ -112,7 +114,7 @@ private:
|
||||
double m_magsq;
|
||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||
|
||||
int m_audioSampleRate;
|
||||
int m_audioSampleRate = 48000;
|
||||
AudioVector m_audioBuffer;
|
||||
unsigned int m_audioBufferFill;
|
||||
AudioVector m_audioReadBuffer;
|
||||
@ -124,14 +126,14 @@ private:
|
||||
uint m_feedbackAudioBufferFill;
|
||||
AudioFifo m_feedbackAudioFifo;
|
||||
|
||||
quint32 m_levelCalcCount;
|
||||
quint32 m_levelCalcCount = 0;
|
||||
qreal m_rmsLevel;
|
||||
qreal m_peakLevelOut;
|
||||
Real m_peakLevel;
|
||||
Real m_levelSum;
|
||||
Real m_peakLevel = 0.0f;
|
||||
Real m_levelSum = 0.0f;
|
||||
|
||||
std::ifstream *m_ifstream;
|
||||
CWKeyer m_cwKeyer;
|
||||
std::ifstream *m_ifstream = nullptr;
|
||||
CWKeyer *m_cwKeyer = nullptr;
|
||||
|
||||
AudioCompressorSnd m_audioCompressor;
|
||||
int m_agcStepLength;
|
||||
@ -140,11 +142,11 @@ private:
|
||||
|
||||
static const int m_levelNbSamples;
|
||||
|
||||
void processOneSample(Complex& ci);
|
||||
void processOneSample(const Complex& ci);
|
||||
void pullAF(Complex& sample);
|
||||
void pullAudio(unsigned int nbSamples);
|
||||
void pushFeedback(Complex sample);
|
||||
void calculateLevel(Complex& sample);
|
||||
void calculateLevel(const Complex& sample);
|
||||
void modulateSample();
|
||||
|
||||
private slots:
|
||||
|
@ -142,6 +142,12 @@ void BladeRF2MIMO::init()
|
||||
|
||||
bool BladeRF2MIMO::startRx()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningRx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebug("BladeRF2MIMO::startRx");
|
||||
|
||||
if (!m_open)
|
||||
@ -150,12 +156,6 @@ bool BladeRF2MIMO::startRx()
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningRx) {
|
||||
stopRx();
|
||||
}
|
||||
|
||||
m_sourceThread = new BladeRF2MIThread(m_dev->getDev());
|
||||
m_sampleMIFifo.reset();
|
||||
m_sourceThread->setFifo(&m_sampleMIFifo);
|
||||
@ -178,6 +178,12 @@ bool BladeRF2MIMO::startRx()
|
||||
|
||||
bool BladeRF2MIMO::startTx()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningTx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebug("BladeRF2MIMO::startTx");
|
||||
|
||||
if (!m_open)
|
||||
@ -186,12 +192,6 @@ bool BladeRF2MIMO::startTx()
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningTx) {
|
||||
stopTx();
|
||||
}
|
||||
|
||||
m_sinkThread = new BladeRF2MOThread(m_dev->getDev());
|
||||
m_sampleMOFifo.reset();
|
||||
m_sinkThread->setFifo(&m_sampleMOFifo);
|
||||
@ -213,18 +213,22 @@ bool BladeRF2MIMO::startTx()
|
||||
|
||||
void BladeRF2MIMO::stopRx()
|
||||
{
|
||||
qDebug("BladeRF2MIMO::stopRx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_runningRx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sourceThread) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug("BladeRF2MIMO::stopRx");
|
||||
m_runningRx = false;
|
||||
|
||||
m_sourceThread->stopWork();
|
||||
delete m_sourceThread;
|
||||
m_sourceThread = nullptr;
|
||||
m_runningRx = false;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
m_dev->closeRx(i);
|
||||
@ -233,18 +237,22 @@ void BladeRF2MIMO::stopRx()
|
||||
|
||||
void BladeRF2MIMO::stopTx()
|
||||
{
|
||||
qDebug("BladeRF2MIMO::stopTx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_runningTx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sinkThread) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug("BladeRF2MIMO::stopTx");
|
||||
m_runningTx = false;
|
||||
|
||||
m_sinkThread->stopWork();
|
||||
delete m_sinkThread;
|
||||
m_sinkThread = nullptr;
|
||||
m_runningTx = false;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
m_dev->closeTx(i);
|
||||
|
@ -256,6 +256,12 @@ void LimeSDRMIMO::init()
|
||||
|
||||
bool LimeSDRMIMO::startRx()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningRx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebug("LimeSDRMIMO::startRx");
|
||||
lms_stream_t *streams[2];
|
||||
|
||||
@ -265,12 +271,6 @@ bool LimeSDRMIMO::startRx()
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningRx) {
|
||||
stopRx();
|
||||
}
|
||||
|
||||
for (unsigned int channel = 0; channel < 2; channel++)
|
||||
{
|
||||
if (channel < m_deviceAPI->getNbSourceStreams())
|
||||
@ -307,18 +307,22 @@ bool LimeSDRMIMO::startRx()
|
||||
|
||||
void LimeSDRMIMO::stopRx()
|
||||
{
|
||||
qDebug("LimeSDRMIMO::stopRx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_runningRx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sourceThread) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug("LimeSDRMIMO::stopRx");
|
||||
m_runningRx = false;
|
||||
|
||||
m_sourceThread->stopWork();
|
||||
delete m_sourceThread;
|
||||
m_sourceThread = nullptr;
|
||||
m_runningRx = false;
|
||||
|
||||
for (unsigned int channel = 0; channel < 2; channel++)
|
||||
{
|
||||
@ -330,6 +334,12 @@ void LimeSDRMIMO::stopRx()
|
||||
|
||||
bool LimeSDRMIMO::startTx()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningTx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebug("LimeSDRMIMO::startTx");
|
||||
lms_stream_t *streams[2];
|
||||
|
||||
@ -339,12 +349,6 @@ bool LimeSDRMIMO::startTx()
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningTx) {
|
||||
stopTx();
|
||||
}
|
||||
|
||||
for (unsigned int channel = 0; channel < 2; channel++)
|
||||
{
|
||||
if (channel < m_deviceAPI->getNbSinkStreams())
|
||||
@ -380,18 +384,22 @@ bool LimeSDRMIMO::startTx()
|
||||
|
||||
void LimeSDRMIMO::stopTx()
|
||||
{
|
||||
qDebug("LimeSDRMIMO::stopTx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_runningTx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sinkThread) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug("LimeSDRMIMO::stopTx");
|
||||
m_runningTx = false;
|
||||
|
||||
m_sinkThread->stopWork();
|
||||
delete m_sinkThread;
|
||||
m_sinkThread = nullptr;
|
||||
m_runningTx = false;
|
||||
|
||||
for (unsigned int channel = 0; channel < 2; channel++)
|
||||
{
|
||||
|
@ -66,6 +66,7 @@ MetisMISO::MetisMISO(DeviceAPI *deviceAPI) :
|
||||
|
||||
MetisMISO::~MetisMISO()
|
||||
{
|
||||
qDebug("MetisMISO::~MetisMISO");
|
||||
QObject::disconnect(
|
||||
m_networkManager,
|
||||
&QNetworkAccessManager::finished,
|
||||
@ -77,6 +78,7 @@ MetisMISO::~MetisMISO()
|
||||
if (m_running) {
|
||||
stopRx();
|
||||
}
|
||||
qDebug("MetisMISO::~MetisMISO: end");
|
||||
}
|
||||
|
||||
void MetisMISO::destroy()
|
||||
@ -155,6 +157,7 @@ void MetisMISO::startMetis()
|
||||
|
||||
void MetisMISO::stopMetis()
|
||||
{
|
||||
qDebug("MetisMISO::stopMetis");
|
||||
MetisMISOUDPHandler::MsgStartStop *message = MetisMISOUDPHandler::MsgStartStop::create(false);
|
||||
m_udpHandler.getInputMessageQueue()->push(message);
|
||||
}
|
||||
|
@ -168,7 +168,11 @@ void PlutoSDRMIMO::init()
|
||||
|
||||
bool PlutoSDRMIMO::startRx()
|
||||
{
|
||||
qDebug("PlutoSDRMIMO::startRx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningRx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_open)
|
||||
{
|
||||
@ -176,11 +180,7 @@ bool PlutoSDRMIMO::startRx()
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningRx) {
|
||||
stopRx();
|
||||
}
|
||||
qDebug("PlutoSDRMIMO::startRx");
|
||||
|
||||
m_sourceThread = new PlutoSDRMIThread(m_plutoParams->getBox());
|
||||
m_sampleMIFifo.reset();
|
||||
@ -206,7 +206,11 @@ bool PlutoSDRMIMO::startRx()
|
||||
|
||||
bool PlutoSDRMIMO::startTx()
|
||||
{
|
||||
qDebug("PlutoSDRMIMO::startTx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningTx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_open)
|
||||
{
|
||||
@ -214,11 +218,7 @@ bool PlutoSDRMIMO::startTx()
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningTx) {
|
||||
stopTx();
|
||||
}
|
||||
qDebug("PlutoSDRMIMO::startTx");
|
||||
|
||||
m_sinkThread = new PlutoSDRMOThread(m_plutoParams->getBox());
|
||||
m_sampleMOFifo.reset();
|
||||
@ -243,18 +243,22 @@ bool PlutoSDRMIMO::startTx()
|
||||
|
||||
void PlutoSDRMIMO::stopRx()
|
||||
{
|
||||
qDebug("PlutoSDRMIMO::stopRx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_runningRx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sourceThread) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug("PlutoSDRMIMO::stopRx");
|
||||
m_runningRx = false;
|
||||
|
||||
m_sourceThread->stopWork();
|
||||
delete m_sourceThread;
|
||||
m_sourceThread = nullptr;
|
||||
m_runningRx = false;
|
||||
|
||||
if (m_nbRx > 1) {
|
||||
m_plutoParams->getBox()->closeSecondRx();
|
||||
@ -270,18 +274,22 @@ void PlutoSDRMIMO::stopRx()
|
||||
|
||||
void PlutoSDRMIMO::stopTx()
|
||||
{
|
||||
qDebug("PlutoSDRMIMO::stopTx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_runningTx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sinkThread) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug("PlutoSDRMIMO::stopTx");
|
||||
m_runningTx = false;
|
||||
|
||||
m_sinkThread->stopWork();
|
||||
delete m_sinkThread;
|
||||
m_sinkThread = nullptr;
|
||||
m_runningTx = false;
|
||||
|
||||
if (m_nbTx > 1) {
|
||||
m_plutoParams->getBox()->closeSecondTx();
|
||||
|
@ -127,7 +127,7 @@ void TestMI::stopRx()
|
||||
}
|
||||
|
||||
qDebug("TestMI::stopRx");
|
||||
m_running = false;
|
||||
m_running = false;
|
||||
stopWorkers();
|
||||
|
||||
m_testSourceWorkers.clear();
|
||||
|
@ -124,7 +124,11 @@ void XTRXMIMO::init()
|
||||
|
||||
bool XTRXMIMO::startRx()
|
||||
{
|
||||
qDebug("XTRXMIMO::startRx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningRx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_open)
|
||||
{
|
||||
@ -132,11 +136,7 @@ bool XTRXMIMO::startRx()
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningRx) {
|
||||
stopRx();
|
||||
}
|
||||
qDebug("XTRXMIMO::startRx");
|
||||
|
||||
m_sourceThread = new XTRXMIThread(m_deviceShared.m_dev->getDevice());
|
||||
m_sampleMIFifo.reset();
|
||||
@ -152,7 +152,11 @@ bool XTRXMIMO::startRx()
|
||||
|
||||
bool XTRXMIMO::startTx()
|
||||
{
|
||||
qDebug("XTRXMIMO::startTx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningTx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_open)
|
||||
{
|
||||
@ -160,11 +164,7 @@ bool XTRXMIMO::startTx()
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_runningRx) {
|
||||
stopRx();
|
||||
}
|
||||
qDebug("XTRXMIMO::startTx");
|
||||
|
||||
m_sinkThread = new XTRXMOThread(m_deviceShared.m_dev->getDevice());
|
||||
m_sampleMOFifo.reset();
|
||||
@ -179,34 +179,42 @@ bool XTRXMIMO::startTx()
|
||||
|
||||
void XTRXMIMO::stopRx()
|
||||
{
|
||||
qDebug("XTRXMIMO::stopRx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_runningRx){
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sourceThread) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug("XTRXMIMO::stopRx");
|
||||
m_runningRx = false;
|
||||
|
||||
m_sourceThread->stopWork();
|
||||
delete m_sourceThread;
|
||||
m_sourceThread = nullptr;
|
||||
m_runningRx = false;
|
||||
}
|
||||
|
||||
void XTRXMIMO::stopTx()
|
||||
{
|
||||
qDebug("XTRXMIMO::stopTx");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_runningTx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sinkThread) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug("XTRXMIMO::stopTx");
|
||||
m_runningTx = false;
|
||||
|
||||
m_sinkThread->stopWork();
|
||||
delete m_sinkThread;
|
||||
m_sinkThread = nullptr;
|
||||
m_runningTx = false;
|
||||
}
|
||||
|
||||
QByteArray XTRXMIMO::serialize() const
|
||||
|
@ -68,11 +68,11 @@ Bladerf1Output::~Bladerf1Output()
|
||||
delete m_networkManager;
|
||||
|
||||
if (m_running) {
|
||||
stop();
|
||||
Bladerf1Output::stop();
|
||||
}
|
||||
|
||||
closeDevice();
|
||||
m_deviceAPI->setBuddySharedPtr(0);
|
||||
m_deviceAPI->setBuddySharedPtr(nullptr);
|
||||
}
|
||||
|
||||
void Bladerf1Output::destroy()
|
||||
@ -82,7 +82,7 @@ void Bladerf1Output::destroy()
|
||||
|
||||
bool Bladerf1Output::openDevice()
|
||||
{
|
||||
if (m_dev != 0) {
|
||||
if (m_dev != nullptr) {
|
||||
closeDevice();
|
||||
}
|
||||
|
||||
@ -90,24 +90,24 @@ bool Bladerf1Output::openDevice()
|
||||
|
||||
m_sampleSourceFifo.resize(SampleSourceFifo::getSizePolicy(m_settings.m_devSampleRate));
|
||||
|
||||
if (m_deviceAPI->getSourceBuddies().size() > 0)
|
||||
if (!m_deviceAPI->getSourceBuddies().empty())
|
||||
{
|
||||
DeviceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0];
|
||||
DeviceBladeRF1Params *buddySharedParams = (DeviceBladeRF1Params *) sourceBuddy->getBuddySharedPtr();
|
||||
const DeviceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0];
|
||||
const DeviceBladeRF1Params *buddySharedParams = (DeviceBladeRF1Params *) sourceBuddy->getBuddySharedPtr();
|
||||
|
||||
if (buddySharedParams == 0)
|
||||
if (buddySharedParams == nullptr)
|
||||
{
|
||||
qCritical("BladerfOutput::start: could not get shared parameters from buddy");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buddySharedParams->m_dev == 0) // device is not opened by buddy
|
||||
if (buddySharedParams->m_dev == nullptr) // device is not opened by buddy
|
||||
{
|
||||
qCritical("BladerfOutput::start: could not get BladeRF handle from buddy");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sharedParams = *(buddySharedParams); // copy parameters from buddy
|
||||
m_sharedParams = *buddySharedParams; // copy parameters from buddy
|
||||
m_dev = m_sharedParams.m_dev; // get BladeRF handle
|
||||
}
|
||||
else
|
||||
@ -121,7 +121,6 @@ bool Bladerf1Output::openDevice()
|
||||
m_sharedParams.m_dev = m_dev;
|
||||
}
|
||||
|
||||
// TODO: adjust USB transfer data according to sample rate
|
||||
if ((res = bladerf_sync_config(m_dev, BLADERF_TX_X1, BLADERF_FORMAT_SC16_Q11, 64, 8192, 32, 10000)) < 0)
|
||||
{
|
||||
qCritical("BladerfOutput::start: bladerf_sync_config with return code %d", res);
|
||||
@ -144,25 +143,24 @@ void Bladerf1Output::init()
|
||||
|
||||
bool Bladerf1Output::start()
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) stop();
|
||||
|
||||
m_bladerfThread = new Bladerf1OutputThread(m_dev, &m_sampleSourceFifo);
|
||||
|
||||
// mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
m_bladerfThread->setLog2Interpolation(m_settings.m_log2Interp);
|
||||
|
||||
m_bladerfThread->startWork();
|
||||
|
||||
qDebug("BladerfOutput::start: started");
|
||||
m_running = true;
|
||||
mutexLocker.unlock();
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -171,7 +169,7 @@ void Bladerf1Output::closeDevice()
|
||||
{
|
||||
int res;
|
||||
|
||||
if (m_dev == 0) { // was never open
|
||||
if (m_dev == nullptr) { // was never open
|
||||
return;
|
||||
}
|
||||
|
||||
@ -180,31 +178,36 @@ void Bladerf1Output::closeDevice()
|
||||
qCritical("BladerfOutput::closeDevice: bladerf_enable_module with return code %d", res);
|
||||
}
|
||||
|
||||
if (m_deviceAPI->getSourceBuddies().size() == 0)
|
||||
if (m_deviceAPI->getSourceBuddies().empty())
|
||||
{
|
||||
qDebug("BladerfOutput::closeDevice: closing device since Rx side is not open");
|
||||
|
||||
if (m_dev != 0) // close BladeRF
|
||||
if (m_dev != nullptr) // close BladeRF
|
||||
{
|
||||
bladerf_close(m_dev);
|
||||
}
|
||||
}
|
||||
|
||||
m_sharedParams.m_dev = 0;
|
||||
m_dev = 0;
|
||||
m_sharedParams.m_dev = nullptr;
|
||||
m_dev = nullptr;
|
||||
}
|
||||
|
||||
void Bladerf1Output::stop()
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
if (m_bladerfThread != 0)
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
|
||||
if (m_bladerfThread)
|
||||
{
|
||||
m_bladerfThread->stopWork();
|
||||
delete m_bladerfThread;
|
||||
m_bladerfThread = 0;
|
||||
m_bladerfThread = nullptr;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray Bladerf1Output::serialize() const
|
||||
@ -269,7 +272,7 @@ bool Bladerf1Output::handleMessage(const Message& message)
|
||||
{
|
||||
if (MsgConfigureBladerf1::match(message))
|
||||
{
|
||||
MsgConfigureBladerf1& conf = (MsgConfigureBladerf1&) message;
|
||||
auto& conf = (const MsgConfigureBladerf1&) message;
|
||||
qDebug() << "BladerfOutput::handleMessage: MsgConfigureBladerf";
|
||||
|
||||
if (!applySettings(conf.getSettings(), conf.getSettingsKeys(), conf.getForce())) {
|
||||
@ -280,7 +283,7 @@ bool Bladerf1Output::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgStartStop::match(message))
|
||||
{
|
||||
MsgStartStop& cmd = (MsgStartStop&) message;
|
||||
auto& cmd = (const MsgStartStop&) message;
|
||||
qDebug() << "BladerfOutput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
|
||||
|
||||
if (cmd.getStartStop())
|
||||
@ -312,7 +315,7 @@ bool Bladerf1Output::applySettings(const BladeRF1OutputSettings& settings, const
|
||||
bool forwardChange = false;
|
||||
bool suspendOwnThread = false;
|
||||
bool threadWasRunning = false;
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (settingsKeys.contains("devSampleRate") ||
|
||||
settingsKeys.contains("log2Interp") || force)
|
||||
@ -320,16 +323,10 @@ bool Bladerf1Output::applySettings(const BladeRF1OutputSettings& settings, const
|
||||
suspendOwnThread = true;
|
||||
}
|
||||
|
||||
if (suspendOwnThread)
|
||||
if (suspendOwnThread && m_bladerfThread && m_bladerfThread->isRunning())
|
||||
{
|
||||
if (m_bladerfThread)
|
||||
{
|
||||
if (m_bladerfThread->isRunning())
|
||||
{
|
||||
m_bladerfThread->stopWork();
|
||||
threadWasRunning = true;
|
||||
}
|
||||
}
|
||||
m_bladerfThread->stopWork();
|
||||
threadWasRunning = true;
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("devSampleRate") ||
|
||||
@ -350,7 +347,7 @@ bool Bladerf1Output::applySettings(const BladeRF1OutputSettings& settings, const
|
||||
{
|
||||
forwardChange = true;
|
||||
|
||||
if (m_dev != 0)
|
||||
if (m_dev != nullptr)
|
||||
{
|
||||
unsigned int actualSamplerate;
|
||||
|
||||
@ -366,129 +363,108 @@ bool Bladerf1Output::applySettings(const BladeRF1OutputSettings& settings, const
|
||||
{
|
||||
forwardChange = true;
|
||||
|
||||
if (m_bladerfThread != 0)
|
||||
if (m_bladerfThread != nullptr)
|
||||
{
|
||||
m_bladerfThread->setLog2Interpolation(settings.m_log2Interp);
|
||||
qDebug() << "BladerfOutput::applySettings: set interpolation to " << (1<<settings.m_log2Interp);
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("vga1") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("vga1") || force))
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if (bladerf_set_txvga1(m_dev, settings.m_vga1) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_set_txvga1() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: VGA1 gain set to " << settings.m_vga1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("vga2") || force)
|
||||
{
|
||||
if(m_dev != 0)
|
||||
{
|
||||
if (bladerf_set_txvga2(m_dev, settings.m_vga2) != 0) {
|
||||
qDebug("BladerfOutput::applySettings:bladerf_set_rxvga2() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: VGA2 gain set to " << settings.m_vga2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("xb200") || force)
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
bool changeSettings;
|
||||
|
||||
if (m_deviceAPI->getSourceBuddies().size() > 0)
|
||||
{
|
||||
DeviceAPI *buddy = m_deviceAPI->getSourceBuddies()[0];
|
||||
|
||||
if (buddy->getDeviceSourceEngine()->state() == DSPDeviceSourceEngine::StRunning) { // Tx side running
|
||||
changeSettings = false;
|
||||
} else {
|
||||
changeSettings = true;
|
||||
}
|
||||
}
|
||||
else // No Rx open
|
||||
{
|
||||
changeSettings = true;
|
||||
}
|
||||
|
||||
if (changeSettings)
|
||||
{
|
||||
if (settings.m_xb200)
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_expansion_attach(xb200) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: Attach XB200";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_NONE) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_expansion_attach(none) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: Detach XB200";
|
||||
}
|
||||
}
|
||||
|
||||
m_sharedParams.m_xb200Attached = settings.m_xb200;
|
||||
}
|
||||
if (bladerf_set_txvga1(m_dev, settings.m_vga1) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_set_txvga1() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: VGA1 gain set to " << settings.m_vga1;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("xb200Path") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("vga2") || force))
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if (bladerf_xb200_set_path(m_dev, BLADERF_MODULE_TX, settings.m_xb200Path) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_xb200_set_path(BLADERF_MODULE_TX) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: set xb200 path to " << settings.m_xb200Path;
|
||||
}
|
||||
}
|
||||
if (bladerf_set_txvga2(m_dev, settings.m_vga2) != 0) {
|
||||
qDebug("BladerfOutput::applySettings:bladerf_set_rxvga2() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: VGA2 gain set to " << settings.m_vga2;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("xb200Filter") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("xb200") || force))
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if (bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_TX, settings.m_xb200Filter) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_xb200_set_filterbank(BLADERF_MODULE_TX) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: set xb200 filter to " << settings.m_xb200Filter;
|
||||
}
|
||||
}
|
||||
bool changeSettings;
|
||||
|
||||
if (!m_deviceAPI->getSourceBuddies().empty())
|
||||
{
|
||||
DeviceAPI *buddy = m_deviceAPI->getSourceBuddies()[0];
|
||||
|
||||
if (buddy->getDeviceSourceEngine()->state() == DSPDeviceSourceEngine::State::StRunning) { // Tx side running
|
||||
changeSettings = false;
|
||||
} else {
|
||||
changeSettings = true;
|
||||
}
|
||||
}
|
||||
else // No Rx open
|
||||
{
|
||||
changeSettings = true;
|
||||
}
|
||||
|
||||
if (changeSettings)
|
||||
{
|
||||
if (settings.m_xb200)
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_expansion_attach(xb200) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: Attach XB200";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_NONE) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_expansion_attach(none) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: Detach XB200";
|
||||
}
|
||||
}
|
||||
|
||||
m_sharedParams.m_xb200Attached = settings.m_xb200;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("bandwidth") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("xb200Path") || force))
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
unsigned int actualBandwidth;
|
||||
if (bladerf_xb200_set_path(m_dev, BLADERF_MODULE_TX, settings.m_xb200Path) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_xb200_set_path(BLADERF_MODULE_TX) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: set xb200 path to " << settings.m_xb200Path;
|
||||
}
|
||||
}
|
||||
|
||||
if (bladerf_set_bandwidth(m_dev, BLADERF_MODULE_TX, settings.m_bandwidth, &actualBandwidth) < 0) {
|
||||
qCritical("BladerfOutput::applySettings: could not set bandwidth: %d", settings.m_bandwidth);
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: bladerf_set_bandwidth(BLADERF_MODULE_TX) actual bandwidth is " << actualBandwidth;
|
||||
}
|
||||
}
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("xb200Filter") || force))
|
||||
{
|
||||
if (bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_TX, settings.m_xb200Filter) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_xb200_set_filterbank(BLADERF_MODULE_TX) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: set xb200 filter to " << settings.m_xb200Filter;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("bandwidth") || force))
|
||||
{
|
||||
unsigned int actualBandwidth;
|
||||
|
||||
if (bladerf_set_bandwidth(m_dev, BLADERF_MODULE_TX, settings.m_bandwidth, &actualBandwidth) < 0) {
|
||||
qCritical("BladerfOutput::applySettings: could not set bandwidth: %d", settings.m_bandwidth);
|
||||
} else {
|
||||
qDebug() << "BladerfOutput::applySettings: bladerf_set_bandwidth(BLADERF_MODULE_TX) actual bandwidth is " << actualBandwidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("centerFrequency"))
|
||||
{
|
||||
forwardChange = true;
|
||||
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if (bladerf_set_frequency( m_dev, BLADERF_MODULE_TX, settings.m_centerFrequency ) != 0) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_set_frequency(%lld) failed", settings.m_centerFrequency);
|
||||
}
|
||||
if ((m_dev != nullptr) && (bladerf_set_frequency( m_dev, BLADERF_MODULE_TX, settings.m_centerFrequency ) != 0)) {
|
||||
qDebug("BladerfOutput::applySettings: bladerf_set_frequency(%lld) failed", settings.m_centerFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
@ -515,7 +491,7 @@ bool Bladerf1Output::applySettings(const BladeRF1OutputSettings& settings, const
|
||||
if (forwardChange)
|
||||
{
|
||||
int sampleRate = m_settings.m_devSampleRate/(1<<m_settings.m_log2Interp);
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, m_settings.m_centerFrequency);
|
||||
auto *notif = new DSPSignalNotification(sampleRate, m_settings.m_centerFrequency);
|
||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||
}
|
||||
|
||||
@ -604,7 +580,7 @@ void Bladerf1Output::webapiUpdateDeviceSettings(
|
||||
settings.m_log2Interp = response.getBladeRf1OutputSettings()->getLog2Interp();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("xb200")) {
|
||||
settings.m_xb200 = response.getBladeRf1OutputSettings()->getXb200() == 0 ? 0 : 1;
|
||||
settings.m_xb200 = response.getBladeRf1OutputSettings()->getXb200() == 0 ? false : true;
|
||||
}
|
||||
if (deviceSettingsKeys.contains("xb200Path")) {
|
||||
settings.m_xb200Path = static_cast<bladerf_xb200_path>(response.getBladeRf1OutputSettings()->getXb200Path());
|
||||
@ -619,10 +595,10 @@ void Bladerf1Output::webapiUpdateDeviceSettings(
|
||||
settings.m_reverseAPIAddress = *response.getBladeRf1OutputSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getBladeRf1OutputSettings()->getReverseApiPort();
|
||||
settings.m_reverseAPIPort = (uint16_t) response.getBladeRf1OutputSettings()->getReverseApiPort();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getBladeRf1OutputSettings()->getReverseApiDeviceIndex();
|
||||
settings.m_reverseAPIDeviceIndex = (uint16_t) response.getBladeRf1OutputSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
}
|
||||
|
||||
@ -656,7 +632,7 @@ int Bladerf1Output::webapiRun(
|
||||
|
||||
void Bladerf1Output::webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const BladeRF1OutputSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(1); // single Tx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("BladeRF1"));
|
||||
@ -700,8 +676,8 @@ void Bladerf1Output::webapiReverseSendSettings(const QList<QString>& deviceSetti
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -714,7 +690,7 @@ void Bladerf1Output::webapiReverseSendSettings(const QList<QString>& deviceSetti
|
||||
|
||||
void Bladerf1Output::webapiReverseSendStartStop(bool start)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(1); // single Tx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("BladeRF1"));
|
||||
@ -726,8 +702,8 @@ void Bladerf1Output::webapiReverseSendStartStop(bool start)
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
QNetworkReply *reply;
|
||||
@ -742,7 +718,7 @@ void Bladerf1Output::webapiReverseSendStartStop(bool start)
|
||||
delete swgDeviceSettings;
|
||||
}
|
||||
|
||||
void Bladerf1Output::networkManagerFinished(QNetworkReply *reply)
|
||||
void Bladerf1Output::networkManagerFinished(QNetworkReply *reply) const
|
||||
{
|
||||
QNetworkReply::NetworkError replyError = reply->error();
|
||||
|
||||
|
@ -74,10 +74,10 @@ public:
|
||||
return new MsgStartStop(startStop);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool m_startStop;
|
||||
|
||||
MsgStartStop(bool startStop) :
|
||||
explicit MsgStartStop(bool startStop) :
|
||||
Message(),
|
||||
m_startStop(startStop)
|
||||
{ }
|
||||
@ -100,57 +100,57 @@ public:
|
||||
{ }
|
||||
};
|
||||
|
||||
Bladerf1Output(DeviceAPI *deviceAPI);
|
||||
virtual ~Bladerf1Output();
|
||||
virtual void destroy();
|
||||
explicit Bladerf1Output(DeviceAPI *deviceAPI);
|
||||
~Bladerf1Output() final;
|
||||
void destroy() final;
|
||||
|
||||
virtual void init();
|
||||
virtual bool start();
|
||||
virtual void stop();
|
||||
void init() final;
|
||||
bool start() final;
|
||||
void stop() final;
|
||||
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
QByteArray serialize() const final;
|
||||
bool deserialize(const QByteArray& data) final;
|
||||
|
||||
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
|
||||
virtual const QString& getDeviceDescription() const;
|
||||
virtual int getSampleRate() const;
|
||||
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
|
||||
virtual quint64 getCenterFrequency() const;
|
||||
virtual void setCenterFrequency(qint64 centerFrequency);
|
||||
void setMessageQueueToGUI(MessageQueue *queue) final { m_guiMessageQueue = queue; }
|
||||
const QString& getDeviceDescription() const final;
|
||||
int getSampleRate() const final;
|
||||
void setSampleRate(int sampleRate) final { (void) sampleRate; }
|
||||
quint64 getCenterFrequency() const final;
|
||||
void setCenterFrequency(qint64 centerFrequency) final;
|
||||
|
||||
virtual bool handleMessage(const Message& message);
|
||||
bool handleMessage(const Message& message) final;
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage);
|
||||
int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage);
|
||||
int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
static void webapiFormatDeviceSettings(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
const BladeRF1OutputSettings& settings);
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
const BladeRF1OutputSettings& settings);
|
||||
|
||||
static void webapiUpdateDeviceSettings(
|
||||
BladeRF1OutputSettings& settings,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response);
|
||||
BladeRF1OutputSettings& settings,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response);
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
QRecursiveMutex m_mutex;
|
||||
BladeRF1OutputSettings m_settings;
|
||||
struct bladerf* m_dev;
|
||||
Bladerf1OutputThread* m_bladerfThread;
|
||||
@ -167,7 +167,7 @@ private:
|
||||
void webapiReverseSendStartStop(bool start);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void networkManagerFinished(QNetworkReply *reply) const;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_BLADERFOUTPUT_H
|
||||
|
@ -399,14 +399,14 @@ void BladeRF2Output::stop()
|
||||
qDebug("BladeRF2Output::stop: SO mode. Just stop and delete the thread");
|
||||
bladeRF2OutputThread->stopWork();
|
||||
delete bladeRF2OutputThread;
|
||||
m_thread = 0;
|
||||
m_thread = nullptr;
|
||||
|
||||
// remove old thread address from buddies (reset in all buddies)
|
||||
const std::vector<DeviceAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
|
||||
std::vector<DeviceAPI*>::const_iterator it = sinkBuddies.begin();
|
||||
|
||||
for (; it != sinkBuddies.end(); ++it) {
|
||||
((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_sink->setThread(0);
|
||||
((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_sink->setThread(nullptr);
|
||||
}
|
||||
|
||||
m_deviceShared.m_dev->closeTx(0); // close the unique channel
|
||||
@ -422,7 +422,7 @@ void BladeRF2Output::stop()
|
||||
for (int i = 0; i < nbOriginalChannels-1; i++) // save original FIFO references
|
||||
{
|
||||
fifos[i] = bladeRF2OutputThread->getFifo(i);
|
||||
stillActiveFIFO = stillActiveFIFO || (bladeRF2OutputThread->getFifo(i) != 0);
|
||||
stillActiveFIFO = stillActiveFIFO || (bladeRF2OutputThread->getFifo(i) != nullptr);
|
||||
log2Interps[i] = bladeRF2OutputThread->getLog2Interpolation(i);
|
||||
}
|
||||
|
||||
@ -450,7 +450,7 @@ void BladeRF2Output::stop()
|
||||
std::vector<DeviceAPI*>::const_iterator it = sinkBuddies.begin();
|
||||
|
||||
for (; it != sinkBuddies.end(); ++it) {
|
||||
((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_sink->setThread(0);
|
||||
((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_sink->setThread(nullptr);
|
||||
}
|
||||
|
||||
// close all channels
|
||||
@ -479,11 +479,9 @@ void BladeRF2Output::stop()
|
||||
else // remove channel from existing thread
|
||||
{
|
||||
qDebug("BladeRF2Output::stop: MO mode. Not changing MO configuration. Just remove FIFO reference");
|
||||
bladeRF2OutputThread->setFifo(requestedChannel, 0); // remove FIFO
|
||||
bladeRF2OutputThread->setFifo(requestedChannel, nullptr); // remove FIFO
|
||||
}
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true); // re-apply forcibly to set sample rate with the new number of channels
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
|
@ -45,9 +45,7 @@ MESSAGE_CLASS_DEFINITION(FileOutput::MsgReportFileOutputStreamTiming, Message)
|
||||
FileOutput::FileOutput(DeviceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_settings(),
|
||||
m_fileOutputWorker(nullptr),
|
||||
m_deviceDescription("FileOutput"),
|
||||
m_startingTimeStamp(0),
|
||||
m_masterTimer(deviceAPI->getMasterTimer())
|
||||
{
|
||||
m_deviceAPI->setNbSinkStreams(1);
|
||||
@ -57,7 +55,7 @@ FileOutput::FileOutput(DeviceAPI *deviceAPI) :
|
||||
FileOutput::~FileOutput()
|
||||
{
|
||||
delete m_networkManager;
|
||||
stop();
|
||||
FileOutput::stop();
|
||||
}
|
||||
|
||||
void FileOutput::destroy()
|
||||
@ -74,7 +72,7 @@ void FileOutput::openFileStream()
|
||||
m_ofstream.open(m_settings.m_fileName.toStdString().c_str(), std::ios::binary);
|
||||
|
||||
FileRecord::Header header;
|
||||
int actualSampleRate = m_settings.m_sampleRate * (1<<m_settings.m_log2Interp);
|
||||
auto actualSampleRate = (int) (m_settings.m_sampleRate * (1<<m_settings.m_log2Interp));
|
||||
header.sampleRate = actualSampleRate;
|
||||
header.centerFrequency = m_settings.m_centerFrequency;
|
||||
m_startingTimeStamp = QDateTime::currentMSecsSinceEpoch();
|
||||
@ -94,19 +92,24 @@ void FileOutput::init()
|
||||
bool FileOutput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebug() << "FileOutput::start";
|
||||
|
||||
openFileStream();
|
||||
|
||||
m_fileOutputWorker = new FileOutputWorker(&m_ofstream, &m_sampleSourceFifo);
|
||||
m_fileOutputWorker->moveToThread(&m_fileOutputWorkerThread);
|
||||
m_fileOutputWorker->setSamplerate(m_settings.m_sampleRate);
|
||||
m_fileOutputWorker->setSamplerate((int) m_settings.m_sampleRate);
|
||||
m_fileOutputWorker->setLog2Interpolation(m_settings.m_log2Interp);
|
||||
m_fileOutputWorker->connectTimer(m_masterTimer);
|
||||
startWorker();
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
//applySettings(m_generalSettings, m_settings, true);
|
||||
qDebug("FileOutput::start: started");
|
||||
|
||||
if (getMessageQueueToGUI())
|
||||
@ -120,9 +123,15 @@ bool FileOutput::start()
|
||||
|
||||
void FileOutput::stop()
|
||||
{
|
||||
qDebug() << "FileSourceInput::stop";
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "FileSourceInput::stop";
|
||||
m_running = false;
|
||||
|
||||
if (m_fileOutputWorker)
|
||||
{
|
||||
stopWorker();
|
||||
@ -188,7 +197,7 @@ const QString& FileOutput::getDeviceDescription() const
|
||||
|
||||
int FileOutput::getSampleRate() const
|
||||
{
|
||||
return m_settings.m_sampleRate;
|
||||
return (int) m_settings.m_sampleRate;
|
||||
}
|
||||
|
||||
quint64 FileOutput::getCenterFrequency() const
|
||||
@ -220,14 +229,14 @@ bool FileOutput::handleMessage(const Message& message)
|
||||
{
|
||||
if (MsgConfigureFileOutputName::match(message))
|
||||
{
|
||||
MsgConfigureFileOutputName& conf = (MsgConfigureFileOutputName&) message;
|
||||
auto& conf = (const MsgConfigureFileOutputName&) message;
|
||||
m_settings.m_fileName = conf.getFileName();
|
||||
openFileStream();
|
||||
return true;
|
||||
}
|
||||
else if (MsgStartStop::match(message))
|
||||
{
|
||||
MsgStartStop& cmd = (MsgStartStop&) message;
|
||||
auto& cmd = (const MsgStartStop&) message;
|
||||
qDebug() << "FileOutput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
|
||||
|
||||
if (cmd.getStartStop())
|
||||
@ -249,17 +258,17 @@ bool FileOutput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgConfigureFileOutput::match(message))
|
||||
{
|
||||
qDebug() << "FileOutput::handleMessage: MsgConfigureFileOutput";
|
||||
MsgConfigureFileOutput& conf = (MsgConfigureFileOutput&) message;
|
||||
qDebug() << "FileOutput::handleMessage: MsgConfigureFileOutput";
|
||||
auto& conf = (const MsgConfigureFileOutput&) message;
|
||||
applySettings(conf.getSettings(), conf.getSettingsKeys(), conf.getForce());
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileOutputWork::match(message))
|
||||
{
|
||||
MsgConfigureFileOutputWork& conf = (MsgConfigureFileOutputWork&) message;
|
||||
auto& conf = (const MsgConfigureFileOutputWork&) message;
|
||||
bool working = conf.isWorking();
|
||||
|
||||
if (m_fileOutputWorker != 0)
|
||||
if (m_fileOutputWorker != nullptr)
|
||||
{
|
||||
if (working) {
|
||||
startWorker();
|
||||
@ -272,11 +281,9 @@ bool FileOutput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgConfigureFileOutputStreamTiming::match(message))
|
||||
{
|
||||
MsgReportFileOutputStreamTiming *report;
|
||||
|
||||
if (m_fileOutputWorker != 0 && getMessageQueueToGUI())
|
||||
if (m_fileOutputWorker != nullptr && getMessageQueueToGUI())
|
||||
{
|
||||
report = MsgReportFileOutputStreamTiming::create(m_fileOutputWorker->getSamplesCount());
|
||||
auto *report = MsgReportFileOutputStreamTiming::create(m_fileOutputWorker->getSamplesCount());
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
|
||||
@ -301,8 +308,8 @@ void FileOutput::applySettings(const FileOutputSettings& settings, const QList<Q
|
||||
|
||||
if (force || settingsKeys.contains("sampleRate"))
|
||||
{
|
||||
if (m_fileOutputWorker != 0) {
|
||||
m_fileOutputWorker->setSamplerate(settings.m_sampleRate);
|
||||
if (m_fileOutputWorker != nullptr) {
|
||||
m_fileOutputWorker->setSamplerate((int) settings.m_sampleRate);
|
||||
}
|
||||
|
||||
forwardChange = true;
|
||||
@ -310,7 +317,7 @@ void FileOutput::applySettings(const FileOutputSettings& settings, const QList<Q
|
||||
|
||||
if (force || settingsKeys.contains("log2Interp"))
|
||||
{
|
||||
if (m_fileOutputWorker != 0) {
|
||||
if (m_fileOutputWorker != nullptr) {
|
||||
m_fileOutputWorker->setLog2Interpolation(settings.m_log2Interp);
|
||||
}
|
||||
|
||||
@ -338,7 +345,7 @@ void FileOutput::applySettings(const FileOutputSettings& settings, const QList<Q
|
||||
m_settings.m_centerFrequency,
|
||||
m_settings.m_sampleRate,
|
||||
m_settings.m_log2Interp);
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(m_settings.m_sampleRate, m_settings.m_centerFrequency);
|
||||
auto *notif = new DSPSignalNotification((int) m_settings.m_sampleRate, m_settings.m_centerFrequency);
|
||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||
}
|
||||
}
|
||||
@ -448,16 +455,16 @@ void FileOutput::webapiUpdateDeviceSettings(
|
||||
settings.m_reverseAPIAddress = *response.getFileOutputSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getFileOutputSettings()->getReverseApiPort();
|
||||
settings.m_reverseAPIPort = (uint16_t) response.getFileOutputSettings()->getReverseApiPort();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getFileOutputSettings()->getReverseApiDeviceIndex();
|
||||
settings.m_reverseAPIDeviceIndex = (uint16_t) response.getFileOutputSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
}
|
||||
|
||||
void FileOutput::webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const FileOutputSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(1); // single Tx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("FileOutput"));
|
||||
@ -486,8 +493,8 @@ void FileOutput::webapiReverseSendSettings(const QList<QString>& deviceSettingsK
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -500,7 +507,7 @@ void FileOutput::webapiReverseSendSettings(const QList<QString>& deviceSettingsK
|
||||
|
||||
void FileOutput::webapiReverseSendStartStop(bool start)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(1); // single Tx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("FileOutput"));
|
||||
@ -512,8 +519,8 @@ void FileOutput::webapiReverseSendStartStop(bool start)
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
QNetworkReply *reply;
|
||||
@ -528,7 +535,7 @@ void FileOutput::webapiReverseSendStartStop(bool start)
|
||||
delete swgDeviceSettings;
|
||||
}
|
||||
|
||||
void FileOutput::networkManagerFinished(QNetworkReply *reply)
|
||||
void FileOutput::networkManagerFinished(QNetworkReply *reply) const
|
||||
{
|
||||
QNetworkReply::NetworkError replyError = reply->error();
|
||||
|
||||
|
@ -76,10 +76,10 @@ public:
|
||||
return new MsgStartStop(startStop);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool m_startStop;
|
||||
|
||||
MsgStartStop(bool startStop) :
|
||||
explicit MsgStartStop(bool startStop) :
|
||||
Message(),
|
||||
m_startStop(startStop)
|
||||
{ }
|
||||
@ -99,7 +99,7 @@ public:
|
||||
private:
|
||||
QString m_fileName;
|
||||
|
||||
MsgConfigureFileOutputName(const QString& fileName) :
|
||||
explicit MsgConfigureFileOutputName(const QString& fileName) :
|
||||
Message(),
|
||||
m_fileName(fileName)
|
||||
{ }
|
||||
@ -119,7 +119,7 @@ public:
|
||||
private:
|
||||
bool m_working;
|
||||
|
||||
MsgConfigureFileOutputWork(bool working) :
|
||||
explicit MsgConfigureFileOutputWork(bool working) :
|
||||
Message(),
|
||||
m_working(working)
|
||||
{ }
|
||||
@ -153,10 +153,10 @@ public:
|
||||
return new MsgReportFileOutputGeneration(acquisition);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool m_acquisition;
|
||||
|
||||
MsgReportFileOutputGeneration(bool acquisition) :
|
||||
explicit MsgReportFileOutputGeneration(bool acquisition) :
|
||||
Message(),
|
||||
m_acquisition(acquisition)
|
||||
{ }
|
||||
@ -173,54 +173,54 @@ public:
|
||||
return new MsgReportFileOutputStreamTiming(samplesCount);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::size_t m_samplesCount;
|
||||
|
||||
MsgReportFileOutputStreamTiming(std::size_t samplesCount) :
|
||||
explicit MsgReportFileOutputStreamTiming(std::size_t samplesCount) :
|
||||
Message(),
|
||||
m_samplesCount(samplesCount)
|
||||
{ }
|
||||
};
|
||||
|
||||
FileOutput(DeviceAPI *deviceAPI);
|
||||
virtual ~FileOutput();
|
||||
virtual void destroy();
|
||||
explicit FileOutput(DeviceAPI *deviceAPI);
|
||||
~FileOutput() final;
|
||||
void destroy() final;
|
||||
|
||||
virtual void init();
|
||||
virtual bool start();
|
||||
virtual void stop();
|
||||
void init() final;
|
||||
bool start() final;
|
||||
void stop() final;
|
||||
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
QByteArray serialize() const final;
|
||||
bool deserialize(const QByteArray& data) final;
|
||||
|
||||
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
|
||||
virtual const QString& getDeviceDescription() const;
|
||||
virtual int getSampleRate() const;
|
||||
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
|
||||
virtual quint64 getCenterFrequency() const;
|
||||
virtual void setCenterFrequency(qint64 centerFrequency);
|
||||
void setMessageQueueToGUI(MessageQueue *queue) final { m_guiMessageQueue = queue; }
|
||||
const QString& getDeviceDescription() const final;
|
||||
int getSampleRate() const final;
|
||||
void setSampleRate(int sampleRate) final { (void) sampleRate; }
|
||||
quint64 getCenterFrequency() const final;
|
||||
void setCenterFrequency(qint64 centerFrequency) final;
|
||||
std::time_t getStartingTimeStamp() const;
|
||||
|
||||
virtual bool handleMessage(const Message& message);
|
||||
bool handleMessage(const Message& message) final;
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage);
|
||||
int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage);
|
||||
int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
static void webapiFormatDeviceSettings(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
@ -234,12 +234,13 @@ public:
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
bool m_running = false;
|
||||
FileOutputSettings m_settings;
|
||||
std::ofstream m_ofstream;
|
||||
FileOutputWorker* m_fileOutputWorker;
|
||||
FileOutputWorker* m_fileOutputWorker = nullptr;
|
||||
QThread m_fileOutputWorkerThread;
|
||||
QString m_deviceDescription;
|
||||
qint64 m_startingTimeStamp;
|
||||
qint64 m_startingTimeStamp = 0;
|
||||
const QTimer& m_masterTimer;
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
@ -252,7 +253,7 @@ private:
|
||||
void webapiReverseSendStartStop(bool start);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void networkManagerFinished(QNetworkReply *reply) const;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FILEOUTPUT_H
|
||||
|
@ -129,27 +129,28 @@ void HackRFOutput::init()
|
||||
|
||||
bool HackRFOutput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) {
|
||||
stop();
|
||||
return true;
|
||||
}
|
||||
|
||||
m_hackRFThread = new HackRFOutputThread(m_dev, &m_sampleSourceFifo);
|
||||
|
||||
// mutexLocker.unlock();
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
m_hackRFThread->setLog2Interpolation(m_settings.m_log2Interp);
|
||||
m_hackRFThread->setFcPos((int) m_settings.m_fcPos);
|
||||
|
||||
m_hackRFThread->startWork();
|
||||
m_running = true;
|
||||
mutexLocker.unlock();
|
||||
|
||||
qDebug("HackRFOutput::start: started");
|
||||
m_running = true;
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -173,8 +174,14 @@ void HackRFOutput::closeDevice()
|
||||
|
||||
void HackRFOutput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("HackRFOutput::stop");
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
m_running = false;
|
||||
|
||||
if(m_hackRFThread != 0)
|
||||
{
|
||||
@ -182,8 +189,6 @@ void HackRFOutput::stop()
|
||||
delete m_hackRFThread;
|
||||
m_hackRFThread = 0;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray HackRFOutput::serialize() const
|
||||
|
@ -380,14 +380,17 @@ void LimeSDROutput::init()
|
||||
|
||||
bool LimeSDROutput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_deviceShared.m_deviceParams->getDevice()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) { stop(); }
|
||||
|
||||
if (!acquireChannel())
|
||||
{
|
||||
if (!acquireChannel()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -396,20 +399,25 @@ bool LimeSDROutput::start()
|
||||
m_limeSDROutputThread = new LimeSDROutputThread(&m_streamId, &m_sampleSourceFifo);
|
||||
qDebug("LimeSDROutput::start: thread created");
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
m_limeSDROutputThread->setLog2Interpolation(m_settings.m_log2SoftInterp);
|
||||
m_limeSDROutputThread->startWork();
|
||||
|
||||
m_deviceShared.m_thread = m_limeSDROutputThread;
|
||||
m_running = true;
|
||||
mutexLocker.unlock();
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LimeSDROutput::stop()
|
||||
{
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("LimeSDROutput::stop");
|
||||
m_running = false;
|
||||
|
||||
if (m_limeSDROutputThread)
|
||||
{
|
||||
@ -419,7 +427,6 @@ void LimeSDROutput::stop()
|
||||
}
|
||||
|
||||
m_deviceShared.m_thread = 0;
|
||||
m_running = false;
|
||||
|
||||
releaseChannel();
|
||||
}
|
||||
|
@ -102,34 +102,44 @@ void PlutoSDROutput::init()
|
||||
|
||||
bool PlutoSDROutput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_deviceShared.m_deviceParams->getBox())
|
||||
{
|
||||
qCritical("PlutoSDROutput::start: device not open");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) {
|
||||
stop();
|
||||
}
|
||||
|
||||
// start / stop streaming is done in the thread.
|
||||
|
||||
m_plutoSDROutputThread = new PlutoSDROutputThread(PLUTOSDR_BLOCKSIZE_SAMPLES, m_deviceShared.m_deviceParams->getBox(), &m_sampleSourceFifo);
|
||||
qDebug("PlutoSDROutput::start: thread created");
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
m_plutoSDROutputThread->setLog2Interpolation(m_settings.m_log2Interp);
|
||||
m_plutoSDROutputThread->startWork();
|
||||
|
||||
m_deviceShared.m_thread = m_plutoSDROutputThread;
|
||||
m_running = true;
|
||||
mutexLocker.unlock();
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlutoSDROutput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
|
||||
if (m_plutoSDROutputThread != 0)
|
||||
{
|
||||
m_plutoSDROutputThread->stopWork();
|
||||
@ -138,7 +148,6 @@ void PlutoSDROutput::stop()
|
||||
}
|
||||
|
||||
m_deviceShared.m_thread = 0;
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray PlutoSDROutput::serialize() const
|
||||
|
@ -47,6 +47,7 @@ MESSAGE_CLASS_DEFINITION(RemoteOutput::MsgRequestFixedData, Message)
|
||||
|
||||
RemoteOutput::RemoteOutput(DeviceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_running(false),
|
||||
m_settings(),
|
||||
m_centerFrequency(435000000),
|
||||
m_sampleRate(48000),
|
||||
@ -83,7 +84,7 @@ RemoteOutput::~RemoteOutput()
|
||||
this,
|
||||
&RemoteOutput::networkManagerFinished
|
||||
);
|
||||
stop();
|
||||
RemoteOutput::stop();
|
||||
delete m_networkManager;
|
||||
}
|
||||
|
||||
@ -95,6 +96,11 @@ void RemoteOutput::destroy()
|
||||
bool RemoteOutput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebug() << "RemoteOutput::start";
|
||||
|
||||
m_remoteOutputWorker = new RemoteOutputWorker(&m_sampleSourceFifo);
|
||||
@ -105,6 +111,7 @@ bool RemoteOutput::start()
|
||||
m_remoteOutputWorker->setNbBlocksFEC(m_settings.m_nbFECBlocks);
|
||||
m_remoteOutputWorker->connectTimer(m_masterTimer);
|
||||
startWorker();
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySampleRate();
|
||||
@ -121,12 +128,18 @@ void RemoteOutput::init()
|
||||
|
||||
void RemoteOutput::stop()
|
||||
{
|
||||
qDebug() << "RemoteOutput::stop";
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "RemoteOutput::stop";
|
||||
m_running = false;
|
||||
|
||||
if (m_remoteOutputWorker)
|
||||
{
|
||||
stopWorker();
|
||||
stopWorker();
|
||||
delete m_remoteOutputWorker;
|
||||
m_remoteOutputWorker = nullptr;
|
||||
}
|
||||
@ -198,21 +211,21 @@ bool RemoteOutput::handleMessage(const Message& message)
|
||||
if (MsgConfigureRemoteOutput::match(message))
|
||||
{
|
||||
qDebug() << "RemoteOutput::handleMessage:" << message.getIdentifier();
|
||||
MsgConfigureRemoteOutput& conf = (MsgConfigureRemoteOutput&) message;
|
||||
auto& conf = (const MsgConfigureRemoteOutput&) message;
|
||||
applySettings(conf.getSettings(), conf.getSettingsKeys(), conf.getForce());
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureRemoteOutputWork::match(message))
|
||||
{
|
||||
MsgConfigureRemoteOutputWork& conf = (MsgConfigureRemoteOutputWork&) message;
|
||||
auto& conf = (const MsgConfigureRemoteOutputWork&) message;
|
||||
bool working = conf.isWorking();
|
||||
|
||||
if (m_remoteOutputWorker != nullptr)
|
||||
{
|
||||
if (working) {
|
||||
m_remoteOutputWorker->startWork();
|
||||
m_remoteOutputWorker->startWork();
|
||||
} else {
|
||||
m_remoteOutputWorker->stopWork();
|
||||
m_remoteOutputWorker->stopWork();
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,7 +233,7 @@ bool RemoteOutput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgStartStop::match(message))
|
||||
{
|
||||
MsgStartStop& cmd = (MsgStartStop&) message;
|
||||
auto& cmd = (const MsgStartStop&) message;
|
||||
qDebug() << "RemoteOutput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
|
||||
|
||||
if (cmd.getStartStop())
|
||||
@ -242,13 +255,13 @@ bool RemoteOutput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgConfigureRemoteOutputChunkCorrection::match(message))
|
||||
{
|
||||
MsgConfigureRemoteOutputChunkCorrection& conf = (MsgConfigureRemoteOutputChunkCorrection&) message;
|
||||
auto& conf = (const MsgConfigureRemoteOutputChunkCorrection&) message;
|
||||
|
||||
if (m_remoteOutputWorker != nullptr) {
|
||||
m_remoteOutputWorker->setChunkCorrection(conf.getChunkCorrection());
|
||||
if (m_remoteOutputWorker != nullptr) {
|
||||
m_remoteOutputWorker->setChunkCorrection(conf.getChunkCorrection());
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else if (MsgRequestFixedData::match(message))
|
||||
{
|
||||
@ -274,30 +287,23 @@ void RemoteOutput::applySettings(const RemoteOutputSettings& settings, const QLi
|
||||
qDebug() << "RemoteOutput::applySettings: force:" << force << settings.getDebugString(settingsKeys, force);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (force ||
|
||||
if ((force ||
|
||||
settingsKeys.contains("dataAddress") ||
|
||||
settingsKeys.contains("dataPort"))
|
||||
settingsKeys.contains("dataPort")) && m_remoteOutputWorker)
|
||||
{
|
||||
if (m_remoteOutputWorker) {
|
||||
m_remoteOutputWorker->setDataAddress(settings.m_dataAddress, settings.m_dataPort);
|
||||
}
|
||||
m_remoteOutputWorker->setDataAddress(settings.m_dataAddress, settings.m_dataPort);
|
||||
}
|
||||
|
||||
if (force || settingsKeys.contains("nbFECBlocks"))
|
||||
if ((force || settingsKeys.contains("nbFECBlocks")) && m_remoteOutputWorker)
|
||||
{
|
||||
if (m_remoteOutputWorker) {
|
||||
m_remoteOutputWorker->setNbBlocksFEC(settings.m_nbFECBlocks);
|
||||
}
|
||||
m_remoteOutputWorker->setNbBlocksFEC(settings.m_nbFECBlocks);
|
||||
}
|
||||
|
||||
if (force || settingsKeys.contains("nbTxBytes"))
|
||||
if ((force || settingsKeys.contains("nbTxBytes")) && m_remoteOutputWorker)
|
||||
{
|
||||
if (m_remoteOutputWorker)
|
||||
{
|
||||
stopWorker();
|
||||
m_remoteOutputWorker->setNbTxBytes(settings.m_nbTxBytes);
|
||||
startWorker();
|
||||
}
|
||||
stopWorker();
|
||||
m_remoteOutputWorker->setNbTxBytes(settings.m_nbTxBytes);
|
||||
startWorker();
|
||||
}
|
||||
|
||||
mutexLocker.unlock();
|
||||
@ -320,7 +326,7 @@ void RemoteOutput::applySettings(const RemoteOutputSettings& settings, const QLi
|
||||
|
||||
void RemoteOutput::applyCenterFrequency()
|
||||
{
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
auto *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||
}
|
||||
|
||||
@ -331,10 +337,11 @@ void RemoteOutput::applySampleRate()
|
||||
}
|
||||
|
||||
m_tickMultiplier = 480000 / m_sampleRate;
|
||||
m_tickMultiplier = m_tickMultiplier < 1 ? 1 : m_tickMultiplier > 10 ? 10 : m_tickMultiplier;
|
||||
m_tickMultiplier = m_tickMultiplier < 1 ? 1 : m_tickMultiplier;
|
||||
m_tickMultiplier = m_tickMultiplier > 10 ? 10 : m_tickMultiplier;
|
||||
m_greaterTickCount = 0;
|
||||
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
auto *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||
}
|
||||
|
||||
@ -415,13 +422,13 @@ void RemoteOutput::webapiUpdateDeviceSettings(
|
||||
settings.m_apiAddress = *response.getRemoteOutputSettings()->getApiAddress();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("apiPort")) {
|
||||
settings.m_apiPort = response.getRemoteOutputSettings()->getApiPort();
|
||||
settings.m_apiPort = (quint16) response.getRemoteOutputSettings()->getApiPort();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("dataAddress")) {
|
||||
settings.m_dataAddress = *response.getRemoteOutputSettings()->getDataAddress();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("dataPort")) {
|
||||
settings.m_dataPort = response.getRemoteOutputSettings()->getDataPort();
|
||||
settings.m_dataPort = (quint16) response.getRemoteOutputSettings()->getDataPort();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("deviceIndex")) {
|
||||
settings.m_deviceIndex = response.getRemoteOutputSettings()->getDeviceIndex();
|
||||
@ -436,10 +443,10 @@ void RemoteOutput::webapiUpdateDeviceSettings(
|
||||
settings.m_reverseAPIAddress = *response.getRemoteOutputSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getRemoteOutputSettings()->getReverseApiPort();
|
||||
settings.m_reverseAPIPort = (quint16) response.getRemoteOutputSettings()->getReverseApiPort();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getRemoteOutputSettings()->getReverseApiDeviceIndex();
|
||||
settings.m_reverseAPIDeviceIndex = (uint16_t) response.getRemoteOutputSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,10 +483,10 @@ void RemoteOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& re
|
||||
response.getRemoteOutputSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
|
||||
}
|
||||
|
||||
void RemoteOutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response)
|
||||
void RemoteOutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response) const
|
||||
{
|
||||
uint64_t nowus = TimeUtil::nowus();
|
||||
response.getRemoteOutputReport()->setTvSec(nowus / 1000000U);
|
||||
response.getRemoteOutputReport()->setTvSec((qint32) (nowus / 1000000U));
|
||||
response.getRemoteOutputReport()->setTvUSec(nowus % 1000000U);
|
||||
response.getRemoteOutputReport()->setCenterFrequency(m_centerFrequency);
|
||||
response.getRemoteOutputReport()->setSampleRate(m_sampleRate);
|
||||
@ -653,7 +660,7 @@ void RemoteOutput::queueLengthCompensation(
|
||||
|
||||
void RemoteOutput::webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const RemoteOutputSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(1); // single Tx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("RemoteOutput"));
|
||||
@ -694,8 +701,8 @@ void RemoteOutput::webapiReverseSendSettings(const QList<QString>& deviceSetting
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -708,7 +715,7 @@ void RemoteOutput::webapiReverseSendSettings(const QList<QString>& deviceSetting
|
||||
|
||||
void RemoteOutput::webapiReverseSendStartStop(bool start)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(1); // single Tx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("RemoteOutput"));
|
||||
@ -720,8 +727,8 @@ void RemoteOutput::webapiReverseSendStartStop(bool start)
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
QNetworkReply *reply;
|
||||
|
@ -83,7 +83,7 @@ public:
|
||||
private:
|
||||
bool m_working;
|
||||
|
||||
MsgConfigureRemoteOutputWork(bool working) :
|
||||
explicit MsgConfigureRemoteOutputWork(bool working) :
|
||||
Message(),
|
||||
m_working(working)
|
||||
{ }
|
||||
@ -99,10 +99,10 @@ public:
|
||||
return new MsgStartStop(startStop);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool m_startStop;
|
||||
|
||||
MsgStartStop(bool startStop) :
|
||||
explicit MsgStartStop(bool startStop) :
|
||||
Message(),
|
||||
m_startStop(startStop)
|
||||
{ }
|
||||
@ -122,7 +122,7 @@ public:
|
||||
private:
|
||||
int m_chunkCorrection;
|
||||
|
||||
MsgConfigureRemoteOutputChunkCorrection(int chunkCorrection) :
|
||||
explicit MsgConfigureRemoteOutputChunkCorrection(int chunkCorrection) :
|
||||
Message(),
|
||||
m_chunkCorrection(chunkCorrection)
|
||||
{ }
|
||||
@ -153,7 +153,7 @@ public:
|
||||
private:
|
||||
RemoteData m_remoteData;
|
||||
|
||||
MsgReportRemoteData(const RemoteData& remoteData) :
|
||||
explicit MsgReportRemoteData(const RemoteData& remoteData) :
|
||||
Message(),
|
||||
m_remoteData(remoteData)
|
||||
{}
|
||||
@ -182,7 +182,7 @@ public:
|
||||
private:
|
||||
RemoteData m_remoteData;
|
||||
|
||||
MsgReportRemoteFixedData(const RemoteData& remoteData) :
|
||||
explicit MsgReportRemoteFixedData(const RemoteData& remoteData) :
|
||||
Message(),
|
||||
m_remoteData(remoteData)
|
||||
{}
|
||||
@ -203,62 +203,63 @@ public:
|
||||
};
|
||||
|
||||
|
||||
RemoteOutput(DeviceAPI *deviceAPI);
|
||||
virtual ~RemoteOutput();
|
||||
virtual void destroy();
|
||||
explicit RemoteOutput(DeviceAPI *deviceAPI);
|
||||
~RemoteOutput() final;
|
||||
void destroy() final;
|
||||
|
||||
virtual void init();
|
||||
virtual bool start();
|
||||
virtual void stop();
|
||||
void init() final;
|
||||
bool start() final;
|
||||
void stop() final;
|
||||
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
QByteArray serialize() const final;
|
||||
bool deserialize(const QByteArray& data) final;
|
||||
|
||||
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
|
||||
virtual const QString& getDeviceDescription() const;
|
||||
virtual int getSampleRate() const;
|
||||
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
|
||||
virtual quint64 getCenterFrequency() const;
|
||||
virtual void setCenterFrequency(qint64 centerFrequency) { (void) centerFrequency; }
|
||||
void setMessageQueueToGUI(MessageQueue *queue) final { m_guiMessageQueue = queue; }
|
||||
const QString& getDeviceDescription() const final;
|
||||
int getSampleRate() const final;
|
||||
void setSampleRate(int sampleRate) final { (void) sampleRate; }
|
||||
quint64 getCenterFrequency() const final;
|
||||
void setCenterFrequency(qint64 centerFrequency) final { (void) centerFrequency; }
|
||||
std::time_t getStartingTimeStamp() const;
|
||||
|
||||
virtual bool handleMessage(const Message& message);
|
||||
bool handleMessage(const Message& message) final;
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage);
|
||||
int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage);
|
||||
int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiReportGet(
|
||||
SWGSDRangel::SWGDeviceReport& response,
|
||||
QString& errorMessage);
|
||||
int webapiReportGet(
|
||||
SWGSDRangel::SWGDeviceReport& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
static void webapiFormatDeviceSettings(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
const RemoteOutputSettings& settings);
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
const RemoteOutputSettings& settings);
|
||||
|
||||
static void webapiUpdateDeviceSettings(
|
||||
RemoteOutputSettings& settings,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response);
|
||||
RemoteOutputSettings& settings,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response);
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
QRecursiveMutex m_mutex;
|
||||
bool m_running;
|
||||
RemoteOutputSettings m_settings;
|
||||
uint64_t m_centerFrequency;
|
||||
int m_sampleRate;
|
||||
@ -283,7 +284,7 @@ private:
|
||||
void applySettings(const RemoteOutputSettings& settings, const QList<QString>& settingsKeys, bool force = false);
|
||||
void applyCenterFrequency();
|
||||
void applySampleRate();
|
||||
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
||||
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response) const;
|
||||
|
||||
void analyzeApiReply(const QJsonObject& jsonObject, const QString& answer);
|
||||
void queueLengthCompensation(
|
||||
|
@ -453,6 +453,11 @@ bool SoapySDROutput::start()
|
||||
//
|
||||
// Note: this is quite similar to the BladeRF2 start handling. The main difference is that the channel allocation (enabling) process is
|
||||
// done in the thread object.
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_openSuccess)
|
||||
{
|
||||
@ -558,11 +563,13 @@ void SoapySDROutput::stop()
|
||||
// channel then the FIFO reference is simply removed from the thread so that this FIFO will not be used anymore.
|
||||
// In this case the channel is not closed (this is managed in the thread object) so that other channels can continue with the
|
||||
// same configuration. The device continues streaming on this channel but the samples are set to all zeros.
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
int requestedChannel = m_deviceAPI->getDeviceItemIndex();
|
||||
SoapySDROutputThread *soapySDROutputThread = findThread();
|
||||
|
||||
@ -648,9 +655,8 @@ void SoapySDROutput::stop()
|
||||
soapySDROutputThread->setFifo(requestedChannel, nullptr); // remove FIFO
|
||||
}
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, true); // re-apply forcibly to set sample rate with the new number of channels
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray SoapySDROutput::serialize() const
|
||||
|
@ -379,12 +379,16 @@ void USRPOutput::init()
|
||||
|
||||
bool USRPOutput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_deviceShared.m_deviceParams->getDevice()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) { stop(); }
|
||||
|
||||
if (!acquireChannel()) {
|
||||
return false;
|
||||
}
|
||||
@ -403,7 +407,14 @@ bool USRPOutput::start()
|
||||
|
||||
void USRPOutput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("USRPOutput::stop");
|
||||
m_running = false;
|
||||
|
||||
if (m_usrpOutputThread)
|
||||
{
|
||||
@ -413,7 +424,6 @@ void USRPOutput::stop()
|
||||
}
|
||||
|
||||
m_deviceShared.m_thread = 0;
|
||||
m_running = false;
|
||||
|
||||
releaseChannel();
|
||||
}
|
||||
|
@ -265,6 +265,11 @@ bool XTRXOutput::start()
|
||||
//
|
||||
// Eventually it registers the FIFO in the thread. If the thread has to be started it enables the channels up to the number of channels
|
||||
// allocated in the thread and starts the thread.
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_deviceShared.m_dev || !m_deviceShared.m_dev->getDevice())
|
||||
{
|
||||
@ -341,6 +346,8 @@ bool XTRXOutput::start()
|
||||
|
||||
xtrxOutputThread->setFifo(requestedChannel, &m_sampleSourceFifo);
|
||||
xtrxOutputThread->setLog2Interpolation(requestedChannel, m_settings.m_log2SoftInterp);
|
||||
m_running = true;
|
||||
mutexLocker.unlock();
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
@ -351,7 +358,6 @@ bool XTRXOutput::start()
|
||||
}
|
||||
|
||||
qDebug("XTRXOutput::start: started");
|
||||
m_running = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -366,16 +372,18 @@ void XTRXOutput::stop()
|
||||
// If the thread is currently managing both channels (MO mode) then we are removing one channel. Thus we must
|
||||
// transition from MO to SO. This transition is handled by stopping the thread, deleting it and creating a new one
|
||||
// managing a single channel.
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
int removedChannel = m_deviceAPI->getDeviceItemIndex(); // channel to remove
|
||||
int requestedChannel = removedChannel ^ 1; // channel to keep (opposite channel)
|
||||
XTRXOutputThread *xtrxOutputThread = findThread();
|
||||
|
||||
if (xtrxOutputThread == 0) { // no thread allocated
|
||||
if (xtrxOutputThread == nullptr) { // no thread allocated
|
||||
return;
|
||||
}
|
||||
|
||||
@ -386,8 +394,8 @@ void XTRXOutput::stop()
|
||||
qDebug("XTRXOutput::stop: SO mode. Just stop and delete the thread");
|
||||
xtrxOutputThread->stopWork();
|
||||
delete xtrxOutputThread;
|
||||
m_XTRXOutputThread = 0;
|
||||
m_deviceShared.m_thread = 0;
|
||||
m_XTRXOutputThread = nullptr;
|
||||
m_deviceShared.m_thread = nullptr;
|
||||
|
||||
// remove old thread address from buddies (reset in all buddies)
|
||||
const std::vector<DeviceAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
|
||||
@ -417,11 +425,10 @@ void XTRXOutput::stop()
|
||||
((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_sink->setThread(nullptr);
|
||||
}
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
xtrxOutputThread->startWork();
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
void XTRXOutput::suspendRxThread()
|
||||
|
@ -197,14 +197,14 @@ bool AirspyInput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_airspyWorkerThread = new QThread();
|
||||
m_airspyWorker = new AirspyWorker(m_dev, &m_sampleFifo);
|
||||
m_airspyWorker->moveToThread(m_airspyWorkerThread);
|
||||
@ -217,13 +217,13 @@ bool AirspyInput::start()
|
||||
m_airspyWorker->setLog2Decimation(m_settings.m_log2Decim);
|
||||
m_airspyWorker->setIQOrder(m_settings.m_iqOrder);
|
||||
m_airspyWorker->setFcPos((int) m_settings.m_fcPos);
|
||||
mutexLocker.unlock();
|
||||
|
||||
m_airspyWorkerThread->start();
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
|
||||
qDebug("AirspyInput::startInput: started");
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
m_running = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ public:
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
QRecursiveMutex m_mutex;
|
||||
AirspySettings m_settings;
|
||||
struct airspy_device* m_dev;
|
||||
AirspyWorker* m_airspyWorker;
|
||||
|
@ -171,12 +171,12 @@ bool AirspyHFInput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_running) {
|
||||
stop();
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_airspyHFWorkerThread = new QThread();
|
||||
@ -198,13 +198,13 @@ bool AirspyHFInput::start()
|
||||
|
||||
m_airspyHFWorker->setLog2Decimation(m_settings.m_log2Decim);
|
||||
m_airspyHFWorker->setIQOrder(m_settings.m_iqOrder);
|
||||
mutexLocker.unlock();
|
||||
|
||||
m_airspyHFWorkerThread->start();
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
|
||||
qDebug("AirspyHFInput::startInput: started");
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
m_running = true;
|
||||
|
||||
return m_running;
|
||||
}
|
||||
@ -223,9 +223,15 @@ void AirspyHFInput::closeDevice()
|
||||
|
||||
void AirspyHFInput::stop()
|
||||
{
|
||||
qDebug("AirspyHFInput::stop");
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("AirspyHFInput::stop");
|
||||
m_running = false;
|
||||
|
||||
if (m_airspyHFWorkerThread)
|
||||
{
|
||||
m_airspyHFWorkerThread->quit();
|
||||
@ -234,7 +240,6 @@ void AirspyHFInput::stop()
|
||||
m_airspyHFWorker = nullptr;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray AirspyHFInput::serialize() const
|
||||
|
@ -165,7 +165,7 @@ public:
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
QRecursiveMutex m_mutex;
|
||||
AirspyHFSettings m_settings;
|
||||
airspyhf_device_t* m_dev;
|
||||
AirspyHFWorker* m_airspyHFWorker;
|
||||
|
@ -40,7 +40,7 @@ MESSAGE_CLASS_DEFINITION(Bladerf1Input::MsgStartStop, Message)
|
||||
Bladerf1Input::Bladerf1Input(DeviceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_settings(),
|
||||
m_dev(0),
|
||||
m_dev(nullptr),
|
||||
m_bladerfThread(nullptr),
|
||||
m_deviceDescription("BladeRFInput"),
|
||||
m_running(false)
|
||||
@ -70,11 +70,11 @@ Bladerf1Input::~Bladerf1Input()
|
||||
delete m_networkManager;
|
||||
|
||||
if (m_running) {
|
||||
stop();
|
||||
Bladerf1Input::stop();
|
||||
}
|
||||
|
||||
closeDevice();
|
||||
m_deviceAPI->setBuddySharedPtr(0);
|
||||
m_deviceAPI->setBuddySharedPtr(nullptr);
|
||||
}
|
||||
|
||||
void Bladerf1Input::destroy()
|
||||
@ -84,7 +84,7 @@ void Bladerf1Input::destroy()
|
||||
|
||||
bool Bladerf1Input::openDevice()
|
||||
{
|
||||
if (m_dev != 0)
|
||||
if (m_dev != nullptr)
|
||||
{
|
||||
closeDevice();
|
||||
}
|
||||
@ -97,24 +97,24 @@ bool Bladerf1Input::openDevice()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_deviceAPI->getSinkBuddies().size() > 0)
|
||||
if (!m_deviceAPI->getSinkBuddies().empty())
|
||||
{
|
||||
DeviceAPI *sinkBuddy = m_deviceAPI->getSinkBuddies()[0];
|
||||
DeviceBladeRF1Params *buddySharedParams = (DeviceBladeRF1Params *) sinkBuddy->getBuddySharedPtr();
|
||||
const DeviceAPI *sinkBuddy = m_deviceAPI->getSinkBuddies()[0];
|
||||
const DeviceBladeRF1Params *buddySharedParams = (DeviceBladeRF1Params *) sinkBuddy->getBuddySharedPtr();
|
||||
|
||||
if (buddySharedParams == 0)
|
||||
if (buddySharedParams == nullptr)
|
||||
{
|
||||
qCritical("BladerfInput::openDevice: could not get shared parameters from buddy");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buddySharedParams->m_dev == 0) // device is not opened by buddy
|
||||
if (buddySharedParams->m_dev == nullptr) // device is not opened by buddy
|
||||
{
|
||||
qCritical("BladerfInput::openDevice: could not get BladeRF handle from buddy");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sharedParams = *(buddySharedParams); // copy parameters from buddy
|
||||
m_sharedParams = *buddySharedParams; // copy parameters from buddy
|
||||
m_dev = m_sharedParams.m_dev; // get BladeRF handle
|
||||
}
|
||||
else
|
||||
@ -128,7 +128,6 @@ bool Bladerf1Input::openDevice()
|
||||
m_sharedParams.m_dev = m_dev;
|
||||
}
|
||||
|
||||
// TODO: adjust USB transfer data according to sample rate
|
||||
if ((res = bladerf_sync_config(m_dev, BLADERF_RX_X1, BLADERF_FORMAT_SC16_Q11, 64, 8192, 32, 10000)) < 0)
|
||||
{
|
||||
qCritical("BladerfInput::start: bladerf_sync_config with return code %d", res);
|
||||
@ -151,7 +150,11 @@ void Bladerf1Input::init()
|
||||
|
||||
bool Bladerf1Input::start()
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_dev)
|
||||
{
|
||||
@ -159,20 +162,17 @@ bool Bladerf1Input::start()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) stop();
|
||||
|
||||
m_bladerfThread = new Bladerf1InputThread(m_dev, &m_sampleFifo);
|
||||
m_bladerfThread->setLog2Decimation(m_settings.m_log2Decim);
|
||||
m_bladerfThread->setFcPos((int) m_settings.m_fcPos);
|
||||
m_bladerfThread->setIQOrder(m_settings.m_iqOrder);
|
||||
|
||||
m_bladerfThread->startWork();
|
||||
m_running = true;
|
||||
|
||||
// mutexLocker.unlock();
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
qDebug("BladerfInput::startInput: started");
|
||||
m_running = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -181,7 +181,7 @@ void Bladerf1Input::closeDevice()
|
||||
{
|
||||
int res;
|
||||
|
||||
if (m_dev == 0) { // was never open
|
||||
if (m_dev == nullptr) { // was never open
|
||||
return;
|
||||
}
|
||||
|
||||
@ -190,23 +190,29 @@ void Bladerf1Input::closeDevice()
|
||||
qCritical("BladerfInput::stop: bladerf_enable_module with return code %d", res);
|
||||
}
|
||||
|
||||
if (m_deviceAPI->getSinkBuddies().size() == 0)
|
||||
if (m_deviceAPI->getSinkBuddies().empty())
|
||||
{
|
||||
qDebug("BladerfInput::closeDevice: closing device since Tx side is not open");
|
||||
|
||||
if(m_dev != 0) // close BladeRF
|
||||
if(m_dev != nullptr) // close BladeRF
|
||||
{
|
||||
bladerf_close(m_dev);
|
||||
}
|
||||
}
|
||||
|
||||
m_sharedParams.m_dev = 0;
|
||||
m_dev = 0;
|
||||
m_sharedParams.m_dev = nullptr;
|
||||
m_dev = nullptr;
|
||||
}
|
||||
|
||||
void Bladerf1Input::stop()
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
|
||||
if(m_bladerfThread)
|
||||
{
|
||||
@ -215,7 +221,6 @@ void Bladerf1Input::stop()
|
||||
m_bladerfThread = nullptr;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray Bladerf1Input::serialize() const
|
||||
@ -280,7 +285,7 @@ bool Bladerf1Input::handleMessage(const Message& message)
|
||||
{
|
||||
if (MsgConfigureBladerf1::match(message))
|
||||
{
|
||||
MsgConfigureBladerf1& conf = (MsgConfigureBladerf1&) message;
|
||||
auto& conf = (const MsgConfigureBladerf1&) message;
|
||||
qDebug() << "Bladerf1Input::handleMessage: MsgConfigureBladerf1";
|
||||
|
||||
if (!applySettings(conf.getSettings(), conf.getSettingsKeys(), conf.getForce())) {
|
||||
@ -291,7 +296,7 @@ bool Bladerf1Input::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgStartStop::match(message))
|
||||
{
|
||||
MsgStartStop& cmd = (MsgStartStop&) message;
|
||||
auto& cmd = (const MsgStartStop&) message;
|
||||
qDebug() << "BladerfInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
|
||||
|
||||
if (cmd.getStartStop())
|
||||
@ -320,126 +325,107 @@ bool Bladerf1Input::handleMessage(const Message& message)
|
||||
bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, const QList<QString>& settingsKeys, bool force)
|
||||
{
|
||||
bool forwardChange = false;
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
qDebug() << "BladerfInput::applySettings: force: " << force << settings.getDebugString(settingsKeys, force);
|
||||
|
||||
if ((settingsKeys.contains("dcBlock")) ||
|
||||
settingsKeys.contains("iqCorrection") || force)
|
||||
settingsKeys.contains("iqCorrection") || force)
|
||||
{
|
||||
m_deviceAPI->configureCorrections(settings.m_dcBlock, settings.m_iqCorrection);
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("lnaGain") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("lnaGain") || force))
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if(bladerf_set_lna_gain(m_dev, getLnaGain(settings.m_lnaGain)) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_set_lna_gain() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: LNA gain set to " << getLnaGain(settings.m_lnaGain);
|
||||
}
|
||||
}
|
||||
if(bladerf_set_lna_gain(m_dev, getLnaGain(settings.m_lnaGain)) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_set_lna_gain() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: LNA gain set to " << getLnaGain(settings.m_lnaGain);
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("vga1") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("vga1") || force))
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if(bladerf_set_rxvga1(m_dev, settings.m_vga1) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_set_rxvga1() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: VGA1 gain set to " << settings.m_vga1;
|
||||
}
|
||||
}
|
||||
if(bladerf_set_rxvga1(m_dev, settings.m_vga1) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_set_rxvga1() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: VGA1 gain set to " << settings.m_vga1;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("vga2") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("vga2") || force))
|
||||
{
|
||||
if(m_dev != 0)
|
||||
{
|
||||
if(bladerf_set_rxvga2(m_dev, settings.m_vga2) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_set_rxvga2() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: VGA2 gain set to " << settings.m_vga2;
|
||||
}
|
||||
}
|
||||
if(bladerf_set_rxvga2(m_dev, settings.m_vga2) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_set_rxvga2() failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: VGA2 gain set to " << settings.m_vga2;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("xb200") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("xb200") || force))
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
bool changeSettings;
|
||||
bool changeSettings;
|
||||
|
||||
if (m_deviceAPI->getSinkBuddies().size() > 0)
|
||||
{
|
||||
DeviceAPI *buddy = m_deviceAPI->getSinkBuddies()[0];
|
||||
if (!m_deviceAPI->getSinkBuddies().empty())
|
||||
{
|
||||
DeviceAPI *buddy = m_deviceAPI->getSinkBuddies()[0];
|
||||
|
||||
if (buddy->getDeviceSinkEngine()->state() == DSPDeviceSinkEngine::StRunning) { // Tx side running
|
||||
changeSettings = false;
|
||||
} else {
|
||||
changeSettings = true;
|
||||
}
|
||||
}
|
||||
else // No Tx open
|
||||
{
|
||||
if (buddy->getDeviceSinkEngine()->state() == DSPDeviceSinkEngine::State::StRunning) { // Tx side running
|
||||
changeSettings = false;
|
||||
} else {
|
||||
changeSettings = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // No Tx open
|
||||
{
|
||||
changeSettings = true;
|
||||
}
|
||||
|
||||
if (changeSettings)
|
||||
{
|
||||
if (settings.m_xb200)
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_expansion_attach(xb200) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: Attach XB200";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_NONE) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_expansion_attach(none) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: Detach XB200";
|
||||
}
|
||||
}
|
||||
if (changeSettings)
|
||||
{
|
||||
if (settings.m_xb200)
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_expansion_attach(xb200) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: Attach XB200";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_NONE) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_expansion_attach(none) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: Detach XB200";
|
||||
}
|
||||
}
|
||||
|
||||
m_sharedParams.m_xb200Attached = settings.m_xb200;
|
||||
}
|
||||
}
|
||||
m_sharedParams.m_xb200Attached = settings.m_xb200;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("xb200Path") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("xb200Path") || force))
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if(bladerf_xb200_set_path(m_dev, BLADERF_MODULE_RX, settings.m_xb200Path) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_xb200_set_path(BLADERF_MODULE_RX) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: set xb200 path to " << settings.m_xb200Path;
|
||||
}
|
||||
}
|
||||
if(bladerf_xb200_set_path(m_dev, BLADERF_MODULE_RX, settings.m_xb200Path) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_xb200_set_path(BLADERF_MODULE_RX) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: set xb200 path to " << settings.m_xb200Path;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("xb200Filter") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("xb200Filter") || force))
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if(bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_RX, settings.m_xb200Filter) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_xb200_set_filterbank(BLADERF_MODULE_RX) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: set xb200 filter to " << settings.m_xb200Filter;
|
||||
}
|
||||
}
|
||||
if(bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_RX, settings.m_xb200Filter) != 0) {
|
||||
qDebug("BladerfInput::applySettings: bladerf_xb200_set_filterbank(BLADERF_MODULE_RX) failed");
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: set xb200 filter to " << settings.m_xb200Filter;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("devSampleRate") || force)
|
||||
{
|
||||
forwardChange = true;
|
||||
|
||||
if (m_dev != 0)
|
||||
if (m_dev != nullptr)
|
||||
{
|
||||
unsigned int actualSamplerate;
|
||||
|
||||
@ -451,27 +437,21 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, const Q
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("bandwidth") || force)
|
||||
if ((m_dev != nullptr) && (settingsKeys.contains("bandwidth") || force))
|
||||
{
|
||||
if(m_dev != 0)
|
||||
{
|
||||
unsigned int actualBandwidth;
|
||||
unsigned int actualBandwidth;
|
||||
|
||||
if( bladerf_set_bandwidth(m_dev, BLADERF_MODULE_RX, settings.m_bandwidth, &actualBandwidth) < 0) {
|
||||
qCritical("BladerfInput::applySettings: could not set bandwidth: %d", settings.m_bandwidth);
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: bladerf_set_bandwidth(BLADERF_MODULE_RX) actual bandwidth is " << actualBandwidth;
|
||||
}
|
||||
}
|
||||
if( bladerf_set_bandwidth(m_dev, BLADERF_MODULE_RX, settings.m_bandwidth, &actualBandwidth) < 0) {
|
||||
qCritical("BladerfInput::applySettings: could not set bandwidth: %d", settings.m_bandwidth);
|
||||
} else {
|
||||
qDebug() << "BladerfInput::applySettings: bladerf_set_bandwidth(BLADERF_MODULE_RX) actual bandwidth is " << actualBandwidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("fcPos") || force)
|
||||
if (m_bladerfThread && (settingsKeys.contains("fcPos") || force))
|
||||
{
|
||||
if (m_bladerfThread)
|
||||
{
|
||||
m_bladerfThread->setFcPos((int) settings.m_fcPos);
|
||||
qDebug() << "BladerfInput::applySettings: set fc pos (enum) to " << (int) settings.m_fcPos;
|
||||
}
|
||||
m_bladerfThread->setFcPos((int) settings.m_fcPos);
|
||||
qDebug() << "BladerfInput::applySettings: set fc pos (enum) to " << (int) settings.m_fcPos;
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("log2Decim") || force)
|
||||
@ -485,11 +465,9 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, const Q
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("iqOrder") || force)
|
||||
if (m_bladerfThread && (settingsKeys.contains("iqOrder") || force))
|
||||
{
|
||||
if (m_bladerfThread) {
|
||||
m_bladerfThread->setIQOrder(settings.m_iqOrder);
|
||||
}
|
||||
m_bladerfThread->setIQOrder(settings.m_iqOrder);
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("centerFrequency")
|
||||
@ -508,7 +486,7 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, const Q
|
||||
|
||||
forwardChange = true;
|
||||
|
||||
if (m_dev != 0)
|
||||
if (m_dev != nullptr)
|
||||
{
|
||||
if (bladerf_set_frequency( m_dev, BLADERF_MODULE_RX, deviceCenterFrequency ) != 0) {
|
||||
qWarning("BladerfInput::applySettings: bladerf_set_frequency(%lld) failed", settings.m_centerFrequency);
|
||||
@ -521,7 +499,7 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, const Q
|
||||
if (forwardChange)
|
||||
{
|
||||
int sampleRate = settings.m_devSampleRate/(1<<settings.m_log2Decim);
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, settings.m_centerFrequency);
|
||||
auto *notif = new DSPSignalNotification(sampleRate, settings.m_centerFrequency);
|
||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||
}
|
||||
|
||||
@ -543,7 +521,7 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, const Q
|
||||
return true;
|
||||
}
|
||||
|
||||
bladerf_lna_gain Bladerf1Input::getLnaGain(int lnaGain)
|
||||
bladerf_lna_gain Bladerf1Input::getLnaGain(int lnaGain) const
|
||||
{
|
||||
if (lnaGain == 2) {
|
||||
return BLADERF_LNA_GAIN_MAX;
|
||||
@ -650,7 +628,7 @@ void Bladerf1Input::webapiUpdateDeviceSettings(
|
||||
settings.m_fcPos = static_cast<BladeRF1InputSettings::fcPos_t>(response.getBladeRf1InputSettings()->getFcPos());
|
||||
}
|
||||
if (deviceSettingsKeys.contains("xb200")) {
|
||||
settings.m_xb200 = response.getBladeRf1InputSettings()->getXb200() == 0 ? 0 : 1;
|
||||
settings.m_xb200 = response.getBladeRf1InputSettings()->getXb200() == 0 ? false : true;
|
||||
}
|
||||
if (deviceSettingsKeys.contains("xb200Path")) {
|
||||
settings.m_xb200Path = static_cast<bladerf_xb200_path>(response.getBladeRf1InputSettings()->getXb200Path());
|
||||
@ -671,10 +649,10 @@ void Bladerf1Input::webapiUpdateDeviceSettings(
|
||||
settings.m_reverseAPIAddress = *response.getBladeRf1InputSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getBladeRf1InputSettings()->getReverseApiPort();
|
||||
settings.m_reverseAPIPort = (uint16_t) response.getBladeRf1InputSettings()->getReverseApiPort();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getBladeRf1InputSettings()->getReverseApiDeviceIndex();
|
||||
settings.m_reverseAPIDeviceIndex = (uint16_t) response.getBladeRf1InputSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
}
|
||||
|
||||
@ -708,7 +686,7 @@ int Bladerf1Input::webapiRun(
|
||||
|
||||
void Bladerf1Input::webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const BladeRF1InputSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(0); // single Rx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("BladeRF1"));
|
||||
@ -767,8 +745,8 @@ void Bladerf1Input::webapiReverseSendSettings(const QList<QString>& deviceSettin
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -781,7 +759,7 @@ void Bladerf1Input::webapiReverseSendSettings(const QList<QString>& deviceSettin
|
||||
|
||||
void Bladerf1Input::webapiReverseSendStartStop(bool start)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(0); // single Rx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("BladeRF1"));
|
||||
@ -793,8 +771,8 @@ void Bladerf1Input::webapiReverseSendStartStop(bool start)
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
QNetworkReply *reply;
|
||||
@ -809,7 +787,7 @@ void Bladerf1Input::webapiReverseSendStartStop(bool start)
|
||||
delete swgDeviceSettings;
|
||||
}
|
||||
|
||||
void Bladerf1Input::networkManagerFinished(QNetworkReply *reply)
|
||||
void Bladerf1Input::networkManagerFinished(QNetworkReply *reply) const
|
||||
{
|
||||
QNetworkReply::NetworkError replyError = reply->error();
|
||||
|
||||
|
@ -76,66 +76,66 @@ public:
|
||||
return new MsgStartStop(startStop);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool m_startStop;
|
||||
|
||||
MsgStartStop(bool startStop) :
|
||||
explicit MsgStartStop(bool startStop) :
|
||||
Message(),
|
||||
m_startStop(startStop)
|
||||
{ }
|
||||
};
|
||||
|
||||
Bladerf1Input(DeviceAPI *deviceAPI);
|
||||
virtual ~Bladerf1Input();
|
||||
virtual void destroy();
|
||||
explicit Bladerf1Input(DeviceAPI *deviceAPI);
|
||||
~Bladerf1Input() final;
|
||||
void destroy() final;
|
||||
|
||||
virtual void init();
|
||||
virtual bool start();
|
||||
virtual void stop();
|
||||
void init() final;
|
||||
bool start() final;
|
||||
void stop() final;
|
||||
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
QByteArray serialize() const final;
|
||||
bool deserialize(const QByteArray& data) final;
|
||||
|
||||
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
|
||||
virtual const QString& getDeviceDescription() const;
|
||||
virtual int getSampleRate() const;
|
||||
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
|
||||
virtual quint64 getCenterFrequency() const;
|
||||
virtual void setCenterFrequency(qint64 centerFrequency);
|
||||
void setMessageQueueToGUI(MessageQueue *queue) final { m_guiMessageQueue = queue; }
|
||||
const QString& getDeviceDescription() const final;
|
||||
int getSampleRate() const final;
|
||||
void setSampleRate(int sampleRate) final { (void) sampleRate; }
|
||||
quint64 getCenterFrequency() const final;
|
||||
void setCenterFrequency(qint64 centerFrequency) final;
|
||||
|
||||
virtual bool handleMessage(const Message& message);
|
||||
bool handleMessage(const Message& message) final;
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage);
|
||||
int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage);
|
||||
int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
static void webapiFormatDeviceSettings(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
const BladeRF1InputSettings& settings);
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
const BladeRF1InputSettings& settings);
|
||||
|
||||
static void webapiUpdateDeviceSettings(
|
||||
BladeRF1InputSettings& settings,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response);
|
||||
BladeRF1InputSettings& settings,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response);
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
QRecursiveMutex m_mutex;
|
||||
BladeRF1InputSettings m_settings;
|
||||
struct bladerf* m_dev;
|
||||
Bladerf1InputThread* m_bladerfThread;
|
||||
@ -148,12 +148,12 @@ private:
|
||||
bool openDevice();
|
||||
void closeDevice();
|
||||
bool applySettings(const BladeRF1InputSettings& settings, const QList<QString>& settingsKeys, bool force);
|
||||
bladerf_lna_gain getLnaGain(int lnaGain);
|
||||
bladerf_lna_gain getLnaGain(int lnaGain) const;
|
||||
void webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const BladeRF1InputSettings& settings, bool force);
|
||||
void webapiReverseSendStartStop(bool start);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void networkManagerFinished(QNetworkReply *reply) const;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_BLADERFINPUT_H
|
||||
|
@ -290,6 +290,11 @@ bool BladeRF2Input::start()
|
||||
//
|
||||
// Eventually it registers the FIFO in the thread. If the thread has to be started it enables the channels up to the number of channels
|
||||
// allocated in the thread and starts the thread.
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_deviceShared.m_dev)
|
||||
{
|
||||
@ -383,10 +388,11 @@ bool BladeRF2Input::start()
|
||||
bladerf2InputThread->startWork();
|
||||
}
|
||||
|
||||
m_running = true;
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
qDebug("BladeRF2Input::start: started");
|
||||
m_running = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -408,6 +414,7 @@ void BladeRF2Input::stop()
|
||||
// anymore. In this case the channel is not closed (disabled) so that other channels can continue with the
|
||||
// same configuration. The device continues streaming on this channel but the samples are simply dropped (by
|
||||
// removing FIFO reference).
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
@ -420,6 +427,7 @@ void BladeRF2Input::stop()
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
int nbOriginalChannels = bladerf2InputThread->getNbChannels();
|
||||
|
||||
if (nbOriginalChannels == 1) // SI mode => just stop and delete the thread
|
||||
@ -500,8 +508,6 @@ void BladeRF2Input::stop()
|
||||
qDebug("BladeRF2Input::stop: MI mode. Not changing MI configuration. Just remove FIFO reference");
|
||||
bladerf2InputThread->setFifo(requestedChannel, 0); // remove FIFO
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray BladeRF2Input::serialize() const
|
||||
|
@ -121,15 +121,18 @@ void FCDProInput::init()
|
||||
|
||||
bool FCDProInput::start()
|
||||
{
|
||||
qDebug() << "FCDProInput::start";
|
||||
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) stop();
|
||||
qDebug() << "FCDProInput::start";
|
||||
|
||||
/* Apply settings before streaming to avoid bus contention;
|
||||
* there is very little spare bandwidth on a full speed USB device.
|
||||
@ -149,12 +152,12 @@ bool FCDProInput::start()
|
||||
m_FCDThread->setFcPos(m_settings.m_fcPos);
|
||||
m_FCDThread->setIQOrder(m_settings.m_iqOrder);
|
||||
m_FCDThread->startWork();
|
||||
m_running = true;
|
||||
|
||||
// mutexLocker.unlock();
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
qDebug("FCDProInput::started");
|
||||
m_running = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -204,7 +207,13 @@ void FCDProInput::closeFCDAudio()
|
||||
|
||||
void FCDProInput::stop()
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
|
||||
if (m_FCDThread)
|
||||
{
|
||||
@ -213,8 +222,6 @@ void FCDProInput::stop()
|
||||
delete m_FCDThread;
|
||||
m_FCDThread = nullptr;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray FCDProInput::serialize() const
|
||||
|
@ -121,14 +121,14 @@ void FCDProPlusInput::init()
|
||||
|
||||
bool FCDProPlusInput::start()
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) {
|
||||
stop();
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebug() << "FCDProPlusInput::start";
|
||||
@ -151,12 +151,12 @@ bool FCDProPlusInput::start()
|
||||
m_FCDThread->setFcPos(m_settings.m_fcPos);
|
||||
m_FCDThread->setIQOrder(m_settings.m_iqOrder);
|
||||
m_FCDThread->startWork();
|
||||
m_running = true;
|
||||
|
||||
// mutexLocker.unlock();
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
qDebug("FCDProPlusInput::started");
|
||||
m_running = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -170,7 +170,7 @@ void FCDProPlusInput::closeDevice()
|
||||
fcdClose(m_dev);
|
||||
m_dev = 0;
|
||||
|
||||
closeFCDAudio();
|
||||
closeFCDAudio();
|
||||
}
|
||||
|
||||
bool FCDProPlusInput::openFCDAudio(const char* cardname)
|
||||
@ -208,6 +208,12 @@ void FCDProPlusInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
|
||||
if (m_FCDThread)
|
||||
{
|
||||
m_FCDThread->stopWork();
|
||||
@ -215,8 +221,6 @@ void FCDProPlusInput::stop()
|
||||
delete m_FCDThread;
|
||||
m_FCDThread = nullptr;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray FCDProPlusInput::serialize() const
|
||||
|
@ -142,29 +142,29 @@ void HackRFInput::init()
|
||||
|
||||
bool HackRFInput::start()
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) {
|
||||
stop();
|
||||
}
|
||||
|
||||
m_hackRFThread = new HackRFInputThread(m_dev, &m_sampleFifo);
|
||||
|
||||
// mutexLocker.unlock();
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
m_hackRFThread->setSamplerate(m_settings.m_devSampleRate);
|
||||
m_hackRFThread->setLog2Decimation(m_settings.m_log2Decim);
|
||||
m_hackRFThread->setFcPos((int) m_settings.m_fcPos);
|
||||
m_hackRFThread->setIQOrder(m_settings.m_iqOrder);
|
||||
m_hackRFThread->startWork();
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
qDebug("HackRFInput::startInput: started");
|
||||
m_running = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -188,8 +188,14 @@ void HackRFInput::closeDevice()
|
||||
|
||||
void HackRFInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("HackRFInput::stop");
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
m_running = false;
|
||||
|
||||
if (m_hackRFThread)
|
||||
{
|
||||
@ -197,8 +203,6 @@ void HackRFInput::stop()
|
||||
delete m_hackRFThread;
|
||||
m_hackRFThread = nullptr;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray HackRFInput::serialize() const
|
||||
@ -349,7 +353,7 @@ void HackRFInput::setDeviceCenterFrequency(quint64 freq_hz, int loPpmTenths)
|
||||
|
||||
bool HackRFInput::applySettings(const HackRFInputSettings& settings, const QList<QString>& settingsKeys, bool force)
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug() << "HackRFInput::applySettings: forcE: " << force << settings.getDebugString(settingsKeys, force);
|
||||
bool forwardChange = false;
|
||||
hackrf_error rc;
|
||||
|
@ -153,7 +153,7 @@ public:
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
QRecursiveMutex m_mutex;
|
||||
HackRFInputSettings m_settings;
|
||||
struct hackrf_device* m_dev;
|
||||
HackRFInputThread* m_hackRFThread;
|
||||
|
@ -409,14 +409,17 @@ void LimeSDRInput::init()
|
||||
|
||||
bool LimeSDRInput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_deviceShared.m_deviceParams->getDevice()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) { stop(); }
|
||||
|
||||
if (!acquireChannel())
|
||||
{
|
||||
if (!acquireChannel()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -425,21 +428,28 @@ bool LimeSDRInput::start()
|
||||
m_limeSDRInputThread = new LimeSDRInputThread(&m_streamId, &m_sampleFifo, &m_replayBuffer);
|
||||
qDebug("LimeSDRInput::start: thread created");
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
m_limeSDRInputThread->setLog2Decimation(m_settings.m_log2SoftDecim);
|
||||
m_limeSDRInputThread->setIQOrder(m_settings.m_iqOrder);
|
||||
m_limeSDRInputThread->startWork();
|
||||
|
||||
m_deviceShared.m_thread = m_limeSDRInputThread;
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LimeSDRInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("LimeSDRInput::stop");
|
||||
m_running = false;
|
||||
|
||||
if (m_limeSDRInputThread)
|
||||
{
|
||||
@ -449,7 +459,6 @@ void LimeSDRInput::stop()
|
||||
}
|
||||
|
||||
m_deviceShared.m_thread = 0;
|
||||
m_running = false;
|
||||
|
||||
releaseChannel();
|
||||
}
|
||||
@ -803,7 +812,7 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, const QLi
|
||||
bool doLPCalibration = false;
|
||||
double clockGenFreq = 0.0;
|
||||
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
qint64 deviceCenterFrequency = settings.m_centerFrequency;
|
||||
deviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0;
|
||||
|
@ -290,7 +290,7 @@ public:
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
QRecursiveMutex m_mutex;
|
||||
LimeSDRInputSettings m_settings;
|
||||
LimeSDRInputThread* m_limeSDRInputThread;
|
||||
QString m_deviceDescription;
|
||||
|
@ -102,35 +102,45 @@ void PlutoSDRInput::init()
|
||||
|
||||
bool PlutoSDRInput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_deviceShared.m_deviceParams->getBox())
|
||||
{
|
||||
qCritical("PlutoSDRInput::start: device not open");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) {
|
||||
stop();
|
||||
}
|
||||
|
||||
// start / stop streaming is done in the thread.
|
||||
|
||||
m_plutoSDRInputThread = new PlutoSDRInputThread(PLUTOSDR_BLOCKSIZE_SAMPLES, m_deviceShared.m_deviceParams->getBox(), &m_sampleFifo);
|
||||
qDebug("PlutoSDRInput::start: thread created");
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
m_plutoSDRInputThread->setLog2Decimation(m_settings.m_log2Decim);
|
||||
m_plutoSDRInputThread->setIQOrder(m_settings.m_iqOrder);
|
||||
m_plutoSDRInputThread->startWork();
|
||||
|
||||
m_deviceShared.m_thread = m_plutoSDRInputThread;
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlutoSDRInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
|
||||
if (m_plutoSDRInputThread)
|
||||
{
|
||||
m_plutoSDRInputThread->stopWork();
|
||||
@ -139,7 +149,6 @@ void PlutoSDRInput::stop()
|
||||
}
|
||||
|
||||
m_deviceShared.m_thread = nullptr;
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray PlutoSDRInput::serialize() const
|
||||
|
@ -78,6 +78,7 @@ RTLSDRInput::RTLSDRInput(DeviceAPI *deviceAPI) :
|
||||
|
||||
RTLSDRInput::~RTLSDRInput()
|
||||
{
|
||||
qDebug("RTLSDRInput::~RTLSDRInput");
|
||||
QObject::disconnect(
|
||||
m_networkManager,
|
||||
&QNetworkAccessManager::finished,
|
||||
@ -91,6 +92,7 @@ RTLSDRInput::~RTLSDRInput()
|
||||
}
|
||||
|
||||
closeDevice();
|
||||
qDebug("RTLSDRInput::~RTLSDRInput: end");
|
||||
}
|
||||
|
||||
void RTLSDRInput::destroy()
|
||||
@ -231,11 +233,15 @@ bool RTLSDRInput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) stop();
|
||||
qDebug("RTLSDRInput::start");
|
||||
|
||||
m_rtlSDRThread = new RTLSDRThread(m_dev, &m_sampleFifo, &m_replayBuffer);
|
||||
m_rtlSDRThread->setSamplerate(m_settings.m_devSampleRate);
|
||||
@ -243,11 +249,11 @@ bool RTLSDRInput::start()
|
||||
m_rtlSDRThread->setFcPos((int) m_settings.m_fcPos);
|
||||
m_rtlSDRThread->setIQOrder(m_settings.m_iqOrder);
|
||||
m_rtlSDRThread->startWork();
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
m_running = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -267,6 +273,12 @@ void RTLSDRInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("RTLSDRInput::stop");
|
||||
|
||||
if (m_rtlSDRThread)
|
||||
{
|
||||
m_rtlSDRThread->stopWork();
|
||||
|
@ -149,15 +149,17 @@ bool SDRPlayInput::openDevice()
|
||||
|
||||
bool SDRPlayInput::start()
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
int res;
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) stop();
|
||||
|
||||
int res;
|
||||
char s12FormatString[] = "336_S16";
|
||||
|
||||
if ((res = mirisdr_set_sample_format(m_dev, s12FormatString))) // sample format S12
|
||||
@ -197,12 +199,11 @@ bool SDRPlayInput::start()
|
||||
m_sdrPlayThread->setFcPos((int) m_settings.m_fcPos);
|
||||
m_sdrPlayThread->setIQOrder(m_settings.m_iqOrder);
|
||||
m_sdrPlayThread->startWork();
|
||||
|
||||
// mutexLocker.unlock();
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true, true);
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -224,7 +225,13 @@ void SDRPlayInput::init()
|
||||
|
||||
void SDRPlayInput::stop()
|
||||
{
|
||||
// QMutexLocker mutexLocker(&m_mutex);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
|
||||
if(m_sdrPlayThread)
|
||||
{
|
||||
@ -232,8 +239,6 @@ void SDRPlayInput::stop()
|
||||
delete m_sdrPlayThread;
|
||||
m_sdrPlayThread = nullptr;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray SDRPlayInput::serialize() const
|
||||
|
@ -173,7 +173,7 @@ public:
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
QRecursiveMutex m_mutex;
|
||||
SDRPlayVariant m_variant;
|
||||
SDRPlaySettings m_settings;
|
||||
mirisdr_dev_t* m_dev;
|
||||
|
@ -147,20 +147,25 @@ bool SDRPlayV3Input::openDevice()
|
||||
|
||||
bool SDRPlayV3Input::start()
|
||||
{
|
||||
qDebug() << "SDRPlayV3Input::start";
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) stop();
|
||||
qDebug() << "SDRPlayV3Input::start";
|
||||
|
||||
m_sdrPlayThread = new SDRPlayV3Thread(m_dev, &m_sampleFifo, &m_replayBuffer);
|
||||
m_sdrPlayThread->setLog2Decimation(m_settings.m_log2Decim);
|
||||
m_sdrPlayThread->setFcPos((int) m_settings.m_fcPos);
|
||||
m_sdrPlayThread->startWork();
|
||||
|
||||
m_running = m_sdrPlayThread->isRunning();
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true, true);
|
||||
|
||||
return true;
|
||||
@ -184,17 +189,21 @@ void SDRPlayV3Input::init()
|
||||
|
||||
void SDRPlayV3Input::stop()
|
||||
{
|
||||
qDebug() << "SDRPlayV3Input::stop";
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "SDRPlayV3Input::stop";
|
||||
m_running = false;
|
||||
|
||||
if(m_sdrPlayThread)
|
||||
{
|
||||
m_sdrPlayThread->stopWork();
|
||||
delete m_sdrPlayThread;
|
||||
m_sdrPlayThread = nullptr;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray SDRPlayV3Input::serialize() const
|
||||
|
@ -158,7 +158,7 @@ public:
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
QRecursiveMutex m_mutex;
|
||||
SDRPlayV3Settings m_settings;
|
||||
sdrplay_api_DeviceT m_devs[SDRPLAY_MAX_DEVICES];
|
||||
sdrplay_api_DeviceT* m_dev;
|
||||
|
@ -62,19 +62,7 @@ MESSAGE_CLASS_DEFINITION(SigMFFileInput::MsgReportTotalSamplesCheck, Message)
|
||||
SigMFFileInput::SigMFFileInput(DeviceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_settings(),
|
||||
m_trackMode(false),
|
||||
m_currentTrackIndex(0),
|
||||
m_recordOpen(false),
|
||||
m_crcAvailable(false),
|
||||
m_crcOK(false),
|
||||
m_recordLengthOK(false),
|
||||
m_fileInputWorker(nullptr),
|
||||
m_deviceDescription("SigMFFileInput"),
|
||||
m_sampleRate(48000),
|
||||
m_sampleBytes(1),
|
||||
m_centerFrequency(0),
|
||||
m_recordLength(0),
|
||||
m_startingTimeStamp(0)
|
||||
m_deviceDescription("SigMFFileInput")
|
||||
{
|
||||
m_sampleFifo.setLabel(m_deviceDescription);
|
||||
m_deviceAPI->setNbSourceStreams(1);
|
||||
@ -103,7 +91,7 @@ SigMFFileInput::~SigMFFileInput()
|
||||
);
|
||||
delete m_networkManager;
|
||||
|
||||
stop();
|
||||
SigMFFileInput::stop();
|
||||
}
|
||||
|
||||
void SigMFFileInput::destroy()
|
||||
@ -155,8 +143,8 @@ bool SigMFFileInput::openFileStreams(const QString& fileName)
|
||||
extractCaptures(&metaRecord);
|
||||
m_metaInfo.m_totalTimeMs = m_captures.back().m_cumulativeTime + ((m_captures.back().m_length * 1000)/m_captures.back().m_sampleRate);
|
||||
|
||||
uint64_t centerFrequency = (m_captures.size() > 0) ? m_captures.at(0).m_centerFrequency : 0;
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(m_metaInfo.m_coreSampleRate, centerFrequency);
|
||||
uint64_t centerFrequency = (!m_captures.empty()) ? m_captures.at(0).m_centerFrequency : 0;
|
||||
auto *notif = new DSPSignalNotification((int) m_metaInfo.m_coreSampleRate, centerFrequency);
|
||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||
|
||||
if (getMessageQueueToGUI())
|
||||
@ -243,14 +231,13 @@ void SigMFFileInput::extractMeta(
|
||||
m_metaInfo.m_arch = QString::fromStdString(metaRecord->global.access<sdrangel::GlobalT>().arch);
|
||||
m_metaInfo.m_os = QString::fromStdString(metaRecord->global.access<sdrangel::GlobalT>().os);
|
||||
// lists
|
||||
m_metaInfo.m_nbCaptures = metaRecord->captures.size();
|
||||
m_metaInfo.m_nbAnnotations = metaRecord->annotations.size();
|
||||
m_metaInfo.m_nbCaptures = (unsigned int) metaRecord->captures.size();
|
||||
m_metaInfo.m_nbAnnotations = (unsigned int) metaRecord->annotations.size();
|
||||
// correct sample bits if sdrangel
|
||||
if (m_metaInfo.m_sdrAngelVersion.size() > 0)
|
||||
if ((m_metaInfo.m_sdrAngelVersion.size() > 0)
|
||||
&& (m_metaInfo.m_dataType.m_sampleBits == 32))
|
||||
{
|
||||
if (m_metaInfo.m_dataType.m_sampleBits == 32) {
|
||||
m_metaInfo.m_dataType.m_sampleBits = 24;
|
||||
}
|
||||
m_metaInfo.m_dataType.m_sampleBits = 24;
|
||||
}
|
||||
// negative sample rate means inversion
|
||||
m_metaInfo.m_dataType.m_swapIQ = m_metaInfo.m_coreSampleRate < 0;
|
||||
@ -269,8 +256,7 @@ void SigMFFileInput::extractCaptures(
|
||||
std::regex datetime_reg("(\\d{4})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d):(\\d\\d)(\\.\\d+)?(([+-]\\d\\d:\\d\\d)|Z)?");
|
||||
std::smatch datetime_match;
|
||||
|
||||
sigmf::SigMFVector<sigmf::Capture<core::DescrT, sdrangel::DescrT>>::iterator it =
|
||||
metaRecord->captures.begin();
|
||||
auto it = metaRecord->captures.begin();
|
||||
uint64_t lastSampleStart = 0;
|
||||
unsigned int i = 0;
|
||||
uint64_t cumulativeTime = 0;
|
||||
@ -278,7 +264,7 @@ void SigMFFileInput::extractCaptures(
|
||||
for (; it != metaRecord->captures.end(); ++it, i++)
|
||||
{
|
||||
m_captures.push_back(SigMFFileCapture());
|
||||
m_captures.back().m_centerFrequency = it->get<core::DescrT>().frequency;
|
||||
m_captures.back().m_centerFrequency = (uint64_t) it->get<core::DescrT>().frequency;
|
||||
m_captures.back().m_sampleStart = it->get<core::DescrT>().sample_start;
|
||||
m_captureStarts.push_back(m_captures.back().m_sampleStart);
|
||||
m_captures.back().m_cumulativeTime = cumulativeTime;
|
||||
@ -286,7 +272,7 @@ void SigMFFileInput::extractCaptures(
|
||||
double globalSampleRate = metaRecord->global.access<core::GlobalT>().sample_rate;
|
||||
|
||||
if (sdrangelSampleRate == 0) {
|
||||
m_captures.back().m_sampleRate = globalSampleRate < 0 ? -globalSampleRate : globalSampleRate;
|
||||
m_captures.back().m_sampleRate = (unsigned int) (globalSampleRate < 0 ? -globalSampleRate : globalSampleRate);
|
||||
} else {
|
||||
m_captures.back().m_sampleRate = sdrangelSampleRate;
|
||||
}
|
||||
@ -325,7 +311,7 @@ void SigMFFileInput::extractCaptures(
|
||||
dateTime = QDateTime::currentDateTimeUtc();
|
||||
}
|
||||
|
||||
double seconds = dateTime.toSecsSinceEpoch();
|
||||
auto seconds = (double) dateTime.toSecsSinceEpoch();
|
||||
// the subsecond part can be milli (strict ISO-8601) or micro or nano (RFC-3339). This will take any width
|
||||
if (datetime_match.size() > 7)
|
||||
{
|
||||
@ -334,13 +320,13 @@ void SigMFFileInput::extractCaptures(
|
||||
double fractionalSecs = boost::lexical_cast<double>(datetime_match[7]);
|
||||
seconds += fractionalSecs;
|
||||
}
|
||||
catch (const boost::bad_lexical_cast &e)
|
||||
catch (const boost::bad_lexical_cast&)
|
||||
{
|
||||
qDebug("SigMFFileInput::extractCaptures: invalid fractional seconds");
|
||||
}
|
||||
}
|
||||
|
||||
m_captures.back().m_tsms = seconds * 1000.0;
|
||||
m_captures.back().m_tsms = (uint64_t) (seconds * 1000.0);
|
||||
}
|
||||
|
||||
m_captures.back().m_length = it->get<core::DescrT>().length;
|
||||
@ -389,7 +375,7 @@ void SigMFFileInput::analyzeDataType(const std::string& dataTypeString, SigMFFil
|
||||
{
|
||||
dataType.m_sampleBits = boost::lexical_cast<int>(dataType_match[3]);
|
||||
}
|
||||
catch(const boost::bad_lexical_cast &e)
|
||||
catch(const boost::bad_lexical_cast&)
|
||||
{
|
||||
qDebug("SigMFFileInput::analyzeDataType: invalid sample bits. Assume 32");
|
||||
dataType.m_sampleBits = 32;
|
||||
@ -413,7 +399,7 @@ uint64_t SigMFFileInput::getTrackSampleStart(unsigned int trackIndex)
|
||||
int SigMFFileInput::getTrackIndex(uint64_t sampleIndex)
|
||||
{
|
||||
auto it = std::upper_bound(m_captureStarts.begin(), m_captureStarts.end(), sampleIndex);
|
||||
return (it - m_captureStarts.begin()) - 1;
|
||||
return (int) ((it - m_captureStarts.begin()) - 1);
|
||||
}
|
||||
|
||||
void SigMFFileInput::seekFileStream(uint64_t sampleIndex)
|
||||
@ -440,19 +426,24 @@ void SigMFFileInput::seekFileMillis(int seekMillis)
|
||||
|
||||
void SigMFFileInput::init()
|
||||
{
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
auto *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||
}
|
||||
|
||||
bool SigMFFileInput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_dataStream.is_open())
|
||||
{
|
||||
qWarning("SigMFFileInput::start: file not open. not starting");
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug() << "SigMFFileInput::start";
|
||||
|
||||
if (m_dataStream.tellg() != (std::streampos) 0) {
|
||||
@ -472,6 +463,7 @@ bool SigMFFileInput::start()
|
||||
m_fileInputWorker->setTrackIndex(0);
|
||||
m_fileInputWorker->moveToThread(&m_fileInputWorkerThread);
|
||||
m_deviceDescription = "SigMFFileInput";
|
||||
m_running = true;
|
||||
|
||||
mutexLocker.unlock();
|
||||
qDebug("SigMFFileInput::startInput: started");
|
||||
@ -486,9 +478,15 @@ bool SigMFFileInput::start()
|
||||
|
||||
void SigMFFileInput::stop()
|
||||
{
|
||||
qDebug() << "SigMFFileInput::stop";
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "SigMFFileInput::stop";
|
||||
m_running = false;
|
||||
|
||||
if (m_fileInputWorker)
|
||||
{
|
||||
stopWorker();
|
||||
@ -583,13 +581,13 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
{
|
||||
if (MsgConfigureSigMFFileInput::match(message))
|
||||
{
|
||||
MsgConfigureSigMFFileInput& conf = (MsgConfigureSigMFFileInput&) message;
|
||||
auto& conf = (const MsgConfigureSigMFFileInput&) message;
|
||||
applySettings(conf.getSettings(), conf.getSettingsKeys(), conf.getForce());
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureTrackIndex::match(message))
|
||||
{
|
||||
MsgConfigureTrackIndex& conf = (MsgConfigureTrackIndex&) message;
|
||||
auto& conf = (const MsgConfigureTrackIndex&) message;
|
||||
m_currentTrackIndex = conf.getTrackIndex();
|
||||
qDebug("SigMFFileInput::handleMessage MsgConfigureTrackIndex: m_currentTrackIndex: %d", m_currentTrackIndex);
|
||||
seekTrackMillis(0);
|
||||
@ -610,7 +608,7 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
);
|
||||
|
||||
if (working) {
|
||||
startWorker();
|
||||
startWorker();
|
||||
}
|
||||
}
|
||||
|
||||
@ -618,7 +616,7 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgConfigureTrackWork::match(message))
|
||||
{
|
||||
MsgConfigureTrackWork& conf = (MsgConfigureTrackWork&) message;
|
||||
auto& conf = (const MsgConfigureTrackWork&) message;
|
||||
bool working = conf.isWorking();
|
||||
m_trackMode = true;
|
||||
|
||||
@ -640,7 +638,7 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgConfigureTrackSeek::match(message))
|
||||
{
|
||||
MsgConfigureTrackSeek& conf = (MsgConfigureTrackSeek&) message;
|
||||
auto& conf = (const MsgConfigureTrackSeek&) message;
|
||||
int seekMillis = conf.getMillis();
|
||||
seekTrackMillis(seekMillis);
|
||||
|
||||
@ -656,7 +654,7 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
m_captures[m_currentTrackIndex].m_sampleStart + ((m_captures[m_currentTrackIndex].m_length*seekMillis)/1000UL));
|
||||
|
||||
if (working) {
|
||||
startWorker();
|
||||
startWorker();
|
||||
}
|
||||
}
|
||||
|
||||
@ -664,7 +662,7 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgConfigureFileSeek::match(message))
|
||||
{
|
||||
MsgConfigureFileSeek& conf = (MsgConfigureFileSeek&) message;
|
||||
auto& conf = (const MsgConfigureFileSeek&) message;
|
||||
int seekMillis = conf.getMillis();
|
||||
seekFileStream(seekMillis);
|
||||
uint64_t sampleCount = (m_metaInfo.m_totalSamples*seekMillis)/1000UL;
|
||||
@ -682,7 +680,7 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
m_fileInputWorker->setSamplesCount(sampleCount);
|
||||
|
||||
if (working) {
|
||||
startWorker();
|
||||
startWorker();
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,7 +688,7 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgConfigureFileWork::match(message))
|
||||
{
|
||||
MsgConfigureFileWork& conf = (MsgConfigureFileWork&) message;
|
||||
auto& conf = (const MsgConfigureFileWork&) message;
|
||||
bool working = conf.isWorking();
|
||||
m_trackMode = false;
|
||||
|
||||
@ -711,27 +709,24 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgConfigureFileInputStreamTiming::match(message))
|
||||
{
|
||||
if (m_fileInputWorker)
|
||||
if (m_fileInputWorker && getMessageQueueToGUI())
|
||||
{
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
quint64 totalSamplesCount = m_fileInputWorker->getSamplesCount();
|
||||
quint64 trackSamplesCount = totalSamplesCount - m_captures[m_currentTrackIndex].m_sampleStart;
|
||||
MsgReportFileInputStreamTiming *report = MsgReportFileInputStreamTiming::create(
|
||||
totalSamplesCount,
|
||||
trackSamplesCount,
|
||||
m_captures[m_currentTrackIndex].m_cumulativeTime,
|
||||
m_currentTrackIndex
|
||||
);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
quint64 totalSamplesCount = m_fileInputWorker->getSamplesCount();
|
||||
quint64 trackSamplesCount = totalSamplesCount - m_captures[m_currentTrackIndex].m_sampleStart;
|
||||
MsgReportFileInputStreamTiming *report = MsgReportFileInputStreamTiming::create(
|
||||
totalSamplesCount,
|
||||
trackSamplesCount,
|
||||
m_captures[m_currentTrackIndex].m_cumulativeTime,
|
||||
m_currentTrackIndex
|
||||
);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgStartStop::match(message))
|
||||
{
|
||||
MsgStartStop& cmd = (MsgStartStop&) message;
|
||||
auto& cmd = (const MsgStartStop&) message;
|
||||
qDebug() << "FileInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
|
||||
|
||||
if (cmd.getStartStop())
|
||||
@ -785,7 +780,7 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (SigMFFileInputWorker::MsgReportTrackChange::match(message))
|
||||
{
|
||||
SigMFFileInputWorker::MsgReportTrackChange& report = (SigMFFileInputWorker::MsgReportTrackChange&) message;
|
||||
auto& report = (const SigMFFileInputWorker::MsgReportTrackChange&) message;
|
||||
m_currentTrackIndex = report.getTrackIndex();
|
||||
qDebug("SigMFFileInput::handleMessage MsgReportTrackChange: m_currentTrackIndex: %d", m_currentTrackIndex);
|
||||
int sampleRate = m_captures.at(m_currentTrackIndex).m_sampleRate;
|
||||
@ -793,7 +788,7 @@ bool SigMFFileInput::handleMessage(const Message& message)
|
||||
|
||||
if ((m_sampleRate != sampleRate) || (m_centerFrequency != centerFrequency))
|
||||
{
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, centerFrequency);
|
||||
auto *notif = new DSPSignalNotification(sampleRate, centerFrequency);
|
||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||
|
||||
m_sampleRate = sampleRate;
|
||||
@ -818,18 +813,15 @@ bool SigMFFileInput::applySettings(const SigMFFileInputSettings& settings, const
|
||||
{
|
||||
qDebug() << "SigMFFileInput::applySettings: force: " << force << settings.getDebugString(settingsKeys, force);
|
||||
|
||||
if (settingsKeys.contains("accelerationFactor") || force)
|
||||
if (m_fileInputWorker && (settingsKeys.contains("accelerationFactor") || force))
|
||||
{
|
||||
if (m_fileInputWorker)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
if (!m_sampleFifo.setSize(m_settings.m_accelerationFactor * m_sampleRate * sizeof(Sample))) {
|
||||
qCritical("SigMFFileInput::applySettings: could not reallocate sample FIFO size to %lu",
|
||||
m_settings.m_accelerationFactor * m_sampleRate * sizeof(Sample));
|
||||
}
|
||||
|
||||
m_fileInputWorker->setAccelerationFactor(settings.m_accelerationFactor); // Fast Forward: 1 corresponds to live. 1/2 is half speed, 2 is double speed
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
if (!m_sampleFifo.setSize(m_settings.m_accelerationFactor * m_sampleRate * sizeof(Sample))) {
|
||||
qCritical("SigMFFileInput::applySettings: could not reallocate sample FIFO size to %lu",
|
||||
m_settings.m_accelerationFactor * m_sampleRate * sizeof(Sample));
|
||||
}
|
||||
|
||||
m_fileInputWorker->setAccelerationFactor(settings.m_accelerationFactor); // Fast Forward: 1 corresponds to live. 1/2 is half speed, 2 is double speed
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("fileName")) {
|
||||
@ -912,10 +904,10 @@ void SigMFFileInput::webapiUpdateDeviceSettings(
|
||||
settings.m_reverseAPIAddress = *response.getSigMfFileInputSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getSigMfFileInputSettings()->getReverseApiPort();
|
||||
settings.m_reverseAPIPort = (uint16_t) response.getSigMfFileInputSettings()->getReverseApiPort();
|
||||
}
|
||||
if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getSigMfFileInputSettings()->getReverseApiDeviceIndex();
|
||||
settings.m_reverseAPIDeviceIndex = (uint16_t) response.getSigMfFileInputSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1067,7 +1059,11 @@ void SigMFFileInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& resp
|
||||
response.getSigMfFileInputReport()->setSampleFormat(m_metaInfo.m_dataType.m_floatingPoint ? 1 : 0);
|
||||
response.getSigMfFileInputReport()->setSampleSigned(m_metaInfo.m_dataType.m_signed ? 1 : 0);
|
||||
response.getSigMfFileInputReport()->setSampleSwapIq(m_metaInfo.m_dataType.m_swapIQ ? 1 : 0);
|
||||
response.getSigMfFileInputReport()->setCrcStatus(!m_crcAvailable ? 0 : m_crcOK ? 1 : 2);
|
||||
if (!m_crcAvailable) {
|
||||
response.getSigMfFileInputReport()->setCrcStatus(0);
|
||||
} else {
|
||||
response.getSigMfFileInputReport()->setCrcStatus(m_crcOK ? 1 : 2);
|
||||
}
|
||||
response.getSigMfFileInputReport()->setTotalBytesStatus(m_recordLengthOK);
|
||||
response.getSigMfFileInputReport()->setTrackNumber(m_currentTrackIndex);
|
||||
QList<SigMFFileCapture>::const_iterator it = m_captures.begin();
|
||||
@ -1111,7 +1107,7 @@ void SigMFFileInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& resp
|
||||
posRatio = (float) totalSamplesCount / (float) m_metaInfo.m_totalSamples;
|
||||
response.getSigMfFileInputReport()->setRecordSamplesRatio(posRatio);
|
||||
|
||||
if (m_captures.size() > 0 )
|
||||
if (!m_captures.empty() )
|
||||
{
|
||||
uint64_t totalTimeMs = m_captures.back().m_cumulativeTime + ((m_captures.back().m_length * 1000) / m_captures.back().m_sampleRate);
|
||||
response.getSigMfFileInputReport()->setRecordDurationMs(totalTimeMs);
|
||||
@ -1124,7 +1120,7 @@ void SigMFFileInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& resp
|
||||
|
||||
void SigMFFileInput::webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const SigMFFileInputSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(0); // single Rx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("SigMFFileInput"));
|
||||
@ -1153,8 +1149,8 @@ void SigMFFileInput::webapiReverseSendSettings(const QList<QString>& deviceSetti
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
@ -1167,7 +1163,7 @@ void SigMFFileInput::webapiReverseSendSettings(const QList<QString>& deviceSetti
|
||||
|
||||
void SigMFFileInput::webapiReverseSendStartStop(bool start)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
auto *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||
swgDeviceSettings->setDirection(0); // single Rx
|
||||
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
|
||||
swgDeviceSettings->setDeviceHwType(new QString("SigMFFileInput"));
|
||||
@ -1179,8 +1175,8 @@ void SigMFFileInput::webapiReverseSendStartStop(bool start)
|
||||
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
auto *buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(swgDeviceSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
QNetworkReply *reply;
|
||||
@ -1195,7 +1191,7 @@ void SigMFFileInput::webapiReverseSendStartStop(bool start)
|
||||
delete swgDeviceSettings;
|
||||
}
|
||||
|
||||
void SigMFFileInput::networkManagerFinished(QNetworkReply *reply)
|
||||
void SigMFFileInput::networkManagerFinished(QNetworkReply *reply) const
|
||||
{
|
||||
QNetworkReply::NetworkError replyError = reply->error();
|
||||
|
||||
|
@ -86,7 +86,7 @@ public:
|
||||
private:
|
||||
bool m_working;
|
||||
|
||||
MsgConfigureTrackWork(bool working) :
|
||||
explicit MsgConfigureTrackWork(bool working) :
|
||||
Message(),
|
||||
m_working(working)
|
||||
{ }
|
||||
@ -109,7 +109,7 @@ public:
|
||||
private:
|
||||
bool m_working;
|
||||
|
||||
MsgConfigureFileWork(bool working) :
|
||||
explicit MsgConfigureFileWork(bool working) :
|
||||
Message(),
|
||||
m_working(working)
|
||||
{ }
|
||||
@ -132,7 +132,7 @@ public:
|
||||
private:
|
||||
int m_trackIndex;
|
||||
|
||||
MsgConfigureTrackIndex(int trackIndex) :
|
||||
explicit MsgConfigureTrackIndex(int trackIndex) :
|
||||
Message(),
|
||||
m_trackIndex(trackIndex)
|
||||
{ }
|
||||
@ -152,10 +152,10 @@ public:
|
||||
return new MsgConfigureTrackSeek(seekMillis);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
int m_seekMillis; //!< millis of seek position from the beginning 0..1000
|
||||
|
||||
MsgConfigureTrackSeek(int seekMillis) :
|
||||
explicit MsgConfigureTrackSeek(int seekMillis) :
|
||||
Message(),
|
||||
m_seekMillis(seekMillis)
|
||||
{ }
|
||||
@ -175,10 +175,10 @@ public:
|
||||
return new MsgConfigureFileSeek(seekMillis);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
int m_seekMillis; //!< millis of seek position from the beginning 0..1000
|
||||
|
||||
MsgConfigureFileSeek(int seekMillis) :
|
||||
explicit MsgConfigureFileSeek(int seekMillis) :
|
||||
Message(),
|
||||
m_seekMillis(seekMillis)
|
||||
{ }
|
||||
@ -217,10 +217,10 @@ public:
|
||||
return new MsgStartStop(startStop);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool m_startStop;
|
||||
|
||||
MsgStartStop(bool startStop) :
|
||||
explicit MsgStartStop(bool startStop) :
|
||||
Message(),
|
||||
m_startStop(startStop)
|
||||
{ }
|
||||
@ -240,10 +240,10 @@ public:
|
||||
return new MsgReportStartStop(startStop);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool m_startStop;
|
||||
|
||||
MsgReportStartStop(bool startStop) :
|
||||
explicit MsgReportStartStop(bool startStop) :
|
||||
Message(),
|
||||
m_startStop(startStop)
|
||||
{ }
|
||||
@ -257,13 +257,13 @@ public:
|
||||
|
||||
public:
|
||||
const SigMFFileMetaInfo& getMetaInfo() const { return m_metaInfo; }
|
||||
const QList<SigMFFileCapture>& getCaptures() { return m_captures; }
|
||||
const QList<SigMFFileCapture>& getCaptures() const { return m_captures; }
|
||||
|
||||
static MsgReportMetaData* create(const SigMFFileMetaInfo& metaInfo, const QList<SigMFFileCapture>& captures) {
|
||||
return new MsgReportMetaData(metaInfo, captures);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
SigMFFileMetaInfo m_metaInfo;
|
||||
QList<SigMFFileCapture> m_captures;
|
||||
|
||||
@ -288,7 +288,7 @@ public:
|
||||
|
||||
private:
|
||||
int m_trackIndex;
|
||||
MsgReportTrackChange(int trackIndex) :
|
||||
explicit MsgReportTrackChange(int trackIndex) :
|
||||
Message(),
|
||||
m_trackIndex(trackIndex)
|
||||
{ }
|
||||
@ -321,7 +321,7 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
quint64 m_samplesCount;
|
||||
quint64 m_trackSamplesCount;
|
||||
quint64 m_trackTimeStart;
|
||||
@ -354,10 +354,10 @@ public:
|
||||
return new MsgReportCRC(ok);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool m_ok;
|
||||
|
||||
MsgReportCRC(bool ok) :
|
||||
explicit MsgReportCRC(bool ok) :
|
||||
Message(),
|
||||
m_ok(ok)
|
||||
{ }
|
||||
@ -376,97 +376,98 @@ public:
|
||||
return new MsgReportTotalSamplesCheck(ok);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool m_ok;
|
||||
|
||||
MsgReportTotalSamplesCheck(bool ok) :
|
||||
explicit MsgReportTotalSamplesCheck(bool ok) :
|
||||
Message(),
|
||||
m_ok(ok)
|
||||
{ }
|
||||
};
|
||||
|
||||
SigMFFileInput(DeviceAPI *deviceAPI);
|
||||
virtual ~SigMFFileInput();
|
||||
virtual void destroy();
|
||||
explicit SigMFFileInput(DeviceAPI *deviceAPI);
|
||||
~SigMFFileInput() final;
|
||||
void destroy() final;
|
||||
|
||||
virtual void init();
|
||||
virtual bool start();
|
||||
virtual void stop();
|
||||
void init() final;
|
||||
bool start() final;
|
||||
void stop() final;
|
||||
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
QByteArray serialize() const final;
|
||||
bool deserialize(const QByteArray& data) final;
|
||||
|
||||
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
|
||||
virtual const QString& getDeviceDescription() const;
|
||||
virtual int getSampleRate() const;
|
||||
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
|
||||
virtual quint64 getCenterFrequency() const;
|
||||
virtual void setCenterFrequency(qint64 centerFrequency);
|
||||
void setMessageQueueToGUI(MessageQueue *queue) final { m_guiMessageQueue = queue; }
|
||||
const QString& getDeviceDescription() const final;
|
||||
int getSampleRate() const final;
|
||||
void setSampleRate(int sampleRate) final { (void) sampleRate; }
|
||||
quint64 getCenterFrequency() const final;
|
||||
void setCenterFrequency(qint64 centerFrequency) final;
|
||||
quint64 getStartingTimeStamp() const;
|
||||
|
||||
virtual bool handleMessage(const Message& message);
|
||||
bool handleMessage(const Message& message) final;
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage);
|
||||
int webapiSettingsGet(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage);
|
||||
int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRunGet(
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiActionsPost(
|
||||
const QStringList& deviceActionsKeys,
|
||||
SWGSDRangel::SWGDeviceActions& query,
|
||||
QString& errorMessage);
|
||||
int webapiActionsPost(
|
||||
const QStringList& deviceActionsKeys,
|
||||
SWGSDRangel::SWGDeviceActions& query,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage);
|
||||
int webapiRun(
|
||||
bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
virtual int webapiReportGet(
|
||||
SWGSDRangel::SWGDeviceReport& response,
|
||||
QString& errorMessage);
|
||||
int webapiReportGet(
|
||||
SWGSDRangel::SWGDeviceReport& response,
|
||||
QString& errorMessage) final;
|
||||
|
||||
static void webapiFormatDeviceSettings(
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
const SigMFFileInputSettings& settings);
|
||||
SWGSDRangel::SWGDeviceSettings& response,
|
||||
const SigMFFileInputSettings& settings);
|
||||
|
||||
static void webapiUpdateDeviceSettings(
|
||||
SigMFFileInputSettings& settings,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response);
|
||||
SigMFFileInputSettings& settings,
|
||||
const QStringList& deviceSettingsKeys,
|
||||
SWGSDRangel::SWGDeviceSettings& response);
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QMutex m_mutex;
|
||||
bool m_running = false;
|
||||
SigMFFileInputSettings m_settings;
|
||||
std::ifstream m_metaStream;
|
||||
std::ifstream m_dataStream;
|
||||
SigMFFileMetaInfo m_metaInfo;
|
||||
QList<SigMFFileCapture> m_captures;
|
||||
std::vector<uint64_t> m_captureStarts;
|
||||
bool m_trackMode;
|
||||
int m_currentTrackIndex;
|
||||
bool m_recordOpen;
|
||||
bool m_crcAvailable;
|
||||
bool m_crcOK;
|
||||
bool m_recordLengthOK;
|
||||
bool m_trackMode = false;
|
||||
int m_currentTrackIndex = 0;
|
||||
bool m_recordOpen = false;
|
||||
bool m_crcAvailable = false;
|
||||
bool m_crcOK = false;
|
||||
bool m_recordLengthOK = false;
|
||||
QString m_recordSummary;
|
||||
SigMFFileInputWorker* m_fileInputWorker;
|
||||
SigMFFileInputWorker* m_fileInputWorker = nullptr;
|
||||
QThread m_fileInputWorkerThread;
|
||||
QString m_deviceDescription;
|
||||
int m_sampleRate;
|
||||
unsigned int m_sampleBytes;
|
||||
quint64 m_centerFrequency;
|
||||
quint64 m_recordLength; //!< record length in seconds computed from file size
|
||||
quint64 m_startingTimeStamp;
|
||||
int m_sampleRate = 48000;
|
||||
unsigned int m_sampleBytes = 1;
|
||||
quint64 m_centerFrequency = 0;
|
||||
quint64 m_recordLength = 0; //!< record length in seconds computed from file size
|
||||
quint64 m_startingTimeStamp = 0;
|
||||
QTimer m_masterTimer;
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
@ -497,7 +498,7 @@ private:
|
||||
void webapiReverseSendStartStop(bool start);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void networkManagerFinished(QNetworkReply *reply) const;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_SIGMFFILEINPUT_H
|
||||
|
@ -481,6 +481,11 @@ bool SoapySDRInput::start()
|
||||
//
|
||||
// Note: this is quite similar to the BladeRF2 start handling. The main difference is that the channel allocation (enabling) process is
|
||||
// done in the thread object.
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_openSuccess)
|
||||
{
|
||||
@ -595,11 +600,13 @@ void SoapySDRInput::stop()
|
||||
//
|
||||
// Note: this is quite similar to the BladeRF2 stop handling. The main difference is that the channel allocation (enabling) process is
|
||||
// done in the thread object.
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
int requestedChannel = m_deviceAPI->getDeviceItemIndex();
|
||||
SoapySDRInputThread *soapySDRInputThread = findThread();
|
||||
|
||||
@ -688,8 +695,6 @@ void SoapySDRInput::stop()
|
||||
qDebug("SoapySDRInput::stop: MI mode. Not changing MI configuration. Just remove FIFO reference");
|
||||
soapySDRInputThread->setFifo(requestedChannel, nullptr); // remove FIFO
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
QByteArray SoapySDRInput::serialize() const
|
||||
|
@ -119,11 +119,16 @@ bool TestSourceInput::start()
|
||||
void TestSourceInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
|
||||
if (m_testSourceWorkerThread)
|
||||
{
|
||||
m_testSourceWorker->stopWork();
|
||||
m_testSourceWorker->stopWork();
|
||||
m_testSourceWorkerThread->quit();
|
||||
m_testSourceWorkerThread->wait();
|
||||
m_testSourceWorker = nullptr;
|
||||
|
@ -414,14 +414,17 @@ void USRPInput::init()
|
||||
|
||||
bool USRPInput::start()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_deviceShared.m_deviceParams->getDevice()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_running) { stop(); }
|
||||
|
||||
if (!acquireChannel())
|
||||
{
|
||||
if (!acquireChannel()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -441,7 +444,14 @@ bool USRPInput::start()
|
||||
|
||||
void USRPInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("USRPInput::stop");
|
||||
m_running = false;
|
||||
|
||||
if (m_usrpInputThread)
|
||||
{
|
||||
@ -451,7 +461,6 @@ void USRPInput::stop()
|
||||
}
|
||||
|
||||
m_deviceShared.m_thread = 0;
|
||||
m_running = false;
|
||||
|
||||
releaseChannel();
|
||||
}
|
||||
|
@ -275,6 +275,11 @@ bool XTRXInput::start()
|
||||
//
|
||||
// Eventually it registers the FIFO in the thread. If the thread has to be started it enables the channels up to the number of channels
|
||||
// allocated in the thread and starts the thread.
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (m_running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_deviceShared.m_dev || !m_deviceShared.m_dev->getDevice())
|
||||
{
|
||||
@ -353,8 +358,6 @@ bool XTRXInput::start()
|
||||
xtrxInputThread->setFifo(requestedChannel, &m_sampleFifo);
|
||||
xtrxInputThread->setLog2Decimation(requestedChannel, m_settings.m_log2SoftDecim);
|
||||
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
if (needsStart)
|
||||
{
|
||||
qDebug("XTRXInput::start: (re)start thread");
|
||||
@ -364,6 +367,9 @@ bool XTRXInput::start()
|
||||
qDebug("XTRXInput::start: started");
|
||||
m_running = true;
|
||||
|
||||
m_mutex.unlock();
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -377,11 +383,13 @@ void XTRXInput::stop()
|
||||
// If the thread is currently managing both channels (MI mode) then we are removing one channel. Thus we must
|
||||
// transition from MI to SI. This transition is handled by stopping the thread, deleting it and creating a new one
|
||||
// managing a single channel.
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
int removedChannel = m_deviceAPI->getDeviceItemIndex(); // channel to remove
|
||||
int requestedChannel = removedChannel ^ 1; // channel to keep (opposite channel)
|
||||
XTRXInputThread *xtrxInputThread = findThread();
|
||||
@ -432,8 +440,6 @@ void XTRXInput::stop()
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
xtrxInputThread->startWork();
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
void XTRXInput::suspendTxThread()
|
||||
|
@ -65,9 +65,7 @@ DeviceAPI::DeviceAPI(
|
||||
}
|
||||
}
|
||||
|
||||
DeviceAPI::~DeviceAPI()
|
||||
{
|
||||
}
|
||||
DeviceAPI::~DeviceAPI() = default;
|
||||
|
||||
void DeviceAPI::setSpectrumSinkInput(bool sourceElseSink, unsigned int index)
|
||||
{
|
||||
@ -269,7 +267,7 @@ DeviceAPI::EngineState DeviceAPI::state(int subsystemIndex) const
|
||||
}
|
||||
}
|
||||
|
||||
QString DeviceAPI::errorMessage(int subsystemIndex)
|
||||
QString DeviceAPI::errorMessage(int subsystemIndex) const
|
||||
{
|
||||
if (m_deviceSourceEngine) {
|
||||
return m_deviceSourceEngine->errorMessage();
|
||||
@ -360,28 +358,28 @@ void DeviceAPI::setDeviceItemIndex(uint32_t index)
|
||||
|
||||
void DeviceAPI::setSamplingDevicePluginInterface(PluginInterface *iface)
|
||||
{
|
||||
m_pluginInterface = iface;
|
||||
m_pluginInterface = iface;
|
||||
}
|
||||
|
||||
void DeviceAPI::getDeviceEngineStateStr(QString& state, int subsystemIndex)
|
||||
void DeviceAPI::getDeviceEngineStateStr(QString& state, int subsystemIndex) const
|
||||
{
|
||||
if (m_deviceSourceEngine)
|
||||
{
|
||||
switch(m_deviceSourceEngine->state())
|
||||
{
|
||||
case DSPDeviceSourceEngine::StNotStarted:
|
||||
case DSPDeviceSourceEngine::State::StNotStarted:
|
||||
state = "notStarted";
|
||||
break;
|
||||
case DSPDeviceSourceEngine::StIdle:
|
||||
case DSPDeviceSourceEngine::State::StIdle:
|
||||
state = "idle";
|
||||
break;
|
||||
case DSPDeviceSourceEngine::StReady:
|
||||
case DSPDeviceSourceEngine::State::StReady:
|
||||
state = "ready";
|
||||
break;
|
||||
case DSPDeviceSourceEngine::StRunning:
|
||||
case DSPDeviceSourceEngine::State::StRunning:
|
||||
state = "running";
|
||||
break;
|
||||
case DSPDeviceSourceEngine::StError:
|
||||
case DSPDeviceSourceEngine::State::StError:
|
||||
state = "error";
|
||||
break;
|
||||
default:
|
||||
@ -393,19 +391,19 @@ void DeviceAPI::getDeviceEngineStateStr(QString& state, int subsystemIndex)
|
||||
{
|
||||
switch(m_deviceSinkEngine->state())
|
||||
{
|
||||
case DSPDeviceSinkEngine::StNotStarted:
|
||||
case DSPDeviceSinkEngine::State::StNotStarted:
|
||||
state = "notStarted";
|
||||
break;
|
||||
case DSPDeviceSinkEngine::StIdle:
|
||||
case DSPDeviceSinkEngine::State::StIdle:
|
||||
state = "idle";
|
||||
break;
|
||||
case DSPDeviceSinkEngine::StReady:
|
||||
case DSPDeviceSinkEngine::State::StReady:
|
||||
state = "ready";
|
||||
break;
|
||||
case DSPDeviceSinkEngine::StRunning:
|
||||
case DSPDeviceSinkEngine::State::StRunning:
|
||||
state = "running";
|
||||
break;
|
||||
case DSPDeviceSinkEngine::StError:
|
||||
case DSPDeviceSinkEngine::State::StError:
|
||||
state = "error";
|
||||
break;
|
||||
default:
|
||||
@ -417,19 +415,19 @@ void DeviceAPI::getDeviceEngineStateStr(QString& state, int subsystemIndex)
|
||||
{
|
||||
switch(m_deviceMIMOEngine->state(subsystemIndex))
|
||||
{
|
||||
case DSPDeviceMIMOEngine::StNotStarted:
|
||||
case DSPDeviceMIMOEngine::State::StNotStarted:
|
||||
state = "notStarted";
|
||||
break;
|
||||
case DSPDeviceMIMOEngine::StIdle:
|
||||
case DSPDeviceMIMOEngine::State::StIdle:
|
||||
state = "idle";
|
||||
break;
|
||||
case DSPDeviceMIMOEngine::StReady:
|
||||
case DSPDeviceMIMOEngine::State::StReady:
|
||||
state = "ready";
|
||||
break;
|
||||
case DSPDeviceMIMOEngine::StRunning:
|
||||
case DSPDeviceMIMOEngine::State::StRunning:
|
||||
state = "running";
|
||||
break;
|
||||
case DSPDeviceMIMOEngine::StError:
|
||||
case DSPDeviceMIMOEngine::State::StError:
|
||||
state = "error";
|
||||
break;
|
||||
default:
|
||||
@ -546,26 +544,26 @@ bool DeviceAPI::deserialize(const QByteArray& data)
|
||||
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray data;
|
||||
QByteArray bdata;
|
||||
QList<quint64> centerFrequency;
|
||||
|
||||
if (m_deviceSourceEngine && m_deviceSourceEngine->getSource())
|
||||
{
|
||||
d.readBlob(1, &data);
|
||||
d.readBlob(1, &bdata);
|
||||
if (data.size() > 0) {
|
||||
m_deviceSourceEngine->getSource()->deserialize(data);
|
||||
}
|
||||
}
|
||||
if (m_deviceSinkEngine && m_deviceSinkEngine->getSink())
|
||||
{
|
||||
d.readBlob(2, &data);
|
||||
d.readBlob(2, &bdata);
|
||||
if (data.size() > 0) {
|
||||
m_deviceSinkEngine->getSink()->deserialize(data);
|
||||
}
|
||||
}
|
||||
if (m_deviceMIMOEngine && m_deviceMIMOEngine->getMIMO())
|
||||
{
|
||||
d.readBlob(3, &data);
|
||||
d.readBlob(3, &bdata);
|
||||
if (data.size() > 0) {
|
||||
m_deviceMIMOEngine->getMIMO()->deserialize(data);
|
||||
}
|
||||
@ -596,7 +594,7 @@ void DeviceAPI::loadSamplingDeviceSettings(const Preset* preset)
|
||||
qDebug("DeviceAPI::loadSamplingDeviceSettings: deserializing source %s[%d]: %s",
|
||||
qPrintable(m_samplingDeviceId), m_samplingDeviceSequence, qPrintable(m_samplingDeviceSerial));
|
||||
|
||||
if (m_deviceSourceEngine->getSource() != 0) // Server flavor
|
||||
if (m_deviceSourceEngine->getSource() != nullptr) // Server flavor
|
||||
{
|
||||
m_deviceSourceEngine->getSource()->deserialize(*sourceConfig);
|
||||
}
|
||||
@ -791,8 +789,8 @@ void DeviceAPI::removeBuddy(DeviceAPI* buddy)
|
||||
|
||||
void DeviceAPI::clearBuddiesLists()
|
||||
{
|
||||
std::vector<DeviceAPI*>::iterator itSource = m_sourceBuddies.begin();
|
||||
std::vector<DeviceAPI*>::iterator itSink = m_sinkBuddies.begin();
|
||||
auto itSource = m_sourceBuddies.begin();
|
||||
auto itSink = m_sinkBuddies.begin();
|
||||
bool leaderElected = false;
|
||||
|
||||
for (;itSource != m_sourceBuddies.end(); ++itSource)
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
DSPDeviceSinkEngine *deviceSinkEngine,
|
||||
DSPDeviceMIMOEngine *deviceMIMOEngine
|
||||
);
|
||||
~DeviceAPI();
|
||||
~DeviceAPI() override;
|
||||
|
||||
void setSpectrumSinkInput(bool sourceElseSink = true, unsigned int index = 0); //!< Used in the MIMO case to select which stream is used as input to main spectrum
|
||||
|
||||
@ -94,7 +94,7 @@ public:
|
||||
bool startDeviceEngine(int subsystemIndex = 0); //!< Start the device engine corresponding to the stream type
|
||||
void stopDeviceEngine(int subsystemIndex = 0); //!< Stop the device engine corresponding to the stream type
|
||||
EngineState state(int subsystemIndex = 0) const; //!< Return the state of the device engine corresponding to the stream type
|
||||
QString errorMessage(int subsystemIndex = 0); //!< Last error message from the device engine
|
||||
QString errorMessage(int subsystemIndex = 0) const; //!< Last error message from the device engine
|
||||
uint getDeviceUID() const; //!< Return the current device engine unique ID
|
||||
|
||||
MessageQueue *getDeviceEngineInputMessageQueue(); //!< Device engine message queue
|
||||
@ -131,7 +131,7 @@ public:
|
||||
void setDeviceSetIndex(int deviceSetIndex);
|
||||
PluginInterface *getPluginInterface() { return m_pluginInterface; }
|
||||
|
||||
void getDeviceEngineStateStr(QString& state, int subsystemIndex = 0);
|
||||
void getDeviceEngineStateStr(QString& state, int subsystemIndex = 0) const;
|
||||
|
||||
ChannelAPI *getChanelSinkAPIAt(int index);
|
||||
ChannelAPI *getChanelSourceAPIAt(int index);
|
||||
@ -142,11 +142,7 @@ public:
|
||||
int getNbMIMOChannels() const { return m_mimoChannelAPIs.size(); }
|
||||
|
||||
void loadSamplingDeviceSettings(const Preset* preset);
|
||||
// void loadSourceSettings(const Preset* preset);
|
||||
// void loadSinkSettings(const Preset* preset);
|
||||
void saveSamplingDeviceSettings(Preset* preset);
|
||||
// void saveSourceSettings(Preset* preset);
|
||||
// void saveSinkSettings(Preset* preset);
|
||||
|
||||
QByteArray serialize() const override;
|
||||
bool deserialize(const QByteArray& data) override;
|
||||
@ -176,7 +172,7 @@ public:
|
||||
|
||||
const QTimer& getMasterTimer() const { return m_masterTimer; } //!< This is the DSPEngine master timer
|
||||
|
||||
protected:
|
||||
private:
|
||||
// common
|
||||
|
||||
StreamType m_streamType;
|
||||
@ -217,7 +213,6 @@ protected:
|
||||
DSPDeviceMIMOEngine *m_deviceMIMOEngine;
|
||||
QList<ChannelAPI*> m_mimoChannelAPIs;
|
||||
|
||||
private:
|
||||
void renumerateChannels();
|
||||
|
||||
private slots:
|
||||
|
@ -59,7 +59,7 @@ void DeviceSet::freeChannels()
|
||||
for(int i = 0; i < m_channelInstanceRegistrations.count(); i++)
|
||||
{
|
||||
qDebug("DeviceSet::freeChannels: destroying channel [%s]", qPrintable(m_channelInstanceRegistrations[i]->getURI()));
|
||||
m_channelInstanceRegistrations[i]->destroy();
|
||||
delete m_channelInstanceRegistrations[i];
|
||||
}
|
||||
|
||||
MainCore::instance()->clearChannels(this);
|
||||
@ -87,7 +87,7 @@ void DeviceSet::deleteChannel(int channelIndex)
|
||||
{
|
||||
if (channelIndex < m_channelInstanceRegistrations.count())
|
||||
{
|
||||
m_channelInstanceRegistrations[channelIndex]->destroy();
|
||||
delete m_channelInstanceRegistrations[channelIndex];
|
||||
m_channelInstanceRegistrations.removeAt(channelIndex);
|
||||
MainCore::instance()->removeChannelInstanceAt(this, channelIndex);
|
||||
renameChannelInstances();
|
||||
@ -141,7 +141,7 @@ void DeviceSet::loadRxChannelSettings(const Preset *preset, PluginAPI *pluginAPI
|
||||
PluginAPI::ChannelRegistrations *channelRegistrations = pluginAPI->getRxChannelRegistrations();
|
||||
|
||||
// copy currently open channels and clear list
|
||||
ChannelInstanceRegistrations openChannels = m_channelInstanceRegistrations;
|
||||
QList<ChannelAPI*> openChannels = m_channelInstanceRegistrations;
|
||||
m_channelInstanceRegistrations.clear();
|
||||
mainCore->clearChannels(this);
|
||||
|
||||
@ -241,7 +241,7 @@ void DeviceSet::loadTxChannelSettings(const Preset *preset, PluginAPI *pluginAPI
|
||||
PluginAPI::ChannelRegistrations *channelRegistrations = pluginAPI->getTxChannelRegistrations();
|
||||
|
||||
// copy currently open channels and clear list
|
||||
ChannelInstanceRegistrations openChannels = m_channelInstanceRegistrations;
|
||||
QList<ChannelAPI*> openChannels = m_channelInstanceRegistrations;
|
||||
m_channelInstanceRegistrations.clear();
|
||||
mainCore->clearChannels(this);
|
||||
|
||||
@ -339,7 +339,7 @@ void DeviceSet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
PluginAPI::ChannelRegistrations *channelRegistrations = pluginAPI->getMIMOChannelRegistrations();
|
||||
|
||||
// copy currently open channels and clear list
|
||||
ChannelInstanceRegistrations openChannels = m_channelInstanceRegistrations;
|
||||
QList<ChannelAPI*> openChannels = m_channelInstanceRegistrations;
|
||||
m_channelInstanceRegistrations.clear();
|
||||
mainCore->clearChannels(this);
|
||||
|
||||
|
@ -86,9 +86,7 @@ public:
|
||||
int webapiSpectrumServerDelete(SWGSDRangel::SWGSuccessResponse& response, QString& errorMessage);
|
||||
|
||||
private:
|
||||
typedef QList<ChannelAPI*> ChannelInstanceRegistrations;
|
||||
|
||||
ChannelInstanceRegistrations m_channelInstanceRegistrations;
|
||||
QList<ChannelAPI*> m_channelInstanceRegistrations;
|
||||
int m_deviceTabIndex;
|
||||
|
||||
void renameChannelInstances();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,12 +19,11 @@
|
||||
#ifndef SDRBASE_DSP_DSPDEVICEMIMOENGINE_H_
|
||||
#define SDRBASE_DSP_DSPDEVICEMIMOENGINE_H_
|
||||
|
||||
#include <QThread>
|
||||
#include <QObject>
|
||||
|
||||
#include "dsp/dsptypes.h"
|
||||
#include "util/message.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "util/syncmessenger.h"
|
||||
#include "util/movingaverage.h"
|
||||
#include "util/incrementalvector.h"
|
||||
#include "export.h"
|
||||
@ -34,14 +33,14 @@ class BasebandSampleSink;
|
||||
class BasebandSampleSource;
|
||||
class MIMOChannel;
|
||||
|
||||
class SDRBASE_API DSPDeviceMIMOEngine : public QThread {
|
||||
class SDRBASE_API DSPDeviceMIMOEngine : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
class SetSampleMIMO : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
public:
|
||||
SetSampleMIMO(DeviceSampleMIMO* sampleMIMO) : Message(), m_sampleMIMO(sampleMIMO) { }
|
||||
explicit SetSampleMIMO(DeviceSampleMIMO* sampleMIMO) : Message(), m_sampleMIMO(sampleMIMO) { }
|
||||
DeviceSampleMIMO* getSampleMIMO() const { return m_sampleMIMO; }
|
||||
private:
|
||||
DeviceSampleMIMO* m_sampleMIMO;
|
||||
@ -81,7 +80,7 @@ public:
|
||||
class AddMIMOChannel : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
public:
|
||||
AddMIMOChannel(MIMOChannel* channel) :
|
||||
explicit AddMIMOChannel(MIMOChannel* channel) :
|
||||
Message(),
|
||||
m_channel(channel)
|
||||
{ }
|
||||
@ -93,7 +92,7 @@ public:
|
||||
class RemoveMIMOChannel : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
public:
|
||||
RemoveMIMOChannel(MIMOChannel* channel) :
|
||||
explicit RemoveMIMOChannel(MIMOChannel* channel) :
|
||||
Message(),
|
||||
m_channel(channel)
|
||||
{ }
|
||||
@ -135,7 +134,7 @@ public:
|
||||
class AddSpectrumSink : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
public:
|
||||
AddSpectrumSink(BasebandSampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
|
||||
explicit AddSpectrumSink(BasebandSampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
|
||||
BasebandSampleSink* getSampleSink() const { return m_sampleSink; }
|
||||
private:
|
||||
BasebandSampleSink* m_sampleSink;
|
||||
@ -144,7 +143,7 @@ public:
|
||||
class RemoveSpectrumSink : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
public:
|
||||
RemoveSpectrumSink(BasebandSampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
|
||||
explicit RemoveSpectrumSink(BasebandSampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
|
||||
BasebandSampleSink* getSampleSink() const { return m_sampleSink; }
|
||||
private:
|
||||
BasebandSampleSink* m_sampleSink;
|
||||
@ -153,7 +152,7 @@ public:
|
||||
class GetErrorMessage : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
public:
|
||||
GetErrorMessage(unsigned int subsystemIndex) :
|
||||
explicit GetErrorMessage(unsigned int subsystemIndex) :
|
||||
m_subsystemIndex(subsystemIndex)
|
||||
{}
|
||||
void setErrorMessage(const QString& text) { m_errorMessage = text; }
|
||||
@ -205,7 +204,7 @@ public:
|
||||
int m_index;
|
||||
};
|
||||
|
||||
enum State {
|
||||
enum class State {
|
||||
StNotStarted, //!< engine is before initialization
|
||||
StIdle, //!< engine is idle
|
||||
StReady, //!< engine is ready to run
|
||||
@ -214,13 +213,10 @@ public:
|
||||
};
|
||||
|
||||
DSPDeviceMIMOEngine(uint32_t uid, QObject* parent = nullptr);
|
||||
~DSPDeviceMIMOEngine();
|
||||
~DSPDeviceMIMOEngine() override;
|
||||
|
||||
MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
|
||||
void start(); //!< This thread start
|
||||
void stop(); //!< This thread stop
|
||||
|
||||
bool initProcess(int subsystemIndex); //!< Initialize process sequence
|
||||
bool startProcess(int subsystemIndex); //!< Start process sequence
|
||||
void stopProcess(int subsystemIndex); //!< Stop process sequence
|
||||
@ -248,25 +244,25 @@ public:
|
||||
} else if (subsystemIndex == 1) {
|
||||
return m_stateTx;
|
||||
} else {
|
||||
return StNotStarted;
|
||||
return State::StNotStarted;
|
||||
}
|
||||
}
|
||||
|
||||
QString errorMessage(int subsystemIndex); //!< Return the current error message
|
||||
QString deviceDescription(); //!< Return the device description
|
||||
QString errorMessage(int subsystemIndex) const; //!< Return the current error message
|
||||
QString deviceDescription() const; //!< Return the device description
|
||||
|
||||
void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection, int isource); //!< Configure source DSP corrections
|
||||
|
||||
private:
|
||||
struct SourceCorrection
|
||||
{
|
||||
bool m_dcOffsetCorrection;
|
||||
bool m_iqImbalanceCorrection;
|
||||
double m_iOffset;
|
||||
double m_qOffset;
|
||||
int m_iRange;
|
||||
int m_qRange;
|
||||
int m_imbalance;
|
||||
bool m_dcOffsetCorrection = false;
|
||||
bool m_iqImbalanceCorrection = false;
|
||||
double m_iOffset = 0;
|
||||
double m_qOffset = 0;
|
||||
int m_iRange = 1 << 16;
|
||||
int m_qRange = 1 << 16;
|
||||
int m_imbalance = 65536;
|
||||
MovingAverageUtil<int32_t, int64_t, 1024> m_iBeta;
|
||||
MovingAverageUtil<int32_t, int64_t, 1024> m_qBeta;
|
||||
#if IMBALANCE_INT
|
||||
@ -288,13 +284,6 @@ private:
|
||||
#endif
|
||||
SourceCorrection()
|
||||
{
|
||||
m_dcOffsetCorrection = false;
|
||||
m_iqImbalanceCorrection = false;
|
||||
m_iOffset = 0;
|
||||
m_qOffset = 0;
|
||||
m_iRange = 1 << 16;
|
||||
m_qRange = 1 << 16;
|
||||
m_imbalance = 65536;
|
||||
m_iBeta.reset();
|
||||
m_qBeta.reset();
|
||||
m_avgAmp.reset();
|
||||
@ -320,19 +309,18 @@ private:
|
||||
int m_sampleMIMOSequence;
|
||||
|
||||
MessageQueue m_inputMessageQueue; //<! Input message queue. Post here.
|
||||
SyncMessenger m_syncMessenger; //!< Used to process messages synchronously with the thread
|
||||
|
||||
typedef std::list<BasebandSampleSink*> BasebandSampleSinks;
|
||||
using BasebandSampleSinks = std::list<BasebandSampleSink *>;
|
||||
std::vector<BasebandSampleSinks> m_basebandSampleSinks; //!< ancillary sample sinks on main thread (per input stream)
|
||||
std::map<int, bool> m_rxRealElseComplex; //!< map of real else complex indicators for device sources (by input stream)
|
||||
typedef std::list<BasebandSampleSource*> BasebandSampleSources;
|
||||
using BasebandSampleSources = std::list<BasebandSampleSource *>;
|
||||
std::vector<BasebandSampleSources> m_basebandSampleSources; //!< channel sample sources (per output stream)
|
||||
std::map<int, bool> m_txRealElseComplex; //!< map of real else complex indicators for device sinks (by input stream)
|
||||
std::vector<IncrementalVector<Sample>> m_sourceSampleBuffers;
|
||||
std::vector<IncrementalVector<Sample>> m_sourceZeroBuffers;
|
||||
unsigned int m_sumIndex; //!< channel index when summing channels
|
||||
|
||||
typedef std::list<MIMOChannel*> MIMOChannels;
|
||||
using MIMOChannels = std::list<MIMOChannel *>;
|
||||
MIMOChannels m_mimoChannels; //!< MIMO channels
|
||||
|
||||
std::vector<SourceCorrection> m_sourcesCorrections;
|
||||
@ -341,7 +329,6 @@ private:
|
||||
bool m_spectrumInputSourceElseSink; //!< Source else sink stream to be used as spectrum sink input
|
||||
unsigned int m_spectrumInputIndex; //!< Index of the stream to be used as spectrum sink input
|
||||
|
||||
void run();
|
||||
void workSampleSinkFifos(); //!< transfer samples of all sink streams (sync mode)
|
||||
void workSampleSinkFifo(unsigned int streamIndex); //!< transfer samples of one sink stream (async mode)
|
||||
void workSamplesSink(const SampleVector::const_iterator& vbegin, const SampleVector::const_iterator& vend, unsigned int streamIndex);
|
||||
@ -357,14 +344,14 @@ private:
|
||||
void setStateTx(State state);
|
||||
|
||||
void handleSetMIMO(DeviceSampleMIMO* mimo); //!< Manage MIMO device setting
|
||||
void iqCorrections(SampleVector::iterator begin, SampleVector::iterator end, int isource, bool imbalanceCorrection);
|
||||
void iqCorrections(SampleVector::iterator begin, SampleVector::iterator end, int isource, bool imbalanceCorrection);
|
||||
bool handleMessage(const Message& cmd);
|
||||
|
||||
private slots:
|
||||
void handleDataRxSync(); //!< Handle data when Rx samples have to be processed synchronously
|
||||
void handleDataRxAsync(int streamIndex); //!< Handle data when Rx samples have to be processed asynchronously
|
||||
void handleDataTxSync(); //!< Handle data when Tx samples have to be processed synchronously
|
||||
void handleDataTxAsync(int streamIndex); //!< Handle data when Tx samples have to be processed asynchronously
|
||||
void handleSynchronousMessages(); //!< Handle synchronous messages with the thread
|
||||
void handleInputMessages(); //!< Handle input message queue
|
||||
|
||||
signals:
|
||||
|
@ -28,9 +28,9 @@
|
||||
#include "dsp/dspcommands.h"
|
||||
|
||||
DSPDeviceSinkEngine::DSPDeviceSinkEngine(uint32_t uid, QObject* parent) :
|
||||
QThread(parent),
|
||||
QObject(parent),
|
||||
m_uid(uid),
|
||||
m_state(StNotStarted),
|
||||
m_state(State::StNotStarted),
|
||||
m_deviceSampleSink(nullptr),
|
||||
m_sampleSinkSequence(0),
|
||||
m_basebandSampleSources(),
|
||||
@ -39,16 +39,13 @@ DSPDeviceSinkEngine::DSPDeviceSinkEngine(uint32_t uid, QObject* parent) :
|
||||
m_centerFrequency(0),
|
||||
m_realElseComplex(false)
|
||||
{
|
||||
setState(State::StIdle);
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
|
||||
connect(&m_syncMessenger, SIGNAL(messageSent()), this, SLOT(handleSynchronousMessages()), Qt::QueuedConnection);
|
||||
|
||||
moveToThread(this);
|
||||
}
|
||||
|
||||
DSPDeviceSinkEngine::~DSPDeviceSinkEngine()
|
||||
{
|
||||
stop();
|
||||
wait();
|
||||
qDebug("DSPDeviceSinkEngine::~DSPDeviceSinkEngine");
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::setState(State state)
|
||||
@ -60,58 +57,35 @@ void DSPDeviceSinkEngine::setState(State state)
|
||||
}
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::run()
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::run";
|
||||
setState(StIdle);
|
||||
exec();
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::start()
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::start";
|
||||
QThread::start();
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::stop()
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::stop";
|
||||
gotoIdle();
|
||||
setState(StNotStarted);
|
||||
QThread::exit();
|
||||
// DSPExit cmd;
|
||||
// m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
bool DSPDeviceSinkEngine::initGeneration()
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::initGeneration";
|
||||
DSPGenerationInit cmd;
|
||||
|
||||
return m_syncMessenger.sendWait(cmd) == StReady;
|
||||
auto *cmd = new DSPGenerationInit();
|
||||
getInputMessageQueue()->push(cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DSPDeviceSinkEngine::startGeneration()
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::startGeneration";
|
||||
DSPGenerationStart cmd;
|
||||
|
||||
return m_syncMessenger.sendWait(cmd) == StRunning;
|
||||
auto *cmd = new DSPGenerationStart();
|
||||
getInputMessageQueue()->push(cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::stopGeneration()
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::stopGeneration";
|
||||
DSPGenerationStop cmd;
|
||||
m_syncMessenger.storeMessage(cmd);
|
||||
handleSynchronousMessages();
|
||||
auto *cmd = new DSPGenerationStop();
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::setSink(DeviceSampleSink* sink)
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::setSink";
|
||||
DSPSetSink cmd(sink);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
m_deviceSampleSink = sink;
|
||||
auto *cmd = new DSPSetSink(sink);
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::setSinkSequence(int sequence)
|
||||
@ -123,45 +97,40 @@ void DSPDeviceSinkEngine::setSinkSequence(int sequence)
|
||||
void DSPDeviceSinkEngine::addChannelSource(BasebandSampleSource* source)
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::addChannelSource: " << source->getSourceName().toStdString().c_str();
|
||||
DSPAddBasebandSampleSource cmd(source);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
auto *cmd = new DSPAddBasebandSampleSource(source);
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::removeChannelSource(BasebandSampleSource* source)
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::removeChannelSource: " << source->getSourceName().toStdString().c_str();
|
||||
DSPRemoveBasebandSampleSource cmd(source);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
auto *cmd = new DSPRemoveBasebandSampleSource(source);
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::addSpectrumSink(BasebandSampleSink* spectrumSink)
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::addSpectrumSink: " << spectrumSink->getSinkName().toStdString().c_str();
|
||||
DSPAddSpectrumSink cmd(spectrumSink);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
m_spectrumSink = spectrumSink;
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::removeSpectrumSink(BasebandSampleSink* spectrumSink)
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::removeSpectrumSink: " << spectrumSink->getSinkName().toStdString().c_str();
|
||||
DSPRemoveSpectrumSink cmd(spectrumSink);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
auto *cmd = new DSPRemoveSpectrumSink(spectrumSink);
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
|
||||
QString DSPDeviceSinkEngine::errorMessage()
|
||||
QString DSPDeviceSinkEngine::errorMessage() const
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::errorMessage";
|
||||
DSPGetErrorMessage cmd;
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
return cmd.getErrorMessage();
|
||||
return m_errorMessage;
|
||||
}
|
||||
|
||||
QString DSPDeviceSinkEngine::sinkDeviceDescription()
|
||||
QString DSPDeviceSinkEngine::sinkDeviceDescription() const
|
||||
{
|
||||
qDebug() << "DSPDeviceSinkEngine::sinkDeviceDescription";
|
||||
DSPGetSinkDeviceDescription cmd;
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
return cmd.getDeviceDescription();
|
||||
return m_deviceDescription;
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::workSampleFifo()
|
||||
@ -173,7 +142,10 @@ void DSPDeviceSinkEngine::workSampleFifo()
|
||||
}
|
||||
|
||||
SampleVector& data = sourceFifo->getData();
|
||||
unsigned int iPart1Begin, iPart1End, iPart2Begin, iPart2End;
|
||||
unsigned int iPart1Begin;
|
||||
unsigned int iPart1End;
|
||||
unsigned int iPart2Begin;
|
||||
unsigned int iPart2End;
|
||||
unsigned int remainder = sourceFifo->remainder();
|
||||
|
||||
while ((remainder > 0) && (m_inputMessageQueue.size() == 0))
|
||||
@ -214,7 +186,7 @@ void DSPDeviceSinkEngine::workSamples(SampleVector& data, unsigned int iBegin, u
|
||||
else
|
||||
{
|
||||
m_sourceSampleBuffer.allocate(nbSamples);
|
||||
SampleVector::iterator sBegin = m_sourceSampleBuffer.m_vector.begin();
|
||||
auto sBegin = m_sourceSampleBuffer.m_vector.begin();
|
||||
BasebandSampleSources::const_iterator srcIt = m_basebandSampleSources.begin();
|
||||
BasebandSampleSource *source = *srcIt;
|
||||
source->pull(begin, nbSamples);
|
||||
@ -230,7 +202,7 @@ void DSPDeviceSinkEngine::workSamples(SampleVector& data, unsigned int iBegin, u
|
||||
sBegin + nbSamples,
|
||||
data.begin() + iBegin,
|
||||
data.begin() + iBegin,
|
||||
[this](Sample& a, const Sample& b) -> Sample {
|
||||
[this](const Sample& a, const Sample& b) -> Sample {
|
||||
FixReal den = m_sumIndex + 1; // at each stage scale sum by n/n+1 and input by 1/n+1
|
||||
FixReal nom = m_sumIndex; // so that final sum is scaled by N (number of channels)
|
||||
FixReal x = a.real()/den + nom*(b.real()/den);
|
||||
@ -256,20 +228,20 @@ DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoIdle()
|
||||
qDebug() << "DSPDeviceSinkEngine::gotoIdle";
|
||||
|
||||
switch(m_state) {
|
||||
case StNotStarted:
|
||||
return StNotStarted;
|
||||
case State::StNotStarted:
|
||||
return State::StNotStarted;
|
||||
|
||||
case StIdle:
|
||||
case StError:
|
||||
return StIdle;
|
||||
case State::StIdle:
|
||||
case State::StError:
|
||||
return State::StIdle;
|
||||
|
||||
case StReady:
|
||||
case StRunning:
|
||||
case State::StReady:
|
||||
case State::StRunning:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m_deviceSampleSink) {
|
||||
return StIdle;
|
||||
return State::StIdle;
|
||||
}
|
||||
|
||||
// stop everything
|
||||
@ -284,23 +256,23 @@ DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoIdle()
|
||||
m_deviceDescription.clear();
|
||||
m_sampleRate = 0;
|
||||
|
||||
return StIdle;
|
||||
return State::StIdle;
|
||||
}
|
||||
|
||||
DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoInit()
|
||||
{
|
||||
switch(m_state) {
|
||||
case StNotStarted:
|
||||
return StNotStarted;
|
||||
case State::StNotStarted:
|
||||
return State::StNotStarted;
|
||||
|
||||
case StRunning: // FIXME: assumes it goes first through idle state. Could we get back to init from running directly?
|
||||
return StRunning;
|
||||
case State::StRunning:
|
||||
return State::StRunning;
|
||||
|
||||
case StReady:
|
||||
return StReady;
|
||||
case State::StReady:
|
||||
return State::StReady;
|
||||
|
||||
case StIdle:
|
||||
case StError:
|
||||
case State::StIdle:
|
||||
case State::StError:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -315,7 +287,7 @@ DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoInit()
|
||||
m_sampleRate = m_deviceSampleSink->getSampleRate();
|
||||
|
||||
qDebug() << "DSPDeviceSinkEngine::gotoInit: "
|
||||
<< " m_deviceDescription: " << m_deviceDescription.toStdString().c_str()
|
||||
<< " m_deviceDescription: " << m_deviceDescription.toStdString().c_str()
|
||||
<< " sampleRate: " << m_sampleRate
|
||||
<< " centerFrequency: " << m_centerFrequency;
|
||||
|
||||
@ -334,11 +306,11 @@ DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoInit()
|
||||
// pass data to listeners
|
||||
if (m_deviceSampleSink->getMessageQueueToGUI())
|
||||
{
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy for the output queue
|
||||
auto* rep = new DSPSignalNotification(notif); // make a copy for the output queue
|
||||
m_deviceSampleSink->getMessageQueueToGUI()->push(rep);
|
||||
}
|
||||
|
||||
return StReady;
|
||||
return State::StReady;
|
||||
}
|
||||
|
||||
DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoRunning()
|
||||
@ -347,17 +319,17 @@ DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoRunning()
|
||||
|
||||
switch(m_state)
|
||||
{
|
||||
case StNotStarted:
|
||||
return StNotStarted;
|
||||
case State::StNotStarted:
|
||||
return State::StNotStarted;
|
||||
|
||||
case StIdle:
|
||||
return StIdle;
|
||||
case State::StIdle:
|
||||
return State::StIdle;
|
||||
|
||||
case StRunning:
|
||||
return StRunning;
|
||||
case State::StRunning:
|
||||
return State::StRunning;
|
||||
|
||||
case StReady:
|
||||
case StError:
|
||||
case State::StReady:
|
||||
case State::StError:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -386,7 +358,7 @@ DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoRunning()
|
||||
|
||||
qDebug() << "DSPDeviceSinkEngine::gotoRunning: input message queue pending: " << m_inputMessageQueue.size();
|
||||
|
||||
return StRunning;
|
||||
return State::StRunning;
|
||||
}
|
||||
|
||||
DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoError(const QString& errorMessage)
|
||||
@ -395,19 +367,17 @@ DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoError(const QString& errorMe
|
||||
|
||||
m_errorMessage = errorMessage;
|
||||
m_deviceDescription.clear();
|
||||
setState(StError);
|
||||
return StError;
|
||||
setState(State::StError);
|
||||
return State::StError;
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::handleSetSink(DeviceSampleSink* sink)
|
||||
void DSPDeviceSinkEngine::handleSetSink(const DeviceSampleSink*)
|
||||
{
|
||||
m_deviceSampleSink = sink;
|
||||
|
||||
if (!m_deviceSampleSink) { // Early leave
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("DSPDeviceSinkEngine::handleSetSink: set %s", qPrintable(sink->getDeviceDescription()));
|
||||
qDebug("DSPDeviceSinkEngine::handleSetSink: set %s", qPrintable(m_deviceSampleSink->getDeviceDescription()));
|
||||
|
||||
QObject::connect(
|
||||
m_deviceSampleSink->getSampleFifo(),
|
||||
@ -416,136 +386,137 @@ void DSPDeviceSinkEngine::handleSetSink(DeviceSampleSink* sink)
|
||||
&DSPDeviceSinkEngine::handleData,
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::handleData()
|
||||
{
|
||||
if (m_state == StRunning) {
|
||||
workSampleFifo();
|
||||
if (m_state == State::StRunning) {
|
||||
workSampleFifo();
|
||||
}
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::handleSynchronousMessages()
|
||||
bool DSPDeviceSinkEngine::handleMessage(const Message& message)
|
||||
{
|
||||
Message *message = m_syncMessenger.getMessage();
|
||||
qDebug() << "DSPDeviceSinkEngine::handleSynchronousMessages: " << message->getIdentifier();
|
||||
if (DSPSignalNotification::match(message))
|
||||
{
|
||||
auto& notif = (const DSPSignalNotification&) message;
|
||||
|
||||
if (DSPGenerationInit::match(*message))
|
||||
// update DSP values
|
||||
|
||||
m_sampleRate = notif.getSampleRate();
|
||||
m_centerFrequency = notif.getCenterFrequency();
|
||||
m_realElseComplex = notif.getRealElseComplex();
|
||||
|
||||
qDebug() << "DSPDeviceSinkEngine::handleInputMessages: DSPSignalNotification:"
|
||||
<< " m_sampleRate: " << m_sampleRate
|
||||
<< " m_centerFrequency: " << m_centerFrequency
|
||||
<< " m_realElseComplex" << m_realElseComplex;
|
||||
|
||||
// forward source changes to sources with immediate execution
|
||||
|
||||
for(BasebandSampleSources::const_iterator it = m_basebandSampleSources.begin(); it != m_basebandSampleSources.end(); it++)
|
||||
{
|
||||
auto *rep = new DSPSignalNotification(notif); // make a copy
|
||||
qDebug() << "DSPDeviceSinkEngine::handleInputMessages: forward message to " << (*it)->getSourceName().toStdString().c_str();
|
||||
(*it)->pushMessage(rep);
|
||||
}
|
||||
|
||||
// forward changes to listeners on DSP output queue
|
||||
if (m_deviceSampleSink)
|
||||
{
|
||||
MessageQueue *guiMessageQueue = m_deviceSampleSink->getMessageQueueToGUI();
|
||||
qDebug("DSPDeviceSinkEngine::handleInputMessages: DSPSignalNotification: guiMessageQueue: %p", guiMessageQueue);
|
||||
|
||||
if (guiMessageQueue)
|
||||
{
|
||||
auto *rep = new DSPSignalNotification(notif); // make a copy for the output queue
|
||||
guiMessageQueue->push(rep);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// From synchronous messages
|
||||
if (DSPGenerationInit::match(message))
|
||||
{
|
||||
setState(gotoIdle());
|
||||
|
||||
if(m_state == StIdle) {
|
||||
if(m_state == State::StIdle) {
|
||||
setState(gotoInit()); // State goes ready if init is performed
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPGenerationStart::match(*message))
|
||||
else if (DSPGenerationStart::match(message))
|
||||
{
|
||||
if(m_state == StReady) {
|
||||
if(m_state == State::StReady) {
|
||||
setState(gotoRunning());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPGenerationStop::match(*message))
|
||||
else if (DSPGenerationStop::match(message))
|
||||
{
|
||||
setState(gotoIdle());
|
||||
return true;
|
||||
}
|
||||
else if (DSPGetSinkDeviceDescription::match(*message))
|
||||
else if (DSPSetSink::match(message))
|
||||
{
|
||||
const auto& cmd = (const DSPSetSink&) message;
|
||||
handleSetSink(cmd.getSampleSink());
|
||||
return true;
|
||||
}
|
||||
else if (DSPRemoveSpectrumSink::match(message))
|
||||
{
|
||||
((DSPGetSinkDeviceDescription*) message)->setDeviceDescription(m_deviceDescription);
|
||||
}
|
||||
else if (DSPGetErrorMessage::match(*message))
|
||||
{
|
||||
((DSPGetErrorMessage*) message)->setErrorMessage(m_errorMessage);
|
||||
}
|
||||
else if (DSPSetSink::match(*message)) {
|
||||
handleSetSink(((DSPSetSink*) message)->getSampleSink());
|
||||
}
|
||||
else if (DSPAddSpectrumSink::match(*message))
|
||||
{
|
||||
m_spectrumSink = ((DSPAddSpectrumSink*) message)->getSampleSink();
|
||||
}
|
||||
else if (DSPRemoveSpectrumSink::match(*message))
|
||||
{
|
||||
BasebandSampleSink* spectrumSink = ((DSPRemoveSpectrumSink*) message)->getSampleSink();
|
||||
auto& cmd = (const DSPRemoveSpectrumSink&) message;
|
||||
BasebandSampleSink* spectrumSink = cmd.getSampleSink();
|
||||
|
||||
if(m_state == StRunning) {
|
||||
if(m_state == State::StRunning) {
|
||||
spectrumSink->stop();
|
||||
}
|
||||
|
||||
m_spectrumSink = nullptr;
|
||||
return true;
|
||||
}
|
||||
else if (DSPAddBasebandSampleSource::match(*message))
|
||||
else if (DSPAddBasebandSampleSource::match(message))
|
||||
{
|
||||
BasebandSampleSource* source = ((DSPAddBasebandSampleSource*) message)->getSampleSource();
|
||||
auto& cmd = (const DSPAddBasebandSampleSource&) message;
|
||||
BasebandSampleSource* source = cmd.getSampleSource();
|
||||
m_basebandSampleSources.push_back(source);
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
auto *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
source->pushMessage(notif);
|
||||
|
||||
if (m_state == StRunning)
|
||||
{
|
||||
if (m_state == State::StRunning) {
|
||||
source->start();
|
||||
}
|
||||
}
|
||||
else if (DSPRemoveBasebandSampleSource::match(*message))
|
||||
{
|
||||
BasebandSampleSource* source = ((DSPRemoveBasebandSampleSource*) message)->getSampleSource();
|
||||
|
||||
if(m_state == StRunning) {
|
||||
return true;
|
||||
}
|
||||
else if (DSPRemoveBasebandSampleSource::match(message))
|
||||
{
|
||||
auto& cmd = (const DSPRemoveBasebandSampleSource&) message;
|
||||
BasebandSampleSource* source = cmd.getSampleSource();
|
||||
|
||||
if(m_state == State::StRunning) {
|
||||
source->stop();
|
||||
}
|
||||
|
||||
m_basebandSampleSources.remove(source);
|
||||
return true;
|
||||
}
|
||||
|
||||
m_syncMessenger.done(m_state);
|
||||
return false;
|
||||
}
|
||||
|
||||
void DSPDeviceSinkEngine::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_inputMessageQueue.pop()) != 0)
|
||||
while ((message = m_inputMessageQueue.pop()) != nullptr)
|
||||
{
|
||||
qDebug("DSPDeviceSinkEngine::handleInputMessages: message: %s", message->getIdentifier());
|
||||
|
||||
if (DSPSignalNotification::match(*message))
|
||||
{
|
||||
DSPSignalNotification *notif = (DSPSignalNotification *) message;
|
||||
|
||||
// update DSP values
|
||||
|
||||
m_sampleRate = notif->getSampleRate();
|
||||
m_centerFrequency = notif->getCenterFrequency();
|
||||
m_realElseComplex = notif->getRealElseComplex();
|
||||
|
||||
qDebug() << "DSPDeviceSinkEngine::handleInputMessages: DSPSignalNotification:"
|
||||
<< " m_sampleRate: " << m_sampleRate
|
||||
<< " m_centerFrequency: " << m_centerFrequency
|
||||
<< " m_realElseComplex" << m_realElseComplex;
|
||||
|
||||
// forward source changes to sources with immediate execution
|
||||
|
||||
for(BasebandSampleSources::const_iterator it = m_basebandSampleSources.begin(); it != m_basebandSampleSources.end(); it++)
|
||||
{
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(*notif); // make a copy
|
||||
qDebug() << "DSPDeviceSinkEngine::handleInputMessages: forward message to " << (*it)->getSourceName().toStdString().c_str();
|
||||
(*it)->pushMessage(rep);
|
||||
}
|
||||
|
||||
// forward changes to listeners on DSP output queue
|
||||
if (m_deviceSampleSink)
|
||||
{
|
||||
MessageQueue *guiMessageQueue = m_deviceSampleSink->getMessageQueueToGUI();
|
||||
qDebug("DSPDeviceSinkEngine::handleInputMessages: DSPSignalNotification: guiMessageQueue: %p", guiMessageQueue);
|
||||
|
||||
if (guiMessageQueue)
|
||||
{
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(*notif); // make a copy for the output queue
|
||||
guiMessageQueue->push(rep);
|
||||
}
|
||||
}
|
||||
|
||||
delete message;
|
||||
}
|
||||
if (handleMessage(*message)) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
#ifndef SDRBASE_DSP_DSPDEVICESINKENGINE_H_
|
||||
#define SDRBASE_DSP_DSPDEVICESINKENGINE_H_
|
||||
|
||||
#include <QThread>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
@ -33,7 +33,6 @@
|
||||
|
||||
#include "dsp/dsptypes.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "util/syncmessenger.h"
|
||||
#include "util/incrementalvector.h"
|
||||
#include "export.h"
|
||||
|
||||
@ -41,11 +40,11 @@ class DeviceSampleSink;
|
||||
class BasebandSampleSource;
|
||||
class BasebandSampleSink;
|
||||
|
||||
class SDRBASE_API DSPDeviceSinkEngine : public QThread {
|
||||
class SDRBASE_API DSPDeviceSinkEngine : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum State {
|
||||
enum class State {
|
||||
StNotStarted, //!< engine is before initialization
|
||||
StIdle, //!< engine is idle
|
||||
StReady, //!< engine is ready to run
|
||||
@ -53,16 +52,13 @@ public:
|
||||
StError //!< engine is in error
|
||||
};
|
||||
|
||||
DSPDeviceSinkEngine(uint32_t uid, QObject* parent = NULL);
|
||||
~DSPDeviceSinkEngine();
|
||||
DSPDeviceSinkEngine(uint32_t uid, QObject* parent = nullptr);
|
||||
~DSPDeviceSinkEngine() final;
|
||||
|
||||
uint32_t getUID() const { return m_uid; }
|
||||
|
||||
MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
|
||||
void start(); //!< This thread start
|
||||
void stop(); //!< This thread stop
|
||||
|
||||
bool initGeneration(); //!< Initialize generation sequence
|
||||
bool startGeneration(); //!< Start generation sequence
|
||||
void stopGeneration(); //!< Stop generation sequence
|
||||
@ -79,14 +75,13 @@ public:
|
||||
|
||||
State state() const { return m_state; } //!< Return DSP engine current state
|
||||
|
||||
QString errorMessage(); //!< Return the current error message
|
||||
QString sinkDeviceDescription(); //!< Return the sink device description
|
||||
QString errorMessage() const; //!< Return the current error message
|
||||
QString sinkDeviceDescription() const; //!< Return the sink device description
|
||||
|
||||
private:
|
||||
uint32_t m_uid; //!< unique ID
|
||||
|
||||
MessageQueue m_inputMessageQueue; //<! Input message queue. Post here.
|
||||
SyncMessenger m_syncMessenger; //!< Used to process messages synchronously with the thread
|
||||
|
||||
State m_state;
|
||||
|
||||
@ -96,7 +91,7 @@ private:
|
||||
DeviceSampleSink* m_deviceSampleSink;
|
||||
int m_sampleSinkSequence;
|
||||
|
||||
typedef std::list<BasebandSampleSource*> BasebandSampleSources;
|
||||
using BasebandSampleSources = std::list<BasebandSampleSource *>;
|
||||
BasebandSampleSources m_basebandSampleSources; //!< baseband sample sources within main thread (usually file input)
|
||||
|
||||
BasebandSampleSink *m_spectrumSink;
|
||||
@ -108,7 +103,6 @@ private:
|
||||
bool m_realElseComplex;
|
||||
unsigned int m_sumIndex; //!< channel index when summing channels
|
||||
|
||||
void run();
|
||||
void workSampleFifo(); //!< transfer samples from baseband sources to sink if in running state
|
||||
void workSamples(SampleVector& data, unsigned int iBegin, unsigned int iEnd);
|
||||
|
||||
@ -118,12 +112,12 @@ private:
|
||||
State gotoError(const QString& errorMsg); //!< Go to an error state
|
||||
void setState(State state);
|
||||
|
||||
void handleSetSink(DeviceSampleSink* sink); //!< Manage sink setting
|
||||
void handleSetSink(const DeviceSampleSink* sink); //!< Manage sink setting
|
||||
bool handleMessage(const Message& cmd);
|
||||
|
||||
private slots:
|
||||
void handleData(); //!< Handle data when samples have to be written to the sample FIFO
|
||||
void handleInputMessages(); //!< Handle input message queue
|
||||
void handleSynchronousMessages(); //!< Handle synchronous messages with the thread
|
||||
|
||||
signals:
|
||||
void stateChanged();
|
||||
|
@ -29,9 +29,9 @@
|
||||
#include "samplesinkfifo.h"
|
||||
|
||||
DSPDeviceSourceEngine::DSPDeviceSourceEngine(uint uid, QObject* parent) :
|
||||
QThread(parent),
|
||||
QObject(parent),
|
||||
m_uid(uid),
|
||||
m_state(StNotStarted),
|
||||
m_state(State::StNotStarted),
|
||||
m_deviceSampleSource(nullptr),
|
||||
m_sampleSourceSequence(0),
|
||||
m_basebandSampleSinks(),
|
||||
@ -46,16 +46,13 @@ DSPDeviceSourceEngine::DSPDeviceSourceEngine(uint uid, QObject* parent) :
|
||||
m_qRange(1 << 16),
|
||||
m_imbalance(65536)
|
||||
{
|
||||
setState(State::StIdle);
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
|
||||
connect(&m_syncMessenger, SIGNAL(messageSent()), this, SLOT(handleSynchronousMessages()), Qt::QueuedConnection);
|
||||
|
||||
moveToThread(this);
|
||||
}
|
||||
|
||||
DSPDeviceSourceEngine::~DSPDeviceSourceEngine()
|
||||
{
|
||||
stop();
|
||||
wait();
|
||||
qDebug("DSPDeviceSourceEngine::~DSPDeviceSourceEngine");
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::setState(State state)
|
||||
@ -67,63 +64,36 @@ void DSPDeviceSourceEngine::setState(State state)
|
||||
}
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::run()
|
||||
bool DSPDeviceSourceEngine::initAcquisition() const
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::run";
|
||||
setState(StIdle);
|
||||
exec();
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::start()
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::start";
|
||||
QThread::start();
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::stop()
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::stop";
|
||||
gotoIdle();
|
||||
setState(StNotStarted);
|
||||
QThread::exit();
|
||||
// DSPExit cmd;
|
||||
// m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
bool DSPDeviceSourceEngine::initAcquisition()
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::initAcquisition";
|
||||
DSPAcquisitionInit cmd;
|
||||
|
||||
return m_syncMessenger.sendWait(cmd) == StReady;
|
||||
qDebug("DSPDeviceSourceEngine::initAcquisition (dummy)");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DSPDeviceSourceEngine::startAcquisition()
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::startAcquisition";
|
||||
DSPAcquisitionStart cmd;
|
||||
|
||||
return m_syncMessenger.sendWait(cmd) == StRunning;
|
||||
qDebug("DSPDeviceSourceEngine::startAcquisition");
|
||||
auto *cmd = new DSPAcquisitionStart();
|
||||
getInputMessageQueue()->push(cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::stopAcquistion()
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::stopAcquistion";
|
||||
DSPAcquisitionStop cmd;
|
||||
m_syncMessenger.storeMessage(cmd);
|
||||
handleSynchronousMessages();
|
||||
qDebug("DSPDeviceSourceEngine::stopAcquistion");
|
||||
auto *cmd = new DSPAcquisitionStop();
|
||||
getInputMessageQueue()->push(cmd);
|
||||
|
||||
if(m_dcOffsetCorrection)
|
||||
{
|
||||
if (m_dcOffsetCorrection) {
|
||||
qDebug("DC offset:%f,%f", m_iOffset, m_qOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::setSource(DeviceSampleSource* source)
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::setSource";
|
||||
DSPSetSource cmd(source);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
qDebug("DSPDeviceSourceEngine::setSource");
|
||||
auto *cmd = new DSPSetSource(source);
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::setSourceSequence(int sequence)
|
||||
@ -135,38 +105,34 @@ void DSPDeviceSourceEngine::setSourceSequence(int sequence)
|
||||
void DSPDeviceSourceEngine::addSink(BasebandSampleSink* sink)
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::addSink: " << sink->getSinkName().toStdString().c_str();
|
||||
DSPAddBasebandSampleSink cmd(sink);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
auto *cmd = new DSPAddBasebandSampleSink(sink);
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::removeSink(BasebandSampleSink* sink)
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::removeSink: " << sink->getSinkName().toStdString().c_str();
|
||||
DSPRemoveBasebandSampleSink cmd(sink);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
auto *cmd = new DSPRemoveBasebandSampleSink(sink);
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection)
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::configureCorrections";
|
||||
DSPConfigureCorrection* cmd = new DSPConfigureCorrection(dcOffsetCorrection, iqImbalanceCorrection);
|
||||
m_inputMessageQueue.push(cmd);
|
||||
qDebug("DSPDeviceSourceEngine::configureCorrections");
|
||||
auto *cmd = new DSPConfigureCorrection(dcOffsetCorrection, iqImbalanceCorrection);
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
|
||||
QString DSPDeviceSourceEngine::errorMessage()
|
||||
QString DSPDeviceSourceEngine::errorMessage() const
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::errorMessage";
|
||||
DSPGetErrorMessage cmd;
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
return cmd.getErrorMessage();
|
||||
qDebug("DSPDeviceSourceEngine::errorMessage");
|
||||
return m_errorMessage;
|
||||
}
|
||||
|
||||
QString DSPDeviceSourceEngine::sourceDeviceDescription()
|
||||
QString DSPDeviceSourceEngine::sourceDeviceDescription() const
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::sourceDeviceDescription";
|
||||
DSPGetSourceDeviceDescription cmd;
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
return cmd.getDeviceDescription();
|
||||
qDebug("DSPDeviceSourceEngine::sourceDeviceDescription");
|
||||
return m_deviceDescription;
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::iqCorrections(SampleVector::iterator begin, SampleVector::iterator end, bool imbalanceCorrection)
|
||||
@ -217,8 +183,8 @@ void DSPDeviceSourceEngine::iqCorrections(SampleVector::iterator begin, SampleVe
|
||||
|
||||
#else
|
||||
// DC correction and conversion
|
||||
float xi = (it->m_real - (int32_t) m_iBeta) / SDR_RX_SCALEF;
|
||||
float xq = (it->m_imag - (int32_t) m_qBeta) / SDR_RX_SCALEF;
|
||||
float xi = (float) (it->m_real - (int32_t) m_iBeta) / SDR_RX_SCALEF;
|
||||
float xq = (float) (it->m_imag - (int32_t) m_qBeta) / SDR_RX_SCALEF;
|
||||
|
||||
// phase imbalance
|
||||
m_avgII(xi*xi); // <I", I">
|
||||
@ -229,8 +195,8 @@ void DSPDeviceSourceEngine::iqCorrections(SampleVector::iterator begin, SampleVe
|
||||
m_avgPhi(m_avgIQ.asDouble()/m_avgII.asDouble());
|
||||
}
|
||||
|
||||
float& yi = xi; // the in phase remains the reference
|
||||
float yq = xq - m_avgPhi.asDouble()*xi;
|
||||
const float& yi = xi; // the in phase remains the reference
|
||||
float yq = xq - (float) m_avgPhi.asDouble()*xi;
|
||||
|
||||
// amplitude I/Q imbalance
|
||||
m_avgII2(yi*yi); // <I, I>
|
||||
@ -241,12 +207,12 @@ void DSPDeviceSourceEngine::iqCorrections(SampleVector::iterator begin, SampleVe
|
||||
}
|
||||
|
||||
// final correction
|
||||
float& zi = yi; // the in phase remains the reference
|
||||
float zq = m_avgAmp.asDouble() * yq;
|
||||
const float& zi = yi; // the in phase remains the reference
|
||||
auto zq = (float) (m_avgAmp.asDouble() * yq);
|
||||
|
||||
// convert and store
|
||||
it->m_real = zi * SDR_RX_SCALEF;
|
||||
it->m_imag = zq * SDR_RX_SCALEF;
|
||||
it->m_real = (FixReal) (zi * SDR_RX_SCALEF);
|
||||
it->m_imag = (FixReal) (zq * SDR_RX_SCALEF);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@ -263,10 +229,10 @@ void DSPDeviceSourceEngine::dcOffset(SampleVector::iterator begin, SampleVector:
|
||||
// sum and correct in one pass
|
||||
for(SampleVector::iterator it = begin; it < end; it++)
|
||||
{
|
||||
m_iBeta(it->real());
|
||||
m_qBeta(it->imag());
|
||||
it->m_real -= (int32_t) m_iBeta;
|
||||
it->m_imag -= (int32_t) m_qBeta;
|
||||
m_iBeta(it->real());
|
||||
m_qBeta(it->imag());
|
||||
it->m_real -= (int32_t) m_iBeta;
|
||||
it->m_imag -= (int32_t) m_qBeta;
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,23 +342,23 @@ void DSPDeviceSourceEngine::work()
|
||||
|
||||
DSPDeviceSourceEngine::State DSPDeviceSourceEngine::gotoIdle()
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::gotoIdle";
|
||||
qDebug("DSPDeviceSourceEngine::gotoIdle");
|
||||
|
||||
switch(m_state) {
|
||||
case StNotStarted:
|
||||
return StNotStarted;
|
||||
case State::StNotStarted:
|
||||
return State::StNotStarted;
|
||||
|
||||
case StIdle:
|
||||
case StError:
|
||||
return StIdle;
|
||||
case State::StIdle:
|
||||
case State::StError:
|
||||
return State::StIdle;
|
||||
|
||||
case StReady:
|
||||
case StRunning:
|
||||
case State::StReady:
|
||||
case State::StRunning:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m_deviceSampleSource) {
|
||||
return StIdle;
|
||||
return State::StIdle;
|
||||
}
|
||||
|
||||
// stop everything
|
||||
@ -406,23 +372,23 @@ DSPDeviceSourceEngine::State DSPDeviceSourceEngine::gotoIdle()
|
||||
m_deviceDescription.clear();
|
||||
m_sampleRate = 0;
|
||||
|
||||
return StIdle;
|
||||
return State::StIdle;
|
||||
}
|
||||
|
||||
DSPDeviceSourceEngine::State DSPDeviceSourceEngine::gotoInit()
|
||||
{
|
||||
switch(m_state) {
|
||||
case StNotStarted:
|
||||
return StNotStarted;
|
||||
case State::StNotStarted:
|
||||
return State::StNotStarted;
|
||||
|
||||
case StRunning: // FIXME: assumes it goes first through idle state. Could we get back to init from running directly?
|
||||
return StRunning;
|
||||
case State::StRunning:
|
||||
return State::StRunning;
|
||||
|
||||
case StReady:
|
||||
return StReady;
|
||||
case State::StReady:
|
||||
return State::StReady;
|
||||
|
||||
case StIdle:
|
||||
case StError:
|
||||
case State::StIdle:
|
||||
case State::StError:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -442,14 +408,14 @@ DSPDeviceSourceEngine::State DSPDeviceSourceEngine::gotoInit()
|
||||
m_sampleRate = m_deviceSampleSource->getSampleRate();
|
||||
|
||||
qDebug() << "DSPDeviceSourceEngine::gotoInit: "
|
||||
<< " m_deviceDescription: " << m_deviceDescription.toStdString().c_str()
|
||||
<< " m_deviceDescription: " << m_deviceDescription.toStdString().c_str()
|
||||
<< " sampleRate: " << m_sampleRate
|
||||
<< " centerFrequency: " << m_centerFrequency;
|
||||
|
||||
|
||||
for (BasebandSampleSinks::const_iterator it = m_basebandSampleSinks.begin(); it != m_basebandSampleSinks.end(); ++it)
|
||||
{
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
auto *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
qDebug() << "DSPDeviceSourceEngine::gotoInit: initializing " << (*it)->getSinkName().toStdString().c_str();
|
||||
(*it)->pushMessage(notif);
|
||||
}
|
||||
@ -457,30 +423,30 @@ DSPDeviceSourceEngine::State DSPDeviceSourceEngine::gotoInit()
|
||||
// pass data to listeners
|
||||
if (m_deviceSampleSource->getMessageQueueToGUI())
|
||||
{
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
auto *rep = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
m_deviceSampleSource->getMessageQueueToGUI()->push(rep);
|
||||
}
|
||||
|
||||
return StReady;
|
||||
return State::StReady;
|
||||
}
|
||||
|
||||
DSPDeviceSourceEngine::State DSPDeviceSourceEngine::gotoRunning()
|
||||
{
|
||||
qDebug() << "DSPDeviceSourceEngine::gotoRunning";
|
||||
qDebug("DSPDeviceSourceEngine::gotoRunning");
|
||||
|
||||
switch(m_state)
|
||||
{
|
||||
case StNotStarted:
|
||||
return StNotStarted;
|
||||
case State::StNotStarted:
|
||||
return State::StNotStarted;
|
||||
|
||||
case StIdle:
|
||||
return StIdle;
|
||||
case State::StIdle:
|
||||
return State::StIdle;
|
||||
|
||||
case StRunning:
|
||||
return StRunning;
|
||||
case State::StRunning:
|
||||
return State::StRunning;
|
||||
|
||||
case StReady:
|
||||
case StError:
|
||||
case State::StReady:
|
||||
case State::StError:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -504,7 +470,7 @@ DSPDeviceSourceEngine::State DSPDeviceSourceEngine::gotoRunning()
|
||||
|
||||
qDebug() << "DSPDeviceSourceEngine::gotoRunning:input message queue pending: " << m_inputMessageQueue.size();
|
||||
|
||||
return StRunning;
|
||||
return State::StRunning;
|
||||
}
|
||||
|
||||
DSPDeviceSourceEngine::State DSPDeviceSourceEngine::gotoError(const QString& errorMessage)
|
||||
@ -513,19 +479,14 @@ DSPDeviceSourceEngine::State DSPDeviceSourceEngine::gotoError(const QString& err
|
||||
|
||||
m_errorMessage = errorMessage;
|
||||
m_deviceDescription.clear();
|
||||
setState(StError);
|
||||
return StError;
|
||||
setState(State::StError);
|
||||
return State::StError;
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::handleSetSource(DeviceSampleSource* source)
|
||||
{
|
||||
gotoIdle();
|
||||
|
||||
// if(m_sampleSource != 0)
|
||||
// {
|
||||
// disconnect(m_sampleSource->getSampleFifo(), SIGNAL(dataReady()), this, SLOT(handleData()));
|
||||
// }
|
||||
|
||||
m_deviceSampleSource = source;
|
||||
|
||||
if (m_deviceSampleSource)
|
||||
@ -541,148 +502,150 @@ void DSPDeviceSourceEngine::handleSetSource(DeviceSampleSource* source)
|
||||
|
||||
void DSPDeviceSourceEngine::handleData()
|
||||
{
|
||||
if(m_state == StRunning)
|
||||
if(m_state == State::StRunning)
|
||||
{
|
||||
work();
|
||||
}
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::handleSynchronousMessages()
|
||||
bool DSPDeviceSourceEngine::handleMessage(const Message& message)
|
||||
{
|
||||
Message *message = m_syncMessenger.getMessage();
|
||||
qDebug() << "DSPDeviceSourceEngine::handleSynchronousMessages: " << message->getIdentifier();
|
||||
if (DSPConfigureCorrection::match(message))
|
||||
{
|
||||
auto& conf = (const DSPConfigureCorrection&) message;
|
||||
m_iqImbalanceCorrection = conf.getIQImbalanceCorrection();
|
||||
|
||||
if (DSPAcquisitionInit::match(*message))
|
||||
if (m_dcOffsetCorrection != conf.getDCOffsetCorrection())
|
||||
{
|
||||
m_dcOffsetCorrection = conf.getDCOffsetCorrection();
|
||||
m_iOffset = 0;
|
||||
m_qOffset = 0;
|
||||
}
|
||||
|
||||
if (m_iqImbalanceCorrection != conf.getIQImbalanceCorrection())
|
||||
{
|
||||
m_iqImbalanceCorrection = conf.getIQImbalanceCorrection();
|
||||
m_iRange = 1 << 16;
|
||||
m_qRange = 1 << 16;
|
||||
m_imbalance = 65536;
|
||||
}
|
||||
|
||||
m_avgAmp.reset();
|
||||
m_avgII.reset();
|
||||
m_avgII2.reset();
|
||||
m_avgIQ.reset();
|
||||
m_avgPhi.reset();
|
||||
m_avgQQ2.reset();
|
||||
m_iBeta.reset();
|
||||
m_qBeta.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPSignalNotification::match(message))
|
||||
{
|
||||
auto& notif = (const DSPSignalNotification&) message;
|
||||
|
||||
// update DSP values
|
||||
|
||||
m_sampleRate = notif.getSampleRate();
|
||||
m_centerFrequency = notif.getCenterFrequency();
|
||||
m_realElseComplex = notif.getRealElseComplex();
|
||||
|
||||
qDebug() << "DSPDeviceSourceEngine::handleInputMessages: DSPSignalNotification:"
|
||||
<< " m_sampleRate: " << m_sampleRate
|
||||
<< " m_centerFrequency: " << m_centerFrequency;
|
||||
|
||||
// forward source changes to channel sinks with immediate execution (no queuing)
|
||||
|
||||
for(BasebandSampleSinks::const_iterator it = m_basebandSampleSinks.begin(); it != m_basebandSampleSinks.end(); it++)
|
||||
{
|
||||
auto* rep = new DSPSignalNotification(notif); // make a copy
|
||||
qDebug() << "DSPDeviceSourceEngine::handleInputMessages: forward message to " << (*it)->getSinkName().toStdString().c_str();
|
||||
(*it)->pushMessage(rep);
|
||||
}
|
||||
|
||||
// forward changes to source GUI input queue
|
||||
if (m_deviceSampleSource)
|
||||
{
|
||||
MessageQueue *guiMessageQueue = m_deviceSampleSource->getMessageQueueToGUI();
|
||||
qDebug("DSPDeviceSourceEngine::handleInputMessages: DSPSignalNotification: guiMessageQueue: %p", guiMessageQueue);
|
||||
|
||||
if (guiMessageQueue)
|
||||
{
|
||||
auto* rep = new DSPSignalNotification(notif); // make a copy for the source GUI
|
||||
guiMessageQueue->push(rep);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// was in handleSynchronousMessages:
|
||||
else if (DSPAcquisitionInit::match(message))
|
||||
{
|
||||
return true; // discard
|
||||
}
|
||||
else if (DSPAcquisitionStart::match(message))
|
||||
{
|
||||
setState(gotoIdle());
|
||||
|
||||
if(m_state == StIdle) {
|
||||
if(m_state == State::StIdle) {
|
||||
setState(gotoInit()); // State goes ready if init is performed
|
||||
}
|
||||
}
|
||||
else if (DSPAcquisitionStart::match(*message))
|
||||
{
|
||||
if(m_state == StReady) {
|
||||
|
||||
if(m_state == State::StReady) {
|
||||
setState(gotoRunning());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPAcquisitionStop::match(*message))
|
||||
else if (DSPAcquisitionStop::match(message))
|
||||
{
|
||||
setState(gotoIdle());
|
||||
return true;
|
||||
}
|
||||
else if (DSPGetSourceDeviceDescription::match(*message))
|
||||
else if (DSPSetSource::match(message))
|
||||
{
|
||||
auto cmd = (const DSPSetSource&) message;
|
||||
handleSetSource(cmd.getSampleSource());
|
||||
}
|
||||
else if (DSPAddBasebandSampleSink::match(message))
|
||||
{
|
||||
((DSPGetSourceDeviceDescription*) message)->setDeviceDescription(m_deviceDescription);
|
||||
}
|
||||
else if (DSPGetErrorMessage::match(*message))
|
||||
{
|
||||
((DSPGetErrorMessage*) message)->setErrorMessage(m_errorMessage);
|
||||
}
|
||||
else if (DSPSetSource::match(*message)) {
|
||||
handleSetSource(((DSPSetSource*) message)->getSampleSource());
|
||||
}
|
||||
else if (DSPAddBasebandSampleSink::match(*message))
|
||||
{
|
||||
BasebandSampleSink* sink = ((DSPAddBasebandSampleSink*) message)->getSampleSink();
|
||||
auto cmd = (const DSPAddBasebandSampleSink&) message;
|
||||
BasebandSampleSink* sink = cmd.getSampleSink();
|
||||
m_basebandSampleSinks.push_back(sink);
|
||||
// initialize sample rate and center frequency in the sink:
|
||||
DSPSignalNotification *msg = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
auto *msg = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
sink->pushMessage(msg);
|
||||
// start the sink:
|
||||
if(m_state == StRunning) {
|
||||
if(m_state == State::StRunning) {
|
||||
sink->start();
|
||||
}
|
||||
}
|
||||
else if (DSPRemoveBasebandSampleSink::match(*message))
|
||||
else if (DSPRemoveBasebandSampleSink::match(message))
|
||||
{
|
||||
BasebandSampleSink* sink = ((DSPRemoveBasebandSampleSink*) message)->getSampleSink();
|
||||
auto cmd = (const DSPRemoveBasebandSampleSink&) message;
|
||||
BasebandSampleSink* sink = cmd.getSampleSink();
|
||||
|
||||
if(m_state == StRunning) {
|
||||
if(m_state == State::StRunning) {
|
||||
sink->stop();
|
||||
}
|
||||
|
||||
m_basebandSampleSinks.remove(sink);
|
||||
}
|
||||
|
||||
m_syncMessenger.done(m_state);
|
||||
return false;
|
||||
}
|
||||
|
||||
void DSPDeviceSourceEngine::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_inputMessageQueue.pop()) != 0)
|
||||
while ((message = m_inputMessageQueue.pop()) != nullptr)
|
||||
{
|
||||
qDebug("DSPDeviceSourceEngine::handleInputMessages: message: %s", message->getIdentifier());
|
||||
|
||||
if (DSPConfigureCorrection::match(*message))
|
||||
{
|
||||
DSPConfigureCorrection* conf = (DSPConfigureCorrection*) message;
|
||||
m_iqImbalanceCorrection = conf->getIQImbalanceCorrection();
|
||||
|
||||
if(m_dcOffsetCorrection != conf->getDCOffsetCorrection())
|
||||
{
|
||||
m_dcOffsetCorrection = conf->getDCOffsetCorrection();
|
||||
m_iOffset = 0;
|
||||
m_qOffset = 0;
|
||||
}
|
||||
|
||||
if(m_iqImbalanceCorrection != conf->getIQImbalanceCorrection())
|
||||
{
|
||||
m_iqImbalanceCorrection = conf->getIQImbalanceCorrection();
|
||||
m_iRange = 1 << 16;
|
||||
m_qRange = 1 << 16;
|
||||
m_imbalance = 65536;
|
||||
}
|
||||
|
||||
m_avgAmp.reset();
|
||||
m_avgII.reset();
|
||||
m_avgII2.reset();
|
||||
m_avgIQ.reset();
|
||||
m_avgPhi.reset();
|
||||
m_avgQQ2.reset();
|
||||
m_iBeta.reset();
|
||||
m_qBeta.reset();
|
||||
|
||||
delete message;
|
||||
}
|
||||
else if (DSPSignalNotification::match(*message))
|
||||
{
|
||||
DSPSignalNotification *notif = (DSPSignalNotification *) message;
|
||||
|
||||
// update DSP values
|
||||
|
||||
m_sampleRate = notif->getSampleRate();
|
||||
m_centerFrequency = notif->getCenterFrequency();
|
||||
m_realElseComplex = notif->getRealElseComplex();
|
||||
|
||||
qDebug() << "DSPDeviceSourceEngine::handleInputMessages: DSPSignalNotification:"
|
||||
<< " m_sampleRate: " << m_sampleRate
|
||||
<< " m_centerFrequency: " << m_centerFrequency;
|
||||
|
||||
// forward source changes to channel sinks with immediate execution (no queuing)
|
||||
|
||||
for(BasebandSampleSinks::const_iterator it = m_basebandSampleSinks.begin(); it != m_basebandSampleSinks.end(); it++)
|
||||
{
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(*notif); // make a copy
|
||||
qDebug() << "DSPDeviceSourceEngine::handleInputMessages: forward message to " << (*it)->getSinkName().toStdString().c_str();
|
||||
(*it)->pushMessage(rep);
|
||||
}
|
||||
|
||||
// forward changes to source GUI input queue
|
||||
if (m_deviceSampleSource)
|
||||
{
|
||||
MessageQueue *guiMessageQueue = m_deviceSampleSource->getMessageQueueToGUI();
|
||||
qDebug("DSPDeviceSourceEngine::handleInputMessages: DSPSignalNotification: guiMessageQueue: %p", guiMessageQueue);
|
||||
|
||||
if (guiMessageQueue)
|
||||
{
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(*notif); // make a copy for the source GUI
|
||||
guiMessageQueue->push(rep);
|
||||
}
|
||||
}
|
||||
|
||||
delete message;
|
||||
}
|
||||
if (handleMessage(*message)) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,24 +22,23 @@
|
||||
#ifndef INCLUDE_DSPDEVICEENGINE_H
|
||||
#define INCLUDE_DSPDEVICEENGINE_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include "dsp/dsptypes.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "util/syncmessenger.h"
|
||||
#include "export.h"
|
||||
#include "util/movingaverage.h"
|
||||
|
||||
class DeviceSampleSource;
|
||||
class BasebandSampleSink;
|
||||
|
||||
class SDRBASE_API DSPDeviceSourceEngine : public QThread {
|
||||
class SDRBASE_API DSPDeviceSourceEngine : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum State {
|
||||
enum class State {
|
||||
StNotStarted, //!< engine is before initialization
|
||||
StIdle, //!< engine is idle
|
||||
StReady, //!< engine is ready to run
|
||||
@ -47,17 +46,14 @@ public:
|
||||
StError //!< engine is in error
|
||||
};
|
||||
|
||||
DSPDeviceSourceEngine(uint uid, QObject* parent = NULL);
|
||||
~DSPDeviceSourceEngine();
|
||||
DSPDeviceSourceEngine(uint uid, QObject* parent = nullptr);
|
||||
~DSPDeviceSourceEngine() final;
|
||||
|
||||
uint getUID() const { return m_uid; }
|
||||
|
||||
MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
|
||||
void start(); //!< This thread start
|
||||
void stop(); //!< This thread stop
|
||||
|
||||
bool initAcquisition(); //!< Initialize acquisition sequence
|
||||
bool initAcquisition() const; //!< Initialize acquisition sequence
|
||||
bool startAcquisition(); //!< Start acquisition sequence
|
||||
void stopAcquistion(); //!< Stop acquisition sequence
|
||||
|
||||
@ -72,14 +68,13 @@ public:
|
||||
|
||||
State state() const { return m_state; } //!< Return DSP engine current state
|
||||
|
||||
QString errorMessage(); //!< Return the current error message
|
||||
QString sourceDeviceDescription(); //!< Return the source device description
|
||||
QString errorMessage() const; //!< Return the current error message
|
||||
QString sourceDeviceDescription() const; //!< Return the source device description
|
||||
|
||||
private:
|
||||
uint m_uid; //!< unique ID
|
||||
|
||||
MessageQueue m_inputMessageQueue; //<! Input message queue. Post here.
|
||||
SyncMessenger m_syncMessenger; //!< Used to process messages synchronously with the thread
|
||||
|
||||
State m_state;
|
||||
|
||||
@ -89,7 +84,7 @@ private:
|
||||
DeviceSampleSource* m_deviceSampleSource;
|
||||
int m_sampleSourceSequence;
|
||||
|
||||
typedef std::list<BasebandSampleSink*> BasebandSampleSinks;
|
||||
using BasebandSampleSinks = std::list<BasebandSampleSink *>;
|
||||
BasebandSampleSinks m_basebandSampleSinks; //!< sample sinks within main thread (usually spectrum, file output)
|
||||
|
||||
uint m_sampleRate;
|
||||
@ -98,7 +93,8 @@ private:
|
||||
|
||||
bool m_dcOffsetCorrection;
|
||||
bool m_iqImbalanceCorrection;
|
||||
double m_iOffset, m_qOffset;
|
||||
double m_iOffset;
|
||||
double m_qOffset;
|
||||
|
||||
MovingAverageUtil<int32_t, int64_t, 1024> m_iBeta;
|
||||
MovingAverageUtil<int32_t, int64_t, 1024> m_qBeta;
|
||||
@ -126,8 +122,6 @@ private:
|
||||
qint32 m_qRange;
|
||||
qint32 m_imbalance;
|
||||
|
||||
void run();
|
||||
|
||||
void iqCorrections(SampleVector::iterator begin, SampleVector::iterator end, bool imbalanceCorrection);
|
||||
void dcOffset(SampleVector::iterator begin, SampleVector::iterator end);
|
||||
void imbalance(SampleVector::iterator begin, SampleVector::iterator end);
|
||||
@ -140,11 +134,11 @@ private:
|
||||
void setState(State state);
|
||||
|
||||
void handleSetSource(DeviceSampleSource* source); //!< Manage source setting
|
||||
bool handleMessage(const Message& cmd);
|
||||
|
||||
private slots:
|
||||
void handleData(); //!< Handle data when samples from source FIFO are ready to be processed
|
||||
void handleInputMessages(); //!< Handle input message queue
|
||||
void handleSynchronousMessages(); //!< Handle synchronous messages with the thread
|
||||
|
||||
signals:
|
||||
void stateChanged();
|
||||
|
@ -42,7 +42,7 @@ DSPEngine::DSPEngine() :
|
||||
|
||||
DSPEngine::~DSPEngine()
|
||||
{
|
||||
QList<DSPDeviceSourceEngine*>::iterator it = m_deviceSourceEngines.begin();
|
||||
auto it = m_deviceSourceEngines.begin();
|
||||
|
||||
while (it != m_deviceSourceEngines.end())
|
||||
{
|
||||
@ -63,24 +63,45 @@ DSPEngine *DSPEngine::instance()
|
||||
|
||||
DSPDeviceSourceEngine *DSPEngine::addDeviceSourceEngine()
|
||||
{
|
||||
m_deviceSourceEngines.push_back(new DSPDeviceSourceEngine(m_deviceSourceEnginesUIDSequence));
|
||||
auto *deviceSourceEngine = new DSPDeviceSourceEngine(m_deviceSourceEnginesUIDSequence);
|
||||
auto *deviceThread = new QThread();
|
||||
m_deviceSourceEnginesUIDSequence++;
|
||||
m_deviceEngineReferences.push_back(DeviceEngineReference{0, m_deviceSourceEngines.back(), nullptr, nullptr});
|
||||
return m_deviceSourceEngines.back();
|
||||
m_deviceSourceEngines.push_back(deviceSourceEngine);
|
||||
m_deviceEngineReferences.push_back(DeviceEngineReference{0, m_deviceSourceEngines.back(), nullptr, nullptr, deviceThread});
|
||||
deviceSourceEngine->moveToThread(deviceThread);
|
||||
|
||||
QObject::connect(
|
||||
deviceThread,
|
||||
&QThread::finished,
|
||||
deviceSourceEngine,
|
||||
&QObject::deleteLater
|
||||
);
|
||||
QObject::connect(
|
||||
deviceThread,
|
||||
&QThread::finished,
|
||||
deviceThread,
|
||||
&QThread::deleteLater
|
||||
);
|
||||
|
||||
deviceThread->start();
|
||||
|
||||
return deviceSourceEngine;
|
||||
}
|
||||
|
||||
void DSPEngine::removeLastDeviceSourceEngine()
|
||||
{
|
||||
if (m_deviceSourceEngines.size() > 0)
|
||||
if (!m_deviceSourceEngines.empty())
|
||||
{
|
||||
DSPDeviceSourceEngine *lastDeviceEngine = m_deviceSourceEngines.back();
|
||||
delete lastDeviceEngine;
|
||||
const DSPDeviceSourceEngine *lastDeviceEngine = m_deviceSourceEngines.back();
|
||||
m_deviceSourceEngines.pop_back();
|
||||
|
||||
for (int i = 0; i < m_deviceEngineReferences.size(); i++)
|
||||
{
|
||||
if (m_deviceEngineReferences[i].m_deviceSourceEngine == lastDeviceEngine)
|
||||
{
|
||||
QThread* deviceThread = m_deviceEngineReferences[i].m_thread;
|
||||
deviceThread->exit();
|
||||
deviceThread->wait();
|
||||
m_deviceEngineReferences.removeAt(i);
|
||||
break;
|
||||
}
|
||||
@ -90,24 +111,45 @@ void DSPEngine::removeLastDeviceSourceEngine()
|
||||
|
||||
DSPDeviceSinkEngine *DSPEngine::addDeviceSinkEngine()
|
||||
{
|
||||
m_deviceSinkEngines.push_back(new DSPDeviceSinkEngine(m_deviceSinkEnginesUIDSequence));
|
||||
auto *deviceSinkEngine = new DSPDeviceSinkEngine(m_deviceSinkEnginesUIDSequence);
|
||||
auto *deviceThread = new QThread();
|
||||
m_deviceSinkEnginesUIDSequence++;
|
||||
m_deviceEngineReferences.push_back(DeviceEngineReference{1, nullptr, m_deviceSinkEngines.back(), nullptr});
|
||||
return m_deviceSinkEngines.back();
|
||||
m_deviceSinkEngines.push_back(deviceSinkEngine);
|
||||
m_deviceEngineReferences.push_back(DeviceEngineReference{1, nullptr, m_deviceSinkEngines.back(), nullptr, deviceThread});
|
||||
deviceSinkEngine->moveToThread(deviceThread);
|
||||
|
||||
QObject::connect(
|
||||
deviceThread,
|
||||
&QThread::finished,
|
||||
deviceSinkEngine,
|
||||
&QObject::deleteLater
|
||||
);
|
||||
QObject::connect(
|
||||
deviceThread,
|
||||
&QThread::finished,
|
||||
deviceThread,
|
||||
&QThread::deleteLater
|
||||
);
|
||||
|
||||
deviceThread->start();
|
||||
|
||||
return deviceSinkEngine;
|
||||
}
|
||||
|
||||
void DSPEngine::removeLastDeviceSinkEngine()
|
||||
{
|
||||
if (m_deviceSinkEngines.size() > 0)
|
||||
if (!m_deviceSinkEngines.empty())
|
||||
{
|
||||
DSPDeviceSinkEngine *lastDeviceEngine = m_deviceSinkEngines.back();
|
||||
delete lastDeviceEngine;
|
||||
const DSPDeviceSinkEngine *lastDeviceEngine = m_deviceSinkEngines.back();
|
||||
m_deviceSinkEngines.pop_back();
|
||||
|
||||
for (int i = 0; i < m_deviceEngineReferences.size(); i++)
|
||||
{
|
||||
if (m_deviceEngineReferences[i].m_deviceSinkEngine == lastDeviceEngine)
|
||||
{
|
||||
QThread* deviceThread = m_deviceEngineReferences[i].m_thread;
|
||||
deviceThread->exit();
|
||||
deviceThread->wait();
|
||||
m_deviceEngineReferences.removeAt(i);
|
||||
break;
|
||||
}
|
||||
@ -117,24 +159,45 @@ void DSPEngine::removeLastDeviceSinkEngine()
|
||||
|
||||
DSPDeviceMIMOEngine *DSPEngine::addDeviceMIMOEngine()
|
||||
{
|
||||
m_deviceMIMOEngines.push_back(new DSPDeviceMIMOEngine(m_deviceMIMOEnginesUIDSequence));
|
||||
auto *deviceMIMOEngine = new DSPDeviceMIMOEngine(m_deviceMIMOEnginesUIDSequence);
|
||||
auto *deviceThread = new QThread();
|
||||
m_deviceMIMOEnginesUIDSequence++;
|
||||
m_deviceEngineReferences.push_back(DeviceEngineReference{2, nullptr, nullptr, m_deviceMIMOEngines.back()});
|
||||
return m_deviceMIMOEngines.back();
|
||||
m_deviceMIMOEngines.push_back(deviceMIMOEngine);
|
||||
m_deviceEngineReferences.push_back(DeviceEngineReference{2, nullptr, nullptr, m_deviceMIMOEngines.back(), deviceThread});
|
||||
deviceMIMOEngine->moveToThread(deviceThread);
|
||||
|
||||
QObject::connect(
|
||||
deviceThread,
|
||||
&QThread::finished,
|
||||
deviceMIMOEngine,
|
||||
&QObject::deleteLater
|
||||
);
|
||||
QObject::connect(
|
||||
deviceThread,
|
||||
&QThread::finished,
|
||||
deviceThread,
|
||||
&QThread::deleteLater
|
||||
);
|
||||
|
||||
deviceThread->start();
|
||||
|
||||
return deviceMIMOEngine;
|
||||
}
|
||||
|
||||
void DSPEngine::removeLastDeviceMIMOEngine()
|
||||
{
|
||||
if (m_deviceMIMOEngines.size() > 0)
|
||||
if (!m_deviceMIMOEngines.empty())
|
||||
{
|
||||
DSPDeviceMIMOEngine *lastDeviceEngine = m_deviceMIMOEngines.back();
|
||||
delete lastDeviceEngine;
|
||||
const DSPDeviceMIMOEngine *lastDeviceEngine = m_deviceMIMOEngines.back();
|
||||
m_deviceMIMOEngines.pop_back();
|
||||
|
||||
for (int i = 0; i < m_deviceEngineReferences.size(); i++)
|
||||
{
|
||||
if (m_deviceEngineReferences[i].m_deviceMIMOEngine == lastDeviceEngine)
|
||||
{
|
||||
QThread* deviceThread = m_deviceEngineReferences[i].m_thread;
|
||||
deviceThread->exit();
|
||||
deviceThread->wait();
|
||||
m_deviceEngineReferences.removeAt(i);
|
||||
break;
|
||||
}
|
||||
@ -151,19 +214,25 @@ void DSPEngine::removeDeviceEngineAt(int deviceIndex)
|
||||
if (m_deviceEngineReferences[deviceIndex].m_deviceEngineType == 0) // source
|
||||
{
|
||||
DSPDeviceSourceEngine *deviceEngine = m_deviceEngineReferences[deviceIndex].m_deviceSourceEngine;
|
||||
delete deviceEngine;
|
||||
QThread *deviceThread = m_deviceEngineReferences[deviceIndex].m_thread;
|
||||
deviceThread->exit();
|
||||
deviceThread->wait();
|
||||
m_deviceSourceEngines.removeAll(deviceEngine);
|
||||
}
|
||||
else if (m_deviceEngineReferences[deviceIndex].m_deviceEngineType == 1) // sink
|
||||
{
|
||||
DSPDeviceSinkEngine *deviceEngine = m_deviceEngineReferences[deviceIndex].m_deviceSinkEngine;
|
||||
delete deviceEngine;
|
||||
QThread *deviceThread = m_deviceEngineReferences[deviceIndex].m_thread;
|
||||
deviceThread->exit();
|
||||
deviceThread->wait();
|
||||
m_deviceSinkEngines.removeAll(deviceEngine);
|
||||
}
|
||||
else if (m_deviceEngineReferences[deviceIndex].m_deviceEngineType == 2) // MIMO
|
||||
{
|
||||
DSPDeviceMIMOEngine *deviceEngine = m_deviceEngineReferences[deviceIndex].m_deviceMIMOEngine;
|
||||
delete deviceEngine;
|
||||
QThread *deviceThread = m_deviceEngineReferences[deviceIndex].m_thread;
|
||||
deviceThread->exit();
|
||||
deviceThread->wait();
|
||||
m_deviceMIMOEngines.removeAll(deviceEngine);
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ class DSPDeviceSourceEngine;
|
||||
class DSPDeviceSinkEngine;
|
||||
class DSPDeviceMIMOEngine;
|
||||
class FFTFactory;
|
||||
class QThread;
|
||||
|
||||
class SDRBASE_API DSPEngine : public QObject {
|
||||
Q_OBJECT
|
||||
@ -79,6 +80,7 @@ private:
|
||||
DSPDeviceSourceEngine *m_deviceSourceEngine;
|
||||
DSPDeviceSinkEngine *m_deviceSinkEngine;
|
||||
DSPDeviceMIMOEngine *m_deviceMIMOEngine;
|
||||
QThread *m_thread;
|
||||
};
|
||||
|
||||
QList<DSPDeviceSourceEngine*> m_deviceSourceEngines;
|
||||
|
@ -84,8 +84,8 @@ public:
|
||||
StreamType streamType; //!< This is the type of stream supported
|
||||
int deviceNbItems; //!< Number of items (or streams) in the device. >1 for composite devices.
|
||||
int deviceItemIndex; //!< For composite devices this is the Rx or Tx stream index. -1 if not initialized
|
||||
int claimed; //!< This is the device set index if claimed else -1
|
||||
bool removed; //!< Set if device has been removed
|
||||
int claimed = -1; //!< This is the device set index if claimed else -1
|
||||
bool removed = false; //!< Set if device has been removed
|
||||
|
||||
SamplingDevice(const QString& _displayedName,
|
||||
const QString& _hardwareId,
|
||||
@ -104,9 +104,7 @@ public:
|
||||
type(_type),
|
||||
streamType(_streamType),
|
||||
deviceNbItems(_deviceNbItems),
|
||||
deviceItemIndex(_deviceItemIndex),
|
||||
claimed(-1),
|
||||
removed(false)
|
||||
deviceItemIndex(_deviceItemIndex)
|
||||
{ }
|
||||
|
||||
bool operator==(const SamplingDevice& rhs) const
|
||||
@ -117,7 +115,7 @@ public:
|
||||
&& serial == rhs.serial;
|
||||
}
|
||||
};
|
||||
typedef QList<SamplingDevice> SamplingDevices;
|
||||
using SamplingDevices = QList<SamplingDevice>;
|
||||
|
||||
/** This is the device from which the sampling devices are derived. For physical devices this represents
|
||||
* a single physical unit (a LimeSDR, HackRF, BladeRF, RTL-SDR dongle, ...) that is enumerated once and
|
||||
@ -148,9 +146,9 @@ public:
|
||||
nbTxStreams(_nbTxStreams)
|
||||
{}
|
||||
};
|
||||
typedef QList<OriginDevice> OriginDevices;
|
||||
using OriginDevices = QList<OriginDevice>;
|
||||
|
||||
virtual ~PluginInterface() { }
|
||||
virtual ~PluginInterface() = default;
|
||||
|
||||
virtual const PluginDescriptor& getPluginDescriptor() const = 0;
|
||||
virtual void initPlugin(PluginAPI* pluginAPI) = 0;
|
||||
|
@ -78,10 +78,7 @@ DeviceUISet::DeviceUISet(int deviceSetIndex, DeviceSet *deviceSet)
|
||||
|
||||
DeviceUISet::~DeviceUISet()
|
||||
{
|
||||
// delete m_channelWindow;
|
||||
delete m_mainSpectrumGUI;
|
||||
// delete m_spectrumGUI; // done above
|
||||
// delete m_spectrum;
|
||||
}
|
||||
|
||||
void DeviceUISet::setIndex(int deviceSetIndex)
|
||||
@ -119,7 +116,7 @@ void DeviceUISet::registerRxChannelInstance(ChannelAPI *channelAPI, ChannelGUI*
|
||||
channelGUI,
|
||||
&ChannelGUI::closing,
|
||||
this,
|
||||
[=](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
[this, channelGUI](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
}
|
||||
@ -132,7 +129,7 @@ void DeviceUISet::registerTxChannelInstance(ChannelAPI *channelAPI, ChannelGUI*
|
||||
channelGUI,
|
||||
&ChannelGUI::closing,
|
||||
this,
|
||||
[=](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
[this, channelGUI](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
}
|
||||
@ -145,7 +142,7 @@ void DeviceUISet::registerChannelInstance(ChannelAPI *channelAPI, ChannelGUI* ch
|
||||
channelGUI,
|
||||
&ChannelGUI::closing,
|
||||
this,
|
||||
[=](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
[this, channelGUI](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
}
|
||||
@ -170,7 +167,7 @@ void DeviceUISet::freeChannels()
|
||||
{
|
||||
qDebug("DeviceUISet::freeChannels: destroying channel [%s]", qPrintable(m_channelInstanceRegistrations[i].m_channelAPI->getURI()));
|
||||
m_channelInstanceRegistrations[i].m_gui->destroy();
|
||||
m_channelInstanceRegistrations[i].m_channelAPI->destroy();
|
||||
delete m_channelInstanceRegistrations[i].m_channelAPI;
|
||||
}
|
||||
|
||||
m_channelInstanceRegistrations.clear();
|
||||
@ -185,7 +182,7 @@ void DeviceUISet::deleteChannel(int channelIndex)
|
||||
qPrintable(m_channelInstanceRegistrations[channelIndex].m_channelAPI->getURI()),
|
||||
channelIndex);
|
||||
m_channelInstanceRegistrations[channelIndex].m_gui->destroy();
|
||||
m_channelInstanceRegistrations[channelIndex].m_channelAPI->destroy();
|
||||
delete m_channelInstanceRegistrations[channelIndex].m_channelAPI;
|
||||
m_channelInstanceRegistrations.removeAt(channelIndex);
|
||||
}
|
||||
|
||||
@ -226,14 +223,14 @@ bool DeviceUISet::deserialize(const QByteArray& data)
|
||||
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray data;
|
||||
QByteArray bdata;
|
||||
|
||||
d.readBlob(1, &data);
|
||||
m_deviceAPI->deserialize(data);
|
||||
d.readBlob(2, &data);
|
||||
m_deviceGUI->deserialize(data);
|
||||
d.readBlob(3, &data);
|
||||
m_spectrumGUI->deserialize(data);
|
||||
d.readBlob(1, &bdata);
|
||||
m_deviceAPI->deserialize(bdata);
|
||||
d.readBlob(2, &bdata);
|
||||
m_deviceGUI->deserialize(bdata);
|
||||
d.readBlob(3, &bdata);
|
||||
m_spectrumGUI->deserialize(bdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -324,16 +321,16 @@ void DeviceUISet::loadRxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
qPrintable(m_channelInstanceRegistrations[i].m_channelAPI->getURI()));
|
||||
m_channelInstanceRegistrations[i].m_channelAPI->setMessageQueueToGUI(nullptr); // have channel stop sending messages to its GUI
|
||||
m_channelInstanceRegistrations[i].m_gui->destroy();
|
||||
m_channelInstanceRegistrations[i].m_channelAPI->destroy();
|
||||
delete m_channelInstanceRegistrations[i].m_channelAPI;
|
||||
}
|
||||
|
||||
m_channelInstanceRegistrations.clear();
|
||||
m_deviceSet->clearChannels();
|
||||
qDebug("DeviceUISet::loadRxChannelSettings: %d channel(s) in preset", preset->getChannelCount());
|
||||
|
||||
for (int i = 0; i < preset->getChannelCount(); i++)
|
||||
for (int j = 0; j < preset->getChannelCount(); j++)
|
||||
{
|
||||
const Preset::ChannelConfig& channelConfig = preset->getChannelConfig(i);
|
||||
const Preset::ChannelConfig& channelConfig = preset->getChannelConfig(j);
|
||||
ChannelGUI *rxChannelGUI = nullptr;
|
||||
ChannelAPI *channelAPI = nullptr;
|
||||
|
||||
@ -348,7 +345,7 @@ void DeviceUISet::loadRxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
qPrintable((*channelRegistrations)[i].m_channelIdURI),
|
||||
qPrintable(channelConfig.m_channelIdURI));
|
||||
BasebandSampleSink *rxChannel = nullptr;
|
||||
PluginInterface *pluginInterface = (*channelRegistrations)[i].m_plugin;
|
||||
const PluginInterface *pluginInterface = (*channelRegistrations)[i].m_plugin;
|
||||
pluginInterface->createRxChannel(m_deviceAPI, &rxChannel, &channelAPI);
|
||||
rxChannelGUI = pluginInterface->createRxChannelGUI(this, rxChannel);
|
||||
rxChannelGUI->setDisplayedame(pluginInterface->getPluginDescriptor().displayedName);
|
||||
@ -357,7 +354,7 @@ void DeviceUISet::loadRxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
rxChannelGUI,
|
||||
&ChannelGUI::closing,
|
||||
this,
|
||||
[=](){ this->handleChannelGUIClosing(rxChannelGUI); },
|
||||
[this, rxChannelGUI](){ this->handleChannelGUIClosing(rxChannelGUI); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
break;
|
||||
@ -370,7 +367,7 @@ void DeviceUISet::loadRxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
rxChannelGUI->deserialize(channelConfig.m_config);
|
||||
int originalWorkspaceIndex = rxChannelGUI->getWorkspaceIndex();
|
||||
|
||||
if (workspaces && (workspaces->size() > 0) && (originalWorkspaceIndex < workspaces->size())) // restore in original workspace
|
||||
if (workspaces && (!workspaces->empty()) && (originalWorkspaceIndex < workspaces->size())) // restore in original workspace
|
||||
{
|
||||
(*workspaces)[originalWorkspaceIndex]->addToMdiArea((QMdiSubWindow*) rxChannelGUI);
|
||||
}
|
||||
@ -395,19 +392,19 @@ void DeviceUISet::loadRxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
rxChannelGUI,
|
||||
&ChannelGUI::moveToWorkspace,
|
||||
this,
|
||||
[=](int wsIndexDest){ MainWindow::getInstance()->channelMove(rxChannelGUI, wsIndexDest); }
|
||||
[rxChannelGUI](int wsIndexDest){ MainWindow::getInstance()->channelMove(rxChannelGUI, wsIndexDest); }
|
||||
);
|
||||
QObject::connect(
|
||||
rxChannelGUI,
|
||||
&ChannelGUI::duplicateChannelEmitted,
|
||||
this,
|
||||
[=](){ MainWindow::getInstance()->channelDuplicate(rxChannelGUI); }
|
||||
[rxChannelGUI](){ MainWindow::getInstance()->channelDuplicate(rxChannelGUI); }
|
||||
);
|
||||
QObject::connect(
|
||||
rxChannelGUI,
|
||||
&ChannelGUI::moveToDeviceSet,
|
||||
this,
|
||||
[=](int dsIndexDest){ MainWindow::getInstance()->channelMoveToDeviceSet(rxChannelGUI, dsIndexDest); }
|
||||
[rxChannelGUI](int dsIndexDest){ MainWindow::getInstance()->channelMoveToDeviceSet(rxChannelGUI, dsIndexDest); }
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -453,16 +450,16 @@ void DeviceUISet::loadTxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
qPrintable(m_channelInstanceRegistrations[i].m_channelAPI->getURI()));
|
||||
m_channelInstanceRegistrations[i].m_channelAPI->setMessageQueueToGUI(nullptr); // have channel stop sending messages to its GUI
|
||||
m_channelInstanceRegistrations[i].m_gui->destroy();
|
||||
m_channelInstanceRegistrations[i].m_channelAPI->destroy();
|
||||
delete m_channelInstanceRegistrations[i].m_channelAPI;
|
||||
}
|
||||
|
||||
m_channelInstanceRegistrations.clear();
|
||||
m_deviceSet->clearChannels();
|
||||
qDebug("DeviceUISet::loadTxChannelSettings: %d channel(s) in preset", preset->getChannelCount());
|
||||
|
||||
for (int i = 0; i < preset->getChannelCount(); i++)
|
||||
for (int j = 0; j < preset->getChannelCount(); j++)
|
||||
{
|
||||
const Preset::ChannelConfig& channelConfig = preset->getChannelConfig(i);
|
||||
const Preset::ChannelConfig& channelConfig = preset->getChannelConfig(j);
|
||||
ChannelGUI *txChannelGUI = nullptr;
|
||||
ChannelAPI *channelAPI = nullptr;
|
||||
|
||||
@ -475,8 +472,8 @@ void DeviceUISet::loadTxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
qDebug("DeviceUISet::loadTxChannelSettings: creating new channel [%s] from config [%s]",
|
||||
qPrintable((*channelRegistrations)[i].m_channelIdURI),
|
||||
qPrintable(channelConfig.m_channelIdURI));
|
||||
BasebandSampleSource *txChannel;
|
||||
PluginInterface *pluginInterface = (*channelRegistrations)[i].m_plugin;
|
||||
BasebandSampleSource *txChannel = nullptr;
|
||||
const PluginInterface *pluginInterface = (*channelRegistrations)[i].m_plugin;
|
||||
pluginInterface->createTxChannel(m_deviceAPI, &txChannel, &channelAPI);
|
||||
txChannelGUI = pluginInterface->createTxChannelGUI(this, txChannel);
|
||||
txChannelGUI->setDisplayedame(pluginInterface->getPluginDescriptor().displayedName);
|
||||
@ -485,7 +482,7 @@ void DeviceUISet::loadTxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
txChannelGUI,
|
||||
&ChannelGUI::closing,
|
||||
this,
|
||||
[=](){ this->handleChannelGUIClosing(txChannelGUI); },
|
||||
[this, txChannelGUI](){ this->handleChannelGUIClosing(txChannelGUI); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
break;
|
||||
@ -498,7 +495,7 @@ void DeviceUISet::loadTxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
txChannelGUI->deserialize(channelConfig.m_config);
|
||||
int originalWorkspaceIndex = txChannelGUI->getWorkspaceIndex();
|
||||
|
||||
if (workspaces && (workspaces->size() > 0) && (originalWorkspaceIndex < workspaces->size())) // restore in original workspace
|
||||
if (workspaces && (!workspaces->empty()) && (originalWorkspaceIndex < workspaces->size())) // restore in original workspace
|
||||
{
|
||||
(*workspaces)[originalWorkspaceIndex]->addToMdiArea((QMdiSubWindow*) txChannelGUI);
|
||||
}
|
||||
@ -523,19 +520,19 @@ void DeviceUISet::loadTxChannelSettings(const Preset *preset, PluginAPI *pluginA
|
||||
txChannelGUI,
|
||||
&ChannelGUI::moveToWorkspace,
|
||||
this,
|
||||
[=](int wsIndexDest){ MainWindow::getInstance()->channelMove(txChannelGUI, wsIndexDest); }
|
||||
[txChannelGUI](int wsIndexDest){ MainWindow::getInstance()->channelMove(txChannelGUI, wsIndexDest); }
|
||||
);
|
||||
QObject::connect(
|
||||
txChannelGUI,
|
||||
&ChannelGUI::duplicateChannelEmitted,
|
||||
this,
|
||||
[=](){ MainWindow::getInstance()->channelDuplicate(txChannelGUI); }
|
||||
[txChannelGUI](){ MainWindow::getInstance()->channelDuplicate(txChannelGUI); }
|
||||
);
|
||||
QObject::connect(
|
||||
txChannelGUI,
|
||||
&ChannelGUI::moveToDeviceSet,
|
||||
this,
|
||||
[=](int dsIndexDest){ MainWindow::getInstance()->channelMoveToDeviceSet(txChannelGUI, dsIndexDest); }
|
||||
[txChannelGUI](int dsIndexDest){ MainWindow::getInstance()->channelMoveToDeviceSet(txChannelGUI, dsIndexDest); }
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -579,16 +576,16 @@ void DeviceUISet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *plugi
|
||||
qDebug("DeviceUISet::loadMIMOChannelSettings: destroying old channel [%s]",
|
||||
qPrintable(m_channelInstanceRegistrations[i].m_channelAPI->getURI()));
|
||||
m_channelInstanceRegistrations[i].m_gui->destroy(); // stop GUI first (issue #1427)
|
||||
m_channelInstanceRegistrations[i].m_channelAPI->destroy(); // stop channel before (issue #860)
|
||||
delete m_channelInstanceRegistrations[i].m_channelAPI; // stop channel before (issue #860)
|
||||
}
|
||||
|
||||
m_channelInstanceRegistrations.clear();
|
||||
m_deviceSet->clearChannels();
|
||||
qDebug("DeviceUISet::loadMIMOChannelSettings: %d channel(s) in preset", preset->getChannelCount());
|
||||
|
||||
for (int i = 0; i < preset->getChannelCount(); i++)
|
||||
for (int j = 0; j < preset->getChannelCount(); j++)
|
||||
{
|
||||
const Preset::ChannelConfig& channelConfig = preset->getChannelConfig(i);
|
||||
const Preset::ChannelConfig& channelConfig = preset->getChannelConfig(j);
|
||||
ChannelGUI *channelGUI = nullptr;
|
||||
ChannelAPI *channelAPI = nullptr;
|
||||
|
||||
@ -602,8 +599,8 @@ void DeviceUISet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *plugi
|
||||
qDebug("DeviceUISet::loadMIMOChannelSettings: creating new MIMO channel [%s] from config [%s]",
|
||||
qPrintable((*channelMIMORegistrations)[i].m_channelIdURI),
|
||||
qPrintable(channelConfig.m_channelIdURI));
|
||||
MIMOChannel *mimoChannel;
|
||||
PluginInterface *pluginInterface = (*channelMIMORegistrations)[i].m_plugin;
|
||||
MIMOChannel *mimoChannel = nullptr;
|
||||
const PluginInterface *pluginInterface = (*channelMIMORegistrations)[i].m_plugin;
|
||||
pluginInterface->createMIMOChannel(m_deviceAPI, &mimoChannel, &channelAPI);
|
||||
channelGUI = pluginInterface->createMIMOChannelGUI(this, mimoChannel);
|
||||
channelGUI->setDisplayedame(pluginInterface->getPluginDescriptor().displayedName);
|
||||
@ -612,7 +609,7 @@ void DeviceUISet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *plugi
|
||||
channelGUI,
|
||||
&ChannelGUI::closing,
|
||||
this,
|
||||
[=](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
[this, channelGUI](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
break;
|
||||
@ -629,8 +626,8 @@ void DeviceUISet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *plugi
|
||||
qDebug("DeviceUISet::loadMIMOChannelSettings: creating new Rx channel [%s] from config [%s]",
|
||||
qPrintable((*channelRxRegistrations)[i].m_channelIdURI),
|
||||
qPrintable(channelConfig.m_channelIdURI));
|
||||
BasebandSampleSink *rxChannel;
|
||||
PluginInterface *pluginInterface = (*channelRxRegistrations)[i].m_plugin;
|
||||
BasebandSampleSink *rxChannel = nullptr;
|
||||
const PluginInterface *pluginInterface = (*channelRxRegistrations)[i].m_plugin;
|
||||
pluginInterface->createRxChannel(m_deviceAPI, &rxChannel, &channelAPI);
|
||||
channelGUI = pluginInterface->createRxChannelGUI(this, rxChannel);
|
||||
channelGUI->setDisplayedame(pluginInterface->getPluginDescriptor().displayedName);
|
||||
@ -639,7 +636,7 @@ void DeviceUISet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *plugi
|
||||
channelGUI,
|
||||
&ChannelGUI::closing,
|
||||
this,
|
||||
[=](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
[this, channelGUI](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
break;
|
||||
@ -656,8 +653,8 @@ void DeviceUISet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *plugi
|
||||
qDebug("DeviceUISet::loadMIMOChannelSettings: creating new Tx channel [%s] from config [%s]",
|
||||
qPrintable((*channelTxRegistrations)[i].m_channelIdURI),
|
||||
qPrintable(channelConfig.m_channelIdURI));
|
||||
BasebandSampleSource *txChannel;
|
||||
PluginInterface *pluginInterface = (*channelTxRegistrations)[i].m_plugin;
|
||||
BasebandSampleSource *txChannel = nullptr;
|
||||
const PluginInterface *pluginInterface = (*channelTxRegistrations)[i].m_plugin;
|
||||
pluginInterface->createTxChannel(m_deviceAPI, &txChannel, &channelAPI);
|
||||
channelGUI = pluginInterface->createTxChannelGUI(this, txChannel);
|
||||
channelGUI->setDisplayedame(pluginInterface->getPluginDescriptor().displayedName);
|
||||
@ -672,7 +669,7 @@ void DeviceUISet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *plugi
|
||||
channelGUI->deserialize(channelConfig.m_config);
|
||||
int originalWorkspaceIndex = channelGUI->getWorkspaceIndex();
|
||||
|
||||
if (workspaces && (workspaces->size() > 0) && (originalWorkspaceIndex < workspaces->size())) // restore in original workspace
|
||||
if (workspaces && (!workspaces->empty()) && (originalWorkspaceIndex < workspaces->size())) // restore in original workspace
|
||||
{
|
||||
(*workspaces)[originalWorkspaceIndex]->addToMdiArea((QMdiSubWindow*) channelGUI);
|
||||
}
|
||||
@ -697,26 +694,26 @@ void DeviceUISet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *plugi
|
||||
channelGUI,
|
||||
&ChannelGUI::closing,
|
||||
this,
|
||||
[=](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
[this, channelGUI](){ this->handleChannelGUIClosing(channelGUI); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
QObject::connect(
|
||||
channelGUI,
|
||||
&ChannelGUI::moveToWorkspace,
|
||||
this,
|
||||
[=](int wsIndexDest){ MainWindow::getInstance()->channelMove(channelGUI, wsIndexDest); }
|
||||
[channelGUI](int wsIndexDest){ MainWindow::getInstance()->channelMove(channelGUI, wsIndexDest); }
|
||||
);
|
||||
QObject::connect(
|
||||
channelGUI,
|
||||
&ChannelGUI::duplicateChannelEmitted,
|
||||
this,
|
||||
[=](){ MainWindow::getInstance()->channelDuplicate(channelGUI); }
|
||||
[channelGUI](){ MainWindow::getInstance()->channelDuplicate(channelGUI); }
|
||||
);
|
||||
QObject::connect(
|
||||
channelGUI,
|
||||
&ChannelGUI::moveToDeviceSet,
|
||||
this,
|
||||
[=](int dsIndexDest){ MainWindow::getInstance()->channelMoveToDeviceSet(channelGUI, dsIndexDest); }
|
||||
[channelGUI](int dsIndexDest){ MainWindow::getInstance()->channelMoveToDeviceSet(channelGUI, dsIndexDest); }
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -766,11 +763,11 @@ bool DeviceUISet::ChannelInstanceRegistration::operator<(const ChannelInstanceRe
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceUISet::handleChannelGUIClosing(ChannelGUI* channelGUI)
|
||||
void DeviceUISet::handleChannelGUIClosing(const ChannelGUI* channelGUI)
|
||||
{
|
||||
qDebug("DeviceUISet::handleChannelGUIClosing: %s: %d", qPrintable(channelGUI->getTitle()), channelGUI->getIndex());
|
||||
|
||||
for (ChannelInstanceRegistrations::iterator it = m_channelInstanceRegistrations.begin(); it != m_channelInstanceRegistrations.end(); ++it)
|
||||
for (auto it = m_channelInstanceRegistrations.begin(); it != m_channelInstanceRegistrations.end(); ++it)
|
||||
{
|
||||
if (it->m_gui == channelGUI)
|
||||
{
|
||||
@ -793,7 +790,7 @@ void DeviceUISet::handleChannelGUIClosing(ChannelGUI* channelGUI)
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceUISet::handleDeleteChannel(ChannelAPI *channelAPI)
|
||||
void DeviceUISet::handleDeleteChannel(ChannelAPI *channelAPI) const
|
||||
{
|
||||
channelAPI->destroy();
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ class SpectrumVis;
|
||||
class GLSpectrum;
|
||||
class GLSpectrumGUI;
|
||||
class MainSpectrumGUI;
|
||||
// class ChannelWindow;
|
||||
class DeviceAPI;
|
||||
class DeviceSet;
|
||||
class DSPDeviceSourceEngine;
|
||||
@ -61,7 +60,6 @@ public:
|
||||
GLSpectrum *m_spectrum;
|
||||
GLSpectrumGUI *m_spectrumGUI;
|
||||
MainSpectrumGUI *m_mainSpectrumGUI;
|
||||
// ChannelWindow *m_channelWindow;
|
||||
DeviceAPI *m_deviceAPI;
|
||||
DeviceGUI *m_deviceGUI;
|
||||
DSPDeviceSourceEngine *m_deviceSourceEngine;
|
||||
@ -74,7 +72,7 @@ public:
|
||||
int m_selectedDeviceItemImdex;
|
||||
|
||||
DeviceUISet(int deviceSetIndex, DeviceSet *deviceSet);
|
||||
~DeviceUISet();
|
||||
~DeviceUISet() final;
|
||||
|
||||
void setIndex(int deviceSetIndex);
|
||||
int getIndex() const { return m_deviceSetIndex; }
|
||||
@ -146,10 +144,8 @@ private:
|
||||
bool operator<(const ChannelInstanceRegistration& other) const;
|
||||
};
|
||||
|
||||
typedef QList<ChannelInstanceRegistration> ChannelInstanceRegistrations;
|
||||
using ChannelInstanceRegistrations = QList<ChannelInstanceRegistration>;
|
||||
|
||||
// ChannelInstanceRegistrations m_rxChannelInstanceRegistrations;
|
||||
// ChannelInstanceRegistrations m_txChannelInstanceRegistrations;
|
||||
ChannelInstanceRegistrations m_channelInstanceRegistrations;
|
||||
int m_deviceSetIndex;
|
||||
DeviceSet *m_deviceSet;
|
||||
@ -165,8 +161,8 @@ private:
|
||||
void saveMIMOChannelSettings(Preset* preset) const;
|
||||
|
||||
private slots:
|
||||
void handleChannelGUIClosing(ChannelGUI* channelGUI);
|
||||
void handleDeleteChannel(ChannelAPI *channelAPI);
|
||||
void handleChannelGUIClosing(const ChannelGUI* channelGUI);
|
||||
void handleDeleteChannel(ChannelAPI *channelAPI) const;
|
||||
void onTimeSelected(int deviceSetIndex, float time);
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -69,27 +69,23 @@ class SerializableInterface;
|
||||
class QMenuBar;
|
||||
class Workspace;
|
||||
|
||||
// namespace Ui {
|
||||
// class MainWindow;
|
||||
// }
|
||||
|
||||
class SDRGUI_API MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parser, QWidget* parent = nullptr);
|
||||
~MainWindow();
|
||||
~MainWindow() final;
|
||||
static MainWindow *getInstance() { return m_instance; } // Main Window is de facto a singleton so this just returns its reference
|
||||
MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
const PluginManager *getPluginManager() const { return m_pluginManager; }
|
||||
std::vector<DeviceUISet*>& getDeviceUISets() { return m_deviceUIs; }
|
||||
void commandKeysConnect(QObject *object, const char *slot);
|
||||
void commandKeysDisconnect(QObject *object, const char *slot);
|
||||
void commandKeysConnect(const QObject *object, const char *slot);
|
||||
void commandKeysDisconnect(const QObject *object, const char *slot) const;
|
||||
int getNumberOfWorkspaces() const { return m_workspaces.size(); }
|
||||
|
||||
public slots:
|
||||
void channelMove(ChannelGUI *gui, int wsIndexDestination);
|
||||
void channelDuplicate(ChannelGUI *gui);
|
||||
void channelDuplicate(const ChannelGUI *gui);
|
||||
void channelMoveToDeviceSet(ChannelGUI *gui, int dsIndexDestination);
|
||||
|
||||
private:
|
||||
@ -101,14 +97,13 @@ private:
|
||||
struct DeviceWidgetTabData
|
||||
{
|
||||
QWidget *gui;
|
||||
QString displayName;
|
||||
QString tabName;
|
||||
QString displayName;
|
||||
QString tabName;
|
||||
};
|
||||
|
||||
static MainWindow *m_instance;
|
||||
QList<Workspace*> m_workspaces;
|
||||
Workspace *m_currentWorkspace;
|
||||
// Ui::MainWindow* ui;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
MainCore *m_mainCore;
|
||||
std::vector<DeviceUISet*> m_deviceUIs;
|
||||
@ -143,10 +138,10 @@ private:
|
||||
void loadFeatureSetPresetSettings(const FeatureSetPreset* preset, int featureSetIndex, Workspace *workspace);
|
||||
void saveFeatureSetPresetSettings(FeatureSetPreset* preset, int featureSetIndex);
|
||||
|
||||
QString openGLVersion();
|
||||
void createMenuBar(QToolButton *button);
|
||||
QString openGLVersion() const;
|
||||
void createMenuBar(QToolButton *button) const;
|
||||
void createStatusBar();
|
||||
void closeEvent(QCloseEvent*);
|
||||
void closeEvent(QCloseEvent*) final;
|
||||
void applySettings();
|
||||
|
||||
void removeDeviceSet(int deviceSetIndex);
|
||||
@ -155,7 +150,7 @@ private:
|
||||
void removeFeatureSet(unsigned int featureSetIndex);
|
||||
void removeAllFeatureSets();
|
||||
void deleteChannel(int deviceSetIndex, int channelIndex);
|
||||
void channelDuplicateToDeviceSet(ChannelGUI *sourceChannelGUI, int dsIndexDestination);
|
||||
void channelDuplicateToDeviceSet(const ChannelGUI *sourceChannelGUI, int dsIndexDestination);
|
||||
void sampleDeviceChange(int deviceType, int deviceSetIndex, int newDeviceIndex, Workspace *workspace);
|
||||
void sampleSourceChange(int deviceSetIndex, int newDeviceIndex, Workspace *workspace);
|
||||
void sampleSinkChange(int deviceSetIndex, int newDeviceIndex, Workspace *workspace);
|
||||
@ -181,7 +176,7 @@ private:
|
||||
bool handleMessage(const Message& cmd);
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
private slots:
|
||||
void handleMessages();
|
||||
@ -202,39 +197,39 @@ private slots:
|
||||
void on_action_My_Position_triggered();
|
||||
void on_action_DeviceUserArguments_triggered();
|
||||
void on_action_commands_triggered();
|
||||
void on_action_Quick_Start_triggered();
|
||||
void on_action_Main_Window_triggered();
|
||||
void on_action_Quick_Start_triggered() const;
|
||||
void on_action_Main_Window_triggered() const;
|
||||
void on_action_Loaded_Plugins_triggered();
|
||||
void on_action_About_triggered();
|
||||
|
||||
void updateStatus();
|
||||
void addWorkspace();
|
||||
void viewAllWorkspaces();
|
||||
void viewAllWorkspaces() const;
|
||||
void removeEmptyWorkspaces();
|
||||
void openConfigurationDialog(bool openOnly);
|
||||
void loadDefaultConfigurations();
|
||||
void loadDefaultConfigurations() const;
|
||||
void loadConfiguration(const Configuration *configuration, bool fromDialog = false);
|
||||
void saveConfiguration(Configuration *configuration);
|
||||
void sampleSourceAdd(Workspace *deviceWorkspace, Workspace *spectrumWorkspace, int deviceIndex);
|
||||
void sampleSinkAdd(Workspace *workspace, Workspace *spectrumWorkspace, int deviceIndex);
|
||||
void sampleMIMOAdd(Workspace *workspace, Workspace *spectrumWorkspace, int deviceIndex);
|
||||
void samplingDeviceChangeHandler(DeviceGUI *deviceGUI, int newDeviceIndex);
|
||||
void samplingDeviceChangeHandler(const DeviceGUI *deviceGUI, int newDeviceIndex);
|
||||
void channelAddClicked(Workspace *workspace, int deviceSetIndex, int channelPluginIndex);
|
||||
void featureAddClicked(Workspace *workspace, int featureIndex);
|
||||
void featureMove(FeatureGUI *gui, int wsIndexDestnation);
|
||||
void deviceStateChanged(DeviceAPI *deviceAPI);
|
||||
void openFeaturePresetsDialog(QPoint p, Workspace *workspace);
|
||||
void startAllDevices(Workspace *workspace);
|
||||
void stopAllDevices(Workspace *workspace);
|
||||
void startAllDevices(const Workspace *workspace) const;
|
||||
void stopAllDevices(const Workspace *workspace) const;
|
||||
void deviceMove(DeviceGUI *gui, int wsIndexDestnation);
|
||||
void mainSpectrumMove(MainSpectrumGUI *gui, int wsIndexDestnation);
|
||||
void mainSpectrumShow(int deviceSetIndex);
|
||||
void mainSpectrumRequestDeviceCenterFrequency(int deviceSetIndex, qint64 deviceCenterFrequency);
|
||||
void showAllChannels(int deviceSetIndex);
|
||||
void openDeviceSetPresetsDialog(QPoint p, DeviceGUI *deviceGUI);
|
||||
void commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release);
|
||||
void openDeviceSetPresetsDialog(QPoint p, const DeviceGUI *deviceGUI);
|
||||
void commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release) const;
|
||||
void fftWisdomProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void orientationChanged(Qt::ScreenOrientation orientation);
|
||||
void orientationChanged(Qt::ScreenOrientation orientation) const;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_MAINWINDOW_H
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include "dsp/dspdevicesourceengine.h"
|
||||
#include "dsp/dspdevicesinkengine.h"
|
||||
#include "dsp/dspdevicemimoengine.h"
|
||||
#include "dsp/devicesamplesource.h"
|
||||
#include "dsp/devicesamplesink.h"
|
||||
#include "dsp/devicesamplemimo.h"
|
||||
#include "dsp/spectrumvis.h"
|
||||
#include "device/deviceapi.h"
|
||||
#include "device/deviceset.h"
|
||||
@ -40,7 +43,7 @@
|
||||
#include "mainparser.h"
|
||||
#include "mainserver.h"
|
||||
|
||||
MainServer *MainServer::m_instance = 0;
|
||||
MainServer *MainServer::m_instance = nullptr;
|
||||
|
||||
MainServer::MainServer(qtwebapp::LoggerWithFile *logger, const MainParser& parser, QObject *parent) :
|
||||
QObject(parent),
|
||||
@ -71,7 +74,7 @@ MainServer::MainServer(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
loadSettings();
|
||||
|
||||
qDebug() << "MainServer::MainServer: finishing...";
|
||||
QString applicationDirPath = QCoreApplication::instance()->applicationDirPath();
|
||||
QString applicationDirPath = QCoreApplication::applicationDirPath();
|
||||
|
||||
m_apiAdapter = new WebAPIAdapter();
|
||||
m_requestMapper = new WebAPIRequestMapper(this);
|
||||
@ -86,7 +89,7 @@ MainServer::MainServer(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
|
||||
MainServer::~MainServer()
|
||||
{
|
||||
while (m_mainCore->m_deviceSets.size() > 0) {
|
||||
while (!m_mainCore->m_deviceSets.empty()) {
|
||||
removeLastDevice();
|
||||
}
|
||||
|
||||
@ -105,7 +108,7 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
{
|
||||
if (MainCore::MsgDeleteInstance::match(cmd))
|
||||
{
|
||||
while (m_mainCore->m_deviceSets.size() > 0)
|
||||
while (!m_mainCore->m_deviceSets.empty())
|
||||
{
|
||||
removeLastDevice();
|
||||
}
|
||||
@ -115,13 +118,13 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MainCore::MsgLoadPreset::match(cmd))
|
||||
{
|
||||
MainCore::MsgLoadPreset& notif = (MainCore::MsgLoadPreset&) cmd;
|
||||
auto& notif = (const MainCore::MsgLoadPreset&) cmd;
|
||||
loadPresetSettings(notif.getPreset(), notif.getDeviceSetIndex());
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgSavePreset::match(cmd))
|
||||
{
|
||||
MainCore::MsgSavePreset& notif = (MainCore::MsgSavePreset&) cmd;
|
||||
auto& notif = (const MainCore::MsgSavePreset&) cmd;
|
||||
savePresetSettings(notif.getPreset(), notif.getDeviceSetIndex());
|
||||
m_mainCore->m_settings.sortPresets();
|
||||
m_mainCore->m_settings.save();
|
||||
@ -129,7 +132,7 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MainCore::MsgDeletePreset::match(cmd))
|
||||
{
|
||||
MainCore::MsgDeletePreset& notif = (MainCore::MsgDeletePreset&) cmd;
|
||||
auto& notif = (const MainCore::MsgDeletePreset&) cmd;
|
||||
const Preset *presetToDelete = notif.getPreset();
|
||||
// remove preset from settings
|
||||
m_mainCore->m_settings.deletePreset(presetToDelete);
|
||||
@ -137,7 +140,7 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MainCore::MsgDeleteConfiguration::match(cmd))
|
||||
{
|
||||
MainCore::MsgDeleteConfiguration& notif = (MainCore::MsgDeleteConfiguration&) cmd;
|
||||
auto& notif = (const MainCore::MsgDeleteConfiguration&) cmd;
|
||||
const Configuration *configuationToDelete = notif.getConfiguration();
|
||||
// remove configuration from settings
|
||||
m_mainCore->m_settings.deleteConfiguration(configuationToDelete);
|
||||
@ -145,13 +148,13 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MainCore::MsgLoadFeatureSetPreset::match(cmd))
|
||||
{
|
||||
MainCore::MsgLoadFeatureSetPreset& notif = (MainCore::MsgLoadFeatureSetPreset&) cmd;
|
||||
auto& notif = (const MainCore::MsgLoadFeatureSetPreset&) cmd;
|
||||
loadFeatureSetPresetSettings(notif.getPreset(), notif.getFeatureSetIndex());
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgSaveFeatureSetPreset::match(cmd))
|
||||
{
|
||||
MainCore::MsgSaveFeatureSetPreset& notif = (MainCore::MsgSaveFeatureSetPreset&) cmd;
|
||||
auto& notif = (const MainCore::MsgSaveFeatureSetPreset&) cmd;
|
||||
saveFeatureSetPresetSettings(notif.getPreset(), notif.getFeatureSetIndex());
|
||||
m_mainCore->m_settings.sortPresets();
|
||||
m_mainCore->m_settings.save();
|
||||
@ -159,7 +162,7 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MainCore::MsgDeleteFeatureSetPreset::match(cmd))
|
||||
{
|
||||
MainCore::MsgDeleteFeatureSetPreset& notif = (MainCore::MsgDeleteFeatureSetPreset&) cmd;
|
||||
auto& notif = (const MainCore::MsgDeleteFeatureSetPreset&) cmd;
|
||||
const FeatureSetPreset *presetToDelete = notif.getPreset();
|
||||
// remove preset from settings
|
||||
m_mainCore->m_settings.deleteFeatureSetPreset(presetToDelete);
|
||||
@ -167,7 +170,7 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MainCore::MsgAddDeviceSet::match(cmd))
|
||||
{
|
||||
MainCore::MsgAddDeviceSet& notif = (MainCore::MsgAddDeviceSet&) cmd;
|
||||
auto& notif = (const MainCore::MsgAddDeviceSet&) cmd;
|
||||
int direction = notif.getDirection();
|
||||
|
||||
if (direction == 1) { // Single stream Tx
|
||||
@ -182,7 +185,7 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MainCore::MsgRemoveLastDeviceSet::match(cmd))
|
||||
{
|
||||
if (m_mainCore->m_deviceSets.size() > 0) {
|
||||
if (!m_mainCore->m_deviceSets.empty()) {
|
||||
removeLastDevice();
|
||||
}
|
||||
|
||||
@ -190,7 +193,7 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MainCore::MsgSetDevice::match(cmd))
|
||||
{
|
||||
MainCore::MsgSetDevice& notif = (MainCore::MsgSetDevice&) cmd;
|
||||
auto& notif = (const MainCore::MsgSetDevice&) cmd;
|
||||
|
||||
if (notif.getDeviceType() == 1) {
|
||||
changeSampleSink(notif.getDeviceSetIndex(), notif.getDeviceIndex());
|
||||
@ -203,26 +206,26 @@ bool MainServer::handleMessage(const Message& cmd)
|
||||
}
|
||||
else if (MainCore::MsgAddChannel::match(cmd))
|
||||
{
|
||||
MainCore::MsgAddChannel& notif = (MainCore::MsgAddChannel&) cmd;
|
||||
auto& notif = (const MainCore::MsgAddChannel&) cmd;
|
||||
addChannel(notif.getDeviceSetIndex(), notif.getChannelRegistrationIndex());
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgDeleteChannel::match(cmd))
|
||||
{
|
||||
MainCore::MsgDeleteChannel& notif = (MainCore::MsgDeleteChannel&) cmd;
|
||||
auto& notif = (const MainCore::MsgDeleteChannel&) cmd;
|
||||
deleteChannel(notif.getDeviceSetIndex(), notif.getChannelIndex());
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgAddFeature::match(cmd))
|
||||
{
|
||||
MainCore::MsgAddFeature& notif = (MainCore::MsgAddFeature&) cmd;
|
||||
auto& notif = (const MainCore::MsgAddFeature&) cmd;
|
||||
addFeature(0, notif.getFeatureRegistrationIndex());
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgDeleteFeature::match(cmd))
|
||||
{
|
||||
MainCore::MsgDeleteFeature& notif = (MainCore::MsgDeleteFeature&) cmd;
|
||||
auto& notif = (const MainCore::MsgDeleteFeature&) cmd;
|
||||
deleteFeature(0, notif.getFeatureIndex());
|
||||
return true;
|
||||
}
|
||||
@ -241,7 +244,7 @@ void MainServer::handleMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_inputMessageQueue.pop()) != 0)
|
||||
while ((message = m_inputMessageQueue.pop()) != nullptr)
|
||||
{
|
||||
qDebug("MainServer::handleMessages: message: %s", message->getIdentifier());
|
||||
handleMessage(*message);
|
||||
@ -267,23 +270,15 @@ void MainServer::applySettings()
|
||||
void MainServer::addSinkDevice()
|
||||
{
|
||||
DSPDeviceSinkEngine *dspDeviceSinkEngine = m_dspEngine->addDeviceSinkEngine();
|
||||
dspDeviceSinkEngine->start();
|
||||
|
||||
uint dspDeviceSinkEngineUID = dspDeviceSinkEngine->getUID();
|
||||
char uidCStr[16];
|
||||
sprintf(uidCStr, "UID:%d", dspDeviceSinkEngineUID);
|
||||
|
||||
int deviceTabIndex = m_mainCore->m_deviceSets.size();
|
||||
auto deviceTabIndex = (int) m_mainCore->m_deviceSets.size();
|
||||
m_mainCore->m_deviceSets.push_back(new DeviceSet(deviceTabIndex, 1));
|
||||
m_mainCore->m_deviceSets.back()->m_deviceSourceEngine = nullptr;
|
||||
m_mainCore->m_deviceSets.back()->m_deviceSinkEngine = dspDeviceSinkEngine;
|
||||
m_mainCore->m_deviceSets.back()->m_deviceMIMOEngine = nullptr;
|
||||
dspDeviceSinkEngine->addSpectrumSink(m_mainCore->m_deviceSets.back()->m_spectrumVis);
|
||||
|
||||
char tabNameCStr[16];
|
||||
sprintf(tabNameCStr, "T%d", deviceTabIndex);
|
||||
|
||||
DeviceAPI *deviceAPI = new DeviceAPI(DeviceAPI::StreamSingleTx, deviceTabIndex, nullptr, dspDeviceSinkEngine, nullptr);
|
||||
auto *deviceAPI = new DeviceAPI(DeviceAPI::StreamSingleTx, deviceTabIndex, nullptr, dspDeviceSinkEngine, nullptr);
|
||||
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI = deviceAPI;
|
||||
QList<QString> channelNames;
|
||||
@ -315,23 +310,15 @@ void MainServer::addSinkDevice()
|
||||
void MainServer::addSourceDevice()
|
||||
{
|
||||
DSPDeviceSourceEngine *dspDeviceSourceEngine = m_dspEngine->addDeviceSourceEngine();
|
||||
dspDeviceSourceEngine->start();
|
||||
|
||||
uint dspDeviceSourceEngineUID = dspDeviceSourceEngine->getUID();
|
||||
char uidCStr[16];
|
||||
sprintf(uidCStr, "UID:%d", dspDeviceSourceEngineUID);
|
||||
|
||||
int deviceTabIndex = m_mainCore->m_deviceSets.size();
|
||||
auto deviceTabIndex = (int) m_mainCore->m_deviceSets.size();
|
||||
m_mainCore->m_deviceSets.push_back(new DeviceSet(deviceTabIndex, 0));
|
||||
m_mainCore->m_deviceSets.back()->m_deviceSourceEngine = dspDeviceSourceEngine;
|
||||
m_mainCore->m_deviceSets.back()->m_deviceSinkEngine = nullptr;
|
||||
m_mainCore->m_deviceSets.back()->m_deviceMIMOEngine = nullptr;
|
||||
dspDeviceSourceEngine->addSink(m_mainCore->m_deviceSets.back()->m_spectrumVis);
|
||||
|
||||
char tabNameCStr[16];
|
||||
sprintf(tabNameCStr, "R%d", deviceTabIndex);
|
||||
|
||||
DeviceAPI *deviceAPI = new DeviceAPI(DeviceAPI::StreamSingleRx, deviceTabIndex, dspDeviceSourceEngine, nullptr, nullptr);
|
||||
auto *deviceAPI = new DeviceAPI(DeviceAPI::StreamSingleRx, deviceTabIndex, dspDeviceSourceEngine, nullptr, nullptr);
|
||||
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI = deviceAPI;
|
||||
|
||||
@ -362,23 +349,15 @@ void MainServer::addSourceDevice()
|
||||
void MainServer::addMIMODevice()
|
||||
{
|
||||
DSPDeviceMIMOEngine *dspDeviceMIMOEngine = m_dspEngine->addDeviceMIMOEngine();
|
||||
dspDeviceMIMOEngine->start();
|
||||
|
||||
uint dspDeviceMIMOEngineUID = dspDeviceMIMOEngine->getUID();
|
||||
char uidCStr[16];
|
||||
sprintf(uidCStr, "UID:%d", dspDeviceMIMOEngineUID);
|
||||
|
||||
int deviceTabIndex = m_mainCore->m_deviceSets.size();
|
||||
auto deviceTabIndex = (int) m_mainCore->m_deviceSets.size();
|
||||
m_mainCore->m_deviceSets.push_back(new DeviceSet(deviceTabIndex, 2));
|
||||
m_mainCore->m_deviceSets.back()->m_deviceSourceEngine = nullptr;
|
||||
m_mainCore->m_deviceSets.back()->m_deviceSinkEngine = nullptr;
|
||||
m_mainCore->m_deviceSets.back()->m_deviceMIMOEngine = dspDeviceMIMOEngine;
|
||||
dspDeviceMIMOEngine->addSpectrumSink(m_mainCore->m_deviceSets.back()->m_spectrumVis);
|
||||
|
||||
char tabNameCStr[16];
|
||||
sprintf(tabNameCStr, "M%d", deviceTabIndex);
|
||||
|
||||
DeviceAPI *deviceAPI = new DeviceAPI(DeviceAPI::StreamMIMO, deviceTabIndex, nullptr, nullptr, dspDeviceMIMOEngine);
|
||||
auto *deviceAPI = new DeviceAPI(DeviceAPI::StreamMIMO, deviceTabIndex, nullptr, nullptr, dspDeviceMIMOEngine);
|
||||
|
||||
// create a test MIMO by default
|
||||
int testMIMODeviceIndex = DeviceEnumerator::instance()->getTestMIMODeviceIndex();
|
||||
@ -406,48 +385,48 @@ void MainServer::addMIMODevice()
|
||||
|
||||
void MainServer::removeLastDevice()
|
||||
{
|
||||
int removedTabIndex = m_mainCore->m_deviceSets.size() - 1;
|
||||
auto removedTabIndex = (int) (m_mainCore->m_deviceSets.size() - 1);
|
||||
|
||||
if (m_mainCore->m_deviceSets.back()->m_deviceSourceEngine) // source set
|
||||
{
|
||||
DSPDeviceSourceEngine *lastDeviceEngine = m_mainCore->m_deviceSets.back()->m_deviceSourceEngine;
|
||||
lastDeviceEngine->stopAcquistion();
|
||||
|
||||
// deletes old UI and input object
|
||||
m_mainCore->m_deviceSets.back()->freeChannels(); // destroys the channel instances
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI->resetSamplingDeviceId();
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI->getPluginInterface()->deleteSampleSourcePluginInstanceInput(
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI->getSampleSource());
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI->clearBuddiesLists(); // clear old API buddies lists
|
||||
|
||||
m_dspEngine->removeLastDeviceSourceEngine();
|
||||
|
||||
DeviceAPI *sourceAPI = m_mainCore->m_deviceSets.back()->m_deviceAPI;
|
||||
delete m_mainCore->m_deviceSets.back();
|
||||
|
||||
lastDeviceEngine->stop();
|
||||
m_dspEngine->removeLastDeviceSourceEngine();
|
||||
|
||||
delete sourceAPI->getSampleSource();
|
||||
delete sourceAPI;
|
||||
}
|
||||
else if (m_mainCore->m_deviceSets.back()->m_deviceSinkEngine) // sink set
|
||||
{
|
||||
DSPDeviceSinkEngine *lastDeviceEngine = m_mainCore->m_deviceSets.back()->m_deviceSinkEngine;
|
||||
lastDeviceEngine->stopGeneration();
|
||||
|
||||
// deletes old UI and output object
|
||||
m_mainCore->m_deviceSets.back()->freeChannels();
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI->resetSamplingDeviceId();
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI->getPluginInterface()->deleteSampleSinkPluginInstanceOutput(
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI->getSampleSink());
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI->clearBuddiesLists(); // clear old API buddies lists
|
||||
|
||||
m_dspEngine->removeLastDeviceSinkEngine();
|
||||
|
||||
DeviceAPI *sinkAPI = m_mainCore->m_deviceSets.back()->m_deviceAPI;
|
||||
delete m_mainCore->m_deviceSets.back();
|
||||
|
||||
lastDeviceEngine->stop();
|
||||
m_dspEngine->removeLastDeviceSinkEngine();
|
||||
|
||||
delete sinkAPI->getSampleSink();
|
||||
delete sinkAPI;
|
||||
}
|
||||
else if (m_mainCore->m_deviceSets.back()->m_deviceMIMOEngine) // MIMO set
|
||||
{
|
||||
m_mainCore->m_deviceSets.back()->freeChannels();
|
||||
m_mainCore->m_deviceSets.back()->m_deviceAPI->resetSamplingDeviceId();
|
||||
|
||||
m_dspEngine->removeLastDeviceSourceEngine();
|
||||
|
||||
DeviceAPI *mimoAPI = m_mainCore->m_deviceSets.back()->m_deviceAPI;
|
||||
delete m_mainCore->m_deviceSets.back();
|
||||
delete mimoAPI->getSampleMIMO();
|
||||
delete mimoAPI;
|
||||
}
|
||||
|
||||
m_mainCore->m_deviceSets.pop_back();
|
||||
emit m_mainCore->deviceSetRemoved(removedTabIndex);
|
||||
@ -494,19 +473,17 @@ void MainServer::changeSampleSource(int deviceSetIndex, int selectedDeviceIndex)
|
||||
}
|
||||
|
||||
// add to buddies list
|
||||
std::vector<DeviceSet*>::iterator it = m_mainCore->m_deviceSets.begin();
|
||||
auto it = m_mainCore->m_deviceSets.begin();
|
||||
int nbOfBuddies = 0;
|
||||
|
||||
for (; it != m_mainCore->m_deviceSets.end(); ++it)
|
||||
{
|
||||
if (*it != deviceSet) // do not add to itself
|
||||
if ((*it != deviceSet) && // do not add to itself
|
||||
(deviceSet->m_deviceAPI->getHardwareId() == (*it)->m_deviceAPI->getHardwareId()) &&
|
||||
(deviceSet->m_deviceAPI->getSamplingDeviceSerial() == (*it)->m_deviceAPI->getSamplingDeviceSerial()))
|
||||
{
|
||||
if ((deviceSet->m_deviceAPI->getHardwareId() == (*it)->m_deviceAPI->getHardwareId()) &&
|
||||
(deviceSet->m_deviceAPI->getSamplingDeviceSerial() == (*it)->m_deviceAPI->getSamplingDeviceSerial()))
|
||||
{
|
||||
(*it)->m_deviceAPI->addBuddy(deviceSet->m_deviceAPI);
|
||||
nbOfBuddies++;
|
||||
}
|
||||
(*it)->m_deviceAPI->addBuddy(deviceSet->m_deviceAPI);
|
||||
nbOfBuddies++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -555,7 +532,7 @@ void MainServer::changeSampleSink(int deviceSetIndex, int selectedDeviceIndex)
|
||||
{
|
||||
qDebug("MainServer::changeSampleSink: non existent device replaced by File Sink");
|
||||
int fileSinkDeviceIndex = DeviceEnumerator::instance()->getFileOutputDeviceIndex();
|
||||
const PluginInterface::SamplingDevice *samplingDevice = DeviceEnumerator::instance()->getTxSamplingDevice(fileSinkDeviceIndex);
|
||||
samplingDevice = DeviceEnumerator::instance()->getTxSamplingDevice(fileSinkDeviceIndex);
|
||||
deviceSet->m_deviceAPI->setSamplingDeviceSequence(samplingDevice->sequence);
|
||||
deviceSet->m_deviceAPI->setDeviceNbItems(samplingDevice->deviceNbItems);
|
||||
deviceSet->m_deviceAPI->setDeviceItemIndex(samplingDevice->deviceItemIndex);
|
||||
@ -567,19 +544,17 @@ void MainServer::changeSampleSink(int deviceSetIndex, int selectedDeviceIndex)
|
||||
}
|
||||
|
||||
// add to buddies list
|
||||
std::vector<DeviceSet*>::iterator it = m_mainCore->m_deviceSets.begin();
|
||||
auto it = m_mainCore->m_deviceSets.begin();
|
||||
int nbOfBuddies = 0;
|
||||
|
||||
for (; it != m_mainCore->m_deviceSets.end(); ++it)
|
||||
{
|
||||
if (*it != deviceSet) // do not add to itself
|
||||
if ((deviceSet->m_deviceAPI->getHardwareId() == (*it)->m_deviceAPI->getHardwareId()) &&
|
||||
(deviceSet->m_deviceAPI->getSamplingDeviceSerial() == (*it)->m_deviceAPI->getSamplingDeviceSerial()) &&
|
||||
(*it != deviceSet)) // do not add to itself
|
||||
{
|
||||
if ((deviceSet->m_deviceAPI->getHardwareId() == (*it)->m_deviceAPI->getHardwareId()) &&
|
||||
(deviceSet->m_deviceAPI->getSamplingDeviceSerial() == (*it)->m_deviceAPI->getSamplingDeviceSerial()))
|
||||
{
|
||||
(*it)->m_deviceAPI->addBuddy(deviceSet->m_deviceAPI);
|
||||
nbOfBuddies++;
|
||||
}
|
||||
(*it)->m_deviceAPI->addBuddy(deviceSet->m_deviceAPI);
|
||||
nbOfBuddies++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -624,7 +599,7 @@ void MainServer::changeSampleMIMO(int deviceSetIndex, int selectedDeviceIndex)
|
||||
{
|
||||
qDebug("MainServer::changeSampleMIMO: non existent device replaced by Test MIMO");
|
||||
int testMIMODeviceIndex = DeviceEnumerator::instance()->getTestMIMODeviceIndex();
|
||||
const PluginInterface::SamplingDevice *samplingDevice = DeviceEnumerator::instance()->getMIMOSamplingDevice(testMIMODeviceIndex);
|
||||
samplingDevice = DeviceEnumerator::instance()->getMIMOSamplingDevice(testMIMODeviceIndex);
|
||||
deviceSet->m_deviceAPI->setSamplingDeviceSequence(samplingDevice->sequence);
|
||||
deviceSet->m_deviceAPI->setDeviceNbItems(samplingDevice->deviceNbItems);
|
||||
deviceSet->m_deviceAPI->setDeviceItemIndex(samplingDevice->deviceItemIndex);
|
||||
@ -679,7 +654,7 @@ void MainServer::deleteChannel(int deviceSetIndex, int channelIndex)
|
||||
void MainServer::addFeatureSet()
|
||||
{
|
||||
m_mainCore->appendFeatureSet();
|
||||
emit m_mainCore->featureSetAdded(m_mainCore->getFeatureeSets().size() - 1);
|
||||
emit m_mainCore->featureSetAdded((int) (m_mainCore->getFeatureeSets().size() - 1));
|
||||
}
|
||||
|
||||
void MainServer::removeFeatureSet(unsigned int featureSetIndex)
|
||||
|
Loading…
Reference in New Issue
Block a user