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.
fcdproplusinput.cpp
Go to the documentation of this file.
1 // Copyright (C) 2016-2018 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 <string.h>
19 #include <errno.h>
20 
21 #include <QDebug>
22 #include <QNetworkReply>
23 #include <QBuffer>
24 
25 #include "SWGDeviceSettings.h"
26 #include "SWGDeviceState.h"
27 
28 #include "dsp/dspcommands.h"
29 #include "dsp/dspengine.h"
30 #include "dsp/filerecord.h"
31 #include "device/deviceapi.h"
32 
33 #include "fcdproplusinput.h"
34 #include "fcdproplusthread.h"
35 #include "fcdtraits.h"
36 #include "fcdproplusconst.h"
37 
41 
43  m_deviceAPI(deviceAPI),
44  m_dev(0),
45  m_settings(),
46  m_FCDThread(0),
47  m_deviceDescription(fcd_traits<ProPlus>::displayedName),
48  m_running(false)
49 {
50  m_fcdFIFO.setSize(20*fcd_traits<ProPlus>::convBufSize);
51  openDevice();
52  m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
53  m_deviceAPI->setNbSourceStreams(1);
54  m_deviceAPI->addAncillarySink(m_fileSink);
55  m_networkManager = new QNetworkAccessManager();
56  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
57 }
58 
60 {
61  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
62  delete m_networkManager;
63 
64  if (m_running) {
65  stop();
66  }
67 
69  delete m_fileSink;
70 
71  closeDevice();
72 }
73 
75 {
76  delete this;
77 }
78 
80 {
81  if (m_dev != 0) {
82  closeDevice();
83  }
84 
85  int device = m_deviceAPI->getSamplingDeviceSequence();
86  qDebug() << "FCDProPlusInput::openDevice with device #" << device;
88 
89  if (m_dev == 0)
90  {
91  qCritical("FCDProPlusInput::start: could not open FCD");
92  return false;
93  }
94 
96  {
97  qCritical("FCDProPlusInput::start: could not open FCD audio source");
98  return false;
99  }
100  else
101  {
102  qDebug("FCDProPlusInput::start: FCD audio source opened");
103  }
104 
105  return true;
106 }
107 
109 {
110  applySettings(m_settings, true);
111 }
112 
114 {
115 // QMutexLocker mutexLocker(&m_mutex);
116 
117  if (!m_dev) {
118  return false;
119  }
120 
121  if (m_running) {
122  stop();
123  }
124 
125  qDebug() << "FCDProPlusInput::start";
126 
127  /* Apply settings before streaming to avoid bus contention;
128  * there is very little spare bandwidth on a full speed USB device.
129  * Failure is harmless if no device is found
130  * ... This is rubbish...*/
131 
132  //applySettings(m_settings, true);
133 
134  if (!m_sampleFifo.setSize(96000*4))
135  {
136  qCritical("FCDProPlusInput::start: could not allocate SampleFifo");
137  return false;
138  }
139 
142 
143 // mutexLocker.unlock();
144  applySettings(m_settings, true);
145 
146  qDebug("FCDProPlusInput::started");
147  m_running = true;
148 
149  return true;
150 }
151 
153 {
154  if (m_dev == 0) { // was never open
155  return;
156  }
157 
158  fcdClose(m_dev);
159  m_dev = 0;
160 
161  closeFCDAudio();
162 }
163 
164 bool FCDProPlusInput::openFCDAudio(const char* cardname)
165 {
167  const QList<QAudioDeviceInfo>& audioList = audioDeviceManager->getInputDevices();
168 
169  for (const auto &itAudio : audioList)
170  {
171  if (itAudio.deviceName().contains(QString(cardname)))
172  {
173  int fcdDeviceIndex = audioDeviceManager->getInputDeviceIndex(itAudio.deviceName());
175  int fcdSampleRate = m_fcdAudioInput.getRate();
176  qDebug("FCDProPlusInput::openFCDAudio: %s index %d at %d S/s",
177  itAudio.deviceName().toStdString().c_str(), fcdDeviceIndex, fcdSampleRate);
179  return true;
180  }
181  }
182 
183  qCritical("FCDProPlusInput::openFCDAudio: device with name %s not found", cardname);
184  return false;
185 }
186 
188 {
191 }
192 
194 {
195  QMutexLocker mutexLocker(&m_mutex);
196 
197  if (m_FCDThread)
198  {
200  // wait for thread to quit ?
201  delete m_FCDThread;
202  m_FCDThread = nullptr;
203  }
204 
205  m_running = false;
206 }
207 
208 QByteArray FCDProPlusInput::serialize() const
209 {
210  return m_settings.serialize();
211 }
212 
213 bool FCDProPlusInput::deserialize(const QByteArray& data)
214 {
215  bool success = true;
216 
217  if (!m_settings.deserialize(data))
218  {
220  success = false;
221  }
222 
224  m_inputMessageQueue.push(message);
225 
226  if (m_guiMessageQueue)
227  {
229  m_guiMessageQueue->push(messageToGUI);
230  }
231 
232  return success;
233 }
234 
236 {
237  return m_deviceDescription;
238 }
239 
241 {
243 }
244 
246 {
248 }
249 
250 void FCDProPlusInput::setCenterFrequency(qint64 centerFrequency)
251 {
252  FCDProPlusSettings settings = m_settings;
253  settings.m_centerFrequency = centerFrequency;
254 
255  MsgConfigureFCDProPlus* message = MsgConfigureFCDProPlus::create(settings, false);
256  m_inputMessageQueue.push(message);
257 
258  if (m_guiMessageQueue)
259  {
260  MsgConfigureFCDProPlus* messageToGUI = MsgConfigureFCDProPlus::create(settings, false);
261  m_guiMessageQueue->push(messageToGUI);
262  }
263 }
264 
266 {
267  if(MsgConfigureFCDProPlus::match(message))
268  {
269  qDebug() << "FCDProPlusInput::handleMessage: MsgConfigureFCD";
271  applySettings(conf.getSettings(), conf.getForce());
272  return true;
273  }
274  else if (MsgStartStop::match(message))
275  {
276  MsgStartStop& cmd = (MsgStartStop&) message;
277  qDebug() << "FCDProPlusInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
278 
279  if (cmd.getStartStop())
280  {
282  {
284  }
285  }
286  else
287  {
289  }
290 
293  }
294 
295  return true;
296  }
297  else if (MsgFileRecord::match(message))
298  {
299  MsgFileRecord& conf = (MsgFileRecord&) message;
300  qDebug() << "FCDProPlusInput::handleMessage: MsgFileRecord: " << conf.getStartStop();
301 
302  if (conf.getStartStop())
303  {
304  if (m_settings.m_fileRecordName.size() != 0) {
306  } else {
308  }
309 
311  }
312  else
313  {
315  }
316 
317  return true;
318  }
319  else
320  {
321  return false;
322  }
323 }
324 
325 void FCDProPlusInput::applySettings(const FCDProPlusSettings& settings, bool force)
326 {
327  bool forwardChange = false;
328  QList<QString> reverseAPIKeys;
329 
330  if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency)) {
331  reverseAPIKeys.append("centerFrequency");
332  }
333  if (force || (m_settings.m_transverterMode != settings.m_transverterMode)) {
334  reverseAPIKeys.append("transverterMode");
335  }
337  reverseAPIKeys.append("transverterDeltaFrequency");
338  }
339  if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) {
340  reverseAPIKeys.append("LOppmTenths");
341  }
342 
343  if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency)
344  || (m_settings.m_LOppmTenths != settings.m_LOppmTenths)
345  || (m_settings.m_fcPos != settings.m_fcPos)
346  || (m_settings.m_log2Decim != settings.m_log2Decim)
349  {
350  qint64 deviceCenterFrequency = DeviceSampleSource::calculateDeviceCenterFrequency(
351  settings.m_centerFrequency,
353  settings.m_log2Decim,
356  DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD,
357  settings.m_transverterMode);
358 
359  if (m_dev != 0) {
360  set_center_freq((double) deviceCenterFrequency);
361  }
362 
363  qDebug() << "FCDProPlusInput::applySettings: center freq: " << settings.m_centerFrequency << " Hz"
364  << " device center freq: " << deviceCenterFrequency << " Hz";
365 
366  forwardChange = (m_settings.m_centerFrequency != settings.m_centerFrequency) || force;
367 
369  }
370 
371  if ((m_settings.m_log2Decim != settings.m_log2Decim) || force)
372  {
373  reverseAPIKeys.append("log2Decim");
374  forwardChange = true;
375 
376  if (m_FCDThread != 0)
377  {
379  qDebug() << "FCDProPlusInput::applySettings: set decimation to " << (1<<settings.m_log2Decim);
380  }
381  }
382 
383  if ((m_settings.m_fcPos != settings.m_fcPos) || force)
384  {
385  reverseAPIKeys.append("fcPos");
386 
387  if (m_FCDThread != 0) {
388  m_FCDThread->setFcPos((int) settings.m_fcPos);
389  }
390 
391  qDebug() << "FCDProPlusInput::applySettings: set fc pos (enum) to " << (int) settings.m_fcPos;
392  }
393 
394  if ((m_settings.m_lnaGain != settings.m_lnaGain) || force)
395  {
396  reverseAPIKeys.append("lnaGain");
397 
398  if (m_dev != 0) {
399  set_lna_gain(settings.m_lnaGain);
400  }
401  }
402 
403  if ((m_settings.m_biasT != settings.m_biasT) || force)
404  {
405  reverseAPIKeys.append("biasT");
406 
407  if (m_dev != 0) {
408  set_bias_t(settings.m_biasT);
409  }
410  }
411 
412  if ((m_settings.m_mixGain != settings.m_mixGain) || force)
413  {
414  reverseAPIKeys.append("mixGain");
415 
416  if (m_dev != 0) {
417  set_mixer_gain(settings.m_mixGain);
418  }
419  }
420 
421  if ((m_settings.m_ifGain != settings.m_ifGain) || force)
422  {
423  reverseAPIKeys.append("ifGain");
424 
425  if (m_dev != 0) {
426  set_if_gain(settings.m_ifGain);
427  }
428  }
429 
430  if ((m_settings.m_ifFilterIndex != settings.m_ifFilterIndex) || force)
431  {
432  reverseAPIKeys.append("ifFilterIndex");
433 
434  if (m_dev != 0) {
435  set_if_filter(settings.m_ifFilterIndex);
436  }
437  }
438 
439  if ((m_settings.m_rfFilterIndex != settings.m_rfFilterIndex) || force)
440  {
441  reverseAPIKeys.append("rfFilterIndex");
442 
443  if (m_dev != 0) {
444  set_rf_filter(settings.m_rfFilterIndex);
445  }
446  }
447 
448  if ((m_settings.m_dcBlock != settings.m_dcBlock) || force)
449  {
450  reverseAPIKeys.append("dcBlock");
452  }
453 
454  if ((m_settings.m_iqImbalance != settings.m_iqImbalance) || force)
455  {
456  reverseAPIKeys.append("iqImbalance");
458  }
459 
460  if (settings.m_useReverseAPI)
461  {
462  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
466  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
467  }
468 
469  m_settings = settings;
470 
471  if (forwardChange)
472  {
474  m_fileSink->handleMessage(*notif); // forward to file sink
476  }
477 }
478 
480 {
481  freq += freq*(((double) m_settings.m_LOppmTenths)/10000000.0);
482 
483  if (fcdAppSetFreq(m_dev, freq) == FCD_MODE_NONE)
484  {
485  qDebug("No FCD HID found for frquency change");
486  }
487 }
488 
490 {
491  quint8 cmd = on ? 1 : 0;
492 
494 }
495 
497 {
498  quint8 cmd = on ? 1 : 0;
499 
501 }
502 
504 {
505  quint8 cmd = on ? 1 : 0;
506 
508 }
509 
511 {
512  if (gain < 0)
513  {
514  return;
515  }
516 
517  quint8 cmd_value = gain;
518 
520  {
521  qWarning() << "FCDProPlusInput::set_if_gain: failed to set at " << cmd_value;
522  }
523 }
524 
525 void FCDProPlusInput::set_if_filter(int filterIndex)
526 {
527  if ((filterIndex < 0) || (filterIndex >= FCDProPlusConstants::fcdproplus_if_filter_nb_values()))
528  {
529  return;
530  }
531 
532  quint8 cmd_value = FCDProPlusConstants::if_filters[filterIndex].value;
533 
535  {
536  qWarning() << "FCDProPlusInput::set_if_filter: failed to set at " << cmd_value;
537  }
538 }
539 
540 
541 void FCDProPlusInput::set_rf_filter(int filterIndex)
542 {
543  if ((filterIndex < 0) || (filterIndex >= FCDProPlusConstants::fcdproplus_rf_filter_nb_values()))
544  {
545  return;
546  }
547 
548  quint8 cmd_value = FCDProPlusConstants::rf_filters[filterIndex].value;
549 
551  {
552  qWarning() << "FCDProPlusInput::set_rf_filter: failed to set at " << cmd_value;
553  }
554 }
555 
557  SWGSDRangel::SWGDeviceState& response,
558  QString& errorMessage)
559 {
560  (void) errorMessage;
562  return 200;
563 }
564 
566  bool run,
567  SWGSDRangel::SWGDeviceState& response,
568  QString& errorMessage)
569 {
570  (void) errorMessage;
572  MsgStartStop *message = MsgStartStop::create(run);
573  m_inputMessageQueue.push(message);
574 
575  if (m_guiMessageQueue) // forward to GUI if any
576  {
577  MsgStartStop *msgToGUI = MsgStartStop::create(run);
578  m_guiMessageQueue->push(msgToGUI);
579  }
580 
581  return 200;
582 }
583 
586  QString& errorMessage)
587 {
588  (void) errorMessage;
590  response.getFcdProPlusSettings()->init();
592  return 200;
593 }
594 
596  bool force,
597  const QStringList& deviceSettingsKeys,
598  SWGSDRangel::SWGDeviceSettings& response, // query + response
599  QString& errorMessage)
600 {
601  (void) errorMessage;
602  FCDProPlusSettings settings = m_settings;
603 
604  if (deviceSettingsKeys.contains("centerFrequency")) {
606  }
607  if (deviceSettingsKeys.contains("log2Decim")) {
608  settings.m_log2Decim = response.getFcdProPlusSettings()->getLog2Decim();
609  }
610  if (deviceSettingsKeys.contains("fcPos")) {
612  }
613  if (deviceSettingsKeys.contains("rangeLow")) {
614  settings.m_rangeLow = response.getFcdProPlusSettings()->getRangeLow() != 0;
615  }
616  if (deviceSettingsKeys.contains("lnaGain")) {
617  settings.m_lnaGain = response.getFcdProPlusSettings()->getLnaGain() != 0;
618  }
619  if (deviceSettingsKeys.contains("mixGain")) {
620  settings.m_mixGain = response.getFcdProPlusSettings()->getMixGain() != 0;
621  }
622  if (deviceSettingsKeys.contains("biasT")) {
623  settings.m_biasT = response.getFcdProPlusSettings()->getBiasT() != 0;
624  }
625  if (deviceSettingsKeys.contains("ifGain")) {
626  settings.m_ifGain = response.getFcdProPlusSettings()->getIfGain();
627  }
628  if (deviceSettingsKeys.contains("ifFilterIndex")) {
629  settings.m_ifFilterIndex = response.getFcdProPlusSettings()->getIfFilterIndex();
630  }
631  if (deviceSettingsKeys.contains("rfFilterIndex")) {
632  settings.m_rfFilterIndex = response.getFcdProPlusSettings()->getRfFilterIndex();
633  }
634  if (deviceSettingsKeys.contains("LOppmTenths")) {
635  settings.m_LOppmTenths = response.getFcdProPlusSettings()->getLOppmTenths();
636  }
637  if (deviceSettingsKeys.contains("dcBlock")) {
638  settings.m_dcBlock = response.getFcdProPlusSettings()->getDcBlock() != 0;
639  }
640  if (deviceSettingsKeys.contains("iqImbalance")) {
641  settings.m_iqImbalance = response.getFcdProPlusSettings()->getIqImbalance() != 0;
642  }
643  if (deviceSettingsKeys.contains("transverterDeltaFrequency")) {
645  }
646  if (deviceSettingsKeys.contains("transverterMode")) {
647  settings.m_transverterMode = response.getFcdProPlusSettings()->getTransverterMode() != 0;
648  }
649  if (deviceSettingsKeys.contains("fileRecordName")) {
650  settings.m_fileRecordName = *response.getFcdProPlusSettings()->getFileRecordName();
651  }
652  if (deviceSettingsKeys.contains("useReverseAPI")) {
653  settings.m_useReverseAPI = response.getFcdProPlusSettings()->getUseReverseApi() != 0;
654  }
655  if (deviceSettingsKeys.contains("reverseAPIAddress")) {
657  }
658  if (deviceSettingsKeys.contains("reverseAPIPort")) {
660  }
661  if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
663  }
664 
667 
668  if (m_guiMessageQueue) // forward to GUI if any
669  {
670  MsgConfigureFCDProPlus *msgToGUI = MsgConfigureFCDProPlus::create(settings, force);
671  m_guiMessageQueue->push(msgToGUI);
672  }
673 
674  webapiFormatDeviceSettings(response, settings);
675  return 200;
676 }
677 
679 {
681  response.getFcdProPlusSettings()->setLog2Decim(settings.m_log2Decim);
682  response.getFcdProPlusSettings()->setFcPos((int) settings.m_fcPos);
683  response.getFcdProPlusSettings()->setRangeLow(settings.m_rangeLow ? 1 : 0);
684  response.getFcdProPlusSettings()->setLnaGain(settings.m_lnaGain ? 1 : 0);
685  response.getFcdProPlusSettings()->setMixGain(settings.m_mixGain ? 1 : 0);
686  response.getFcdProPlusSettings()->setBiasT(settings.m_biasT ? 1 : 0);
687  response.getFcdProPlusSettings()->setIfGain(settings.m_ifGain);
690  response.getFcdProPlusSettings()->setLOppmTenths(settings.m_LOppmTenths);
691  response.getFcdProPlusSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
692  response.getFcdProPlusSettings()->setIqImbalance(settings.m_iqImbalance ? 1 : 0);
694  response.getFcdProPlusSettings()->setTransverterMode(settings.m_transverterMode ? 1 : 0);
695 
696  if (response.getFcdProPlusSettings()->getFileRecordName()) {
697  *response.getFcdProPlusSettings()->getFileRecordName() = settings.m_fileRecordName;
698  } else {
699  response.getFcdProPlusSettings()->setFileRecordName(new QString(settings.m_fileRecordName));
700  }
701 
702  response.getFcdProPlusSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
703 
704  if (response.getFcdProPlusSettings()->getReverseApiAddress()) {
706  } else {
707  response.getFcdProPlusSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
708  }
709 
712 }
713 
714 void FCDProPlusInput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const FCDProPlusSettings& settings, bool force)
715 {
717  swgDeviceSettings->setDirection(0); // single Rx
718  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
719  swgDeviceSettings->setDeviceHwType(new QString("FCDPro+"));
721  SWGSDRangel::SWGFCDProPlusSettings *swgFCDProPlusSettings = swgDeviceSettings->getFcdProPlusSettings();
722 
723  // transfer data that has been modified. When force is on transfer all data except reverse API data
724 
725  if (deviceSettingsKeys.contains("centerFrequency") || force) {
726  swgFCDProPlusSettings->setCenterFrequency(settings.m_centerFrequency);
727  }
728  if (deviceSettingsKeys.contains("log2Decim") || force) {
729  swgFCDProPlusSettings->setLog2Decim(settings.m_log2Decim);
730  }
731  if (deviceSettingsKeys.contains("fcPos") || force) {
732  swgFCDProPlusSettings->setFcPos((int) settings.m_fcPos);
733  }
734  if (deviceSettingsKeys.contains("rangeLow") || force) {
735  swgFCDProPlusSettings->setRangeLow(settings.m_rangeLow ? 1 : 0);
736  }
737  if (deviceSettingsKeys.contains("lnaGain") || force) {
738  swgFCDProPlusSettings->setLnaGain(settings.m_lnaGain ? 1 : 0);
739  }
740  if (deviceSettingsKeys.contains("mixGain") || force) {
741  swgFCDProPlusSettings->setMixGain(settings.m_mixGain ? 1 : 0);
742  }
743  if (deviceSettingsKeys.contains("biasT") || force) {
744  swgFCDProPlusSettings->setBiasT(settings.m_biasT ? 1 : 0);
745  }
746  if (deviceSettingsKeys.contains("ifGain") || force) {
747  swgFCDProPlusSettings->setIfGain(settings.m_ifGain);
748  }
749  if (deviceSettingsKeys.contains("ifFilterIndex") || force) {
750  swgFCDProPlusSettings->setIfFilterIndex(settings.m_ifFilterIndex);
751  }
752  if (deviceSettingsKeys.contains("rfFilterIndex") || force) {
753  swgFCDProPlusSettings->setRfFilterIndex(settings.m_rfFilterIndex);
754  }
755  if (deviceSettingsKeys.contains("LOppmTenths") || force) {
756  swgFCDProPlusSettings->setLOppmTenths(settings.m_LOppmTenths);
757  }
758  if (deviceSettingsKeys.contains("dcBlock") || force) {
759  swgFCDProPlusSettings->setDcBlock(settings.m_dcBlock ? 1 : 0);
760  }
761  if (deviceSettingsKeys.contains("iqImbalance") || force) {
762  swgFCDProPlusSettings->setIqImbalance(settings.m_iqImbalance ? 1 : 0);
763  }
764  if (deviceSettingsKeys.contains("transverterDeltaFrequency") || force) {
765  swgFCDProPlusSettings->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency);
766  }
767  if (deviceSettingsKeys.contains("transverterMode") || force) {
768  swgFCDProPlusSettings->setTransverterMode(settings.m_transverterMode ? 1 : 0);
769  }
770  if (deviceSettingsKeys.contains("fileRecordName") || force) {
771  swgFCDProPlusSettings->setFileRecordName(new QString(settings.m_fileRecordName));
772  }
773 
774  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings")
775  .arg(settings.m_reverseAPIAddress)
776  .arg(settings.m_reverseAPIPort)
777  .arg(settings.m_reverseAPIDeviceIndex);
778  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
779  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
780 
781  QBuffer *buffer=new QBuffer();
782  buffer->open((QBuffer::ReadWrite));
783  buffer->write(swgDeviceSettings->asJson().toUtf8());
784  buffer->seek(0);
785 
786  // Always use PATCH to avoid passing reverse API settings
787  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
788 
789  delete swgDeviceSettings;
790 }
791 
793 {
795  swgDeviceSettings->setDirection(0); // single Rx
796  swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
797  swgDeviceSettings->setDeviceHwType(new QString("FCDPro+"));
798 
799  QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run")
803  m_networkRequest.setUrl(QUrl(deviceSettingsURL));
804  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
805 
806  QBuffer *buffer=new QBuffer();
807  buffer->open((QBuffer::ReadWrite));
808  buffer->write(swgDeviceSettings->asJson().toUtf8());
809  buffer->seek(0);
810 
811  if (start) {
812  m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer);
813  } else {
814  m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer);
815  }
816 
817  delete swgDeviceSettings;
818 }
819 
820 void FCDProPlusInput::networkManagerFinished(QNetworkReply *reply)
821 {
822  QNetworkReply::NetworkError replyError = reply->error();
823 
824  if (replyError)
825  {
826  qWarning() << "FCDProPlusInput::networkManagerFinished:"
827  << " error(" << (int) replyError
828  << "): " << replyError
829  << ": " << reply->errorString();
830  return;
831  }
832 
833  QString answer = reply->readAll();
834  answer.chop(1); // remove last \n
835  qDebug("FCDProPlusInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
836 }
const QList< QAudioDeviceInfo > & getInputDevices() const
bool startDeviceEngine()
Start the device engine corresponding to the stream type.
Definition: deviceapi.cpp:253
FCD_MODE_ENUM fcdAppSetParam(hid_device *phd, uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len)
Write FCD parameter (e.g. gain or filter)
Definition: fcdhid.c:826
FCDProPlusThread * m_FCDThread
static qint64 calculateDeviceCenterFrequency(quint64 centerFrequency, qint64 transverterDeltaFrequency, int log2Decim, fcPos_t fcPos, quint32 devSampleRate, FrequencyShiftScheme frequencyShiftScheme, bool transverterMode=false)
void fcdClose(hid_device *phd)
Close FCD HID device.
Definition: fcdhid.c:78
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void stopDeviceEngine()
Stop the device engine corresponding to the stream type.
Definition: deviceapi.cpp:266
void setRfFilterIndex(qint32 rf_filter_index)
virtual void setCenterFrequency(qint64 centerFrequency)
static const fcdproplus_rf_filter rf_filters[]
void setFileName(const QString &filename)
Definition: filerecord.cpp:59
uint getDeviceUID() const
Return the current device engine unique ID.
Definition: deviceapi.cpp:303
FCD_MODE_ENUM fcdAppSetFreq(hid_device *phd, int nFreq)
Set FCD frequency with Hz resolution.
Definition: fcdhid.c:450
void startRecording()
Definition: filerecord.cpp:105
MessageQueue m_inputMessageQueue
Input queue to the source.
virtual QString asJson() override
MessageQueue * getDeviceEngineInputMessageQueue()
Device engine message queue.
Definition: deviceapi.cpp:316
QNetworkAccessManager * m_networkManager
#define FCDPROPLUS_HID_CMD_SET_LNA_GAIN
#define FCDPROPLUS_HID_CMD_SET_IF_GAIN
static const fcdproplus_if_filter if_filters[]
QByteArray serialize() const
bool initDeviceEngine()
Init the device engine corresponding to the stream type.
Definition: deviceapi.cpp:240
void set_if_filter(int filterIndex)
virtual int webapiSettingsGet(SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
#define FCDPROPLUS_HID_CMD_SET_RF_FILTER
virtual void init()
initializations to be done when all collaborating objects are created and possibly connected ...
bool openFCDAudio(const char *filename)
static int fcdproplus_rf_filter_nb_values()
void setOriginatorIndex(qint32 originator_index)
DeviceAPI * m_deviceAPI
void setReverseApiPort(qint32 reverse_api_port)
SampleSinkFifo m_sampleFifo
bool setSize(int size)
void webapiReverseSendSettings(QList< QString > &deviceSettingsKeys, const FCDProPlusSettings &settings, bool force)
void setFcPos(int fcPos)
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
virtual bool handleMessage(const Message &message)
Processing of a message. Returns true if message has actually been processed.
Definition: filerecord.cpp:128
FileRecord * m_fileSink
File sink to record device I/Q output.
#define FCDPROPLUS_HID_CMD_SET_BIAS_TEE
virtual int webapiRun(bool run, SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
fcdproplus_rf_filter_value value
void setCenterFrequency(qint64 center_frequency)
void applySettings(const FCDProPlusSettings &settings, bool force)
static MsgConfigureFCDProPlus * create(const FCDProPlusSettings &settings, bool force)
void setIfFilterIndex(qint32 if_filter_index)
int getDeviceSetIndex() const
Definition: deviceapi.h:131
void setTransverterMode(qint32 transverter_mode)
hid_device * fcdOpen(uint16_t usVID, uint16_t usPID, int whichdongle)
Open FCD device.
Definition: fcdhid.c:31
virtual bool handleMessage(const Message &message)
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
void genUniqueFileName(uint deviceUID, int istream=-1)
Definition: filerecord.cpp:67
void setLog2Decimation(unsigned int log2_decim)
void webapiReverseSendStartStop(bool start)
static DSPEngine * instance()
Definition: dspengine.cpp:51
virtual ~FCDProPlusInput()
void setFileRecordName(QString *file_record_name)
void stopRecording()
Definition: filerecord.cpp:117
virtual bool start()
static int fcdproplus_if_filter_nb_values()
virtual void stop()
bool start(int device, int rate)
Definition: audioinput.cpp:49
static bool match(const Message *message)
Definition: message.cpp:45
void setLOppmTenths(qint32 l_oppm_tenths)
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void removeAncillarySink(BasebandSampleSink *sink, unsigned int index=0)
Removes it.
Definition: deviceapi.cpp:100
SWGFCDProPlusSettings * getFcdProPlusSettings()
QNetworkRequest m_networkRequest
void removeFifo(AudioFifo *audioFifo)
Definition: audioinput.cpp:149
bool deserialize(const QByteArray &data)
hid_device * m_dev
FCDProPlusSettings m_settings
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
void set_rf_filter(int filterIndex)
#define FCDPROPLUS_HID_CMD_SET_MIXER_GAIN
void stop()
Definition: audioinput.cpp:121
void setTransverterDeltaFrequency(qint64 transverter_delta_frequency)
void getDeviceEngineStateStr(QString &state)
Definition: deviceapi.cpp:389
void setFcdProPlusSettings(SWGFCDProPlusSettings *fcd_pro_plus_settings)
fcdproplus_if_filter_value value
virtual int getSampleRate() const
Sample rate exposed by the source.
AudioDeviceManager * getAudioDeviceManager()
Definition: dspengine.h:55
#define FCDPROPLUS_HID_CMD_SET_IF_FILTER
virtual int webapiRunGet(SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
virtual quint64 getCenterFrequency() const
Center frequency exposed by the source.
void set_center_freq(double freq)
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings &response, const FCDProPlusSettings &settings)
void networkManagerFinished(QNetworkReply *reply)
int getInputDeviceIndex(const QString &deviceName) const
void setUseReverseApi(qint32 use_reverse_api)
virtual QByteArray serialize() const
uint getRate() const
Definition: audioinput.h:45
const FCDProPlusSettings & getSettings() const
void set_mixer_gain(bool on)
void set_if_gain(int gain)
QString m_deviceDescription
static MsgStartStop * create(bool startStop)
void set_lna_gain(bool on)
void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection, int streamIndex=0)
Configure current device engine DSP corrections (Rx)
Definition: deviceapi.cpp:355
virtual const QString & getDeviceDescription() const
uint32_t getSamplingDeviceSequence() const
Definition: deviceapi.h:123
void setDirection(qint32 direction)
AudioInput m_fcdAudioInput
virtual void destroy()
uint16_t m_reverseAPIDeviceIndex
virtual int webapiSettingsPutPatch(bool force, const QStringList &deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
void set_bias_t(bool on)
virtual bool deserialize(const QByteArray &data)
void setDeviceHwType(QString *device_hw_type)
void addFifo(AudioFifo *audioFifo)
Definition: audioinput.cpp:142
void setReverseApiAddress(QString *reverse_api_address)