| 
									
										
										
										
											2015-12-06 19:47:55 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2015 F4EXB                                                      //
 | 
					
						
							|  |  |  | // written by Edouard Griffiths                                                  //
 | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify          //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by          //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                  //
 | 
					
						
							| 
									
										
										
										
											2019-04-11 06:39:30 +02:00
										 |  |  | // (at your option) any later version.                                           //
 | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,               //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-02 02:28:31 +01:00
										 |  |  | #include <QUdpSocket>
 | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | #include <QHostAddress>
 | 
					
						
							| 
									
										
										
										
											2018-12-24 10:27:35 +01:00
										 |  |  | #include <QNetworkAccessManager>
 | 
					
						
							|  |  |  | #include <QNetworkReply>
 | 
					
						
							|  |  |  | #include <QBuffer>
 | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  | #include "SWGChannelSettings.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | #include "SWGUDPSinkSettings.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  | #include "SWGChannelReport.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | #include "SWGUDPSinkReport.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | #include "dsp/dspengine.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | #include "util/db.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-04 22:41:58 +02:00
										 |  |  | #include "dsp/downchannelizer.h"
 | 
					
						
							|  |  |  | #include "dsp/threadedbasebandsamplesink.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-14 20:11:36 +01:00
										 |  |  | #include "dsp/dspcommands.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-04 22:41:58 +02:00
										 |  |  | #include "device/devicesourceapi.h"
 | 
					
						
							| 
									
										
										
										
											2016-10-02 13:18:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | #include "udpsink.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | const Real UDPSink::m_agcTarget = 16384.0f; | 
					
						
							| 
									
										
										
										
											2017-08-21 13:10:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  | MESSAGE_CLASS_DEFINITION(UDPSink::MsgConfigureUDPSource, Message) | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | MESSAGE_CLASS_DEFINITION(UDPSink::MsgConfigureChannelizer, Message) | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  | MESSAGE_CLASS_DEFINITION(UDPSink::MsgUDPSinkSpectrum, Message) | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | const QString UDPSink::m_channelIdURI = "sdrangel.channel.udpsink"; | 
					
						
							|  |  |  | const QString UDPSink::m_channelId = "UDPSink"; | 
					
						
							| 
									
										
										
										
											2017-11-08 14:23:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | UDPSink::UDPSink(DeviceSourceAPI *deviceAPI) : | 
					
						
							| 
									
										
										
										
											2017-12-20 23:57:06 +01:00
										 |  |  |         ChannelSinkAPI(m_channelIdURI), | 
					
						
							|  |  |  |         m_deviceAPI(deviceAPI), | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |         m_inputSampleRate(48000), | 
					
						
							|  |  |  |         m_inputFrequencyOffset(0), | 
					
						
							| 
									
										
										
										
											2017-12-20 23:57:06 +01:00
										 |  |  |         m_outMovingAverage(480, 1e-10), | 
					
						
							|  |  |  |         m_inMovingAverage(480, 1e-10), | 
					
						
							|  |  |  |         m_amMovingAverage(1200, 1e-10), | 
					
						
							|  |  |  |         m_audioFifo(24000), | 
					
						
							|  |  |  |         m_spectrum(0), | 
					
						
							|  |  |  |         m_squelch(1e-6), | 
					
						
							|  |  |  |         m_squelchOpen(false), | 
					
						
							|  |  |  |         m_squelchOpenCount(0), | 
					
						
							|  |  |  |         m_squelchCloseCount(0), | 
					
						
							|  |  |  |         m_squelchGate(4800), | 
					
						
							|  |  |  |         m_squelchRelease(4800), | 
					
						
							|  |  |  |         m_agc(9600, m_agcTarget, 1e-6), | 
					
						
							|  |  |  |         m_settingsMutex(QMutex::Recursive) | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-23 01:19:32 +01:00
										 |  |  | 	setObjectName(m_channelId); | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 23:45:56 +02:00
										 |  |  | 	m_udpBuffer16 = new UDPSinkUtil<Sample16>(this, udpBlockSize, m_settings.m_udpPort); | 
					
						
							|  |  |  | 	m_udpBufferMono16 = new UDPSinkUtil<int16_t>(this, udpBlockSize, m_settings.m_udpPort); | 
					
						
							|  |  |  |     m_udpBuffer24 = new UDPSinkUtil<Sample24>(this, udpBlockSize, m_settings.m_udpPort); | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | 	m_audioSocket = new QUdpSocket(this); | 
					
						
							| 
									
										
										
										
											2016-04-06 09:33:29 +02:00
										 |  |  | 	m_udpAudioBuf = new char[m_udpAudioPayloadSize]; | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	m_audioBuffer.resize(1<<9); | 
					
						
							|  |  |  | 	m_audioBufferFill = 0; | 
					
						
							| 
									
										
										
										
											2015-12-02 02:28:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  | 	m_nco.setFreq(0, m_inputSampleRate); | 
					
						
							|  |  |  | 	m_interpolator.create(16, m_inputSampleRate, m_settings.m_rfBandwidth / 2.0); | 
					
						
							|  |  |  | 	m_sampleDistanceRemain = m_inputSampleRate / m_settings.m_outputSampleRate; | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 	m_spectrumEnabled = false; | 
					
						
							|  |  |  | 	m_nextSSBId = 0; | 
					
						
							|  |  |  | 	m_nextS16leId = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_last = 0; | 
					
						
							|  |  |  | 	m_this = 0; | 
					
						
							|  |  |  | 	m_scale = 0; | 
					
						
							|  |  |  | 	m_magsq = 0; | 
					
						
							| 
									
										
										
										
											2017-08-17 20:23:17 +02:00
										 |  |  | 	m_inMagsq = 0; | 
					
						
							| 
									
										
										
										
											2017-10-04 22:41:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 	UDPFilter = new fftfilt(0.0, (m_settings.m_rfBandwidth / 2.0) / m_settings.m_outputSampleRate, udpBlockSize); | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 	m_phaseDiscri.setFMScaling((float) m_settings. m_outputSampleRate / (2.0f * m_settings.m_fmDeviation)); | 
					
						
							| 
									
										
										
										
											2016-04-04 03:44:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 	if (m_audioSocket->bind(QHostAddress::LocalHost, m_settings.m_audioPort)) | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | 		qDebug("UDPSink::UDPSink: bind audio socket to port %d", m_settings.m_audioPort); | 
					
						
							| 
									
										
										
										
											2016-04-06 09:33:29 +02:00
										 |  |  | 		connect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()), Qt::QueuedConnection); | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | 		qWarning("UDPSink::UDPSink: cannot bind audio port"); | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-22 08:46:05 +01:00
										 |  |  |     m_agc.setClampMax(SDR_RX_SCALED*SDR_RX_SCALED); | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  |     m_agc.setClamping(true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 03:46:51 +01:00
										 |  |  | 	//DSPEngine::instance()->addAudioSink(&m_audioFifo);
 | 
					
						
							| 
									
										
										
										
											2017-11-06 01:39:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-16 10:24:19 +01:00
										 |  |  |     applyChannelSettings(m_inputSampleRate, m_inputFrequencyOffset, true); | 
					
						
							|  |  |  |     applySettings(m_settings, true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-06 01:39:44 +01:00
										 |  |  |     m_channelizer = new DownChannelizer(this); | 
					
						
							|  |  |  |     m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); | 
					
						
							|  |  |  |     m_deviceAPI->addThreadedSink(m_threadedChannelizer); | 
					
						
							| 
									
										
										
										
											2017-11-19 18:18:17 +01:00
										 |  |  |     m_deviceAPI->addChannelAPI(this); | 
					
						
							| 
									
										
										
										
											2018-12-24 10:27:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_networkManager = new QNetworkAccessManager(); | 
					
						
							|  |  |  |     connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | UDPSink::~UDPSink() | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-24 10:27:35 +01:00
										 |  |  |     disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); | 
					
						
							|  |  |  |     delete m_networkManager; | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | 	delete m_audioSocket; | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  | 	delete m_udpBuffer24; | 
					
						
							|  |  |  |     delete m_udpBuffer16; | 
					
						
							|  |  |  |     delete m_udpBufferMono16; | 
					
						
							| 
									
										
										
										
											2016-04-06 09:33:29 +02:00
										 |  |  | 	delete[] m_udpAudioBuf; | 
					
						
							| 
									
										
										
										
											2018-03-24 03:36:49 +01:00
										 |  |  | 	DSPEngine::instance()->getAudioDeviceManager()->removeAudioSink(&m_audioFifo); | 
					
						
							| 
									
										
										
										
											2017-11-19 18:18:17 +01:00
										 |  |  | 	m_deviceAPI->removeChannelAPI(this); | 
					
						
							| 
									
										
										
										
											2017-10-04 22:41:58 +02:00
										 |  |  |     m_deviceAPI->removeThreadedSink(m_threadedChannelizer); | 
					
						
							|  |  |  |     delete m_threadedChannelizer; | 
					
						
							|  |  |  |     delete m_channelizer; | 
					
						
							| 
									
										
										
										
											2018-04-18 22:20:47 +02:00
										 |  |  |     delete UDPFilter; | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | void UDPSink::setSpectrum(MessageQueue* messageQueue, bool enabled) | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  | 	Message* cmd = MsgUDPSinkSpectrum::create(enabled); | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 	messageQueue->push(cmd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | void UDPSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	Complex ci; | 
					
						
							|  |  |  | 	fftfilt::cmplx* sideband; | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | 	double l, r; | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	m_sampleBuffer.clear(); | 
					
						
							|  |  |  | 	m_settingsMutex.lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-03 11:29:11 +02:00
										 |  |  | 	for(SampleVector::const_iterator it = begin; it < end; ++it) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 		Complex c(it->real(), it->imag()); | 
					
						
							|  |  |  | 		c *= m_nco.nextIQ(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-10 01:53:32 +02:00
										 |  |  | 		if(m_interpolator.decimate(&m_sampleDistanceRemain, c, &ci)) | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  | 		    double inMagSq; | 
					
						
							|  |  |  | 		    double agcFactor = 1.0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |             if ((m_settings.m_agc) && | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  |                 (m_settings.m_sampleFormat != UDPSinkSettings::FormatNFM) && | 
					
						
							|  |  |  |                 (m_settings.m_sampleFormat != UDPSinkSettings::FormatNFMMono) && | 
					
						
							|  |  |  |                 (m_settings.m_sampleFormat != UDPSinkSettings::FormatIQ16) && | 
					
						
							|  |  |  |                 (m_settings.m_sampleFormat != UDPSinkSettings::FormatIQ24)) | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  |             { | 
					
						
							|  |  |  |                 agcFactor = m_agc.feedAndGetValue(ci); | 
					
						
							|  |  |  |                 inMagSq = m_agc.getMagSq(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 inMagSq = ci.real()*ci.real() + ci.imag()*ci.imag(); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-22 08:46:05 +01:00
										 |  |  | 		    m_inMovingAverage.feed(inMagSq / (SDR_RX_SCALED*SDR_RX_SCALED)); | 
					
						
							| 
									
										
										
										
											2017-08-17 20:23:17 +02:00
										 |  |  | 		    m_inMagsq = m_inMovingAverage.average(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | 			Sample ss(ci.real(), ci.imag()); | 
					
						
							|  |  |  | 			m_sampleBuffer.push_back(ss); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  | 			m_sampleDistanceRemain += m_inputSampleRate / m_settings.m_outputSampleRate; | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | 			calculateSquelch(m_inMagsq); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | 			if (m_settings.m_sampleFormat == UDPSinkSettings::FormatLSB) // binaural LSB
 | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  | 			    ci *= agcFactor; | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 				int n_out = UDPFilter->runSSB(ci, &sideband, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (n_out) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					for (int i = 0; i < n_out; i++) | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 						l = m_squelchOpen ? sideband[i].real() * m_settings.m_gain : 0; | 
					
						
							|  |  |  | 						r = m_squelchOpen ? sideband[i].imag() * m_settings.m_gain : 0; | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  | 						udpWrite(l, r); | 
					
						
							| 
									
										
										
										
											2018-01-22 08:46:05 +01:00
										 |  |  | 					    m_outMovingAverage.feed((l*l + r*r) / (SDR_RX_SCALED*SDR_RX_SCALED)); | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | 			if (m_settings.m_sampleFormat == UDPSinkSettings::FormatUSB) // binaural USB
 | 
					
						
							| 
									
										
										
										
											2015-12-02 02:28:31 +01:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  | 			    ci *= agcFactor; | 
					
						
							| 
									
										
										
										
											2016-04-03 11:29:11 +02:00
										 |  |  | 				int n_out = UDPFilter->runSSB(ci, &sideband, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (n_out) | 
					
						
							| 
									
										
										
										
											2015-12-02 02:28:31 +01:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 					for (int i = 0; i < n_out; i++) | 
					
						
							| 
									
										
										
										
											2016-04-03 11:29:11 +02:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 						l = m_squelchOpen ? sideband[i].real() * m_settings.m_gain : 0; | 
					
						
							|  |  |  | 						r = m_squelchOpen ? sideband[i].imag() * m_settings.m_gain : 0; | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  |                         udpWrite(l, r); | 
					
						
							| 
									
										
										
										
											2018-01-22 08:46:05 +01:00
										 |  |  | 						m_outMovingAverage.feed((l*l + r*r) / (SDR_RX_SCALED*SDR_RX_SCALED)); | 
					
						
							| 
									
										
										
										
											2016-04-03 11:29:11 +02:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | 			else if (m_settings.m_sampleFormat == UDPSinkSettings::FormatNFM) | 
					
						
							| 
									
										
										
										
											2015-12-02 02:28:31 +01:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  |                 Real discri = m_squelchOpen ? m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_gain : 0; | 
					
						
							| 
									
										
										
										
											2018-01-28 03:06:30 +01:00
										 |  |  | 				udpWriteNorm(discri, discri); | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  | 				m_outMovingAverage.feed(discri*discri); | 
					
						
							| 
									
										
										
										
											2016-04-03 11:29:11 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | 			else if (m_settings.m_sampleFormat == UDPSinkSettings::FormatNFMMono) | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  | 			    Real discri = m_squelchOpen ? m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_gain : 0; | 
					
						
							| 
									
										
										
										
											2018-01-28 03:06:30 +01:00
										 |  |  | 				udpWriteNormMono(discri); | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  | 				m_outMovingAverage.feed(discri*discri); | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | 			else if (m_settings.m_sampleFormat == UDPSinkSettings::FormatLSBMono) // Monaural LSB
 | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  | 			    ci *= agcFactor; | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 				int n_out = UDPFilter->runSSB(ci, &sideband, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (n_out) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					for (int i = 0; i < n_out; i++) | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 						l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_settings.m_gain : 0; | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  | 		                udpWriteMono(l); | 
					
						
							| 
									
										
										
										
											2018-01-22 08:46:05 +01:00
										 |  |  | 						m_outMovingAverage.feed((l * l) / (SDR_RX_SCALED*SDR_RX_SCALED)); | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | 			else if (m_settings.m_sampleFormat == UDPSinkSettings::FormatUSBMono) // Monaural USB
 | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  | 			    ci *= agcFactor; | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 				int n_out = UDPFilter->runSSB(ci, &sideband, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (n_out) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					for (int i = 0; i < n_out; i++) | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 						l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_settings.m_gain : 0; | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  |                         udpWriteMono(l); | 
					
						
							| 
									
										
										
										
											2018-01-22 08:46:05 +01:00
										 |  |  | 						m_outMovingAverage.feed((l * l) / (SDR_RX_SCALED*SDR_RX_SCALED)); | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | 			else if (m_settings.m_sampleFormat == UDPSinkSettings::FormatAMMono) | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  | 			    Real amplitude = m_squelchOpen ? sqrt(inMagSq) * agcFactor * m_settings.m_gain : 0; | 
					
						
							|  |  |  | 				FixReal demod = (FixReal) amplitude; | 
					
						
							|  |  |  |                 udpWriteMono(demod); | 
					
						
							|  |  |  | 				m_outMovingAverage.feed((amplitude/SDR_RX_SCALEF)*(amplitude/SDR_RX_SCALEF)); | 
					
						
							| 
									
										
										
										
											2016-04-05 17:02:24 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  |             else if (m_settings.m_sampleFormat == UDPSinkSettings::FormatAMNoDCMono) | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  |             { | 
					
						
							|  |  |  |                 if (m_squelchOpen) | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2017-08-20 22:51:22 +02:00
										 |  |  |                     double demodf = sqrt(inMagSq); | 
					
						
							|  |  |  |                     m_amMovingAverage.feed(demodf); | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  |                     Real amplitude = (demodf - m_amMovingAverage.average()) * agcFactor * m_settings.m_gain; | 
					
						
							|  |  |  |                     FixReal demod = (FixReal) amplitude; | 
					
						
							|  |  |  |                     udpWriteMono(demod); | 
					
						
							|  |  |  |                     m_outMovingAverage.feed((amplitude/SDR_RX_SCALEF)*(amplitude/SDR_RX_SCALEF)); | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  |                     udpWriteMono(0); | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  |                     m_outMovingAverage.feed(0); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-08-20 22:18:33 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  |             else if (m_settings.m_sampleFormat == UDPSinkSettings::FormatAMBPFMono) | 
					
						
							| 
									
										
										
										
											2017-08-20 22:18:33 +02:00
										 |  |  |             { | 
					
						
							|  |  |  |                 if (m_squelchOpen) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     double demodf = sqrt(inMagSq); | 
					
						
							|  |  |  |                     demodf = m_bandpass.filter(demodf); | 
					
						
							|  |  |  |                     demodf /= 301.0; | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  |                     Real amplitude = demodf * agcFactor * m_settings.m_gain; | 
					
						
							|  |  |  |                     FixReal demod = (FixReal) amplitude; | 
					
						
							|  |  |  |                     udpWriteMono(demod); | 
					
						
							|  |  |  |                     m_outMovingAverage.feed((amplitude/SDR_RX_SCALEF)*(amplitude/SDR_RX_SCALEF)); | 
					
						
							| 
									
										
										
										
											2017-08-20 22:18:33 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  |                     udpWriteMono(0); | 
					
						
							| 
									
										
										
										
											2017-08-20 22:18:33 +02:00
										 |  |  |                     m_outMovingAverage.feed(0); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2016-04-03 11:29:11 +02:00
										 |  |  | 			else // Raw I/Q samples
 | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | 			    if (m_squelchOpen) | 
					
						
							|  |  |  | 			    { | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  | 	                udpWrite(ci.real() * m_settings.m_gain, ci.imag() * m_settings.m_gain); | 
					
						
							| 
									
										
										
										
											2018-01-22 08:46:05 +01:00
										 |  |  | 	                m_outMovingAverage.feed((inMagSq*m_settings.m_gain*m_settings.m_gain) / (SDR_RX_SCALED*SDR_RX_SCALED)); | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | 			    } | 
					
						
							|  |  |  | 			    else | 
					
						
							|  |  |  | 			    { | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  | 	                udpWrite(0, 0); | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | 	                m_outMovingAverage.feed(0); | 
					
						
							|  |  |  | 			    } | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-08-18 00:10:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             m_magsq = m_outMovingAverage.average(); | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-04-03 11:29:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | 	//qDebug() << "UDPSink::feed: " << m_sampleBuffer.size() * 4;
 | 
					
						
							| 
									
										
										
										
											2016-04-03 11:29:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if((m_spectrum != 0) && (m_spectrumEnabled)) | 
					
						
							| 
									
										
										
										
											2015-12-02 02:28:31 +01:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2016-04-03 11:29:11 +02:00
										 |  |  | 		m_spectrum->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), positiveOnly); | 
					
						
							| 
									
										
										
										
											2015-12-02 02:28:31 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	m_settingsMutex.unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | void UDPSink::start() | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-04 03:44:06 +02:00
										 |  |  | 	m_phaseDiscri.reset(); | 
					
						
							| 
									
										
										
										
											2018-01-09 00:59:10 +01:00
										 |  |  | 	applyChannelSettings(m_inputSampleRate, m_inputFrequencyOffset, true); | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | void UDPSink::stop() | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | bool UDPSink::handleMessage(const Message& cmd) | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-02 21:52:39 +02:00
										 |  |  | 	if (DownChannelizer::MsgChannelizerNotification::match(cmd)) | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2016-10-02 21:52:39 +02:00
										 |  |  | 		DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | 		qDebug() << "UDPSink::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << notif.getSampleRate() | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |                  << " frequencyOffset: " << notif.getFrequencyOffset(); | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  | 		applyChannelSettings(notif.getSampleRate(), notif.getFrequencyOffset()); | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-04 22:41:58 +02:00
										 |  |  |     else if (MsgConfigureChannelizer::match(cmd)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         qDebug() << "UDPSink::handleMessage: MsgConfigureChannelizer:" | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |                 << " sampleRate: " << cfg.getSampleRate() | 
					
						
							|  |  |  |                 << " centerFrequency: " << cfg.getCenterFrequency(); | 
					
						
							| 
									
										
										
										
											2017-10-04 22:41:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         m_channelizer->configure(m_channelizer->getInputMessageQueue(), | 
					
						
							|  |  |  |             cfg.getSampleRate(), | 
					
						
							|  |  |  |             cfg.getCenterFrequency()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 05:44:43 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  |     else if (MsgConfigureUDPSource::match(cmd)) | 
					
						
							| 
									
										
										
										
											2017-10-07 05:44:43 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  |         MsgConfigureUDPSource& cfg = (MsgConfigureUDPSource&) cmd; | 
					
						
							|  |  |  |         qDebug("UDPSink::handleMessage: MsgConfigureUDPSource"); | 
					
						
							| 
									
										
										
										
											2017-10-07 05:44:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |         applySettings(cfg.getSettings(), cfg.getForce()); | 
					
						
							| 
									
										
										
										
											2017-10-07 05:44:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-04 22:41:58 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  | 	else if (MsgUDPSinkSpectrum::match(cmd)) | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  | 		MsgUDPSinkSpectrum& spc = (MsgUDPSinkSpectrum&) cmd; | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		m_spectrumEnabled = spc.getEnabled(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  | 		qDebug() << "UDPSink::handleMessage: MsgUDPSinkSpectrum: m_spectrumEnabled: " << m_spectrumEnabled; | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-14 20:11:36 +01:00
										 |  |  |     else if (DSPSignalNotification::match(cmd)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-11-19 03:27:37 +01:00
										 |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if(m_spectrum != 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		   return m_spectrum->handleMessage(cmd); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | void UDPSink::audioReadyRead() | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	while (m_audioSocket->hasPendingDatagrams()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	    qint64 pendingDataSize = m_audioSocket->pendingDatagramSize(); | 
					
						
							|  |  |  | 	    qint64 udpReadBytes = m_audioSocket->readDatagram(m_udpAudioBuf, pendingDataSize, 0, 0); | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | 		//qDebug("UDPSink::audioReadyRead: %lld", udpReadBytes);
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (m_settings.m_audioActive) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (m_settings.m_audioStereo) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				for (int i = 0; i < udpReadBytes - 3; i += 4) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					qint16 l_sample = (qint16) *(&m_udpAudioBuf[i]); | 
					
						
							|  |  |  | 					qint16 r_sample = (qint16) *(&m_udpAudioBuf[i+2]); | 
					
						
							|  |  |  | 					m_audioBuffer[m_audioBufferFill].l  = l_sample * m_settings.m_volume; | 
					
						
							|  |  |  | 					m_audioBuffer[m_audioBufferFill].r  = r_sample * m_settings.m_volume; | 
					
						
							|  |  |  | 					++m_audioBufferFill; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (m_audioBufferFill >= m_audioBuffer.size()) | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 						uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill); | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						if (res != m_audioBufferFill) | 
					
						
							|  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | 							qDebug("UDPSink::audioReadyRead: (stereo) lost %u samples", m_audioBufferFill - res); | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						m_audioBufferFill = 0; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				for (int i = 0; i < udpReadBytes - 1; i += 2) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					qint16 sample = (qint16) *(&m_udpAudioBuf[i]); | 
					
						
							|  |  |  | 					m_audioBuffer[m_audioBufferFill].l  = sample * m_settings.m_volume; | 
					
						
							|  |  |  | 					m_audioBuffer[m_audioBufferFill].r  = sample * m_settings.m_volume; | 
					
						
							|  |  |  | 					++m_audioBufferFill; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (m_audioBufferFill >= m_audioBuffer.size()) | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 						uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill); | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						if (res != m_audioBufferFill) | 
					
						
							|  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | 							qDebug("UDPSink::audioReadyRead: (mono) lost %u samples", m_audioBufferFill - res); | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						m_audioBufferFill = 0; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 			if (m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill) != m_audioBufferFill) | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | 				qDebug("UDPSink::audioReadyRead: lost samples"); | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			m_audioBufferFill = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  | 	//qDebug("UDPSink::audioReadyRead: done");
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | void UDPSink::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force) | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |     qDebug() << "UDPSink::applyChannelSettings:" | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |             << " inputSampleRate: " << inputSampleRate | 
					
						
							|  |  |  |             << " inputFrequencyOffset: " << inputFrequencyOffset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if((inputFrequencyOffset != m_inputFrequencyOffset) || | 
					
						
							| 
									
										
										
										
											2018-01-09 00:59:10 +01:00
										 |  |  |         (inputSampleRate != m_inputSampleRate) || force) | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         m_nco.setFreq(-inputFrequencyOffset, inputSampleRate); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 00:59:10 +01:00
										 |  |  |     if ((inputSampleRate != m_inputSampleRate) || force) | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         m_settingsMutex.lock(); | 
					
						
							|  |  |  |         m_interpolator.create(16, inputSampleRate, m_settings.m_rfBandwidth / 2.0); | 
					
						
							|  |  |  |         m_sampleDistanceRemain = inputSampleRate / m_settings.m_outputSampleRate; | 
					
						
							|  |  |  |         m_settingsMutex.unlock(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_inputSampleRate = inputSampleRate; | 
					
						
							|  |  |  |     m_inputFrequencyOffset = inputFrequencyOffset; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | void UDPSink::applySettings(const UDPSinkSettings& settings, bool force) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |     qDebug() << "UDPSink::applySettings:" | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |             << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset | 
					
						
							|  |  |  |             << " m_audioActive: " << settings.m_audioActive | 
					
						
							|  |  |  |             << " m_audioStereo: " << settings.m_audioStereo | 
					
						
							|  |  |  |             << " m_gain: " << settings.m_gain | 
					
						
							|  |  |  |             << " m_volume: " << settings.m_volume | 
					
						
							|  |  |  |             << " m_squelchEnabled: " << settings.m_squelchEnabled | 
					
						
							|  |  |  |             << " m_squelchdB: " << settings.m_squelchdB | 
					
						
							|  |  |  |             << " m_squelchGate" << settings.m_squelchGate | 
					
						
							|  |  |  |             << " m_agc" << settings.m_agc | 
					
						
							|  |  |  |             << " m_sampleFormat: " << settings.m_sampleFormat | 
					
						
							|  |  |  |             << " m_outputSampleRate: " << settings.m_outputSampleRate | 
					
						
							|  |  |  |             << " m_rfBandwidth: " << settings.m_rfBandwidth | 
					
						
							|  |  |  |             << " m_fmDeviation: " << settings.m_fmDeviation | 
					
						
							|  |  |  |             << " m_udpAddressStr: " << settings.m_udpAddress | 
					
						
							|  |  |  |             << " m_udpPort: " << settings.m_udpPort | 
					
						
							|  |  |  |             << " m_audioPort: " << settings.m_audioPort | 
					
						
							| 
									
										
										
										
											2019-04-20 19:53:16 +02:00
										 |  |  |             << " m_useReverseAPI: " << settings.m_useReverseAPI | 
					
						
							|  |  |  |             << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress | 
					
						
							|  |  |  |             << " m_reverseAPIPort: " << settings.m_reverseAPIPort | 
					
						
							|  |  |  |             << " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex | 
					
						
							|  |  |  |             << " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |             << " force: " << force; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-24 10:27:35 +01:00
										 |  |  |     QList<QString> reverseAPIKeys; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("inputFrequencyOffset"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_audioActive != m_settings.m_audioActive) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("audioActive"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_audioStereo != m_settings.m_audioStereo) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("audioStereo"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_gain != m_settings.m_gain) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("gain"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_volume != m_settings.m_volume) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("volume"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_squelchEnabled != m_settings.m_squelchEnabled) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("squelchEnabled"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_squelchdB != m_settings.m_squelchdB) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("squelchDB"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_squelchGate != m_settings.m_squelchGate) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("squelchGate"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_agc != m_settings.m_agc) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("agc"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_sampleFormat != m_settings.m_sampleFormat) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("sampleFormat"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_outputSampleRate != m_settings.m_outputSampleRate) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("outputSampleRate"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("rfBandwidth"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("fmDeviation"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_udpAddress != m_settings.m_udpAddress) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("udpAddress"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_udpPort != m_settings.m_udpPort) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("udpPort"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((settings.m_audioPort != m_settings.m_audioPort) || force) { | 
					
						
							|  |  |  |         reverseAPIKeys.append("audioPort"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     m_settingsMutex.lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |     if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         (settings.m_rfBandwidth != m_settings.m_rfBandwidth) || | 
					
						
							|  |  |  |         (settings.m_outputSampleRate != m_settings.m_outputSampleRate) || force) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-12-29 11:04:47 +01:00
										 |  |  |         m_interpolator.create(16, m_inputSampleRate, settings.m_rfBandwidth / 2.0); | 
					
						
							|  |  |  |         m_sampleDistanceRemain = m_inputSampleRate / settings.m_outputSampleRate; | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  |         if ((settings.m_sampleFormat == UDPSinkSettings::FormatLSB) || | 
					
						
							|  |  |  |             (settings.m_sampleFormat == UDPSinkSettings::FormatLSBMono) || | 
					
						
							|  |  |  |             (settings.m_sampleFormat == UDPSinkSettings::FormatUSB) || | 
					
						
							|  |  |  |             (settings.m_sampleFormat == UDPSinkSettings::FormatUSBMono)) | 
					
						
							| 
									
										
										
										
											2017-08-20 23:44:40 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |             m_squelchGate = settings.m_outputSampleRate * 0.05; | 
					
						
							| 
									
										
										
										
											2017-08-20 23:44:40 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |             m_squelchGate = (settings.m_outputSampleRate * settings.m_squelchGate) / 100; | 
					
						
							| 
									
										
										
										
											2017-08-20 23:44:40 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         m_squelchRelease = (settings.m_outputSampleRate * settings.m_squelchGate) / 100; | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |         initSquelch(m_squelchOpen); | 
					
						
							| 
									
										
										
										
											2018-05-06 02:39:39 +02:00
										 |  |  |         m_agc.resize(settings.m_outputSampleRate/5, settings.m_outputSampleRate/20, m_agcTarget); // Fixed 200 ms
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         int stepDownDelay =  (settings.m_outputSampleRate * (settings.m_squelchGate == 0 ? 1 : settings.m_squelchGate))/100; | 
					
						
							| 
									
										
										
										
											2017-10-07 05:44:43 +02:00
										 |  |  |         m_agc.setStepDownDelay(stepDownDelay); | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         m_agc.setGate(settings.m_outputSampleRate * 0.05); | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         m_bandpass.create(301, settings.m_outputSampleRate, 300.0, settings.m_rfBandwidth / 2.0f); | 
					
						
							| 
									
										
										
										
											2017-08-20 22:18:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         m_inMovingAverage.resize(settings.m_outputSampleRate * 0.01, 1e-10);  // 10 ms
 | 
					
						
							|  |  |  |         m_amMovingAverage.resize(settings.m_outputSampleRate * 0.005, 1e-10); //  5 ms
 | 
					
						
							|  |  |  |         m_outMovingAverage.resize(settings.m_outputSampleRate * 0.01, 1e-10); // 10 ms
 | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |     if ((settings.m_audioActive != m_settings.m_audioActive) || force) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         if (settings.m_audioActive) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |             m_audioBufferFill = 0; | 
					
						
							| 
									
										
										
										
											2018-03-25 11:50:34 +02:00
										 |  |  |             DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue()); | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2018-03-24 03:36:49 +01:00
										 |  |  |             DSPEngine::instance()->getAudioDeviceManager()->removeAudioSink(&m_audioFifo); | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |     if ((settings.m_squelchGate != m_settings.m_squelchGate) || force) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  |         if ((settings.m_sampleFormat == UDPSinkSettings::FormatLSB) || | 
					
						
							|  |  |  |             (settings.m_sampleFormat == UDPSinkSettings::FormatLSBMono) || | 
					
						
							|  |  |  |             (settings.m_sampleFormat == UDPSinkSettings::FormatUSB) || | 
					
						
							|  |  |  |             (settings.m_sampleFormat == UDPSinkSettings::FormatUSBMono)) | 
					
						
							| 
									
										
										
										
											2017-08-20 23:44:40 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |             m_squelchGate = settings.m_outputSampleRate * 0.05; | 
					
						
							| 
									
										
										
										
											2017-08-20 23:44:40 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |             m_squelchGate = (settings.m_outputSampleRate * settings.m_squelchGate)/100; | 
					
						
							| 
									
										
										
										
											2017-08-20 23:44:40 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         m_squelchRelease = (settings.m_outputSampleRate * settings.m_squelchGate)/100; | 
					
						
							| 
									
										
										
										
											2017-08-19 00:52:10 +02:00
										 |  |  |         initSquelch(m_squelchOpen); | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         int stepDownDelay =  (settings.m_outputSampleRate * (settings.m_squelchGate == 0 ? 1 : settings.m_squelchGate))/100; | 
					
						
							| 
									
										
										
										
											2017-10-07 05:44:43 +02:00
										 |  |  |         m_agc.setStepDownDelay(stepDownDelay); // same delay for up and down
 | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |     if ((settings.m_squelchdB != m_settings.m_squelchdB) || force) | 
					
						
							| 
									
										
										
										
											2017-08-20 00:32:40 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         m_squelch = CalcDb::powerFromdB(settings.m_squelchdB); | 
					
						
							|  |  |  |         m_agc.setThreshold(m_squelch*(1<<23)); | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |     if ((settings.m_udpAddress != m_settings.m_udpAddress) || force) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  |         m_udpBuffer16->setAddress(const_cast<QString&>(settings.m_udpAddress)); | 
					
						
							|  |  |  |         m_udpBufferMono16->setAddress(const_cast<QString&>(settings.m_udpAddress)); | 
					
						
							|  |  |  |         m_udpBuffer24->setAddress(const_cast<QString&>(settings.m_udpAddress)); | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |     if ((settings.m_udpPort != m_settings.m_udpPort) || force) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-01-28 02:30:15 +01:00
										 |  |  |         m_udpBuffer16->setPort(settings.m_udpPort); | 
					
						
							|  |  |  |         m_udpBufferMono16->setPort(settings.m_udpPort); | 
					
						
							|  |  |  |         m_udpBuffer24->setPort(settings.m_udpPort); | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |     if ((settings.m_audioPort != m_settings.m_audioPort) || force) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         disconnect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead())); | 
					
						
							|  |  |  |         delete m_audioSocket; | 
					
						
							|  |  |  |         m_audioSocket = new QUdpSocket(this); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         if (m_audioSocket->bind(QHostAddress::LocalHost, settings.m_audioPort)) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |             connect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()), Qt::QueuedConnection); | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |             qDebug("UDPSink::handleMessage: audio socket bound to port %d", settings.m_audioPort); | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |             qWarning("UDPSink::handleMessage: cannot bind audio socket"); | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |     if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |         m_phaseDiscri.setFMScaling((float) settings.m_outputSampleRate / (2.0f * settings.m_fmDeviation)); | 
					
						
							| 
									
										
										
										
											2017-08-19 00:12:56 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settingsMutex.unlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-24 10:27:35 +01:00
										 |  |  |     if (settings.m_useReverseAPI) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || | 
					
						
							|  |  |  |                 (m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) || | 
					
						
							|  |  |  |                 (m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) || | 
					
						
							|  |  |  |                 (m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex) || | 
					
						
							|  |  |  |                 (m_settings.m_reverseAPIChannelIndex != settings.m_reverseAPIChannelIndex); | 
					
						
							|  |  |  |         webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 06:30:30 +02:00
										 |  |  |     m_settings = settings; | 
					
						
							| 
									
										
										
										
											2015-12-03 04:02:21 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-17 23:15:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | QByteArray UDPSink::serialize() const | 
					
						
							| 
									
										
										
										
											2017-12-17 23:15:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return m_settings.serialize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | bool UDPSink::deserialize(const QByteArray& data) | 
					
						
							| 
									
										
										
										
											2017-12-17 23:15:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (m_settings.deserialize(data)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  |         MsgConfigureUDPSource *msg = MsgConfigureUDPSource::create(m_settings, true); | 
					
						
							| 
									
										
										
										
											2017-12-17 23:15:42 +01:00
										 |  |  |         m_inputMessageQueue.push(msg); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_settings.resetToDefaults(); | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  |         MsgConfigureUDPSource *msg = MsgConfigureUDPSource::create(m_settings, true); | 
					
						
							| 
									
										
										
										
											2017-12-17 23:15:42 +01:00
										 |  |  |         m_inputMessageQueue.push(msg); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | int UDPSink::webapiSettingsGet( | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |         SWGSDRangel::SWGChannelSettings& response, | 
					
						
							| 
									
										
										
										
											2018-11-13 00:45:03 +01:00
										 |  |  |         QString& errorMessage) | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-11-13 00:45:03 +01:00
										 |  |  |     (void) errorMessage; | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |     response.setUdpSinkSettings(new SWGSDRangel::SWGUDPSinkSettings()); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->init(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     webapiFormatChannelSettings(response, m_settings); | 
					
						
							|  |  |  |     return 200; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | int UDPSink::webapiSettingsPutPatch( | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |                 bool force, | 
					
						
							|  |  |  |                 const QStringList& channelSettingsKeys, | 
					
						
							|  |  |  |                 SWGSDRangel::SWGChannelSettings& response, | 
					
						
							| 
									
										
										
										
											2018-11-13 00:45:03 +01:00
										 |  |  |                 QString& errorMessage) | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-11-13 00:45:03 +01:00
										 |  |  |     (void) errorMessage; | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  |     UDPSinkSettings settings = m_settings; | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     bool frequencyOffsetChanged = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("outputSampleRate")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_outputSampleRate = response.getUdpSinkSettings()->getOutputSampleRate(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("sampleFormat")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_sampleFormat = (UDPSinkSettings::SampleFormat) response.getUdpSinkSettings()->getSampleFormat(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("inputFrequencyOffset")) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_inputFrequencyOffset = response.getUdpSinkSettings()->getInputFrequencyOffset(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |         frequencyOffsetChanged = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("rfBandwidth")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_rfBandwidth = response.getUdpSinkSettings()->getRfBandwidth(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("fmDeviation")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_fmDeviation = response.getUdpSinkSettings()->getFmDeviation(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("channelMute")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_channelMute = response.getUdpSinkSettings()->getChannelMute() != 0; | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("gain")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_gain = response.getUdpSinkSettings()->getGain(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("squelchDB")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_squelchdB = response.getUdpSinkSettings()->getSquelchDb(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("squelchGate")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_squelchGate = response.getUdpSinkSettings()->getSquelchGate(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("squelchEnabled")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_squelchEnabled = response.getUdpSinkSettings()->getSquelchEnabled() != 0; | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("agc")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_agc = response.getUdpSinkSettings()->getAgc() != 0; | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("audioActive")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_audioActive = response.getUdpSinkSettings()->getAudioActive() != 0; | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("audioStereo")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_audioStereo = response.getUdpSinkSettings()->getAudioStereo() != 0; | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("volume")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_volume = response.getUdpSinkSettings()->getVolume(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("udpAddress")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_udpAddress = *response.getUdpSinkSettings()->getUdpAddress(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("udpPort")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_udpPort = response.getUdpSinkSettings()->getUdpPort(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("audioPort")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_audioPort = response.getUdpSinkSettings()->getAudioPort(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("rgbColor")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_rgbColor = response.getUdpSinkSettings()->getRgbColor(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("title")) { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         settings.m_title = *response.getUdpSinkSettings()->getTitle(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-20 19:53:16 +02:00
										 |  |  |     if (channelSettingsKeys.contains("useReverseAPI")) { | 
					
						
							|  |  |  |         settings.m_useReverseAPI = response.getUdpSinkSettings()->getUseReverseApi() != 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("reverseAPIAddress")) { | 
					
						
							|  |  |  |         settings.m_reverseAPIAddress = *response.getUdpSinkSettings()->getReverseApiAddress(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("reverseAPIPort")) { | 
					
						
							|  |  |  |         settings.m_reverseAPIPort = response.getUdpSinkSettings()->getReverseApiPort(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) { | 
					
						
							|  |  |  |         settings.m_reverseAPIDeviceIndex = response.getUdpSinkSettings()->getReverseApiDeviceIndex(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("reverseAPIChannelIndex")) { | 
					
						
							|  |  |  |         settings.m_reverseAPIChannelIndex = response.getUdpSinkSettings()->getReverseApiChannelIndex(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (frequencyOffsetChanged) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  |         UDPSink::MsgConfigureChannelizer *msgChan = UDPSink::MsgConfigureChannelizer::create( | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |                 (int) settings.m_outputSampleRate, | 
					
						
							|  |  |  |                 (int) settings.m_inputFrequencyOffset); | 
					
						
							|  |  |  |         m_inputMessageQueue.push(msgChan); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  |     MsgConfigureUDPSource *msg = MsgConfigureUDPSource::create(settings, force); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     m_inputMessageQueue.push(msg); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |     qDebug("getUdpSinkSettings::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     if (m_guiMessageQueue) // forward to GUI if any
 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-09-12 15:46:42 +02:00
										 |  |  |         MsgConfigureUDPSource *msgToGUI = MsgConfigureUDPSource::create(settings, force); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |         m_guiMessageQueue->push(msgToGUI); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     webapiFormatChannelSettings(response, settings); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 200; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | int UDPSink::webapiReportGet( | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |         SWGSDRangel::SWGChannelReport& response, | 
					
						
							| 
									
										
										
										
											2018-11-13 00:45:03 +01:00
										 |  |  |         QString& errorMessage) | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-11-13 00:45:03 +01:00
										 |  |  |     (void) errorMessage; | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |     response.setUdpSinkReport(new SWGSDRangel::SWGUDPSinkReport()); | 
					
						
							|  |  |  |     response.getUdpSinkReport()->init(); | 
					
						
							| 
									
										
										
										
											2018-05-25 18:44:24 +02:00
										 |  |  |     webapiFormatChannelReport(response); | 
					
						
							|  |  |  |     return 200; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | void UDPSink::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const UDPSinkSettings& settings) | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |     response.getUdpSinkSettings()->setOutputSampleRate(settings.m_outputSampleRate); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setSampleFormat((int) settings.m_sampleFormat); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setRfBandwidth(settings.m_rfBandwidth); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setFmDeviation(settings.m_fmDeviation); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setChannelMute(settings.m_channelMute ? 1 : 0); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setGain(settings.m_gain); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setSquelchDb(settings.m_squelchdB); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setSquelchGate(settings.m_squelchGate); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setSquelchEnabled(settings.m_squelchEnabled ? 1 : 0); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setAgc(settings.m_agc ? 1 : 0); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setAudioActive(settings.m_audioActive ? 1 : 0); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setAudioStereo(settings.m_audioStereo ? 1 : 0); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setVolume(settings.m_volume); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (response.getUdpSinkSettings()->getUdpAddress()) { | 
					
						
							|  |  |  |         *response.getUdpSinkSettings()->getUdpAddress() = settings.m_udpAddress; | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         response.getUdpSinkSettings()->setUdpAddress(new QString(settings.m_udpAddress)); | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |     response.getUdpSinkSettings()->setUdpPort(settings.m_udpPort); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setAudioPort(settings.m_audioPort); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setRgbColor(settings.m_rgbColor); | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |     if (response.getUdpSinkSettings()->getTitle()) { | 
					
						
							|  |  |  |         *response.getUdpSinkSettings()->getTitle() = settings.m_title; | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |         response.getUdpSinkSettings()->setTitle(new QString(settings.m_title)); | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-20 19:53:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (response.getUdpSinkSettings()->getReverseApiAddress()) { | 
					
						
							|  |  |  |         *response.getUdpSinkSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         response.getUdpSinkSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setReverseApiPort(settings.m_reverseAPIPort); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); | 
					
						
							|  |  |  |     response.getUdpSinkSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex); | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 00:08:47 +02:00
										 |  |  | void UDPSink::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-12 00:36:30 +02:00
										 |  |  |     response.getUdpSinkReport()->setChannelPowerDb(CalcDb::dbPower(getInMagSq())); | 
					
						
							|  |  |  |     response.getUdpSinkReport()->setOutputPowerDb(CalcDb::dbPower(getMagSq())); | 
					
						
							|  |  |  |     response.getUdpSinkReport()->setSquelch(m_squelchOpen ? 1 : 0); | 
					
						
							|  |  |  |     response.getUdpSinkReport()->setInputSampleRate(m_inputSampleRate); | 
					
						
							| 
									
										
										
										
											2018-05-25 10:45:40 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-12-24 10:27:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void UDPSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const UDPSinkSettings& settings, bool force) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); | 
					
						
							| 
									
										
										
										
											2019-05-07 14:43:38 +02:00
										 |  |  |     swgChannelSettings->setDirection(0); // single sink (Rx)
 | 
					
						
							| 
									
										
										
										
											2019-03-25 13:53:48 +01:00
										 |  |  |     swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); | 
					
						
							|  |  |  |     swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); | 
					
						
							| 
									
										
										
										
											2018-12-24 10:27:35 +01:00
										 |  |  |     swgChannelSettings->setChannelType(new QString("UDPSink")); | 
					
						
							|  |  |  |     swgChannelSettings->setUdpSinkSettings(new SWGSDRangel::SWGUDPSinkSettings()); | 
					
						
							|  |  |  |     SWGSDRangel::SWGUDPSinkSettings *swgUDPSinkSettings = swgChannelSettings->getUdpSinkSettings(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // transfer data that has been modified. When force is on transfer all data except reverse API data
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("outputSampleRate") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setOutputSampleRate(settings.m_outputSampleRate); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("sampleFormat") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setSampleFormat((int) settings.m_sampleFormat); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("rfBandwidth") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setRfBandwidth(settings.m_rfBandwidth); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("fmDeviation") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setFmDeviation(settings.m_fmDeviation); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("channelMute") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setChannelMute(settings.m_channelMute ? 1 : 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("gain") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setGain(settings.m_gain); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("squelchDB") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setSquelchDb(settings.m_squelchdB); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("squelchGate") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setSquelchGate(settings.m_squelchGate); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("squelchEnabled") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setSquelchEnabled(settings.m_squelchEnabled ? 1 : 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("agc") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setAgc(settings.m_agc ? 1 : 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("audioActive") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setAudioActive(settings.m_audioActive ? 1 : 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("audioStereo") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setAudioStereo(settings.m_audioStereo ? 1 : 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("volume") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setVolume(settings.m_volume); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("udpAddress") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setUdpAddress(new QString(settings.m_udpAddress)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("udpPort") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setUdpPort(settings.m_udpPort); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("audioPort") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setAudioPort(settings.m_audioPort); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("rgbColor") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setRgbColor(settings.m_rgbColor); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (channelSettingsKeys.contains("title") || force) { | 
					
						
							|  |  |  |         swgUDPSinkSettings->setTitle(new QString(settings.m_title)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") | 
					
						
							|  |  |  |             .arg(settings.m_reverseAPIAddress) | 
					
						
							|  |  |  |             .arg(settings.m_reverseAPIPort) | 
					
						
							|  |  |  |             .arg(settings.m_reverseAPIDeviceIndex) | 
					
						
							|  |  |  |             .arg(settings.m_reverseAPIChannelIndex); | 
					
						
							|  |  |  |     m_networkRequest.setUrl(QUrl(channelSettingsURL)); | 
					
						
							|  |  |  |     m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QBuffer *buffer=new QBuffer(); | 
					
						
							|  |  |  |     buffer->open((QBuffer::ReadWrite)); | 
					
						
							|  |  |  |     buffer->write(swgChannelSettings->asJson().toUtf8()); | 
					
						
							|  |  |  |     buffer->seek(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Always use PATCH to avoid passing reverse API settings
 | 
					
						
							|  |  |  |     m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     delete swgChannelSettings; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void UDPSink::networkManagerFinished(QNetworkReply *reply) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QNetworkReply::NetworkError replyError = reply->error(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (replyError) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qWarning() << "UDPSink::networkManagerFinished:" | 
					
						
							|  |  |  |                 << " error(" << (int) replyError | 
					
						
							|  |  |  |                 << "): " << replyError | 
					
						
							|  |  |  |                 << ": " << reply->errorString(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString answer = reply->readAll(); | 
					
						
							|  |  |  |     answer.chop(1); // remove last \n
 | 
					
						
							|  |  |  |     qDebug("UDPSink::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); | 
					
						
							|  |  |  | } |