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.
filesource.cpp
Go to the documentation of this file.
1 // Copyright (C) 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 "filesource.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 
28 #include <QDebug>
29 #include <QNetworkAccessManager>
30 #include <QNetworkReply>
31 #include <QBuffer>
32 
33 #include "SWGChannelSettings.h"
34 #include "SWGChannelReport.h"
35 #include "SWGFileSourceReport.h"
36 
37 #include "device/deviceapi.h"
38 #include "dsp/dspcommands.h"
39 #include "dsp/devicesamplesink.h"
40 #include "dsp/upchannelizer.h"
43 #include "dsp/filerecord.h"
44 #include "util/db.h"
45 
58 
59 const QString FileSource::m_channelIdURI = "sdrangel.channeltx.filesource";
60 const QString FileSource::m_channelId ="FileSource";
61 
63  ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
64  m_deviceAPI(deviceAPI),
65  m_fileName("..."),
66  m_sampleSize(0),
67  m_centerFrequency(0),
68  m_frequencyOffset(0),
69  m_fileSampleRate(0),
70  m_samplesCount(0),
71  m_sampleRate(0),
72  m_deviceSampleRate(0),
73  m_recordLength(0),
74  m_startingTimeStamp(0),
75  m_running(false)
76 {
77  setObjectName(m_channelId);
78 
79  m_channelizer = new UpChannelizer(this);
83 
84  m_networkManager = new QNetworkAccessManager();
85  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
86 
87  m_linearGain = 1.0f;
88  m_magsq = 0.0f;
89  m_magsqSum = 0.0f;
90  m_magsqPeak = 0.0f;
91  m_magsqCount = 0;
92 }
93 
95 {
96  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
97  delete m_networkManager;
100  delete m_threadedChannelizer;
101  delete m_channelizer;
102 }
103 
105 {
106  Real re;
107  Real im;
108 
109  struct Sample16
110  {
111  int16_t real;
112  int16_t imag;
113  };
114 
115  struct Sample24
116  {
117  int32_t real;
118  int32_t imag;
119  };
120 
121  if (!m_running)
122  {
123  re = 0;
124  im = 0;
125  }
126  else if (m_sampleSize == 16)
127  {
128  Sample16 sample16;
129  m_ifstream.read(reinterpret_cast<char*>(&sample16), sizeof(Sample16));
130 
131  if (m_ifstream.eof()) {
132  handleEOF();
133  } else {
134  m_samplesCount++;
135  }
136 
137  // scale to +/-1.0
138  re = (sample16.real * m_linearGain) / 32760.0f;
139  im = (sample16.imag * m_linearGain) / 32760.0f;
140  }
141  else if (m_sampleSize == 24)
142  {
143  Sample24 sample24;
144  m_ifstream.read(reinterpret_cast<char*>(&sample24), sizeof(Sample24));
145 
146  if (m_ifstream.eof()) {
147  handleEOF();
148  } else {
149  m_samplesCount++;
150  }
151 
152  // scale to +/-1.0
153  re = (sample24.real * m_linearGain) / 8388608.0f;
154  im = (sample24.imag * m_linearGain) / 8388608.0f;
155  }
156  else
157  {
158  re = 0;
159  im = 0;
160  }
161 
162 
163  if (SDR_TX_SAMP_SZ == 16)
164  {
165  sample.setReal(re * 32768.0f);
166  sample.setImag(im * 32768.0f);
167  }
168  else if (SDR_TX_SAMP_SZ == 24)
169  {
170  sample.setReal(re * 8388608.0f);
171  sample.setImag(im * 8388608.0f);
172  }
173  else
174  {
175  sample.setReal(0);
176  sample.setImag(0);
177  }
178 
179  Real magsq = re*re + im*im;
180  m_movingAverage(magsq);
182  m_magsqSum += magsq;
183 
184  if (magsq > m_magsqPeak) {
185  m_magsqPeak = magsq;
186  }
187 
188  m_magsqCount++;
189 }
190 
191 void FileSource::pullAudio(int nbSamples)
192 {
193  (void) nbSamples;
194 }
195 
197 {
198  qDebug("FileSource::start");
199  m_running = true;
200 
201  if (getMessageQueueToGUI())
202  {
204  getMessageQueueToGUI()->push(report);
205  }
206 }
207 
209 {
210  qDebug("FileSource::stop");
211  m_running = false;
212 
213  if (getMessageQueueToGUI())
214  {
216  getMessageQueueToGUI()->push(report);
217  }
218 }
219 
221 {
223  {
225  int sampleRate = notif.getSampleRate();
226 
227  qDebug() << "FileSource::handleMessage: MsgChannelizerNotification:"
228  << " channelSampleRate: " << sampleRate
229  << " offsetFrequency: " << notif.getFrequencyOffset();
230 
231  if (sampleRate > 0) {
232  setSampleRate(sampleRate);
233  }
234 
235  return true;
236  }
237  else if (DSPSignalNotification::match(cmd))
238  {
240 
241  qDebug() << "FileSource::handleMessage: DSPSignalNotification:"
242  << " inputSampleRate: " << notif.getSampleRate()
243  << " centerFrequency: " << notif.getCenterFrequency();
244 
247  calculateFrequencyOffset(); // This is when device sample rate changes
248 
249  // Redo the channelizer stuff with the new sample rate to re-synchronize everything
253 
254  if (m_guiMessageQueue)
255  {
257  m_guiMessageQueue->push(msg);
258  }
259 
260  return true;
261  }
262  else if (MsgConfigureFileSource::match(cmd))
263  {
265  qDebug() << "FileSource::handleMessage: MsgConfigureFileSource";
266  applySettings(cfg.getSettings(), cfg.getForce());
267  return true;
268  }
269  else if (MsgConfigureChannelizer::match(cmd))
270  {
274 
275  qDebug() << "FileSource::handleMessage: MsgConfigureChannelizer:"
276  << " log2Interp: " << m_settings.m_log2Interp
277  << " filterChainHash: " << m_settings.m_filterChainHash;
278 
282 
283  calculateFrequencyOffset(); // This is when decimation or filter chain changes
284 
285  return true;
286  }
287  else if (MsgConfigureFileSourceName::match(cmd))
288  {
290  m_fileName = conf.getFileName();
291  openFileStream();
292  return true;
293  }
294  else if (MsgConfigureFileSourceWork::match(cmd))
295  {
297 
298  if (conf.isWorking()) {
299  start();
300  } else {
301  stop();
302  }
303 
304  return true;
305  }
306  else if (MsgConfigureFileSourceSeek::match(cmd))
307  {
309  int seekMillis = conf.getMillis();
310  seekFileStream(seekMillis);
311 
312  return true;
313  }
315  {
317 
318  if (getMessageQueueToGUI())
319  {
321  getMessageQueueToGUI()->push(report);
322  }
323 
324  return true;
325  }
326  else
327  {
328  return false;
329  }
330 }
331 
332 QByteArray FileSource::serialize() const
333 {
334  return m_settings.serialize();
335 }
336 
337 bool FileSource::deserialize(const QByteArray& data)
338 {
339  (void) data;
340  if (m_settings.deserialize(data))
341  {
344  return true;
345  }
346  else
347  {
351  return false;
352  }
353 }
354 
356 {
357  //stop();
358 
359  if (m_ifstream.is_open()) {
360  m_ifstream.close();
361  }
362 
363 #ifdef Q_OS_WIN
364  m_ifstream.open(m_fileName.toStdWString().c_str(), std::ios::binary | std::ios::ate);
365 #else
366  m_ifstream.open(m_fileName.toStdString().c_str(), std::ios::binary | std::ios::ate);
367 #endif
368  quint64 fileSize = m_ifstream.tellg();
369  m_samplesCount = 0;
370 
371  if (fileSize > sizeof(FileRecord::Header))
372  {
373  FileRecord::Header header;
374  m_ifstream.seekg(0,std::ios_base::beg);
375  bool crcOK = FileRecord::readHeader(m_ifstream, header);
376  m_fileSampleRate = header.sampleRate;
379  m_sampleSize = header.sampleSize;
380  QString crcHex = QString("%1").arg(header.crc32 , 0, 16);
381 
382  if (crcOK)
383  {
384  qDebug("FileSource::openFileStream: CRC32 OK for header: %s", qPrintable(crcHex));
385  m_recordLength = (fileSize - sizeof(FileRecord::Header)) / ((m_sampleSize == 24 ? 8 : 4) * m_fileSampleRate);
386  }
387  else
388  {
389  qCritical("FileSource::openFileStream: bad CRC32 for header: %s", qPrintable(crcHex));
390  m_recordLength = 0;
391  }
392 
393  if (getMessageQueueToGUI()) {
395  getMessageQueueToGUI()->push(report);
396  }
397  }
398  else
399  {
400  m_recordLength = 0;
401  }
402 
403  qDebug() << "FileSource::openFileStream: " << m_fileName.toStdString().c_str()
404  << " fileSize: " << fileSize << " bytes"
405  << " length: " << m_recordLength << " seconds"
406  << " sample rate: " << m_fileSampleRate << " S/s"
407  << " center frequency: " << m_centerFrequency << " Hz"
408  << " sample size: " << m_sampleSize << " bits"
409  << " starting TS: " << m_startingTimeStamp << "s";
410 
411  if (getMessageQueueToGUI()) {
413  m_sampleSize,
415  m_startingTimeStamp,
416  m_recordLength); // file stream data
417  getMessageQueueToGUI()->push(report);
418  }
419 
420  if (m_recordLength == 0) {
421  m_ifstream.close();
422  }
423 }
424 
425 void FileSource::seekFileStream(int seekMillis)
426 {
427  QMutexLocker mutexLocker(&m_mutex);
428 
429  if ((m_ifstream.is_open()) && !m_running)
430  {
431  quint64 seekPoint = ((m_recordLength * seekMillis) / 1000) * m_fileSampleRate;
432  m_samplesCount = seekPoint;
433  seekPoint *= (m_sampleSize == 24 ? 8 : 4); // + sizeof(FileSink::Header)
434  m_ifstream.clear();
435  m_ifstream.seekg(seekPoint + sizeof(FileRecord::Header), std::ios::beg);
436  }
437 }
438 
440 {
441  if (getMessageQueueToGUI())
442  {
444  getMessageQueueToGUI()->push(report);
445  }
446 
447  if (m_settings.m_loop)
448  {
449  stop();
450  seekFileStream(0);
451  start();
452  }
453  else
454  {
455  stop();
456 
457  if (getMessageQueueToGUI())
458  {
459  MsgPlayPause *report = MsgPlayPause::create(false);
460  getMessageQueueToGUI()->push(report);
461  }
462  }
463 }
464 
465 void FileSource::applySettings(const FileSourceSettings& settings, bool force)
466 {
467  qDebug() << "FileSource::applySettings:"
468  << " force: " << force;
469 
470  QList<QString> reverseAPIKeys;
471 
472  if ((m_settings.m_loop != settings.m_loop) || force) {
473  reverseAPIKeys.append("loop");
474  }
475  if ((m_settings.m_fileName != settings.m_fileName) || force) {
476  reverseAPIKeys.append("fileName");
477  }
478 
479  if ((m_settings.m_gainDB != settings.m_gainDB) || force)
480  {
482  reverseAPIKeys.append("gainDB");
483  }
484 
485  if (settings.m_useReverseAPI)
486  {
487  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
492  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
493  }
494 
495  m_settings = settings;
496 }
497 
499 {
500  unsigned int s = 1;
501 
502  for (unsigned int i = 0; i < settings.m_log2Interp; i++) {
503  s *= 3;
504  }
505 
506  settings.m_filterChainHash = settings.m_filterChainHash >= s ? s-1 : settings.m_filterChainHash;
507 }
508 
510 {
512  m_frequencyOffset = m_deviceSampleRate * shiftFactor;
513 }
514 
517  QString& errorMessage)
518 {
519  (void) errorMessage;
521  response.getFileSourceSettings()->init();
523  return 200;
524 }
525 
527  bool force,
528  const QStringList& channelSettingsKeys,
530  QString& errorMessage)
531 {
532  (void) errorMessage;
533  FileSourceSettings settings = m_settings;
534 
535  if (channelSettingsKeys.contains("log2Interp")) {
536  settings.m_log2Interp = response.getFileSourceSettings()->getLog2Interp();
537  }
538 
539  if (channelSettingsKeys.contains("filterChainHash"))
540  {
542  validateFilterChainHash(settings);
543  }
544 
545  if (channelSettingsKeys.contains("rgbColor")) {
546  settings.m_rgbColor = response.getFileSourceSettings()->getRgbColor();
547  }
548  if (channelSettingsKeys.contains("title")) {
549  settings.m_title = *response.getFileSourceSettings()->getTitle();
550  }
551  if (channelSettingsKeys.contains("gainDB")) {
552  settings.m_gainDB = response.getFileSourceSettings()->getGainDb();
553  }
554  if (channelSettingsKeys.contains("useReverseAPI")) {
555  settings.m_useReverseAPI = response.getFileSourceSettings()->getUseReverseApi() != 0;
556  }
557  if (channelSettingsKeys.contains("reverseAPIAddress")) {
559  }
560  if (channelSettingsKeys.contains("reverseAPIPort")) {
562  }
563  if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
565  }
566  if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
568  }
569 
572 
573  qDebug("FileSource::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
574  if (m_guiMessageQueue) // forward to GUI if any
575  {
576  MsgConfigureFileSource *msgToGUI = MsgConfigureFileSource::create(settings, force);
577  m_guiMessageQueue->push(msgToGUI);
578  }
579 
580  webapiFormatChannelSettings(response, settings);
581 
582  return 200;
583 }
584 
587  QString& errorMessage)
588 {
589  (void) errorMessage;
591  response.getFileSourceReport()->init();
592  webapiFormatChannelReport(response);
593  return 200;
594 }
595 
597 {
598  response.getFileSourceSettings()->setLog2Interp(settings.m_log2Interp);
600  response.getFileSourceSettings()->setGainDb(settings.m_gainDB);
601  response.getFileSourceSettings()->setRgbColor(settings.m_rgbColor);
602 
603  if (response.getFileSourceSettings()->getTitle()) {
604  *response.getFileSourceSettings()->getTitle() = settings.m_title;
605  } else {
606  response.getFileSourceSettings()->setTitle(new QString(settings.m_title));
607  }
608 
609  response.getFileSourceSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
610 
611  if (response.getFileSourceSettings()->getReverseApiAddress()) {
613  } else {
614  response.getFileSourceSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
615  }
616 
620 }
621 
623 {
624  qint64 t_sec = 0;
625  qint64 t_msec = 0;
626  quint64 samplesCount = getSamplesCount();
627 
628  if (m_fileSampleRate > 0)
629  {
630  t_sec = samplesCount / m_fileSampleRate;
631  t_msec = (samplesCount - (t_sec * m_fileSampleRate)) * 1000 / m_fileSampleRate;
632  }
633 
634  QTime t(0, 0, 0, 0);
635  t = t.addSecs(t_sec);
636  t = t.addMSecs(t_msec);
637  response.getFileSourceReport()->setElapsedTime(new QString(t.toString("HH:mm:ss.zzz")));
638 
639  qint64 startingTimeStampMsec = m_startingTimeStamp * 1000LL;
640  QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec);
641  dt = dt.addSecs(t_sec);
642  dt = dt.addMSecs(t_msec);
643  response.getFileSourceReport()->setAbsoluteTime(new QString(dt.toString("yyyy-MM-dd HH:mm:ss.zzz")));
644 
645  QTime recordLength(0, 0, 0, 0);
646  recordLength = recordLength.addSecs(m_recordLength);
647  response.getFileSourceReport()->setDurationTime(new QString(recordLength.toString("HH:mm:ss")));
648 
649  response.getFileSourceReport()->setFileName(new QString(m_settings.m_fileName));
654 }
655 
656 void FileSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FileSourceSettings& settings, bool force)
657 {
659  swgChannelSettings->setDirection(1); // single source (Tx)
660  swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
661  swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
662  swgChannelSettings->setChannelType(new QString("FileSource"));
664  SWGSDRangel::SWGFileSourceSettings *swgFileSourceSettings = swgChannelSettings->getFileSourceSettings();
665 
666  // transfer data that has been modified. When force is on transfer all data except reverse API data
667 
668  if (channelSettingsKeys.contains("log2Interp") || force) {
669  swgFileSourceSettings->setLog2Interp(settings.m_log2Interp);
670  }
671  if (channelSettingsKeys.contains("filterChainHash") || force) {
672  swgFileSourceSettings->setFilterChainHash(settings.m_filterChainHash);
673  }
674  if (channelSettingsKeys.contains("gainDB") || force) {
675  swgFileSourceSettings->setGainDb(settings.m_gainDB);
676  }
677  if (channelSettingsKeys.contains("rgbColor") || force) {
678  swgFileSourceSettings->setRgbColor(settings.m_rgbColor);
679  }
680  if (channelSettingsKeys.contains("title") || force) {
681  swgFileSourceSettings->setTitle(new QString(settings.m_title));
682  }
683 
684  QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
685  .arg(settings.m_reverseAPIAddress)
686  .arg(settings.m_reverseAPIPort)
687  .arg(settings.m_reverseAPIDeviceIndex)
688  .arg(settings.m_reverseAPIChannelIndex);
689  m_networkRequest.setUrl(QUrl(channelSettingsURL));
690  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
691 
692  QBuffer *buffer=new QBuffer();
693  buffer->open((QBuffer::ReadWrite));
694  buffer->write(swgChannelSettings->asJson().toUtf8());
695  buffer->seek(0);
696 
697  // Always use PATCH to avoid passing reverse API settings
698  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
699 
700  delete swgChannelSettings;
701 }
702 
703 void FileSource::networkManagerFinished(QNetworkReply *reply)
704 {
705  QNetworkReply::NetworkError replyError = reply->error();
706 
707  if (replyError)
708  {
709  qWarning() << "FileSource::networkManagerFinished:"
710  << " error(" << (int) replyError
711  << "): " << replyError
712  << ": " << reply->errorString();
713  return;
714  }
715 
716  QString answer = reply->readAll();
717  answer.chop(1); // remove last \n
718  qDebug("FileSource::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
719 }
void applySettings(const FileSourceSettings &settings, bool force=false)
Definition: filesource.cpp:465
short int16_t
Definition: rtptypes_win.h:43
void setSampleRate(qint32 sample_rate)
quint64 m_startingTimeStamp
Definition: filesource.h:406
void setOriginatorChannelIndex(qint32 originator_channel_index)
void setCenterFrequency(uint64_t centerFrequency)
Definition: filesource.h:351
void setDurationTime(QString *duration_time)
QNetworkAccessManager * m_networkManager
Definition: filesource.h:409
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const FileSourceSettings &settings)
Definition: filesource.cpp:596
bool deserialize(const QByteArray &data)
static MsgReportHeaderCRC * create(bool ok)
Definition: filesource.h:295
void push(Message *message, bool emitSignal=true)
Push message onto queue.
uint32_t m_sampleRate
Definition: filesource.h:403
void setFileName(QString *file_name)
quint32 m_sampleSize
Definition: filesource.h:398
void removeChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:181
static double dbPower(double magsq, double floor=1e-12)
Definition: db.cpp:22
static MsgReportFileSourceAcquisition * create(bool acquisition)
Definition: filesource.h:196
DeviceAPI * m_deviceAPI
Definition: filesource.h:391
QString m_fileName
Definition: filesource.h:397
SWGFileSourceReport * getFileSourceReport()
SWGFileSourceSettings * getFileSourceSettings()
int getDeviceSetIndex() const
Definition: channelapi.h:89
void setSampleRate(uint32_t sampleRate)
Definition: filesource.h:354
quint64 getSamplesCount() const
Definition: filesource.h:356
void removeChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Remove a channel source (Tx)
Definition: deviceapi.cpp:147
quint64 centerFrequency
Definition: filerecord.h:38
void networkManagerFinished(QNetworkReply *reply)
Definition: filesource.cpp:703
uint32_t m_fileSampleRate
Definition: filesource.h:401
bool m_running
Definition: filesource.h:408
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
virtual QByteArray serialize() const
Definition: filesource.cpp:332
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
Definition: filesource.cpp:585
void calculateFrequencyOffset()
Definition: filesource.cpp:509
UpChannelizer * m_channelizer
Definition: filesource.h:394
void setChannelType(QString *channel_type)
void addChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Add a channel source (Tx)
Definition: deviceapi.cpp:138
void validateFilterChainHash(FileSourceSettings &settings)
Definition: filesource.cpp:498
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
virtual void pull(Sample &sample)
Definition: filesource.cpp:104
std::ifstream m_ifstream
Definition: filesource.h:396
QNetworkRequest m_networkRequest
Definition: filesource.h:410
void set(MessageQueue *messageQueue, unsigned int log2Interp, unsigned int filterChainHash)
void setFileSourceSettings(SWGFileSourceSettings *file_source_settings)
void setFilterChainHash(qint32 filter_chain_hash)
void handleEOF()
Definition: filesource.cpp:439
QByteArray serialize() const
double m_magsq
Definition: filesource.h:413
qint64 getCenterFrequency() const
Definition: dspcommands.h:329
void setFileSampleRate(qint32 file_sample_rate)
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
void setReverseApiPort(qint32 reverse_api_port)
static MsgConfigureFileSource * create(const FileSourceSettings &settings, bool force)
Definition: filesource.h:77
void seekFileStream(int seekMillis)
Definition: filesource.cpp:425
static const QString m_channelId
Definition: filesource.h:378
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
Definition: filesource.cpp:526
static MsgReportFileSourceStreamTiming * create(quint64 samplesCount)
Definition: filesource.h:275
int32_t i
Definition: decimators.h:244
virtual bool deserialize(const QByteArray &data)
Definition: filesource.cpp:337
static MsgPlayPause * create(bool playPause)
Definition: filesource.h:216
static bool match(const Message *message)
Definition: message.cpp:45
void setImag(FixReal v)
Definition: dsptypes.h:59
int int32_t
Definition: rtptypes_win.h:45
void setChannelPowerDb(float channel_power_db)
quint64 m_recordLength
record length in seconds computed from file size
Definition: filesource.h:405
#define SDR_TX_SAMP_SZ
Definition: dsptypes.h:38
QMutex m_mutex
Definition: filesource.h:392
uint16_t m_reverseAPIChannelIndex
double getMagSq() const
Definition: filesource.h:357
virtual void stop()
Definition: filesource.cpp:208
void setFileSourceReport(SWGFileSourceReport *file_source_report)
void setReverseApiAddress(QString *reverse_api_address)
virtual QString asJson() override
uint16_t m_reverseAPIDeviceIndex
double m_magsqSum
Definition: filesource.h:414
void setElapsedTime(QString *elapsed_time)
int64_t m_frequencyOffset
Definition: filesource.h:400
ThreadedBasebandSampleSource * m_threadedChannelizer
Definition: filesource.h:393
void setReal(FixReal v)
Definition: dsptypes.h:58
void setAbsoluteTime(QString *absolute_time)
quint32 sampleRate
Definition: filerecord.h:37
void setUseReverseApi(qint32 use_reverse_api)
quint64 m_centerFrequency
Definition: filesource.h:399
MessageQueue * getMessageQueueToGUI()
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
Definition: filesource.cpp:220
int getSampleRate() const
Definition: dspcommands.h:328
const FileSourceSettings & getSettings() const
Definition: filesource.h:74
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
quint32 sampleSize
Definition: filerecord.h:40
const QString & getFileName() const
Definition: filesource.h:117
void openFileStream()
Definition: filesource.cpp:355
virtual void pullAudio(int nbSamples)
Definition: filesource.cpp:191
static MsgSampleRateNotification * create(int sampleRate)
Definition: filesource.h:97
FileSourceSettings m_settings
Definition: filesource.h:395
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void addChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:174
virtual void start()
Definition: filesource.cpp:196
uint32_t m_deviceSampleRate
Definition: filesource.h:404
double m_linearGain
Definition: filesource.h:412
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
Definition: filesource.cpp:515
int m_magsqCount
Definition: filesource.h:416
int getIndexInDeviceSet() const
Definition: channelapi.h:87
static bool readHeader(std::ifstream &samplefile, Header &header)
returns true if CRC checksum is correct else false
Definition: filerecord.cpp:168
static MsgReportFileSourceStreamData * create(int sampleRate, quint32 sampleSize, quint64 centerFrequency, quint64 startingTimeStamp, quint64 recordLength)
Definition: filesource.h:239
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
quint64 startTimeStamp
Definition: filerecord.h:39
double asDouble() const
Definition: movingaverage.h:57
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const FileSourceSettings &settings, bool force)
Definition: filesource.cpp:656
static double getShiftFactor(unsigned int log2, unsigned int chainHash)
float Real
Definition: dsptypes.h:42
MovingAverageUtil< Real, double, 16 > m_movingAverage
Definition: filesource.h:418
static double powerFromdB(double powerdB)
Definition: db.cpp:36
static const QString m_channelIdURI
Definition: filesource.h:377
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
Definition: filesource.cpp:622
FileSource(DeviceAPI *deviceAPI)
Definition: filesource.cpp:62
double m_magsqPeak
Definition: filesource.h:415
void setFileSampleSize(qint32 file_sample_size)
quint64 m_samplesCount
Definition: filesource.h:402