mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 21:20:31 -05:00 
			
		
		
		
	FreeDV demodulator: created as a copy of SSB demod
This commit is contained in:
		
							parent
							
								
									cc4604f6d8
								
							
						
					
					
						commit
						23c7a9d359
					
				@ -30,6 +30,11 @@ if(CM256CC_FOUND)
 | 
				
			|||||||
    add_subdirectory(remotesink)
 | 
					    add_subdirectory(remotesink)
 | 
				
			||||||
endif(CM256CC_FOUND)
 | 
					endif(CM256CC_FOUND)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					find_package(Codec2)
 | 
				
			||||||
 | 
					if (CODEC2_FOUND)
 | 
				
			||||||
 | 
					    add_subdirectory(demodfreedv)
 | 
				
			||||||
 | 
					endif(CODEC2_FOUND)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (BUILD_DEBIAN)
 | 
					if (BUILD_DEBIAN)
 | 
				
			||||||
    add_subdirectory(demoddsd)
 | 
					    add_subdirectory(demoddsd)
 | 
				
			||||||
    add_subdirectory(remotesink)
 | 
					    add_subdirectory(remotesink)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										49
									
								
								plugins/channelrx/demodfreedv/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								plugins/channelrx/demodfreedv/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					project(demodfreedv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(freedv_SOURCES
 | 
				
			||||||
 | 
						freedvdemod.cpp
 | 
				
			||||||
 | 
						freedvdemodgui.cpp
 | 
				
			||||||
 | 
						freedvdemodsettings.cpp
 | 
				
			||||||
 | 
						freedvplugin.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(freedv_HEADERS
 | 
				
			||||||
 | 
						freedvdemod.h
 | 
				
			||||||
 | 
						freedvdemodgui.h
 | 
				
			||||||
 | 
						freedvdemodsettings.h
 | 
				
			||||||
 | 
						freedvplugin.h
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(freedv_FORMS
 | 
				
			||||||
 | 
						freedvdemodgui.ui
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include_directories(
 | 
				
			||||||
 | 
						.
 | 
				
			||||||
 | 
						${CMAKE_CURRENT_BINARY_DIR}
 | 
				
			||||||
 | 
					    ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client	
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_definitions(${QT_DEFINITIONS})
 | 
				
			||||||
 | 
					add_definitions(-DQT_PLUGIN)
 | 
				
			||||||
 | 
					add_definitions(-DQT_SHARED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qt5_wrap_ui(freedv_FORMS_HEADERS ${freedv_FORMS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(demodfreedv SHARED
 | 
				
			||||||
 | 
						${freedv_SOURCES}
 | 
				
			||||||
 | 
						${freedv_HEADERS_MOC}
 | 
				
			||||||
 | 
						${freedv_FORMS_HEADERS}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(demodfreedv
 | 
				
			||||||
 | 
						${QT_LIBRARIES}
 | 
				
			||||||
 | 
						sdrbase
 | 
				
			||||||
 | 
						sdrgui
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(demodfreedv Qt5::Core Qt5::Widgets)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(TARGETS demodfreedv DESTINATION lib/plugins/channelrx)
 | 
				
			||||||
							
								
								
									
										898
									
								
								plugins/channelrx/demodfreedv/freedvdemod.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										898
									
								
								plugins/channelrx/demodfreedv/freedvdemod.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,898 @@
 | 
				
			|||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Copyright (C) 2019 Edouard Griffiths, F4EXB                                   //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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                  //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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/>.          //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QTime>
 | 
				
			||||||
 | 
					#include <QDebug>
 | 
				
			||||||
 | 
					#include <QNetworkAccessManager>
 | 
				
			||||||
 | 
					#include <QNetworkReply>
 | 
				
			||||||
 | 
					#include <QBuffer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "SWGChannelSettings.h"
 | 
				
			||||||
 | 
					#include "SWGSSBDemodSettings.h"
 | 
				
			||||||
 | 
					#include "SWGChannelReport.h"
 | 
				
			||||||
 | 
					#include "SWGSSBDemodReport.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "audio/audiooutput.h"
 | 
				
			||||||
 | 
					#include "dsp/dspengine.h"
 | 
				
			||||||
 | 
					#include "dsp/downchannelizer.h"
 | 
				
			||||||
 | 
					#include "dsp/threadedbasebandsamplesink.h"
 | 
				
			||||||
 | 
					#include "dsp/dspcommands.h"
 | 
				
			||||||
 | 
					#include "device/devicesourceapi.h"
 | 
				
			||||||
 | 
					#include "util/db.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "freedvdemod.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MESSAGE_CLASS_DEFINITION(FreeDVDemod::MsgConfigureFreeDVDemod, Message)
 | 
				
			||||||
 | 
					MESSAGE_CLASS_DEFINITION(FreeDVDemod::MsgConfigureFreeDVDemodPrivate, Message)
 | 
				
			||||||
 | 
					MESSAGE_CLASS_DEFINITION(FreeDVDemod::MsgConfigureChannelizer, Message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const QString FreeDVDemod::m_channelIdURI = "sdrangel.channel.freedvdemod";
 | 
				
			||||||
 | 
					const QString FreeDVDemod::m_channelId = "FreeDVDemod";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FreeDVDemod::FreeDVDemod(DeviceSourceAPI *deviceAPI) :
 | 
				
			||||||
 | 
					        ChannelSinkAPI(m_channelIdURI),
 | 
				
			||||||
 | 
					        m_deviceAPI(deviceAPI),
 | 
				
			||||||
 | 
					        m_audioBinaual(false),
 | 
				
			||||||
 | 
					        m_audioFlipChannels(false),
 | 
				
			||||||
 | 
					        m_dsb(false),
 | 
				
			||||||
 | 
					        m_audioMute(false),
 | 
				
			||||||
 | 
					        m_agc(12000, agcTarget, 1e-2),
 | 
				
			||||||
 | 
					        m_agcActive(false),
 | 
				
			||||||
 | 
					        m_agcClamping(false),
 | 
				
			||||||
 | 
					        m_agcNbSamples(12000),
 | 
				
			||||||
 | 
					        m_agcPowerThreshold(1e-2),
 | 
				
			||||||
 | 
					        m_agcThresholdGate(0),
 | 
				
			||||||
 | 
					        m_squelchDelayLine(2*48000),
 | 
				
			||||||
 | 
					        m_audioActive(false),
 | 
				
			||||||
 | 
					        m_sampleSink(0),
 | 
				
			||||||
 | 
					        m_audioFifo(24000),
 | 
				
			||||||
 | 
					        m_settingsMutex(QMutex::Recursive)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						setObjectName(m_channelId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_Bandwidth = 5000;
 | 
				
			||||||
 | 
						m_LowCutoff = 300;
 | 
				
			||||||
 | 
						m_volume = 2.0;
 | 
				
			||||||
 | 
						m_spanLog2 = 3;
 | 
				
			||||||
 | 
						m_inputSampleRate = 48000;
 | 
				
			||||||
 | 
						m_inputFrequencyOffset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
 | 
				
			||||||
 | 
					    m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_audioBuffer.resize(1<<14);
 | 
				
			||||||
 | 
						m_audioBufferFill = 0;
 | 
				
			||||||
 | 
						m_undersampleCount = 0;
 | 
				
			||||||
 | 
						m_sum = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_usb = true;
 | 
				
			||||||
 | 
						m_magsq = 0.0f;
 | 
				
			||||||
 | 
						m_magsqSum = 0.0f;
 | 
				
			||||||
 | 
						m_magsqPeak = 0.0f;
 | 
				
			||||||
 | 
						m_magsqCount = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_agc.setClampMax(SDR_RX_SCALED/100.0);
 | 
				
			||||||
 | 
						m_agc.setClamping(m_agcClamping);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, ssbFftLen);
 | 
				
			||||||
 | 
						DSBFilter = new fftfilt((2.0f * m_Bandwidth) / m_audioSampleRate, 2 * ssbFftLen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    applyChannelSettings(m_inputSampleRate, m_inputFrequencyOffset, true);
 | 
				
			||||||
 | 
						applySettings(m_settings, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_channelizer = new DownChannelizer(this);
 | 
				
			||||||
 | 
					    m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
 | 
				
			||||||
 | 
					    m_deviceAPI->addThreadedSink(m_threadedChannelizer);
 | 
				
			||||||
 | 
					    m_deviceAPI->addChannelAPI(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_networkManager = new QNetworkAccessManager();
 | 
				
			||||||
 | 
					    connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FreeDVDemod::~FreeDVDemod()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
 | 
				
			||||||
 | 
					    delete m_networkManager;
 | 
				
			||||||
 | 
						DSPEngine::instance()->getAudioDeviceManager()->removeAudioSink(&m_audioFifo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_deviceAPI->removeChannelAPI(this);
 | 
				
			||||||
 | 
					    m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
 | 
				
			||||||
 | 
					    delete m_threadedChannelizer;
 | 
				
			||||||
 | 
					    delete m_channelizer;
 | 
				
			||||||
 | 
					    delete SSBFilter;
 | 
				
			||||||
 | 
					    delete DSBFilter;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::configure(MessageQueue* messageQueue,
 | 
				
			||||||
 | 
							Real Bandwidth,
 | 
				
			||||||
 | 
							Real LowCutoff,
 | 
				
			||||||
 | 
							Real volume,
 | 
				
			||||||
 | 
							int spanLog2,
 | 
				
			||||||
 | 
							bool audioBinaural,
 | 
				
			||||||
 | 
							bool audioFlipChannel,
 | 
				
			||||||
 | 
							bool dsb,
 | 
				
			||||||
 | 
							bool audioMute,
 | 
				
			||||||
 | 
							bool agc,
 | 
				
			||||||
 | 
							bool agcClamping,
 | 
				
			||||||
 | 
					        int agcTimeLog2,
 | 
				
			||||||
 | 
					        int agcPowerThreshold,
 | 
				
			||||||
 | 
					        int agcThresholdGate)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Message* cmd = MsgConfigureFreeDVDemodPrivate::create(
 | 
				
			||||||
 | 
						        Bandwidth,
 | 
				
			||||||
 | 
						        LowCutoff,
 | 
				
			||||||
 | 
						        volume,
 | 
				
			||||||
 | 
						        spanLog2,
 | 
				
			||||||
 | 
						        audioBinaural,
 | 
				
			||||||
 | 
						        audioFlipChannel,
 | 
				
			||||||
 | 
						        dsb,
 | 
				
			||||||
 | 
						        audioMute,
 | 
				
			||||||
 | 
						        agc,
 | 
				
			||||||
 | 
						        agcClamping,
 | 
				
			||||||
 | 
						        agcTimeLog2,
 | 
				
			||||||
 | 
						        agcPowerThreshold,
 | 
				
			||||||
 | 
						        agcThresholdGate);
 | 
				
			||||||
 | 
						messageQueue->push(cmd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) positiveOnly;
 | 
				
			||||||
 | 
						Complex ci;
 | 
				
			||||||
 | 
						fftfilt::cmplx *sideband;
 | 
				
			||||||
 | 
						int n_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_settingsMutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int decim = 1<<(m_spanLog2 - 1);
 | 
				
			||||||
 | 
						unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(SampleVector::const_iterator it = begin; it < end; ++it)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Complex c(it->real(), it->imag());
 | 
				
			||||||
 | 
							c *= m_nco.nextIQ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (m_dsb)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									n_out = DSBFilter->runDSB(ci, &sideband);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									n_out = SSBFilter->runSSB(ci, &sideband, m_usb);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								m_interpolatorDistanceRemain += m_interpolatorDistance;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								n_out = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (int i = 0; i < n_out; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
 | 
				
			||||||
 | 
								// smart decimation with bit gain using float arithmetic (23 bits significand)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								m_sum += sideband[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!(m_undersampleCount++ & decim_mask))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Real avgr = m_sum.real() / decim;
 | 
				
			||||||
 | 
									Real avgi = m_sum.imag() / decim;
 | 
				
			||||||
 | 
									m_magsq = (avgr * avgr + avgi * avgi) / (SDR_RX_SCALED*SDR_RX_SCALED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                m_magsqSum += m_magsq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (m_magsq > m_magsqPeak)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    m_magsqPeak = m_magsq;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                m_magsqCount++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (!m_dsb & !m_usb)
 | 
				
			||||||
 | 
									{ // invert spectrum for LSB
 | 
				
			||||||
 | 
										m_sampleBuffer.push_back(Sample(avgi, avgr));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										m_sampleBuffer.push_back(Sample(avgr, avgi));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                m_sum.real(0.0);
 | 
				
			||||||
 | 
					                m_sum.imag(0.0);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            float agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 10.0; // 10.0 for 3276.8, 1.0 for 327.68
 | 
				
			||||||
 | 
					            fftfilt::cmplx& delayedSample = m_squelchDelayLine.readBack(m_agc.getStepDownDelay());
 | 
				
			||||||
 | 
					            m_audioActive = delayedSample.real() != 0.0;
 | 
				
			||||||
 | 
					            m_squelchDelayLine.write(sideband[i]*agcVal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (m_audioMute)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									m_audioBuffer[m_audioBufferFill].r = 0;
 | 
				
			||||||
 | 
									m_audioBuffer[m_audioBufferFill].l = 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
								    fftfilt::cmplx z = delayedSample * m_agc.getStepValue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (m_audioBinaual)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										if (m_audioFlipChannels)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											m_audioBuffer[m_audioBufferFill].r = (qint16)(z.imag() * m_volume);
 | 
				
			||||||
 | 
											m_audioBuffer[m_audioBufferFill].l = (qint16)(z.real() * m_volume);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											m_audioBuffer[m_audioBufferFill].r = (qint16)(z.real() * m_volume);
 | 
				
			||||||
 | 
											m_audioBuffer[m_audioBufferFill].l = (qint16)(z.imag() * m_volume);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Real demod = (z.real() + z.imag()) * 0.7;
 | 
				
			||||||
 | 
										qint16 sample = (qint16)(demod * m_volume);
 | 
				
			||||||
 | 
										m_audioBuffer[m_audioBufferFill].l = sample;
 | 
				
			||||||
 | 
										m_audioBuffer[m_audioBufferFill].r = sample;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								++m_audioBufferFill;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (m_audioBufferFill >= m_audioBuffer.size())
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (res != m_audioBufferFill)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
									    qDebug("FreeDVDemod::feed: %u/%u samples written", res, m_audioBufferFill);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									m_audioBufferFill = 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (res != m_audioBufferFill)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					        qDebug("FreeDVDemod::feed: %u/%u tail samples written", res, m_audioBufferFill);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_audioBufferFill = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (m_sampleSink != 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), !m_dsb);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_sampleBuffer.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_settingsMutex.unlock();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::start()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    applyChannelSettings(m_inputSampleRate, m_inputFrequencyOffset, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::stop()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool FreeDVDemod::handleMessage(const Message& cmd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (DownChannelizer::MsgChannelizerNotification::match(cmd))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
 | 
				
			||||||
 | 
							qDebug("FreeDVDemod::handleMessage: MsgChannelizerNotification: m_sampleRate");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							applyChannelSettings(notif.getSampleRate(), notif.getFrequencyOffset());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    else if (MsgConfigureChannelizer::match(cmd))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
 | 
				
			||||||
 | 
					        qDebug() << "FreeDVDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << cfg.getSampleRate()
 | 
				
			||||||
 | 
					                << " centerFrequency: " << cfg.getCenterFrequency();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_channelizer->configure(m_channelizer->getInputMessageQueue(),
 | 
				
			||||||
 | 
					            cfg.getSampleRate(),
 | 
				
			||||||
 | 
					            cfg.getCenterFrequency());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (MsgConfigureFreeDVDemod::match(cmd))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MsgConfigureFreeDVDemod& cfg = (MsgConfigureFreeDVDemod&) cmd;
 | 
				
			||||||
 | 
					        qDebug("FreeDVDemod::handleMessage: MsgConfigureFreeDVDemod");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        applySettings(cfg.getSettings(), cfg.getForce());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (BasebandSampleSink::MsgThreadedSink::match(cmd))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        BasebandSampleSink::MsgThreadedSink& cfg = (BasebandSampleSink::MsgThreadedSink&) cmd;
 | 
				
			||||||
 | 
					        const QThread *thread = cfg.getThread();
 | 
				
			||||||
 | 
					        qDebug("FreeDVDemod::handleMessage: BasebandSampleSink::MsgThreadedSink: %p", thread);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (DSPConfigureAudio::match(cmd))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd;
 | 
				
			||||||
 | 
					        uint32_t sampleRate = cfg.getSampleRate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        qDebug() << "FreeDVDemod::handleMessage: DSPConfigureAudio:"
 | 
				
			||||||
 | 
					                << " sampleRate: " << sampleRate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (sampleRate != m_audioSampleRate) {
 | 
				
			||||||
 | 
					            applyAudioSampleRate(sampleRate);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (DSPSignalNotification::match(cmd))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if(m_sampleSink != 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							   return m_sampleSink->handleMessage(cmd);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    qDebug() << "FreeDVDemod::applyChannelSettings:"
 | 
				
			||||||
 | 
					            << " inputSampleRate: " << inputSampleRate
 | 
				
			||||||
 | 
					            << " inputFrequencyOffset: " << inputFrequencyOffset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((m_inputFrequencyOffset != inputFrequencyOffset) ||
 | 
				
			||||||
 | 
					        (m_inputSampleRate != inputSampleRate) || force)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_nco.setFreq(-inputFrequencyOffset, inputSampleRate);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((m_inputSampleRate != inputSampleRate) || force)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_settingsMutex.lock();
 | 
				
			||||||
 | 
					        m_interpolator.create(16, inputSampleRate, m_Bandwidth * 1.5f, 2.0f);
 | 
				
			||||||
 | 
					        m_interpolatorDistanceRemain = 0;
 | 
				
			||||||
 | 
					        m_interpolatorDistance = (Real) inputSampleRate / (Real) m_audioSampleRate;
 | 
				
			||||||
 | 
					        m_settingsMutex.unlock();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_inputSampleRate = inputSampleRate;
 | 
				
			||||||
 | 
					    m_inputFrequencyOffset = inputFrequencyOffset;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::applyAudioSampleRate(int sampleRate)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    qDebug("FreeDVDemod::applyAudioSampleRate: %d", sampleRate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    MsgConfigureChannelizer* channelConfigMsg = MsgConfigureChannelizer::create(
 | 
				
			||||||
 | 
					            sampleRate, m_settings.m_inputFrequencyOffset);
 | 
				
			||||||
 | 
					    m_inputMessageQueue.push(channelConfigMsg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_settingsMutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_interpolator.create(16, m_inputSampleRate, m_Bandwidth * 1.5f, 2.0f);
 | 
				
			||||||
 | 
					    m_interpolatorDistanceRemain = 0;
 | 
				
			||||||
 | 
					    m_interpolatorDistance = (Real) m_inputSampleRate / (Real) sampleRate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SSBFilter->create_filter(m_LowCutoff / (float) sampleRate, m_Bandwidth / (float) sampleRate);
 | 
				
			||||||
 | 
					    DSBFilter->create_dsb_filter((2.0f * m_Bandwidth) / (float) sampleRate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int agcNbSamples = (sampleRate / 1000) * (1<<m_settings.m_agcTimeLog2);
 | 
				
			||||||
 | 
					    int agcThresholdGate = (sampleRate / 1000) * m_settings.m_agcThresholdGate; // ms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m_agcNbSamples != agcNbSamples)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_agc.resize(agcNbSamples, agcNbSamples/2, agcTarget);
 | 
				
			||||||
 | 
					        m_agc.setStepDownDelay(agcNbSamples);
 | 
				
			||||||
 | 
					        m_agcNbSamples = agcNbSamples;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m_agcThresholdGate != agcThresholdGate)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_agc.setGate(agcThresholdGate);
 | 
				
			||||||
 | 
					        m_agcThresholdGate = agcThresholdGate;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_audioFifo.setSize(sampleRate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_settingsMutex.unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_audioSampleRate = sampleRate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m_guiMessageQueue) // forward to GUI if any
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        DSPConfigureAudio *cfg = new DSPConfigureAudio(m_audioSampleRate);
 | 
				
			||||||
 | 
					        m_guiMessageQueue->push(cfg);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::applySettings(const FreeDVDemodSettings& settings, bool force)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    qDebug() << "FreeDVDemod::applySettings:"
 | 
				
			||||||
 | 
					            << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
 | 
				
			||||||
 | 
					            << " m_rfBandwidth: " << settings.m_rfBandwidth
 | 
				
			||||||
 | 
					            << " m_lowCutoff: " << settings.m_lowCutoff
 | 
				
			||||||
 | 
					            << " m_volume: " << settings.m_volume
 | 
				
			||||||
 | 
					            << " m_spanLog2: " << settings.m_spanLog2
 | 
				
			||||||
 | 
					            << " m_audioBinaual: " << settings.m_audioBinaural
 | 
				
			||||||
 | 
					            << " m_audioFlipChannels: " << settings.m_audioFlipChannels
 | 
				
			||||||
 | 
					            << " m_dsb: " << settings.m_dsb
 | 
				
			||||||
 | 
					            << " m_audioMute: " << settings.m_audioMute
 | 
				
			||||||
 | 
					            << " m_agcActive: " << settings.m_agc
 | 
				
			||||||
 | 
					            << " m_agcClamping: " << settings.m_agcClamping
 | 
				
			||||||
 | 
					            << " m_agcTimeLog2: " << settings.m_agcTimeLog2
 | 
				
			||||||
 | 
					            << " agcPowerThreshold: " << settings.m_agcPowerThreshold
 | 
				
			||||||
 | 
					            << " agcThresholdGate: " << settings.m_agcThresholdGate
 | 
				
			||||||
 | 
					            << " m_audioDeviceName: " << settings.m_audioDeviceName
 | 
				
			||||||
 | 
					            << " force: " << force;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QList<QString> reverseAPIKeys;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if((m_settings.m_inputFrequencyOffset != settings.m_inputFrequencyOffset) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("inputFrequencyOffset");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if((m_settings.m_rfBandwidth != settings.m_rfBandwidth) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("rfBandwidth");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if((m_settings.m_lowCutoff != settings.m_lowCutoff) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("lowCutoff");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if((m_settings.m_rfBandwidth != settings.m_rfBandwidth) ||
 | 
				
			||||||
 | 
					        (m_settings.m_lowCutoff != settings.m_lowCutoff) || force)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        float band, lowCutoff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        band = settings.m_rfBandwidth;
 | 
				
			||||||
 | 
					        lowCutoff = settings.m_lowCutoff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (band < 0) {
 | 
				
			||||||
 | 
					            band = -band;
 | 
				
			||||||
 | 
					            lowCutoff = -lowCutoff;
 | 
				
			||||||
 | 
					            m_usb = false;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            m_usb = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (band < 100.0f)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            band = 100.0f;
 | 
				
			||||||
 | 
					            lowCutoff = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_Bandwidth = band;
 | 
				
			||||||
 | 
					        m_LowCutoff = lowCutoff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_settingsMutex.lock();
 | 
				
			||||||
 | 
					        m_interpolator.create(16, m_inputSampleRate, m_Bandwidth * 1.5f, 2.0f);
 | 
				
			||||||
 | 
					        m_interpolatorDistanceRemain = 0;
 | 
				
			||||||
 | 
					        m_interpolatorDistance = (Real) m_inputSampleRate / (Real) m_audioSampleRate;
 | 
				
			||||||
 | 
					        SSBFilter->create_filter(m_LowCutoff / (float) m_audioSampleRate, m_Bandwidth / (float) m_audioSampleRate);
 | 
				
			||||||
 | 
					        DSBFilter->create_dsb_filter((2.0f * m_Bandwidth) / (float) m_audioSampleRate);
 | 
				
			||||||
 | 
					        m_settingsMutex.unlock();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((m_settings.m_volume != settings.m_volume) || force)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("volume");
 | 
				
			||||||
 | 
					        m_volume = settings.m_volume;
 | 
				
			||||||
 | 
					        m_volume /= 4.0; // for 3276.8
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((m_settings.m_agcTimeLog2 != settings.m_agcTimeLog2) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("agcTimeLog2");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((m_settings.m_agcPowerThreshold != settings.m_agcPowerThreshold) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("agcPowerThreshold");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("agcThresholdGate");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((m_settings.m_agcClamping != settings.m_agcClamping) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("agcClamping");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((m_settings.m_agcTimeLog2 != settings.m_agcTimeLog2) ||
 | 
				
			||||||
 | 
					        (m_settings.m_agcPowerThreshold != settings.m_agcPowerThreshold) ||
 | 
				
			||||||
 | 
					        (m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) ||
 | 
				
			||||||
 | 
					        (m_settings.m_agcClamping != settings.m_agcClamping) || force)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int agcNbSamples = (m_audioSampleRate / 1000) * (1<<settings.m_agcTimeLog2);
 | 
				
			||||||
 | 
					        m_agc.setThresholdEnable(settings.m_agcPowerThreshold != -FreeDVDemodSettings::m_minPowerThresholdDB);
 | 
				
			||||||
 | 
					        double agcPowerThreshold = CalcDb::powerFromdB(settings.m_agcPowerThreshold) * (SDR_RX_SCALED*SDR_RX_SCALED);
 | 
				
			||||||
 | 
					        int agcThresholdGate = (m_audioSampleRate / 1000) * settings.m_agcThresholdGate; // ms
 | 
				
			||||||
 | 
					        bool agcClamping = settings.m_agcClamping;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_agcNbSamples != agcNbSamples)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            m_settingsMutex.lock();
 | 
				
			||||||
 | 
					            m_agc.resize(agcNbSamples, agcNbSamples/2, agcTarget);
 | 
				
			||||||
 | 
					            m_agc.setStepDownDelay(agcNbSamples);
 | 
				
			||||||
 | 
					            m_agcNbSamples = agcNbSamples;
 | 
				
			||||||
 | 
					            m_settingsMutex.unlock();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_agcPowerThreshold != agcPowerThreshold)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            m_agc.setThreshold(agcPowerThreshold);
 | 
				
			||||||
 | 
					            m_agcPowerThreshold = agcPowerThreshold;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_agcThresholdGate != agcThresholdGate)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            m_agc.setGate(agcThresholdGate);
 | 
				
			||||||
 | 
					            m_agcThresholdGate = agcThresholdGate;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_agcClamping != agcClamping)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            m_agc.setClamping(agcClamping);
 | 
				
			||||||
 | 
					            m_agcClamping = agcClamping;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        qDebug() << "SBDemod::applySettings: AGC:"
 | 
				
			||||||
 | 
					            << " agcNbSamples: " << agcNbSamples
 | 
				
			||||||
 | 
					            << " agcPowerThreshold: " << agcPowerThreshold
 | 
				
			||||||
 | 
					            << " agcThresholdGate: " << agcThresholdGate
 | 
				
			||||||
 | 
					            << " agcClamping: " << agcClamping;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("audioDeviceName");
 | 
				
			||||||
 | 
					        AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
 | 
				
			||||||
 | 
					        int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_audioDeviceName);
 | 
				
			||||||
 | 
					        audioDeviceManager->addAudioSink(&m_audioFifo, getInputMessageQueue(), audioDeviceIndex);
 | 
				
			||||||
 | 
					        uint32_t audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_audioSampleRate != audioSampleRate) {
 | 
				
			||||||
 | 
					            applyAudioSampleRate(audioSampleRate);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((m_settings.m_spanLog2 != settings.m_spanLog2) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("spanLog2");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((m_settings.m_audioBinaural != settings.m_audioBinaural) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("audioBinaural");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((m_settings.m_audioFlipChannels != settings.m_audioFlipChannels) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("audioFlipChannels");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((m_settings.m_dsb != settings.m_dsb) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("dsb");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((m_settings.m_audioMute != settings.m_audioMute) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("audioMute");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((m_settings.m_agc != settings.m_agc) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("agc");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_spanLog2 = settings.m_spanLog2;
 | 
				
			||||||
 | 
					    m_audioBinaual = settings.m_audioBinaural;
 | 
				
			||||||
 | 
					    m_audioFlipChannels = settings.m_audioFlipChannels;
 | 
				
			||||||
 | 
					    m_dsb = settings.m_dsb;
 | 
				
			||||||
 | 
					    m_audioMute = settings.m_audioMute;
 | 
				
			||||||
 | 
					    m_agcActive = settings.m_agc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_settings = settings;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArray FreeDVDemod::serialize() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return m_settings.serialize();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool FreeDVDemod::deserialize(const QByteArray& data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (m_settings.deserialize(data))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MsgConfigureFreeDVDemod *msg = MsgConfigureFreeDVDemod::create(m_settings, true);
 | 
				
			||||||
 | 
					        m_inputMessageQueue.push(msg);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_settings.resetToDefaults();
 | 
				
			||||||
 | 
					        MsgConfigureFreeDVDemod *msg = MsgConfigureFreeDVDemod::create(m_settings, true);
 | 
				
			||||||
 | 
					        m_inputMessageQueue.push(msg);
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int FreeDVDemod::webapiSettingsGet(
 | 
				
			||||||
 | 
					        SWGSDRangel::SWGChannelSettings& response,
 | 
				
			||||||
 | 
					        QString& errorMessage)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) errorMessage;
 | 
				
			||||||
 | 
					    response.setSsbDemodSettings(new SWGSDRangel::SWGSSBDemodSettings());
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->init();
 | 
				
			||||||
 | 
					    webapiFormatChannelSettings(response, m_settings);
 | 
				
			||||||
 | 
					    return 200;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int FreeDVDemod::webapiSettingsPutPatch(
 | 
				
			||||||
 | 
					        bool force,
 | 
				
			||||||
 | 
					        const QStringList& channelSettingsKeys,
 | 
				
			||||||
 | 
					        SWGSDRangel::SWGChannelSettings& response,
 | 
				
			||||||
 | 
					        QString& errorMessage)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) errorMessage;
 | 
				
			||||||
 | 
					    FreeDVDemodSettings settings = m_settings;
 | 
				
			||||||
 | 
					    bool frequencyOffsetChanged = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("inputFrequencyOffset"))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        settings.m_inputFrequencyOffset = response.getSsbDemodSettings()->getInputFrequencyOffset();
 | 
				
			||||||
 | 
					        frequencyOffsetChanged = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("rfBandwidth")) {
 | 
				
			||||||
 | 
					        settings.m_rfBandwidth = response.getSsbDemodSettings()->getRfBandwidth();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("lowCutoff")) {
 | 
				
			||||||
 | 
					        settings.m_lowCutoff = response.getSsbDemodSettings()->getLowCutoff();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("volume")) {
 | 
				
			||||||
 | 
					        settings.m_volume = response.getSsbDemodSettings()->getVolume();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("spanLog2")) {
 | 
				
			||||||
 | 
					        settings.m_spanLog2 = response.getSsbDemodSettings()->getSpanLog2();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioBinaural")) {
 | 
				
			||||||
 | 
					        settings.m_audioBinaural = response.getSsbDemodSettings()->getAudioBinaural() != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioFlipChannels")) {
 | 
				
			||||||
 | 
					        settings.m_audioFlipChannels = response.getSsbDemodSettings()->getAudioFlipChannels() != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("dsb")) {
 | 
				
			||||||
 | 
					        settings.m_dsb = response.getSsbDemodSettings()->getDsb() != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioMute")) {
 | 
				
			||||||
 | 
					        settings.m_audioMute = response.getSsbDemodSettings()->getAudioMute() != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agc")) {
 | 
				
			||||||
 | 
					        settings.m_agc = response.getSsbDemodSettings()->getAgc() != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agcClamping")) {
 | 
				
			||||||
 | 
					        settings.m_agcClamping = response.getSsbDemodSettings()->getAgcClamping() != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agcTimeLog2")) {
 | 
				
			||||||
 | 
					        settings.m_agcTimeLog2 = response.getSsbDemodSettings()->getAgcTimeLog2();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agcPowerThreshold")) {
 | 
				
			||||||
 | 
					        settings.m_agcPowerThreshold = response.getSsbDemodSettings()->getAgcPowerThreshold();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agcThresholdGate")) {
 | 
				
			||||||
 | 
					        settings.m_agcThresholdGate = response.getSsbDemodSettings()->getAgcThresholdGate();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("rgbColor")) {
 | 
				
			||||||
 | 
					        settings.m_rgbColor = response.getSsbDemodSettings()->getRgbColor();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("title")) {
 | 
				
			||||||
 | 
					        settings.m_title = *response.getSsbDemodSettings()->getTitle();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioDeviceName")) {
 | 
				
			||||||
 | 
					        settings.m_audioDeviceName = *response.getSsbDemodSettings()->getAudioDeviceName();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (frequencyOffsetChanged)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MsgConfigureChannelizer* channelConfigMsg = MsgConfigureChannelizer::create(
 | 
				
			||||||
 | 
					                m_audioSampleRate, settings.m_inputFrequencyOffset);
 | 
				
			||||||
 | 
					        m_inputMessageQueue.push(channelConfigMsg);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    MsgConfigureFreeDVDemod *msg = MsgConfigureFreeDVDemod::create(settings, force);
 | 
				
			||||||
 | 
					    m_inputMessageQueue.push(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qDebug("FreeDVDemod::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
 | 
				
			||||||
 | 
					    if (m_guiMessageQueue) // forward to GUI if any
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MsgConfigureFreeDVDemod *msgToGUI = MsgConfigureFreeDVDemod::create(settings, force);
 | 
				
			||||||
 | 
					        m_guiMessageQueue->push(msgToGUI);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    webapiFormatChannelSettings(response, settings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 200;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int FreeDVDemod::webapiReportGet(
 | 
				
			||||||
 | 
					        SWGSDRangel::SWGChannelReport& response,
 | 
				
			||||||
 | 
					        QString& errorMessage)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) errorMessage;
 | 
				
			||||||
 | 
					    response.setSsbDemodReport(new SWGSDRangel::SWGSSBDemodReport());
 | 
				
			||||||
 | 
					    response.getSsbDemodReport()->init();
 | 
				
			||||||
 | 
					    webapiFormatChannelReport(response);
 | 
				
			||||||
 | 
					    return 200;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const FreeDVDemodSettings& settings)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setAudioMute(settings.m_audioMute ? 1 : 0);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setRfBandwidth(settings.m_rfBandwidth);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setLowCutoff(settings.m_lowCutoff);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setVolume(settings.m_volume);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setSpanLog2(settings.m_spanLog2);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setAudioBinaural(settings.m_audioBinaural ? 1 : 0);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setAudioFlipChannels(settings.m_audioFlipChannels ? 1 : 0);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setDsb(settings.m_dsb ? 1 : 0);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setAudioMute(settings.m_audioMute ? 1 : 0);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setAgc(settings.m_agc ? 1 : 0);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setAgcClamping(settings.m_agcClamping ? 1 : 0);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setAgcTimeLog2(settings.m_agcTimeLog2);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setAgcPowerThreshold(settings.m_agcPowerThreshold);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setAgcThresholdGate(settings.m_agcThresholdGate);
 | 
				
			||||||
 | 
					    response.getSsbDemodSettings()->setRgbColor(settings.m_rgbColor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (response.getSsbDemodSettings()->getTitle()) {
 | 
				
			||||||
 | 
					        *response.getSsbDemodSettings()->getTitle() = settings.m_title;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        response.getSsbDemodSettings()->setTitle(new QString(settings.m_title));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (response.getSsbDemodSettings()->getAudioDeviceName()) {
 | 
				
			||||||
 | 
					        *response.getSsbDemodSettings()->getAudioDeviceName() = settings.m_audioDeviceName;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        response.getSsbDemodSettings()->setAudioDeviceName(new QString(settings.m_audioDeviceName));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    double magsqAvg, magsqPeak;
 | 
				
			||||||
 | 
					    int nbMagsqSamples;
 | 
				
			||||||
 | 
					    getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    response.getSsbDemodReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg));
 | 
				
			||||||
 | 
					    response.getSsbDemodReport()->setSquelch(m_audioActive ? 1 : 0);
 | 
				
			||||||
 | 
					    response.getSsbDemodReport()->setAudioSampleRate(m_audioSampleRate);
 | 
				
			||||||
 | 
					    response.getSsbDemodReport()->setChannelSampleRate(m_inputSampleRate);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreeDVDemodSettings& settings, bool force)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
 | 
				
			||||||
 | 
					    swgChannelSettings->setTx(0);
 | 
				
			||||||
 | 
					    swgChannelSettings->setChannelType(new QString("SSBDemod"));
 | 
				
			||||||
 | 
					    swgChannelSettings->setSsbDemodSettings(new SWGSDRangel::SWGSSBDemodSettings());
 | 
				
			||||||
 | 
					    SWGSDRangel::SWGSSBDemodSettings *swgSSBDemodSettings = swgChannelSettings->getSsbDemodSettings();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // transfer data that has been modified. When force is on transfer all data except reverse API data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("rfBandwidth") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setRfBandwidth(settings.m_rfBandwidth);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("lowCutoff") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setLowCutoff(settings.m_lowCutoff);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("volume") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setVolume(settings.m_volume);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("spanLog2") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setSpanLog2(settings.m_spanLog2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioBinaural") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setAudioBinaural(settings.m_audioBinaural ? 1 : 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioFlipChannels") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setAudioFlipChannels(settings.m_audioFlipChannels ? 1 : 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("dsb") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setDsb(settings.m_dsb ? 1 : 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioMute") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setAudioMute(settings.m_audioMute ? 1 : 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agc") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setAgc(settings.m_agc ? 1 : 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agcClamping") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setAgcClamping(settings.m_agcClamping ? 1 : 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agcTimeLog2") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setAgcTimeLog2(settings.m_agcTimeLog2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agcPowerThreshold") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setAgcPowerThreshold(settings.m_agcPowerThreshold);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("agcThresholdGate") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setAgcThresholdGate(settings.m_agcThresholdGate);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("rgbColor") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setRgbColor(settings.m_rgbColor);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("title") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setTitle(new QString(settings.m_title));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioDeviceName") || force) {
 | 
				
			||||||
 | 
					        swgSSBDemodSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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 FreeDVDemod::networkManagerFinished(QNetworkReply *reply)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QNetworkReply::NetworkError replyError = reply->error();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (replyError)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        qWarning() << "FreeDVDemod::networkManagerFinished:"
 | 
				
			||||||
 | 
					                << " error(" << (int) replyError
 | 
				
			||||||
 | 
					                << "): " << replyError
 | 
				
			||||||
 | 
					                << ": " << reply->errorString();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QString answer = reply->readAll();
 | 
				
			||||||
 | 
					    answer.chop(1); // remove last \n
 | 
				
			||||||
 | 
					    qDebug("FreeDVDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										333
									
								
								plugins/channelrx/demodfreedv/freedvdemod.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								plugins/channelrx/demodfreedv/freedvdemod.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,333 @@
 | 
				
			|||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Copyright (C) 2019 Edouard Griffiths, F4EXB                                   //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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                  //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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/>.          //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef INCLUDE_FREEDVDEMOD_H
 | 
				
			||||||
 | 
					#define INCLUDE_FREEDVDEMOD_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QMutex>
 | 
				
			||||||
 | 
					#include <QNetworkRequest>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "dsp/basebandsamplesink.h"
 | 
				
			||||||
 | 
					#include "channel/channelsinkapi.h"
 | 
				
			||||||
 | 
					#include "dsp/ncof.h"
 | 
				
			||||||
 | 
					#include "dsp/interpolator.h"
 | 
				
			||||||
 | 
					#include "dsp/fftfilt.h"
 | 
				
			||||||
 | 
					#include "dsp/agc.h"
 | 
				
			||||||
 | 
					#include "audio/audiofifo.h"
 | 
				
			||||||
 | 
					#include "util/message.h"
 | 
				
			||||||
 | 
					#include "util/doublebufferfifo.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "freedvdemodsettings.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ssbFftLen 1024
 | 
				
			||||||
 | 
					#define agcTarget 3276.8 // -10 dB amplitude => -20 dB power: center of normal signal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class QNetworkAccessManager;
 | 
				
			||||||
 | 
					class QNetworkReply;
 | 
				
			||||||
 | 
					class DeviceSourceAPI;
 | 
				
			||||||
 | 
					class ThreadedBasebandSampleSink;
 | 
				
			||||||
 | 
					class DownChannelizer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FreeDVDemod : public BasebandSampleSink, public ChannelSinkAPI {
 | 
				
			||||||
 | 
						Q_OBJECT
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    class MsgConfigureFreeDVDemod : public Message {
 | 
				
			||||||
 | 
					        MESSAGE_CLASS_DECLARATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        const FreeDVDemodSettings& getSettings() const { return m_settings; }
 | 
				
			||||||
 | 
					        bool getForce() const { return m_force; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static MsgConfigureFreeDVDemod* create(const FreeDVDemodSettings& settings, bool force)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return new MsgConfigureFreeDVDemod(settings, force);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        FreeDVDemodSettings m_settings;
 | 
				
			||||||
 | 
					        bool m_force;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MsgConfigureFreeDVDemod(const FreeDVDemodSettings& settings, bool force) :
 | 
				
			||||||
 | 
					            Message(),
 | 
				
			||||||
 | 
					            m_settings(settings),
 | 
				
			||||||
 | 
					            m_force(force)
 | 
				
			||||||
 | 
					        { }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class MsgConfigureChannelizer : public Message {
 | 
				
			||||||
 | 
					        MESSAGE_CLASS_DECLARATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        int getSampleRate() const { return m_sampleRate; }
 | 
				
			||||||
 | 
					        int getCenterFrequency() const { return m_centerFrequency; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return new MsgConfigureChannelizer(sampleRate, centerFrequency);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        int m_sampleRate;
 | 
				
			||||||
 | 
					        int  m_centerFrequency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MsgConfigureChannelizer(int sampleRate, int centerFrequency) :
 | 
				
			||||||
 | 
					            Message(),
 | 
				
			||||||
 | 
					            m_sampleRate(sampleRate),
 | 
				
			||||||
 | 
					            m_centerFrequency(centerFrequency)
 | 
				
			||||||
 | 
					        { }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FreeDVDemod(DeviceSourceAPI *deviceAPI);
 | 
				
			||||||
 | 
						virtual ~FreeDVDemod();
 | 
				
			||||||
 | 
						virtual void destroy() { delete this; }
 | 
				
			||||||
 | 
						void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void configure(MessageQueue* messageQueue,
 | 
				
			||||||
 | 
								Real Bandwidth,
 | 
				
			||||||
 | 
								Real LowCutoff,
 | 
				
			||||||
 | 
								Real volume,
 | 
				
			||||||
 | 
								int spanLog2,
 | 
				
			||||||
 | 
								bool audioBinaural,
 | 
				
			||||||
 | 
								bool audioFlipChannels,
 | 
				
			||||||
 | 
								bool dsb,
 | 
				
			||||||
 | 
								bool audioMute,
 | 
				
			||||||
 | 
								bool agc,
 | 
				
			||||||
 | 
								bool agcClamping,
 | 
				
			||||||
 | 
								int agcTimeLog2,
 | 
				
			||||||
 | 
								int agcPowerThreshold,
 | 
				
			||||||
 | 
								int agcThresholdGate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
 | 
				
			||||||
 | 
						virtual void start();
 | 
				
			||||||
 | 
						virtual void stop();
 | 
				
			||||||
 | 
						virtual bool handleMessage(const Message& cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual void getIdentifier(QString& id) { id = objectName(); }
 | 
				
			||||||
 | 
					    virtual void getTitle(QString& title) { title = m_settings.m_title; }
 | 
				
			||||||
 | 
					    virtual qint64 getCenterFrequency() const { return m_settings.m_inputFrequencyOffset; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual QByteArray serialize() const;
 | 
				
			||||||
 | 
					    virtual bool deserialize(const QByteArray& data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t getAudioSampleRate() const { return m_audioSampleRate; }
 | 
				
			||||||
 | 
					    double getMagSq() const { return m_magsq; }
 | 
				
			||||||
 | 
						bool getAudioActive() const { return m_audioActive; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void getMagSqLevels(double& avg, double& peak, int& nbSamples)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (m_magsqCount > 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            m_magsq = m_magsqSum / m_magsqCount;
 | 
				
			||||||
 | 
					            m_magSqLevelStore.m_magsq = m_magsq;
 | 
				
			||||||
 | 
					            m_magSqLevelStore.m_magsqPeak = m_magsqPeak;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        avg = m_magSqLevelStore.m_magsq;
 | 
				
			||||||
 | 
					        peak = m_magSqLevelStore.m_magsqPeak;
 | 
				
			||||||
 | 
					        nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_magsqSum = 0.0f;
 | 
				
			||||||
 | 
					        m_magsqPeak = 0.0f;
 | 
				
			||||||
 | 
					        m_magsqCount = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual int webapiSettingsGet(
 | 
				
			||||||
 | 
					            SWGSDRangel::SWGChannelSettings& response,
 | 
				
			||||||
 | 
					            QString& errorMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual int webapiSettingsPutPatch(
 | 
				
			||||||
 | 
					            bool force,
 | 
				
			||||||
 | 
					            const QStringList& channelSettingsKeys,
 | 
				
			||||||
 | 
					            SWGSDRangel::SWGChannelSettings& response,
 | 
				
			||||||
 | 
					            QString& errorMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual int webapiReportGet(
 | 
				
			||||||
 | 
					            SWGSDRangel::SWGChannelReport& response,
 | 
				
			||||||
 | 
					            QString& errorMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static const QString m_channelIdURI;
 | 
				
			||||||
 | 
					    static const QString m_channelId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    struct MagSqLevelsStore
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MagSqLevelsStore() :
 | 
				
			||||||
 | 
					            m_magsq(1e-12),
 | 
				
			||||||
 | 
					            m_magsqPeak(1e-12)
 | 
				
			||||||
 | 
					        {}
 | 
				
			||||||
 | 
					        double m_magsq;
 | 
				
			||||||
 | 
					        double m_magsqPeak;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class MsgConfigureFreeDVDemodPrivate : public Message {
 | 
				
			||||||
 | 
							MESSAGE_CLASS_DECLARATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Real getBandwidth() const { return m_Bandwidth; }
 | 
				
			||||||
 | 
							Real getLoCutoff() const { return m_LowCutoff; }
 | 
				
			||||||
 | 
							Real getVolume() const { return m_volume; }
 | 
				
			||||||
 | 
							int  getSpanLog2() const { return m_spanLog2; }
 | 
				
			||||||
 | 
							bool getAudioBinaural() const { return m_audioBinaural; }
 | 
				
			||||||
 | 
							bool getAudioFlipChannels() const { return m_audioFlipChannels; }
 | 
				
			||||||
 | 
							bool getDSB() const { return m_dsb; }
 | 
				
			||||||
 | 
							bool getAudioMute() const { return m_audioMute; }
 | 
				
			||||||
 | 
							bool getAGC() const { return m_agc; }
 | 
				
			||||||
 | 
							bool getAGCClamping() const { return m_agcClamping; }
 | 
				
			||||||
 | 
							int  getAGCTimeLog2() const { return m_agcTimeLog2; }
 | 
				
			||||||
 | 
							int  getAGCPowerThershold() const { return m_agcPowerThreshold; }
 | 
				
			||||||
 | 
					        int  getAGCThersholdGate() const { return m_agcThresholdGate; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static MsgConfigureFreeDVDemodPrivate* create(Real Bandwidth,
 | 
				
			||||||
 | 
									Real LowCutoff,
 | 
				
			||||||
 | 
									Real volume,
 | 
				
			||||||
 | 
									int spanLog2,
 | 
				
			||||||
 | 
									bool audioBinaural,
 | 
				
			||||||
 | 
									bool audioFlipChannels,
 | 
				
			||||||
 | 
									bool dsb,
 | 
				
			||||||
 | 
									bool audioMute,
 | 
				
			||||||
 | 
					                bool agc,
 | 
				
			||||||
 | 
					                bool agcClamping,
 | 
				
			||||||
 | 
					                int  agcTimeLog2,
 | 
				
			||||||
 | 
					                int  agcPowerThreshold,
 | 
				
			||||||
 | 
					                int  agcThresholdGate)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return new MsgConfigureFreeDVDemodPrivate(
 | 
				
			||||||
 | 
								        Bandwidth,
 | 
				
			||||||
 | 
								        LowCutoff,
 | 
				
			||||||
 | 
								        volume,
 | 
				
			||||||
 | 
								        spanLog2,
 | 
				
			||||||
 | 
								        audioBinaural,
 | 
				
			||||||
 | 
								        audioFlipChannels,
 | 
				
			||||||
 | 
								        dsb,
 | 
				
			||||||
 | 
								        audioMute,
 | 
				
			||||||
 | 
								        agc,
 | 
				
			||||||
 | 
								        agcClamping,
 | 
				
			||||||
 | 
								        agcTimeLog2,
 | 
				
			||||||
 | 
								        agcPowerThreshold,
 | 
				
			||||||
 | 
								        agcThresholdGate);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							Real m_Bandwidth;
 | 
				
			||||||
 | 
							Real m_LowCutoff;
 | 
				
			||||||
 | 
							Real m_volume;
 | 
				
			||||||
 | 
							int  m_spanLog2;
 | 
				
			||||||
 | 
							bool m_audioBinaural;
 | 
				
			||||||
 | 
							bool m_audioFlipChannels;
 | 
				
			||||||
 | 
							bool m_dsb;
 | 
				
			||||||
 | 
							bool m_audioMute;
 | 
				
			||||||
 | 
							bool m_agc;
 | 
				
			||||||
 | 
							bool m_agcClamping;
 | 
				
			||||||
 | 
							int  m_agcTimeLog2;
 | 
				
			||||||
 | 
							int  m_agcPowerThreshold;
 | 
				
			||||||
 | 
							int  m_agcThresholdGate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							MsgConfigureFreeDVDemodPrivate(Real Bandwidth,
 | 
				
			||||||
 | 
									Real LowCutoff,
 | 
				
			||||||
 | 
									Real volume,
 | 
				
			||||||
 | 
									int spanLog2,
 | 
				
			||||||
 | 
									bool audioBinaural,
 | 
				
			||||||
 | 
									bool audioFlipChannels,
 | 
				
			||||||
 | 
									bool dsb,
 | 
				
			||||||
 | 
									bool audioMute,
 | 
				
			||||||
 | 
									bool agc,
 | 
				
			||||||
 | 
									bool agcClamping,
 | 
				
			||||||
 | 
									int  agcTimeLog2,
 | 
				
			||||||
 | 
									int  agcPowerThreshold,
 | 
				
			||||||
 | 
									int  agcThresholdGate) :
 | 
				
			||||||
 | 
								Message(),
 | 
				
			||||||
 | 
								m_Bandwidth(Bandwidth),
 | 
				
			||||||
 | 
								m_LowCutoff(LowCutoff),
 | 
				
			||||||
 | 
								m_volume(volume),
 | 
				
			||||||
 | 
								m_spanLog2(spanLog2),
 | 
				
			||||||
 | 
								m_audioBinaural(audioBinaural),
 | 
				
			||||||
 | 
								m_audioFlipChannels(audioFlipChannels),
 | 
				
			||||||
 | 
								m_dsb(dsb),
 | 
				
			||||||
 | 
								m_audioMute(audioMute),
 | 
				
			||||||
 | 
								m_agc(agc),
 | 
				
			||||||
 | 
								m_agcClamping(agcClamping),
 | 
				
			||||||
 | 
								m_agcTimeLog2(agcTimeLog2),
 | 
				
			||||||
 | 
								m_agcPowerThreshold(agcPowerThreshold),
 | 
				
			||||||
 | 
								m_agcThresholdGate(agcThresholdGate)
 | 
				
			||||||
 | 
							{ }
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DeviceSourceAPI *m_deviceAPI;
 | 
				
			||||||
 | 
					    ThreadedBasebandSampleSink* m_threadedChannelizer;
 | 
				
			||||||
 | 
					    DownChannelizer* m_channelizer;
 | 
				
			||||||
 | 
					    FreeDVDemodSettings m_settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Real m_Bandwidth;
 | 
				
			||||||
 | 
						Real m_LowCutoff;
 | 
				
			||||||
 | 
						Real m_volume;
 | 
				
			||||||
 | 
						int m_spanLog2;
 | 
				
			||||||
 | 
						fftfilt::cmplx m_sum;
 | 
				
			||||||
 | 
						int m_undersampleCount;
 | 
				
			||||||
 | 
						int m_inputSampleRate;
 | 
				
			||||||
 | 
						int m_inputFrequencyOffset;
 | 
				
			||||||
 | 
						bool m_audioBinaual;
 | 
				
			||||||
 | 
						bool m_audioFlipChannels;
 | 
				
			||||||
 | 
						bool m_usb;
 | 
				
			||||||
 | 
						bool m_dsb;
 | 
				
			||||||
 | 
						bool m_audioMute;
 | 
				
			||||||
 | 
						double m_magsq;
 | 
				
			||||||
 | 
						double m_magsqSum;
 | 
				
			||||||
 | 
						double m_magsqPeak;
 | 
				
			||||||
 | 
					    int  m_magsqCount;
 | 
				
			||||||
 | 
					    MagSqLevelsStore m_magSqLevelStore;
 | 
				
			||||||
 | 
					    MagAGC m_agc;
 | 
				
			||||||
 | 
					    bool m_agcActive;
 | 
				
			||||||
 | 
					    bool m_agcClamping;
 | 
				
			||||||
 | 
					    int m_agcNbSamples;         //!< number of audio (48 kHz) samples for AGC averaging
 | 
				
			||||||
 | 
					    double m_agcPowerThreshold; //!< AGC power threshold (linear)
 | 
				
			||||||
 | 
					    int m_agcThresholdGate;     //!< Gate length in number of samples befor threshold triggers
 | 
				
			||||||
 | 
					    DoubleBufferFIFO<fftfilt::cmplx> m_squelchDelayLine;
 | 
				
			||||||
 | 
					    bool m_audioActive;         //!< True if an audio signal is produced (no AGC or AGC and above threshold)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NCOF m_nco;
 | 
				
			||||||
 | 
					    Interpolator m_interpolator;
 | 
				
			||||||
 | 
					    Real m_interpolatorDistance;
 | 
				
			||||||
 | 
					    Real m_interpolatorDistanceRemain;
 | 
				
			||||||
 | 
						fftfilt* SSBFilter;
 | 
				
			||||||
 | 
						fftfilt* DSBFilter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BasebandSampleSink* m_sampleSink;
 | 
				
			||||||
 | 
						SampleVector m_sampleBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AudioVector m_audioBuffer;
 | 
				
			||||||
 | 
						uint m_audioBufferFill;
 | 
				
			||||||
 | 
						AudioFifo m_audioFifo;
 | 
				
			||||||
 | 
						quint32 m_audioSampleRate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QNetworkAccessManager *m_networkManager;
 | 
				
			||||||
 | 
					    QNetworkRequest m_networkRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QMutex m_settingsMutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force = false);
 | 
				
			||||||
 | 
						void applySettings(const FreeDVDemodSettings& settings, bool force = false);
 | 
				
			||||||
 | 
					    void applyAudioSampleRate(int sampleRate);
 | 
				
			||||||
 | 
					    void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const FreeDVDemodSettings& settings);
 | 
				
			||||||
 | 
					    void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
 | 
				
			||||||
 | 
					    void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreeDVDemodSettings& settings, bool force);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private slots:
 | 
				
			||||||
 | 
					    void networkManagerFinished(QNetworkReply *reply);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // INCLUDE_FREEDVDEMOD_H
 | 
				
			||||||
							
								
								
									
										638
									
								
								plugins/channelrx/demodfreedv/freedvdemodgui.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										638
									
								
								plugins/channelrx/demodfreedv/freedvdemodgui.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,638 @@
 | 
				
			|||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Copyright (C) 2019 Edouard Griffiths, F4EXB                                   //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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                  //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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/>.          //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QPixmap>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "freedvdemodgui.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "device/devicesourceapi.h"
 | 
				
			||||||
 | 
					#include "device/deviceuiset.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ui_freedvdemodgui.h"
 | 
				
			||||||
 | 
					#include "dsp/spectrumvis.h"
 | 
				
			||||||
 | 
					#include "dsp/dspengine.h"
 | 
				
			||||||
 | 
					#include "dsp/dspcommands.h"
 | 
				
			||||||
 | 
					#include "gui/glspectrum.h"
 | 
				
			||||||
 | 
					#include "gui/basicchannelsettingsdialog.h"
 | 
				
			||||||
 | 
					#include "plugin/pluginapi.h"
 | 
				
			||||||
 | 
					#include "util/simpleserializer.h"
 | 
				
			||||||
 | 
					#include "util/db.h"
 | 
				
			||||||
 | 
					#include "gui/crightclickenabler.h"
 | 
				
			||||||
 | 
					#include "gui/audioselectdialog.h"
 | 
				
			||||||
 | 
					#include "mainwindow.h"
 | 
				
			||||||
 | 
					#include "freedvdemod.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FreeDVDemodGUI* FreeDVDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    FreeDVDemodGUI* gui = new FreeDVDemodGUI(pluginAPI, deviceUISet, rxChannel);
 | 
				
			||||||
 | 
						return gui;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::destroy()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						delete this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::setName(const QString& name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						setObjectName(name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString FreeDVDemodGUI::getName() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return objectName();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qint64 FreeDVDemodGUI::getCenterFrequency() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return m_channelMarker.getCenterFrequency();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::setCenterFrequency(qint64 centerFrequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						m_channelMarker.setCenterFrequency(centerFrequency);
 | 
				
			||||||
 | 
						m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
 | 
				
			||||||
 | 
						applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::resetToDefaults()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						m_settings.resetToDefaults();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArray FreeDVDemodGUI::serialize() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return m_settings.serialize();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool FreeDVDemodGUI::deserialize(const QByteArray& data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(m_settings.deserialize(data))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        displaySettings();
 | 
				
			||||||
 | 
					        applySettings(true); // will have true
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_settings.resetToDefaults();
 | 
				
			||||||
 | 
					        displaySettings();
 | 
				
			||||||
 | 
					        applySettings(true); // will have true
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool FreeDVDemodGUI::handleMessage(const Message& message)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (FreeDVDemod::MsgConfigureFreeDVDemod::match(message))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        qDebug("FreeDVDemodGUI::handleMessage: FreeDVDemodGUI::MsgConfigureFreeDVDemod");
 | 
				
			||||||
 | 
					        const FreeDVDemod::MsgConfigureFreeDVDemod& cfg = (FreeDVDemod::MsgConfigureFreeDVDemod&) message;
 | 
				
			||||||
 | 
					        m_settings = cfg.getSettings();
 | 
				
			||||||
 | 
					        blockApplySettings(true);
 | 
				
			||||||
 | 
					        displaySettings();
 | 
				
			||||||
 | 
					        blockApplySettings(false);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (DSPConfigureAudio::match(message))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        qDebug("FreeDVDemodGUI::handleMessage: DSPConfigureAudio: %d", m_freeDVDemod->getAudioSampleRate());
 | 
				
			||||||
 | 
					        applyBandwidths(5 - ui->spanLog2->value()); // will update spectrum details with new sample rate
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::handleInputMessages()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Message* message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while ((message = getInputMessageQueue()->pop()) != 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (handleMessage(*message))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            delete message;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::channelMarkerChangedByCursor()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
 | 
				
			||||||
 | 
					    m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::channelMarkerHighlightedByCursor()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    setHighlighted(m_channelMarker.getHighlighted());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_audioBinaural_toggled(bool binaural)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						m_audioBinaural = binaural;
 | 
				
			||||||
 | 
						m_settings.m_audioBinaural = binaural;
 | 
				
			||||||
 | 
						applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_audioFlipChannels_toggled(bool flip)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						m_audioFlipChannels = flip;
 | 
				
			||||||
 | 
						m_settings.m_audioFlipChannels = flip;
 | 
				
			||||||
 | 
						applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_dsb_toggled(bool dsb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ui->flipSidebands->setEnabled(!dsb);
 | 
				
			||||||
 | 
					    applyBandwidths(5 - ui->spanLog2->value());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_deltaFrequency_changed(qint64 value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_channelMarker.setCenterFrequency(value);
 | 
				
			||||||
 | 
					    m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_BW_valueChanged(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) value;
 | 
				
			||||||
 | 
					    applyBandwidths(5 - ui->spanLog2->value());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_lowCut_valueChanged(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) value;
 | 
				
			||||||
 | 
					    applyBandwidths(5 - ui->spanLog2->value());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_volume_valueChanged(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
 | 
				
			||||||
 | 
						m_settings.m_volume = value / 10.0;
 | 
				
			||||||
 | 
						applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_agc_toggled(bool checked)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_settings.m_agc = checked;
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_agcClamping_toggled(bool checked)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_settings.m_agcClamping = checked;
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_agcTimeLog2_valueChanged(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QString s = QString::number((1<<value), 'f', 0);
 | 
				
			||||||
 | 
					    ui->agcTimeText->setText(s);
 | 
				
			||||||
 | 
					    m_settings.m_agcTimeLog2 = value;
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_agcPowerThreshold_valueChanged(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    displayAGCPowerThreshold(value);
 | 
				
			||||||
 | 
					    m_settings.m_agcPowerThreshold = value;
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_agcThresholdGate_valueChanged(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QString s = QString::number(value, 'f', 0);
 | 
				
			||||||
 | 
					    ui->agcThresholdGateText->setText(s);
 | 
				
			||||||
 | 
					    m_settings.m_agcThresholdGate = value;
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_audioMute_toggled(bool checked)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						m_audioMute = checked;
 | 
				
			||||||
 | 
						m_settings.m_audioMute = checked;
 | 
				
			||||||
 | 
						applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_spanLog2_valueChanged(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if ((value < 0) || (value > 4)) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    applyBandwidths(5 - ui->spanLog2->value());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::on_flipSidebands_clicked(bool checked)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) checked;
 | 
				
			||||||
 | 
					    int bwValue = ui->BW->value();
 | 
				
			||||||
 | 
					    int lcValue = ui->lowCut->value();
 | 
				
			||||||
 | 
					    ui->BW->setValue(-bwValue);
 | 
				
			||||||
 | 
					    ui->lowCut->setValue(-lcValue);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::onMenuDialogCalled(const QPoint &p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BasicChannelSettingsDialog dialog(&m_channelMarker, this);
 | 
				
			||||||
 | 
					    dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
 | 
				
			||||||
 | 
					    dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress);
 | 
				
			||||||
 | 
					    dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
 | 
				
			||||||
 | 
					    dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
 | 
				
			||||||
 | 
					    dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dialog.move(p);
 | 
				
			||||||
 | 
					    dialog.exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
 | 
				
			||||||
 | 
					    m_settings.m_rgbColor = m_channelMarker.getColor().rgb();
 | 
				
			||||||
 | 
					    m_settings.m_title = m_channelMarker.getTitle();
 | 
				
			||||||
 | 
					    m_settings.m_useReverseAPI = dialog.useReverseAPI();
 | 
				
			||||||
 | 
					    m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
 | 
				
			||||||
 | 
					    m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
 | 
				
			||||||
 | 
					    m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex();
 | 
				
			||||||
 | 
					    m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setWindowTitle(m_settings.m_title);
 | 
				
			||||||
 | 
					    setTitleColor(m_settings.m_rgbColor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) widget;
 | 
				
			||||||
 | 
					    (void) rollDown;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FreeDVDemodGUI::FreeDVDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) :
 | 
				
			||||||
 | 
						RollupWidget(parent),
 | 
				
			||||||
 | 
						ui(new Ui::FreeDVDemodGUI),
 | 
				
			||||||
 | 
						m_pluginAPI(pluginAPI),
 | 
				
			||||||
 | 
						m_deviceUISet(deviceUISet),
 | 
				
			||||||
 | 
						m_channelMarker(this),
 | 
				
			||||||
 | 
						m_doApplySettings(true),
 | 
				
			||||||
 | 
					    m_spectrumRate(6000),
 | 
				
			||||||
 | 
						m_audioBinaural(false),
 | 
				
			||||||
 | 
						m_audioFlipChannels(false),
 | 
				
			||||||
 | 
					    m_audioMute(false),
 | 
				
			||||||
 | 
						m_squelchOpen(false)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ui->setupUi(this);
 | 
				
			||||||
 | 
						setAttribute(Qt::WA_DeleteOnClose, true);
 | 
				
			||||||
 | 
						connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
 | 
				
			||||||
 | 
						connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_spectrumVis = new SpectrumVis(SDR_RX_SCALEF, ui->glSpectrum);
 | 
				
			||||||
 | 
						m_freeDVDemod = (FreeDVDemod*) rxChannel;
 | 
				
			||||||
 | 
						m_freeDVDemod->setSampleSink(m_spectrumVis);
 | 
				
			||||||
 | 
						m_freeDVDemod->setMessageQueueToGUI(getInputMessageQueue());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resetToDefaults();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->glSpectrum->setCenterFrequency(m_spectrumRate/2);
 | 
				
			||||||
 | 
					    ui->glSpectrum->setSampleRate(m_spectrumRate);
 | 
				
			||||||
 | 
						ui->glSpectrum->setDisplayWaterfall(true);
 | 
				
			||||||
 | 
						ui->glSpectrum->setDisplayMaxHold(true);
 | 
				
			||||||
 | 
					    ui->glSpectrum->setSsbSpectrum(true);
 | 
				
			||||||
 | 
						ui->glSpectrum->connectTimer(MainWindow::getInstance()->getMasterTimer());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute);
 | 
				
			||||||
 | 
					    connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
 | 
				
			||||||
 | 
					    ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
 | 
				
			||||||
 | 
					    ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
 | 
				
			||||||
 | 
						ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_channelMarker.setVisible(true); // activate signal on the last setting only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_settings.setChannelMarker(&m_channelMarker);
 | 
				
			||||||
 | 
					    m_settings.setSpectrumGUI(ui->spectrumGUI);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_deviceUISet->registerRxChannelInstance(FreeDVDemod::m_channelIdURI, this);
 | 
				
			||||||
 | 
						m_deviceUISet->addChannelMarker(&m_channelMarker);
 | 
				
			||||||
 | 
						m_deviceUISet->addRollupWidget(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
 | 
				
			||||||
 | 
					    connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
 | 
				
			||||||
 | 
					    connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_iconDSBUSB.addPixmap(QPixmap("://dsb.png"), QIcon::Normal, QIcon::On);
 | 
				
			||||||
 | 
					    m_iconDSBUSB.addPixmap(QPixmap("://usb.png"), QIcon::Normal, QIcon::Off);
 | 
				
			||||||
 | 
						m_iconDSBLSB.addPixmap(QPixmap("://dsb.png"), QIcon::Normal, QIcon::On);
 | 
				
			||||||
 | 
					    m_iconDSBLSB.addPixmap(QPixmap("://lsb.png"), QIcon::Normal, QIcon::Off);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						displaySettings();
 | 
				
			||||||
 | 
						applyBandwidths(5 - ui->spanLog2->value(), true); // does applySettings(true)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FreeDVDemodGUI::~FreeDVDemodGUI()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_deviceUISet->removeRxChannelInstance(this);
 | 
				
			||||||
 | 
						delete m_freeDVDemod; // TODO: check this: when the GUI closes it has to delete the demodulator
 | 
				
			||||||
 | 
						delete m_spectrumVis;
 | 
				
			||||||
 | 
						delete ui;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool FreeDVDemodGUI::blockApplySettings(bool block)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bool ret = !m_doApplySettings;
 | 
				
			||||||
 | 
					    m_doApplySettings = !block;
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::applySettings(bool force)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (m_doApplySettings)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					        FreeDVDemod::MsgConfigureChannelizer* channelConfigMsg = FreeDVDemod::MsgConfigureChannelizer::create(
 | 
				
			||||||
 | 
					                m_freeDVDemod->getAudioSampleRate(), m_channelMarker.getCenterFrequency());
 | 
				
			||||||
 | 
					        m_freeDVDemod->getInputMessageQueue()->push(channelConfigMsg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        FreeDVDemod::MsgConfigureFreeDVDemod* message = FreeDVDemod::MsgConfigureFreeDVDemod::create( m_settings, force);
 | 
				
			||||||
 | 
					        m_freeDVDemod->getInputMessageQueue()->push(message);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::applyBandwidths(int spanLog2, bool force)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bool dsb = ui->dsb->isChecked();
 | 
				
			||||||
 | 
					    //int spanLog2 = ui->spanLog2->value();
 | 
				
			||||||
 | 
					    m_spectrumRate = m_freeDVDemod->getAudioSampleRate() / (1<<spanLog2);
 | 
				
			||||||
 | 
					    int bw = ui->BW->value();
 | 
				
			||||||
 | 
					    int lw = ui->lowCut->value();
 | 
				
			||||||
 | 
					    int bwMax = m_freeDVDemod->getAudioSampleRate() / (100*(1<<spanLog2));
 | 
				
			||||||
 | 
					    int tickInterval = m_spectrumRate / 1200;
 | 
				
			||||||
 | 
					    tickInterval = tickInterval == 0 ? 1 : tickInterval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qDebug() << "FreeDVDemodGUI::applyBandwidths:"
 | 
				
			||||||
 | 
					            << " dsb: " << dsb
 | 
				
			||||||
 | 
					            << " spanLog2: " << spanLog2
 | 
				
			||||||
 | 
					            << " m_spectrumRate: " << m_spectrumRate
 | 
				
			||||||
 | 
					            << " bw: " << bw
 | 
				
			||||||
 | 
					            << " lw: " << lw
 | 
				
			||||||
 | 
					            << " bwMax: " << bwMax
 | 
				
			||||||
 | 
					            << " tickInterval: " << tickInterval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->BW->setTickInterval(tickInterval);
 | 
				
			||||||
 | 
					    ui->lowCut->setTickInterval(tickInterval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bw = bw < -bwMax ? -bwMax : bw > bwMax ? bwMax : bw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bw < 0) {
 | 
				
			||||||
 | 
					        lw = lw < bw+1 ? bw+1 : lw < 0 ? lw : 0;
 | 
				
			||||||
 | 
					    } else if (bw > 0) {
 | 
				
			||||||
 | 
					        lw = lw > bw-1 ? bw-1 : lw < 0 ? 0 : lw;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        lw = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dsb)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        bw = bw < 0 ? -bw : bw;
 | 
				
			||||||
 | 
					        lw = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QString spanStr = QString::number(bwMax/10.0, 'f', 1);
 | 
				
			||||||
 | 
					    QString bwStr   = QString::number(bw/10.0, 'f', 1);
 | 
				
			||||||
 | 
					    QString lwStr   = QString::number(lw/10.0, 'f', 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dsb)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ui->BWText->setText(tr("%1%2k").arg(QChar(0xB1, 0x00)).arg(bwStr));
 | 
				
			||||||
 | 
					        ui->spanText->setText(tr("%1%2k").arg(QChar(0xB1, 0x00)).arg(spanStr));
 | 
				
			||||||
 | 
					        ui->scaleMinus->setText("0");
 | 
				
			||||||
 | 
					        ui->scaleCenter->setText("");
 | 
				
			||||||
 | 
					        ui->scalePlus->setText(tr("%1").arg(QChar(0xB1, 0x00)));
 | 
				
			||||||
 | 
					        ui->lsbLabel->setText("");
 | 
				
			||||||
 | 
					        ui->usbLabel->setText("");
 | 
				
			||||||
 | 
					        ui->glSpectrum->setCenterFrequency(0);
 | 
				
			||||||
 | 
					        ui->glSpectrum->setSampleRate(2*m_spectrumRate);
 | 
				
			||||||
 | 
					        ui->glSpectrum->setSsbSpectrum(false);
 | 
				
			||||||
 | 
					        ui->glSpectrum->setLsbDisplay(false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ui->BWText->setText(tr("%1k").arg(bwStr));
 | 
				
			||||||
 | 
					        ui->spanText->setText(tr("%1k").arg(spanStr));
 | 
				
			||||||
 | 
					        ui->scaleMinus->setText("-");
 | 
				
			||||||
 | 
					        ui->scaleCenter->setText("0");
 | 
				
			||||||
 | 
					        ui->scalePlus->setText("+");
 | 
				
			||||||
 | 
					        ui->lsbLabel->setText("LSB");
 | 
				
			||||||
 | 
					        ui->usbLabel->setText("USB");
 | 
				
			||||||
 | 
					        ui->glSpectrum->setCenterFrequency(m_spectrumRate/2);
 | 
				
			||||||
 | 
					        ui->glSpectrum->setSampleRate(m_spectrumRate);
 | 
				
			||||||
 | 
					        ui->glSpectrum->setSsbSpectrum(true);
 | 
				
			||||||
 | 
					        ui->glSpectrum->setLsbDisplay(bw < 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->lowCutText->setText(tr("%1k").arg(lwStr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->BW->blockSignals(true);
 | 
				
			||||||
 | 
					    ui->lowCut->blockSignals(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->BW->setMaximum(bwMax);
 | 
				
			||||||
 | 
					    ui->BW->setMinimum(dsb ? 0 : -bwMax);
 | 
				
			||||||
 | 
					    ui->BW->setValue(bw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->lowCut->setMaximum(dsb ? 0 :  bwMax);
 | 
				
			||||||
 | 
					    ui->lowCut->setMinimum(dsb ? 0 : -bwMax);
 | 
				
			||||||
 | 
					    ui->lowCut->setValue(lw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->lowCut->blockSignals(false);
 | 
				
			||||||
 | 
					    ui->BW->blockSignals(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->channelPowerMeter->setRange(FreeDVDemodSettings::m_minPowerThresholdDB, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_settings.m_dsb = dsb;
 | 
				
			||||||
 | 
					    m_settings.m_spanLog2 = spanLog2;
 | 
				
			||||||
 | 
					    m_settings.m_rfBandwidth = bw * 100;
 | 
				
			||||||
 | 
					    m_settings.m_lowCutoff = lw * 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    applySettings(force);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool wasBlocked = blockApplySettings(true);
 | 
				
			||||||
 | 
					    m_channelMarker.setBandwidth(bw * 200);
 | 
				
			||||||
 | 
					    m_channelMarker.setSidebands(dsb ? ChannelMarker::dsb : bw < 0 ? ChannelMarker::lsb : ChannelMarker::usb);
 | 
				
			||||||
 | 
					    ui->dsb->setIcon(bw < 0 ? m_iconDSBLSB: m_iconDSBUSB);
 | 
				
			||||||
 | 
					    if (!dsb) { m_channelMarker.setLowCutoff(lw * 100); }
 | 
				
			||||||
 | 
					    blockApplySettings(wasBlocked);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::displaySettings()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_channelMarker.blockSignals(true);
 | 
				
			||||||
 | 
					    m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
 | 
				
			||||||
 | 
					    m_channelMarker.setBandwidth(m_settings.m_rfBandwidth * 2);
 | 
				
			||||||
 | 
					    m_channelMarker.setTitle(m_settings.m_title);
 | 
				
			||||||
 | 
					    m_channelMarker.setLowCutoff(m_settings.m_lowCutoff);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->flipSidebands->setEnabled(!m_settings.m_dsb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m_settings.m_dsb) {
 | 
				
			||||||
 | 
					        m_channelMarker.setSidebands(ChannelMarker::dsb);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        if (m_settings.m_rfBandwidth < 0) {
 | 
				
			||||||
 | 
					            m_channelMarker.setSidebands(ChannelMarker::lsb);
 | 
				
			||||||
 | 
					            ui->dsb->setIcon(m_iconDSBLSB);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            m_channelMarker.setSidebands(ChannelMarker::usb);
 | 
				
			||||||
 | 
					            ui->dsb->setIcon(m_iconDSBUSB);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_channelMarker.blockSignals(false);
 | 
				
			||||||
 | 
					    m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setTitleColor(m_settings.m_rgbColor);
 | 
				
			||||||
 | 
					    setWindowTitle(m_channelMarker.getTitle());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    blockApplySettings(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->agc->setChecked(m_settings.m_agc);
 | 
				
			||||||
 | 
					    ui->agcClamping->setChecked(m_settings.m_agcClamping);
 | 
				
			||||||
 | 
					    ui->audioBinaural->setChecked(m_settings.m_audioBinaural);
 | 
				
			||||||
 | 
					    ui->audioFlipChannels->setChecked(m_settings.m_audioFlipChannels);
 | 
				
			||||||
 | 
					    ui->audioMute->setChecked(m_settings.m_audioMute);
 | 
				
			||||||
 | 
					    ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Prevent uncontrolled triggering of applyBandwidths
 | 
				
			||||||
 | 
					    ui->spanLog2->blockSignals(true);
 | 
				
			||||||
 | 
					    ui->dsb->blockSignals(true);
 | 
				
			||||||
 | 
					    ui->BW->blockSignals(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->dsb->setChecked(m_settings.m_dsb);
 | 
				
			||||||
 | 
					    ui->spanLog2->setValue(5 - m_settings.m_spanLog2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->BW->setValue(m_settings.m_rfBandwidth / 100.0);
 | 
				
			||||||
 | 
					    QString s = QString::number(m_settings.m_rfBandwidth/1000.0, 'f', 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m_settings.m_dsb)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ui->BWText->setText(tr("%1%2k").arg(QChar(0xB1, 0x00)).arg(s));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ui->BWText->setText(tr("%1k").arg(s));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->spanLog2->blockSignals(false);
 | 
				
			||||||
 | 
					    ui->dsb->blockSignals(false);
 | 
				
			||||||
 | 
					    ui->BW->blockSignals(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // The only one of the four signals triggering applyBandwidths will trigger it once only with all other values
 | 
				
			||||||
 | 
					    // set correctly and therefore validate the settings and apply them to dependent widgets
 | 
				
			||||||
 | 
					    ui->lowCut->setValue(m_settings.m_lowCutoff / 100.0);
 | 
				
			||||||
 | 
					    ui->lowCutText->setText(tr("%1k").arg(m_settings.m_lowCutoff / 1000.0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->volume->setValue(m_settings.m_volume * 10.0);
 | 
				
			||||||
 | 
					    ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->agcTimeLog2->setValue(m_settings.m_agcTimeLog2);
 | 
				
			||||||
 | 
					    s = QString::number((1<<ui->agcTimeLog2->value()), 'f', 0);
 | 
				
			||||||
 | 
					    ui->agcTimeText->setText(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->agcPowerThreshold->setValue(m_settings.m_agcPowerThreshold);
 | 
				
			||||||
 | 
					    displayAGCPowerThreshold(ui->agcPowerThreshold->value());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->agcThresholdGate->setValue(m_settings.m_agcThresholdGate);
 | 
				
			||||||
 | 
					    s = QString::number(ui->agcThresholdGate->value(), 'f', 0);
 | 
				
			||||||
 | 
					    ui->agcThresholdGateText->setText(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    blockApplySettings(false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::displayAGCPowerThreshold(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (value == FreeDVDemodSettings::m_minPowerThresholdDB)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ui->agcPowerThresholdText->setText("---");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        QString s = QString::number(value, 'f', 0);
 | 
				
			||||||
 | 
					        ui->agcPowerThresholdText->setText(s);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::leaveEvent(QEvent*)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						m_channelMarker.setHighlighted(false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::enterEvent(QEvent*)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						m_channelMarker.setHighlighted(true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::audioSelect()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    qDebug("FreeDVDemodGUI::audioSelect");
 | 
				
			||||||
 | 
					    AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName);
 | 
				
			||||||
 | 
					    audioSelect.exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (audioSelect.m_selected)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_settings.m_audioDeviceName = audioSelect.m_audioDeviceName;
 | 
				
			||||||
 | 
					        applySettings();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodGUI::tick()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    double magsqAvg, magsqPeak;
 | 
				
			||||||
 | 
					    int nbMagsqSamples;
 | 
				
			||||||
 | 
					    m_freeDVDemod->getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
 | 
				
			||||||
 | 
					    double powDbAvg = CalcDb::dbPower(magsqAvg);
 | 
				
			||||||
 | 
					    double powDbPeak = CalcDb::dbPower(magsqPeak);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->channelPowerMeter->levelChanged(
 | 
				
			||||||
 | 
					            (FreeDVDemodSettings::m_mminPowerThresholdDBf + powDbAvg) / FreeDVDemodSettings::m_mminPowerThresholdDBf,
 | 
				
			||||||
 | 
					            (FreeDVDemodSettings::m_mminPowerThresholdDBf + powDbPeak) / FreeDVDemodSettings::m_mminPowerThresholdDBf,
 | 
				
			||||||
 | 
					            nbMagsqSamples);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m_tickCount % 4 == 0) {
 | 
				
			||||||
 | 
					        ui->channelPower->setText(tr("%1 dB").arg(powDbAvg, 0, 'f', 1));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool squelchOpen = m_freeDVDemod->getAudioActive();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (squelchOpen != m_squelchOpen)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (squelchOpen) {
 | 
				
			||||||
 | 
					            ui->audioMute->setStyleSheet("QToolButton { background-color : green; }");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            ui->audioMute->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_squelchOpen = squelchOpen;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_tickCount++;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										120
									
								
								plugins/channelrx/demodfreedv/freedvdemodgui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								plugins/channelrx/demodfreedv/freedvdemodgui.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,120 @@
 | 
				
			|||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Copyright (C) 2019 Edouard Griffiths, F4EXB                                   //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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                  //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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/>.          //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef INCLUDE_FREEDVDEMODGUI_H
 | 
				
			||||||
 | 
					#define INCLUDE_FREEDVDEMODGUI_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QIcon>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "plugin/plugininstancegui.h"
 | 
				
			||||||
 | 
					#include "gui/rollupwidget.h"
 | 
				
			||||||
 | 
					#include "dsp/channelmarker.h"
 | 
				
			||||||
 | 
					#include "dsp/movingaverage.h"
 | 
				
			||||||
 | 
					#include "util/messagequeue.h"
 | 
				
			||||||
 | 
					#include "freedvdemodsettings.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PluginAPI;
 | 
				
			||||||
 | 
					class DeviceUISet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AudioFifo;
 | 
				
			||||||
 | 
					class FreeDVDemod;
 | 
				
			||||||
 | 
					class SpectrumVis;
 | 
				
			||||||
 | 
					class BasebandSampleSink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ui {
 | 
				
			||||||
 | 
						class FreeDVDemodGUI;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FreeDVDemodGUI : public RollupWidget, public PluginInstanceGUI {
 | 
				
			||||||
 | 
						Q_OBJECT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						static FreeDVDemodGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
 | 
				
			||||||
 | 
						virtual void destroy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void setName(const QString& name);
 | 
				
			||||||
 | 
						QString getName() const;
 | 
				
			||||||
 | 
						virtual qint64 getCenterFrequency() const;
 | 
				
			||||||
 | 
						virtual void setCenterFrequency(qint64 centerFrequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void resetToDefaults();
 | 
				
			||||||
 | 
						QByteArray serialize() const;
 | 
				
			||||||
 | 
						bool deserialize(const QByteArray& data);
 | 
				
			||||||
 | 
						virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
 | 
				
			||||||
 | 
						virtual bool handleMessage(const Message& message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public slots:
 | 
				
			||||||
 | 
						void channelMarkerChangedByCursor();
 | 
				
			||||||
 | 
					    void channelMarkerHighlightedByCursor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						Ui::FreeDVDemodGUI* ui;
 | 
				
			||||||
 | 
						PluginAPI* m_pluginAPI;
 | 
				
			||||||
 | 
						DeviceUISet* m_deviceUISet;
 | 
				
			||||||
 | 
						ChannelMarker m_channelMarker;
 | 
				
			||||||
 | 
						FreeDVDemodSettings m_settings;
 | 
				
			||||||
 | 
						bool m_doApplySettings;
 | 
				
			||||||
 | 
					    int m_spectrumRate;
 | 
				
			||||||
 | 
						bool m_audioBinaural;
 | 
				
			||||||
 | 
						bool m_audioFlipChannels;
 | 
				
			||||||
 | 
						bool m_audioMute;
 | 
				
			||||||
 | 
						bool m_squelchOpen;
 | 
				
			||||||
 | 
						uint32_t m_tickCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FreeDVDemod* m_freeDVDemod;
 | 
				
			||||||
 | 
						SpectrumVis* m_spectrumVis;
 | 
				
			||||||
 | 
						MessageQueue m_inputMessageQueue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QIcon m_iconDSBUSB;
 | 
				
			||||||
 | 
						QIcon m_iconDSBLSB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						explicit FreeDVDemodGUI(PluginAPI* pluginAPI, DeviceUISet* deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
 | 
				
			||||||
 | 
						virtual ~FreeDVDemodGUI();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool blockApplySettings(bool block);
 | 
				
			||||||
 | 
						void applySettings(bool force = false);
 | 
				
			||||||
 | 
						void applyBandwidths(int spanLog2, bool force = false);
 | 
				
			||||||
 | 
						void displaySettings();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void displayAGCPowerThreshold(int value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void leaveEvent(QEvent*);
 | 
				
			||||||
 | 
						void enterEvent(QEvent*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private slots:
 | 
				
			||||||
 | 
						void on_deltaFrequency_changed(qint64 value);
 | 
				
			||||||
 | 
						void on_audioBinaural_toggled(bool binaural);
 | 
				
			||||||
 | 
						void on_audioFlipChannels_toggled(bool flip);
 | 
				
			||||||
 | 
						void on_dsb_toggled(bool dsb);
 | 
				
			||||||
 | 
						void on_BW_valueChanged(int value);
 | 
				
			||||||
 | 
						void on_lowCut_valueChanged(int value);
 | 
				
			||||||
 | 
						void on_volume_valueChanged(int value);
 | 
				
			||||||
 | 
						void on_agc_toggled(bool checked);
 | 
				
			||||||
 | 
					    void on_agcClamping_toggled(bool checked);
 | 
				
			||||||
 | 
						void on_agcTimeLog2_valueChanged(int value);
 | 
				
			||||||
 | 
					    void on_agcPowerThreshold_valueChanged(int value);
 | 
				
			||||||
 | 
					    void on_agcThresholdGate_valueChanged(int value);
 | 
				
			||||||
 | 
						void on_audioMute_toggled(bool checked);
 | 
				
			||||||
 | 
						void on_spanLog2_valueChanged(int value);
 | 
				
			||||||
 | 
						void on_flipSidebands_clicked(bool checked);
 | 
				
			||||||
 | 
						void onWidgetRolled(QWidget* widget, bool rollDown);
 | 
				
			||||||
 | 
					    void onMenuDialogCalled(const QPoint& p);
 | 
				
			||||||
 | 
					    void handleInputMessages();
 | 
				
			||||||
 | 
					    void audioSelect();
 | 
				
			||||||
 | 
						void tick();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // INCLUDE_FREEDVDEMODGUI_H
 | 
				
			||||||
							
								
								
									
										999
									
								
								plugins/channelrx/demodfreedv/freedvdemodgui.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										999
									
								
								plugins/channelrx/demodfreedv/freedvdemodgui.ui
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,999 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<ui version="4.0">
 | 
				
			||||||
 | 
					 <class>FreeDVDemodGUI</class>
 | 
				
			||||||
 | 
					 <widget class="RollupWidget" name="FreeDVDemodGUI">
 | 
				
			||||||
 | 
					  <property name="geometry">
 | 
				
			||||||
 | 
					   <rect>
 | 
				
			||||||
 | 
					    <x>0</x>
 | 
				
			||||||
 | 
					    <y>0</y>
 | 
				
			||||||
 | 
					    <width>412</width>
 | 
				
			||||||
 | 
					    <height>190</height>
 | 
				
			||||||
 | 
					   </rect>
 | 
				
			||||||
 | 
					  </property>
 | 
				
			||||||
 | 
					  <property name="sizePolicy">
 | 
				
			||||||
 | 
					   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 | 
				
			||||||
 | 
					    <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					    <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					   </sizepolicy>
 | 
				
			||||||
 | 
					  </property>
 | 
				
			||||||
 | 
					  <property name="minimumSize">
 | 
				
			||||||
 | 
					   <size>
 | 
				
			||||||
 | 
					    <width>412</width>
 | 
				
			||||||
 | 
					    <height>0</height>
 | 
				
			||||||
 | 
					   </size>
 | 
				
			||||||
 | 
					  </property>
 | 
				
			||||||
 | 
					  <property name="font">
 | 
				
			||||||
 | 
					   <font>
 | 
				
			||||||
 | 
					    <family>Liberation Sans</family>
 | 
				
			||||||
 | 
					    <pointsize>9</pointsize>
 | 
				
			||||||
 | 
					   </font>
 | 
				
			||||||
 | 
					  </property>
 | 
				
			||||||
 | 
					  <property name="windowTitle">
 | 
				
			||||||
 | 
					   <string>SSB Demodulator</string>
 | 
				
			||||||
 | 
					  </property>
 | 
				
			||||||
 | 
					  <widget class="QWidget" name="settingsContainer" native="true">
 | 
				
			||||||
 | 
					   <property name="geometry">
 | 
				
			||||||
 | 
					    <rect>
 | 
				
			||||||
 | 
					     <x>0</x>
 | 
				
			||||||
 | 
					     <y>0</y>
 | 
				
			||||||
 | 
					     <width>410</width>
 | 
				
			||||||
 | 
					     <height>171</height>
 | 
				
			||||||
 | 
					    </rect>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <property name="minimumSize">
 | 
				
			||||||
 | 
					    <size>
 | 
				
			||||||
 | 
					     <width>410</width>
 | 
				
			||||||
 | 
					     <height>0</height>
 | 
				
			||||||
 | 
					    </size>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <property name="windowTitle">
 | 
				
			||||||
 | 
					    <string>Settings</string>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <layout class="QVBoxLayout" name="verticalLayout_2">
 | 
				
			||||||
 | 
					    <property name="spacing">
 | 
				
			||||||
 | 
					     <number>3</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="leftMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="topMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="rightMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="bottomMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QHBoxLayout" name="deltaFreqPowLayout">
 | 
				
			||||||
 | 
					      <property name="topMargin">
 | 
				
			||||||
 | 
					       <number>2</number>
 | 
				
			||||||
 | 
					      </property>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <layout class="QHBoxLayout" name="deltaFrequencyLayout">
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="QLabel" name="deltaFrequencyLabel">
 | 
				
			||||||
 | 
					          <property name="minimumSize">
 | 
				
			||||||
 | 
					           <size>
 | 
				
			||||||
 | 
					            <width>16</width>
 | 
				
			||||||
 | 
					            <height>0</height>
 | 
				
			||||||
 | 
					           </size>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="text">
 | 
				
			||||||
 | 
					           <string>Df</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="ValueDialZ" name="deltaFrequency" native="true">
 | 
				
			||||||
 | 
					          <property name="sizePolicy">
 | 
				
			||||||
 | 
					           <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
 | 
				
			||||||
 | 
					            <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					            <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					           </sizepolicy>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="minimumSize">
 | 
				
			||||||
 | 
					           <size>
 | 
				
			||||||
 | 
					            <width>125</width>
 | 
				
			||||||
 | 
					            <height>16</height>
 | 
				
			||||||
 | 
					           </size>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="font">
 | 
				
			||||||
 | 
					           <font>
 | 
				
			||||||
 | 
					            <family>Liberation Mono</family>
 | 
				
			||||||
 | 
					            <pointsize>12</pointsize>
 | 
				
			||||||
 | 
					           </font>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="cursor">
 | 
				
			||||||
 | 
					           <cursorShape>PointingHandCursor</cursorShape>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="focusPolicy">
 | 
				
			||||||
 | 
					           <enum>Qt::StrongFocus</enum>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="toolTip">
 | 
				
			||||||
 | 
					           <string>Demod shift frequency from center in Hz</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="QLabel" name="deltaUnits">
 | 
				
			||||||
 | 
					          <property name="text">
 | 
				
			||||||
 | 
					           <string> Hz </string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					       </layout>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <spacer name="freqPowSpacer">
 | 
				
			||||||
 | 
					        <property name="orientation">
 | 
				
			||||||
 | 
					         <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="sizeHint" stdset="0">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>40</width>
 | 
				
			||||||
 | 
					          <height>20</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </spacer>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="channelPower">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>60</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Channel power</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="layoutDirection">
 | 
				
			||||||
 | 
					         <enum>Qt::RightToLeft</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>-100.0 dB</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="Line" name="line">
 | 
				
			||||||
 | 
					        <property name="orientation">
 | 
				
			||||||
 | 
					         <enum>Qt::Vertical</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <layout class="QHBoxLayout" name="audioOptionsLayout">
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="QToolButton" name="audioBinaural">
 | 
				
			||||||
 | 
					          <property name="toolTip">
 | 
				
			||||||
 | 
					           <string>Toggle btw Mono and Binaural I/Q audio</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="text">
 | 
				
			||||||
 | 
					           <string>...</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="icon">
 | 
				
			||||||
 | 
					           <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
				
			||||||
 | 
					            <normaloff>:/mono.png</normaloff>
 | 
				
			||||||
 | 
					            <normalon>:/stereo.png</normalon>:/mono.png</iconset>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="checkable">
 | 
				
			||||||
 | 
					           <bool>true</bool>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="QToolButton" name="audioFlipChannels">
 | 
				
			||||||
 | 
					          <property name="toolTip">
 | 
				
			||||||
 | 
					           <string>Flip left/right audio channels</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="text">
 | 
				
			||||||
 | 
					           <string>...</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="icon">
 | 
				
			||||||
 | 
					           <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
				
			||||||
 | 
					            <normaloff>:/flip_lr.png</normaloff>
 | 
				
			||||||
 | 
					            <normalon>:/flip_rl.png</normalon>:/flip_lr.png</iconset>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="checkable">
 | 
				
			||||||
 | 
					           <bool>true</bool>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="Line" name="line_4">
 | 
				
			||||||
 | 
					          <property name="orientation">
 | 
				
			||||||
 | 
					           <enum>Qt::Vertical</enum>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="QPushButton" name="flipSidebands">
 | 
				
			||||||
 | 
					          <property name="toolTip">
 | 
				
			||||||
 | 
					           <string>Flip sideband in SSB mode (LSB->USB or USB->LSB)</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="text">
 | 
				
			||||||
 | 
					           <string/>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="icon">
 | 
				
			||||||
 | 
					           <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
				
			||||||
 | 
					            <normaloff>:/flip_sidebands.png</normaloff>:/flip_sidebands.png</iconset>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="QToolButton" name="dsb">
 | 
				
			||||||
 | 
					          <property name="toolTip">
 | 
				
			||||||
 | 
					           <string>DSB/SSB toggle</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="text">
 | 
				
			||||||
 | 
					           <string>...</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="icon">
 | 
				
			||||||
 | 
					           <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
				
			||||||
 | 
					            <normaloff>:/usb.png</normaloff>
 | 
				
			||||||
 | 
					            <normalon>:/dsb.png</normalon>:/usb.png</iconset>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					          <property name="checkable">
 | 
				
			||||||
 | 
					           <bool>true</bool>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					       </layout>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QHBoxLayout" name="channelPowerMeterLayout">
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="channelPowerMeterUnits">
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>dB</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="LevelMeterSignalDB" name="channelPowerMeter" native="true">
 | 
				
			||||||
 | 
					        <property name="sizePolicy">
 | 
				
			||||||
 | 
					         <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
 | 
				
			||||||
 | 
					          <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					          <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					         </sizepolicy>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>0</width>
 | 
				
			||||||
 | 
					          <height>24</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="font">
 | 
				
			||||||
 | 
					         <font>
 | 
				
			||||||
 | 
					          <family>Liberation Mono</family>
 | 
				
			||||||
 | 
					          <pointsize>8</pointsize>
 | 
				
			||||||
 | 
					         </font>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QHBoxLayout" name="spanLayout">
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="spanLabel">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>16777215</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>Span</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QSlider" name="spanLog2">
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Demod frequency span</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="minimum">
 | 
				
			||||||
 | 
					         <number>0</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximum">
 | 
				
			||||||
 | 
					         <number>4</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="pageStep">
 | 
				
			||||||
 | 
					         <number>1</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="value">
 | 
				
			||||||
 | 
					         <number>2</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="sliderPosition">
 | 
				
			||||||
 | 
					         <number>2</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="orientation">
 | 
				
			||||||
 | 
					         <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="spanText">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>16777215</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>6.0k</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QHBoxLayout" name="lowCutLayout">
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="lowCutLabel">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>16777215</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>Low cut</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="TickedSlider" name="lowCut">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>16777215</width>
 | 
				
			||||||
 | 
					          <height>16</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Highpass filter cutoff frequency (SSB)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="minimum">
 | 
				
			||||||
 | 
					         <number>-60</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximum">
 | 
				
			||||||
 | 
					         <number>60</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="pageStep">
 | 
				
			||||||
 | 
					         <number>1</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="value">
 | 
				
			||||||
 | 
					         <number>3</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="orientation">
 | 
				
			||||||
 | 
					         <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="invertedAppearance">
 | 
				
			||||||
 | 
					         <bool>false</bool>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="tickPosition">
 | 
				
			||||||
 | 
					         <enum>QSlider::NoTicks</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="tickInterval">
 | 
				
			||||||
 | 
					         <number>5</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="lowCutText">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>16777215</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>0.3k</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QHBoxLayout" name="bqndwidthLayout">
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="BWLabel">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>16777215</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>Hi cut</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="TickedSlider" name="BW">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>16777215</width>
 | 
				
			||||||
 | 
					          <height>16</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Lowpass filter cutoff frequency</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="minimum">
 | 
				
			||||||
 | 
					         <number>-60</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximum">
 | 
				
			||||||
 | 
					         <number>60</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="pageStep">
 | 
				
			||||||
 | 
					         <number>1</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="value">
 | 
				
			||||||
 | 
					         <number>30</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="orientation">
 | 
				
			||||||
 | 
					         <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="tickPosition">
 | 
				
			||||||
 | 
					         <enum>QSlider::TicksBelow</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="tickInterval">
 | 
				
			||||||
 | 
					         <number>5</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="BWText">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>16777215</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>3.0k</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QHBoxLayout" name="scaleLayout">
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="scalePadLeft">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>10</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="font">
 | 
				
			||||||
 | 
					         <font>
 | 
				
			||||||
 | 
					          <pointsize>8</pointsize>
 | 
				
			||||||
 | 
					         </font>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>f: </string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="scaleMinus">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>10</width>
 | 
				
			||||||
 | 
					          <height>10</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="font">
 | 
				
			||||||
 | 
					         <font>
 | 
				
			||||||
 | 
					          <pointsize>8</pointsize>
 | 
				
			||||||
 | 
					         </font>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>-</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="lsbLabel">
 | 
				
			||||||
 | 
					        <property name="font">
 | 
				
			||||||
 | 
					         <font>
 | 
				
			||||||
 | 
					          <pointsize>8</pointsize>
 | 
				
			||||||
 | 
					         </font>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>LSB</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="scaleCenter">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>12</width>
 | 
				
			||||||
 | 
					          <height>10</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="font">
 | 
				
			||||||
 | 
					         <font>
 | 
				
			||||||
 | 
					          <pointsize>8</pointsize>
 | 
				
			||||||
 | 
					         </font>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>0</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="usbLabel">
 | 
				
			||||||
 | 
					        <property name="font">
 | 
				
			||||||
 | 
					         <font>
 | 
				
			||||||
 | 
					          <pointsize>8</pointsize>
 | 
				
			||||||
 | 
					         </font>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>USB</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="scalePlus">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>10</width>
 | 
				
			||||||
 | 
					          <height>10</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="font">
 | 
				
			||||||
 | 
					         <font>
 | 
				
			||||||
 | 
					          <pointsize>8</pointsize>
 | 
				
			||||||
 | 
					         </font>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>+</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="scalePadRight">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>50</width>
 | 
				
			||||||
 | 
					          <height>10</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string/>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <widget class="Line" name="line_3">
 | 
				
			||||||
 | 
					      <property name="orientation">
 | 
				
			||||||
 | 
					       <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					      </property>
 | 
				
			||||||
 | 
					     </widget>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QHBoxLayout" name="volumeLayout">
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="volumeLabel">
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>Vol</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QDial" name="volume">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>24</width>
 | 
				
			||||||
 | 
					          <height>24</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>24</width>
 | 
				
			||||||
 | 
					          <height>24</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="pageStep">
 | 
				
			||||||
 | 
					         <number>1</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="volumeText">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>30</width>
 | 
				
			||||||
 | 
					          <height>16777215</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>2.0</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="Line" name="line_2">
 | 
				
			||||||
 | 
					        <property name="orientation">
 | 
				
			||||||
 | 
					         <enum>Qt::Vertical</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="ButtonSwitch" name="agc">
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Toggle AGC</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>AGC</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="checkable">
 | 
				
			||||||
 | 
					         <bool>true</bool>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="ButtonSwitch" name="agcClamping">
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Toggle AGC clamping to maximum allowable signal</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>CL</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="checkable">
 | 
				
			||||||
 | 
					         <bool>true</bool>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QDial" name="agcTimeLog2">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>24</width>
 | 
				
			||||||
 | 
					          <height>24</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>AGC time constant (ms in log2 steps)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="minimum">
 | 
				
			||||||
 | 
					         <number>4</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximum">
 | 
				
			||||||
 | 
					         <number>11</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="pageStep">
 | 
				
			||||||
 | 
					         <number>1</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="value">
 | 
				
			||||||
 | 
					         <number>7</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="agcTimeText">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>35</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>AGC time constant (ms)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>0000</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QDial" name="agcPowerThreshold">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>24</width>
 | 
				
			||||||
 | 
					          <height>24</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Power threshold (dB)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="minimum">
 | 
				
			||||||
 | 
					         <number>-120</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximum">
 | 
				
			||||||
 | 
					         <number>0</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="pageStep">
 | 
				
			||||||
 | 
					         <number>1</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="value">
 | 
				
			||||||
 | 
					         <number>-40</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="agcPowerThresholdText">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>26</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Power threshold (dB)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>-000</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QDial" name="agcThresholdGate">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>24</width>
 | 
				
			||||||
 | 
					          <height>24</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Power threshold gate (ms)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximum">
 | 
				
			||||||
 | 
					         <number>20</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="pageStep">
 | 
				
			||||||
 | 
					         <number>1</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="value">
 | 
				
			||||||
 | 
					         <number>4</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="agcThresholdGateText">
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>16</width>
 | 
				
			||||||
 | 
					          <height>0</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Power threshold gate (ms)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>00</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="alignment">
 | 
				
			||||||
 | 
					         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <spacer name="horizontalSpacer">
 | 
				
			||||||
 | 
					        <property name="orientation">
 | 
				
			||||||
 | 
					         <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="sizeHint" stdset="0">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>40</width>
 | 
				
			||||||
 | 
					          <height>20</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </spacer>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QToolButton" name="audioMute">
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Mute/Unmute audio</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string/>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="icon">
 | 
				
			||||||
 | 
					         <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
				
			||||||
 | 
					          <normaloff>:/sound_on.png</normaloff>
 | 
				
			||||||
 | 
					          <normalon>:/sound_off.png</normalon>:/sound_on.png</iconset>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="checkable">
 | 
				
			||||||
 | 
					         <bool>true</bool>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					   </layout>
 | 
				
			||||||
 | 
					  </widget>
 | 
				
			||||||
 | 
					  <widget class="QWidget" name="spectrumContainer" native="true">
 | 
				
			||||||
 | 
					   <property name="geometry">
 | 
				
			||||||
 | 
					    <rect>
 | 
				
			||||||
 | 
					     <x>10</x>
 | 
				
			||||||
 | 
					     <y>170</y>
 | 
				
			||||||
 | 
					     <width>218</width>
 | 
				
			||||||
 | 
					     <height>284</height>
 | 
				
			||||||
 | 
					    </rect>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <property name="windowTitle">
 | 
				
			||||||
 | 
					    <string>Channel Spectrum</string>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <layout class="QVBoxLayout" name="verticalLayout">
 | 
				
			||||||
 | 
					    <property name="spacing">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="leftMargin">
 | 
				
			||||||
 | 
					     <number>3</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="topMargin">
 | 
				
			||||||
 | 
					     <number>3</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="rightMargin">
 | 
				
			||||||
 | 
					     <number>3</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="bottomMargin">
 | 
				
			||||||
 | 
					     <number>3</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <widget class="GLSpectrum" name="glSpectrum" native="true">
 | 
				
			||||||
 | 
					      <property name="minimumSize">
 | 
				
			||||||
 | 
					       <size>
 | 
				
			||||||
 | 
					        <width>200</width>
 | 
				
			||||||
 | 
					        <height>250</height>
 | 
				
			||||||
 | 
					       </size>
 | 
				
			||||||
 | 
					      </property>
 | 
				
			||||||
 | 
					      <property name="font">
 | 
				
			||||||
 | 
					       <font>
 | 
				
			||||||
 | 
					        <family>Liberation Mono</family>
 | 
				
			||||||
 | 
					        <pointsize>8</pointsize>
 | 
				
			||||||
 | 
					       </font>
 | 
				
			||||||
 | 
					      </property>
 | 
				
			||||||
 | 
					     </widget>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <widget class="GLSpectrumGUI" name="spectrumGUI" native="true"/>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					   </layout>
 | 
				
			||||||
 | 
					  </widget>
 | 
				
			||||||
 | 
					 </widget>
 | 
				
			||||||
 | 
					 <customwidgets>
 | 
				
			||||||
 | 
					  <customwidget>
 | 
				
			||||||
 | 
					   <class>RollupWidget</class>
 | 
				
			||||||
 | 
					   <extends>QWidget</extends>
 | 
				
			||||||
 | 
					   <header>gui/rollupwidget.h</header>
 | 
				
			||||||
 | 
					   <container>1</container>
 | 
				
			||||||
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					  <customwidget>
 | 
				
			||||||
 | 
					   <class>LevelMeterSignalDB</class>
 | 
				
			||||||
 | 
					   <extends>QWidget</extends>
 | 
				
			||||||
 | 
					   <header>gui/levelmeter.h</header>
 | 
				
			||||||
 | 
					   <container>1</container>
 | 
				
			||||||
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					  <customwidget>
 | 
				
			||||||
 | 
					   <class>GLSpectrum</class>
 | 
				
			||||||
 | 
					   <extends>QWidget</extends>
 | 
				
			||||||
 | 
					   <header>gui/glspectrum.h</header>
 | 
				
			||||||
 | 
					   <container>1</container>
 | 
				
			||||||
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					  <customwidget>
 | 
				
			||||||
 | 
					   <class>GLSpectrumGUI</class>
 | 
				
			||||||
 | 
					   <extends>QWidget</extends>
 | 
				
			||||||
 | 
					   <header>gui/glspectrumgui.h</header>
 | 
				
			||||||
 | 
					   <container>1</container>
 | 
				
			||||||
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					  <customwidget>
 | 
				
			||||||
 | 
					   <class>ValueDialZ</class>
 | 
				
			||||||
 | 
					   <extends>QWidget</extends>
 | 
				
			||||||
 | 
					   <header>gui/valuedialz.h</header>
 | 
				
			||||||
 | 
					   <container>1</container>
 | 
				
			||||||
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					  <customwidget>
 | 
				
			||||||
 | 
					   <class>ButtonSwitch</class>
 | 
				
			||||||
 | 
					   <extends>QToolButton</extends>
 | 
				
			||||||
 | 
					   <header>gui/buttonswitch.h</header>
 | 
				
			||||||
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					  <customwidget>
 | 
				
			||||||
 | 
					   <class>TickedSlider</class>
 | 
				
			||||||
 | 
					   <extends>QSlider</extends>
 | 
				
			||||||
 | 
					   <header>gui/tickedslider.h</header>
 | 
				
			||||||
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					 </customwidgets>
 | 
				
			||||||
 | 
					 <resources>
 | 
				
			||||||
 | 
					  <include location="../../../sdrgui/resources/res.qrc"/>
 | 
				
			||||||
 | 
					 </resources>
 | 
				
			||||||
 | 
					 <connections/>
 | 
				
			||||||
 | 
					</ui>
 | 
				
			||||||
							
								
								
									
										216
									
								
								plugins/channelrx/demodfreedv/freedvdemodsettings.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								plugins/channelrx/demodfreedv/freedvdemodsettings.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,216 @@
 | 
				
			|||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Copyright (C) 2019 Edouard Griffiths, F4EXB.                                  //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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                  //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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/>.          //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QColor>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "dsp/dspengine.h"
 | 
				
			||||||
 | 
					#include "util/simpleserializer.h"
 | 
				
			||||||
 | 
					#include "settings/serializable.h"
 | 
				
			||||||
 | 
					#include "freedvdemodsettings.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef SDR_RX_SAMPLE_24BIT
 | 
				
			||||||
 | 
					const int FreeDVDemodSettings::m_minPowerThresholdDB = -120;
 | 
				
			||||||
 | 
					const float FreeDVDemodSettings::m_mminPowerThresholdDBf = 120.0f;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					const int FreeDVDemodSettings::m_minPowerThresholdDB = -100;
 | 
				
			||||||
 | 
					const float FreeDVDemodSettings::m_mminPowerThresholdDBf = 100.0f;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FreeDVDemodSettings::FreeDVDemodSettings() :
 | 
				
			||||||
 | 
					    m_channelMarker(0),
 | 
				
			||||||
 | 
					    m_spectrumGUI(0)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    resetToDefaults();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVDemodSettings::resetToDefaults()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_audioBinaural = false;
 | 
				
			||||||
 | 
					    m_audioFlipChannels = false;
 | 
				
			||||||
 | 
					    m_dsb = false;
 | 
				
			||||||
 | 
					    m_audioMute = false;
 | 
				
			||||||
 | 
					    m_agc = false;
 | 
				
			||||||
 | 
					    m_agcClamping = false;
 | 
				
			||||||
 | 
					    m_agcPowerThreshold = -40;
 | 
				
			||||||
 | 
					    m_agcThresholdGate = 4;
 | 
				
			||||||
 | 
					    m_agcTimeLog2 = 7;
 | 
				
			||||||
 | 
					    m_rfBandwidth = 3000;
 | 
				
			||||||
 | 
					    m_lowCutoff = 300;
 | 
				
			||||||
 | 
					    m_volume = 3.0;
 | 
				
			||||||
 | 
					    m_spanLog2 = 3;
 | 
				
			||||||
 | 
					    m_inputFrequencyOffset = 0;
 | 
				
			||||||
 | 
					    m_rgbColor = QColor(0, 255, 204).rgb();
 | 
				
			||||||
 | 
					    m_title = "FreeDV Demodulator";
 | 
				
			||||||
 | 
					    m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
 | 
				
			||||||
 | 
					    m_freeDVMode = FreeDVMode2400A;
 | 
				
			||||||
 | 
					    m_useReverseAPI = false;
 | 
				
			||||||
 | 
					    m_reverseAPIAddress = "127.0.0.1";
 | 
				
			||||||
 | 
					    m_reverseAPIPort = 8888;
 | 
				
			||||||
 | 
					    m_reverseAPIDeviceIndex = 0;
 | 
				
			||||||
 | 
					    m_reverseAPIChannelIndex = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArray FreeDVDemodSettings::serialize() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SimpleSerializer s(1);
 | 
				
			||||||
 | 
					    s.writeS32(1, m_inputFrequencyOffset);
 | 
				
			||||||
 | 
					    s.writeS32(2, m_rfBandwidth / 100.0);
 | 
				
			||||||
 | 
					    s.writeS32(3, m_volume * 10.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m_spectrumGUI) {
 | 
				
			||||||
 | 
					        s.writeBlob(4, m_spectrumGUI->serialize());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s.writeU32(5, m_rgbColor);
 | 
				
			||||||
 | 
					    s.writeS32(6, m_lowCutoff / 100.0);
 | 
				
			||||||
 | 
					    s.writeS32(7, m_spanLog2);
 | 
				
			||||||
 | 
					    s.writeBool(8, m_audioBinaural);
 | 
				
			||||||
 | 
					    s.writeBool(9, m_audioFlipChannels);
 | 
				
			||||||
 | 
					    s.writeBool(10, m_dsb);
 | 
				
			||||||
 | 
					    s.writeBool(11, m_agc);
 | 
				
			||||||
 | 
					    s.writeS32(12, m_agcTimeLog2);
 | 
				
			||||||
 | 
					    s.writeS32(13, m_agcPowerThreshold);
 | 
				
			||||||
 | 
					    s.writeS32(14, m_agcThresholdGate);
 | 
				
			||||||
 | 
					    s.writeBool(15, m_agcClamping);
 | 
				
			||||||
 | 
					    s.writeString(16, m_title);
 | 
				
			||||||
 | 
					    s.writeString(17, m_audioDeviceName);
 | 
				
			||||||
 | 
					    s.writeBool(18, m_useReverseAPI);
 | 
				
			||||||
 | 
					    s.writeString(19, m_reverseAPIAddress);
 | 
				
			||||||
 | 
					    s.writeU32(20, m_reverseAPIPort);
 | 
				
			||||||
 | 
					    s.writeU32(21, m_reverseAPIDeviceIndex);
 | 
				
			||||||
 | 
					    s.writeU32(22, m_reverseAPIChannelIndex);
 | 
				
			||||||
 | 
					    s.writeS32(23, (int) m_freeDVMode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return s.final();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool FreeDVDemodSettings::deserialize(const QByteArray& data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SimpleDeserializer d(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(!d.isValid())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        resetToDefaults();
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(d.getVersion() == 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        QByteArray bytetmp;
 | 
				
			||||||
 | 
					        qint32 tmp;
 | 
				
			||||||
 | 
					        uint32_t utmp;
 | 
				
			||||||
 | 
					        QString strtmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d.readS32(1, &m_inputFrequencyOffset, 0);
 | 
				
			||||||
 | 
					        d.readS32(2, &tmp, 30);
 | 
				
			||||||
 | 
					        m_rfBandwidth = tmp * 100.0;
 | 
				
			||||||
 | 
					        d.readS32(3, &tmp, 30);
 | 
				
			||||||
 | 
					        m_volume = tmp / 10.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_spectrumGUI) {
 | 
				
			||||||
 | 
					            d.readBlob(4, &bytetmp);
 | 
				
			||||||
 | 
					            m_spectrumGUI->deserialize(bytetmp);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d.readU32(5, &m_rgbColor);
 | 
				
			||||||
 | 
					        d.readS32(6, &tmp, 30);
 | 
				
			||||||
 | 
					        m_lowCutoff = tmp * 100.0;
 | 
				
			||||||
 | 
					        d.readS32(7, &m_spanLog2, 3);
 | 
				
			||||||
 | 
					        d.readBool(8, &m_audioBinaural, false);
 | 
				
			||||||
 | 
					        d.readBool(9, &m_audioFlipChannels, false);
 | 
				
			||||||
 | 
					        d.readBool(10, &m_dsb, false);
 | 
				
			||||||
 | 
					        d.readBool(11, &m_agc, false);
 | 
				
			||||||
 | 
					        d.readS32(12, &m_agcTimeLog2, 7);
 | 
				
			||||||
 | 
					        d.readS32(13, &m_agcPowerThreshold, -40);
 | 
				
			||||||
 | 
					        d.readS32(14, &m_agcThresholdGate, 4);
 | 
				
			||||||
 | 
					        d.readBool(15, &m_agcClamping, false);
 | 
				
			||||||
 | 
					        d.readString(16, &m_title, "SSB Demodulator");
 | 
				
			||||||
 | 
					        d.readString(17, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
 | 
				
			||||||
 | 
					        d.readBool(18, &m_useReverseAPI, false);
 | 
				
			||||||
 | 
					        d.readString(19, &m_reverseAPIAddress, "127.0.0.1");
 | 
				
			||||||
 | 
					        d.readU32(20, &utmp, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((utmp > 1023) && (utmp < 65535)) {
 | 
				
			||||||
 | 
					            m_reverseAPIPort = utmp;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            m_reverseAPIPort = 8888;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d.readU32(21, &utmp, 0);
 | 
				
			||||||
 | 
					        m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp;
 | 
				
			||||||
 | 
					        d.readU32(22, &utmp, 0);
 | 
				
			||||||
 | 
					        m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d.readS32(23, &tmp, 0);
 | 
				
			||||||
 | 
					        if ((tmp < 0) || (tmp > (int) FreeDVMode::FreeDVMode700D)) {
 | 
				
			||||||
 | 
					            m_freeDVMode = FreeDVMode::FreeDVMode2400A;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            m_freeDVMode = (FreeDVMode) tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        resetToDefaults();
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int FreeDVDemodSettings::getHiCutoff(FreeDVMode freeDVMode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch(freeDVMode)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case FreeDVMode800XA: // C4FM NB
 | 
				
			||||||
 | 
					            return 2400.0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case FreeDVMode700D: // OFDM
 | 
				
			||||||
 | 
					        case FreeDVMode1600: // OFDM
 | 
				
			||||||
 | 
					            return 2200.0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case FreeDVMode2400A: // C4FM WB
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return 6000.0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int FreeDVDemodSettings::getLowCutoff(FreeDVMode freeDVMode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch(freeDVMode)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case FreeDVMode800XA: // C4FM NB
 | 
				
			||||||
 | 
					            return 400.0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case FreeDVMode700D: // OFDM
 | 
				
			||||||
 | 
					        case FreeDVMode1600: // OFDM
 | 
				
			||||||
 | 
					            return 800.0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case FreeDVMode2400A: // C4FM WB
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return 0.0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int FreeDVDemodSettings::getModSampleRate(FreeDVMode freeDVMode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (freeDVMode == FreeDVMode2400A) {
 | 
				
			||||||
 | 
					        return 48000;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return 8000;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										79
									
								
								plugins/channelrx/demodfreedv/freedvdemodsettings.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								plugins/channelrx/demodfreedv/freedvdemodsettings.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Copyright (C) 2019 Edouard Griffiths, F4EXB                                   //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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                  //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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/>.          //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef PLUGINS_CHANNELRX_DEMODFREEDV_FREEDVDEMODSETTINGS_H_
 | 
				
			||||||
 | 
					#define PLUGINS_CHANNELRX_DEMODFREEDV_FREEDVDEMODSETTINGS_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QByteArray>
 | 
				
			||||||
 | 
					#include <QString>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Serializable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FreeDVDemodSettings
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    typedef enum
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        FreeDVMode2400A,
 | 
				
			||||||
 | 
					        FreeDVMode1600,
 | 
				
			||||||
 | 
					        FreeDVMode800XA,
 | 
				
			||||||
 | 
					        FreeDVMode700D
 | 
				
			||||||
 | 
					    } FreeDVMode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qint32 m_inputFrequencyOffset;
 | 
				
			||||||
 | 
					    Real m_rfBandwidth;
 | 
				
			||||||
 | 
					    Real m_lowCutoff;
 | 
				
			||||||
 | 
					    Real m_volume;
 | 
				
			||||||
 | 
					    int  m_spanLog2;
 | 
				
			||||||
 | 
					    bool m_audioBinaural;
 | 
				
			||||||
 | 
					    bool m_audioFlipChannels;
 | 
				
			||||||
 | 
					    bool m_dsb;
 | 
				
			||||||
 | 
					    bool m_audioMute;
 | 
				
			||||||
 | 
					    bool m_agc;
 | 
				
			||||||
 | 
					    bool m_agcClamping;
 | 
				
			||||||
 | 
					    int  m_agcTimeLog2;
 | 
				
			||||||
 | 
					    int  m_agcPowerThreshold;
 | 
				
			||||||
 | 
					    int  m_agcThresholdGate;
 | 
				
			||||||
 | 
					    quint32 m_rgbColor;
 | 
				
			||||||
 | 
					    QString m_title;
 | 
				
			||||||
 | 
					    QString m_audioDeviceName;
 | 
				
			||||||
 | 
					    FreeDVMode m_freeDVMode;
 | 
				
			||||||
 | 
					    bool m_useReverseAPI;
 | 
				
			||||||
 | 
					    QString m_reverseAPIAddress;
 | 
				
			||||||
 | 
					    uint16_t m_reverseAPIPort;
 | 
				
			||||||
 | 
					    uint16_t m_reverseAPIDeviceIndex;
 | 
				
			||||||
 | 
					    uint16_t m_reverseAPIChannelIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Serializable *m_channelMarker;
 | 
				
			||||||
 | 
					    Serializable *m_spectrumGUI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FreeDVDemodSettings();
 | 
				
			||||||
 | 
					    void resetToDefaults();
 | 
				
			||||||
 | 
					    void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
 | 
				
			||||||
 | 
					    void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; }
 | 
				
			||||||
 | 
					    QByteArray serialize() const;
 | 
				
			||||||
 | 
					    bool deserialize(const QByteArray& data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static const int m_minPowerThresholdDB;
 | 
				
			||||||
 | 
					    static const float m_mminPowerThresholdDBf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static int getHiCutoff(FreeDVMode freeDVMode);
 | 
				
			||||||
 | 
					    static int getLowCutoff(FreeDVMode freeDVMode);
 | 
				
			||||||
 | 
					    static int getModSampleRate(FreeDVMode freeDVMode);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* PLUGINS_CHANNELRX_DEMODFREEDV_FREEDVDEMODSETTINGS_H_ */
 | 
				
			||||||
							
								
								
									
										78
									
								
								plugins/channelrx/demodfreedv/freedvplugin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								plugins/channelrx/demodfreedv/freedvplugin.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Copyright (C) 2019 Edouard Griffiths, F4EXB                                   //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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                  //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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/>.          //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QtPlugin>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "device/devicesourceapi.h"
 | 
				
			||||||
 | 
					#include "plugin/pluginapi.h"
 | 
				
			||||||
 | 
					#ifndef SERVER_MODE
 | 
				
			||||||
 | 
					#include "freedvdemodgui.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#include "freedvdemod.h"
 | 
				
			||||||
 | 
					#include "freedvplugin.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PluginDescriptor FreeDVPlugin::m_pluginDescriptor = {
 | 
				
			||||||
 | 
						QString("FreeDV Demodulator"),
 | 
				
			||||||
 | 
						QString("4.5.0"),
 | 
				
			||||||
 | 
						QString("(c) Edouard Griffiths, F4EXB"),
 | 
				
			||||||
 | 
						QString("https://github.com/f4exb/sdrangel"),
 | 
				
			||||||
 | 
						true,
 | 
				
			||||||
 | 
						QString("https://github.com/f4exb/sdrangel")
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FreeDVPlugin::FreeDVPlugin(QObject* parent) :
 | 
				
			||||||
 | 
						QObject(parent),
 | 
				
			||||||
 | 
						m_pluginAPI(0)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PluginDescriptor& FreeDVPlugin::getPluginDescriptor() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return m_pluginDescriptor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FreeDVPlugin::initPlugin(PluginAPI* pluginAPI)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						m_pluginAPI = pluginAPI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// register demodulator
 | 
				
			||||||
 | 
						m_pluginAPI->registerRxChannel(FreeDVDemod::m_channelIdURI, FreeDVDemod::m_channelId, this);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef SERVER_MODE
 | 
				
			||||||
 | 
					PluginInstanceGUI* FreeDVPlugin::createRxChannelGUI(
 | 
				
			||||||
 | 
					        DeviceUISet *deviceUISet __attribute__((unused)),
 | 
				
			||||||
 | 
					        BasebandSampleSink *rxChannel __attribute__((unused)))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					PluginInstanceGUI* FreeDVPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return FreeDVDemodGUI::create(m_pluginAPI, deviceUISet, rxChannel);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BasebandSampleSink* FreeDVPlugin::createRxChannelBS(DeviceSourceAPI *deviceAPI)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return new FreeDVDemod(deviceAPI);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ChannelSinkAPI* FreeDVPlugin::createRxChannelCS(DeviceSourceAPI *deviceAPI)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return new FreeDVDemod(deviceAPI);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										47
									
								
								plugins/channelrx/demodfreedv/freedvplugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								plugins/channelrx/demodfreedv/freedvplugin.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Copyright (C) 2019 Edouard Griffiths, F4EXB                                   //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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                  //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// 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/>.          //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef INCLUDE_FREEDVPLUGIN_H
 | 
				
			||||||
 | 
					#define INCLUDE_FREEDVPLUGIN_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QObject>
 | 
				
			||||||
 | 
					#include "plugin/plugininterface.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeviceUISet;
 | 
				
			||||||
 | 
					class BasebandSampleSink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FreeDVPlugin : public QObject, PluginInterface {
 | 
				
			||||||
 | 
						Q_OBJECT
 | 
				
			||||||
 | 
						Q_INTERFACES(PluginInterface)
 | 
				
			||||||
 | 
						Q_PLUGIN_METADATA(IID "sdrangel.channel.freedvdemod")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit FreeDVPlugin(QObject* parent = NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const PluginDescriptor& getPluginDescriptor() const;
 | 
				
			||||||
 | 
						void initPlugin(PluginAPI* pluginAPI);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						virtual PluginInstanceGUI* createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
 | 
				
			||||||
 | 
						virtual BasebandSampleSink* createRxChannelBS(DeviceSourceAPI *deviceAPI);
 | 
				
			||||||
 | 
						virtual ChannelSinkAPI* createRxChannelCS(DeviceSourceAPI *deviceAPI);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						static const PluginDescriptor m_pluginDescriptor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PluginAPI* m_pluginAPI;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // INCLUDE_FREEDVPLUGIN_H
 | 
				
			||||||
@ -1,6 +1,5 @@
 | 
				
			|||||||
#include <QPixmap>
 | 
					#include <QPixmap>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ssbdemodgui.h"
 | 
					 | 
				
			||||||
#include "ssbdemodgui.h"
 | 
					#include "ssbdemodgui.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <device/devicesourceapi.h>
 | 
					#include <device/devicesourceapi.h>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user