SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
remotesource.cpp
Go to the documentation of this file.
1 // Copyright (C) 2018-2019 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include "remotesource.h"
19 
20 #if (defined _WIN32_) || (defined _MSC_VER)
21 #include "windows_time.h"
22 #include <stdint.h>
23 #else
24 #include <sys/time.h>
25 #include <unistd.h>
26 #endif
27 #include <boost/crc.hpp>
28 #include <boost/cstdint.hpp>
29 
30 #include <QDebug>
31 #include <QNetworkAccessManager>
32 #include <QNetworkReply>
33 #include <QBuffer>
34 
35 #include "SWGChannelSettings.h"
36 #include "SWGChannelReport.h"
37 #include "SWGRemoteSourceReport.h"
38 
39 #include "dsp/devicesamplesink.h"
40 #include "device/deviceapi.h"
41 #include "dsp/upchannelizer.h"
43 
44 #include "remotesourcethread.h"
45 
50 
51 const QString RemoteSource::m_channelIdURI = "sdrangel.channeltx.remotesource";
52 const QString RemoteSource::m_channelId ="RemoteSource";
53 
55  ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
56  m_deviceAPI(deviceAPI),
57  m_sourceThread(0),
58  m_running(false),
59  m_nbCorrectableErrors(0),
60  m_nbUncorrectableErrors(0)
61 {
62  setObjectName(m_channelId);
63 
64  connect(&m_dataQueue, SIGNAL(dataBlockEnqueued()), this, SLOT(handleData()), Qt::QueuedConnection);
65  m_cm256p = m_cm256.isInitialized() ? &m_cm256 : 0;
67 
68  m_channelizer = new UpChannelizer(this);
72 
73  m_networkManager = new QNetworkAccessManager();
74  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
75 }
76 
78 {
79  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
80  delete m_networkManager;
83  delete m_threadedChannelizer;
84  delete m_channelizer;
85 }
86 
88 {
89  m_dataReadQueue.readSample(sample, true); // true is scale for Tx
90 }
91 
92 void RemoteSource::pullAudio(int nbSamples)
93 {
94  (void) nbSamples;
95 }
96 
98 {
99  qDebug("RemoteSource::start");
100 
101  if (m_running) {
102  stop();
103  }
104 
106  m_sourceThread->startStop(true);
108  m_running = true;
109 }
110 
112 {
113  qDebug("RemoteSource::stop");
114 
115  if (m_sourceThread != 0)
116  {
117  m_sourceThread->startStop(false);
118  m_sourceThread->deleteLater();
119  m_sourceThread = 0;
120  }
121 
122  m_running = false;
123 }
124 
125 void RemoteSource::setDataLink(const QString& dataAddress, uint16_t dataPort)
126 {
127  RemoteSourceSettings settings = m_settings;
128  settings.m_dataAddress = dataAddress;
129  settings.m_dataPort = dataPort;
130 
133 }
134 
136 {
138  {
140  qDebug() << "RemoteSource::handleMessage: MsgChannelizerNotification:"
141  << " basebandSampleRate: " << notif.getBasebandSampleRate()
142  << " outputSampleRate: " << notif.getSampleRate()
143  << " inputFrequencyOffset: " << notif.getFrequencyOffset();
144 
145  if (m_guiMessageQueue)
146  {
148  m_guiMessageQueue->push(msg);
149  }
150 
151  return true;
152  }
153  else if (MsgConfigureRemoteSource::match(cmd))
154  {
156  qDebug() << "MsgConfigureRemoteSource::handleMessage: MsgConfigureRemoteSource";
157  applySettings(cfg.getSettings(), cfg.getForce());
158 
159  return true;
160  }
161  else if (MsgQueryStreamData::match(cmd))
162  {
163  if (m_guiMessageQueue)
164  {
165  struct timeval tv;
166  gettimeofday(&tv, 0);
167 
169  tv.tv_sec,
170  tv.tv_usec,
180  m_guiMessageQueue->push(msg);
181  }
182 
183  return true;
184  }
185  return false;
186 }
187 
188 QByteArray RemoteSource::serialize() const
189 {
190  return m_settings.serialize();
191 }
192 
193 bool RemoteSource::deserialize(const QByteArray& data)
194 {
195  (void) data;
196  if (m_settings.deserialize(data))
197  {
200  return true;
201  }
202  else
203  {
207  return false;
208  }
209 }
210 
211 void RemoteSource::applySettings(const RemoteSourceSettings& settings, bool force)
212 {
213  qDebug() << "RemoteSource::applySettings:"
214  << " m_dataAddress: " << settings.m_dataAddress
215  << " m_dataPort: " << settings.m_dataPort
216  << " force: " << force;
217 
218  bool change = false;
219  QList<QString> reverseAPIKeys;
220 
221  if ((m_settings.m_dataAddress != settings.m_dataAddress) || force)
222  {
223  reverseAPIKeys.append("dataAddress");
224  change = true;
225  }
226 
227  if ((m_settings.m_dataPort != settings.m_dataPort) || force)
228  {
229  reverseAPIKeys.append("dataPort");
230  change = true;
231  }
232 
233  if (change && m_sourceThread)
234  {
235  reverseAPIKeys.append("sourceThread");
236  m_sourceThread->dataBind(settings.m_dataAddress, settings.m_dataPort);
237  }
238 
239  if (settings.m_useReverseAPI)
240  {
241  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
246  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
247  }
248 
249  m_settings = settings;
250 }
251 
253 {
254  (void) dataBlock;
255  if (dataBlock->m_rxControlBlock.m_blockCount < RemoteNbOrginalBlocks)
256  {
257  qWarning("RemoteSource::handleDataBlock: incomplete data block: not processing");
258  }
259  else
260  {
261  int blockCount = 0;
262 
263  for (int blockIndex = 0; blockIndex < 256; blockIndex++)
264  {
265  if ((blockIndex == 0) && (dataBlock->m_rxControlBlock.m_metaRetrieved))
266  {
267  m_cm256DescriptorBlocks[blockCount].Index = 0;
268  m_cm256DescriptorBlocks[blockCount].Block = (void *) &(dataBlock->m_superBlocks[0].m_protectedBlock);
269  blockCount++;
270  }
271  else if (dataBlock->m_superBlocks[blockIndex].m_header.m_blockIndex != 0)
272  {
273  m_cm256DescriptorBlocks[blockCount].Index = dataBlock->m_superBlocks[blockIndex].m_header.m_blockIndex;
274  m_cm256DescriptorBlocks[blockCount].Block = (void *) &(dataBlock->m_superBlocks[blockIndex].m_protectedBlock);
275  blockCount++;
276  }
277  }
278 
279  //qDebug("RemoteSource::handleDataBlock: frame: %u blocks: %d", dataBlock.m_rxControlBlock.m_frameIndex, blockCount);
280 
281  // Need to use the CM256 recovery
282  if (m_cm256p &&(dataBlock->m_rxControlBlock.m_originalCount < RemoteNbOrginalBlocks))
283  {
284  qDebug("RemoteSource::handleDataBlock: %d recovery blocks", dataBlock->m_rxControlBlock.m_recoveryCount);
285  CM256::cm256_encoder_params paramsCM256;
286  paramsCM256.BlockBytes = sizeof(RemoteProtectedBlock); // never changes
287  paramsCM256.OriginalCount = RemoteNbOrginalBlocks; // never changes
288 
289  if (m_currentMeta.m_tv_sec == 0) {
290  paramsCM256.RecoveryCount = dataBlock->m_rxControlBlock.m_recoveryCount;
291  } else {
292  paramsCM256.RecoveryCount = m_currentMeta.m_nbFECBlocks;
293  }
294 
295  // update counters
296  if (dataBlock->m_rxControlBlock.m_originalCount < RemoteNbOrginalBlocks - paramsCM256.RecoveryCount) {
297  m_nbUncorrectableErrors += RemoteNbOrginalBlocks - paramsCM256.RecoveryCount - dataBlock->m_rxControlBlock.m_originalCount;
298  } else {
300  }
301 
302  if (m_cm256.cm256_decode(paramsCM256, m_cm256DescriptorBlocks)) // CM256 decode
303  {
304  qWarning() << "RemoteSource::handleDataBlock: decode CM256 error:"
305  << " m_originalCount: " << dataBlock->m_rxControlBlock.m_originalCount
306  << " m_recoveryCount: " << dataBlock->m_rxControlBlock.m_recoveryCount;
307  }
308  else
309  {
310  for (int ir = 0; ir < dataBlock->m_rxControlBlock.m_recoveryCount; ir++) // restore missing blocks
311  {
312  int recoveryIndex = RemoteNbOrginalBlocks - dataBlock->m_rxControlBlock.m_recoveryCount + ir;
313  int blockIndex = m_cm256DescriptorBlocks[recoveryIndex].Index;
314  RemoteProtectedBlock *recoveredBlock =
315  (RemoteProtectedBlock *) m_cm256DescriptorBlocks[recoveryIndex].Block;
316  memcpy((void *) &(dataBlock->m_superBlocks[blockIndex].m_protectedBlock), recoveredBlock, sizeof(RemoteProtectedBlock));
317  if ((blockIndex == 0) && !dataBlock->m_rxControlBlock.m_metaRetrieved) {
318  dataBlock->m_rxControlBlock.m_metaRetrieved = true;
319  }
320  }
321  }
322  }
323 
324  // Validate block zero and retrieve its data
325  if (dataBlock->m_rxControlBlock.m_metaRetrieved)
326  {
327  RemoteMetaDataFEC *metaData = (RemoteMetaDataFEC *) &(dataBlock->m_superBlocks[0].m_protectedBlock);
328  boost::crc_32_type crc32;
329  crc32.process_bytes(metaData, sizeof(RemoteMetaDataFEC)-4);
330 
331  if (crc32.checksum() == metaData->m_crc32)
332  {
333  if (!(m_currentMeta == *metaData))
334  {
335  printMeta("RemoteSource::handleDataBlock", metaData);
336 
337  if (m_currentMeta.m_sampleRate != metaData->m_sampleRate)
338  {
341  }
342  }
343 
344  m_currentMeta = *metaData;
345  }
346  else
347  {
348  qWarning() << "RemoteSource::handleDataBlock: recovered meta: invalid CRC32";
349  }
350  }
351 
352  m_dataReadQueue.push(dataBlock); // Push into R/W buffer
353  }
354 }
355 
357 {
358  RemoteDataBlock* dataBlock;
359 
360  while (m_running && ((dataBlock = m_dataQueue.pop()) != 0)) {
361  handleDataBlock(dataBlock);
362  }
363 }
364 
365 void RemoteSource::printMeta(const QString& header, RemoteMetaDataFEC *metaData)
366 {
367  qDebug().noquote() << header << ": "
368  << "|" << metaData->m_centerFrequency
369  << ":" << metaData->m_sampleRate
370  << ":" << (int) (metaData->m_sampleBytes & 0xF)
371  << ":" << (int) metaData->m_sampleBits
372  << ":" << (int) metaData->m_nbOriginalBlocks
373  << ":" << (int) metaData->m_nbFECBlocks
374  << "|" << metaData->m_tv_sec
375  << ":" << metaData->m_tv_usec
376  << "|";
377 }
378 
380 {
381  // scale for 20 blocks at 48 kS/s. Take next even number.
382  uint32_t maxSize = sampleRate / 2400;
383  maxSize = (maxSize % 2 == 0) ? maxSize : maxSize + 1;
384  qDebug("RemoteSource::calculateDataReadQueueSize: set max queue size to %u blocks", maxSize);
385  return maxSize;
386 }
387 
390  QString& errorMessage)
391 {
392  (void) errorMessage;
394  response.getRemoteSourceSettings()->init();
396  return 200;
397 }
398 
400  bool force,
401  const QStringList& channelSettingsKeys,
403  QString& errorMessage)
404 {
405  (void) errorMessage;
406  RemoteSourceSettings settings = m_settings;
407 
408  if (channelSettingsKeys.contains("dataAddress")) {
409  settings.m_dataAddress = *response.getRemoteSourceSettings()->getDataAddress();
410  }
411  if (channelSettingsKeys.contains("dataPort"))
412  {
413  int dataPort = response.getRemoteSourceSettings()->getDataPort();
414 
415  if ((dataPort < 1024) || (dataPort > 65535)) {
416  settings.m_dataPort = 9090;
417  } else {
418  settings.m_dataPort = dataPort;
419  }
420  }
421  if (channelSettingsKeys.contains("rgbColor")) {
422  settings.m_rgbColor = response.getRemoteSourceSettings()->getRgbColor();
423  }
424  if (channelSettingsKeys.contains("title")) {
425  settings.m_title = *response.getRemoteSourceSettings()->getTitle();
426  }
427  if (channelSettingsKeys.contains("useReverseAPI")) {
428  settings.m_useReverseAPI = response.getRemoteSourceSettings()->getUseReverseApi() != 0;
429  }
430  if (channelSettingsKeys.contains("reverseAPIAddress")) {
432  }
433  if (channelSettingsKeys.contains("reverseAPIPort")) {
435  }
436  if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
438  }
439  if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
441  }
442 
445 
446  qDebug("RemoteSource::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
447  if (m_guiMessageQueue) // forward to GUI if any
448  {
449  MsgConfigureRemoteSource *msgToGUI = MsgConfigureRemoteSource::create(settings, force);
450  m_guiMessageQueue->push(msgToGUI);
451  }
452 
453  webapiFormatChannelSettings(response, settings);
454 
455  return 200;
456 }
457 
460  QString& errorMessage)
461 {
462  (void) errorMessage;
464  response.getRemoteSourceReport()->init();
465  webapiFormatChannelReport(response);
466  return 200;
467 }
468 
470 {
471  if (response.getRemoteSourceSettings()->getDataAddress()) {
472  *response.getRemoteSourceSettings()->getDataAddress() = settings.m_dataAddress;
473  } else {
474  response.getRemoteSourceSettings()->setDataAddress(new QString(settings.m_dataAddress));
475  }
476 
477  response.getRemoteSourceSettings()->setDataPort(settings.m_dataPort);
478  response.getRemoteSourceSettings()->setRgbColor(settings.m_rgbColor);
479 
480  if (response.getRemoteSourceSettings()->getTitle()) {
481  *response.getRemoteSourceSettings()->getTitle() = settings.m_title;
482  } else {
483  response.getRemoteSourceSettings()->setTitle(new QString(settings.m_title));
484  }
485 
486  response.getRemoteSourceSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
487 
488  if (response.getRemoteSourceSettings()->getReverseApiAddress()) {
490  } else {
491  response.getRemoteSourceSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
492  }
493 
497 }
498 
500 {
501  struct timeval tv;
502  gettimeofday(&tv, 0);
503 
504  response.getRemoteSourceReport()->setTvSec(tv.tv_sec);
505  response.getRemoteSourceReport()->setTvUSec(tv.tv_usec);
517 }
518 
519 void RemoteSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const RemoteSourceSettings& settings, bool force)
520 {
522  swgChannelSettings->setDirection(1); // single source (Tx)
523  swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
524  swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
525  swgChannelSettings->setChannelType(new QString("RemoteSource"));
527  SWGSDRangel::SWGRemoteSourceSettings *swgRemoteSourceSettings = swgChannelSettings->getRemoteSourceSettings();
528 
529  // transfer data that has been modified. When force is on transfer all data except reverse API data
530 
531  if (channelSettingsKeys.contains("dataAddress") || force) {
532  swgRemoteSourceSettings->setDataAddress(new QString(settings.m_dataAddress));
533  }
534  if (channelSettingsKeys.contains("dataPort") || force) {
535  swgRemoteSourceSettings->setDataPort(settings.m_dataPort);
536  }
537  if (channelSettingsKeys.contains("rgbColor") || force) {
538  swgRemoteSourceSettings->setRgbColor(settings.m_rgbColor);
539  }
540  if (channelSettingsKeys.contains("title") || force) {
541  swgRemoteSourceSettings->setTitle(new QString(settings.m_title));
542  }
543 
544  QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
545  .arg(settings.m_reverseAPIAddress)
546  .arg(settings.m_reverseAPIPort)
547  .arg(settings.m_reverseAPIDeviceIndex)
548  .arg(settings.m_reverseAPIChannelIndex);
549  m_networkRequest.setUrl(QUrl(channelSettingsURL));
550  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
551 
552  QBuffer *buffer=new QBuffer();
553  buffer->open((QBuffer::ReadWrite));
554  buffer->write(swgChannelSettings->asJson().toUtf8());
555  buffer->seek(0);
556 
557  // Always use PATCH to avoid passing reverse API settings
558  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
559 
560  delete swgChannelSettings;
561 }
562 
563 void RemoteSource::networkManagerFinished(QNetworkReply *reply)
564 {
565  QNetworkReply::NetworkError replyError = reply->error();
566 
567  if (replyError)
568  {
569  qWarning() << "RemoteSource::networkManagerFinished:"
570  << " error(" << (int) replyError
571  << "): " << replyError
572  << ": " << reply->errorString();
573  return;
574  }
575 
576  QString answer = reply->readAll();
577  answer.chop(1); // remove last \n
578  qDebug("RemoteSource::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
579 }
void setOriginatorChannelIndex(qint32 originator_channel_index)
RemoteSourceThread * m_sourceThread
Definition: remotesource.h:236
void setDeviceCenterFreq(qint32 device_center_freq)
uint32_t m_sampleRate
12 sample rate in Hz
virtual bool deserialize(const QByteArray &data)
void setReverseApiPort(qint32 reverse_api_port)
QNetworkAccessManager * m_networkManager
Definition: remotesource.h:251
RemoteDataBlock * pop()
Pop message from queue.
void setSamplesCount(qint32 samples_count)
uint32_t size() const
Returns queue size (max length)
uint32_t m_nbCorrectableErrors
count of correctable errors in number of blocks
Definition: remotesource.h:248
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void removeChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:181
RemoteSuperBlock * m_superBlocks
RemoteDataReadQueue m_dataReadQueue
Definition: remotesource.h:246
void setCorrectableErrorsCount(qint32 correctable_errors_count)
void setRemoteSourceReport(SWGRemoteSourceReport *remote_source_report)
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const RemoteSourceSettings &settings, bool force)
int getDeviceSetIndex() const
Definition: channelapi.h:89
void setUseReverseApi(qint32 use_reverse_api)
bool deserialize(const QByteArray &data)
virtual void start()
virtual QByteArray serialize() const
void removeChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Remove a channel source (Tx)
Definition: deviceapi.cpp:147
void handleDataBlock(RemoteDataBlock *dataBlock)
const RemoteSourceSettings & getSettings() const
Definition: remotesource.h:52
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
RemoteProtectedBlock m_protectedBlock
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const RemoteSourceSettings &settings)
int m_recoveryCount
number of recovery blocks received
void setDataLink(const QString &dataAddress, uint16_t dataPort)
void setChannelType(QString *channel_type)
void addChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Add a channel source (Tx)
Definition: deviceapi.cpp:138
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
void applySettings(const RemoteSourceSettings &settings, bool force=false)
DeviceSampleSink * getSampleSink()
Return pointer to the device sample sink (single Tx) or nullptr.
Definition: deviceapi.cpp:222
void readSample(Sample &s, bool scaleForTx=false)
Read sample from queue possibly scaling to Tx size.
void setReverseApiAddress(QString *reverse_api_address)
unsigned int uint32_t
Definition: rtptypes_win.h:46
void setRemoteSourceSettings(SWGRemoteSourceSettings *remote_source_settings)
uint32_t readSampleCount() const
Returns the absolute number of samples read.
virtual void pullAudio(int nbSamples)
uint8_t m_sampleBytes
13 4 LSB: number of bytes per sample (2 or 4)
virtual quint64 getCenterFrequency() const =0
Center frequency exposed by the sink.
DeviceAPI * m_deviceAPI
Definition: remotesource.h:232
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
RemoteRxControlBlock m_rxControlBlock
int m_originalCount
number of original blocks received
void setSize(uint32_t size)
Sets the queue size (max length)
unsigned short uint16_t
Definition: rtptypes_win.h:44
uint16_t m_dataPort
Listening data port.
void setUncorrectableErrorsCount(qint32 uncorrectable_errors_count)
static MsgConfigureRemoteSource * create(const RemoteSourceSettings &settings, bool force)
Definition: remotesource.h:55
uint32_t m_crc32
28 CRC32 of the above
uint8_t m_nbFECBlocks
16 number of blocks carrying FEC
uint32_t m_tv_usec
24 microseconds of timestamp at start time of super-frame processing
uint8_t m_blockIndex
ThreadedBasebandSampleSource * m_threadedChannelizer
Definition: remotesource.h:233
RemoteDataQueue m_dataQueue
Definition: remotesource.h:235
SWGRemoteSourceReport * getRemoteSourceReport()
uint8_t m_sampleBits
14 number of effective bits per sample (deprecated)
static bool match(const Message *message)
Definition: message.cpp:45
CM256 * m_cm256p
Definition: remotesource.h:238
uint32_t m_nbUncorrectableErrors
count of uncorrectable errors in number of blocks
Definition: remotesource.h:249
QString m_dataAddress
Listening (local) data address.
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
uint32_t length() const
Returns queue length.
uint32_t m_tv_sec
20 seconds of timestamp at start time of super-frame processing
QByteArray serialize() const
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
static MsgSampleRateNotification * create(int sampleRate)
Definition: remotesource.h:75
void printMeta(const QString &header, RemoteMetaDataFEC *metaData)
virtual QString asJson() override
CM256::cm256_block m_cm256DescriptorBlocks[2 *RemoteNbOrginalBlocks]
CM256 decoder descriptors (block addresses and block indexes)
Definition: remotesource.h:243
void setNbOriginalBlocks(qint32 nb_original_blocks)
RemoteHeader m_header
void dataBind(const QString &address, uint16_t port)
RemoteSourceSettings m_settings
Definition: remotesource.h:241
void networkManagerFinished(QNetworkReply *reply)
virtual void stop()
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
void setNbFecBlocks(qint32 nb_fec_blocks)
uint8_t m_nbOriginalBlocks
15 number of blocks with original (protected) data
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
static MsgReportStreamData * create(uint32_t tv_sec, uint32_t tv_usec, uint32_t queueSize, uint32_t queueLength, uint32_t readSamplesCount, uint32_t nbCorrectableErrors, uint32_t nbUncorrectableErrors, uint32_t nbOriginalBlocks, uint32_t nbFECBlocks, uint32_t centerFreq, uint32_t sampleRate)
Definition: remotesource.h:117
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
RemoteMetaDataFEC m_currentMeta
Definition: remotesource.h:244
void startStop(bool start)
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
static const QString m_channelIdURI
Definition: remotesource.h:228
void addChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:174
virtual int getSampleRate() const =0
Sample rate exposed by the sink.
uint32_t crc32(const uint8_t *buf, int len)
Definition: crc.h:58
virtual void pull(Sample &sample)
uint64_t m_centerFrequency
8 center frequency in kHz
UpChannelizer * m_channelizer
Definition: remotesource.h:234
int getIndexInDeviceSet() const
Definition: channelapi.h:87
static const QString m_channelId
Definition: remotesource.h:229
void push(RemoteDataBlock *dataBlock)
push block on the queue
void setDeviceSampleRate(qint32 device_sample_rate)
RemoteSource(DeviceAPI *deviceAPI)
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
uint32_t calculateDataReadQueueSize(int sampleRate)
SWGRemoteSourceSettings * getRemoteSourceSettings()
QNetworkRequest m_networkRequest
Definition: remotesource.h:252
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
int m_blockCount
number of blocks received for this frame
bool m_metaRetrieved
true if meta data (block zero) was retrieved
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)